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;