浏览代码

Use an improved (generalized) depth distribution

/main
Evgenii Golubev 7 年前
当前提交
1ef2e80a
共有 7 个文件被更改,包括 85 次插入31 次删除
  1. 34
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl
  2. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  3. 14
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/Resources/VolumetricLighting.compute
  4. 24
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VBuffer.hlsl
  5. 34
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs
  6. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderVariables.hlsl
  7. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/AtmosphericScattering/AtmosphericScattering.hlsl

34
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl


return mul(viewProjMatrix, float4(positionWS, 1.0)).w;
}
// 'z' is the view space Z position (linear depth).
// saturate(z) the output of the function to clamp them to the [0, 1] range.
// d = log2(c * (z - n) + 1) / log2(c * (f - n) + 1)
// = log2(c * (z - n + 1/c)) / log2(c * (f - n) + 1)
// = log2(c) / log2(c * (f - n) + 1) + log2(z - (n - 1/c)) / log2(c * (f - n) + 1)
// = E + F * log2(z - G)
// encodingParams = { E, F, G, 0 }
float EncodeLogarithmicDepthGeneralized(float z, float4 encodingParams)
{
// Use max() to avoid NaNs.
return encodingParams.x + encodingParams.y * log2(max(0, z - encodingParams.z));
}
// 'd' is the logarithmically encoded depth value.
// saturate(d) to clamp the output of the function to the [n, f] range.
// z = 1/c * (pow(c * (f - n) + 1, d) - 1) + n
// = 1/c * pow(c * (f - n) + 1, d) + n - 1/c
// = L * pow(M, d) + N
// decodingParams = { L, M, N, 0 }
// Graph: https://www.desmos.com/calculator/qrtatrlrba
float DecodeLogarithmicDepthGeneralized(float d, float4 decodingParams)
{
// Use abs() to avoid the compiler warning.
return decodingParams.x * pow(abs(decodingParams.y), d) + decodingParams.z;
}
// saturate() the output of the function to clamp them to the [0, 1] range.
// saturate(z) the output of the function to clamp them to the [0, 1] range.
// TODO: plot and modify the distribution to be a little more linear.
// This is an optimized version of EncodeLogarithmicDepthGeneralized() for (c = 2).
// Use max() to avoid NaNs.
return log2(max(0, z * encodingParams.z)) * encodingParams.w;
}

// TODO: plot and modify the distribution to be a little more linear.
// This is an optimized version of DecodeLogarithmicDepthGeneralized() for (c = 2).
// Graph: https://www.desmos.com/calculator/qrtatrlrba
float DecodeLogarithmicDepth(float d, float4 encodingParams)
{
return encodingParams.x * exp2(d * encodingParams.y);

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


public static readonly int _VBufferResolution = Shader.PropertyToID("_VBufferResolution");
public static readonly int _VBufferScaleAndSliceCount = Shader.PropertyToID("_VBufferScaleAndSliceCount");
public static readonly int _VBufferDepthEncodingParams = Shader.PropertyToID("_VBufferDepthEncodingParams");
public static readonly int _VBufferDepthDecodingParams = Shader.PropertyToID("_VBufferDepthDecodingParams");
public static readonly int _VBufferCoordToViewDirWS = Shader.PropertyToID("_VBufferCoordToViewDirWS");
public static readonly int _VBufferDensity = Shader.PropertyToID("_VBufferDensity");
public static readonly int _VBufferLighting = Shader.PropertyToID("_VBufferLighting");

14
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/Resources/VolumetricLighting.compute


void FillVolumetricLightingBuffer(LightLoopContext context, uint featureFlags,
PositionInputs posInput, DualRay ray)
{
float z0 = _VBufferDepthEncodingParams.x; // Start integration from the near plane
float t0 = ray.strataDirInvViewZ * z0; // Convert view space Z to distance along the stratified ray
float de = rcp(VBUFFER_SLICE_COUNT); // Log-encoded distance between slices
float n = _VBufferDepthDecodingParams.x + _VBufferDepthDecodingParams.z;
float z0 = n; // Start integration from the near plane
float t0 = ray.strataDirInvViewZ * z0; // Convert view space Z to distance along the stratified ray
float de = rcp(VBUFFER_SLICE_COUNT); // Log-encoded distance between slices
uint sliceCountHack = max(VBUFFER_SLICE_COUNT, (uint)_VBufferDepthEncodingParams.x); // Prevent unrolling...
uint sliceCountHack = max(VBUFFER_SLICE_COUNT, (uint)_VBufferDepthEncodingParams.w); // Prevent unrolling...
#ifdef LIGHTLOOP_TILE_PASS
// Our voxel is not necessarily completely inside a single light cluster.

for (uint slice = 0; slice < sliceCountHack; slice++)
{
float e1 = slice * de + de; // (slice + 1) / sliceCount
float z1 = DecodeLogarithmicDepth(e1, _VBufferDepthEncodingParams);
float z1 = DecodeLogarithmicDepthGeneralized(e1, _VBufferDepthDecodingParams);
float t1 = ray.strataDirInvViewZ * z1; // Convert view space Z to distance along the stratified ray
float dt = t1 - t0;

float4 reprojValue = SampleVBuffer(TEXTURE3D_PARAM(_VBufferLightingHistory, s_trilinear_clamp_sampler),
false, reprojPosNDC, reprojZ,
_VBufferScaleAndSliceCount,
_VBufferDepthEncodingParams);
_VBufferDepthEncodingParams,
_VBufferDepthDecodingParams);
// Compute the exponential moving average over 'n' frames:
// X = (1 - a) * ValueAtFrame[n] + a * AverageOverPreviousFrames.

24
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VBuffer.hlsl


// which allows us to perform HW interpolation which is linear in the view space.
float ComputeLerpPositionForLogEncoding(float linearDepth, float logEncodedDepth,
float4 VBufferScaleAndSliceCount,
float4 VBufferDepthEncodingParams)
float4 VBufferDepthDecodingParams)
{
float z = linearDepth;
float d = logEncodedDepth;

float s1 = ceil(d * numSlices - 0.5);
float d0 = saturate(s0 * rcpNumSlices + (0.5 * rcpNumSlices));
float d1 = saturate(s1 * rcpNumSlices + (0.5 * rcpNumSlices));
float z0 = DecodeLogarithmicDepth(d0, VBufferDepthEncodingParams);
float z1 = DecodeLogarithmicDepth(d1, VBufferDepthEncodingParams);
float z0 = DecodeLogarithmicDepthGeneralized(d0, VBufferDepthDecodingParams);
float z1 = DecodeLogarithmicDepthGeneralized(d1, VBufferDepthDecodingParams);
// Compute the linear interpolation weight.
float t = saturate((z - z0) / (z1 - z0));

float4 SampleVBuffer(TEXTURE3D_ARGS(VBufferLighting, trilinearSampler), bool clampToEdge,
float2 positionNDC, float linearDepth,
float4 VBufferScaleAndSliceCount,
float4 VBufferDepthEncodingParams)
float4 VBufferDepthEncodingParams,
float4 VBufferDepthDecodingParams)
{
float numSlices = VBufferScaleAndSliceCount.z;
float rcpNumSlices = VBufferScaleAndSliceCount.w;

// The distance between slices is log-encoded.
float z = linearDepth;
float d = EncodeLogarithmicDepth(z, VBufferDepthEncodingParams);
float d = EncodeLogarithmicDepthGeneralized(z, VBufferDepthEncodingParams);
// Unity doesn't support samplers clamping to border, so we have to do it ourselves.
// TODO: add the proper sampler support.

float w = d;
#else
// Adjust the texture coordinate for HW trilinear sampling.
float w = ComputeLerpPositionForLogEncoding(z, d, VBufferScaleAndSliceCount, VBufferDepthEncodingParams);
float w = ComputeLerpPositionForLogEncoding(z, d, VBufferScaleAndSliceCount, VBufferDepthDecodingParams);
#endif
return SAMPLE_TEXTURE3D_LOD(VBufferLighting, trilinearSampler, float3(uv, w), 0);

float2 positionNDC, float linearDepth,
float4 VBufferResolution,
float4 VBufferScaleAndSliceCount,
float4 VBufferDepthEncodingParams)
float4 VBufferDepthEncodingParams,
float4 VBufferDepthDecodingParams)
VBufferScaleAndSliceCount, VBufferDepthEncodingParams);
VBufferScaleAndSliceCount,
VBufferDepthEncodingParams,
VBufferDepthDecodingParams);
#else
// Perform biquadratic reconstruction in XY, linear in Z, using 4x trilinear taps.

// The distance between slices is log-encoded.
float z = linearDepth;
float d = EncodeLogarithmicDepth(z, VBufferDepthEncodingParams);
float d = EncodeLogarithmicDepthGeneralized(z, VBufferDepthEncodingParams);
float w = ComputeLerpPositionForLogEncoding(z, d, VBufferScaleAndSliceCount, VBufferDepthEncodingParams);
float w = ComputeLerpPositionForLogEncoding(z, d, VBufferScaleAndSliceCount, VBufferDepthDecodingParams);
float2 weights[2], offsets[2];
BiquadraticFilter(1 - fc, weights, offsets); // Inverse-translate the filter centered around 0.5

34
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs


List<VBuffer> m_VBuffers = null;
float m_VBufferNearPlane = 0.5f; // Distance in meters; dynamic modifications not handled by reprojection
float m_VBufferFarPlane = 64.0f; // Distance in meters; dynamic modifications not handled by reprojection
const float k_LogScale = 0.5f;
public void Build(HDRenderPipelineAsset asset)
{

return new Vector2((float)screenWidth / (float)(w * t), (float)screenHeight / (float)(h * t));
}
// Uses a logarithmic depth encoding.
// Near plane: depth = 0; far plane: depth = 1.
// x = n, y = log2(f/n), z = 1/n, w = 1/log2(f/n).
static Vector4 ComputeLogarithmicDepthEncodingParams(float nearPlane, float farPlane)
// See EncodeLogarithmicDepthGeneralized().
static Vector4 ComputeLogarithmicDepthEncodingParams(float nearPlane, float farPlane, float c)
{
Vector4 depthParams = new Vector4();
float n = nearPlane;
float f = farPlane;
depthParams.x = Mathf.Log(c, 2) * (1.0f / Mathf.Log(c * (f - n) + 1, 2));
depthParams.y = 1.0f / Mathf.Log(c * (f - n) + 1, 2);
depthParams.z = n - 1.0f / c; // Same
depthParams.w = 0.0f;
return depthParams;
}
// See DecodeLogarithmicDepthGeneralized().
static Vector4 ComputeLogarithmicDepthDecodingParams(float nearPlane, float farPlane, float c)
{
Vector4 depthParams = new Vector4();

depthParams.x = n;
depthParams.y = Mathf.Log(f / n, 2);
depthParams.z = 1.0f / depthParams.x;
depthParams.w = 1.0f / depthParams.y;
depthParams.x = 1.0f / c;
depthParams.y = c * (f - n) + 1;
depthParams.z = n - 1.0f / c; // Same
depthParams.w = 0.0f;
return depthParams;
}

cmd.SetGlobalVector( HDShaderIDs._VBufferResolution, new Vector4(w, h, 1.0f / w, 1.0f / h));
cmd.SetGlobalVector( HDShaderIDs._VBufferScaleAndSliceCount, new Vector4(scale.x, scale.y, d, 1.0f / d));
cmd.SetGlobalVector( HDShaderIDs._VBufferDepthEncodingParams, ComputeLogarithmicDepthEncodingParams(m_VBufferNearPlane, m_VBufferFarPlane));
cmd.SetGlobalVector( HDShaderIDs._VBufferDepthEncodingParams, ComputeLogarithmicDepthEncodingParams(m_VBufferNearPlane, m_VBufferFarPlane, k_LogScale));
cmd.SetGlobalVector( HDShaderIDs._VBufferDepthDecodingParams, ComputeLogarithmicDepthDecodingParams(m_VBufferNearPlane, m_VBufferFarPlane, k_LogScale));
cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, vBuffer.GetLightingIntegralBuffer());
}

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderVariables.hlsl


float _GlobalFog_Extinction;
float4 _VBufferResolution; // { w, h, 1/w, 1/h }
float4 _VBufferScaleAndSliceCount; // { fracVisW, fracVisH, count, 1/count }
float4 _VBufferDepthEncodingParams; // { n, log2(f/n), 1/n, 1/log2(f/n) }
float4 _VBufferDepthEncodingParams; // See the call site for description
float4 _VBufferDepthDecodingParams; // See the call site for description
CBUFFER_END
// ----------------------------------------------------------------------------

6
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/AtmosphericScattering/AtmosphericScattering.hlsl


#if (SHADEROPTIONS_VOLUMETRIC_LIGHTING_PRESET != 0)
float4 volFog = SampleInScatteredRadianceAndTransmittance(TEXTURE3D_PARAM(_VBufferLighting, s_trilinear_clamp_sampler),
posInput.positionNDC, posInput.linearDepth,
_VBufferResolution, _VBufferScaleAndSliceCount,
_VBufferDepthEncodingParams);
_VBufferResolution,
_VBufferScaleAndSliceCount,
_VBufferDepthEncodingParams,
_VBufferDepthDecodingParams);
fogColor = volFog.rgb;
fogFactor = 1 - volFog.a;
#else

正在加载...
取消
保存