浏览代码

Optimize Disney SSS using the tagged irradiance buffer

/Yibing-Project-2
Evgenii Golubev 7 年前
当前提交
a5a2abf8
共有 6 个文件被更改,包括 36 次插入25 次删除
  1. 16
      ScriptableRenderPipeline/Core/ShaderLibrary/CommonMaterial.hlsl
  2. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  3. 7
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Deferred.shader
  4. 8
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Deferred.compute
  5. 23
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.compute
  6. 6
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.shader

16
ScriptableRenderPipeline/Core/ShaderLibrary/CommonMaterial.hlsl


return saturate((NdotL + w) / ((1 + w) * (1 + w)));
}
// In order to support subsurface scattering, we need to know which pixels have an SSS material.
// It can be accomplished by reading the stencil buffer.
// A faster solution (which avoids an extra texture fetch) is to simply make sure that
// all pixels which belong to an SSS material are not black (those that don't always are).
float3 TagLightingForSSS(float3 subsurfaceLighting)
{
subsurfaceLighting.r = max(subsurfaceLighting.r, HFLT_MIN);
return subsurfaceLighting;
}
// See TagLightingForSSS() for details.
bool TestLightingForSSS(float3 subsurfaceLighting)
{
return subsurfaceLighting.r > 0;
}
// MACRO from Legacy Untiy
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex, name) ((tex.xy) * name##_ST.xy + name##_ST.zw)

1
ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, HDShaderIDs._GBufferTexture2, m_GbufferManager.GetGBuffers()[2]);
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, HDShaderIDs._GBufferTexture3, m_GbufferManager.GetGBuffers()[3]);
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, HDShaderIDs._DepthTexture, GetDepthTexture());
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, HDShaderIDs._StencilTexture, GetStencilTexture());
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, HDShaderIDs._HTile, GetHTile());
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, HDShaderIDs._IrradianceSource, m_CameraSssDiffuseLightingBufferRT);

7
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Deferred.shader


Outputs outputs;
#ifdef OUTPUT_SPLIT_LIGHTING
outputs.specularLighting = float4(specularLighting, 1.0);
outputs.diffuseLighting = diffuseLighting;
// We SSSSS is enabled with use split lighting.
// SSSSS algorithm need to know which pixels contribute to SSS and which doesn't. We could use the stencil for that but it mean that it will increase the cost of SSSSS
// A simpler solution is to add a slight contribution here that isn't visible (here we chose fp16 min (which is also fp11 and fp10 min).
// The SSSSS algorithm will check if diffuse lighting is black and discard the pixel if it is the case
outputs.diffuseLighting.r = max(outputs.diffuseLighting.r, HFLT_MIN);
outputs.diffuseLighting = TagLightingForSSS(diffuseLighting);
#else
outputs.combinedLighting = float4(diffuseLighting + specularLighting, 1.0);
#endif

8
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Deferred.compute


if (_EnableSSSAndTransmission != 0 && bsdfData.materialId == MATERIALID_LIT_SSS && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_SSS))
{
// We SSSSS is enabled with use split lighting.
// SSSSS algorithm need to know which pixels contribute to SSS and which doesn't. We could use the stencil for that but it mean that it will increase the cost of SSSSS
// A simpler solution is to add a slight contribution here that isn't visible (here we chose fp16 min (which is also fp11 and fp10 min).
// The SSSSS algorithm will check if diffuse lighting is black and discard the pixel if it is the case
diffuseLighting.r = max(diffuseLighting.r, HFLT_MIN);
diffuseLightingUAV[pixelCoord] = diffuseLighting;
diffuseLightingUAV[pixelCoord] = TagLightingForSSS(diffuseLighting);
}
else
{

23
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.compute


DECLARE_GBUFFER_TEXTURE(_GBufferTexture); // Contains the albedo and SSS parameters
TEXTURE2D(_DepthTexture); // Z-buffer
TEXTURE2D(_StencilTexture); // DXGI_FORMAT_R8_UINT is not supported by Unity
TEXTURE2D(_HTile); // DXGI_FORMAT_R8_UINT is not supported by Unity
TEXTURE2D(_IrradianceSource); // Includes transmitted light

bool passedStencilTest;
#if SSS_SAMPLE_TEST_HTILE
int2 tileCoord = pixelCoord >> 3; // Divide by 8
int2 tileCoord = pixelCoord / 8;
// Perform the stencil test (reject at the tile rate).
passedStencilTest = stencilRef == LOAD_TEXTURE2D(_HTile, tileCoord).r;

{
// Unfortunately, our copy of HTile does not allow to accept at the tile rate.
// Therefore, we have to additionally perform the stencil test at the pixel rate.
passedStencilTest = (uint)stencilRef == UnpackByte(LOAD_TEXTURE2D(_StencilTexture, pixelCoord).r);
// We check the tagged irradiance buffer to avoid an extra stencil texture fetch.
passedStencilTest = TestLightingForSSS(LOAD_TEXTURE2D(_IrradianceSource, pixelCoord).rgb);
}
return passedStencilTest;

float4 textureSample = LoadSample(position, cacheAnchor);
float3 irradiance = textureSample.rgb;
float linearDepth = textureSample.a;
if (linearDepth > 0)
if (TestLightingForSSS(irradiance))
float linearDepth = textureSample.a;
float z = linearDepth - centerPosVS.z;
float p = _FilterKernels[profileID][i][iP];
float3 w = ComputeBilateralWeight(xy2, z, mmPerUnit, shapeParam, p);

}
else
{
// The irradiance is 0. This could happen for 2 reasons.
// Most likely, the surface fragment does not have an SSS material.
// Alternatively, our sample comes from a region without any geometry.
// 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).
}
}
void WriteResult(uint2 pixelCoord, float3 irradiance)

float3 centerIrradiance = 0;
float centerDepth = 0;
float4 cachedValue = float4(0, 0, 0, 0);
float4 cachedValue = 0;
bool passedStencilTest = StencilTest((int2)pixelCoord, stencilRef);

uint2 cacheCoord2 = 2 * (startQuad + quadCoord) + uint2(laneIndex & 1, (laneIndex >> 1) & 1);
int2 pixelCoord2 = (int2)(tileAnchor + cacheCoord2) - TEXTURE_CACHE_BORDER;
float4 cachedValue2 = float4(0, 0, 0, 0);
float4 cachedValue2 = 0;
[branch] if (StencilTest(pixelCoord2, stencilRef))
{

6
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.shader


sampleWeight = _FilterKernelsBasic[profileID][i].rgb;
sampleIrradiance = LOAD_TEXTURE2D(_IrradianceSource, samplePosition).rgb;
[flatten]
if (any(sampleIrradiance))
if (TestLightingForSSS(sampleIrradiance))
{
// Apply bilateral weighting.
// Ref #1: Skin Rendering by Pseudo–Separable Cross Bilateral Filtering.

}
else
{
// The irradiance is 0. This could happen for 3 reasons.
// The irradiance is 0. This could happen for 2 reasons.
// 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).

正在加载...
取消
保存