浏览代码

Implement world-space tangent plane integration

/RenderPassXR_Sandbox
Evgenii Golubev 8 年前
当前提交
2ecf7c3d
共有 2 个文件被更改,包括 102 次插入8 次删除
  1. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  2. 102
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader

8
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


if (sssSettings.useDisneySSS)
{
cmd.SetGlobalTexture("_IrradianceSource", m_CameraSubsurfaceBufferRT); // Cannot set a RT on a material
// Temp >>>
Matrix4x4 viewMatrix = hdCamera.camera.worldToCameraMatrix;
viewMatrix.SetRow(2, -viewMatrix.GetRow(2)); // Make Z axis point forwards in the view space (left-handed CS)
Matrix4x4 projMatrix = GL.GetGPUProjectionMatrix(hdCamera.camera.projectionMatrix, false);
projMatrix.SetColumn(2, -projMatrix.GetColumn(2)); // Undo the view-space transformation
m_FilterAndCombineSubsurfaceScattering.SetMatrix("_ViewMatrix", viewMatrix);
m_FilterAndCombineSubsurfaceScattering.SetMatrix("_ProjMatrix", projMatrix);
// <<< Temp
m_FilterAndCombineSubsurfaceScattering.SetFloatArray("_WorldScales", sssParameters.worldScales);
m_FilterAndCombineSubsurfaceScattering.SetFloatArray("_FilterKernelsNearField", sssParameters.filterKernelsNearField);
m_FilterAndCombineSubsurfaceScattering.SetFloatArray("_FilterKernelsFarField", sssParameters.filterKernelsFarField);

102
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader


#define SSS_PASS 1
#define SSS_BILATERAL 1
#define SSS_DEBUG 0
#define SSS_USE_TANGENT_PLANE 0
#define MILLIMETERS_PER_METER 1000
#ifdef SSS_MODEL_BASIC
#define CENTIMETERS_PER_METER 100

//-------------------------------------------------------------------------------------
// Inputs & outputs
//-------------------------------------------------------------------------------------
float4x4 _ViewMatrix, _ProjMatrix; // TEMP: make these global
float _WorldScales[SSS_N_PROFILES]; // Size of the world unit in meters
#ifdef SSS_MODEL_DISNEY

float maxDistance = _FilterKernelsBasic[profileID][SSS_BASIC_N_SAMPLES - 1].a;
#endif
// Take the first (central) sample.
// TODO: copy its neighborhood into LDS.
float2 centerPosition = posInput.unPositionSS;
float3 centerIrradiance = LOAD_TEXTURE2D(_IrradianceSource, centerPosition).rgb;
float centerDepth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.unPositionSS).r;
float centerDepth = LOAD_TEXTURE2D(_MainDepthTexture, centerPosition).r;
// 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(millimPerUnit * unitsPerPixel);
#if SSS_USE_TANGENT_PLANE
[branch]
if (distScale == 0)
{
#if SSS_DEBUG
return float4(0, 0, 1, 1);
#else
return float4(bsdfData.diffuseColor * centerIrradiance, 1);
#endif
}
// Take the first (central) sample.
// TODO: copy its neighborhood into LDS.
float2 centerPosition = posInput.unPositionSS;
float3 centerIrradiance = LOAD_TEXTURE2D(_IrradianceSource, centerPosition).rgb;
UpdatePositionInput(centerDepth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
// Compute the disk tangential to the surface.
float3 normalVS = mul((float3x3)_ViewMatrix, bsdfData.normalWS);
float3x3 basisVS = GetLocalFrame(normalVS);
float3 tangentX = basisVS[0] * rcp(millimPerUnit);
float3 tangentY = basisVS[1] * rcp(millimPerUnit);
// Accumulate filtered irradiance and bilateral weights (for renormalization).
float3 totalIrradiance, totalWeight;
{
float centerRcpPdf = _FilterKernelsNearField[profileID][0][1];
float3 centerWeight = KernelValCircle(0, shapeParam) * centerRcpPdf;
totalIrradiance = centerWeight * centerIrradiance;
totalWeight = centerWeight;
[unroll]
for (uint i = 1; i < SSS_N_SAMPLES_NEAR_FIELD; i++)
{
float r = _FilterKernelsNearField[profileID][i][0];
/* The relative sample position is known at compile time. */
float phi = TWO_PI * Fibonacci2d(i, SSS_N_SAMPLES_NEAR_FIELD).y;
float2 vec = r * float2(cos(phi), sin(phi));
float3 relPosVS = vec.x * tangentX + vec.y * tangentY;
float3 positionVS = centerPosVS + relPosVS;
float4 positionCS = mul(_ProjMatrix, float4(positionVS, 1));
float2 positionSS = positionCS.xy * (rcp(positionCS.w) * 0.5) + 0.5;
float2 positionXY = positionSS * _ScreenSize.xy;
float3 irradiance = LOAD_TEXTURE2D(_IrradianceSource, positionXY).rgb;
/* TODO: see if making this a [branch] improves performance. */
[flatten]
if (any(irradiance))
{
/* Apply bilateral weighting. */
float z = LOAD_TEXTURE2D(_MainDepthTexture, positionXY).r;
float d = LinearEyeDepth(z, _ZBufferParams);
float t = d - positionVS.z;
float3 x = millimPerUnit * length(relPosVS + float3(0, 0, t));
float p = _FilterKernelsNearField[profileID][i][1];
#if SSS_BILATERAL
float3 w = KernelValCircle(x, shapeParam) * p;
#else
float3 w = KernelValCircle(r, shapeParam) * p;
#endif
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 */
/*************************************************************************/
}
}
}
#else
// 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(millimPerUnit * unitsPerPixel);
// We perform point sampling. Therefore, we can avoid the cost
// of filtering if we stay within the bounds of the current pixel.

millimPerUnit, pixelsPerMm, totalIrradiance, totalWeight)
#endif
}
#endif
// Compute the view-space dimensions of the pixel as a quad projected onto geometry.
float2 unitsPerPixel = 2 * abs(cornerPosVS.xy - centerPosVS.xy);
float2 pixelsPerCm = rcp(centimPerUnit * unitsPerPixel);
// Compute the filtering direction.

正在加载...
取消
保存