浏览代码

Prepare the volumetric reprojection framework

/Yibing-Project-2
Evgenii Golubev 7 年前
当前提交
016a51ff
共有 5 个文件被更改,包括 78 次插入35 次删除
  1. 11
      ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl
  2. 46
      ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl
  3. 20
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/Resources/VolumetricLighting.compute
  4. 28
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs
  5. 8
      ScriptableRenderPipeline/HDRenderPipeline/Sky/AtmosphericScattering/AtmosphericScattering.hlsl

11
ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl


return mul(viewProjMatrix, float4(positionWS, 1.0)).w;
}
// 'z' is the view-space Z position. It is assumed to lie between the near and the far planes.
// For (z <= n), the function returns 0. For (z >= f), the function returns 1.
// 'z' is the view-space Z position (linear depth).
// saturate() the output of the function to clamp them to the [0, 1] range.
return saturate(log2(max(1, z * encodingParams.z)) * encodingParams.w);
return log2(max(0, z * encodingParams.z)) * encodingParams.w;
// The encoded depth 'd' is assumed to lie in the [0, 1] range.
// 'd' is the logarithmically encoded depth value.
// saturate(d) to clamp the output of the function to the [n, f] range.
return encodingParams.x * exp2(saturate(d) * encodingParams.y);
return encodingParams.x * exp2(d * encodingParams.y);
}
// ----------------------------------------------------------------------------

46
ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl


#define VBUFFER_SLICE_COUNT 128
#endif // PRESET_ULTRA
// Returns {volumetric radiance, opacity}.
float4 GetInScatteredRadianceAndTransmittance(float2 positionNDC, float linearDepth,
TEXTURE3D_ARGS(VBufferLighting, linearClampSampler),
float2 VBufferScale, float4 VBufferDepthEncodingParams)
// Point samples {volumetric radiance, optical depth}. Out-of-bounds loads return 0.
float4 LoadInScatteredRadianceAndTransmittance(float2 positionNDC, float linearDepth,
TEXTURE3D(VBufferLighting),
float4 VBufferResolutionAndScale,
float4 VBufferDepthEncodingParams)
int n = VBUFFER_SLICE_COUNT;
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));
}
// Returns linearly interpolated {volumetric radiance, opacity}. The sampler clamps to edge.
float4 SampleInScatteredRadianceAndTransmittance(float2 positionNDC, float linearDepth,
TEXTURE3D_ARGS(VBufferLighting, linearClampSampler),
float2 VBufferScale, float4 VBufferDepthEncodingParams)
{
int k = VBUFFER_SLICE_COUNT;
float z = linearDepth;
float d = EncodeLogarithmicDepth(z, VBufferDepthEncodingParams);

float4 L;
if (d == 1)
[branch] if (d != saturate(d))
// We are behind the far plane of the V-buffer.
// The sampler should clamp to edge.
L = SAMPLE_TEXTURE3D_LOD(VBufferLighting, linearClampSampler, float3(uv, 1), 0);
// We are in front of the near or behind the far plane of the V-buffer.
// The sampler will clamp to edge.
L = SAMPLE_TEXTURE3D_LOD(VBufferLighting, linearClampSampler, float3(uv, d), 0);
}
else
{

float s0 = floor(d * n - 0.5);
float s1 = ceil( d * n - 0.5);
float d0 = s0 * rcp(n) + (0.5 * rcp(n));
float d1 = s1 * rcp(n) + (0.5 * rcp(n));
float s0 = floor(d * k - 0.5);
float s1 = ceil(d * k - 0.5);
float d0 = saturate(s0 * rcp(k) + (0.5 * rcp(k)));
float d1 = saturate(s1 * rcp(k) + (0.5 * rcp(k)));
// The sampler should clamp to edge.
// The sampler will clamp to edge.
float4 L0 = SAMPLE_TEXTURE3D_LOD(VBufferLighting, linearClampSampler, float3(uv, d0), 0);
float4 L1 = SAMPLE_TEXTURE3D_LOD(VBufferLighting, linearClampSampler, float3(uv, d1), 0);

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


//--------------------------------------------------------------------------------------------------
RW_TEXTURE3D(float4, _VBufferLightingCurr); // RGB = radiance, A = optical depth
TEXTURE3D(_VBufferLightingCurrPrev); // RGB = radiance, A = optical depth
TEXTURE3D(_VBufferLightingPrev); // RGB = radiance, A = optical depth
float4x4 _VBufferCoordToViewDirWS; // Actually just 3x3, but Unity can only set 4x4
float4x4 _VBufferCoordToViewDirWS; // Actually just 3x3, but Unity can only set 4x4
CBUFFER_END
//--------------------------------------------------------------------------------------------------

// We will use it for participating media sampling and reprojection.
float tc = t0 + 0.5 * dt;
float3 centerWS = GetPointAtDistance(ray, tc);
// Reproject 'centerWS'. It performs a point sample.
float2 reprojPosNDC = ComputeNormalizedDeviceCoordinates(centerWS, _PrevViewProjMatrix);
float reprojZ = mul(_PrevViewProjMatrix, float4(centerWS, 1)).w;
float4 reprojValue = LoadInScatteredRadianceAndTransmittance(reprojPosNDC, reprojZ,
_VBufferLightingPrev,
_VBufferResolutionAndScale,
_VBufferDepthEncodingParams);
// Sample the participating medium at 'tc' (or 'centerWS').
// We consider it to be constant along the interval [t0, t1] (within the voxel).

// Compute the optical depth up to the center of the interval.
opticalDepth += 0.5 * extinction * dt;
// Store the voxel data. TODO: reprojection of 'tc' (or 'centerWS').
_VBufferLightingCurr[uint3(posInput.positionSS, slice)] = float4(totalRadiance, opticalDepth);
// Perform temporal blending.
float4 newValue = float4(totalRadiance, opticalDepth);
float4 blendedValue = lerp(reprojValue, newValue, reprojValue.a == 0 ? 1 : 0.1);
// Store the voxel data.
_VBufferLightingCurr[uint3(posInput.positionSS, slice)] = blendedValue;
// Compute the optical depth up to the end of the interval.
opticalDepth += 0.5 * extinction * dt;

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


VolumetricLightingPreset m_VolumetricLightingPreset = VolumetricLightingPreset.Normal;
ComputeShader m_VolumetricLightingCS { get { return m_Asset.renderPipelineResources.volumetricLightingCS; } }
float m_VBufferNearPlane = 0.5f; // Distance in meters
float m_VBufferFarPlane = 64.0f; // Distance in meters
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
RenderTexture[] m_VBufferLighting = null; // Used for even / odd frames
RenderTargetIdentifier[] m_VBufferLightingRT = null;

return globalFogComponent;
}
RenderTargetIdentifier GetVBufferCurrFrame()
{
bool evenFrame = (Time.renderedFrameCount & 1) == 0;
return m_VBufferLightingRT[evenFrame ? 0 : 1];
}
RenderTargetIdentifier GetVBufferPrevFrame()
{
bool evenFrame = (Time.renderedFrameCount & 1) == 0;
return m_VBufferLightingRT[evenFrame ? 1 : 0];
}
public void SetVolumetricLightingData(HDCamera camera, CommandBuffer cmd)
{
HomogeneousFog globalFogComponent = GetGlobalFogComponent();

cmd.SetGlobalVector( HDShaderIDs._VBufferResolutionAndScale, resAndScale);
cmd.SetGlobalVector( HDShaderIDs._VBufferDepthEncodingParams, depthParams);
cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, m_VBufferLightingRT[0]);
cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, GetVBufferCurrFrame());
}
void VolumetricLightingPass(HDCamera camera, CommandBuffer cmd)

if (GetGlobalFogComponent() == null)
{
// Clear the render target instead of running the shader.
CoreUtils.SetRenderTarget(cmd, m_VBufferLightingRT[0], ClearFlag.Color, CoreUtils.clearColorAllBlack);
CoreUtils.SetRenderTarget(cmd, GetVBufferCurrFrame(), ClearFlag.Color, CoreUtils.clearColorAllBlack);
camera.SetupComputeShader(m_VolumetricLightingCS, cmd);
bool enableClustered = m_FrameSettings.lightLoopSettings.enableTileAndCluster;
int kernel = m_VolumetricLightingCS.FindKernel(enableClustered ? "VolumetricLightingClustered"

Vector4 scaledRes = new Vector4(w * scale.x, h * scale.y, 1.0f / (w * scale.x), 1.0f / (h * scale.y));
Matrix4x4 transform = HDUtils.ComputePixelCoordToWorldSpaceViewDirectionMatrix(vFoV, scaledRes, camera.viewMatrix, false);
camera.SetupComputeShader(m_VolumetricLightingCS, cmd);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingCurr, m_VBufferLightingRT[0]);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingPrev, m_VBufferLightingRT[1]);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingCurr, GetVBufferCurrFrame());
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingPrev, GetVBufferPrevFrame());
// The shader defines GROUP_SIZE_1D = 16.
cmd.DispatchCompute(m_VolumetricLightingCS, kernel, (w + 15) / 16, (h + 15) / 16, 1);

8
ScriptableRenderPipeline/HDRenderPipeline/Sky/AtmosphericScattering/AtmosphericScattering.hlsl


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

正在加载...
取消
保存