浏览代码

Remove the Disney model from the pixel shader

/RenderPassXR_Sandbox
Evgenii Golubev 7 年前
当前提交
41ed2b47
共有 3 个文件被更改,包括 10 次插入231 次删除
  1. 13
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  2. 10
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.compute
  3. 218
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.shader

13
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


m_DebugFullScreen = Utilities.CreateEngineMaterial(m_Asset.renderPipelineResources.debugFullScreenShader);
}
// Old SSS Model >>>
// Old SSS Model >>>
Utilities.SelectKeyword(m_SssVerticalFilterPass, "SSS_MODEL_DISNEY", "SSS_MODEL_BASIC", useDisneySSS);
Utilities.SelectKeyword(m_SssHorizontalFilterAndCombinePass, "SSS_MODEL_DISNEY", "SSS_MODEL_BASIC", useDisneySSS);
// <<< Old SSS Model
// <<< Old SSS Model
public void OnSceneLoad()
{

cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, "_CameraColorTexture", m_CameraColorBufferRT);
cmd.DispatchCompute(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, ((int)hdCamera.screenSize.x + 15) / 16, ((int)hdCamera.screenSize.y + 15) / 16, 1);
return;
//cmd.SetGlobalTexture("_IrradianceSource", m_CameraDiffuseIrradianceBufferRT); // Cannot set a RT on a material
//m_SssHorizontalFilterAndCombinePass.SetVectorArray("_WorldScales", sssParameters.worldScales);
//m_SssHorizontalFilterAndCombinePass.SetVectorArray("_FilterKernels", sssParameters.filterKernels);
//Utilities.DrawFullScreen(cmd, m_SssHorizontalFilterAndCombinePass, m_CameraColorBufferRT, m_CameraDepthStencilBufferRT);
}
else
{

10
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.compute


// Definitions
//--------------------------------------------------------------------------------------------------
#pragma enable_d3d11_debug_symbols
// #pragma enable_d3d11_debug_symbols
// Tweak parameters.
#define SSS_BILATERAL_FILTER 1

}
void EvaluateSample(uint i, uint n, uint profileID, uint iR, uint iP, uint2 pixelCoord, int2 cacheAnchor,
float3 shapeParam, float3 centerPosVS, float2 mmPerUnit, float2 pixelsPerMm,
float3 shapeParam, float3 centerPosVS, float mmPerUnit, float2 pixelsPerMm,
bool useTangentPlane, float3 tangentX, float3 tangentY, float4x4 projMatrix,
inout float3 totalIrradiance, inout float3 totalWeight)
{

[branch] if (!processGroup) { return; }
float3 centerIrradiance;
float centerDepth;
float4 cachedValue = float4(0, 0, 0, 0);
float3 centerIrradiance = 0;
float centerDepth = 0;
float4 cachedValue = float4(0, 0, 0, 0);
bool passedStencilTest = StencilTest(pixelCoord, stencilRef);

218
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.shader


Shader "Hidden/HDRenderPipeline/SubsurfaceScattering"
{
// Old SSS Model >>>
// <<< Old SSS Model
SubShader
{

Cull Off
ZTest Always
ZWrite Off
// Old SSS Model >>>
// <<< Old SSS Model
HLSLPROGRAM
#pragma target 4.5

#pragma vertex Vert
#pragma fragment Frag
// Old SSS Model >>>
#pragma multi_compile SSS_MODEL_BASIC SSS_MODEL_DISNEY
// <<< Old SSS Model
// Tweak parameters for the Disney SSS below.
#define SSS_BILATERAL_FILTER 1
#define SSS_USE_TANGENT_PLANE 0
#define SSS_CLAMP_ARTIFACT 0
#define SSS_DEBUG_LOD 0
#define SSS_DEBUG_NORMAL_VS 0
// Do not modify these.
#define SSS_PASS 1

// Inputs & outputs
//-------------------------------------------------------------------------------------
float4 _WorldScales[SSS_N_PROFILES]; // Size of the world unit in meters (only the X component is used)
#ifdef SSS_MODEL_DISNEY
float _FilterKernelsNearField[SSS_N_PROFILES][SSS_N_SAMPLES_NEAR_FIELD][2]; // 0 = radius, 1 = reciprocal of the PDF
float _FilterKernelsFarField[SSS_N_PROFILES][SSS_N_SAMPLES_FAR_FIELD][2]; // 0 = radius, 1 = reciprocal of the PDF
#else
float4 _FilterKernelsBasic[SSS_N_PROFILES][SSS_BASIC_N_SAMPLES]; // RGB = weights, A = radial distance
float4 _HalfRcpWeightedVariances[SSS_BASIC_N_SAMPLES]; // RGB for chromatic, A for achromatic
#endif
float4 _WorldScales[SSS_N_PROFILES]; // Size of the world unit in meters (only the X component is used)
float4 _FilterKernelsBasic[SSS_N_PROFILES][SSS_BASIC_N_SAMPLES]; // RGB = weights, A = radial distance
float4 _HalfRcpWeightedVariances[SSS_BASIC_N_SAMPLES]; // RGB for chromatic, A for achromatic
TEXTURE2D(_IrradianceSource); // Includes transmitted light
DECLARE_GBUFFER_TEXTURE(_GBufferTexture); // Contains the albedo and SSS parameters

//-------------------------------------------------------------------------------------
// Computes the value of the integrand over a disk: (2 * PI * r) * KernelVal().
// N.b.: the returned value is multiplied by 4. It is irrelevant due to weight renormalization.
float3 KernelValCircle(float r, float3 S)
{
float3 expOneThird = exp(((-1.0 / 3.0) * r) * S);
return /* 0.25 * */ S * (expOneThird + expOneThird * expOneThird * expOneThird);
}
// Computes F(r)/P(r), s.t. r = sqrt(a^2 + b^2).
// Rescaling of the PDF is handled by 'totalWeight'.
float3 ComputeBilateralWeight(float a2, float b, float mmPerUnit, float3 S, float rcpPdf)
{
#if (SSS_BILATERAL_FILTER == 0)
b = 0;
#endif
#if SSS_USE_TANGENT_PLANE
// Both 'a2' and 'b2' require unit conversion.
float r = sqrt(a2 + b * b) * mmPerUnit;
#else
// Only 'b2' requires unit conversion.
float r = sqrt(a2 + (b * mmPerUnit) * (b * mmPerUnit));
#endif
#if SSS_CLAMP_ARTIFACT
return saturate(KernelValCircle(r, S) * rcpPdf);
#else
return KernelValCircle(r, S) * rcpPdf;
#endif
}
#define SSS_ITER(i, n, kernel, profileID, shapeParam, centerPosUnSS, centerPosVS, \
useTangentPlane, tangentX, tangentY, mmPerUnit, pixelsPerMm, \
totalIrradiance, totalWeight) \
{ \
float r = kernel[profileID][i][0]; \
/* The relative sample position is known at compile time. */ \
float phi = SampleDiskFibonacci(i, n).y; \
float2 vec = r * float2(cos(phi), sin(phi)); \
\
/* Compute the screen-space position and the associated irradiance. */ \
float2 position; float3 irradiance; \
/* Compute the squared distance (in mm) in the screen-aligned plane. */ \
float dXY2; \
\
if (useTangentPlane) \
{ \
/* 'vec' is given relative to the tangent frame. */ \
float3 relPosVS = vec.x * tangentX + vec.y * tangentY; \
float3 positionVS = centerPosVS + relPosVS; \
float4 positionCS = mul(projMatrix, float4(positionVS, 1)); \
float2 positionSS = ComputeScreenSpacePosition(positionCS); \
\
position = positionSS * _ScreenSize.xy; \
irradiance = LOAD_TEXTURE2D(_IrradianceSource, position).rgb; \
dXY2 = dot(relPosVS.xy, relPosVS.xy); \
} \
else \
{ \
/* 'vec' is given directly in screen-space. */ \
position = centerPosUnSS + vec * pixelsPerMm; \
irradiance = LOAD_TEXTURE2D(_IrradianceSource, position).rgb; \
dXY2 = r * r; \
} \
\
/* TODO: see if making this a [branch] improves performance. */ \
[flatten] \
if (any(irradiance)) \
{ \
/* Apply bilateral weighting. */ \
float z = LOAD_TEXTURE2D(_MainDepthTexture, position).r; \
float d = LinearEyeDepth(z, _ZBufferParams); \
float t = d - centerPosVS.z; \
float p = kernel[profileID][i][1]; \
float3 w = ComputeBilateralWeight(dXY2, t, mmPerUnit, shapeParam, p); \
\
totalIrradiance += w * irradiance; \
totalWeight += w; \
} \
else \
{ \
/*************************************************************************/ \
/* The irradiance is 0. This could happen for 3 reasons. */ \
/* Most likely, the surface fragment does not have an SSS material. */ \
/* Alternatively, our sample comes from a region without any geometry. */ \
/* Finally, the surface fragment could be completely shadowed. */ \
/* Our blur is energy-preserving, so 'centerWeight' should be set to 0. */ \
/* We do not terminate the loop since we want to gather the contribution */ \
/* of the remaining samples (e.g. in case of hair covering skin). */ \
/* Note: See comment in the output of deferred.shader */ \
/*************************************************************************/ \
} \
}
#define SSS_LOOP(n, kernel, profileID, shapeParam, centerPosUnSS, centerPosVS, \
useTangentPlane, tangentX, tangentY, mmPerUnit, pixelsPerMm, \
totalIrradiance, totalWeight) \
{ \
float centerRadius = kernel[profileID][0][0]; \
float centerRcpPdf = kernel[profileID][0][1]; \
float3 centerWeight = KernelValCircle(centerRadius, shapeParam) * centerRcpPdf; \
\
totalIrradiance = centerWeight * centerIrradiance; \
totalWeight = centerWeight; \
\
/* Integrate over the screen-aligned or tangent plane in the view space. */ \
[unroll] \
for (uint i = 1; i < n; i++) \
{ \
SSS_ITER(i, n, kernel, profileID, shapeParam, centerPosUnSS, centerPosVS, \
useTangentPlane, tangentX, tangentY, mmPerUnit, pixelsPerMm, \
totalIrradiance, totalWeight) \
} \
}
struct Attributes
{
uint vertexID : SV_VertexID;

int profileID = bsdfData.subsurfaceProfile;
float distScale = bsdfData.subsurfaceRadius;
#ifdef SSS_MODEL_DISNEY
float3 shapeParam = _ShapeParams[profileID].rgb;
float maxDistance = _ShapeParams[profileID].a;
#else
#endif
// Take the first (central) sample.
// TODO: copy its neighborhood into LDS.

float3 centerPosVS = ComputeViewSpacePosition(centerPosSS, centerDepth, _InvProjMatrix);
float3 cornerPosVS = ComputeViewSpacePosition(cornerPosSS, centerDepth, _InvProjMatrix);
#ifdef SSS_MODEL_DISNEY
// Rescaling the filter is equivalent to inversely scaling the world.
float mmPerUnit = MILLIMETERS_PER_METER * (_WorldScales[profileID].x / distScale);
float unitsPerMm = rcp(mmPerUnit);
// Compute the view-space dimensions of the pixel as a quad projected onto geometry.
float2 unitsPerPixel = 2 * abs(cornerPosVS.xy - centerPosVS.xy);
float2 pixelsPerMm = rcp(unitsPerPixel) * unitsPerMm;
// We perform point sampling. Therefore, we can avoid the cost
// of filtering if we stay within the bounds of the current pixel.
// We use the value of 1 instead of 0.5 as an optimization.
// N.b.: our LoD selection algorithm is the same regardless of
// whether we integrate over the tangent plane or not, since we
// don't want the orientation of the tangent plane to create
// divergence of execution across the warp.
float maxDistInPixels = maxDistance * max(pixelsPerMm.x, pixelsPerMm.y);
[branch]
if (distScale == 0 || maxDistInPixels < 1)
{
#if SSS_DEBUG_LOD
return float4(0, 0, 1, 1);
#else
return float4(bsdfData.diffuseColor * centerIrradiance, 1);
#endif
}
const bool useTangentPlane = SSS_USE_TANGENT_PLANE != 0;
float4x4 viewMatrix, projMatrix;
GetLeftHandedViewSpaceMatrices(viewMatrix, projMatrix);
// Compute the tangent frame in view space.
float3 normalVS = mul((float3x3)viewMatrix, bsdfData.normalWS);
float3 tangentX = GetLocalFrame(normalVS)[0] * unitsPerMm;
float3 tangentY = GetLocalFrame(normalVS)[1] * unitsPerMm;
#if SSS_DEBUG_NORMAL_VS
// We expect the view-space normal to be front-facing.
if (normalVS.z >= 0) return float4(1, 0, 0, 1);
#endif
// Accumulate filtered irradiance and bilateral weights (for renormalization).
float3 totalIrradiance, totalWeight;
// Use fewer samples for SS regions smaller than 5x5 pixels (rotated by 45 degrees).
[branch]
if (maxDistInPixels < SSS_LOD_THRESHOLD)
{
#if SSS_DEBUG_LOD
return float4(0.5, 0.5, 0, 1);
#else
SSS_LOOP(SSS_N_SAMPLES_FAR_FIELD, _FilterKernelsFarField,
profileID, shapeParam, centerPosition, centerPosVS,
useTangentPlane, tangentX, tangentY, mmPerUnit, pixelsPerMm,
totalIrradiance, totalWeight)
#endif
}
else
{
#if SSS_DEBUG_LOD
return float4(1, 0, 0, 1);
#else
SSS_LOOP(SSS_N_SAMPLES_NEAR_FIELD, _FilterKernelsNearField,
profileID, shapeParam, centerPosition, centerPosVS,
useTangentPlane, tangentX, tangentY, mmPerUnit, pixelsPerMm,
totalIrradiance, totalWeight)
#endif
}
#else
// Rescaling the filter is equivalent to inversely scaling the world.
float metersPerUnit = _WorldScales[profileID].x / distScale * SSS_BASIC_DISTANCE_SCALE;
float centimPerUnit = CENTIMETERS_PER_METER * metersPerUnit;

// of the remaining samples (e.g. in case of hair covering skin).
}
}
#endif
return float4(bsdfData.diffuseColor * totalIrradiance / totalWeight, 1);
}

正在加载...
取消
保存