diff --git a/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2008_Light_Volumetrics/2008_Light_Volumetrics_Volume.asset b/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2008_Light_Volumetrics/2008_Light_Volumetrics_Volume.asset
index e1166fcdef7..7f5daca687c 100644
--- a/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2008_Light_Volumetrics/2008_Light_Volumetrics_Volume.asset
+++ b/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/2x_Lighting/2008_Light_Volumetrics/2008_Light_Volumetrics_Volume.asset
@@ -104,6 +104,16 @@ MonoBehaviour:
m_Value: 0.75
min: 0
max: 1
+ screenResolutionPercentage:
+ m_OverrideState: 1
+ m_Value: 25
+ min: 6.25
+ max: 100
+ volumeSliceCount:
+ m_OverrideState: 1
+ m_Value: 128
+ min: 1
+ max: 1024
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
diff --git a/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5001_Fog_FogFallback/Volume_Base.asset b/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5001_Fog_FogFallback/Volume_Base.asset
index bebc4807d79..c23d19c35dd 100644
--- a/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5001_Fog_FogFallback/Volume_Base.asset
+++ b/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5001_Fog_FogFallback/Volume_Base.asset
@@ -198,6 +198,16 @@ MonoBehaviour:
m_Value: 0.75
min: 0
max: 1
+ screenResolutionPercentage:
+ m_OverrideState: 1
+ m_Value: 25
+ min: 6.25
+ max: 100
+ volumeSliceCount:
+ m_OverrideState: 1
+ m_Value: 128
+ min: 1
+ max: 1024
--- !u!114 &3474294613101294443
MonoBehaviour:
m_ObjectHideFlags: 3
diff --git a/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5002_Fog_DensityVolumes/Scene Settings Profile.asset b/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5002_Fog_DensityVolumes/Scene Settings Profile.asset
index aaf923a2a14..0fecf7ac517 100644
--- a/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5002_Fog_DensityVolumes/Scene Settings Profile.asset
+++ b/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5002_Fog_DensityVolumes/Scene Settings Profile.asset
@@ -81,6 +81,16 @@ MonoBehaviour:
m_Value: 0.75
min: 0
max: 1
+ screenResolutionPercentage:
+ m_OverrideState: 1
+ m_Value: 25
+ min: 6.25
+ max: 100
+ volumeSliceCount:
+ m_OverrideState: 1
+ m_Value: 128
+ min: 1
+ max: 1024
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
diff --git a/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5003_Fog_DensityVolumesShadows/Scene Settings Profile.asset b/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5003_Fog_DensityVolumesShadows/Scene Settings Profile.asset
index 5c62f69d04a..e3d3d9ec426 100644
--- a/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5003_Fog_DensityVolumesShadows/Scene Settings Profile.asset
+++ b/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5003_Fog_DensityVolumesShadows/Scene Settings Profile.asset
@@ -254,3 +254,13 @@ MonoBehaviour:
m_Value: 1
min: 0
max: 1
+ screenResolutionPercentage:
+ m_OverrideState: 1
+ m_Value: 25
+ min: 6.25
+ max: 100
+ volumeSliceCount:
+ m_OverrideState: 1
+ m_Value: 128
+ min: 1
+ max: 1024
diff --git a/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5008_FogFiltering/Sky and Fog Settings Profile.asset b/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5008_FogFiltering/Sky and Fog Settings Profile.asset
index b0cb6de3bc0..53e4a07064e 100644
--- a/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5008_FogFiltering/Sky and Fog Settings Profile.asset
+++ b/TestProjects/HDRP_Tests/Assets/GraphicTests/Scenes/5x_SkyAndFog/5008_FogFiltering/Sky and Fog Settings Profile.asset
@@ -81,6 +81,16 @@ MonoBehaviour:
m_Value: 0.75
min: 0
max: 1
+ screenResolutionPercentage:
+ m_OverrideState: 1
+ m_Value: 25
+ min: 6.25
+ max: 100
+ volumeSliceCount:
+ m_OverrideState: 1
+ m_Value: 128
+ min: 1
+ max: 1024
filter:
m_OverrideState: 1
m_Value: 1
diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md
index 99a9213d17e..71b6e1ad214 100644
--- a/com.unity.render-pipelines.high-definition/CHANGELOG.md
+++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md
@@ -110,6 +110,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added alpha channel support in motion blur pass.
- Added the HDRP Compositor Tool (in Preview).
- Added a ray tracing mode option in the HDRP asset that allows to override and shader stripping.
+- Added support for arbitrary resolution scaling of Volumetric Lighting to the Fog volume component.
### Fixed
- Fix when rescale probe all direction below zero (1219246)
@@ -662,6 +663,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Raytracing: Remove the LOD cross fade multi compile for ray tracing.
- Cookie are now supported in lightmaper. All lights casting cookie and baked will now include cookie influence.
- Avoid building the mip chain a second time for SSR for transparent objects.
+- Replaced "High Quality" Subsurface Scattering with a set of Quality Levels.
+- Replaced "High Quality" Volumetric Lighting with "Screen Resolution Percentage" and "Volume Slice Count" on the Fog volume component.
## [7.1.1] - 2019-09-05
diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs
index 4eab7c8ec18..0d118994ec2 100644
--- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs
+++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs
@@ -865,13 +865,6 @@ static void Drawer_SectionLightingUnsorted(SerializedHDRenderPipelineAsset seria
EditorGUILayout.PropertyField(serialized.renderPipelineSettings.supportSSAO, Styles.supportSSAOContent);
EditorGUILayout.PropertyField(serialized.renderPipelineSettings.supportVolumetrics, Styles.supportVolumetricContent);
- using (new EditorGUI.DisabledScope(serialized.renderPipelineSettings.supportVolumetrics.hasMultipleDifferentValues
- || !serialized.renderPipelineSettings.supportVolumetrics.boolValue))
- {
- ++EditorGUI.indentLevel;
- EditorGUILayout.PropertyField(serialized.renderPipelineSettings.increaseResolutionOfVolumetrics, Styles.volumetricResolutionContent);
- --EditorGUI.indentLevel;
- }
EditorGUILayout.PropertyField(serialized.renderPipelineSettings.supportProbeVolume, Styles.supportProbeVolumeContent);
using (new EditorGUI.DisabledScope(!serialized.renderPipelineSettings.supportProbeVolume.boolValue))
diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedRenderPipelineSettings.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedRenderPipelineSettings.cs
index a5f94e16815..e5cef881cb6 100644
--- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedRenderPipelineSettings.cs
+++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedRenderPipelineSettings.cs
@@ -26,7 +26,6 @@ class SerializedRenderPipelineSettings
public SerializedScalableSetting sssSampleBudget;
[FormerlySerializedAs("supportVolumetric")]
public SerializedProperty supportVolumetrics;
- public SerializedProperty increaseResolutionOfVolumetrics;
public SerializedProperty supportLightLayers;
public SerializedProperty lightLayerName0;
public SerializedProperty lightLayerName1;
@@ -88,7 +87,6 @@ public SerializedRenderPipelineSettings(SerializedProperty root)
supportSubsurfaceScattering = root.Find((RenderPipelineSettings s) => s.supportSubsurfaceScattering);
sssSampleBudget = new SerializedScalableSetting(root.Find((RenderPipelineSettings s) => s.sssSampleBudget));
supportVolumetrics = root.Find((RenderPipelineSettings s) => s.supportVolumetrics);
- increaseResolutionOfVolumetrics = root.Find((RenderPipelineSettings s) => s.increaseResolutionOfVolumetrics);
supportLightLayers = root.Find((RenderPipelineSettings s) => s.supportLightLayers);
lightLayerName0 = root.Find((RenderPipelineSettings s) => s.lightLayerName0);
lightLayerName1 = root.Find((RenderPipelineSettings s) => s.lightLayerName1);
diff --git a/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs b/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs
index ce918bb696b..9626b33834f 100644
--- a/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs
+++ b/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs
@@ -25,6 +25,8 @@ class FogEditor : VolumeComponentEditor
protected SerializedDataParameter m_EnableVolumetricFog;
protected SerializedDataParameter m_DepthExtent;
protected SerializedDataParameter m_SliceDistributionUniformity;
+ protected SerializedDataParameter m_ScreenResolutionPercentage;
+ protected SerializedDataParameter m_VolumeSliceCount;
protected SerializedDataParameter m_Filter;
static GUIContent s_Enabled = new GUIContent("Enable", "Check this to enable fog in your scene.");
@@ -61,6 +63,8 @@ public override void OnEnable()
m_EnableVolumetricFog = Unpack(o.Find(x => x.enableVolumetricFog));
m_DepthExtent = Unpack(o.Find(x => x.depthExtent));
m_SliceDistributionUniformity = Unpack(o.Find(x => x.sliceDistributionUniformity));
+ m_ScreenResolutionPercentage = Unpack(o.Find(x => x.screenResolutionPercentage));
+ m_VolumeSliceCount = Unpack(o.Find(x => x.volumeSliceCount));
m_Filter = Unpack(o.Find(x => x.filter));
}
@@ -117,6 +121,8 @@ public override void OnInspectorGUI()
{
PropertyField(m_DepthExtent);
PropertyField(m_SliceDistributionUniformity);
+ PropertyField(m_ScreenResolutionPercentage);
+ PropertyField(m_VolumeSliceCount);
PropertyField(m_Filter);
}
diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/AtmosphericScattering.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/AtmosphericScattering.hlsl
index 12e38ac1d75..dabaf8b19cd 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/AtmosphericScattering.hlsl
+++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/AtmosphericScattering.hlsl
@@ -14,6 +14,8 @@
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl"
#endif
+TEXTURE3D(_VBufferLighting);
+
float3 ExpLerp(float3 A, float3 B, float t, float x, float y)
{
// Remap t: (exp(10 k t) - 1) / (exp(10 k) - 1) = exp(x t) y - y.
@@ -276,14 +278,14 @@ void EvaluateAtmosphericScattering(PositionInputs posInput, float3 V, out float3
if (_EnableVolumetricFog != 0)
{
float4 value = SampleVBuffer(TEXTURE3D_ARGS(_VBufferLighting, s_linear_clamp_sampler),
- posInput.positionNDC,
- fogFragDist,
- _VBufferViewportSize,
- _VBufferSharedUvScaleAndLimit.xy,
- _VBufferSharedUvScaleAndLimit.zw,
- _VBufferDistanceEncodingParams,
- _VBufferDistanceDecodingParams,
- true, false);
+ posInput.positionNDC,
+ fogFragDist,
+ _VBufferViewportSize,
+ _VBufferLightingViewportScale.xyz,
+ _VBufferLightingViewportLimit.xyz,
+ _VBufferDistanceEncodingParams,
+ _VBufferDistanceDecodingParams,
+ true, false);
// TODO: add some slowly animated noise (dither?) to the reconstructed value.
// TODO: re-enable tone mapping after implementing pre-exposure.
diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/Fog.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/Fog.cs
index cdf05918aec..7acdd1647a1 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/Fog.cs
+++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/Fog.cs
@@ -60,6 +60,13 @@ public class Fog : VolumeComponent
/// Controls the distribution of slices along the Camera's focal axis. 0 is exponential distribution and 1 is linear distribution.
[Tooltip("Controls the distribution of slices along the Camera's focal axis. 0 is exponential distribution and 1 is linear distribution.")]
public ClampedFloatParameter sliceDistributionUniformity = new ClampedFloatParameter(0.75f, 0, 1);
+ /// Resolution of the volumetric buffer (3D texture) along the X and Y axes relative to the resolution of the frame buffer.
+ [Tooltip("Resolution of the volumetric buffer (3D texture) along the X and Y axes relative to the resolution of the frame buffer. " +
+ "Setting it to 12.5% (1/8) means the number of voxels per slice is 1/8^2 = 1/64 = 1.5625% of the resolution of the frame buffer.")]
+ public ClampedFloatParameter screenResolutionPercentage = new ClampedFloatParameter((1.0f/8.0f) * 100, (1.0f/16.0f) * 100, 100);
+ /// Number of slices of the volumetric buffer (3D texture) along the camera's focal axis.
+ [Tooltip("Number of slices of the volumetric buffer (3D texture) along the camera's focal axis.")]
+ public ClampedIntParameter volumeSliceCount = new ClampedIntParameter(64, 1, 1024);
/// Applies a blur to smoothen the volumetric lighting output.
[Tooltip("Applies a blur to smoothen the volumetric lighting output.")]
diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/ShaderVariablesAtmosphericScattering.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/ShaderVariablesAtmosphericScattering.hlsl
index a7a59afb9b5..6908c059203 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/ShaderVariablesAtmosphericScattering.hlsl
+++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/ShaderVariablesAtmosphericScattering.hlsl
@@ -1,4 +1,3 @@
-TEXTURE3D(_VBufferLighting);
TEXTURECUBE_ARRAY(_SkyTexture);
#define _MipFogNear _MipFogParameters.x
diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VBuffer.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VBuffer.hlsl
index 1bfd11ee33b..8db97933abf 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VBuffer.hlsl
+++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VBuffer.hlsl
@@ -9,15 +9,15 @@
// This means storing tone mapped radiance and transmittance instead of optical depth.
// See "A Fresh Look at Generalized Sampling", p. 51.
//
-// if (clampToBorder), samples outside of the buffer return 0 (we perform a smooth fade).
+// if (clampToBorder), samples outside of the buffer return 0 (border color).
// Otherwise, the sampler simply clamps the texture coordinate to the edge of the texture.
// Warning: clamping to border may not work as expected with the quadratic filter due to its extent.
float4 SampleVBuffer(TEXTURE3D_PARAM(VBuffer, clampSampler),
float2 positionNDC,
float linearDistance,
float4 VBufferViewportSize,
- float2 VBufferUvScale,
- float2 VBufferUvLimit,
+ float3 VBufferViewportScale,
+ float3 VBufferViewportLimit,
float4 VBufferDistanceEncodingParams,
float4 VBufferDistanceDecodingParams,
bool quadraticFilterXY,
@@ -27,17 +27,19 @@ float4 SampleVBuffer(TEXTURE3D_PARAM(VBuffer, clampSampler),
float2 uv = positionNDC;
float w = EncodeLogarithmicDepthGeneralized(linearDistance, VBufferDistanceEncodingParams);
- bool coordIsInsideFrustum = true;
+ bool coordIsInsideFrustum;
if (clampToBorder)
{
- // Coordinates are always clamped to edge. We just introduce a clipping operation.
+ // Coordinates are always clamped to the edge. We just introduce a clipping operation.
float3 positionCS = float3(uv, w) * 2 - 1;
coordIsInsideFrustum = Max3(abs(positionCS.x), abs(positionCS.y), abs(positionCS.z)) < 1;
}
-
- float4 result = 0;
+ else
+ {
+ coordIsInsideFrustum = true; // No clipping, only clamping
+ }
#if defined(UNITY_STEREO_INSTANCING_ENABLED)
// With XR single-pass, one 3D buffer is used to store all views (split along w)
@@ -51,6 +53,8 @@ float4 SampleVBuffer(TEXTURE3D_PARAM(VBuffer, clampSampler),
w = clamp(w, lowerSliceRange + limitSliceRange, upperSliceRange - limitSliceRange);
#endif
+ float4 result = 0;
+
if (coordIsInsideFrustum)
{
if (quadraticFilterXY)
@@ -62,21 +66,30 @@ float4 SampleVBuffer(TEXTURE3D_PARAM(VBuffer, clampSampler),
float2 weights[2], offsets[2];
BiquadraticFilter(1 - fc, weights, offsets); // Inverse-translate the filter centered around 0.5
- const float2 ssToUv = VBufferViewportSize.zw * VBufferUvScale;
+ // Don't want to pass another shader parameter...
+ const float2 rcpBufDim = VBufferViewportScale.xy * VBufferViewportSize.zw; // (vp_dim / buf_dim) * (1 / vp_dim)
+
+ // And these are the texture coordinates.
+ // TODO: will the compiler eliminate redundant computations?
+ float2 texUv0 = (ic + float2(offsets[0].x, offsets[0].y)) * rcpBufDim; // Top left
+ float2 texUv1 = (ic + float2(offsets[1].x, offsets[0].y)) * rcpBufDim; // Top right
+ float2 texUv2 = (ic + float2(offsets[0].x, offsets[1].y)) * rcpBufDim; // Bottom left
+ float2 texUv3 = (ic + float2(offsets[1].x, offsets[1].y)) * rcpBufDim; // Bottom right
+ float texW = w * VBufferViewportScale.z;
- // The sampler clamps to edge. This takes care of 4 frustum faces out of 6.
- // Due to the RTHandle scaling system, we must take care of the other 2 manually.
+ // The sampler clamps to the edge (so UVWs < 0 are OK).
// TODO: perform per-sample (4, in this case) bilateral filtering, rather than per-pixel. This should reduce leaking.
- result = (weights[0].x * weights[0].y) * SAMPLE_TEXTURE3D_LOD(VBuffer, clampSampler, float3(min((ic + float2(offsets[0].x, offsets[0].y)) * ssToUv, VBufferUvLimit), w), 0) // Top left
- + (weights[1].x * weights[0].y) * SAMPLE_TEXTURE3D_LOD(VBuffer, clampSampler, float3(min((ic + float2(offsets[1].x, offsets[0].y)) * ssToUv, VBufferUvLimit), w), 0) // Top right
- + (weights[0].x * weights[1].y) * SAMPLE_TEXTURE3D_LOD(VBuffer, clampSampler, float3(min((ic + float2(offsets[0].x, offsets[1].y)) * ssToUv, VBufferUvLimit), w), 0) // Bottom left
- + (weights[1].x * weights[1].y) * SAMPLE_TEXTURE3D_LOD(VBuffer, clampSampler, float3(min((ic + float2(offsets[1].x, offsets[1].y)) * ssToUv, VBufferUvLimit), w), 0); // Bottom right
+ result = (weights[0].x * weights[0].y) * SAMPLE_TEXTURE3D_LOD(VBuffer, clampSampler, min(float3(texUv0, texW), VBufferViewportLimit), 0)
+ + (weights[1].x * weights[0].y) * SAMPLE_TEXTURE3D_LOD(VBuffer, clampSampler, min(float3(texUv1, texW), VBufferViewportLimit), 0)
+ + (weights[0].x * weights[1].y) * SAMPLE_TEXTURE3D_LOD(VBuffer, clampSampler, min(float3(texUv2, texW), VBufferViewportLimit), 0)
+ + (weights[1].x * weights[1].y) * SAMPLE_TEXTURE3D_LOD(VBuffer, clampSampler, min(float3(texUv3, texW), VBufferViewportLimit), 0);
}
else
{
- // The sampler clamps to edge. This takes care of 4 frustum faces out of 6.
- // Due to the RTHandle scaling system, we must take care of the other 2 manually.
- result = SAMPLE_TEXTURE3D_LOD(VBuffer, clampSampler, float3(min(uv * VBufferUvScale, VBufferUvLimit), w), 0);
+ // And these are the texture coordinates.
+ float3 texUVW = float3(uv, w) * VBufferViewportScale;
+ // The sampler clamps to the edge (so UVWs < 0 are OK).
+ result = SAMPLE_TEXTURE3D_LOD(VBuffer, clampSampler, min(texUVW, VBufferViewportLimit), 0);
}
}
@@ -88,22 +101,22 @@ float4 SampleVBuffer(TEXTURE3D_PARAM(VBuffer, clampSampler),
float3 cameraPositionWS,
float4x4 viewProjMatrix,
float4 VBufferViewportSize,
- float2 VBufferUvScale,
- float2 VBufferUvLimit,
+ float3 VBufferViewportScale,
+ float3 VBufferViewportLimit,
float4 VBufferDistanceEncodingParams,
float4 VBufferDistanceDecodingParams,
bool quadraticFilterXY,
bool clampToBorder)
{
- float2 positionNDC = ComputeNormalizedDeviceCoordinates(positionWS, viewProjMatrix);
+ float2 positionNDC = ComputeNormalizedDeviceCoordinates(positionWS, viewProjMatrix);
float linearDistance = distance(positionWS, cameraPositionWS);
return SampleVBuffer(TEXTURE3D_ARGS(VBuffer, clampSampler),
positionNDC,
linearDistance,
VBufferViewportSize,
- VBufferUvScale,
- VBufferUvLimit,
+ VBufferViewportScale,
+ VBufferViewportLimit,
VBufferDistanceEncodingParams,
VBufferDistanceDecodingParams,
quadraticFilterXY,
diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumeVoxelization.compute b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumeVoxelization.compute
index 32d1310e27f..a26479a67fd 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumeVoxelization.compute
+++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumeVoxelization.compute
@@ -5,24 +5,18 @@
// #pragma enable_d3d11_debug_symbols
#pragma only_renderers d3d11 playstation xboxone vulkan metal switch
-#pragma kernel VolumeVoxelizationBruteforceMQ VolumeVoxelization=VolumeVoxelizationBruteforceMQ LIGHTLOOP_DISABLE_TILE_AND_CLUSTER VL_PRESET_MQ
-#pragma kernel VolumeVoxelizationTiledMQ VolumeVoxelization=VolumeVoxelizationTiledMQ VL_PRESET_MQ
-#pragma kernel VolumeVoxelizationBruteforceHQ VolumeVoxelization=VolumeVoxelizationBruteforceHQ LIGHTLOOP_DISABLE_TILE_AND_CLUSTER VL_PRESET_HQ
-#pragma kernel VolumeVoxelizationTiledHQ VolumeVoxelization=VolumeVoxelizationTiledHQ VL_PRESET_HQ
+#pragma kernel VolumeVoxelizationBruteforceOptimal VolumeVoxelization=VolumeVoxelizationBruteforceOptimal LIGHTLOOP_DISABLE_TILE_AND_CLUSTER VL_PRESET_OPTIMAL
+#pragma kernel VolumeVoxelizationTiledOptimal VolumeVoxelization=VolumeVoxelizationTiledOptimal VL_PRESET_OPTIMAL
+#pragma kernel VolumeVoxelizationBruteforce VolumeVoxelization=VolumeVoxelizationBruteforce LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
+#pragma kernel VolumeVoxelizationTiled VolumeVoxelization=VolumeVoxelizationTiled
#ifndef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
#define USE_BIG_TILE_LIGHTLIST
#endif
-#ifdef VL_PRESET_MQ
- // E.g. for 1080p: (1920/8)x(1080/8)x(64) = 2,073,600 voxels
- // Same texel count as in a 1080p frame buffer.
- #define VBUFFER_TILE_SIZE 8
-#endif
-#ifdef VL_PRESET_HQ
- // E.g. for 1080p: (1920/4)x(1080/4)x(128) = 16,588,800 voxels
- // Double the texel count of a 4K frame buffer!
- #define VBUFFER_TILE_SIZE 4
+#ifdef VL_PRESET_OPTIMAL
+ // E.g. for 1080p: (1920/8)x(1080/8)x(64) = 2,073,600 voxels
+ #define VBUFFER_VOXEL_SIZE 8
#endif
#define GROUP_SIZE_1D 8
@@ -316,15 +310,21 @@ void VolumeVoxelization(uint3 dispatchThreadId : SV_DispatchThreadID,
uint2 groupId : SV_GroupID,
uint2 groupThreadId : SV_GroupThreadID)
{
- // Perform compile-time checks.
- if (!IsPower2(VBUFFER_TILE_SIZE) || !IsPower2(TILE_SIZE_BIG_TILE)) return;
-
UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z);
uint2 groupOffset = groupId * GROUP_SIZE_1D;
uint2 voxelCoord = groupOffset + groupThreadId;
- uint2 tileCoord = groupOffset * VBUFFER_TILE_SIZE / TILE_SIZE_BIG_TILE;
- uint tileIndex = tileCoord.x + _NumTileBigTileX * tileCoord.y;
+#ifdef VL_PRESET_OPTIMAL
+ // The entire thread group is within the same light tile.
+ uint2 tileCoord = groupOffset * VBUFFER_VOXEL_SIZE / TILE_SIZE_BIG_TILE;
+#else
+ // No compile-time optimizations, no scalarization.
+ // If _VBufferVoxelSize is not a power of 2 or > TILE_SIZE_BIG_TILE, a voxel may straddle
+ // a tile boundary. This means different voxel subsamples may belong to different tiles.
+ // We accept this error, and simply use the coordinates of the center of the voxel.
+ uint2 tileCoord = (uint2)((voxelCoord + 0.5) * _VBufferVoxelSize / TILE_SIZE_BIG_TILE);
+#endif
+ uint tileIndex = tileCoord.x + _NumTileBigTileX * tileCoord.y;
// Reminder: our voxels are sphere-capped right frustums (truncated right pyramids).
// The curvature of the front and back faces is quite gentle, so we can use
diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.compute b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.compute
index 15855d24b24..7874d5c8ad8 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.compute
+++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.compute
@@ -10,7 +10,7 @@
#pragma multi_compile _ LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
#pragma multi_compile _ ENABLE_REPROJECTION
#pragma multi_compile _ ENABLE_ANISOTROPY
-#pragma multi_compile VL_PRESET_MQ VL_PRESET_HQ
+#pragma multi_compile _ VL_PRESET_OPTIMAL
#ifndef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
#define USE_BIG_TILE_LIGHTLIST
@@ -19,23 +19,19 @@
// Don't want contact shadows
#define LIGHT_EVALUATION_NO_CONTACT_SHADOWS // To define before LightEvaluation.hlsl
-#ifdef VL_PRESET_MQ
- // E.g. for 1080p: (1920/8)x(1080/8)x(64) = 2,073,600 voxels
- // Same texel count as in a 1080p frame buffer.
- #define VBUFFER_TILE_SIZE 8
-#endif
-#ifdef VL_PRESET_HQ
- // E.g. for 1080p: (1920/4)x(1080/4)x(128) = 16,588,800 voxels
- // Double the texel count of a 4K frame buffer!
- #define VBUFFER_TILE_SIZE 4
+#ifndef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
+ #define USE_BIG_TILE_LIGHTLIST
#endif
-#define GROUP_SIZE_1D 8
-#define SUPPORT_LOCAL_LIGHTS 1 // Local lights contribute to fog lighting
-
-#define SHADOW_USE_DEPTH_BIAS 0
+#ifdef VL_PRESET_OPTIMAL
+ // E.g. for 1080p: (1920/8)x(1080/8)x(64) = 2,073,600 voxels
+ #define VBUFFER_VOXEL_SIZE 8
+#endif
-#define PREFER_HALF 0
+#define GROUP_SIZE_1D 8
+#define SUPPORT_LOCAL_LIGHTS 1 // Local lights contribute to fog lighting
+#define SHADOW_USE_DEPTH_BIAS 0
+#define PREFER_HALF 0
//--------------------------------------------------------------------------------------------------
// Included headers
@@ -67,9 +63,9 @@
// Inputs & outputs
//--------------------------------------------------------------------------------------------------
-RW_TEXTURE3D(float4, _VBufferLightingIntegral);
-RW_TEXTURE3D(float4, _VBufferLightingFeedback);
-TEXTURE3D(_VBufferLightingHistory);
+RW_TEXTURE3D(float4, _VBufferLighting);
+RW_TEXTURE3D(float4, _VBufferFeedback);
+TEXTURE3D(_VBufferHistory);
TEXTURE3D(_VBufferDensity); // RGB = scattering, A = extinction
//--------------------------------------------------------------------------------------------------
@@ -545,18 +541,18 @@ void FillVolumetricLightingBuffer(LightLoopContext context, uint featureFlags,
#endif
// Reproject the history at 'centerWS'.
- float4 reprojValue = SampleVBuffer(TEXTURE3D_ARGS(_VBufferLightingHistory, s_linear_clamp_sampler),
+ float4 reprojValue = SampleVBuffer(TEXTURE3D_ARGS(_VBufferHistory, s_linear_clamp_sampler),
centerWS,
_PrevCamPosRWS,
UNITY_MATRIX_PREV_VP,
_VBufferPrevViewportSize,
- _VBufferHistoryPrevUvScaleAndLimit.xy,
- _VBufferHistoryPrevUvScaleAndLimit.zw,
- _VBufferPrevDepthEncodingParams,
- _VBufferPrevDepthDecodingParams,
+ _VBufferHistoryViewportScale.xyz,
+ _VBufferHistoryViewportLimit.xyz,
+ _VBufferPrevDistanceEncodingParams,
+ _VBufferPrevDistanceDecodingParams,
false, true) * float4(GetInversePreviousExposureMultiplier().xxx, 1);
- bool reprojSuccess = (_VBufferLightingHistoryIsValid != 0) && (reprojValue.a != 0);
+ bool reprojSuccess = (_VBufferHistoryIsValid != 0) && (reprojValue.a != 0);
if (reprojSuccess)
{
@@ -568,7 +564,7 @@ void FillVolumetricLightingBuffer(LightLoopContext context, uint featureFlags,
// TODO: dynamic lights (which update their position, rotation, cookie or shadow at runtime)
// do not support reprojection and should neither read nor write to the history buffer.
// This will cause them to alias, but it is the only way to prevent ghosting.
- _VBufferLightingFeedback[voxelCoord] = normalizedBlendValue * float4(GetCurrentExposureMultiplier().xxx, 1);
+ _VBufferFeedback[voxelCoord] = normalizedBlendValue * float4(GetCurrentExposureMultiplier().xxx, 1);
float4 linearizedBlendValue = normalizedBlendValue * dt;
float4 blendValue = DelinearizeRGBD(linearizedBlendValue);
@@ -626,7 +622,7 @@ void FillVolumetricLightingBuffer(LightLoopContext context, uint featureFlags,
// This means storing the tone mapped radiance and transmittance instead of optical depth.
// See "A Fresh Look at Generalized Sampling", p. 51.
// TODO: re-enable tone mapping after implementing pre-exposure.
- _VBufferLightingIntegral[voxelCoord] = LinearizeRGBD(float4(/*FastTonemap*/(totalRadiance), opticalDepth)) * float4(GetCurrentExposureMultiplier().xxx, 1);
+ _VBufferLighting[voxelCoord] = LinearizeRGBD(float4(/*FastTonemap*/(totalRadiance), opticalDepth)) * float4(GetCurrentExposureMultiplier().xxx, 1);
// Compute the optical depth up to the end of the interval.
opticalDepth += 0.5 * blendValue.a;
@@ -640,15 +636,21 @@ void VolumetricLighting(uint3 dispatchThreadId : SV_DispatchThreadID,
uint2 groupId : SV_GroupID,
uint2 groupThreadId : SV_GroupThreadID)
{
- // Perform compile-time checks.
- if (!IsPower2(VBUFFER_TILE_SIZE) || !IsPower2(TILE_SIZE_BIG_TILE)) return;
-
UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z);
uint2 groupOffset = groupId * GROUP_SIZE_1D;
uint2 voxelCoord = groupOffset + groupThreadId;
- uint2 tileCoord = groupOffset * VBUFFER_TILE_SIZE / TILE_SIZE_BIG_TILE;
- uint tileIndex = tileCoord.x + _NumTileBigTileX * tileCoord.y;
+#ifdef VL_PRESET_OPTIMAL
+ // The entire thread group is within the same light tile.
+ uint2 tileCoord = groupOffset * VBUFFER_VOXEL_SIZE / TILE_SIZE_BIG_TILE;
+#else
+ // No compile-time optimizations, no scalarization.
+ // If _VBufferVoxelSize is not a power of 2 or > TILE_SIZE_BIG_TILE, a voxel may straddle
+ // a tile boundary. This means different voxel subsamples may belong to different tiles.
+ // We accept this error, and simply use the coordinates of the center of the voxel.
+ uint2 tileCoord = (uint2)((voxelCoord + 0.5) * _VBufferVoxelSize / TILE_SIZE_BIG_TILE);
+#endif
+ uint tileIndex = tileCoord.x + _NumTileBigTileX * tileCoord.y;
// Reminder: our voxels are sphere-capped right frustums (truncated right pyramids).
// The curvature of the front and back faces is quite gentle, so we can use
diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs
index f555a01a0e2..60d4a5d2fe6 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs
+++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs
@@ -25,14 +25,14 @@ public static DensityVolumeEngineData GetNeutralValues()
{
DensityVolumeEngineData data;
- data.scattering = Vector3.zero;
- data.extinction = 0;
- data.textureIndex = -1;
- data.textureTiling = Vector3.one;
- data.textureScroll = Vector3.zero;
- data.rcpPosFaceFade = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
- data.rcpNegFaceFade = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
- data.invertFade = 0;
+ data.scattering = Vector3.zero;
+ data.extinction = 0;
+ data.textureIndex = -1;
+ data.textureTiling = Vector3.one;
+ data.textureScroll = Vector3.zero;
+ data.rcpPosFaceFade = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
+ data.rcpNegFaceFade = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
+ data.invertFade = 0;
data.rcpDistFadeLen = 0;
data.endTimesRcpDistFadeLen = 1;
@@ -49,7 +49,7 @@ unsafe struct ShaderVariablesVolumetric
public float _VBufferUnitDepthTexelSpacing;
public uint _NumVisibleDensityVolumes;
public float _CornetteShanksConstant;
- public uint _VBufferLightingHistoryIsValid;
+ public uint _VBufferHistoryIsValid;
public Vector4 _VBufferSampleOffset;
public Vector4 _VolumeMaskDimensions;
@@ -57,10 +57,15 @@ unsafe struct ShaderVariablesVolumetric
[HLSLArray(7, typeof(Vector4))]
public fixed float _AmbientProbeCoeffs[7 * 4]; // 3 bands of SH, packed, rescaled and convolved with the phase function
+ public float _VBufferVoxelSize;
+ public float _HaveToPad;
+ public float _OtherwiseTheBuffer;
+ public float _IsFilledWithGarbage;
public Vector4 _VBufferPrevViewportSize;
- public Vector4 _VBufferHistoryPrevUvScaleAndLimit;
- public Vector4 _VBufferPrevDepthEncodingParams;
- public Vector4 _VBufferPrevDepthDecodingParams;
+ public Vector4 _VBufferHistoryViewportScale;
+ public Vector4 _VBufferHistoryViewportLimit;
+ public Vector4 _VBufferPrevDistanceEncodingParams;
+ public Vector4 _VBufferPrevDistanceDecodingParams;
// TODO: Remove if equals to the ones in global CB?
public uint _NumTileBigTileX;
@@ -98,36 +103,31 @@ public static Vector3 AlbedoFromMeanFreePathAndScattering(float meanFreePath, Ve
struct DensityVolumeList
{
- public List bounds;
+ public List bounds;
public List density;
}
- enum VolumetricLightingPreset
- {
- Off,
- Medium,
- High,
- Count
- }
-
struct VBufferParameters
{
public Vector3Int viewportSize;
- public Vector4 depthEncodingParams;
- public Vector4 depthDecodingParams;
+ public float voxelSize;
+ public Vector4 depthEncodingParams;
+ public Vector4 depthDecodingParams;
- public VBufferParameters(Vector3Int viewportResolution, float depthExtent, float camNear, float camFar, float camVFoV, float sliceDistributionUniformity)
+ public VBufferParameters(Vector3Int viewportSize, float depthExtent, float camNear, float camFar, float camVFoV,
+ float sliceDistributionUniformity, float voxelSize)
{
- viewportSize = viewportResolution;
+ this.viewportSize = viewportSize;
+ this.voxelSize = voxelSize;
// The V-Buffer is sphere-capped, while the camera frustum is not.
// We always start from the near plane of the camera.
- float aspectRatio = viewportResolution.x / (float)viewportResolution.y;
+ float aspectRatio = viewportSize.x / (float)viewportSize.y;
float farPlaneHeight = 2.0f * Mathf.Tan(0.5f * camVFoV) * camFar;
- float farPlaneWidth = farPlaneHeight * aspectRatio;
+ float farPlaneWidth = farPlaneHeight * aspectRatio;
float farPlaneMaxDim = Mathf.Max(farPlaneWidth, farPlaneHeight);
- float farPlaneDist = Mathf.Sqrt(camFar * camFar + 0.25f * farPlaneMaxDim * farPlaneMaxDim);
+ float farPlaneDist = Mathf.Sqrt(camFar * camFar + 0.25f * farPlaneMaxDim * farPlaneMaxDim);
float nearDist = camNear;
float farDist = Math.Min(nearDist + depthExtent, farPlaneDist);
@@ -139,13 +139,21 @@ public VBufferParameters(Vector3Int viewportResolution, float depthExtent, float
depthDecodingParams = ComputeLogarithmicDepthDecodingParams(nearDist, farDist, c);
}
- internal Vector4 ComputeUvScaleAndLimit(Vector2Int bufferSize)
+ internal Vector3 ComputeViewportScale(Vector3Int bufferSize)
+ {
+ return new Vector3(HDUtils.ComputeViewportScale(viewportSize.x, bufferSize.x),
+ HDUtils.ComputeViewportScale(viewportSize.y, bufferSize.y),
+ HDUtils.ComputeViewportScale(viewportSize.z, bufferSize.z));
+ }
+
+ internal Vector3 ComputeViewportLimit(Vector3Int bufferSize)
{
- // The slice count is fixed for now.
- return HDUtils.ComputeUvScaleAndLimit(new Vector2Int(viewportSize.x, viewportSize.y), bufferSize);
+ return new Vector3(HDUtils.ComputeViewportLimit(viewportSize.x, bufferSize.x),
+ HDUtils.ComputeViewportLimit(viewportSize.y, bufferSize.y),
+ HDUtils.ComputeViewportLimit(viewportSize.z, bufferSize.z));
}
- internal float ComputeLastSliceDistance(int sliceCount)
+ internal float ComputeLastSliceDistance(uint sliceCount)
{
float d = 1.0f - 0.5f / sliceCount;
float ln2 = 0.69314718f;
@@ -189,8 +197,6 @@ static Vector4 ComputeLogarithmicDepthDecodingParams(float nearPlane, float farP
public partial class HDRenderPipeline
{
- VolumetricLightingPreset volumetricLightingPreset = VolumetricLightingPreset.Off;
-
ComputeShader m_VolumeVoxelizationCS = null;
ComputeShader m_VolumetricLightingCS = null;
ComputeShader m_VolumetricLightingFilteringCS = null;
@@ -204,8 +210,8 @@ public partial class HDRenderPipeline
ComputeBuffer m_VisibleVolumeDataBuffer = null;
// These two buffers do not depend on the frameID and are therefore shared by all views.
- RTHandle m_DensityBufferHandle;
- RTHandle m_LightingBufferHandle;
+ RTHandle m_DensityBuffer;
+ RTHandle m_LightingBuffer;
ShaderVariablesVolumetric m_ShaderVariablesVolumetricCB = new ShaderVariablesVolumetric();
@@ -233,88 +239,58 @@ public partial class HDRenderPipeline
Matrix4x4[] m_PixelCoordToViewDirWS;
- void InitializeVolumetricLighting()
+ static internal void SafeDestroy(ref RenderTexture rt)
{
- m_SupportVolumetrics = asset.currentPlatformRenderPipelineSettings.supportVolumetrics;
-
- if (!m_SupportVolumetrics)
- return;
-
- volumetricLightingPreset = asset.currentPlatformRenderPipelineSettings.increaseResolutionOfVolumetrics
- ? VolumetricLightingPreset.High
- : VolumetricLightingPreset.Medium;
-
- m_VolumeVoxelizationCS = defaultResources.shaders.volumeVoxelizationCS;
- m_VolumetricLightingCS = defaultResources.shaders.volumetricLightingCS;
- m_VolumetricLightingFilteringCS = defaultResources.shaders.volumetricLightingFilteringCS;
-
- m_PackedCoeffs = new Vector4[7];
- m_PhaseZH = new ZonalHarmonicsL2();
- m_PhaseZH.coeffs = new float[3];
-
- m_xySeq = new Vector2[7];
-
- m_PixelCoordToViewDirWS = new Matrix4x4[ShaderConfig.s_XrMaxViews];
-
- CreateVolumetricLightingBuffers();
- }
-
- // RTHandleSystem API expects a function that computes the resolution. We define it here.
- // Note that the RTHandleSytem never reduces the size of the render target.
- // Therefore, if this function returns a smaller resolution, the size of the render target will not change.
- Vector2Int ComputeVBufferResolutionXY(Vector2Int screenSize)
- {
- Vector3Int resolution = ComputeVBufferResolution(volumetricLightingPreset, screenSize.x, screenSize.y);
-
- return new Vector2Int(resolution.x, resolution.y);
+ if (rt != null)
+ {
+ rt.Release(); // The texture itself is not destroyed: https://docs.unity3d.com/ScriptReference/RenderTexture.Release.html
+ Object.DestroyImmediate(rt); // Destroy() may not be called from the Edit mode
+ }
}
- void CreateVolumetricLightingBuffers()
+ static internal Vector3Int ComputeVolumetricViewportSize(HDCamera hdCamera, ref float voxelSize)
{
- Debug.Assert(m_VolumetricLightingCS != null);
+ var controller = hdCamera.volumeStack.GetComponent();
+ Debug.Assert(controller != null);
- m_VisibleVolumeBounds = new List();
- m_VisibleVolumeData = new List();
- m_VisibleVolumeBoundsBuffer = new ComputeBuffer(k_MaxVisibleVolumeCount, Marshal.SizeOf(typeof(OrientedBBox)));
- m_VisibleVolumeDataBuffer = new ComputeBuffer(k_MaxVisibleVolumeCount, Marshal.SizeOf(typeof(DensityVolumeEngineData)));
+ int viewportWidth = hdCamera.actualWidth;
+ int viewportHeight = hdCamera.actualHeight;
+ float screenFraction = controller.screenResolutionPercentage.value * 0.01f;
+ int sliceCount = controller.volumeSliceCount.value;
- int d = ComputeVBufferSliceCount(volumetricLightingPreset);
+ int w = Mathf.RoundToInt(viewportWidth * screenFraction);
+ int h = Mathf.RoundToInt(viewportHeight * screenFraction);
+ int d = sliceCount;
- m_DensityBufferHandle = RTHandles.Alloc(scaleFunc: ComputeVBufferResolutionXY,
- slices: d,
- dimension: TextureDimension.Tex3D,
- colorFormat: GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough
- enableRandomWrite: true,
- enableMSAA: false,
- /* useDynamicScale: true, // <- TODO */
- name: "VBufferDensity");
+ if (controller.screenResolutionPercentage.value == (1.0f/8.0f) * 100)
+ voxelSize = 8;
+ else
+ voxelSize = 1.0f / screenFraction; // Does not account for rounding (same function, above)
- m_LightingBufferHandle = RTHandles.Alloc(scaleFunc: ComputeVBufferResolutionXY,
- slices: d,
- dimension: TextureDimension.Tex3D,
- colorFormat: GraphicsFormat.R16G16B16A16_SFloat,
- enableRandomWrite: true,
- enableMSAA: false,
- /* useDynamicScale: true, // <- TODO */
- name: "VBufferIntegral");
+ return new Vector3Int(w, h, d);
}
- // For the initial allocation, no suballocation happens (the texture is full size).
- VBufferParameters ComputeVBufferParameters(HDCamera hdCamera)
+ static internal VBufferParameters ComputeVolumetricBufferParameters(HDCamera hdCamera)
{
- Vector3Int viewportResolution = ComputeVBufferResolution(volumetricLightingPreset, hdCamera.actualWidth, hdCamera.actualHeight);
-
var controller = hdCamera.volumeStack.GetComponent();
+ Debug.Assert(controller != null);
+
+ float voxelSize = 0;
+ Vector3Int viewportSize = ComputeVolumetricViewportSize(hdCamera, ref voxelSize);
- return new VBufferParameters(viewportResolution, controller.depthExtent.value,
+ return new VBufferParameters(viewportSize, controller.depthExtent.value,
hdCamera.camera.nearClipPlane,
hdCamera.camera.farClipPlane,
hdCamera.camera.fieldOfView,
- controller.sliceDistributionUniformity.value);
+ controller.sliceDistributionUniformity.value,
+ voxelSize);
}
- internal void ReinitializeVolumetricBufferParams(HDCamera hdCamera)
+ static internal void ReinitializeVolumetricBufferParams(HDCamera hdCamera)
{
+ if (!Fog.IsVolumetricFogEnabled(hdCamera))
+ return;
+
bool fog = Fog.IsVolumetricFogEnabled(hdCamera);
bool init = hdCamera.vBufferParams != null;
@@ -329,7 +305,7 @@ internal void ReinitializeVolumetricBufferParams(HDCamera hdCamera)
{
// Initialize.
// Start with the same parameters for both frames. Then update them one by one every frame.
- var parameters = ComputeVBufferParameters(hdCamera);
+ var parameters = ComputeVolumetricBufferParameters(hdCamera);
hdCamera.vBufferParams = new VBufferParameters[2];
hdCamera.vBufferParams[0] = parameters;
hdCamera.vBufferParams[1] = parameters;
@@ -339,120 +315,219 @@ internal void ReinitializeVolumetricBufferParams(HDCamera hdCamera)
// This function relies on being called once per camera per frame.
// The results are undefined otherwise.
- internal void UpdateVolumetricBufferParams(HDCamera hdCamera)
+ static internal void UpdateVolumetricBufferParams(HDCamera hdCamera, int frameIndex)
{
if (!Fog.IsVolumetricFogEnabled(hdCamera))
return;
- var parameters = ComputeVBufferParameters(hdCamera);
+ Debug.Assert(hdCamera.vBufferParams != null);
+ Debug.Assert(hdCamera.vBufferParams.Length == 2);
+
+ var currentParams = ComputeVolumetricBufferParameters(hdCamera);
+
+ var currIdx = (frameIndex + 0) & 1;
+ var prevIdx = (frameIndex + 1) & 1;
+
+ hdCamera.vBufferParams[currIdx] = currentParams;
- // Double-buffer. I assume the cost of copying is negligible (don't want to use the frame index).
// Handle case of first frame. When we are on the first frame, we reuse the value of original frame.
- if (hdCamera.vBufferParams[0].viewportSize.x == 0.0f && hdCamera.vBufferParams[0].viewportSize.y == 0.0f)
+ if (hdCamera.vBufferParams[prevIdx].viewportSize.x == 0.0f && hdCamera.vBufferParams[prevIdx].viewportSize.y == 0.0f)
{
- hdCamera.vBufferParams[1] = parameters;
+ hdCamera.vBufferParams[prevIdx] = currentParams;
}
- else
+ }
+
+ // Do not access 'rt.name', it allocates memory every time...
+ // Have to manually cache and pass the name.
+ static internal void ResizeVolumetricBuffer(ref RTHandle rt, string name, int viewportWidth, int viewportHeight, int viewportDepth)
+ {
+ Debug.Assert(rt != null);
+
+ int width = rt.rt.width;
+ int height = rt.rt.height;
+ int depth = rt.rt.volumeDepth;
+
+ bool realloc = (width < viewportWidth) || (height < viewportHeight) || (depth < viewportDepth);
+
+ if (realloc)
{
- hdCamera.vBufferParams[1] = hdCamera.vBufferParams[0];
+ RTHandles.Release(rt);
+
+ width = Math.Max(width, viewportWidth);
+ height = Math.Max(height, viewportHeight);
+ depth = Math.Max(depth, viewportDepth);
+
+ rt = RTHandles.Alloc(width, height, depth, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough
+ dimension: TextureDimension.Tex3D, enableRandomWrite: true, name: name);
}
- hdCamera.vBufferParams[0] = parameters;
}
- internal void AllocateVolumetricHistoryBuffers(HDCamera hdCamera, int bufferCount)
+ static internal void CreateVolumetricHistoryBuffers(HDCamera hdCamera, int bufferCount)
{
- RTHandle HistoryBufferAllocatorFunction(string viewName, int frameIndex, RTHandleSystem rtHandleSystem)
+ if (!Fog.IsVolumetricFogEnabled(hdCamera))
+ return;
+
+ Debug.Assert(hdCamera.volumetricHistoryBuffers == null);
+
+ hdCamera.volumetricHistoryBuffers = new RTHandle[bufferCount];
+
+ // Allocation happens early in the frame. So we shouldn't rely on 'hdCamera.vBufferParams'.
+ // Allocate the smallest possible 3D texture.
+ // We will perform rescaling manually, in a custom manner, based on volume parameters.
+ const int minSize = 4;
+
+ for (int i = 0; i < bufferCount; i++)
{
- frameIndex &= 1; // 0 or 1
-
- int d = ComputeVBufferSliceCount(volumetricLightingPreset);
-
- return rtHandleSystem.Alloc(scaleFunc: ComputeVBufferResolutionXY,
- slices: d,
- dimension: TextureDimension.Tex3D,
- colorFormat: GraphicsFormat.R16G16B16A16_SFloat,
- enableRandomWrite: true,
- enableMSAA: false,
- /* useDynamicScale: true, // <- TODO */
- name: string.Format("{0}_VBufferHistory{1}", viewName, frameIndex)
- );
+ hdCamera.volumetricHistoryBuffers[i] = RTHandles.Alloc(minSize, minSize, minSize, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough
+ dimension: TextureDimension.Tex3D, enableRandomWrite: true, name: string.Format("VBufferHistory{0}", i));
}
- hdCamera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.VolumetricLighting, HistoryBufferAllocatorFunction, bufferCount);
+ hdCamera.volumetricHistoryIsValid = false;
}
- void DestroyVolumetricLightingBuffers()
+ static internal void DestroyVolumetricHistoryBuffers(HDCamera hdCamera)
{
- if (m_DensityBufferHandle != null)
- RTHandles.Release(m_DensityBufferHandle);
- if (m_LightingBufferHandle != null)
- RTHandles.Release(m_LightingBufferHandle);
+ if (hdCamera.volumetricHistoryBuffers == null)
+ return;
- CoreUtils.SafeRelease(m_VisibleVolumeBoundsBuffer);
- CoreUtils.SafeRelease(m_VisibleVolumeDataBuffer);
+ int bufferCount = hdCamera.volumetricHistoryBuffers.Length;
+
+ for (int i = 0; i < bufferCount; i++)
+ {
+ RTHandles.Release(hdCamera.volumetricHistoryBuffers[i]);
+ }
- m_VisibleVolumeBounds = null;
- m_VisibleVolumeData = null;
+ hdCamera.volumetricHistoryBuffers = null;
+ hdCamera.volumetricHistoryIsValid = false;
}
- void CleanupVolumetricLighting()
+ // Must be called AFTER UpdateVolumetricBufferParams.
+ static internal void ResizeVolumetricHistoryBuffers(HDCamera hdCamera, int frameIndex)
{
- // Note: No need to test for support volumetric here, we do saferelease and null assignation
- DestroyVolumetricLightingBuffers();
+ if (!hdCamera.IsVolumetricReprojectionEnabled())
+ return;
- m_VolumeVoxelizationCS = null;
- m_VolumetricLightingCS = null;
- m_VolumetricLightingFilteringCS = null;
- }
+ Debug.Assert(hdCamera.vBufferParams != null);
+ Debug.Assert(hdCamera.vBufferParams.Length == 2);
+ Debug.Assert(hdCamera.volumetricHistoryBuffers != null);
- static int ComputeVBufferTileSize(VolumetricLightingPreset preset)
- {
- switch (preset)
+ var currIdx = (frameIndex + 0) & 1;
+ var prevIdx = (frameIndex + 1) & 1;
+
+ var currentParams = hdCamera.vBufferParams[currIdx];
+
+ // Render texture contents can become "lost" on certain events, like loading a new level,
+ // system going to a screensaver mode, in and out of fullscreen and so on.
+ // https://docs.unity3d.com/ScriptReference/RenderTexture.html
+ if (hdCamera.volumetricHistoryBuffers[0] == null || hdCamera.volumetricHistoryBuffers[1] == null)
{
- case VolumetricLightingPreset.Medium:
- return 8;
- case VolumetricLightingPreset.High:
- return 4;
- case VolumetricLightingPreset.Off:
- return 0;
- default:
- Debug.Assert(false, "Encountered an unexpected VolumetricLightingPreset.");
- return 0;
+ DestroyVolumetricHistoryBuffers(hdCamera);
+ CreateVolumetricHistoryBuffers(hdCamera, hdCamera.vBufferParams.Length); // Basically, assume it's 2
}
+
+ string[] names = new string[2]{ "VBufferHistory0", "VBufferHistory1" };
+
+ // We only resize the feedback buffer (#0), not the history buffer (#1).
+ // We must NOT resize the buffer from the previous frame (#1), as that would invalidate its contents.
+ ResizeVolumetricBuffer(ref hdCamera.volumetricHistoryBuffers[currIdx], names[currIdx], currentParams.viewportSize.x,
+ currentParams.viewportSize.y,
+ currentParams.viewportSize.z);
}
- static int ComputeVBufferSliceCount(VolumetricLightingPreset preset)
+ internal void CreateVolumetricLightingBuffers()
{
- var result = 0;
- switch (preset)
+ Debug.Assert(m_VolumetricLightingCS != null);
+ Debug.Assert(m_DensityBuffer == null);
+ Debug.Assert(m_LightingBuffer == null);
+
+ m_VisibleVolumeBounds = new List();
+ m_VisibleVolumeData = new List();
+ m_VisibleVolumeBoundsBuffer = new ComputeBuffer(k_MaxVisibleVolumeCount, Marshal.SizeOf(typeof(OrientedBBox)));
+ m_VisibleVolumeDataBuffer = new ComputeBuffer(k_MaxVisibleVolumeCount, Marshal.SizeOf(typeof(DensityVolumeEngineData)));
+
+ // Allocate the smallest possible 3D texture.
+ // We will perform rescaling manually, in a custom manner, based on volume parameters.
+ const int minSize = 4;
+
+ m_DensityBuffer = RTHandles.Alloc(minSize, minSize, minSize, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough
+ dimension: TextureDimension.Tex3D, enableRandomWrite: true, name: "VBufferDensity");
+
+ m_LightingBuffer = RTHandles.Alloc(minSize, minSize, minSize, colorFormat: GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough
+ dimension: TextureDimension.Tex3D, enableRandomWrite: true, name: "VBufferLighting");
+ }
+
+ internal void DestroyVolumetricLightingBuffers()
+ {
+ RTHandles.Release(m_LightingBuffer);
+ RTHandles.Release(m_DensityBuffer);
+
+ CoreUtils.SafeRelease(m_VisibleVolumeDataBuffer);
+ CoreUtils.SafeRelease(m_VisibleVolumeBoundsBuffer);
+
+ m_VisibleVolumeData = null; // free()
+ m_VisibleVolumeBounds = null; // free()
+ }
+
+ // Must be called AFTER UpdateVolumetricBufferParams.
+ internal void ResizeVolumetricLightingBuffers(HDCamera hdCamera, int frameIndex)
+ {
+ if (!Fog.IsVolumetricFogEnabled(hdCamera))
+ return;
+
+ Debug.Assert(hdCamera.vBufferParams != null);
+
+ // Render texture contents can become "lost" on certain events, like loading a new level,
+ // system going to a screensaver mode, in and out of fullscreen and so on.
+ // https://docs.unity3d.com/ScriptReference/RenderTexture.html
+ if (m_DensityBuffer == null || m_LightingBuffer == null)
{
- case VolumetricLightingPreset.Medium:
- result = 64;
- break;
- case VolumetricLightingPreset.High:
- result = 128;
- break;
- case VolumetricLightingPreset.Off:
- result = 0;
- break;
- default:
- Debug.Assert(false, "Encountered an unexpected VolumetricLightingPreset.");
- result = 0;
- break;
+ DestroyVolumetricLightingBuffers();
+ CreateVolumetricLightingBuffers();
}
- return result;
+ var currIdx = (frameIndex + 0) & 1;
+ var prevIdx = (frameIndex + 1) & 1;
+
+ var currentParams = hdCamera.vBufferParams[currIdx];
+
+ ResizeVolumetricBuffer(ref m_DensityBuffer, "VBufferDensity", currentParams.viewportSize.x,
+ currentParams.viewportSize.y,
+ currentParams.viewportSize.z);
+ ResizeVolumetricBuffer(ref m_LightingBuffer, "VBufferLighting", currentParams.viewportSize.x,
+ currentParams.viewportSize.y,
+ currentParams.viewportSize.z);
}
- static Vector3Int ComputeVBufferResolution(VolumetricLightingPreset preset, int screenWidth, int screenHeight)
+ void InitializeVolumetricLighting()
{
- int t = ComputeVBufferTileSize(preset);
+ m_SupportVolumetrics = asset.currentPlatformRenderPipelineSettings.supportVolumetrics;
- int w = HDUtils.DivRoundUp(screenWidth, t);
- int h = HDUtils.DivRoundUp(screenHeight, t);
- int d = ComputeVBufferSliceCount(preset);
+ if (!m_SupportVolumetrics)
+ return;
- return new Vector3Int(w, h, d);
+ m_VolumeVoxelizationCS = defaultResources.shaders.volumeVoxelizationCS;
+ m_VolumetricLightingCS = defaultResources.shaders.volumetricLightingCS;
+ m_VolumetricLightingFilteringCS = defaultResources.shaders.volumetricLightingFilteringCS;
+
+ m_PackedCoeffs = new Vector4[7];
+ m_PhaseZH = new ZonalHarmonicsL2();
+ m_PhaseZH.coeffs = new float[3];
+
+ m_xySeq = new Vector2[7];
+
+ m_PixelCoordToViewDirWS = new Matrix4x4[ShaderConfig.s_XrMaxViews];
+
+ CreateVolumetricLightingBuffers();
+ }
+
+ void CleanupVolumetricLighting()
+ {
+ // Note: No need to test for support volumetric here, we do saferelease and null assignation
+ DestroyVolumetricLightingBuffers();
+
+ m_VolumeVoxelizationCS = null;
+ m_VolumetricLightingCS = null;
+ m_VolumetricLightingFilteringCS = null;
}
static float CornetteShanksPhasePartConstant(float anisotropy)
@@ -469,18 +544,35 @@ void UpdateShaderVariablesGlobalVolumetrics(ref ShaderVariablesGlobal cb, in RTH
return;
}
- var currFrameParams = hdCamera.vBufferParams[0];
- var cvp = currFrameParams.viewportSize;
+ // Get the interpolated anisotropy value.
+ var fog = hdCamera.volumeStack.GetComponent();
+ int frameIndex = m_FrameCount;
+ int currIdx = (frameIndex + 0) & 1;
+
+ var currParams = hdCamera.vBufferParams[currIdx];
+
+ // The lighting & density buffers are shared by all cameras.
+ // The history & feedback buffers are specific to the camera.
+ // These 2 types of buffers can have different sizes.
+ // Additionally, history buffers can have different sizes, since they are not resized at the same time.
+ Vector3Int lightingBufferSize = new Vector3Int(m_LightingBuffer.rt.width, m_LightingBuffer.rt.height, m_LightingBuffer.rt.volumeDepth);
+
+ Debug.Assert(m_LightingBuffer.rt.width == m_DensityBuffer.rt.width);
+ Debug.Assert(m_LightingBuffer.rt.height == m_DensityBuffer.rt.height);
+
+ var cvp = currParams.viewportSize;
+
// Adjust slices for XR rendering: VBuffer is shared for all single-pass views
- int sliceCount = cvp.z / hdCamera.viewCount;
+ uint sliceCount = (uint)(cvp.z / hdCamera.viewCount);
cb._VBufferViewportSize = new Vector4(cvp.x, cvp.y, 1.0f / cvp.x, 1.0f / cvp.y);
- cb._VBufferSliceCount = (uint)sliceCount;
+ cb._VBufferSliceCount = sliceCount;
cb._VBufferRcpSliceCount = 1.0f / sliceCount;
- cb._VBufferSharedUvScaleAndLimit = currFrameParams.ComputeUvScaleAndLimit(ComputeVBufferResolutionXY(sharedRTHandleProperties.currentRenderTargetSize));
- cb._VBufferDistanceEncodingParams = currFrameParams.depthEncodingParams;
- cb._VBufferDistanceDecodingParams = currFrameParams.depthDecodingParams;
- cb._VBufferLastSliceDist = currFrameParams.ComputeLastSliceDistance(sliceCount);
+ cb._VBufferLightingViewportScale = currParams.ComputeViewportScale(lightingBufferSize);
+ cb._VBufferLightingViewportLimit = currParams.ComputeViewportLimit(lightingBufferSize);
+ cb._VBufferDistanceEncodingParams = currParams.depthEncodingParams;
+ cb._VBufferDistanceDecodingParams = currParams.depthDecodingParams;
+ cb._VBufferLastSliceDist = currParams.ComputeLastSliceDistance(sliceCount);
cb._VBufferRcpInstancedViewCount = 1.0f / hdCamera.viewCount;
}
@@ -492,7 +584,7 @@ void PushVolumetricLightingGlobalParams(HDCamera hdCamera, CommandBuffer cmd, in
}
else
{
- cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, m_LightingBufferHandle);
+ cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, m_LightingBuffer);
}
}
@@ -596,7 +688,7 @@ unsafe void UpdateShaderVariableslVolumetrics(ref ShaderVariablesVolumetric cb,
cb._VBufferUnitDepthTexelSpacing = HDUtils.ComputZPlaneTexelSpacing(1.0f, vFoV, resolution.y);
cb._NumVisibleDensityVolumes = (uint)m_VisibleVolumeBounds.Count;
cb._CornetteShanksConstant = CornetteShanksPhasePartConstant(fog.anisotropy.value);
- cb._VBufferLightingHistoryIsValid = hdCamera.volumetricHistoryIsValid ? 1u : 0u;
+ cb._VBufferHistoryIsValid = hdCamera.volumetricHistoryIsValid ? 1u : 0u;
GetHexagonalClosePackedSpheres7(m_xySeq);
int sampleIndex = frameIndex % 7;
@@ -618,21 +710,44 @@ unsafe void UpdateShaderVariableslVolumetrics(ref ShaderVariablesVolumetric cb,
SetPreconvolvedAmbientLightProbe(ref cb, hdCamera, fog);
+ var currIdx = (frameIndex + 0) & 1;
+ var prevIdx = (frameIndex + 1) & 1;
+
+ var currParams = hdCamera.vBufferParams[currIdx];
+ var prevParams = hdCamera.vBufferParams[prevIdx];
+
+ var pvp = prevParams.viewportSize;
+
// The lighting & density buffers are shared by all cameras.
// The history & feedback buffers are specific to the camera.
// These 2 types of buffers can have different sizes.
- // Additionally, history buffers can have different sizes, since they are not resized at the same time
- // (every frame, we swap the buffers, and resize the feedback buffer but not the history buffer).
- // The viewport size is the same for all of these buffers.
- // All of these buffers may have sub-native-resolution viewports.
- // The 3rd dimension (number of slices) is the same for all of these buffers.
- var prevFrameParams = hdCamera.vBufferParams[1];
- var pvp = prevFrameParams.viewportSize;
+ // Additionally, history buffers can have different sizes, since they are not resized at the same time.
+ Vector3Int lightingBufferSize = new Vector3Int(m_LightingBuffer.rt.width, m_LightingBuffer.rt.height, m_LightingBuffer.rt.volumeDepth);
+
+ Debug.Assert(m_LightingBuffer.rt.width == m_DensityBuffer.rt.width);
+ Debug.Assert(m_LightingBuffer.rt.height == m_DensityBuffer.rt.height);
+
+ Vector3Int historyBufferSize = Vector3Int.zero;
+
+ if (hdCamera.IsVolumetricReprojectionEnabled())
+ {
+ RTHandle historyRT = hdCamera.volumetricHistoryBuffers[prevIdx];
+
+ historyBufferSize = new Vector3Int(historyRT.rt.width, historyRT.rt.height, historyRT.rt.volumeDepth);
+
+ // Handle case of first frame. When we are on the first frame, we reuse the value of original frame.
+ if (historyBufferSize.x == 0.0f && historyBufferSize.y == 0.0f)
+ {
+ historyBufferSize = lightingBufferSize;
+ }
+ }
+ cb._VBufferVoxelSize = currParams.voxelSize;
cb._VBufferPrevViewportSize = new Vector4(pvp.x, pvp.y, 1.0f / pvp.x, 1.0f / pvp.y);
- cb._VBufferHistoryPrevUvScaleAndLimit = prevFrameParams.ComputeUvScaleAndLimit(ComputeVBufferResolutionXY(hdCamera.historyRTHandleProperties.currentRenderTargetSize));
- cb._VBufferPrevDepthEncodingParams = prevFrameParams.depthEncodingParams;
- cb._VBufferPrevDepthDecodingParams = prevFrameParams.depthDecodingParams;
+ cb._VBufferHistoryViewportScale = prevParams.ComputeViewportScale(historyBufferSize);
+ cb._VBufferHistoryViewportLimit = prevParams.ComputeViewportLimit(historyBufferSize);
+ cb._VBufferPrevDistanceEncodingParams = prevParams.depthEncodingParams;
+ cb._VBufferPrevDistanceDecodingParams = prevParams.depthDecodingParams;
cb._NumTileBigTileX = (uint)GetNumTileBigTileX(hdCamera);
cb._NumTileBigTileY = (uint)GetNumTileBigTileY(hdCamera);
}
@@ -641,14 +756,20 @@ VolumeVoxelizationParameters PrepareVolumeVoxelizationParameters(HDCamera hdCame
{
var parameters = new VolumeVoxelizationParameters();
+ var currIdx = (frameIndex + 0) & 1;
+ var prevIdx = (frameIndex + 1) & 1;
+
+ var currParams = hdCamera.vBufferParams[currIdx];
+
parameters.viewCount = hdCamera.viewCount;
parameters.tiledLighting = HasLightToCull() && hdCamera.frameSettings.IsEnabled(FrameSettingsField.BigTilePrepass);
- bool highQuality = volumetricLightingPreset == VolumetricLightingPreset.High;
+ bool optimal = currParams.voxelSize == 8;
parameters.voxelizationCS = m_VolumeVoxelizationCS;
- parameters.voxelizationKernel = (parameters.tiledLighting ? 1 : 0) | (highQuality ? 2 : 0);
+ parameters.voxelizationKernel = (parameters.tiledLighting ? 1 : 0) | (!optimal ? 2 : 0);
+
+ var cvp = currParams.viewportSize;
- var cvp = hdCamera.vBufferParams[0].viewportSize;
parameters.resolution = new Vector4(cvp.x, cvp.y, 1.0f / cvp.x, 1.0f / cvp.y);
parameters.volumeAtlas = DensityVolumeManager.manager.volumeAtlas.GetAtlas();
@@ -674,9 +795,9 @@ static void VolumeVoxelizationPass( in VolumeVoxelizationParameters parameters,
if (parameters.tiledLighting)
cmd.SetComputeBufferParam(parameters.voxelizationCS, parameters.voxelizationKernel, HDShaderIDs.g_vBigTileLightList, bigTileLightList);
- cmd.SetComputeTextureParam(parameters.voxelizationCS, parameters.voxelizationKernel, HDShaderIDs._VBufferDensity, densityBuffer);
- cmd.SetComputeBufferParam(parameters.voxelizationCS, parameters.voxelizationKernel, HDShaderIDs._VolumeBounds, visibleVolumeBoundsBuffer);
- cmd.SetComputeBufferParam(parameters.voxelizationCS, parameters.voxelizationKernel, HDShaderIDs._VolumeData, visibleVolumeDataBuffer);
+ cmd.SetComputeTextureParam(parameters.voxelizationCS, parameters.voxelizationKernel, HDShaderIDs._VBufferDensity, densityBuffer);
+ cmd.SetComputeBufferParam( parameters.voxelizationCS, parameters.voxelizationKernel, HDShaderIDs._VolumeBounds, visibleVolumeBoundsBuffer);
+ cmd.SetComputeBufferParam( parameters.voxelizationCS, parameters.voxelizationKernel, HDShaderIDs._VolumeData, visibleVolumeDataBuffer);
cmd.SetComputeTextureParam(parameters.voxelizationCS, parameters.voxelizationKernel, HDShaderIDs._VolumeMaskAtlas, parameters.volumeAtlas);
ConstantBuffer.Push(cmd, parameters.volumetricCB, parameters.voxelizationCS, HDShaderIDs._ShaderVariablesVolumetric);
@@ -694,7 +815,7 @@ void VolumeVoxelizationPass(HDCamera hdCamera, CommandBuffer cmd, int frameIndex
using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.VolumeVoxelization)))
{
var parameters = PrepareVolumeVoxelizationParameters(hdCamera, frameIndex);
- VolumeVoxelizationPass(parameters, m_DensityBufferHandle, m_VisibleVolumeBoundsBuffer, m_VisibleVolumeDataBuffer, m_TileAndClusterData.bigTileLightList, cmd);
+ VolumeVoxelizationPass(parameters, m_DensityBuffer, m_VisibleVolumeBoundsBuffer, m_VisibleVolumeDataBuffer, m_TileAndClusterData.bigTileLightList, cmd);
}
}
@@ -754,6 +875,11 @@ VolumetricLightingParameters PrepareVolumetricLightingParameters(HDCamera hdCame
{
var parameters = new VolumetricLightingParameters();
+ var currIdx = (frameIndex + 0) & 1;
+ var prevIdx = (frameIndex + 1) & 1;
+
+ var currParams = hdCamera.vBufferParams[currIdx];
+
// Get the interpolated anisotropy value.
var fog = hdCamera.volumeStack.GetComponent();
@@ -761,7 +887,7 @@ VolumetricLightingParameters PrepareVolumetricLightingParameters(HDCamera hdCame
parameters.tiledLighting = hdCamera.frameSettings.IsEnabled(FrameSettingsField.BigTilePrepass);
parameters.enableReprojection = hdCamera.IsVolumetricReprojectionEnabled();
bool enableAnisotropy = fog.anisotropy.value != 0;
- bool highQuality = volumetricLightingPreset == VolumetricLightingPreset.High;
+ bool optimal = currParams.voxelSize == 8;
parameters.volumetricLightingCS = m_VolumetricLightingCS;
parameters.volumetricLightingCS.shaderKeywords = null;
@@ -781,22 +907,24 @@ VolumetricLightingParameters PrepareVolumetricLightingParameters(HDCamera hdCame
parameters.volumetricLightingCS.EnableKeyword("ENABLE_ANISOTROPY");
}
- if (highQuality)
+ if (optimal)
{
- parameters.volumetricLightingCS.EnableKeyword("VL_PRESET_HQ");
+ parameters.volumetricLightingCS.EnableKeyword("VL_PRESET_OPTIMAL");
}
else
{
- parameters.volumetricLightingCS.EnableKeyword("VL_PRESET_MQ");
+ parameters.volumetricLightingCS.DisableKeyword("VL_PRESET_OPTIMAL");
}
parameters.volumetricLightingKernel = parameters.volumetricLightingCS.FindKernel("VolumetricLighting");
+
parameters.volumetricLightingFilteringCS = m_VolumetricLightingFilteringCS;
parameters.volumetricFilteringKernelX = parameters.volumetricLightingFilteringCS.FindKernel("FilterVolumetricLightingX");
parameters.volumetricFilteringKernelY = parameters.volumetricLightingFilteringCS.FindKernel("FilterVolumetricLightingY");
- var cvp = hdCamera.vBufferParams[0].viewportSize;
+ var cvp = currParams.viewportSize;
+
parameters.resolution = new Vector4(cvp.x, cvp.y, 1.0f / cvp.x, 1.0f / cvp.y);
parameters.viewCount = hdCamera.viewCount;
parameters.filterVolume = fog.filter.value;
@@ -809,23 +937,23 @@ VolumetricLightingParameters PrepareVolumetricLightingParameters(HDCamera hdCame
}
static void VolumetricLightingPass( in VolumetricLightingParameters parameters,
- RTHandle densityBuffer,
- RTHandle lightingBuffer,
- RTHandle historyRT,
- RTHandle feedbackRT,
- ComputeBuffer bigTileLightList,
- CommandBuffer cmd)
+ RTHandle densityBuffer,
+ RTHandle lightingBuffer,
+ RTHandle historyRT,
+ RTHandle feedbackRT,
+ ComputeBuffer bigTileLightList,
+ CommandBuffer cmd)
{
if (parameters.tiledLighting)
cmd.SetComputeBufferParam(parameters.volumetricLightingCS, parameters.volumetricLightingKernel, HDShaderIDs.g_vBigTileLightList, bigTileLightList);
- cmd.SetComputeTextureParam(parameters.volumetricLightingCS, parameters.volumetricLightingKernel, HDShaderIDs._VBufferDensity, densityBuffer); // Read
- cmd.SetComputeTextureParam(parameters.volumetricLightingCS, parameters.volumetricLightingKernel, HDShaderIDs._VBufferLightingIntegral, lightingBuffer); // Write
+ cmd.SetComputeTextureParam(parameters.volumetricLightingCS, parameters.volumetricLightingKernel, HDShaderIDs._VBufferDensity, densityBuffer); // Read
+ cmd.SetComputeTextureParam(parameters.volumetricLightingCS, parameters.volumetricLightingKernel, HDShaderIDs._VBufferLighting, lightingBuffer); // Write
if (parameters.enableReprojection)
{
- cmd.SetComputeTextureParam(parameters.volumetricLightingCS, parameters.volumetricLightingKernel, HDShaderIDs._VBufferLightingHistory, historyRT); // Read
- cmd.SetComputeTextureParam(parameters.volumetricLightingCS, parameters.volumetricLightingKernel, HDShaderIDs._VBufferLightingFeedback, feedbackRT); // Write
+ cmd.SetComputeTextureParam(parameters.volumetricLightingCS, parameters.volumetricLightingKernel, HDShaderIDs._VBufferHistory, historyRT); // Read
+ cmd.SetComputeTextureParam(parameters.volumetricLightingCS, parameters.volumetricLightingKernel, HDShaderIDs._VBufferFeedback, feedbackRT); // Write
}
ConstantBuffer.Push(cmd, parameters.volumetricCB, parameters.volumetricLightingCS, HDShaderIDs._ShaderVariablesVolumetric);
@@ -842,12 +970,12 @@ static void FilterVolumetricLighting(in VolumetricLightingParameters parameters,
ConstantBuffer.Push(cmd, parameters.volumetricCB, parameters.volumetricLightingCS, HDShaderIDs._ShaderVariablesVolumetric);
// The shader defines GROUP_SIZE_1D = 8.
- cmd.SetComputeTextureParam(parameters.volumetricLightingFilteringCS, parameters.volumetricFilteringKernelX, HDShaderIDs._VBufferLightingFeedback, inputBuffer); // Read
- cmd.SetComputeTextureParam(parameters.volumetricLightingFilteringCS, parameters.volumetricFilteringKernelX, HDShaderIDs._VBufferLightingIntegral, outputBuffer); // Write
+ cmd.SetComputeTextureParam(parameters.volumetricLightingFilteringCS, parameters.volumetricFilteringKernelX, HDShaderIDs._VBufferFilteringInput, inputBuffer); // Read
+ cmd.SetComputeTextureParam(parameters.volumetricLightingFilteringCS, parameters.volumetricFilteringKernelX, HDShaderIDs._VBufferFilteringOutput, outputBuffer); // Write
cmd.DispatchCompute(parameters.volumetricLightingFilteringCS, parameters.volumetricFilteringKernelX, ((int)parameters.resolution.x + 7) / 8, ((int)parameters.resolution.y + 7) / 8, parameters.viewCount);
- cmd.SetComputeTextureParam(parameters.volumetricLightingFilteringCS, parameters.volumetricFilteringKernelY, HDShaderIDs._VBufferLightingFeedback, outputBuffer); // Read
- cmd.SetComputeTextureParam(parameters.volumetricLightingFilteringCS, parameters.volumetricFilteringKernelY, HDShaderIDs._VBufferLightingIntegral, inputBuffer); // Write
+ cmd.SetComputeTextureParam(parameters.volumetricLightingFilteringCS, parameters.volumetricFilteringKernelY, HDShaderIDs._VBufferFilteringInput, outputBuffer); // Read
+ cmd.SetComputeTextureParam(parameters.volumetricLightingFilteringCS, parameters.volumetricFilteringKernelY, HDShaderIDs._VBufferFilteringOutput, inputBuffer); // Write
cmd.DispatchCompute(parameters.volumetricLightingFilteringCS, parameters.volumetricFilteringKernelY, ((int)parameters.resolution.x + 7) / 8, ((int)parameters.resolution.y + 7) / 8, parameters.viewCount);
}
}
@@ -864,12 +992,18 @@ void VolumetricLightingPass(HDCamera hdCamera, CommandBuffer cmd, int frameIndex
using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.VolumetricLighting)))
{
- // It is safe to request these RTs even if they have not been allocated.
- // The system will return NULL in that case.
- RTHandle historyRT = hdCamera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.VolumetricLighting);
- RTHandle feedbackRT = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.VolumetricLighting);
+ RTHandle feedbackRT = null, historyRT = null;
+
+ if (parameters.enableReprojection)
+ {
+ var currIdx = (frameIndex + 0) & 1;
+ var prevIdx = (frameIndex + 1) & 1;
+
+ feedbackRT = hdCamera.volumetricHistoryBuffers[currIdx];
+ historyRT = hdCamera.volumetricHistoryBuffers[prevIdx];
+ }
- VolumetricLightingPass(parameters, m_DensityBufferHandle, m_LightingBufferHandle, historyRT, feedbackRT, m_TileAndClusterData.bigTileLightList, cmd);
+ VolumetricLightingPass(parameters, m_DensityBuffer, m_LightingBuffer, historyRT, feedbackRT, m_TileAndClusterData.bigTileLightList, cmd);
if (parameters.enableReprojection)
hdCamera.volumetricHistoryIsValid = true; // For the next frame...
@@ -877,9 +1011,9 @@ void VolumetricLightingPass(HDCamera hdCamera, CommandBuffer cmd, int frameIndex
// Let's filter out volumetric buffer
if (parameters.filterVolume)
- FilterVolumetricLighting(parameters, m_DensityBufferHandle, m_LightingBufferHandle, cmd);
+ FilterVolumetricLighting(parameters, m_DensityBuffer, m_LightingBuffer, cmd);
- cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, m_LightingBufferHandle);
+ cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, m_LightingBuffer);
}
} // class VolumetricLightingModule
} // namespace UnityEngine.Rendering.HighDefinition
diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs.hlsl
index 7394831c232..9f64f8bf410 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs.hlsl
+++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLighting.cs.hlsl
@@ -27,14 +27,19 @@ CBUFFER_START(ShaderVariablesVolumetric)
float _VBufferUnitDepthTexelSpacing;
uint _NumVisibleDensityVolumes;
float _CornetteShanksConstant;
- uint _VBufferLightingHistoryIsValid;
+ uint _VBufferHistoryIsValid;
float4 _VBufferSampleOffset;
float4 _VolumeMaskDimensions;
float4 _AmbientProbeCoeffs[7];
+ float _VBufferVoxelSize;
+ float _HaveToPad;
+ float _OtherwiseTheBuffer;
+ float _IsFilledWithGarbage;
float4 _VBufferPrevViewportSize;
- float4 _VBufferHistoryPrevUvScaleAndLimit;
- float4 _VBufferPrevDepthEncodingParams;
- float4 _VBufferPrevDepthDecodingParams;
+ float4 _VBufferHistoryViewportScale;
+ float4 _VBufferHistoryViewportLimit;
+ float4 _VBufferPrevDistanceEncodingParams;
+ float4 _VBufferPrevDistanceDecodingParams;
uint _NumTileBigTileX;
uint _NumTileBigTileY;
CBUFFER_END
diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLightingFiltering.compute b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLightingFiltering.compute
index fbff303be31..4b674ece566 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLightingFiltering.compute
+++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/VolumetricLightingFiltering.compute
@@ -20,8 +20,8 @@
// Inputs & outputs
//--------------------------------------------------------------------------------------------------
-RW_TEXTURE3D(float4, _VBufferLightingIntegral);
-RW_TEXTURE3D(float4, _VBufferLightingFeedback);
+RW_TEXTURE3D(float4, _VBufferFilteringInput);
+RW_TEXTURE3D(float4, _VBufferFilteringOutput);
#define SIGMA_FILTER 2.0
@@ -69,7 +69,7 @@ void FilterVolumetricLighting(uint3 dispatchThreadId : SV_DispatchThreadID,
// Compute the next tapping coordinate
int3 tapCoord = int3(voxelCoord.x, voxelCoord.y, voxelCoord.z) + vec * idx;
// Tap the value we should be tapping from
- float4 currentValue = _VBufferLightingFeedback[tapCoord];
+ float4 currentValue = _VBufferFilteringInput[tapCoord];
// Compute the weight for this tap
float weight = Gaussian(abs(idx), SIGMA_FILTER);
@@ -85,6 +85,6 @@ void FilterVolumetricLighting(uint3 dispatchThreadId : SV_DispatchThreadID,
sumW += weight;
}
// Normalize and output
- _VBufferLightingIntegral[voxelCoord] = value / sumW;
+ _VBufferFilteringOutput[voxelCoord] = value / sumW;
}
}
diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs
index 721d597a27d..74ad3623b32 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs
+++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs
@@ -186,7 +186,8 @@ internal struct ShadowHistoryUsage
internal Transform volumeAnchor;
internal Rect finalViewport; // This will have the correct viewport position and the size will be full resolution (ie : not taking dynamic rez into account)
internal int colorPyramidHistoryMipCount = 0;
- internal VBufferParameters[] vBufferParams; // Double-buffered; needed even if reprojection is off
+ internal VBufferParameters[] vBufferParams; // Double-buffered; needed even if reprojection is off
+ internal RTHandle[] volumetricHistoryBuffers; // Double-buffered; only used for reprojection
// Currently the frame count is not increase every render, for ray tracing shadow filtering. We need to have a number that increases every render
internal uint cameraFrameCount = 0;
internal bool animateMaterials;
@@ -406,7 +407,7 @@ internal void Update(FrameSettings currentFrameSettings, HDRenderPipeline hdrp,
{
// Have to do this every frame in case the settings have changed.
// The condition inside controls whether we perform init/deinit or not.
- hdrp.ReinitializeVolumetricBufferParams(this);
+ HDRenderPipeline.ReinitializeVolumetricBufferParams(this);
bool isCurrentColorPyramidRequired = frameSettings.IsEnabled(FrameSettingsField.Refraction) || frameSettings.IsEnabled(FrameSettingsField.Distortion);
bool isHistoryColorPyramidRequired = IsSSREnabled() || antialiasing == AntialiasingMode.TemporalAntialiasing;
@@ -425,7 +426,8 @@ internal void Update(FrameSettings currentFrameSettings, HDRenderPipeline hdrp,
{
// Reinit the system.
colorPyramidHistoryIsValid = false;
- volumetricHistoryIsValid = false;
+
+ HDRenderPipeline.DestroyVolumetricHistoryBuffers(this);
// The history system only supports the "nuke all" option.
m_HistoryRTSystem.Dispose();
@@ -438,7 +440,7 @@ internal void Update(FrameSettings currentFrameSettings, HDRenderPipeline hdrp,
if (numVolumetricBuffersRequired != 0)
{
- hdrp.AllocateVolumetricHistoryBuffers(this, numVolumetricBuffersRequired);
+ HDRenderPipeline.CreateVolumetricHistoryBuffers(this, numVolumetricBuffersRequired);
}
// Mark as init.
@@ -482,7 +484,8 @@ internal void Update(FrameSettings currentFrameSettings, HDRenderPipeline hdrp,
isFirstFrame = false;
cameraFrameCount++;
- hdrp.UpdateVolumetricBufferParams(this);
+ HDRenderPipeline.UpdateVolumetricBufferParams(this, hdrp.GetFrameCount());
+ HDRenderPipeline.ResizeVolumetricHistoryBuffers(this, hdrp.GetFrameCount());
// Here we use the non scaled resolution for the RTHandleSystem ref size because we assume that at some point we will need full resolution anyway.
// This is necessary because we assume that after post processes, we have the full size render target for debug rendering
diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs
index bc6ae1a3eb3..47b2c979f1b 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs
+++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCameraFrameHistoryType.cs
@@ -7,8 +7,6 @@ public enum HDCameraFrameHistoryType
{
/// Color buffer mip chain.
ColorBufferMipChain,
- /// Volumetric lighting buffer.
- VolumetricLighting,
/// Exposure buffer.
Exposure,
/// Temporal antialiasing history.
diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs
index cbda6597b97..66b4f223214 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs
+++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.LightLoop.cs
@@ -411,12 +411,16 @@ TextureHandle VolumeVoxelizationPass( RenderGraph renderGraph,
passData.visibleVolumeBoundsBuffer = visibleVolumeBoundsBuffer;
passData.visibleVolumeDataBuffer = visibleVolumeDataBuffer;
passData.bigTileLightListBuffer = bigTileLightListBuffer;
- passData.densityBuffer = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(ComputeVBufferResolutionXY, false, false)
+
+ float tileSize = 0;
+ Vector3Int viewportSize = ComputeVolumetricViewportSize(hdCamera, ref tileSize);
+
+ passData.densityBuffer = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(viewportSize.x, viewportSize.y, false, false)
{
dimension = TextureDimension.Tex3D,
colorFormat = GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough
enableRandomWrite = true,
- slices = ComputeVBufferSliceCount(volumetricLightingPreset),
+ slices = viewportSize.z,
/* useDynamicScale: true, // <- TODO ,*/
name = "VBufferDensity"
}));
@@ -461,19 +465,26 @@ TextureHandle VolumetricLightingPass(RenderGraph renderGraph, HDCamera hdCamera,
passData.parameters = parameters;
passData.bigTileLightListBuffer = bigTileLightListBuffer;
passData.densityBuffer = builder.ReadTexture(densityBuffer);
- passData.lightingBuffer = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(ComputeVBufferResolutionXY, false, false)
+
+ float tileSize = 0;
+ Vector3Int viewportSize = ComputeVolumetricViewportSize(hdCamera, ref tileSize);
+
+ passData.lightingBuffer = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(viewportSize.x, viewportSize.y, false, false)
{
dimension = TextureDimension.Tex3D,
colorFormat = GraphicsFormat.R16G16B16A16_SFloat, // 8888_sRGB is not precise enough
enableRandomWrite = true,
- slices = ComputeVBufferSliceCount(volumetricLightingPreset),
+ slices = viewportSize.z,
/* useDynamicScale: true, // <- TODO ,*/
- name = "VBufferIntegral"
+ name = "VBufferLighting"
}, HDShaderIDs._VBufferLighting));
if (passData.parameters.enableReprojection)
{
- passData.historyBuffer = builder.ReadTexture(renderGraph.ImportTexture(hdCamera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.VolumetricLighting)));
- passData.feedbackBuffer = builder.WriteTexture(renderGraph.ImportTexture(hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.VolumetricLighting)));
+ var currIdx = (frameIndex + 0) & 1;
+ var prevIdx = (frameIndex + 1) & 1;
+
+ passData.feedbackBuffer = builder.WriteTexture(renderGraph.ImportTexture(hdCamera.volumetricHistoryBuffers[currIdx]));
+ passData.historyBuffer = builder.ReadTexture(renderGraph.ImportTexture(hdCamera.volumetricHistoryBuffers[prevIdx]));
}
HDShadowManager.ReadShadowResult(shadowResult, builder);
@@ -483,10 +494,11 @@ TextureHandle VolumetricLightingPass(RenderGraph renderGraph, HDCamera hdCamera,
{
RTHandle densityBufferRT = ctx.resources.GetTexture(data.densityBuffer);
RTHandle lightinBufferRT = ctx.resources.GetTexture(data.lightingBuffer);
+
VolumetricLightingPass( data.parameters,
densityBufferRT,
lightinBufferRT,
- data.parameters.enableReprojection ? ctx.resources.GetTexture(data.historyBuffer) : null,
+ data.parameters.enableReprojection ? ctx.resources.GetTexture(data.historyBuffer) : null,
data.parameters.enableReprojection ? ctx.resources.GetTexture(data.feedbackBuffer) : null,
data.bigTileLightListBuffer,
ctx.cmd);
diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs
index 5cc12c92643..f4dd6b79314 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs
+++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs
@@ -2726,6 +2726,7 @@ out ScriptableCullingParameters cullingParams
// From this point, we should only use frame settings from the camera
hdCamera.Update(currentFrameSettings, this, m_MSAASamples, xrPass);
+ ResizeVolumetricLightingBuffers(hdCamera, GetFrameCount()); // Safe to update the Volumetric Lighting System now
// Custom Render requires a proper HDCamera, so we return after the HDCamera was setup
if (additionalCameraData != null && additionalCameraData.hasCustomRender)
@@ -3526,7 +3527,7 @@ void RenderSky(HDCamera hdCamera, CommandBuffer cmd)
if (Fog.IsFogEnabled(hdCamera) || Fog.IsPBRFogEnabled(hdCamera))
{
var pixelCoordToViewDirWS = hdCamera.mainViewConstants.pixelCoordToViewDirWS;
- m_SkyManager.RenderOpaqueAtmosphericScattering(cmd, hdCamera, colorBuffer, m_LightingBufferHandle, intermediateBuffer, depthBuffer, pixelCoordToViewDirWS, hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA));
+ m_SkyManager.RenderOpaqueAtmosphericScattering(cmd, hdCamera, colorBuffer, m_LightingBuffer, intermediateBuffer, depthBuffer, pixelCoordToViewDirWS, hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA));
}
}
@@ -3918,7 +3919,7 @@ RenderSSRParameters PrepareSSRParameters(HDCamera hdCamera, in HDUtils.PackedMip
cb._SsrRoughnessFadeEndTimesRcpLength = (roughnessFadeLength != 0) ? (cb._SsrRoughnessFadeEnd * (1.0f / roughnessFadeLength)) : 1;
cb._SsrRoughnessFadeRcpLength = (roughnessFadeLength != 0) ? (1.0f / roughnessFadeLength) : 0;
cb._SsrEdgeFadeRcpLength = Mathf.Min(1.0f / volumeSettings.screenFadeDistance.value, float.MaxValue);
- cb._ColorPyramidUvScaleAndLimitPrevFrame = HDUtils.ComputeUvScaleAndLimit(hdCamera.historyRTHandleProperties.previousViewportSize, hdCamera.historyRTHandleProperties.previousRenderTargetSize);
+ cb._ColorPyramidUvScaleAndLimitPrevFrame = HDUtils.ComputeViewportScaleAndLimit(hdCamera.historyRTHandleProperties.previousViewportSize, hdCamera.historyRTHandleProperties.previousRenderTargetSize);
cb._SsrColorPyramidMaxMip = hdCamera.colorPyramidHistoryMipCount - 1;
cb._SsrDepthPyramidMaxMip = depthPyramid.mipLevelCount - 1;
diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs
index 2e779381206..f221e32003a 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs
+++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs
@@ -380,9 +380,10 @@ static class HDShaderIDs
public static readonly int _VBufferDensity = Shader.PropertyToID("_VBufferDensity");
public static readonly int _VBufferLighting = Shader.PropertyToID("_VBufferLighting");
- 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 _VBufferHistory = Shader.PropertyToID("_VBufferHistory");
+ public static readonly int _VBufferFeedback = Shader.PropertyToID("_VBufferFeedback");
+ public static readonly int _VBufferFilteringInput = Shader.PropertyToID("_VBufferFilteringInput");
+ public static readonly int _VBufferFilteringOutput = Shader.PropertyToID("_VBufferFilteringOutput");
public static readonly int _VolumeBounds = Shader.PropertyToID("_VolumeBounds");
public static readonly int _VolumeData = Shader.PropertyToID("_VolumeData");
public static readonly int _VolumeMaskAtlas = Shader.PropertyToID("_VolumeMaskAtlas");
diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/RenderPipelineSettings.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/RenderPipelineSettings.cs
index 66fd0398fb5..686106a379a 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/RenderPipelineSettings.cs
+++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Settings/RenderPipelineSettings.cs
@@ -147,8 +147,6 @@ public struct LightSettings
public IntScalableSetting sssSampleBudget;
/// Support volumetric lighting.
public bool supportVolumetrics;
- /// High quality volumetric lighting.
- public bool increaseResolutionOfVolumetrics;
/// Support light layers.
public bool supportLightLayers;
/// Name for light layer 0.
diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/HDUtils.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/HDUtils.cs
index f09c5257339..69e5fee1443 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/HDUtils.cs
+++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/HDUtils.cs
@@ -589,21 +589,31 @@ internal static void CheckRTCreated(RenderTexture rt)
rt.Create();
}
- internal static Vector4 ComputeUvScaleAndLimit(Vector2Int viewportResolution, Vector2Int bufferSize)
+ internal static float ComputeViewportScale(int viewportSize, int bufferSize)
{
- Vector2 rcpBufferSize = new Vector2(1.0f / bufferSize.x, 1.0f / bufferSize.y);
+ float rcpBufferSize = 1.0f / bufferSize;
- // vp_scale = vp_dim / tex_dim.
- Vector2 uvScale = new Vector2(viewportResolution.x * rcpBufferSize.x,
- viewportResolution.y * rcpBufferSize.y);
+ // Scale by (vp_dim / buf_dim).
+ return viewportSize * rcpBufferSize;
+ }
+
+ internal static float ComputeViewportLimit(int viewportSize, int bufferSize)
+ {
+ float rcpBufferSize = 1.0f / bufferSize;
- // clamp to (vp_dim - 0.5) / tex_dim.
- Vector2 uvLimit = new Vector2((viewportResolution.x - 0.5f) * rcpBufferSize.x,
- (viewportResolution.y - 0.5f) * rcpBufferSize.y);
+ // Clamp to (vp_dim - 0.5) / buf_dim.
+ return (viewportSize - 0.5f) * rcpBufferSize;
+ }
- return new Vector4(uvScale.x, uvScale.y, uvLimit.x, uvLimit.y);
+ internal static Vector4 ComputeViewportScaleAndLimit(Vector2Int viewportSize, Vector2Int bufferSize)
+ {
+ return new Vector4(ComputeViewportScale(viewportSize.x, bufferSize.x), // Scale(x)
+ ComputeViewportScale(viewportSize.y, bufferSize.y), // Scale(y)
+ ComputeViewportLimit(viewportSize.x, bufferSize.x), // Limit(x)
+ ComputeViewportLimit(viewportSize.y, bufferSize.y)); // Limit(y)
}
+
#if UNITY_EDITOR
// This function can't be in HDEditorUtils because we need it in HDRenderPipeline.cs (and HDEditorUtils is in an editor asmdef)
internal static bool IsSupportedBuildTarget(UnityEditor.BuildTarget buildTarget)
diff --git a/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesGlobal.cs b/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesGlobal.cs
index 66f7b13cacd..5cb15eb4136 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesGlobal.cs
+++ b/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesGlobal.cs
@@ -126,7 +126,8 @@ unsafe struct ShaderVariablesGlobal
// VBuffer
public Vector4 _VBufferViewportSize; // { w, h, 1/w, 1/h }
- public Vector4 _VBufferSharedUvScaleAndLimit; // Necessary us to work with sub-allocation (resource aliasing) in the RTHandle system
+ public Vector4 _VBufferLightingViewportScale; // Necessary us to work with sub-allocation (resource aliasing) in the RTHandle system
+ public Vector4 _VBufferLightingViewportLimit; // Necessary us to work with sub-allocation (resource aliasing) in the RTHandle system
public Vector4 _VBufferDistanceEncodingParams; // See the call site for description
public Vector4 _VBufferDistanceDecodingParams; // See the call site for description
public uint _VBufferSliceCount;
diff --git a/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesGlobal.cs.hlsl b/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesGlobal.cs.hlsl
index f952d600063..ad91938ad04 100644
--- a/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesGlobal.cs.hlsl
+++ b/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesGlobal.cs.hlsl
@@ -58,7 +58,8 @@ GLOBAL_CBUFFER_START(ShaderVariablesGlobal, b0)
float _HeightFogBaseHeight;
float _GlobalFogAnisotropy;
float4 _VBufferViewportSize;
- float4 _VBufferSharedUvScaleAndLimit;
+ float4 _VBufferLightingViewportScale;
+ float4 _VBufferLightingViewportLimit;
float4 _VBufferDistanceEncodingParams;
float4 _VBufferDistanceDecodingParams;
uint _VBufferSliceCount;