您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

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
}