浏览代码

Clean up the volumetric lighting code

/Yibing-Project-2
Evgenii Golubev 7 年前
当前提交
c212b126
共有 14 个文件被更改,包括 395 次插入308 次删除
  1. 79
      SampleScenes/HDTest/HDRenderLoopTest.unity
  2. 58
      ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl
  3. 20
      ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  4. 17
      ScriptableRenderPipeline/HDRenderPipeline/HDStringConstants.cs
  5. 15
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Deferred.shader
  6. 15
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Deferred.compute
  7. 14
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  8. 152
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/Resources/VolumetricLighting.compute
  9. 278
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs
  10. 22
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs.hlsl
  11. 15
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  12. 8
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.compute
  13. 2
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringSettings.cs.hlsl
  14. 8
      ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl

79
SampleScenes/HDTest/HDRenderLoopTest.unity


spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 16
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 16
shapeWidth: 2
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 1
shapeLength: 4
shapeWidth: 2
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

m_IsActive: 1
--- !u!114 &1046252901
MonoBehaviour:
m_ObjectHideFlags: 0
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1046252900}

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

m_LocalEulerAnglesHint: {x: 40.735, y: -87.087006, z: -23.206001}
--- !u!114 &1046252904
MonoBehaviour:
m_ObjectHideFlags: 0
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1046252900}

- 0.2
- 0.2
shadowAlgorithm: 0
shadowVariant: 0
shadowVariant: 3
format: 0
data:
shadowDatas: []
format: 3
data: 0bd7a33b0000803f
shadowDatas:
- format: 3
data: 0bd7a33b0000803f
--- !u!1001 &1062558345
Prefab:
m_ObjectHideFlags: 0

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 1
shapeWidth: 1
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

m_Father: {fileID: 657202130}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1494324908 stripped
GameObject:
m_PrefabParentObject: {fileID: 100000, guid: a4ce73c115746a34ba12813555ed5d78, type: 3}
m_PrefabInternal: {fileID: 1145101430}
--- !u!114 &1494324909
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1494324908}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8f608e240d5376341bcef2478d231457, type: 3}
m_Name:
m_EditorClassIdentifier:
volumeParameters:
bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: Infinity, y: Infinity, z: Infinity}
albedo: {r: 0.5, g: 0.5, b: 0.5, a: 1}
meanFreePath: 19.13
--- !u!1 &1514376229
GameObject:
m_ObjectHideFlags: 0

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 4
shapeWidth: 2
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

m_ShowToolkit: 0
m_ShowCustomSorter: 0
breakBeforeColorGrading: 0
m_BeforeTransparentBundles: []
m_BeforeTransparentBundles:
- assemblyQualifiedName: InvertOpaque, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
m_BeforeStackBundles:
- assemblyQualifiedName: HalfToneOpaque, Assembly-CSharp, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 2
shapeLength: 4
shapeWidth: 2
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

spotLightShape: 0
shapeLength: 0
shapeWidth: 0
aspectRatio: 1
shapeRadius: 0
maxSmoothness: 1
applyRangeAttenuation: 1

58
ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl


HenyeyGreensteinPhasePartVarying(asymmetry, LdotD);
}
// TODO: share this...
#define PRESET_ULTRA 0
#if PRESET_ULTRA
// E.g. for 1080p: (1920/4)x(1080/4)x(256) = 33,177,600 voxels
#define VBUFFER_TILE_SIZE 4
#define VBUFFER_SLICE_COUNT 256
#else
// E.g. for 1080p: (1920/8)x(1080/8)x(128) = 4,147,200 voxels
#define VBUFFER_TILE_SIZE 8
#define VBUFFER_SLICE_COUNT 128
#endif
float globalFogExtinction,
TEXTURE3D(vBuffer), SAMPLER3D(bilinearSampler),
float4 vBufferResolution,
float4 vBufferDepthEncodingParams,
int numSlices = 64)
TEXTURE3D(VBufferLighting), SAMPLER3D(sampler_LinearXY_PointZ_Clamp),
float4 VBufferDepthEncodingParams, float2 VBufferScale)
int n = numSlices;
float d = EncodeLogarithmicDepth(depthVS, vBufferDepthEncodingParams);
int n = VBUFFER_SLICE_COUNT;
float z = depthVS;
float d = EncodeLogarithmicDepth(z, VBufferDepthEncodingParams);
// We cannot simply perform trilinear interpolation since the distance between slices is Z-encoded.
// We cannot use hardware trilinear interpolation since the distance between slices is log-encoded.
// TODO: test the visual difference in practice.
float z0 = DecodeLogarithmicDepth(d0, vBufferDepthEncodingParams);
float z1 = DecodeLogarithmicDepth(d1, vBufferDepthEncodingParams);
float z = depthVS;
float z0 = DecodeLogarithmicDepth(d0, VBufferDepthEncodingParams);
float z1 = DecodeLogarithmicDepth(d1, VBufferDepthEncodingParams);
// Scale and bias the UVs s.t.
// {0} in the screen space corresponds to {0.5/n} and
// {1} in the screen space corresponds to {1 - 0.5/n}.
// TODO: precompute.
float u = positionSS.x * (vBufferResolution.x - 1) / vBufferResolution.x + 0.5 / vBufferResolution.x;
float v = positionSS.y * (vBufferResolution.y - 1) / vBufferResolution.y + 0.5 / vBufferResolution.y;
// Account for the visible area of the VBuffer.
float2 uv = positionSS * VBufferScale;
// Perform 2 bilinear taps.
float4 v0 = SAMPLE_TEXTURE3D_LOD(vBuffer, bilinearSampler, float3(u, v, d0), 0);
float4 v1 = SAMPLE_TEXTURE3D_LOD(vBuffer, bilinearSampler, float3(u, v, d1), 0);
// Perform 2 bilinear taps. The sampler should clamp the values at the boundaries of the 3D texture.
float4 v0 = SAMPLE_TEXTURE3D_LOD(VBufferLighting, sampler_LinearXY_PointZ_Clamp, float3(uv, d0), 0);
float4 v1 = SAMPLE_TEXTURE3D_LOD(VBufferLighting, sampler_LinearXY_PointZ_Clamp, float3(uv, d1), 0);
[flatten] if (z - z1 > 0)
{
// Our sample is beyond the far plane of the V-buffer.
// Apply additional global fog attenuation.
vt.a += OpticalDepthHomogeneous(globalFogExtinction, z - z1);
// TODO: extra in-scattering from directional and ambient lights.
}
float TransmittanceColorAtDistanceToAbsorption(float3 transmittanceColor, float atDistance)
float3 TransmittanceColorAtDistanceToAbsorption(float3 transmittanceColor, float atDistance)
{
return -log(transmittanceColor + 0.00001) / max(atDistance, 0.000001);
}

20
ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


m_LightLoop.AllocResolutionDependentBuffers(camera.pixelWidth, camera.pixelHeight);
}
if (resolutionChanged && m_VolumetricLightingEnabled)
CreateVolumetricLightingBuffers(camera.pixelWidth, camera.pixelHeight);
if (resolutionChanged && m_VolumetricLightingPreset != VolumetricLightingPreset.Off)
CreateVBuffer(camera.pixelWidth, camera.pixelHeight);
// update recorded window resolution
m_CurrentWidth = camera.pixelWidth;

cmd.SetGlobalVectorArray(HDShaderIDs._HalfRcpVariancesAndWeights, sssParameters.halfRcpVariancesAndWeights);
cmd.SetGlobalVectorArray(HDShaderIDs._TransmissionTints, sssParameters.transmissionTints);
SetGlobalVolumeProperties(m_VolumetricLightingEnabled, cmd);
if (m_VolumetricLightingPreset != VolumetricLightingPreset.Off)
{
// TODO: enable keyword VOLUMETRIC_LIGHTING_ENABLED.
SetVolumetricLightingData(hdCamera, cmd);
}
else
{
// TODO: disable keyword VOLUMETRIC_LIGHTING_ENABLED.
// We should not access any volumetric lighting data in our shaders.
}
}
}

var depthTexture = GetDepthTexture();
var options = new LightLoop.LightingPassOptions();
options.volumetricLightingEnabled = m_VolumetricLightingEnabled;
options.volumetricLightingEnabled = m_VolumetricLightingPreset != VolumetricLightingPreset.Off;
if (m_CurrentDebugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission)
{

CoreUtils.SetRenderTarget(cmd, m_HTileRT, ClearFlag.Color, Color.black);
}
}
if (m_VolumetricLightingEnabled)
ClearVolumetricLightingBuffers(cmd, camera.isFirstFrame);
// TEMP: As we are in development and have not all the setup pass we still clear the color in emissive buffer and gbuffer, but this will be removed later.

17
ScriptableRenderPipeline/HDRenderPipeline/HDStringConstants.cs


public static readonly int _Source4 = Shader.PropertyToID("_Source4");
public static readonly int _Result1 = Shader.PropertyToID("_Result1");
internal static readonly int _GlobalFog_Extinction = Shader.PropertyToID("_GlobalFog_Extinction");
internal static readonly int _GlobalFog_Asymmetry = Shader.PropertyToID("_GlobalFog_Asymmetry");
internal static readonly int _GlobalFog_Scattering = Shader.PropertyToID("_GlobalFog_Scattering");
internal static readonly int _vBufferResolution = Shader.PropertyToID("_vBufferResolution");
internal static readonly int _vBufferDepthEncodingParams = Shader.PropertyToID("_vBufferDepthEncodingParams");
internal static readonly int _vBufferCoordToViewDirWS = Shader.PropertyToID("_vBufferCoordToViewDirWS");
internal static readonly int _VolumetricLightingBuffer = Shader.PropertyToID("_VolumetricLightingBuffer");
internal static readonly int _VolumetricLightingBufferCurrentFrame = Shader.PropertyToID("_VolumetricLightingBufferCurrentFrame");
internal static readonly int _VolumetricLightingBufferAccumulation = Shader.PropertyToID("_VolumetricLightingBufferAccumulation");
internal static readonly int _GlobalFog_Extinction = Shader.PropertyToID("_GlobalFog_Extinction");
internal static readonly int _GlobalFog_Scattering = Shader.PropertyToID("_GlobalFog_Scattering");
internal static readonly int _VBufferResolutionAndScale = Shader.PropertyToID("_VBufferResolutionAndScale");
internal static readonly int _VBufferDepthEncodingParams = Shader.PropertyToID("_VBufferDepthEncodingParams");
internal static readonly int _VBufferCoordToViewDirWS = Shader.PropertyToID("_VBufferCoordToViewDirWS");
internal static readonly int _VBufferDensity = Shader.PropertyToID("_VBufferDensity");
internal static readonly int _VBufferLighting = Shader.PropertyToID("_VBufferLighting");
internal static readonly int _VBufferLightingPrev = Shader.PropertyToID("_VBufferLightingPrev");
}
}

15
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Deferred.shader


//-------------------------------------------------------------------------------------
DECLARE_GBUFFER_TEXTURE(_GBufferTexture);
#ifdef VOLUMETRIC_LIGHTING_ENABLED
TEXTURE3D(_VBufferLighting);
#endif
struct Attributes
{

float3 diffuseLighting;
float3 specularLighting;
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, LIGHT_FEATURE_MASK_FLAGS_OPAQUE, diffuseLighting, specularLighting);
#ifdef VOLUMETRIC_LIGHTING_ENABLED
float4 volumetricLighting = GetInScatteredRadianceAndTransmittance(posInput.positionSS,
posInput.depthVS,
_VBufferLighting,
s_linear_clamp_sampler, // TODO: use the right sampler
_VBufferDepthEncodingParams,
_VBufferResolutionAndScale.zw);
diffuseLighting *= volumetricLighting.a;
specularLighting *= volumetricLighting.a;
specularLighting += volumetricLighting.rgb;
#endif
Outputs outputs;
#ifdef OUTPUT_SPLIT_LIGHTING

15
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Deferred.compute


//-------------------------------------------------------------------------------------
DECLARE_GBUFFER_TEXTURE(_GBufferTexture);
#ifdef VOLUMETRIC_LIGHTING_ENABLED
TEXTURE3D(_VBufferLighting);
#endif
RWTexture2D<float3> diffuseLightingUAV;
RWTexture2D<float4> specularLightingUAV;

float3 diffuseLighting;
float3 specularLighting;
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, featureFlags, diffuseLighting, specularLighting);
#ifdef VOLUMETRIC_LIGHTING_ENABLED
float4 volumetricLighting = GetInScatteredRadianceAndTransmittance(posInput.positionSS,
posInput.depthVS,
_VBufferLighting,
s_linear_clamp_sampler, // TODO: use the right sampler
_VBufferDepthEncodingParams,
_VBufferResolutionAndScale.zw);
diffuseLighting *= volumetricLighting.a;
specularLighting *= volumetricLighting.a;
specularLighting += volumetricLighting.rgb;
#endif
if (_EnableSSSAndTransmission != 0 && bsdfData.materialId == MATERIALID_LIT_SSS && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_SSS))
{

14
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs


cmd.SetComputeTextureParam(deferredComputeShader, kernel, HDShaderIDs.specularLightingUAV, colorBuffers[0]);
cmd.SetComputeTextureParam(deferredComputeShader, kernel, HDShaderIDs.diffuseLightingUAV, colorBuffers[1]);
HDRenderPipeline.SetGlobalVolumeProperties(options.volumetricLightingEnabled, cmd, deferredComputeShader);
// always do deferred lighting in blocks of 16x16 (not same as tiled light size)
if (options.volumetricLightingEnabled)
{
// TODO: enable keyword VOLUMETRIC_LIGHTING_ENABLED.
// TODO: do not use globals, call HDRenderPipeline.SetVolumetricLightingData() instead.
HDRenderPipeline.SetVolumetricLightingDataFromGlobals(cmd, deferredComputeShader, kernel);
}
else
{
// TODO: disable keyword VOLUMETRIC_LIGHTING_ENABLED.
// We should not access any volumetric lighting data in our shaders.
}
if (enableFeatureVariants)
{

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


// Definitions
//--------------------------------------------------------------------------------------------------
#define PRESET_ULTRA 0
#if PRESET_ULTRA
// E.g. for 1080p: (1920/4)x(1080/4)x(256) = 33,177,600 voxels
#define VBUFFER_TILE_SIZE 4
#define VBUFFER_SLICE_COUNT 256
#else
// E.g. for 1080p: (1920/8)x(1080/8)x(128) = 4,147,200 voxels
#define VBUFFER_TILE_SIZE 8
#define VBUFFER_SLICE_COUNT 128
#endif
#pragma kernel VolumetricLightingAllLights VolumetricLighting=VolumetricLightingAllLights LIGHTLOOP_SINGLE_PASS
#pragma kernel VolumetricLightingClustered VolumetricLighting=VolumetricLightingClustered LIGHTLOOP_TILE_PASS USE_CLUSTERED_LIGHTLIST

#define SHADERPASS SHADERPASS_VOLUMETRIC_LIGHTING
#define GROUP_SIZE_1D 16
#define GROUP_SIZE_2D (GROUP_SIZE_1D * GROUP_SIZE_1D)
// #define USE_HENYEY_GREENSTEIN_PHASE_FUNCTION
//--------------------------------------------------------------------------------------------------
// Included headers

// Inputs & outputs
//--------------------------------------------------------------------------------------------------
RW_TEXTURE3D(float4, _VolumetricLightingBufferCurrentFrame); // RGB = radiance, A = optical depth
TEXTURE3D(_VolumetricLightingBufferAccumulation); // RGB = radiance, A = optical depth
RW_TEXTURE3D(float4, _VBufferLighting); // 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
//--------------------------------------------------------------------------------------------------

{
float3 originWS;
float3 directionWS; // Normalized
float ratioLenToZ; // Ratio of view space length to view space Z
float ratioLenToZ; // 1 / ViewSpaceZ
float ratioZtoLen; // ViewSpaceZ
void FillVolumetricLightingBuffer(Ray cameraRay, float4 depthParams, uint2 tileCoord, uint2 voxelCoord, uint sliceCount = 64)
void FillVolumetricLightingBuffer(Ray cameraRay, uint2 voxelCoord, uint2 tileCoord)
float3 scattering = _GlobalFog_Scattering;
float extinction = _GlobalFog_Extinction;
#ifdef USE_HENYEY_GREENSTEIN_PHASE_FUNCTION
float asymmetry = _GlobalFog_Asymmetry;
#endif
uint featureFlags = 0xFFFFFFFF; // TODO
float n = depthParams.x; // View space Z coordinate of the near plane
float t0 = n * cameraRay.ratioLenToZ; // Distance to the near plane
float du = rcp(sliceCount); // Log-encoded distance between slices
uint featureFlags = 0xFFFFFFFF; // TODO
float4 depthParams = _VBufferDepthEncodingParams;
float z0 = depthParams.x; // View space Z coordinate of the near plane
float t0 = z0 * cameraRay.ratioLenToZ; // Distance to the near plane
float de = rcp(VBUFFER_SLICE_COUNT); // Log-encoded distance between slices
for (uint s = 0; s < sliceCount; s++)
uint sliceCountHack = max(VBUFFER_SLICE_COUNT, (uint)z0); // Prevent unrolling...
// TODO: replace 'sliceCountHack' with VBUFFER_SLICE_COUNT when the shader compiler bug is fixed.
for (uint s = 0; s < sliceCountHack; s++)
float u1 = s * du + du; // (s + 1) / sliceCount
float t1 = DecodeLogarithmicDepth(u1, depthParams) * cameraRay.ratioLenToZ;
float e1 = s * de + de; // (s + 1) / sliceCount
float z1 = DecodeLogarithmicDepth(e1, depthParams);
float t1 = z1 * cameraRay.ratioLenToZ;
// Integral{a, b}{Transmittance(0, x) dx} = Transmittance(0, a) * Integral{0, b - a}{Transmittance(a, a + x) dx}.
float transmittance = Transmittance(opticalDepth) * TransmittanceIntegralHomogeneous(extinction, dt);
// TODO: low-discrepancy point set, mirroring around the bounds of the camera frustum.
// Note: using 0.5 here (in the linear space) does not guarantee that we stay within the bounds!
// TODO: low-discrepancy point set.
float z = t * cameraRay.ratioZtoLen;
// Get volume properties at 't'.
float3 scattering = _GlobalFog_Scattering;
float extinction = _GlobalFog_Extinction;
float3 sampleRadiance = 0;

float3 L = -lightData.forward; // Lights point backwards in Unity
float intensity = 1;
float3 color = lightData.color;
#ifdef USE_HENYEY_GREENSTEIN_PHASE_FUNCTION
// Note: we apply the scattering coefficient and the constant part of the phase function later.
intensity *= HenyeyGreensteinPhasePartVarying(asymmetry, dot(L, cameraRay.directionWS));
#endif
0, lightData.shadowIndex, L);
float3(0, 0, 0), lightData.shadowIndex, L);
// Note: no global fog attenuation along shadow rays for directional lights.
[branch] if (lightData.cookieIndex >= 0)
{

#ifdef LIGHTLOOP_TILE_PASS
PositionInputs posInput;
posInput.depthVS = t;
posInput.depthVS = z;
// TODO: do not refetch between consecutive samples if possible.
GetCountAndStart(posInput, LIGHTCATEGORY_PUNCTUAL, punctualLightStart, punctualLightCount);
GetCountAndStartCluster(posInput, LIGHTCATEGORY_PUNCTUAL, punctualLightStart, punctualLightCount);
#else
punctualLightCount = _PunctualLightCount;
#endif

float distSq = dot(lightToSample, lightToSample);
float dist = sqrt(distSq);
float3 L = lightToSample * -rsqrt(distSq);
float clampedDistSq = max(distSq, 0.25); // Reduce undersampling
float clampedDistSq = max(distSq, 0.5 * dt); // Hack to reduce undersampling
#ifdef USE_HENYEY_GREENSTEIN_PHASE_FUNCTION
// Note: we apply the scattering coefficient and the constant part of the phase function later.
intensity *= HenyeyGreensteinPhasePartVarying(asymmetry, dot(L, cameraRay.directionWS));
#endif
float3 offset = 0; // GetShadowPosOffset(nDotL, normal);
float shadow = GetPunctualShadowAttenuation(context.shadowContext, positionWS + offset,
0, lightData.shadowIndex, float4(L, dist));
float shadow = GetPunctualShadowAttenuation(context.shadowContext, positionWS,
float3(0, 0, 0), lightData.shadowIndex, float4(L, dist));
intensity *= lerp(1, shadow, lightData.shadowDimmer);
}

}
}
#ifdef USE_HENYEY_GREENSTEIN_PHASE_FUNCTION
float3 phaseConstant = scattering * HenyeyGreensteinPhasePartConstant(asymmetry);
#else
float3 phaseConstant = scattering * IsotropicPhaseFunction();
#endif
// We consider the volume to be homogeneous along the interval (within the voxel).
// Integral{a, b}{Transmittance(0, x) dx} = Transmittance(0, a) * Integral{0, b - a}{Transmittance(a, a + x) dx}.
float transmittance = Transmittance(opticalDepth) * TransmittanceIntegralHomogeneous(extinction, dt);
// Compute optical depth up to the center of the interval.
opticalDepth += extinction * (0.5 * dt);
totalRadiance += transmittance * phaseConstant * sampleRadiance;
// Compute the optical depth up to the sample.
opticalDepth += extinction * (t - t0);
// We consider the lighting (and the volume properties) to be constant along the interval (within the voxel).
totalRadiance += (transmittance * IsotropicPhaseFunction()) * scattering * sampleRadiance;
_VolumetricLightingBufferCurrentFrame[uint3(voxelCoord, s)] = float4(totalRadiance, opticalDepth);
_VBufferLighting[uint3(voxelCoord, s)] = float4(totalRadiance, opticalDepth);
// Compute optical depth up to the end of the interval.
opticalDepth += extinction * (0.5 * dt);
// Compute the optical depth up to the end of the interval.
opticalDepth += extinction * (t1 - t);
int GetLog2NumVoxelsPerLightTile()
{
// Assume that the light tile size is an base-2 multiple of the voxel tile size.
return (int)log2(GetTileSize()) - (int)_vBufferResolution.w;
}
uint waveIndex = groupThreadId / 64;
uint waveIndex = WaveReadFirstLane(groupThreadId / 64);
uint laneIndex = groupThreadId % 64;
uint quadIndex = laneIndex / 4;

uint2 tileAnchor = groupId * GROUP_SIZE_1D;
uint2 voxelCoord = tileAnchor + localCoord;
uint2 tileCoord = tileAnchor >> GetLog2NumVoxelsPerLightTile();
uint2 groupCoord = groupId * GROUP_SIZE_1D;
uint2 voxelCoord = groupCoord + localCoord;
uint2 tileCoord = voxelCoord * VBUFFER_TILE_SIZE / TILE_SIZE_CLUSTERED; // TODO: scalarize
[branch] if (voxelCoord.x >= (uint)_vBufferResolution.x ||
voxelCoord.y >= (uint)_vBufferResolution.y)
[branch] if (voxelCoord.x >= (uint)_VBufferResolutionAndScale.x ||
voxelCoord.y >= (uint)_VBufferResolutionAndScale.y)
// TODO: read the HiZ texture in order to skip evaluation of lighting in occluded voxels.
#ifdef UNITY_REVERSED_Z
// float tileMaxZ = ...
#else
// float tileMaxZ = ...
#endif
// Determine the farthest unoccluded voxel...
// TODO: low-discrepancy point set, mirroring around the bounds of the camera frustum.
// TODO: use a low-discrepancy point set.
// Compute the unnormalized ray direction s.t. its Z coordinate in the view space is equal to 1.
float3 dir = -mul(float3(sampleCoord, 1), (float3x3)_vBufferCoordToViewDirWS);
// Compute the ratio of the length of the vector to its view space Z coordinate.
float len = length(dir);
// Compute the unnormalized ray direction s.t. its ViewSpaceZ = 1.
float3 dir = -mul(float3(sampleCoord, 1), (float3x3)_VBufferCoordToViewDirWS);
cameraRay.directionWS = normalize(dir);
cameraRay.ratioLenToZ = len;
cameraRay.ratioLenToZ = sqrt(dot(dir, dir));
cameraRay.ratioZtoLen = rsqrt(dot(dir, dir));
cameraRay.directionWS = dir * cameraRay.ratioZtoLen;
FillVolumetricLightingBuffer(cameraRay, _vBufferDepthEncodingParams, tileCoord, voxelCoord);
FillVolumetricLightingBuffer(cameraRay, voxelCoord, tileCoord);
}

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


{
public Vector3 scattering; // [0, 1], prefer sRGB
public float extinction; // [0, 1], prefer sRGB
public float asymmetry; // Global (scene) property
public float align16_0;
public float align16_1;
public float align16_2;
public static VolumeProperties GetNeutralVolumeProperties()
{

properties.extinction = 0;
properties.asymmetry = 0;
return properties;
}

public Bounds bounds; // Position and dimensions in meters
public Color albedo; // Single scattering albedo [0, 1]
public float meanFreePath; // In meters [1, inf]. Should be chromatic - this is an optimization!
public float anisotropy; // [-1, 1]; 0 = isotropic
public VolumeParameters()
{

anisotropy = 0.0f;
}
public bool IsVolumeUnbounded()

albedo.b = Mathf.Clamp01(albedo.b);
meanFreePath = Mathf.Max(meanFreePath, 1.0f);
anisotropy = Mathf.Clamp(anisotropy, -1.0f, 1.0f);
}
public VolumeProperties GetProperties()

properties.scattering = GetScatteringCoefficient();
properties.extinction = GetExtinctionCoefficient();
properties.asymmetry = anisotropy;
return properties;
}

{
bool m_VolumetricLightingEnabled = false;
int m_VolumetricBufferTileSize = 4; // In pixels, must be a power of 2
float m_VolumetricBufferMaxFarPlane = 32.0f; // Distance in meters
public enum VolumetricLightingPreset
{
Off,
Normal,
Ultra,
Count
};
RenderTexture m_VolumetricLightingBufferCurrentFrame = null;
RenderTexture m_VolumetricLightingBufferAccumulation = null;
VolumetricLightingPreset m_VolumetricLightingPreset = VolumetricLightingPreset.Normal;
ComputeShader m_VolumetricLightingCS { get { return m_Asset.renderPipelineResources.volumetricLightingCS; } }
RenderTargetIdentifier m_VolumetricLightingBufferCurrentFrameRT;
RenderTargetIdentifier m_VolumetricLightingBufferAccumulationRT;
float m_VBufferNearPlane = 0.5f; // Distance in meters
float m_VBufferFarPlane = 32.0f; // Distance in meters
ComputeShader m_VolumetricLightingCS { get { return m_Asset.renderPipelineResources.volumetricLightingCS; } }
RenderTexture[] m_VBufferLighting = null; // Used for even / odd frames
RenderTargetIdentifier[] m_VBufferLightingRT = null;
void ComputeVolumetricBufferResolution(int screenWidth, int screenHeight, ref int w, ref int h, ref int d)
public static int ComputeVBufferTileSize(VolumetricLightingPreset preset)
int t = m_VolumetricBufferTileSize;
Debug.Assert((t & (t - 1)) == 0, "m_VolumetricBufferTileSize must be a power of 2.");
switch (preset)
{
case VolumetricLightingPreset.Normal:
return 8;
case VolumetricLightingPreset.Ultra:
return 4;
case VolumetricLightingPreset.Off:
return 0;
default:
Debug.Assert(false, "Encountered an unexpected VolumetricLightingPreset.");
return 0;
}
}
// Ceil(ScreenSize / TileSize).
w = (screenWidth + t - 1) / t;
h = (screenHeight + t - 1) / t;
d = 64;
// Cell-centered -> node-centered.
w += 1;
h += 1;
public static int ComputeVBufferSliceCount(VolumetricLightingPreset preset)
{
switch (preset)
{
case VolumetricLightingPreset.Normal:
return 128;
case VolumetricLightingPreset.Ultra:
return 256;
case VolumetricLightingPreset.Off:
return 0;
default:
Debug.Assert(false, "Encountered an unexpected VolumetricLightingPreset.");
return 0;
}
// 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).
Vector4 ComputeVolumetricBufferDepthEncodingParams(float cameraNearPlane, float cameraFarPlane, float sliceCount)
// Since we are rendering tiles of pixels, our VBuffer can potentially extend past the boundaries of the viewport.
// The function returns the fraction of the {width, height} of the VBuffer visible on screen.
Vector2 ComputeVBufferResolutionAndScale(float screenWidth, float screenHeight,
ref int w, ref int h, ref int d)
float n = cameraNearPlane;
float f = Math.Min(cameraFarPlane, m_VolumetricBufferMaxFarPlane);
float s = sliceCount;
int t = ComputeVBufferTileSize(m_VolumetricLightingPreset);
// Cell-centered -> node-centered.
// Remap near and far planes s.t. Depth(n) = 0.5/s and Depth(f) = 1-0.5/s.
float x = Mathf.Pow(n, (s - 0.5f) / (s - 1)) * Mathf.Pow(f, -0.5f / (s - 1));
f = n * f / x;
n = x;
// Ceil(ScreenSize / TileSize).
w = ((int)screenWidth + t - 1) / t;
h = ((int)screenHeight + t - 1) / t;
d = ComputeVBufferSliceCount(m_VolumetricLightingPreset);
Vector4 depthParams = new Vector4();
depthParams.x = n;
depthParams.y = Mathf.Log(f / n, 2);
depthParams.z = 1 / depthParams.x;
depthParams.w = 1 / depthParams.y;
return depthParams;
return new Vector2(screenWidth / (w * t), screenHeight / (h * t));
void CreateVolumetricLightingBuffers(int width, int height)
void CreateVBuffer(int screenWidth, int screenHeight)
if (m_VolumetricLightingBufferAccumulation != null)
if (m_VBufferLighting != null)
{
if (m_VBufferLighting[0] != null) m_VBufferLighting[0].Release();
if (m_VBufferLighting[1] != null) m_VBufferLighting[1].Release();
}
else
m_VolumetricLightingBufferAccumulation.Release();
m_VolumetricLightingBufferCurrentFrame.Release();
m_VBufferLighting = new RenderTexture[2];
m_VBufferLightingRT = new RenderTargetIdentifier[2];
ComputeVolumetricBufferResolution(width, height, ref w, ref h, ref d);
m_VolumetricLightingBufferCurrentFrame = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear); // UAV with ARGBHalf appears to be broken...
m_VolumetricLightingBufferCurrentFrame.filterMode = FilterMode.Bilinear; // Custom trilinear
m_VolumetricLightingBufferCurrentFrame.dimension = TextureDimension.Tex3D; // Prefer 3D Thick tiling layout
m_VolumetricLightingBufferCurrentFrame.volumeDepth = d;
m_VolumetricLightingBufferCurrentFrame.enableRandomWrite = true;
m_VolumetricLightingBufferCurrentFrame.Create();
m_VolumetricLightingBufferCurrentFrameRT = new RenderTargetIdentifier(m_VolumetricLightingBufferCurrentFrame);
ComputeVBufferResolutionAndScale(screenWidth, screenHeight, ref w, ref h, ref d);
m_VolumetricLightingBufferAccumulation = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear); // UAV with ARGBHalf appears to be broken...
m_VolumetricLightingBufferAccumulation.filterMode = FilterMode.Bilinear; // Custom trilinear
m_VolumetricLightingBufferAccumulation.dimension = TextureDimension.Tex3D; // Prefer 3D Thick tiling layout
m_VolumetricLightingBufferAccumulation.volumeDepth = d;
m_VolumetricLightingBufferAccumulation.enableRandomWrite = true;
m_VolumetricLightingBufferAccumulation.Create();
m_VolumetricLightingBufferAccumulationRT = new RenderTargetIdentifier(m_VolumetricLightingBufferAccumulation);
}
void ClearVolumetricLightingBuffers(CommandBuffer cmd, bool isFirstFrame)
{
using (new ProfilingSample(cmd, "Clear volumetric lighting buffers"))
for (int i = 0; i < 2; i++)
CoreUtils.SetRenderTarget(cmd, m_VolumetricLightingBufferCurrentFrameRT, ClearFlag.Color, Color.black);
if (isFirstFrame)
{
CoreUtils.SetRenderTarget(cmd, m_VolumetricLightingBufferAccumulation, ClearFlag.Color, Color.black);
}
m_VBufferLighting[i] = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear); // UAV with ARGBHalf appears to be broken...
m_VBufferLighting[i].filterMode = FilterMode.Bilinear; // Custom trilinear
m_VBufferLighting[i].dimension = TextureDimension.Tex3D; // TODO: request the thick 3D tiling layout
m_VBufferLighting[i].volumeDepth = d;
m_VBufferLighting[i].enableRandomWrite = true;
m_VBufferLighting[i].Create();
m_VBufferLightingRT[i] = new RenderTargetIdentifier(m_VBufferLighting[i]);
// Returns 'true' if the global fog is enabled, 'false' otherwise.
public static bool SetGlobalVolumeProperties(bool volumetricLightingEnabled, CommandBuffer cmd, ComputeShader cs = null)
// Returns 'true' if a global fog component exists.
public static bool SetGlobalVolumeProperties(CommandBuffer cmd, ComputeShader cs = null)
if (volumetricLightingEnabled)
HomogeneousFog[] fogComponents = Object.FindObjectsOfType(typeof(HomogeneousFog)) as HomogeneousFog[];
foreach (HomogeneousFog fogComponent in fogComponents)
HomogeneousFog[] fogComponents = Object.FindObjectsOfType(typeof(HomogeneousFog)) as HomogeneousFog[];
foreach (HomogeneousFog fogComponent in fogComponents)
if (fogComponent.enabled && fogComponent.volumeParameters.IsVolumeUnbounded())
if (fogComponent.enabled && fogComponent.volumeParameters.IsVolumeUnbounded())
{
globalFogComponent = fogComponent;
break;
}
globalFogComponent = fogComponent;
break;
}
}

{
cmd.SetComputeVectorParam(cs, HDShaderIDs._GlobalFog_Scattering, globalFogProperties.scattering);
cmd.SetComputeFloatParam( cs, HDShaderIDs._GlobalFog_Extinction, globalFogProperties.extinction);
cmd.SetComputeFloatParam( cs, HDShaderIDs._GlobalFog_Asymmetry, globalFogProperties.asymmetry);
cmd.SetGlobalFloat( HDShaderIDs._GlobalFog_Asymmetry, globalFogProperties.asymmetry);
public void SetVolumetricLightingData(bool volumetricLightingEnabled, CommandBuffer cmd, HDCamera camera, ComputeShader cs = null, int kernel = 0)
// 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).
public static Vector4 ComputeLogarithmicDepthEncodingParams(float nearPlane, float farPlane)
SetGlobalVolumeProperties(volumetricLightingEnabled, cmd, cs);
Vector4 depthParams = new Vector4();
float n = nearPlane;
float f = farPlane;
depthParams.x = n;
depthParams.y = Mathf.Log(f / n, 2);
depthParams.z = 1 / depthParams.x;
depthParams.w = 1 / depthParams.y;
return depthParams;
}
public void SetVolumetricLightingData(HDCamera camera, CommandBuffer cmd, ComputeShader cs = null, int kernel = 0)
{
SetGlobalVolumeProperties(cmd, cs);
// Compute dimensions of the buffer.
ComputeVolumetricBufferResolution((int)camera.screenSize.x, (int)camera.screenSize.y, ref w, ref h, ref d);
Vector4 resolution = new Vector4(w, h, d, Mathf.Log(m_VolumetricBufferTileSize, 2));
Vector2 scale = ComputeVBufferResolutionAndScale(camera.screenSize.x, camera.screenSize.y, ref w, ref h, ref d);
// Compute custom near and far flipping planes of the volumetric lighting buffer.
Vector4 depthParams = ComputeVolumetricBufferDepthEncodingParams(camera.camera.nearClipPlane, camera.camera.farClipPlane, d);
Vector4 resAndScale = new Vector4(w, h, scale.x, scale.y);
Vector4 depthParams = ComputeLogarithmicDepthEncodingParams(m_VBufferNearPlane, m_VBufferFarPlane);
cmd.SetComputeVectorParam( cs, HDShaderIDs._vBufferResolution, resolution);
cmd.SetComputeVectorParam( cs, HDShaderIDs._vBufferDepthEncodingParams, depthParams);
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._VolumetricLightingBuffer, m_VolumetricLightingBufferCurrentFrameRT);
cmd.SetComputeVectorParam( cs, HDShaderIDs._VBufferResolutionAndScale, resAndScale);
cmd.SetComputeVectorParam( cs, HDShaderIDs._VBufferDepthEncodingParams, depthParams);
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._VBufferLighting, m_VBufferLightingRT[0]);
cmd.SetGlobalVector( HDShaderIDs._vBufferResolution, resolution);
cmd.SetGlobalVector( HDShaderIDs._vBufferDepthEncodingParams, depthParams);
cmd.SetGlobalTexture(HDShaderIDs._VolumetricLightingBuffer, m_VolumetricLightingBufferCurrentFrameRT);
cmd.SetGlobalVector( HDShaderIDs._VBufferResolutionAndScale, resAndScale);
cmd.SetGlobalVector( HDShaderIDs._VBufferDepthEncodingParams, depthParams);
cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, m_VBufferLightingRT[0]);
public static void SetVolumetricLightingDataFromGlobals(CommandBuffer cmd, ComputeShader cs, int kernel)
{
SetGlobalVolumeProperties(cmd, cs);
cmd.SetComputeVectorParam( cs, HDShaderIDs._VBufferResolutionAndScale, Shader.GetGlobalVector( HDShaderIDs._VBufferResolutionAndScale));
cmd.SetComputeVectorParam( cs, HDShaderIDs._VBufferDepthEncodingParams, Shader.GetGlobalVector( HDShaderIDs._VBufferDepthEncodingParams));
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._VBufferLighting, Shader.GetGlobalTexture(HDShaderIDs._VBufferLighting));
}
if (!SetGlobalVolumeProperties(m_VolumetricLightingEnabled, cmd, m_VolumetricLightingCS)) { return; }
if (m_VolumetricLightingPreset == VolumetricLightingPreset.Off) return;
using (new ProfilingSample(cmd, "VolumetricLighting"))
using (new ProfilingSample(cmd, "Volumetric Lighting"))
bool enableClustered = m_Asset.tileSettings.enableClustered && m_Asset.tileSettings.enableTileAndCluster;
bool hasGlobalVolume = SetGlobalVolumeProperties(cmd, m_VolumetricLightingCS);
if (!hasGlobalVolume)
{
// Clear the render target instead of running the shader.
CoreUtils.SetRenderTarget(cmd, m_VBufferLightingRT[0], ClearFlag.Color, Color.black);
return;
}
int volumetricLightingKernel = m_VolumetricLightingCS.FindKernel(enableClustered ? "VolumetricLightingClustered"
: "VolumetricLightingAllLights");
// Compute dimensions of the buffer.
bool enableClustered = m_Asset.tileSettings.enableClustered && m_Asset.tileSettings.enableTileAndCluster;
int kernel = m_VolumetricLightingCS.FindKernel(enableClustered ? "VolumetricLightingClustered"
: "VolumetricLightingAllLights");
ComputeVolumetricBufferResolution((int)camera.screenSize.x, (int)camera.screenSize.y, ref w, ref h, ref d);
Vector4 resolution = new Vector4(w, h, d, Mathf.Log(m_VolumetricBufferTileSize, 2));
Vector2 scale = ComputeVBufferResolutionAndScale(camera.screenSize.x, camera.screenSize.y, ref w, ref h, ref d);
// Compute custom near and far flipping planes of the volumetric lighting buffer.
Vector4 depthParams = ComputeVolumetricBufferDepthEncodingParams(camera.camera.nearClipPlane, camera.camera.farClipPlane, d);
// Cell-centered -> node-centered.
float vFoV = camera.camera.fieldOfView * Mathf.Deg2Rad;
vFoV = 2 * Mathf.Atan(Mathf.Tan(0.5f * vFoV) * h / (h - 1));
Vector4 resAndScale = new Vector4(w, h, scale.x, scale.y);
Vector4 depthParams = ComputeLogarithmicDepthEncodingParams(m_VBufferNearPlane, m_VBufferFarPlane);
float vFoV = camera.camera.fieldOfView * Mathf.Deg2Rad;
Matrix4x4 transform = SkyManager.ComputePixelCoordToWorldSpaceViewDirectionMatrix(vFoV, new Vector4(w, h, 1.0f / w, 1.0f / h), camera.viewMatrix, false);
// Compute it using the scaled resolution to account for the visible area of the VBuffer.
Vector4 scaledRes = new Vector4(w * scale.x, h * scale.y, 1.0f / (w * scale.x), 1.0f / (h * scale.y));
Matrix4x4 transform = SkyManager.ComputePixelCoordToWorldSpaceViewDirectionMatrix(vFoV, scaledRes, camera.viewMatrix, false);
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._vBufferResolution, resolution);
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._vBufferDepthEncodingParams, depthParams);
cmd.SetComputeMatrixParam( m_VolumetricLightingCS, HDShaderIDs._vBufferCoordToViewDirWS, transform);
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._Time, Shader.GetGlobalVector(HDShaderIDs._Time));
cmd.SetComputeTextureParam(m_VolumetricLightingCS, volumetricLightingKernel, HDShaderIDs._VolumetricLightingBufferCurrentFrame, m_VolumetricLightingBufferCurrentFrameRT);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, volumetricLightingKernel, HDShaderIDs._VolumetricLightingBufferAccumulation, m_VolumetricLightingBufferAccumulationRT);
// TODO: set 'm_VolumetricLightingPreset'.
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._Time, Shader.GetGlobalVector(HDShaderIDs._Time));
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._VBufferResolutionAndScale, resAndScale);
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._VBufferDepthEncodingParams, depthParams);
cmd.SetComputeMatrixParam( m_VolumetricLightingCS, HDShaderIDs._VBufferCoordToViewDirWS, transform);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLighting, m_VBufferLightingRT[0]);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingPrev, m_VBufferLightingRT[1]);
// Pass clustered light data (if present) to the compute shader.
m_LightLoop.PushGlobalParams(camera.camera, cmd, m_VolumetricLightingCS, volumetricLightingKernel, true);
cmd.SetComputeIntParam(m_VolumetricLightingCS, HDShaderIDs._UseTileLightList, 0);
// Pass the light data to the compute shader.
m_LightLoop.PushGlobalParams(camera.camera, cmd, m_VolumetricLightingCS, kernel, true);
cmd.DispatchCompute(m_VolumetricLightingCS, volumetricLightingKernel, (w + 15) / 16, (h + 15) / 16, 1);
// The shader defines GROUP_SIZE_1D = 16.
cmd.DispatchCompute(m_VolumetricLightingCS, kernel, (w + 15) / 16, (h + 15) / 16, 1);
}
}
} // class HDRenderPipeline

22
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs.hlsl


//
// This file was automatically generated from Assets/SRP/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs. Please don't edit by hand.
// This file was automatically generated. Please don't edit by hand.
//
#ifndef VOLUMETRICLIGHTING_CS_HLSL

{
float3 scattering;
float extinction;
float asymmetry;
float align16_0;
float align16_1;
float align16_2;
};
//

float GetExtinction(VolumeProperties value)
{
return value.extinction;
}
float GetAsymmetry(VolumeProperties value)
{
return value.asymmetry;
}
float GetAlign16_0(VolumeProperties value)
{
return value.align16_0;
}
float GetAlign16_1(VolumeProperties value)
{
return value.align16_1;
}
float GetAlign16_2(VolumeProperties value)
{
return value.align16_2;
}

15
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


#ifndef USE_LEGACY_UNITY_SHADER_VARIABLES
#define VOLUMETRIC_LIGHTING_ENABLED
#endif
//-----------------------------------------------------------------------------
// SurfaceData and BSDFData
//-----------------------------------------------------------------------------

#include "SubsurfaceScatteringSettings.cs.hlsl"
// Enables attenuation of light source contributions by participating media (fog).
#define VOLUMETRIC_SHADOWING_ENABLED
#ifdef VOLUMETRIC_SHADOWING_ENABLED
#ifdef VOLUMETRIC_LIGHTING_ENABLED
// Apparently, not all shaders include "ShaderVariables.hlsl".
#include "../../ShaderVariables.hlsl"
#include "../../../Core/ShaderLibrary/VolumeRendering.hlsl"

float3 transmissionTransmittance; // transmittance due to absorption
float transmissionSSMipLevel; // mip level of the screen space gaussian pyramid for rough refraction
#ifdef VOLUMETRIC_SHADOWING_ENABLED
#ifdef VOLUMETRIC_LIGHTING_ENABLED
float globalFogExtinction;
#endif
};

preLightData.ltcMagnitudeFresnel = bsdfData.fresnel0 * ltcGGXFresnelMagnitudeDiff + (float3)ltcGGXFresnelMagnitude;
}
#ifdef VOLUMETRIC_SHADOWING_ENABLED
#ifdef VOLUMETRIC_LIGHTING_ENABLED
preLightData.globalFogExtinction = _GlobalFog_Extinction;
#endif

illuminance *= shadow;
}
#ifdef VOLUMETRIC_SHADOWING_ENABLED
#ifdef VOLUMETRIC_LIGHTING_ENABLED
float volumetricShadow = Transmittance(OpticalDepthHomogeneous(preLightData.globalFogExtinction, dist));
// Premultiply.

8
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/SubsurfaceScattering.compute


// Arrange threads in the Morton order to optimally match the memory layout of GCN tiles.
uint mortonCode = groupThreadId;
uint2 localCoord = DecodeMorton2D(mortonCode);
uint2 tileAnchor = groupId * GROUP_SIZE_1D;
uint2 pixelCoord = tileAnchor + localCoord;
int2 cacheAnchor = (int2)tileAnchor - TEXTURE_CACHE_BORDER;
uint2 groupCoord = groupId * GROUP_SIZE_1D;
uint2 pixelCoord = groupCoord + localCoord;
int2 cacheAnchor = (int2)groupCoord - TEXTURE_CACHE_BORDER;
uint2 cacheCoord = localCoord + TEXTURE_CACHE_BORDER;
float stencilRef = STENCILLIGHTINGUSAGE_SPLIT_LIGHTING;

}
uint2 cacheCoord2 = 2 * (startQuad + quadCoord) + uint2(laneIndex & 1, (laneIndex >> 1) & 1);
int2 pixelCoord2 = (int2)(tileAnchor + cacheCoord2) - TEXTURE_CACHE_BORDER;
int2 pixelCoord2 = (int2)(groupCoord + cacheCoord2) - TEXTURE_CACHE_BORDER;
float4 cachedValue2 = 0;
[branch] if (StencilTest(pixelCoord2, stencilRef))

2
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringSettings.cs.hlsl


// UnityEngine.Experimental.Rendering.HDPipeline.SssConstants: static fields
//
#define SSS_N_PROFILES (16)
#define SSS_NEUTRAL_PROFILE_ID (15)
#define SSS_NEUTRAL_PROFILE_ID (0)
#define SSS_N_SAMPLES_NEAR_FIELD (55)
#define SSS_N_SAMPLES_FAR_FIELD (21)
#define SSS_LOD_THRESHOLD (4)

8
ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl


// Volumetric lighting. Should be a struct in 'UnityPerFrame'.
// Unfortunately, structures inside constant buffers are not supported by Unity.
float4 _vBufferDepthEncodingParams; // { n, log2(f/n), 1/n, 1/log2(f/n) }
float4 _vBufferResolution; // { w, h, sliceCount = 64, log2(vBufferTileSize) }
float _GlobalFog_Asymmetry;
float _GlobalFog_Align16_0;
float _GlobalFog_Align16_1;
float _GlobalFog_Align16_2;
float4 _VBufferDepthEncodingParams; // { n, log2(f/n), 1/n, 1/log2(f/n) }
float4 _VBufferResolutionAndScale; // { w, h, fracVisW, fracVisH }
CBUFFER_END
// ----------------------------------------------------------------------------

正在加载...
取消
保存