You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
no backscattering yet, might replace Preintegrated and Subsurface shading models, can be optimized, postprocess pass only runs if an object on the screen is using it, uses SeparableSSS by Jorge Jimenez and Diego Gutierrez [CL 2236313 by Martin Mittring in Main branch]
191 lines
4.9 KiB
Plaintext
191 lines
4.9 KiB
Plaintext
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
PostProcessSubsurface.usf: Screenspace subsurface scattering shaders.
|
|
=============================================================================*/
|
|
|
|
#include "Common.usf"
|
|
#include "PostProcessCommon.usf"
|
|
#include "DeferredShadingCommon.usf"
|
|
|
|
/** RGBA8 linear texture containing random normals */
|
|
Texture2D SSProfilesTexture;
|
|
SamplerState SSProfilesTextureSampler;
|
|
|
|
// x:Radius, y:DistanceToProjectionWindow, zw:xy scale correction for BufferSize!=ViewportSize
|
|
float4 SSSParams;
|
|
|
|
// ------------------------------------------
|
|
|
|
// setup for "SeparableSSS.usf"
|
|
|
|
#define SSSS_HLSL_4 1
|
|
|
|
// can be optimized
|
|
float GetSubsurfaceStrength(float2 UV)
|
|
{
|
|
FScreenSpaceData ScreenSpaceData = GetScreenSpaceData(UV);
|
|
|
|
float Mask = ScreenSpaceData.GBuffer.ShadingModelID >= SHADINGMODELID_SUBSURFACE_PROFILE;
|
|
|
|
return Mask * ScreenSpaceData.GBuffer.Opacity;
|
|
}
|
|
|
|
//#define SSSS_STREGTH_SOURCE 1 // todo: masking fom LightingModel or SSSColor
|
|
#define SSSS_STREGTH_SOURCE GetSubsurfaceStrength(texcoord)
|
|
|
|
// 0:speculars leak into SSS / 1:requires alpha channel for scenecolor
|
|
// #define SSSS_SPECULAR_CORRECTION 1
|
|
|
|
// 0: faster
|
|
// 1: no color bleeding in z direction
|
|
#define SSSS_FOLLOW_SURFACE 1
|
|
|
|
// from https://github.com/iryoku/separable-sss/tree/master/Demo
|
|
// Jorge Jimenez http://www.iryoku.com/
|
|
// http://www.iryoku.com/translucency/downloads/Real-Time-Realistic-Skin-Translucency.pdf
|
|
#include "SeparableSSS.usf"
|
|
|
|
// ------------------------------------------
|
|
|
|
|
|
|
|
#if SSSS_SPECULAR_CORRECTION == 1
|
|
// requires alpha channel for scenecolor
|
|
#elif SSSS_SPECULAR_CORRECTION == 0
|
|
// speculars leak into SSS
|
|
#else
|
|
error
|
|
#endif
|
|
|
|
#if METHOD == 0
|
|
// horizontal
|
|
#elif METHOD == 1
|
|
// vertical
|
|
#elif METHOD == 2
|
|
// vertical and reconstruct specular
|
|
#else
|
|
error
|
|
#endif
|
|
|
|
// 0 / 1
|
|
#define VISUALIZE_KERNEL 0
|
|
|
|
|
|
void SetupPS(in float4 UVAndScreenPos : TEXCOORD0, out float4 OutColor : SV_Target0)
|
|
{
|
|
float2 UV = UVAndScreenPos.xy;
|
|
|
|
OutColor = 0;
|
|
|
|
FScreenSpaceData ScreenSpaceData = GetScreenSpaceData(UV);
|
|
|
|
FLATTEN if(ScreenSpaceData.GBuffer.ShadingModelID >= SHADINGMODELID_SUBSURFACE_PROFILE)
|
|
{
|
|
float4 SceneColor4 = Texture2DSample(PostprocessInput0, PostprocessInput0Sampler, UV);
|
|
|
|
#if SSSS_SPECULAR_CORRECTION == 1
|
|
// we take out the specular highlights
|
|
float3 Lighting = LightAccumulator_ReconstructDiffuseLighting(SceneColor4);
|
|
#else
|
|
float3 Lighting = SceneColor4.rgb;
|
|
#endif
|
|
|
|
OutColor.rgb = Lighting;
|
|
}
|
|
}
|
|
|
|
// input0 is created by the SetupPS shader
|
|
void MainPS(float4 UVAndScreenPos : TEXCOORD0, out float4 OutColor : SV_Target0)
|
|
{
|
|
float2 UV = UVAndScreenPos.xy;
|
|
|
|
FScreenSpaceData ScreenSpaceData = GetScreenSpaceData(UV);
|
|
//
|
|
|
|
// test
|
|
// if (UV.y > 0.5f)
|
|
if (0)
|
|
{
|
|
uint SubsurfaceProfileInt = ExtractSubsurfaceProfileInt(ScreenSpaceData.GBuffer);
|
|
OutColor = float4(0.5f, 0.5f, 0.5f, 0);
|
|
if (SubsurfaceProfileInt == 0)
|
|
{
|
|
OutColor = float4(0.8f, 0.7f, 0.6f, 0);
|
|
}
|
|
if (SubsurfaceProfileInt == 1)
|
|
{
|
|
OutColor = float4(1, 0, 0, 0);
|
|
}
|
|
if (SubsurfaceProfileInt == 2)
|
|
{
|
|
OutColor = float4(0, 1, 0, 0);
|
|
}
|
|
if (SubsurfaceProfileInt == 3)
|
|
{
|
|
OutColor = float4(0, 0, 1, 0);
|
|
}
|
|
if (SubsurfaceProfileInt == 4)
|
|
{
|
|
OutColor = float4(1, 0, 1, 0);
|
|
}
|
|
if (SubsurfaceProfileInt == 5)
|
|
{
|
|
OutColor = float4(0, 1, 1, 0);
|
|
}
|
|
if (SubsurfaceProfileInt == 6)
|
|
{
|
|
OutColor = float4(1, 1, 0, 0);
|
|
}
|
|
if (SubsurfaceProfileInt == 100)
|
|
{
|
|
OutColor = float4(0, 0.2f, 0, 0);
|
|
}
|
|
if (SubsurfaceProfileInt == 255)
|
|
{
|
|
OutColor = float4(1, 1, 1, 0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// call into "SeparableSSS.usf"
|
|
|
|
// in world units, *0.01 to scale from units(cm) to m
|
|
float sssWidth = SSSParams.x;
|
|
|
|
// the viewport is only a fraction of the buffersize, here we compensate for that
|
|
// *1000 as we store the sample distances / 1000 to allows for scaling
|
|
float Scaler = View.ViewSizeAndSceneTexelSize.x * View.ViewSizeAndSceneTexelSize.z * 1000.0f;
|
|
|
|
#if METHOD == 0
|
|
// first pass
|
|
float2 Direction = float2(1, 0) * Scaler;
|
|
#else
|
|
// second pass
|
|
float2 Direction = float2(0, View.ViewSizeAndSceneTexelSize.w / View.ViewSizeAndSceneTexelSize.z) * Scaler;
|
|
#endif
|
|
OutColor = SSSSBlurPS(UV, sssWidth, Direction, false);
|
|
|
|
OutColor.a = 1.0f;
|
|
|
|
// Lighting
|
|
|
|
#if METHOD > 0
|
|
// on second pass we recombine with the scene color
|
|
|
|
float4 SceneColor4 = Texture2DSample(PostprocessInput0, PostprocessInput0Sampler, UV);
|
|
|
|
float4 SSSColor = OutColor;
|
|
|
|
SSSColor.a = (ScreenSpaceData.GBuffer.ShadingModelID >= SHADINGMODELID_SUBSURFACE_PROFILE);
|
|
|
|
#if METHOD > 1
|
|
// we took the specular highlights out, now we add them back in
|
|
SSSColor.rgb += LightAccumulator_ReconstructNonDiffuseLighting(SceneColor4);
|
|
#endif
|
|
|
|
// alpha channel can be anything - we consumed the value and likely output to a format that doesn't need the value
|
|
OutColor = float4(lerp(SceneColor4.rgb, SSSColor.rgb, SSSColor.a), 0);
|
|
#endif
|
|
}
|