浏览代码

Merge pull request #342 from EvgeniiG/opt_sss

Port SSS to compute with an LDS texture cache
/RenderPassXR_Sandbox
GitHub 7 年前
当前提交
f92ef9c5
共有 27 个文件被更改,包括 2927 次插入401 次删除
  1. 161
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  2. 3
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipelineAsset.asset
  3. 5
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  4. 10
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  5. 11
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CopyStencilBuffer.shader
  6. 224
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.shader
  7. 154
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SkinSSSProfile.asset
  8. 84
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs
  9. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/RenderPipelineResources/HDRenderPipelineResources.asset
  10. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/RenderPipelineResources/RenderPipelineResources.cs
  11. 1
      Assets/ScriptableRenderPipeline/ShaderLibrary/API/D3D11.hlsl
  12. 1
      Assets/ScriptableRenderPipeline/ShaderLibrary/API/Metal.hlsl
  13. 1
      Assets/ScriptableRenderPipeline/ShaderLibrary/API/PSSL.hlsl
  14. 1
      Assets/ScriptableRenderPipeline/ShaderLibrary/Common.hlsl
  15. 2
      Assets/TestScenes/HDTest/GraphicTest/SSS/Materials/SSSHead.mat
  16. 428
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.compute
  17. 10
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.compute.meta
  18. 72
      Assets/ScriptableRenderPipeline/ShaderLibrary/SpaceFillingCurves.hlsl
  19. 10
      Assets/ScriptableRenderPipeline/ShaderLibrary/SpaceFillingCurves.hlsl.meta
  20. 116
      Assets/TestScenes/HDTest/GraphicTest/SSS/ProfilingSkinSSSProfile.asset
  21. 9
      Assets/TestScenes/HDTest/GraphicTest/SSS/ProfilingSkinSSSProfile.asset.meta
  22. 1001
      Assets/TestScenes/HDTest/GraphicTest/SSS/Test - SSS model .prefab
  23. 10
      Assets/TestScenes/HDTest/GraphicTest/SSS/Test - SSS model .prefab.meta
  24. 1001
      Assets/TestScenes/HDTest/SSSProfiling.unity
  25. 9
      Assets/TestScenes/HDTest/SSSProfiling.unity.meta
  26. 0
      /Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.shader.meta
  27. 0
      /Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.shader

161
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


cmd.SetComputeVectorParam(cs, "_ScreenSize", screenSize);
cmd.SetComputeMatrixParam(cs, "_PrevViewProjMatrix", prevViewProjMatrix);
cmd.SetComputeVectorArrayParam(cs, "_FrustumPlanes", frustumPlaneEquations);
// Copy values set by Unity which are not configured in scripts.
cmd.SetComputeVectorParam(cs, "unity_OrthoParams", Shader.GetGlobalVector("unity_OrthoParams"));
cmd.SetComputeVectorParam(cs, "_ProjectionParams", Shader.GetGlobalVector("_ProjectionParams"));
cmd.SetComputeVectorParam(cs, "_ScreenParams", Shader.GetGlobalVector("_ScreenParams"));
cmd.SetComputeVectorParam(cs, "_ZBufferParams", Shader.GetGlobalVector("_ZBufferParams"));
cmd.SetComputeVectorParam(cs, "_WorldSpaceCameraPos", Shader.GetGlobalVector("_WorldSpaceCameraPos"));
}
}

Material m_CopyStencilBuffer;
// Various set of material use in render loop
Material m_FilterAndCombineSubsurfaceScattering;
ComputeShader m_SubsurfaceScatteringCS { get { return m_Asset.renderPipelineResources.subsurfaceScatteringCS; } }
int m_SubsurfaceScatteringKernel;
Material m_FilterSubsurfaceScattering;
Material m_SssVerticalFilterPass;
Material m_SssHorizontalFilterAndCombinePass;
// <<< Old SSS Model
Material m_CameraMotionVectorsMaterial;

// Various buffer
readonly int m_CameraColorBuffer;
readonly int m_CameraSubsurfaceBuffer;
readonly int m_CameraDiffuseIrradianceBuffer;
// Old SSS Model >>>
readonly int m_CameraFilteringBuffer;
// <<< Old SSS Model

// 'm_CameraColorBuffer' does not contain diffuse lighting of SSS materials until the SSS pass.
// It is stored within 'm_CameraSubsurfaceBufferRT'.
readonly RenderTargetIdentifier m_CameraColorBufferRT;
readonly RenderTargetIdentifier m_CameraSubsurfaceBufferRT;
readonly RenderTargetIdentifier m_CameraDiffuseIrradianceBufferRT;
// Old SSS Model >>>
readonly RenderTargetIdentifier m_CameraFilteringBufferRT;
// <<< Old SSS Model

private RenderTexture m_CameraDepthStencilBuffer = null;
private RenderTexture m_CameraDepthBufferCopy = null;
private RenderTexture m_CameraStencilBufferCopy = null; // Currently, it's manually copied using a pixel shader, and optimized to only contain the SSS bit
private RenderTexture m_HTile = null; // If the hardware does not expose it, we compute our own, optimized to only contain the SSS bit
private RenderTargetIdentifier m_HTileRT;
// Post-processing context and screen-space effects (recycled on every frame to avoid GC alloc)
readonly PostProcessRenderContext m_PostProcessContext;

// whereas it work. Don't know what is hapening, DebugDisplay use the same code and name is correct there.
// Debug.Assert(m_DeferredMaterial != null);
m_CameraColorBuffer = Shader.PropertyToID("_CameraColorTexture");
m_CameraSubsurfaceBuffer = Shader.PropertyToID("_CameraSubsurfaceTexture");
m_CameraColorBuffer = Shader.PropertyToID("_CameraColorTexture");
m_CameraColorBufferRT = new RenderTargetIdentifier(m_CameraColorBuffer);
m_CameraDiffuseIrradianceBuffer = Shader.PropertyToID("_CameraDiffuseIrradianceTexture");
m_CameraDiffuseIrradianceBufferRT = new RenderTargetIdentifier(m_CameraDiffuseIrradianceBuffer);
m_CameraColorBufferRT = new RenderTargetIdentifier(m_CameraColorBuffer);
m_CameraSubsurfaceBufferRT = new RenderTargetIdentifier(m_CameraSubsurfaceBuffer);
// Old SSS Model >>>
m_CameraFilteringBuffer = Shader.PropertyToID("_CameraFilteringBuffer");

m_DebugFullScreen = Utilities.CreateEngineMaterial(m_Asset.renderPipelineResources.debugFullScreenShader);
}
// Old SSS Model >>>
Utilities.Destroy(m_FilterSubsurfaceScattering);
m_FilterSubsurfaceScattering = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/CombineSubsurfaceScattering");
Utilities.SelectKeyword(m_FilterSubsurfaceScattering, "SSS_MODEL_DISNEY", "SSS_MODEL_BASIC", useDisneySSS);
m_FilterSubsurfaceScattering.DisableKeyword("SSS_FILTER_HORIZONTAL_AND_COMBINE");
m_FilterSubsurfaceScattering.SetFloat("_DstBlend", (float)BlendMode.Zero);
m_SubsurfaceScatteringKernel = m_SubsurfaceScatteringCS.FindKernel("SubsurfaceScattering");
// Old SSS Model >>>
Utilities.Destroy(m_SssVerticalFilterPass);
m_SssVerticalFilterPass = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/SubsurfaceScattering");
m_SssVerticalFilterPass.DisableKeyword("SSS_FILTER_HORIZONTAL_AND_COMBINE");
m_SssVerticalFilterPass.SetFloat("_DstBlend", (float)BlendMode.Zero);
Utilities.Destroy(m_FilterAndCombineSubsurfaceScattering);
m_FilterAndCombineSubsurfaceScattering = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/CombineSubsurfaceScattering");
Utilities.SelectKeyword(m_FilterAndCombineSubsurfaceScattering, "SSS_MODEL_DISNEY", "SSS_MODEL_BASIC", useDisneySSS);
m_FilterAndCombineSubsurfaceScattering.EnableKeyword("SSS_FILTER_HORIZONTAL_AND_COMBINE");
m_FilterAndCombineSubsurfaceScattering.SetFloat("_DstBlend", (float)BlendMode.One);
Utilities.Destroy(m_SssHorizontalFilterAndCombinePass);
m_SssHorizontalFilterAndCombinePass = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/SubsurfaceScattering");
m_SssHorizontalFilterAndCombinePass.EnableKeyword("SSS_FILTER_HORIZONTAL_AND_COMBINE");
m_SssHorizontalFilterAndCombinePass.SetFloat("_DstBlend", (float)BlendMode.One);
// <<< Old SSS Model
// <<< Old SSS Model
public void OnSceneLoad()
{

{
m_CameraStencilBufferCopy.Release();
}
m_CameraStencilBufferCopy = new RenderTexture(camera.pixelWidth, camera.pixelHeight, 0, RenderTextureFormat.R8);
m_CameraStencilBufferCopy = new RenderTexture(camera.pixelWidth, camera.pixelHeight, 0, RenderTextureFormat.R8, RenderTextureReadWrite.Linear); // DXGI_FORMAT_R8_UINT is not supported by Unity
if (NeedHTileCopy())
{
if (m_HTile!= null)
{
m_HTile.Release();
}
// We use 8x8 tiles in order to match the native GCN HTile as closely as possible.
m_HTile = new RenderTexture((camera.pixelWidth + 7) / 8, (camera.pixelHeight + 7) / 8, 0, RenderTextureFormat.R8, RenderTextureReadWrite.Linear); // DXGI_FORMAT_R8_UINT is not supported by Unity
m_HTile.filterMode = FilterMode.Point;
m_HTile.enableRandomWrite = true;
m_HTile.Create();
m_HTileRT = new RenderTargetIdentifier(m_HTile);
}
}
void Resize(Camera camera)

return m_DebugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission;
}
bool NeedHTileCopy()
{
// Currently, Unity does not offer a way to access the GCN HTile even on PS4 and Xbox One.
// Therefore, it's computed in a pixel shader, and optimized to only contain the SSS bit.
return NeedStencilBufferCopy();
}
RenderTargetIdentifier GetDepthTexture()
{
return NeedDepthBufferCopy() ? m_CameraDepthBufferCopy : m_CameraDepthStencilBuffer;

{
return NeedStencilBufferCopy() ? m_CameraStencilBufferCopyRT : m_CameraDepthStencilBufferRT;
}
RenderTargetIdentifier GetHTile()
{
// Currently, Unity does not offer a way to access the GCN HTile.
return m_HTileRT;
}
private void CopyDepthBufferIfNeeded(CommandBuffer cmd)

{
using (new Utilities.ProfilingSample("Copy StencilBuffer", cmd))
{
cmd.SetRandomWriteTarget(1, GetHTile());
cmd.ClearRandomWriteTargets();
cmd.SetGlobalTexture("_HTile", GetHTile());
cmd.SetGlobalTexture("_StencilTexture", GetStencilTexture());
}

// We compute subsurface scattering here. Therefore, no objects rendered afterwards will exhibit SSS.
// Currently, there is no efficient way to switch between SRT and MRT for the forward pass;
// therefore, forward-rendered objects do not output split lighting required for the SSS pass.
CombineSubsurfaceScattering(hdCamera, cmd, m_Asset.sssSettings);
SubsurfaceScatteringPass(hdCamera, cmd, m_Asset.sssSettings);
// For opaque forward we have split rendering in two categories
// Material that are always forward and material that can be deferred or forward depends on render pipeline options (like switch to rendering forward only mode)

return;
}
RenderTargetIdentifier[] colorRTs = { m_CameraColorBufferRT, m_CameraSubsurfaceBufferRT };
RenderTargetIdentifier[] colorRTs = { m_CameraColorBufferRT, m_CameraDiffuseIrradianceBufferRT };
RenderTargetIdentifier depthTexture = GetDepthTexture();
if (m_DebugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission)

}
// Combines specular lighting and diffuse lighting with subsurface scattering.
void CombineSubsurfaceScattering(HDCamera hdCamera, CommandBuffer cmd, SubsurfaceScatteringSettings sssParameters)
void SubsurfaceScatteringPass(HDCamera hdCamera, CommandBuffer cmd, SubsurfaceScatteringSettings sssParameters)
{
// Currently, forward-rendered objects do not output split lighting required for the SSS pass.
if (!m_DebugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission || m_Asset.renderingSettings.ShouldUseForwardRenderingOnly())

{
if (sssSettings.useDisneySSS)
{
cmd.SetGlobalTexture("_IrradianceSource", m_CameraSubsurfaceBufferRT); // Cannot set a RT on a material
m_FilterAndCombineSubsurfaceScattering.SetFloatArray("_WorldScales", sssParameters.worldScales);
m_FilterAndCombineSubsurfaceScattering.SetFloatArray("_FilterKernelsNearField", sssParameters.filterKernelsNearField);
m_FilterAndCombineSubsurfaceScattering.SetFloatArray("_FilterKernelsFarField", sssParameters.filterKernelsFarField);
hdCamera.SetupComputeShader(m_SubsurfaceScatteringCS, cmd);
Utilities.DrawFullScreen(cmd, m_FilterAndCombineSubsurfaceScattering, m_CameraColorBufferRT, m_CameraDepthStencilBufferRT);
cmd.SetComputeIntParam( m_SubsurfaceScatteringCS, "_TexturingModeFlags", sssParameters.texturingModeFlags);
cmd.SetComputeVectorArrayParam(m_SubsurfaceScatteringCS, "_WorldScales", sssParameters.worldScales);
cmd.SetComputeVectorArrayParam(m_SubsurfaceScatteringCS, "_FilterKernels", sssParameters.filterKernels);
cmd.SetComputeVectorArrayParam(m_SubsurfaceScatteringCS, "_ShapeParams", sssParameters.shapeParams);
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, "_GBufferTexture0", m_gbufferManager.GetGBuffers()[0]);
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, "_GBufferTexture1", m_gbufferManager.GetGBuffers()[1]);
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, "_GBufferTexture2", m_gbufferManager.GetGBuffers()[2]);
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, "_GBufferTexture3", m_gbufferManager.GetGBuffers()[3]);
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, "_DepthTexture", GetDepthTexture());
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, "_StencilTexture", GetStencilTexture());
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, "_HTile", GetHTile());
cmd.SetComputeTextureParam(m_SubsurfaceScatteringCS, m_SubsurfaceScatteringKernel, "_IrradianceSource", m_CameraDiffuseIrradianceBufferRT);
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);
cmd.SetGlobalTexture("_IrradianceSource", m_CameraSubsurfaceBufferRT); // Cannot set a RT on a material
m_FilterSubsurfaceScattering.SetFloatArray("_WorldScales", sssParameters.worldScales);
m_FilterSubsurfaceScattering.SetVectorArray("_FilterKernelsBasic", sssParameters.filterKernelsBasic);
m_FilterSubsurfaceScattering.SetVectorArray("_HalfRcpWeightedVariances", sssParameters.halfRcpWeightedVariances);
Utilities.DrawFullScreen(cmd, m_FilterSubsurfaceScattering, m_CameraFilteringBufferRT, m_CameraDepthStencilBufferRT);
cmd.SetGlobalTexture("_IrradianceSource", m_CameraDiffuseIrradianceBufferRT); // Cannot set a RT on a material
m_SssVerticalFilterPass.SetVectorArray("_WorldScales", sssParameters.worldScales);
m_SssVerticalFilterPass.SetVectorArray("_FilterKernelsBasic", sssParameters.filterKernelsBasic);
m_SssVerticalFilterPass.SetVectorArray("_HalfRcpWeightedVariances", sssParameters.halfRcpWeightedVariances);
Utilities.DrawFullScreen(cmd, m_SssVerticalFilterPass, m_CameraFilteringBufferRT, m_CameraDepthStencilBufferRT);
m_FilterAndCombineSubsurfaceScattering.SetFloatArray("_WorldScales", sssParameters.worldScales);
m_FilterAndCombineSubsurfaceScattering.SetVectorArray("_FilterKernelsBasic", sssParameters.filterKernelsBasic);
m_FilterAndCombineSubsurfaceScattering.SetVectorArray("_HalfRcpWeightedVariances", sssParameters.halfRcpWeightedVariances);
Utilities.DrawFullScreen(cmd, m_FilterAndCombineSubsurfaceScattering, m_CameraColorBufferRT, m_CameraDepthStencilBufferRT);
m_SssHorizontalFilterAndCombinePass.SetVectorArray("_WorldScales", sssParameters.worldScales);
m_SssHorizontalFilterAndCombinePass.SetVectorArray("_FilterKernelsBasic", sssParameters.filterKernelsBasic);
m_SssHorizontalFilterAndCombinePass.SetVectorArray("_HalfRcpWeightedVariances", sssParameters.halfRcpWeightedVariances);
Utilities.DrawFullScreen(cmd, m_SssHorizontalFilterAndCombinePass, m_CameraColorBufferRT, m_CameraDepthStencilBufferRT);
}
}
}

int w = camera.pixelWidth;
int h = camera.pixelHeight;
cmd.GetTemporaryRT(m_CameraColorBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraSubsurfaceBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.RGB111110Float, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraColorBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraDiffuseIrradianceBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.RGB111110Float, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraFilteringBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.RGB111110Float, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraFilteringBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.RGB111110Float, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
// <<< Old SSS Model
if (!m_Asset.renderingSettings.ShouldUseForwardRenderingOnly())

// Clear the diffuse SSS lighting target
using (new Utilities.ProfilingSample("Clear SSS diffuse target", cmd))
{
Utilities.SetRenderTarget(cmd, m_CameraSubsurfaceBufferRT, m_CameraDepthStencilBufferRT, ClearFlag.ClearColor, Color.black);
Utilities.SetRenderTarget(cmd, m_CameraDiffuseIrradianceBufferRT, m_CameraDepthStencilBufferRT, ClearFlag.ClearColor, Color.black);
// Clear the SSS filtering target
using (new Utilities.ProfilingSample("Clear SSS filtering target", cmd))
if (!sssSettings.useDisneySSS)
Utilities.SetRenderTarget(cmd, m_CameraFilteringBuffer, m_CameraDepthStencilBufferRT, ClearFlag.ClearColor, Color.black);
// Clear the SSS filtering target
using (new Utilities.ProfilingSample("Clear SSS filtering target", cmd))
{
Utilities.SetRenderTarget(cmd, m_CameraFilteringBuffer, m_CameraDepthStencilBufferRT, ClearFlag.ClearColor, Color.black);
}
if (NeedStencilBufferCopy())
{
using (new Utilities.ProfilingSample("Clear stencil texture", cmd))
{
Utilities.SetRenderTarget(cmd, m_CameraStencilBufferCopyRT, ClearFlag.ClearColor, Color.black);
}
}
if (NeedHTileCopy())
{
using (new Utilities.ProfilingSample("Clear HTile", cmd))
{
Utilities.SetRenderTarget(cmd, m_HTileRT, ClearFlag.ClearColor, Color.black);
}
}
// TEMP: As we are in development and have not all the setup pass we still clear the color in emissive buffer and gbuffer, but this will be removed later.

3
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipelineAsset.asset


useForwardRenderingOnly: 0
useDepthPrepass: 0
sssSettings:
numProfiles: 4
numProfiles: 5
- {fileID: 11400000, guid: aa5f2cc1c22cad043a617e9e9548b1b9, type: 2}
useDisneySSS: 1
tileSettings:
enableTileAndCluster: 1

5
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs


cmd.SetComputeVectorParam(deferredComputeShader, "_SinTime", sinTime);
cmd.SetComputeVectorParam(deferredComputeShader, "_CosTime", cosTime);
cmd.SetComputeVectorParam(deferredComputeShader, "unity_DeltaTime", unity_DeltaTime);
cmd.SetComputeVectorParam(deferredComputeShader, "_WorldSpaceCameraPos", worldSpaceCameraPos);
cmd.SetComputeVectorParam(deferredComputeShader, "_ProjectionParams", projectionParams);
cmd.SetComputeVectorParam(deferredComputeShader, "_ScreenParams", screenParams);
cmd.SetComputeVectorParam(deferredComputeShader, "_ZBufferParams", zbufferParams);
cmd.SetComputeVectorParam(deferredComputeShader, "unity_OrthoParams", unity_OrthoParams);
cmd.SetComputeIntParam(deferredComputeShader, "_EnvLightSkyEnabled", envLightSkyEnabled);
cmd.SetComputeFloatParam(deferredComputeShader, "_AmbientOcclusionDirectLightStrenght", ambientOcclusionDirectLightStrenght);

10
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


bool performPostScatterTexturing = IsBitSet(_TexturingModeFlags, subsurfaceProfile);
bool enableSssAndTransmission = true;
if (0)
#else
if (_EnableSSSAndTransmission != 0) // If we globally disable SSS effect, don't modify diffuseColor
enableSssAndTransmission = false;
#elif (SSS_PASS == 0)
enableSssAndTransmission = _EnableSSSAndTransmission != 0;
if (enableSssAndTransmission) // If we globally disable SSS effect, don't modify diffuseColor
{
// We modify the albedo here as this code is used by all lighting (including light maps and GI).
if (performPostScatterTexturing)

11
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CopyStencilBuffer.shader


#include "../../../ShaderVariables.hlsl"
#include "../../../Lighting/LightDefinition.cs.hlsl"
RW_TEXTURE2D(float, _HTile); // DXGI_FORMAT_R8_UINT is not supported by Unity
struct Attributes
{
uint vertexID : SV_VertexID;

return output;
}
// Should use HiS and therefore be faster than a GPU memcpy().
// Force the stencil test before the UAV write.
[earlydepthstencil]
uint2 positionSS = (uint2)input.positionCS.xy;
// There's no need for atomics as we are always writing the same value.
// Note: the GCN tile size is 8x8 pixels.
_HTile[positionSS / 8] = STENCILLIGHTINGUSAGE_SPLIT_LIGHTING;
return float4(STENCILLIGHTINGUSAGE_SPLIT_LIGHTING, 0, 0, 0);
}
ENDHLSL

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


Shader "Hidden/HDRenderPipeline/CombineSubsurfaceScattering"
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
//-------------------------------------------------------------------------------------
float _WorldScales[SSS_N_PROFILES]; // Size of the world unit in meters
#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
float mmPerUnit = MILLIMETERS_PER_METER * (_WorldScales[profileID] / 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] / distScale * SSS_BASIC_DISTANCE_SCALE;
float metersPerUnit = _WorldScales[profileID].x / distScale * SSS_BASIC_DISTANCE_SCALE;
float centimPerUnit = CENTIMETERS_PER_METER * metersPerUnit;
// Compute the view-space dimensions of the pixel as a quad projected onto geometry.
float2 unitsPerPixel = 2 * abs(cornerPosVS.xy - centerPosVS.xy);

return float4(bsdfData.diffuseColor * sampleIrradiance, 1);
#endif
}
#if SSS_DEBUG_LOD
return float4(0.5, 0.5, 0, 1);
#endif

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

154
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SkinSSSProfile.asset


worldScale: 1
settingsIndex: 0
m_ShapeParam: {x: 1.3192612, y: 3.1152647, z: 4.9751244}
m_MaxRadius: 8.458925
m_MaxRadius: 10.03481
- {x: 0, y: 1.516}
- {x: 0.027902514, y: 1.5535468}
- {x: 0.056502663, y: 1.5927485}
- {x: 0.0858313, y: 1.6337082}
- {x: 0.1159215, y: 1.6765369}
- {x: 0.14680836, y: 1.7213551}
- {x: 0.17852913, y: 1.7682924}
- {x: 0.21112362, y: 1.81749}
- {x: 0.24463426, y: 1.8691009}
- {x: 0.27910653, y: 1.9232914}
- {x: 0.31458887, y: 1.9802433}
- {x: 0.35113326, y: 2.0401537}
- {x: 0.3887955, y: 2.1032388}
- {x: 0.42763543, y: 2.1697347}
- {x: 0.46771717, y: 2.2399004}
- {x: 0.5091102, y: 2.3140202}
- {x: 0.55188924, y: 2.3924074}
- {x: 0.59613484, y: 2.4754071}
- {x: 0.6419343, y: 2.563401}
- {x: 0.68938226, y: 2.6568115}
- {x: 0.7385812, y: 2.756108}
- {x: 0.78964317, y: 2.8618138}
- {x: 0.8426895, y: 2.9745123}
- {x: 0.89785355, y: 3.0948577}
- {x: 0.95528066, y: 3.2235847}
- {x: 1.0151305, y: 3.3615222}
- {x: 1.0775794, y: 3.5096087}
- {x: 1.1428206, y: 3.66891}
- {x: 1.2110695, y: 3.8406446}
- {x: 1.282564, y: 4.026209}
- {x: 1.3575704, y: 4.227214}
- {x: 1.4363859, y: 4.4455285}
- {x: 1.5193442, y: 4.6833334}
- {x: 1.6068225, y: 4.943191}
- {x: 1.6992486, y: 5.228136}
- {x: 1.7971107, y: 5.541792}
- {x: 1.9009686, y: 5.88852}
- {x: 2.0114706, y: 6.273631}
- {x: 2.1293726, y: 6.7036633}
- {x: 2.2555614, y: 7.18675}
- {x: 2.3910918, y: 7.7331758}
- {x: 2.537231, y: 8.35613}
- {x: 2.6955185, y: 9.072821}
- {x: 2.8678567, y: 9.906171}
- {x: 3.056636, y: 10.887414}
- {x: 3.2649205, y: 12.060253}
- {x: 3.496729, y: 13.487793}
- {x: 3.7574923, y: 15.264698}
- {x: 4.054809, y: 17.539753}
- {x: 4.3997865, y: 20.560957}
- {x: 4.8096266, y: 24.774817}
- {x: 5.3131247, y: 31.074501}
- {x: 5.9642344, y: 41.544285}
- {x: 6.884045, y: 62.43729}
- {x: 8.458925, y: 125.02069}
- {x: 0.013865918, y: 1.5345725}
- {x: 0.04211352, y: 1.5729346}
- {x: 0.07107388, y: 1.6130018}
- {x: 0.100779116, y: 1.6548817}
- {x: 0.13126306, y: 1.6986896}
- {x: 0.16256203, y: 1.7445502}
- {x: 0.1947145, y: 1.7925992}
- {x: 0.22776169, y: 1.8429838}
- {x: 0.26174724, y: 1.8958628}
- {x: 0.29671827, y: 1.9514104}
- {x: 0.33272493, y: 2.0098157}
- {x: 0.369821, y: 2.0712852}
- {x: 0.40806437, y: 2.1360447}
- {x: 0.44751683, y: 2.2043417}
- {x: 0.48824534, y: 2.276447}
- {x: 0.5303216, y: 2.3526597}
- {x: 0.5738235, y: 2.433308}
- {x: 0.61883456, y: 2.5187542}
- {x: 0.665446, y: 2.609401}
- {x: 0.713756, y: 2.7056925}
- {x: 0.763872, y: 2.808125}
- {x: 0.8159103, y: 2.91725}
- {x: 0.8699981, y: 3.0336854}
- {x: 0.9262747, y: 3.1581244}
- {x: 0.98489225, y: 3.2913465}
- {x: 1.0460185, y: 3.434234}
- {x: 1.1098381, y: 3.5877857}
- {x: 1.1765549, y: 3.7531407}
- {x: 1.2463952, y: 3.9316032}
- {x: 1.319611, y: 4.124672}
- {x: 1.3964823, y: 4.3340797}
- {x: 1.4773248, y: 4.561845}
- {x: 1.5624928, y: 4.810328}
- {x: 1.6523882, y: 5.082317}
- {x: 1.747467, y: 5.381122}
- {x: 1.8482518, y: 5.710715}
- {x: 1.9553448, y: 6.0759025}
- {x: 2.069445, y: 6.482568}
- {x: 2.1913698, y: 6.9379897}
- {x: 2.3220856, y: 7.4513016}
- {x: 2.4627466, y: 8.0341215}
- {x: 2.614747, y: 8.701484}
- {x: 2.7797952, y: 9.473195}
- {x: 2.9600194, y: 10.375936}
- {x: 3.1581159, y: 11.446505}
- {x: 3.3775842, y: 12.737201}
- {x: 3.6230793, y: 14.324919}
- {x: 3.9009922, y: 16.327562}
- {x: 4.220452, y: 18.935623}
- {x: 4.5951686, y: 22.478209}
- {x: 5.047148, y: 27.57712}
- {x: 5.615129, y: 35.564823}
- {x: 6.3776174, y: 49.90625}
- {x: 7.5374603, y: 83.30668}
- {x: 10.03481, y: 250.11497}
- {x: 0, y: 1.516}
- {x: 0.07457052, y: 1.6178904}
- {x: 0.15428384, y: 1.7323332}
- {x: 0.23978925, y: 1.861574}
- {x: 0.33185518, y: 2.0083904}
- {x: 0.43139812, y: 2.1762547}
- {x: 0.53952074, y: 2.3695562}
- {x: 0.6575622, y: 2.5939138}
- {x: 0.7871677, y: 2.8566267}
- {x: 0.93038195, y: 3.1673388}
- {x: 1.0897847, y: 3.5390525}
- {x: 1.2686841, y: 3.9897263}
- {x: 1.4714115, y: 4.544919}
- {x: 1.7037815, y: 5.2423906}
- {x: 1.9738544, y: 6.140622}
- {x: 2.2932806, y: 7.335897}
- {x: 2.679871, y: 8.999949}
- {x: 3.1630776, y: 11.474433}
- {x: 3.797516, y: 15.554795}
- {x: 4.7049003, y: 23.627026}
- {x: 6.2721014, y: 47.62654}
- {x: 0.03667902, y: 1.5654991}
- {x: 0.11374626, y: 1.6734134}
- {x: 0.19626758, y: 1.7949444}
- {x: 0.28494877, y: 1.9325867}
- {x: 0.38062802, y: 2.0894418}
- {x: 0.48430943, y: 2.2694077}
- {x: 0.59720695, y: 2.4774427}
- {x: 0.72080237, y: 2.7199378}
- {x: 0.8569269, y: 3.005264}
- {x: 1.007873, y: 3.3445888}
- {x: 1.1765549, y: 3.7531407}
- {x: 1.3667475, y: 4.252257}
- {x: 1.5834517, y: 4.872841}
- {x: 1.8334827, y: 5.6615734}
- {x: 2.126473, y: 6.692844}
- {x: 2.4767098, y: 8.093767}
- {x: 2.9068332, y: 10.102725}
- {x: 3.4562516, y: 13.228675}
- {x: 4.2041187, y: 18.793621}
- {x: 5.3538504, y: 31.646347}
- {x: 7.84603, y: 95.44374}
scatterDistance1: {r: 0.3, g: 0.2, b: 0.2, a: 0}
scatterDistance2: {r: 0.6, g: 0.2, b: 0.2, a: 0}
lerpWeight: 0.5

84
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs


public int numProfiles; // Excluding the neutral profile
public SubsurfaceScatteringProfile[] profiles;
// Below are the cached values.
[NonSerialized] public uint texturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
[NonSerialized] public uint transmissionFlags; // 2 bit/profile; 0 = inf. thick, 1 = thin, 2 = regular
[NonSerialized] public int texturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
[NonSerialized] public int transmissionFlags; // 2 bit/profile; 0 = inf. thick, 1 = thin, 2 = regular
[NonSerialized] public float[] worldScales; // Size of the world unit in meters
[NonSerialized] public Vector4[] worldScales; // Size of the world unit in meters (only the X component is used)
[NonSerialized] public float[] filterKernelsNearField; // 0 = radius, 1 = reciprocal of the PDF
[NonSerialized] public float[] filterKernelsFarField; // 0 = radius, 1 = reciprocal of the PDF
[NonSerialized] public Vector4[] filterKernels; // XY = near field, ZW = far field; 0 = radius, 1 = reciprocal of the PDF
// Old SSS Model >>>
public bool useDisneySSS;
[NonSerialized] public Vector4[] halfRcpWeightedVariances;

worldScales = null;
shapeParams = null;
transmissionTints = null;
filterKernelsNearField = null;
filterKernelsFarField = null;
filterKernels = null;
// Old SSS Model >>>
useDisneySSS = true;
halfRcpWeightedVariances = null;

if (worldScales == null || worldScales.Length != SssConstants.SSS_N_PROFILES)
{
worldScales = new float[SssConstants.SSS_N_PROFILES];
worldScales = new Vector4[SssConstants.SSS_N_PROFILES];
}
if (shapeParams == null || shapeParams.Length != SssConstants.SSS_N_PROFILES)

transmissionTints = new Vector4[SssConstants.SSS_N_PROFILES];
}
const int filterKernelsNearFieldLen = 2 * SssConstants.SSS_N_PROFILES * SssConstants.SSS_N_SAMPLES_NEAR_FIELD;
if (filterKernelsNearField == null || filterKernelsNearField.Length != filterKernelsNearFieldLen)
{
filterKernelsNearField = new float[filterKernelsNearFieldLen];
}
const int filterKernelsFarFieldLen = 2 * SssConstants.SSS_N_PROFILES * SssConstants.SSS_N_SAMPLES_FAR_FIELD;
if (filterKernelsFarField == null || filterKernelsFarField.Length != filterKernelsFarFieldLen)
const int filterKernelsNearFieldLen = SssConstants.SSS_N_PROFILES * SssConstants.SSS_N_SAMPLES_NEAR_FIELD;
if (filterKernels == null || filterKernels.Length != filterKernelsNearFieldLen)
filterKernelsFarField = new float[filterKernelsFarFieldLen];
filterKernels = new Vector4[filterKernelsNearFieldLen];
}
// Old SSS Model >>>

if (i >= numProfiles || profiles[i] == null)
{
// Pink transmission
transmissionFlags |= (uint)1 << i * 2;
transmissionFlags |= 1 << i * 2;
worldScales[i] = 1.0f;
worldScales[i] = Vector4.one;
filterKernelsNearField[2 * (n * i + j) + 0] = 0.0f;
filterKernelsNearField[2 * (n * i + j) + 1] = 1.0f;
}
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_FAR_FIELD; j < n; j++)
{
filterKernelsFarField[2 * (n * i + j) + 0] = 0.0f;
filterKernelsFarField[2 * (n * i + j) + 1] = 1.0f;
filterKernels[n * i + j].x = 0.0f;
filterKernels[n * i + j].y = 1.0f;
filterKernels[n * i + j].z = 0.0f;
filterKernels[n * i + j].w = 1.0f;
}
// Old SSS Model >>>

Debug.Assert(numProfiles < 16, "Transmission flags (32-bit integer) cannot support more than 16 profiles.");
texturingModeFlags |= (uint)profiles[i].texturingMode << i;
transmissionFlags |= (uint)profiles[i].transmissionMode << i * 2;
texturingModeFlags |= (int)profiles[i].texturingMode << i;
transmissionFlags |= (int)profiles[i].transmissionMode << i * 2;
thicknessRemaps[i] = new Vector4(profiles[i].thicknessRemap.x, profiles[i].thicknessRemap.y - profiles[i].thicknessRemap.x, 0.0f, 0.0f);
worldScales[i] = profiles[i].worldScale;
shapeParams[i] = profiles[i].shapeParameter;
shapeParams[i].w = profiles[i].maxRadius;
transmissionTints[i] = profiles[i].transmissionTint;
thicknessRemaps[i] = new Vector4(profiles[i].thicknessRemap.x, profiles[i].thicknessRemap.y - profiles[i].thicknessRemap.x, 0.0f, 0.0f);
worldScales[i] = new Vector4(profiles[i].worldScale, 0, 0, 0);
shapeParams[i] = profiles[i].shapeParameter;
shapeParams[i].w = profiles[i].maxRadius;
transmissionTints[i] = profiles[i].transmissionTint;
filterKernelsNearField[2 * (n * i + j) + 0] = profiles[i].filterKernelNearField[j].x;
filterKernelsNearField[2 * (n * i + j) + 1] = profiles[i].filterKernelNearField[j].y;
}
filterKernels[n * i + j].x = profiles[i].filterKernelNearField[j].x;
filterKernels[n * i + j].y = profiles[i].filterKernelNearField[j].y;
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_FAR_FIELD; j < n; j++)
{
filterKernelsFarField[2 * (n * i + j) + 0] = profiles[i].filterKernelFarField[j].x;
filterKernelsFarField[2 * (n * i + j) + 1] = profiles[i].filterKernelFarField[j].y;
if (j < SssConstants.SSS_N_SAMPLES_FAR_FIELD)
{
filterKernels[n * i + j].z = profiles[i].filterKernelFarField[j].x;
filterKernels[n * i + j].w = profiles[i].filterKernelFarField[j].y;
}
}
// Old SSS Model >>>

{
int i = SssConstants.SSS_NEUTRAL_PROFILE_ID;
worldScales[i] = 1.0f;
worldScales[i] = Vector4.one;
filterKernelsNearField[2 * (n * i + j) + 0] = 0.0f;
filterKernelsNearField[2 * (n * i + j) + 1] = 1.0f;
}
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_FAR_FIELD; j < n; j++)
{
filterKernelsFarField[2 * (n * i + j) + 0] = 0.0f;
filterKernelsFarField[2 * (n * i + j) + 1] = 1.0f;
filterKernels[n * i + j].x = 0.0f;
filterKernels[n * i + j].y = 1.0f;
filterKernels[n * i + j].z = 0.0f;
filterKernels[n * i + j].w = 1.0f;
}
// Old SSS Model >>>

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/RenderPipelineResources/HDRenderPipelineResources.asset


deferredShader: {fileID: 4800000, guid: 00dd221e34a6ab349a1196b0f2fab693, type: 3}
screenSpaceAmbientOcclusionShader: {fileID: 4800000, guid: cf0db7f5267ad944dbf4326b7102c9ca,
type: 3}
subsurfaceScatteringCS: {fileID: 7200000, guid: b06a7993621def248addd55d0fe931b1,
type: 3}
clearDispatchIndirectShader: {fileID: 7200000, guid: fc1f553acb80a6446a32d33e403d0656,
type: 3}
buildDispatchIndirectShader: {fileID: 7200000, guid: 4eb1b418be7044c40bb5200496c50f14,

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/RenderPipelineResources/RenderPipelineResources.cs


instance.deferredShader = UnityEditor.AssetDatabase.LoadAssetAtPath<Shader>("Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Deferred.Shader");
instance.screenSpaceAmbientOcclusionShader = UnityEditor.AssetDatabase.LoadAssetAtPath<Shader>("Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/AmbientOcclusion/ScreenSpaceAmbientOcclusion.Shader");
instance.subsurfaceScatteringCS = UnityEditor.AssetDatabase.LoadAssetAtPath<ComputeShader>("Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.compute");
instance.clearDispatchIndirectShader = UnityEditor.AssetDatabase.LoadAssetAtPath<ComputeShader>("Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/cleardispatchindirect.compute");
instance.buildDispatchIndirectShader = UnityEditor.AssetDatabase.LoadAssetAtPath<ComputeShader>("Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/builddispatchindirect.compute");

// Lighting resources
public Shader deferredShader;
public Shader screenSpaceAmbientOcclusionShader;
public ComputeShader subsurfaceScatteringCS;
// Lighting tile pass resources
public ComputeShader clearDispatchIndirectShader;

1
Assets/ScriptableRenderPipeline/ShaderLibrary/API/D3D11.hlsl


#define TEXTURECUBE(textureName) TextureCube textureName
#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName
#define TEXTURE3D(textureName) Texture3D textureName
#define RW_TEXTURE2D(type, textureName) RWTexture2D<type> textureName
#define SAMPLER2D(samplerName) SamplerState samplerName
#define SAMPLERCUBE(samplerName) SamplerState samplerName

1
Assets/ScriptableRenderPipeline/ShaderLibrary/API/Metal.hlsl


#define TEXTURECUBE(textureName) TextureCube textureName
#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName
#define TEXTURE3D(textureName) Texture3D textureName
#define RW_TEXTURE2D(type, textureName) RWTexture2D<type> textureName
#define SAMPLER2D(samplerName) SamplerState samplerName
#define SAMPLERCUBE(samplerName) SamplerState samplerName

1
Assets/ScriptableRenderPipeline/ShaderLibrary/API/PSSL.hlsl


#define TEXTURECUBE(textureName) TextureCube textureName
#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName
#define TEXTURE3D(textureName) Texture3D textureName
#define RW_TEXTURE2D(type, textureName) RW_Texture2D<type> textureName
#define SAMPLER2D(samplerName) SamplerState samplerName
#define SAMPLERCUBE(samplerName) SamplerState samplerName

1
Assets/ScriptableRenderPipeline/ShaderLibrary/Common.hlsl


#define INV_FOUR_PI 0.07957747155
#define HALF_PI 1.57079632679
#define INV_HALF_PI 0.636619772367
#define INFINITY asfloat(0x7F800000)
#define FLT_EPSILON 1.192092896e-07 // Smallest positive number, such that 1.0 + FLT_EPSILON != 1.0
#define FLT_MIN 1.175494351e-38 // Minimum representable positive floating-point number

2
Assets/TestScenes/HDTest/GraphicTest/SSS/Materials/SSSHead.mat


- _SrcBlend: 1
- _StencilRef: 1
- _Stiffness: 1
- _SubsurfaceProfile: 0
- _SubsurfaceProfile: 4
- _SubsurfaceRadius: 1
- _SurfaceType: 0
- _TexWorldScale: 1

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


// ===================== Performs integration of the Disney BSSRDF over a disk =====================
//--------------------------------------------------------------------------------------------------
// Definitions
//--------------------------------------------------------------------------------------------------
// #pragma enable_d3d11_debug_symbols
// Tweak parameters.
#define SSS_BILATERAL_FILTER 1
#define SSS_USE_LDS_CACHE 1
#define SSS_ENABLE_NEAR_FIELD 0
#define SSS_SAMPLE_TEST_HTILE 0
#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
#define MILLIMETERS_PER_METER 1000
#define CENTIMETERS_PER_METER 100
#define GROUP_SIZE_1D 16
#define GROUP_SIZE_2D (GROUP_SIZE_1D * GROUP_SIZE_1D)
#define TEXTURE_CACHE_BORDER 2
#define TEXTURE_CACHE_SIZE_1D (GROUP_SIZE_1D + 2 * TEXTURE_CACHE_BORDER)
//--------------------------------------------------------------------------------------------------
// Included headers
//--------------------------------------------------------------------------------------------------
#include "../../../../ShaderLibrary/Common.hlsl"
#include "../../../../ShaderLibrary/SpaceFillingCurves.hlsl"
#include "../../../ShaderVariables.hlsl"
#define UNITY_MATERIAL_LIT
#include "../../../Material/Material.hlsl"
#include "../../../Lighting/LightDefinition.cs.hlsl"
//--------------------------------------------------------------------------------------------------
// Inputs & outputs
//--------------------------------------------------------------------------------------------------
float4 _WorldScales[SSS_N_PROFILES]; // Size of the world unit in meters (only the X component is used)
float4 _FilterKernels[SSS_N_PROFILES][SSS_N_SAMPLES_NEAR_FIELD]; // XY = near field, ZW = far field; 0 = radius, 1 = reciprocal of the PDF
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
// Contains the HDR color for non-SSS materials.
// In case of SSS, it only contains the specular lighting, which we additively blend with the SSS lighting.
RW_TEXTURE2D(float4, _CameraColorTexture);
//--------------------------------------------------------------------------------------------------
// Implementation
//--------------------------------------------------------------------------------------------------
// 6656 bytes used. It appears that the reserved LDS space must be a multiple of 512 bytes.
#if SSS_USE_LDS_CACHE
groupshared float4 textureCache[TEXTURE_CACHE_SIZE_1D * TEXTURE_CACHE_SIZE_1D]; // {irradiance, linearDepth}
#endif
groupshared bool processGroup;
bool StencilTest(int2 pixelCoord, float stencilRef)
{
bool passedStencilTest;
#if SSS_SAMPLE_TEST_HTILE
int2 tileCoord = pixelCoord >> 3; // Divide by 8
// Perform the stencil test (reject at the tile rate).
passedStencilTest = stencilRef == LOAD_TEXTURE2D(_HTile, tileCoord).r;
[branch] if (passedStencilTest)
#else
// It is extremely uncommon for individual samples to fail the HTile test.
// Unfortunately, our copy of HTile does not allow to accept at the tile rate.
// Therefore, we choose not to perform the HiS test here.
#endif
{
// 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 = stencilRef == LOAD_TEXTURE2D(_StencilTexture, pixelCoord).r;
}
return passedStencilTest;
}
#if SSS_USE_LDS_CACHE
float4 LoadSampleFromCacheMemory(int2 cacheCoord)
{
return textureCache[Mad24(TEXTURE_CACHE_SIZE_1D, cacheCoord.y, cacheCoord.x)];
}
#endif
float4 LoadSampleFromVideoMemory(int2 pixelCoord)
{
float3 irradiance = LOAD_TEXTURE2D(_IrradianceSource, pixelCoord).rgb;
float depth = LOAD_TEXTURE2D(_DepthTexture, pixelCoord).r;
return float4(irradiance, LinearEyeDepth(depth, _ZBufferParams));
}
// Returns {irradiance, linearDepth}.
float4 LoadSample(int2 pixelCoord, int2 cacheAnchor)
{
int2 cacheCoord = pixelCoord - cacheAnchor;
bool isInCache = max((uint)cacheCoord.x, (uint)cacheCoord.y) < TEXTURE_CACHE_SIZE_1D;
#if SSS_USE_LDS_CACHE
[branch] if (isInCache)
{
return LoadSampleFromCacheMemory(cacheCoord);
}
else
#endif
{
float stencilRef = STENCILLIGHTINGUSAGE_SPLIT_LIGHTING;
[branch] if (StencilTest(pixelCoord, stencilRef))
{
return LoadSampleFromVideoMemory(pixelCoord);
}
else
{
return float4(0, 0, 0, 0);
}
}
}
// 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(xy^2 + z^2).
// Rescaling of the PDF is handled by 'totalWeight'.
float3 ComputeBilateralWeight(float xy2, float z, float mmPerUnit, float3 S, float rcpPdf)
{
#if (SSS_BILATERAL_FILTER == 0)
z = 0;
#endif
#if SSS_USE_TANGENT_PLANE
// Both 'xy2' and 'z' require conversion to millimeters.
float r = sqrt(xy2 + z * z) * mmPerUnit;
#else
// Only 'z' requires conversion to millimeters.
float r = sqrt(xy2 + (z * mmPerUnit) * (z * mmPerUnit));
#endif
#if SSS_CLAMP_ARTIFACT
return saturate(KernelValCircle(r, S) * rcpPdf);
#else
return KernelValCircle(r, S) * rcpPdf;
#endif
}
void EvaluateSample(uint i, uint n, uint profileID, uint iR, uint iP, float2 centerCoord, int2 cacheAnchor,
float3 shapeParam, float3 centerPosVS, float mmPerUnit, float2 pixelsPerMm,
float3 tangentX, float3 tangentY, float4x4 projMatrix,
inout float3 totalIrradiance, inout float3 totalWeight)
{
float r = _FilterKernels[profileID][i][iR];
// The relative sample position is known at the compile time.
float phi = SampleDiskFibonacci(i, n).y;
float2 vec = r * float2(cos(phi), sin(phi));
// Compute the screen-space position and the squared distance (in mm) in the image plane.
int2 position; float xy2;
#if SSS_USE_TANGENT_PLANE
float3 relPosVS = vec.x * tangentX + vec.y * tangentY;
float3 positionVS = centerPosVS + relPosVS;
float4 positionCS = mul(projMatrix, float4(positionVS, 1));
float2 positionSS = ComputeScreenSpacePosition(positionCS);
position = (int2)(positionSS * _ScreenSize.xy);
xy2 = dot(relPosVS.xy, relPosVS.xy);
#else
position = (int2)(centerCoord + vec * pixelsPerMm);
xy2 = r * r;
#endif
float4 textureSample = LoadSample(position, cacheAnchor);
float3 irradiance = textureSample.rgb;
float linearDepth = textureSample.a;
// Check the results of the stencil test.
if (linearDepth > 0)
{
// Apply bilateral weighting.
float z = linearDepth - centerPosVS.z;
float p = _FilterKernels[profileID][i][iP];
float3 w = ComputeBilateralWeight(xy2, z, mmPerUnit, shapeParam, p);
totalIrradiance += w * irradiance;
totalWeight += w;
}
}
#pragma kernel SubsurfaceScattering
[numthreads(GROUP_SIZE_2D, 1, 1)]
void SubsurfaceScattering(uint2 groupId : SV_GroupID,
uint groupThreadId : SV_GroupThreadID)
{
// Note: any factor of 64 is a suitable wave size for our algorithm.
uint waveIndex = groupThreadId / 64;
uint laneIndex = groupThreadId % 64;
uint quadIndex = laneIndex / 4;
// Arrange threads in the Morton order to optimally match the memory layout of GCN tiles.
uint mortonCode = groupThreadId;
uint2 localCoord = DecodeMorton2D(mortonCode);
uint2 tileAnchor = groupId * GROUP_SIZE_1D;
uint2 pixelCoord = tileAnchor + localCoord;
int2 cacheAnchor = (int2)tileAnchor - TEXTURE_CACHE_BORDER;
uint2 cacheCoord = localCoord + TEXTURE_CACHE_BORDER;
float stencilRef = STENCILLIGHTINGUSAGE_SPLIT_LIGHTING;
[branch] if (groupThreadId == 0)
{
// Check whether the thread group needs to perform any work.
float s00 = LOAD_TEXTURE2D(_HTile, 2 * groupId + uint2(0, 0)).r;
float s10 = LOAD_TEXTURE2D(_HTile, 2 * groupId + uint2(1, 0)).r;
float s01 = LOAD_TEXTURE2D(_HTile, 2 * groupId + uint2(0, 1)).r;
float s11 = LOAD_TEXTURE2D(_HTile, 2 * groupId + uint2(1, 1)).r;
// Perform the stencil test (reject at the tile rate).
processGroup = (stencilRef == s00 || stencilRef == s10 || stencilRef == s01 || stencilRef == s11);
}
// Wait for the LDS.
GroupMemoryBarrierWithGroupSync();
[branch] if (!processGroup) { return; }
float3 centerIrradiance = 0;
float centerDepth = 0;
float4 cachedValue = float4(0, 0, 0, 0);
bool passedStencilTest = StencilTest((int2)pixelCoord, stencilRef);
[branch] if (passedStencilTest)
{
centerIrradiance = LOAD_TEXTURE2D(_IrradianceSource, pixelCoord).rgb;
centerDepth = LOAD_TEXTURE2D(_DepthTexture, pixelCoord).r;
cachedValue = float4(centerIrradiance, LinearEyeDepth(centerDepth, _ZBufferParams));
}
#if SSS_USE_LDS_CACHE
// Populate the central region of the LDS cache.
textureCache[Mad24(TEXTURE_CACHE_SIZE_1D, cacheCoord.y, cacheCoord.x)] = cachedValue;
uint numBorderQuadsPerWave = TEXTURE_CACHE_SIZE_1D / 2 - 1;
uint halfCacheWidthInQuads = TEXTURE_CACHE_SIZE_1D / 4;
[branch] if (quadIndex < numBorderQuadsPerWave)
{
// Fetch another texel into the LDS.
uint2 startQuad = halfCacheWidthInQuads * uint2(waveIndex & 1, waveIndex >> 1);
uint2 quadCoord;
// The traversal order is such that the quad's X coordinate is monotonically increasing.
// Note: the compiler can heavily optimize the code below, as the switch is scalar,
// and there are very few unique values due to the symmetry.
switch (waveIndex)
{
case 0:
quadCoord.x = max(0, (int)(quadIndex - (halfCacheWidthInQuads - 1)));
quadCoord.y = max(0, (int)((halfCacheWidthInQuads - 1) - quadIndex));
break;
case 1:
quadCoord.x = min(quadIndex, halfCacheWidthInQuads - 1);
quadCoord.y = max(0, (int)(quadIndex - (halfCacheWidthInQuads - 1)));
break;
case 2:
quadCoord.x = max(0, (int)(quadIndex - (halfCacheWidthInQuads - 1)));
quadCoord.y = min(quadIndex, halfCacheWidthInQuads - 1);
break;
default: // 3
quadCoord.x = min(quadIndex, halfCacheWidthInQuads - 1);
quadCoord.y = min(halfCacheWidthInQuads - 1, 2 * (halfCacheWidthInQuads - 1) - quadIndex);
break;
}
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);
[branch] if (StencilTest(pixelCoord2, stencilRef))
{
cachedValue2 = LoadSampleFromVideoMemory(pixelCoord2);
}
// Populate the border region of the LDS cache.
textureCache[Mad24(TEXTURE_CACHE_SIZE_1D, cacheCoord2.y, cacheCoord2.x)] = cachedValue2;
}
// Wait for the LDS.
GroupMemoryBarrierWithGroupSync();
#endif
bool isOffScreen = pixelCoord.x >= (uint)_ScreenSize.x || pixelCoord.y >= (uint)_ScreenSize.y;
[branch] if (!passedStencilTest || isOffScreen) { return; }
PositionInputs posInput = GetPositionInput(pixelCoord, _ScreenSize.zw);
float3 unused;
// The result of the stencil test allows us to statically determine the material type (SSS).
BSDFData bsdfData;
FETCH_GBUFFER(gbuffer, _GBufferTexture, pixelCoord);
DECODE_FROM_GBUFFER(gbuffer, MATERIALFEATUREFLAGS_LIT_SSS, bsdfData, unused);
int profileID = bsdfData.subsurfaceProfile;
float distScale = bsdfData.subsurfaceRadius;
float3 shapeParam = _ShapeParams[profileID].rgb;
float maxDistance = _ShapeParams[profileID].a;
// Reconstruct the view-space position corresponding to the central sample.
float2 centerPosSS = posInput.positionSS;
float2 cornerPosSS = centerPosSS + 0.5 * _ScreenSize.zw;
float3 centerPosVS = ComputeViewSpacePosition(centerPosSS, centerDepth, _InvProjMatrix);
float3 cornerPosVS = ComputeViewSpacePosition(cornerPosSS, centerDepth, _InvProjMatrix);
// 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
_CameraColorTexture[pixelCoord] = float4(0, 0, 1, 1);
#else
_CameraColorTexture[pixelCoord] += float4(bsdfData.diffuseColor * centerIrradiance, 1);
#endif
return;
}
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)
{
_CameraColorTexture[pixelCoord] = float4(1, 1, 1, 1);
return;
}
#endif
// Use more samples for SS regions larger than 5x5 pixels (rotated by 45 degrees).
bool useNearFieldKernel = SSS_ENABLE_NEAR_FIELD && maxDistInPixels > SSS_LOD_THRESHOLD;
#if SSS_DEBUG_LOD
_CameraColorTexture[pixelCoord] = useNearFieldKernel ? float4(1, 0, 0, 1) : float4(0.5, 0.5, 0, 1);
return;
#endif
// Compute the indices used to access the individual components of the float4 of the kernel.
uint iR = useNearFieldKernel ? 0 : 2; // radius
uint iP = useNearFieldKernel ? 1 : 3; // rcp(pdf)
float centerRadius = _FilterKernels[profileID][0][iR];
float centerRcpPdf = _FilterKernels[profileID][0][iP];
float3 centerWeight = KernelValCircle(centerRadius, shapeParam) * centerRcpPdf;
// Accumulate filtered irradiance and bilateral weights (for renormalization).
float3 totalIrradiance = centerWeight * centerIrradiance;
float3 totalWeight = centerWeight;
int i, n; // Declare once to avoid the warning from the Unity shader compiler.
[unroll]
for (i = 1, n = SSS_N_SAMPLES_FAR_FIELD; i < n; i++)
{
// Integrate over the image or tangent plane in the view space.
EvaluateSample(i, n, profileID, iR, iP, pixelCoord + 0.5, cacheAnchor,
shapeParam, centerPosVS, mmPerUnit, pixelsPerMm,
tangentX, tangentY, projMatrix,
totalIrradiance, totalWeight);
}
[branch] if (!useNearFieldKernel)
{
_CameraColorTexture[pixelCoord] += float4(bsdfData.diffuseColor * totalIrradiance / totalWeight, 1);
return;
}
[unroll]
for (i = SSS_N_SAMPLES_FAR_FIELD, n = SSS_N_SAMPLES_NEAR_FIELD; i < n; i++)
{
// Integrate over the image or tangent plane in the view space.
EvaluateSample(i, n, profileID, iR, iP, pixelCoord + 0.5, cacheAnchor,
shapeParam, centerPosVS, mmPerUnit, pixelsPerMm,
tangentX, tangentY, projMatrix,
totalIrradiance, totalWeight);
}
_CameraColorTexture[pixelCoord] += float4(bsdfData.diffuseColor * totalIrradiance / totalWeight, 1);
}

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


fileFormatVersion: 2
guid: b06a7993621def248addd55d0fe931b1
timeCreated: 1500310187
licenseType: Pro
ComputeShaderImporter:
externalObjects: {}
currentAPIMask: 4
userData:
assetBundleName:
assetBundleVariant:

72
Assets/ScriptableRenderPipeline/ShaderLibrary/SpaceFillingCurves.hlsl


#ifndef UNITY_SPACE_FILLING_CURVES_INCLUDED
#define UNITY_SPACE_FILLING_CURVES_INCLUDED
// "Insert" a 0 bit after each of the 16 low bits of x.
// Ref: https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
uint Part1By1(uint x)
{
x &= 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
x = (x ^ (x << 8)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
x = (x ^ (x << 4)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
x = (x ^ (x << 2)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
x = (x ^ (x << 1)) & 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
return x;
}
// "Insert" two 0 bits after each of the 10 low bits of x/
// Ref: https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
uint Part1By2(uint x)
{
x &= 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210
x = (x ^ (x << 16)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210
x = (x ^ (x << 8)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210
x = (x ^ (x << 4)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10
x = (x ^ (x << 2)) & 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
return x;
}
// Inverse of Part1By1 - "delete" all odd-indexed bits/
// Ref: https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
uint Compact1By1(uint x)
{
x &= 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
x = (x ^ (x >> 1)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
x = (x ^ (x >> 2)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
x = (x ^ (x >> 4)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
x = (x ^ (x >> 8)) & 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
return x;
}
// Inverse of Part1By2 - "delete" all bits not at positions divisible by 3/
// Ref: https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
uint Compact1By2(uint x)
{
x &= 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
x = (x ^ (x >> 2)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10
x = (x ^ (x >> 4)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210
x = (x ^ (x >> 8)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210
x = (x ^ (x >> 16)) & 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210
return x;
}
uint EncodeMorton2D(uint2 coord)
{
return (Part1By1(coord.y) << 1) + Part1By1(coord.x);
}
uint EncodeMorton3D(uint3 coord)
{
return (Part1By2(coord.z) << 2) + (Part1By2(coord.y) << 1) + Part1By2(coord.x);
}
uint2 DecodeMorton2D(uint code)
{
return uint2(Compact1By1(code >> 0), Compact1By1(code >> 1));
}
uint3 DecodeMorton3D(uint code)
{
return uint3(Compact1By2(code >> 0), Compact1By2(code >> 1), Compact1By2(code >> 2));
}
#endif // UNITY_SPACE_FILLING_CURVES_INCLUDED

10
Assets/ScriptableRenderPipeline/ShaderLibrary/SpaceFillingCurves.hlsl.meta


fileFormatVersion: 2
guid: 063144fddd2c1be41b9d09dec6314fc7
timeCreated: 1500391830
licenseType: Pro
ShaderImporter:
externalObjects: {}
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

116
Assets/TestScenes/HDTest/GraphicTest/SSS/ProfilingSkinSSSProfile.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a6e7465350bf0d248b4799d98e18cd24, type: 3}
m_Name: ProfilingSkinSSSProfile
m_EditorClassIdentifier:
scatteringDistance: {r: 0.758, g: 0.321, b: 0.201, a: 1}
transmissionTint: {r: 0.7568628, g: 0.32156864, b: 0.20000002, a: 1}
texturingMode: 0
transmissionMode: 0
thicknessRemap: {x: 0, y: 12.031147}
worldScale: 1
settingsIndex: 4
m_ShapeParam: {x: 1.3192612, y: 3.1152647, z: 4.9751244}
m_MaxRadius: 10.03481
m_FilterKernelNearField:
- {x: 0.013865918, y: 1.5345725}
- {x: 0.04211352, y: 1.5729346}
- {x: 0.07107388, y: 1.6130018}
- {x: 0.100779116, y: 1.6548817}
- {x: 0.13126306, y: 1.6986896}
- {x: 0.16256203, y: 1.7445502}
- {x: 0.1947145, y: 1.7925992}
- {x: 0.22776169, y: 1.8429838}
- {x: 0.26174724, y: 1.8958628}
- {x: 0.29671827, y: 1.9514104}
- {x: 0.33272493, y: 2.0098157}
- {x: 0.369821, y: 2.0712852}
- {x: 0.40806437, y: 2.1360447}
- {x: 0.44751683, y: 2.2043417}
- {x: 0.48824534, y: 2.276447}
- {x: 0.5303216, y: 2.3526597}
- {x: 0.5738235, y: 2.433308}
- {x: 0.61883456, y: 2.5187542}
- {x: 0.665446, y: 2.609401}
- {x: 0.713756, y: 2.7056925}
- {x: 0.763872, y: 2.808125}
- {x: 0.8159103, y: 2.91725}
- {x: 0.8699981, y: 3.0336854}
- {x: 0.9262747, y: 3.1581244}
- {x: 0.98489225, y: 3.2913465}
- {x: 1.0460185, y: 3.434234}
- {x: 1.1098381, y: 3.5877857}
- {x: 1.1765549, y: 3.7531407}
- {x: 1.2463952, y: 3.9316032}
- {x: 1.319611, y: 4.124672}
- {x: 1.3964823, y: 4.3340797}
- {x: 1.4773248, y: 4.561845}
- {x: 1.5624928, y: 4.810328}
- {x: 1.6523882, y: 5.082317}
- {x: 1.747467, y: 5.381122}
- {x: 1.8482518, y: 5.710715}
- {x: 1.9553448, y: 6.0759025}
- {x: 2.069445, y: 6.482568}
- {x: 2.1913698, y: 6.9379897}
- {x: 2.3220856, y: 7.4513016}
- {x: 2.4627466, y: 8.0341215}
- {x: 2.614747, y: 8.701484}
- {x: 2.7797952, y: 9.473195}
- {x: 2.9600194, y: 10.375936}
- {x: 3.1581159, y: 11.446505}
- {x: 3.3775842, y: 12.737201}
- {x: 3.6230793, y: 14.324919}
- {x: 3.9009922, y: 16.327562}
- {x: 4.220452, y: 18.935623}
- {x: 4.5951686, y: 22.478209}
- {x: 5.047148, y: 27.57712}
- {x: 5.615129, y: 35.564823}
- {x: 6.3776174, y: 49.90625}
- {x: 7.5374603, y: 83.30668}
- {x: 10.03481, y: 250.11497}
m_FilterKernelFarField:
- {x: 0.03667902, y: 1.5654991}
- {x: 0.11374626, y: 1.6734134}
- {x: 0.19626758, y: 1.7949444}
- {x: 0.28494877, y: 1.9325867}
- {x: 0.38062802, y: 2.0894418}
- {x: 0.48430943, y: 2.2694077}
- {x: 0.59720695, y: 2.4774427}
- {x: 0.72080237, y: 2.7199378}
- {x: 0.8569269, y: 3.005264}
- {x: 1.007873, y: 3.3445888}
- {x: 1.1765549, y: 3.7531407}
- {x: 1.3667475, y: 4.252257}
- {x: 1.5834517, y: 4.872841}
- {x: 1.8334827, y: 5.6615734}
- {x: 2.126473, y: 6.692844}
- {x: 2.4767098, y: 8.093767}
- {x: 2.9068332, y: 10.102725}
- {x: 3.4562516, y: 13.228675}
- {x: 4.2041187, y: 18.793621}
- {x: 5.3538504, y: 31.646347}
- {x: 7.84603, y: 95.44374}
scatterDistance1: {r: 0.3, g: 0.2, b: 0.2, a: 0}
scatterDistance2: {r: 0.6, g: 0.2, b: 0.2, a: 0}
lerpWeight: 0.5
m_HalfRcpWeightedVariances: {x: 2.4691355, y: 12.5, z: 12.5, w: 2.4691355}
m_FilterKernelBasic:
- {x: 0.09090909, y: 0.21162307, z: 0.21162307, w: -0.000000048879357}
- {x: 0.09090909, y: 0.18990478, z: 0.18990478, w: -0.11381993}
- {x: 0.09090909, y: 0.13233659, z: 0.13233659, w: -0.23580086}
- {x: 0.09090909, y: 0.061445467, z: 0.061445467, w: -0.37865555}
- {x: 0.09090909, y: 0.010501689, z: 0.010501689, w: -0.57677805}
- {x: 0.09090909, y: 2.9458339e-10, z: 2.9458339e-10, w: -1.3907351}
- {x: 0.09090909, y: 0.18990476, z: 0.18990476, w: 0.11382001}
- {x: 0.09090909, y: 0.13233659, z: 0.13233659, w: 0.23580086}
- {x: 0.09090909, y: 0.061445467, z: 0.061445467, w: 0.37865555}
- {x: 0.09090909, y: 0.010501689, z: 0.010501689, w: 0.57677805}
- {x: 0.09090909, y: 2.9456845e-10, z: 2.9456845e-10, w: 1.3907368}

9
Assets/TestScenes/HDTest/GraphicTest/SSS/ProfilingSkinSSSProfile.asset.meta


fileFormatVersion: 2
guid: aa5f2cc1c22cad043a617e9e9548b1b9
timeCreated: 1493291209
licenseType: Pro
NativeFormatImporter:
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

1001
Assets/TestScenes/HDTest/GraphicTest/SSS/Test - SSS model .prefab
文件差异内容过多而无法显示
查看文件

10
Assets/TestScenes/HDTest/GraphicTest/SSS/Test - SSS model .prefab.meta


fileFormatVersion: 2
guid: ef1a9eb2ee53a8f44bf5543cfe520dc7
timeCreated: 1500646713
licenseType: Pro
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 100100000
userData:
assetBundleName:
assetBundleVariant:

1001
Assets/TestScenes/HDTest/SSSProfiling.unity
文件差异内容过多而无法显示
查看文件

9
Assets/TestScenes/HDTest/SSSProfiling.unity.meta


fileFormatVersion: 2
guid: 3ae49a004ada4ea4486096f6ed8c5d46
timeCreated: 1500647185
licenseType: Pro
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

/Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader.meta → /Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.shader.meta

/Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader → /Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.shader

正在加载...
取消
保存