您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
148 行
5.8 KiB
148 行
5.8 KiB
Shader "Hidden/HDRenderPipeline/CombineSubsurfaceScattering"
|
|
{
|
|
Properties
|
|
{
|
|
[HideInInspector] _DstBlend("", Float) = 1 // Can be set to 1 for blending with specular
|
|
}
|
|
|
|
SubShader
|
|
{
|
|
Pass
|
|
{
|
|
Stencil
|
|
{
|
|
Ref 1 // StencilBits.SSS
|
|
Comp Equal
|
|
Pass Keep
|
|
}
|
|
|
|
Cull Off
|
|
ZTest Always
|
|
ZWrite Off
|
|
Blend One [_DstBlend]
|
|
|
|
HLSLPROGRAM
|
|
#pragma target 4.5
|
|
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
|
|
|
|
#pragma vertex Vert
|
|
#pragma fragment Frag
|
|
|
|
#pragma multi_compile _ FILTER_HORIZONTAL
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Include
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
#include "Common.hlsl"
|
|
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Inputs & outputs
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
#define N_PROFILES 8
|
|
#define N_SAMPLES 7
|
|
|
|
float4 _FilterKernels[N_PROFILES][N_SAMPLES + 1]; // RGB = weights, A = radial distance
|
|
float4x4 _InvProjMatrix;
|
|
|
|
TEXTURE2D_FLOAT(_CameraDepthTexture);
|
|
TEXTURE2D(_GBufferTexture2);
|
|
TEXTURE2D(_IrradianceSource);
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Implementation
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
struct Attributes
|
|
{
|
|
uint vertexID : SV_VertexID;
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionCS : SV_Position;
|
|
};
|
|
|
|
Varyings Vert(Attributes input)
|
|
{
|
|
Varyings output;
|
|
output.positionCS = GetFullscreenTriangleVertexPosition(input.vertexID);
|
|
return output;
|
|
}
|
|
|
|
float3 Frag(Varyings input) : SV_Target
|
|
{
|
|
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
|
|
|
|
float2 gBufferData = LOAD_TEXTURE2D(_GBufferTexture2, posInput.unPositionSS).ra;
|
|
int profileID = int(gBufferData.y * N_PROFILES);
|
|
float distScale = gBufferData.x * 0.01;
|
|
float invDistScale = rcp(distScale);
|
|
|
|
// Reconstruct the view-space position.
|
|
float rawDepth = LOAD_TEXTURE2D(_CameraDepthTexture, posInput.unPositionSS).r;
|
|
float3 centerPosVS = ComputeViewSpacePosition(posInput.positionSS, rawDepth, _InvProjMatrix);
|
|
|
|
// Compute the dimensions of the surface fragment viewed as a quad facing the camera.
|
|
float fragWidth = ddx(centerPosVS.x);
|
|
float fragheight = ddy(centerPosVS.y);
|
|
float stepSizeX = rcp(fragWidth);
|
|
float stepSizeY = rcp(fragheight);
|
|
|
|
// Compute the filtering direction.
|
|
#ifdef FILTER_HORIZONTAL
|
|
float stepSize = stepSizeX;
|
|
float2 unitDirection = float2(1, 0);
|
|
#else
|
|
float stepSize = stepSizeY;
|
|
float2 unitDirection = float2(0, 1);
|
|
#endif
|
|
float2 scaledDirection = distScale * stepSize * unitDirection;
|
|
|
|
// Load (1 / (2 * Variance)) for bilateral weighting.
|
|
#ifdef RBG_BILATERAL_WEIGHTS
|
|
float3 halfRcpVariance = _FilterKernels[profileID][N_SAMPLES].rgb;
|
|
#else
|
|
float halfRcpVariance = _FilterKernels[profileID][N_SAMPLES].a;
|
|
#endif
|
|
// Take the first (central) sample.
|
|
float2 samplePosition = posInput.unPositionSS;
|
|
float3 sampleWeight = _FilterKernels[profileID][0].rgb;
|
|
float3 sampleIrradiance = LOAD_TEXTURE2D(_IrradianceSource, samplePosition).rgb;
|
|
|
|
// Accumulate filtered irradiance (already weighted by (albedo / Pi)).
|
|
float3 totalIrradiance = sampleIrradiance * sampleWeight;
|
|
|
|
// Make sure bilateral filtering does not cause energy loss.
|
|
// TODO: ask Morten if there is a better way to do this.
|
|
float3 totalWeight = sampleWeight;
|
|
|
|
[unroll]
|
|
for (int i = 1; i < N_SAMPLES; i++)
|
|
{
|
|
samplePosition = posInput.unPositionSS + scaledDirection * _FilterKernels[profileID][i].a;
|
|
sampleWeight = _FilterKernels[profileID][i].rgb;
|
|
|
|
rawDepth = LOAD_TEXTURE2D(_CameraDepthTexture, samplePosition).r;
|
|
sampleIrradiance = LOAD_TEXTURE2D(_IrradianceSource, samplePosition).rgb;
|
|
|
|
// Apply bilateral weighting.
|
|
// Ref #1: Skin Rendering by Pseudo–Separable Cross Bilateral Filtering.
|
|
// Ref #2: Separable SSS, Supplementary Materials, Section E.
|
|
float sampleDepth = LinearEyeDepth(rawDepth, _ZBufferParams);
|
|
float zDistance = invDistScale * sampleDepth - (invDistScale * centerPosVS.z);
|
|
sampleWeight *= exp(-zDistance * zDistance * halfRcpVariance);
|
|
|
|
totalIrradiance += sampleIrradiance * sampleWeight;
|
|
totalWeight += sampleWeight;
|
|
}
|
|
|
|
return totalIrradiance / totalWeight;
|
|
}
|
|
ENDHLSL
|
|
}
|
|
}
|
|
Fallback Off
|
|
}
|