浏览代码

Improve the reprojection quality

/Yibing-Project-2
Evgenii Golubev 7 年前
当前提交
a013ecb1
共有 5 个文件被更改,包括 76 次插入42 次删除
  1. 22
      ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl
  2. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDStringConstants.cs
  3. 74
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/Resources/VolumetricLighting.compute
  4. 17
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs
  5. 4
      ScriptableRenderPipeline/HDRenderPipeline/Sky/AtmosphericScattering/AtmosphericScattering.hlsl

22
ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl


#define VBUFFER_SLICE_COUNT 128
#endif // PRESET_ULTRA
// Point samples the V-Buffer. Out-of-bounds loads return 0.
float4 LoadFromVBuffer(float2 positionNDC, float linearDepth,
TEXTURE3D(VBufferLighting),
float4 VBufferResolutionAndScale,
float4 VBufferDepthEncodingParams)
{
int k = VBUFFER_SLICE_COUNT;
float z = linearDepth;
float d = EncodeLogarithmicDepth(z, VBufferDepthEncodingParams);
// Account for the visible area of the VBuffer.
float2 positionSS = positionNDC * (VBufferResolutionAndScale.xy * VBufferResolutionAndScale.zw);
float slice = d * k;
// Out-of-bounds loads return 0.
return LOAD_TEXTURE3D(VBufferLighting, float3(positionSS, slice));
}
float4 SampleInScatteredRadianceAndTransmittance(float2 positionNDC, float linearDepth,
TEXTURE3D_ARGS(VBufferLighting, linearClampSampler),
float4 SampleInScatteredRadianceAndTransmittance(TEXTURE3D_ARGS(VBufferLighting, linearClampSampler),
float2 positionNDC, float linearDepth,
float2 VBufferScale, float4 VBufferDepthEncodingParams)
{
int k = VBUFFER_SLICE_COUNT;

1
ScriptableRenderPipeline/HDRenderPipeline/HDStringConstants.cs


public static readonly int _VBufferLightingIntegral = Shader.PropertyToID("_VBufferLightingIntegral");
public static readonly int _VBufferLightingHistory = Shader.PropertyToID("_VBufferLightingHistory");
public static readonly int _VBufferLightingFeedback = Shader.PropertyToID("_VBufferLightingFeedback");
public static readonly int _VBufferIntegrationOffset = Shader.PropertyToID("_VBufferIntegrationOffset");
}
}

74
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/Resources/VolumetricLighting.compute


#pragma enable_d3d11_debug_symbols
#define ENABLE_REPROJECTION 0
#define ENABLE_REPROJECTION 1
#define DEBUG_REPROJECTION 0
#include "../../../ShaderPass/ShaderPass.cs.hlsl"

// TODO: avoid creating another Constant Buffer...
CBUFFER_START(UnityVolumetricLighting)
float4x4 _VBufferCoordToViewDirWS; // Actually just 3x3, but Unity can only set 4x4
float4 _VBufferIntegrationOffset; // {x, y, z}, w = unused
CBUFFER_END
//--------------------------------------------------------------------------------------------------

return ray.originWS + t * ray.directionWS;
}
BakeLightingData unused; // Unused, so define once
// Computes the light integral (in-scattered radiance) within the voxel.
// Multiplication by the scattering coefficient and the phase function is performed outside.

#endif
{
float3 voxelRadiance = 0;
BakeLightingData unused; // Unused for now, so define once
if (featureFlags & LIGHTFEATUREFLAGS_DIRECTIONAL)
{

return voxelRadiance;
}
// Samples the linearly interpolated V-Buffer. Out-of-bounds loads return 0.
float4 SampleVBuffer(TEXTURE3D_ARGS(VBufferLighting, trilinearSampler),
float2 positionNDC, float linearDepth,
float2 VBufferScale,
float4 VBufferDepthEncodingParams)
{
int k = VBUFFER_SLICE_COUNT;
float z = linearDepth;
float d = EncodeLogarithmicDepth(z, VBufferDepthEncodingParams);
// Account for the visible area of the V-Buffer.
float2 uv = positionNDC * VBufferScale;
// TODO: Unity doesn't support samplers clamping to border, so we have to do it ourselves.
bool isInBounds = Min3(uv.x, uv.y, d) > 0 && Max3(uv.x, uv.y, d) < 1;
[branch] if (isInBounds)
{
// We use hardware trilinear filtering.
// In theory, this is wrong, since the distance between slices is log-encoded.
// In practice, doing the right thing in a loop is simply too expensive.
return SAMPLE_TEXTURE3D_LOD(VBufferLighting, trilinearSampler, float3(uv, d), 0);
}
else
{
return 0;
}
}
// Computes the in-scattered radiance along the ray.
void FillVolumetricLightingBuffer(LightLoopContext context, uint featureFlags,
PositionInputs posInput, Ray ray)

float3 scattering = _GlobalFog_Scattering;
float extinction = _GlobalFog_Extinction;
// TODO: use a low-discrepancy point set.
float rndVal = VanDerCorputBase2(_TaaFrameIndex + 1);
#if ENABLE_REPROJECTION
// This is a sequence of 7 equidistant numbers from 1/14 to 13/14.
// Each of them is the centroid of the interval of length 2/14.
float rndVal = _VBufferIntegrationOffset.z;
#else
float rndVal = 0.5;
#endif
float3 voxelRadiance = EvaluateVoxelLighting(context, featureFlags, posInput,
ray, t0, t1, dt, rndVal, extinction

#if ENABLE_REPROJECTION
// Reproject the history at 'centerWS'.
// TODO! WARNING! THE REPROJECTED VALUE IS AN INTEGRAL OVER A SEGMENT, THE LENGTH OF THE CURRENT SEGMENT IS DIFFERENT, ACCOUNT FOR THAT!
float4 reprojValue = LoadFromVBuffer(reprojPosNDC, reprojZ,
_VBufferLightingHistory,
_VBufferResolutionAndScale,
_VBufferDepthEncodingParams);
float4 reprojValue = SampleVBuffer(TEXTURE3D_PARAM(_VBufferLightingHistory, s_trilinear_clamp_sampler),
reprojPosNDC, reprojZ,
_VBufferResolutionAndScale.zw,
_VBufferDepthEncodingParams);
float3 blendedRadiance = lerp(voxelRadiance, reprojValue.rgb, reprojValue.a == 0 ? 0 : 0.9);
// Both radiance values are obtained by integrating over line segments of different length.
// Blending only makes sense if the length of both intervals is the same.
// Therefore, the reprojected radiance is defined as an integral over the unit interval,
// and it needs to be rescaled by 'dt'.
float confidence = reprojValue.a * 0.75; // 0.75 ^ 7 ≈ 1/7
float3 reprojRadiance = reprojValue.rgb;
float3 blendedRadiance = (1 - confidence) * voxelRadiance + confidence * dt * reprojRadiance;
// Store the feedback.
_VBufferLightingFeedback[uint3(posInput.positionSS, slice)] = float4(blendedRadiance, 1);
// Store the feedback for a unit interval.
// TODO: store a non-constant confidence value.
_VBufferLightingFeedback[uint3(posInput.positionSS, slice)] = float4(blendedRadiance / dt, 1);
#else
float3 blendedRadiance = voxelRadiance;
#endif

}
#if ENABLE_REPROJECTION
// TODO: use a low-discrepancy point set.
float2 halton23[8] = {float2(1.0/2.0, 1.0/3.0), float2(1.0/4.0, 2.0/3.0), float2(3.0/4.0, 1.0/9.0), float2(1.0/8.0, 4.0/9.0), float2(5.0/8.0, 7.0/9.0), float2(3.0/8.0, 2.0/9.0), float2(7.0/8.0, 5.0/9.0), float2(1.0/16.0, 8.0/9.0)};
float2 sampleCoord = voxelCoord + halton23[_TaaFrameIndex];
float2 sampleCoord = voxelCoord + 0.5;
// // TODO: use a low-discrepancy point set.
// float2 halton23[8] = {float2(1.0/2.0, 1.0/3.0), float2(1.0/4.0, 2.0/3.0), float2(3.0/4.0, 1.0/9.0), float2(1.0/8.0, 4.0/9.0), float2(5.0/8.0, 7.0/9.0), float2(3.0/8.0, 2.0/9.0), float2(7.0/8.0, 5.0/9.0), float2(1.0/16.0, 8.0/9.0)};
// float2 sampleCoord = voxelCoord + halton23[_TaaFrameIndex];
#else
float2 sampleCoord = voxelCoord + 0.5;
#endif

17
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs


camera.SetupComputeShader(m_VolumetricLightingCS, cmd);
// This is a sequence of 7 equidistant numbers from 1/14 to 13/14.
// Each of them is the centroid of the interval of length 2/14.
// They've been rearranged in a sequence of pairs {small, large}, s.t. (small + large) = 1.
// That way, the running average position is close to 0.5.
float[] seq = {7.0f/14.0f, 3.0f/14.0f, 11.0f/14.0f, 5.0f/14.0f, 9.0f/14.0f, 1.0f/14.0f, 13.0f/14.0f};
uint sampleIndex = (camera.camera.cameraType == CameraType.Game) ? (uint)Time.renderedFrameCount % 7 : 0;
cmd.SetComputeMatrixParam( m_VolumetricLightingCS, HDShaderIDs._VBufferCoordToViewDirWS, transform);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingHistory, GetVBufferLightingHistory()); // Read
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingFeedback, GetVBufferLightingFeedback()); // Write
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingIntegral, GetVBufferLightingIntegral()); // Write
cmd.SetComputeMatrixParam( m_VolumetricLightingCS, HDShaderIDs._VBufferCoordToViewDirWS, transform);
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._VBufferIntegrationOffset, new Vector4(0.0f, 0.0f, seq[sampleIndex]));
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingHistory, GetVBufferLightingHistory()); // Read
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingFeedback, GetVBufferLightingFeedback()); // Write
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingIntegral, GetVBufferLightingIntegral()); // Write
// The shader defines GROUP_SIZE_1D = 16.
cmd.DispatchCompute(m_VolumetricLightingCS, kernel, (w + 15) / 16, (h + 15) / 16, 1);

4
ScriptableRenderPipeline/HDRenderPipeline/Sky/AtmosphericScattering/AtmosphericScattering.hlsl


float4 EvaluateAtmosphericScattering(PositionInputs posInput)
{
#ifdef VOLUMETRIC_LIGHTING_ENABLED
return SampleInScatteredRadianceAndTransmittance(posInput.positionNDC, posInput.linearDepth,
TEXTURE3D_PARAM(_VBufferLighting, s_linear_clamp_sampler),
return SampleInScatteredRadianceAndTransmittance(TEXTURE3D_PARAM(_VBufferLighting, s_linear_clamp_sampler),
posInput.positionNDC, posInput.linearDepth,
_VBufferResolutionAndScale.zw,
_VBufferDepthEncodingParams);
#endif

正在加载...
取消
保存