Files
UnrealEngineUWP/Engine/Shaders/PostProcessSubsurface.usf
Martin Mittring b58ae4285d * added new shading model Subsurface_Profile, can specify SubsurfaceProfile asset on the material, create it in content browser
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]
2014-07-29 17:33:28 -04:00

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
}