浏览代码

Merge pull request #307 from EvgeniiG/upstream

Implement tangent plane SSS
/RenderPassXR_Sandbox
GitHub 8 年前
当前提交
2238da85
共有 2 个文件被更改,包括 101 次插入41 次删除
  1. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  2. 134
      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);

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


#pragma multi_compile _ SSS_FILTER_HORIZONTAL_AND_COMBINE
// <<< Old SSS Model
// Tweak parameters for the Disney SSS below.
#define SSS_BILATERAL_FILTER 1
#define SSS_USE_TANGENT_PLANE 0
#define SSS_CLAMP_COLOR_BLEED 0
#define SSS_DEBUG 0
// Do not modify these.
#define SSS_BILATERAL 1
#define SSS_DEBUG 0
#ifdef SSS_MODEL_BASIC
#define RBG_BILATERAL_WEIGHTS 0
#endif
//-------------------------------------------------------------------------------------
// Include

//-------------------------------------------------------------------------------------
// Inputs & outputs
//-------------------------------------------------------------------------------------
float4x4 _ViewMatrix, _ProjMatrix; // TEMP: make these global
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

return /* 0.25 * */ S * (expOneThird + expOneThird * expOneThird * expOneThird);
}
// Computes F(x)/P(x), s.t. x = sqrt(r^2 + t^2).
float3 ComputeBilateralWeight(float3 S, float r, float t, float rcpPdf)
// 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 == 0)
t = 0;
#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));
float3 val = KernelValCircle(sqrt(r * r + t * t), S);
// Rescaling of the PDF is handled by 'totalWeight'.
return val * rcpPdf;
#if SSS_CLAMP_COLOR_BLEED
return saturate(KernelValCircle(r, S) * rcpPdf);
#else
return KernelValCircle(r, S) * rcpPdf;
#endif
#define SSS_ITER(i, n, kernel, profileID, shapeParam, centerPosUnSS, centerDepthVS, \
millimPerUnit, pixelsPerMm, totalIrradiance, totalWeight) \
#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. */ \

float2 position = centerPosUnSS + vec * pixelsPerMm; \
float3 irradiance = LOAD_TEXTURE2D(_IrradianceSource, position).rgb; \
/* 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 = positionCS.xy * (rcp(positionCS.w) * 0.5) + 0.5; \
\
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] \

float z = LOAD_TEXTURE2D(_MainDepthTexture, position).r; \
float d = LinearEyeDepth(z, _ZBufferParams); \
float t = millimPerUnit * d - (millimPerUnit * centerDepthVS); \
float t = d - centerPosVS.z; \
float3 w = ComputeBilateralWeight(shapeParam, r, t, p); \
float3 w = ComputeBilateralWeight(dXY2, t, mmPerUnit, shapeParam, p); \
\
totalIrradiance += w * irradiance; \
totalWeight += w; \

} \
}
#define SSS_LOOP(n, kernel, profileID, shapeParam, centerPosUnSS, centerDepthVS, \
millimPerUnit, pixelsPerMm, totalIrradiance, totalWeight) \
#define SSS_LOOP(n, kernel, profileID, shapeParam, centerPosUnSS, centerPosVS, \
useTangentPlane, tangentX, tangentY, mmPerUnit, pixelsPerMm, \
totalIrradiance, totalWeight) \
{ \
float centerRcpPdf = kernel[profileID][0][1]; \
float3 centerWeight = KernelValCircle(0, shapeParam) * centerRcpPdf; \

\
/* Perform integration over the screen-aligned plane in the view space. */ \
/* TODO: it would be more accurate to use the tangent plane instead. */ \
/* Integrate over the screen-aligned or tangent plane in the view space. */ \
SSS_ITER(i, n, kernel, profileID, shapeParam, centerPosUnSS, centerDepthVS, \
millimPerUnit, pixelsPerMm, totalIrradiance, totalWeight) \
SSS_ITER(i, n, kernel, profileID, shapeParam, centerPosUnSS, centerPosVS, \
useTangentPlane, tangentX, tangentY, mmPerUnit, pixelsPerMm, \
totalIrradiance, totalWeight) \
} \
}

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);
float metersPerUnit = _WorldScales[profileID] / distScale;
float millimPerUnit = MILLIMETERS_PER_METER * metersPerUnit;
float2 pixelsPerMm = rcp(millimPerUnit * unitsPerPixel);
float mmPerUnit = MILLIMETERS_PER_METER * (_WorldScales[profileID] / distScale);
float unitsPerMm = rcp(mmPerUnit);
// Take the first (central) sample.
// TODO: copy its neighborhood into LDS.
float2 centerPosition = posInput.unPositionSS;
float3 centerIrradiance = LOAD_TEXTURE2D(_IrradianceSource, centerPosition).rgb;
// 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;
// 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]

#endif
}
const bool useTangentPlane = SSS_USE_TANGENT_PLANE != 0;
// 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;
// Accumulate filtered irradiance and bilateral weights (for renormalization).
float3 totalIrradiance, totalWeight;

return float4(0.5, 0.5, 0, 1);
#else
SSS_LOOP(SSS_N_SAMPLES_FAR_FIELD, _FilterKernelsFarField,
profileID, shapeParam, centerPosition, centerPosVS.z,
millimPerUnit, pixelsPerMm, totalIrradiance, totalWeight)
profileID, shapeParam, centerPosition, centerPosVS,
useTangentPlane, tangentX, tangentY, mmPerUnit, pixelsPerMm,
totalIrradiance, totalWeight)
#endif
}
else

#else
SSS_LOOP(SSS_N_SAMPLES_NEAR_FIELD, _FilterKernelsNearField,
profileID, shapeParam, centerPosition, centerPosVS.z,
millimPerUnit, pixelsPerMm, totalIrradiance, totalWeight)
profileID, shapeParam, centerPosition, centerPosVS,
useTangentPlane, tangentX, tangentY, mmPerUnit, pixelsPerMm,
totalIrradiance, totalWeight)
#endif
}
#else

// 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.

[flatten]
if (any(sampleIrradiance))
{
#if SSS_BILATERAL
// Apply bilateral weighting.
// Ref #1: Skin Rendering by Pseudo–Separable Cross Bilateral Filtering.
// Ref #2: Separable SSS, Supplementary Materials, Section E.

sampleWeight *= exp(-zDistance * zDistance * halfRcpVariance);
#endif
totalIrradiance += sampleWeight * sampleIrradiance;
totalWeight += sampleWeight;

正在加载...
取消
保存