diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index e351306150e..90c6cf3af20 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added rasterized area light shadows for AxF material - Added View Bias for mesh decals. - Added a cloud system and the CloudLayer volume override. +- Added a setting in the HDRP asset to change the Density Volume mask resolution of being locked at 32x32x32 (HDRP Asset > Lighting > Volumetrics > Max Density Volume Size). +- Added a Falloff Mode (Linear or Exponential) in the Density Volume for volume blending with Blend Distance. ### Fixed - Fixed probe volumes debug views. @@ -39,6 +41,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - The DrawRenderers function of CustomPassUtils class now takes a sortingCriteria in parameter. - When in half res, RTR denoising is executed at half resolution and the upscale happens at the end. - Removed the upscale radius from the RTR. +- Density Volumes can now take a 3D RenderTexture as mask, the mask can use RGBA format for RGB fog. +- Decreased the minimal Fog Distance value in the Density Volume to 0.05. ## [10.3.0] - 2020-12-01 diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Density-Volume.md b/com.unity.render-pipelines.high-definition/Documentation~/Density-Volume.md index 33c2c7df614..b6c7889fb95 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/Density-Volume.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/Density-Volume.md @@ -22,27 +22,27 @@ To create a Density Volume, right click in the Hierarchy and select __Rendering | **Fog Distance** | Controls the density at the base of the fog and determines how far you can see through the fog in meters. At this distance, the fog has absorbed and out-scattered 63% of background light. | | **Size** | Controls the dimensions of the Volume. | | **Per Axis Control** | Enable this to control blend distance per axis instead of globally. | -| **Blend Distance** | Blend Distance creates a linear fade from the fog level in the Volume to the fog level outside it. This is not a percentage, it is the absolute distance from the edge of the Volume bounds, defined by the Size property, where the fade starts. Unity clamps this value between 0 and half of the lowest axis value in the Size property. If you use the Normal tab, you can alter a single float value named Blend Distance, which gives a uniform fade in every direction. If you open the Advanced tab, you can use two fades per axis, one for each direction. For example, on the x-axis you could have one for left-to-right and one for right-to-left. Setting the distance to 0 hides the fade, while setting the distance to 1 creates a fade. | +| **Blend Distance** | Blend Distance creates a fade from the fog level in the Volume to the fog level outside it. This is not a percentage, it is the absolute distance from the edge of the Volume bounds, defined by the Size property, where the fade starts. Unity clamps this value between 0 and half of the lowest axis value in the Size property. If you use the Normal tab, you can alter a single float value named Blend Distance, which gives a uniform fade in every direction. If you open the Advanced tab, you can use two fades per axis, one for each direction. For example, on the x-axis you could have one for left-to-right and one for right-to-left. Setting the distance to 0 hides the fade, while setting the distance to 1 creates a fade. | +| **Falloff Mode** | Controls the falloff function applied to the blending of **Blend Distance**. By default the falloff is linear but you can change it to exponential for a more realistic look. | | **Invert Blend** | Reverses the direction of the fade. Setting the Blend Distances on each axis to its maximum possible value preserves the fog at the center of the Volume and fades the edges. Inverting the blend fades the center and preserves the edges instead. | | **Distance Fade Start** | Distance from the camera at which the Density Volume starts to fade out. This is useful when optimizing a scene with many Density Volumes and making the more distant ones disappear| | **Distance Fade End** | Distance from the camera at which the Density Volume has completely fade out. This is useful when optimizing a scene with many Density Volumes and making the more distant ones disappear| -| **Density Mask Texture** | Specifies a 3D texture mapped to the interior of the Volume. The Density Volume only uses the alpha channel of the texture. The value of the texture acts as a density multiplier. A value of 0 in the Texture results in a Volume of 0 density, and the texture value of 1 results in the original constant (homogeneous) volume. | +| **Density Mask Texture** | Specifies a 3D texture mapped to the interior of the Volume. The Density Volume only uses the RGB channels of the texture for the fog color and A for the fog density multiplier. A value of 0 in the Texture alpha channel results in a Volume of 0 density, and the value of 1 results in the original constant (homogeneous) volume. | | **Scroll Speed** | Specifies the speed (per-axis) at which the Density Volume scrolls the texture. If you set every axis to 0, the Density Volume does not scroll the texture and the fog is static. | | **Tiling** | Specifies the per-axis tiling rate of the texture. For example, setting the x-axis component to 2 means that the texture repeats 2 times on the x-axis within the interior of the volume. | +## Related Settings in the HDRP Asset +There are two settings related to density volumes in the HDRP Asset settings: **Max Density Volume Size** and **Max Density Volume On Screen**. You can find both of these settings in the HDRP Asset's **Lighting** section. -## Creating a Density Mask Texture - -1. In image-editing software of your choice, prepare a grayscale flipbook texture and [import it as a 3D texture](https://docs.unity3d.com/2020.2/Documentation/Manual/class-Texture3D.html). For example, a texture of size 1024x32 describes a 3D texture of size 32x32x32 with 32 slices laid out one after another. +![](Images/HDRPAsset_VolumetricSettings.png) -2. Additionnaly, in the Texture Import Settings: - 1. Set the __Texture Type__ to __Single Channel__. +The **Max Density Volume Size** controls the maximum resolution you can use for the **Density Mask Texture**. Changing this setting can have a large impact on memory usage. For information on how much memory HDRP allocates for the Density Volume system, see the info box below this setting in the HDRP Asset. - 2. Set the __Channel__ to __Alpha__. +The **Max Density Volume On Screen** controls how many Density Volumes can appear on-screen at once. This setting also has an impact on memory. - 3. (Optionnal) Set the __Alpha Source__ to __From Gray Scale__. +## Creating a Density Mask Texture - 4. Click Apply. +1. In image-editing software of your choice, prepare an RGBA flipbook texture and [import it as a 3D texture](https://docs.unity3d.com/2020.2/Documentation/Manual/class-Texture3D.html). For example, a texture of size 1024x32 describes a 3D texture of size 32x32x32 with 32 slices laid out one after another. -3. Open a Density Volume component and assign the texture you just imported to the __Texture__ field in the __Density Mask Texture__ section. +2. Open a Density Volume component and assign the texture you just imported to the __Texture__ field in the __Density Mask Texture__ section. diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Images/DensityVolume1.png b/com.unity.render-pipelines.high-definition/Documentation~/Images/DensityVolume1.png index cee9c009d09..945d539b289 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/Images/DensityVolume1.png +++ b/com.unity.render-pipelines.high-definition/Documentation~/Images/DensityVolume1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4e4ba60c8aa303bb1ca774db9b3ca734508e20c32ae2c558bfc0b31ecd3f823 -size 22173 +oid sha256:59782a337b4dc428bcb0912fff10eb54b9dd25d0b2b071874fb72add7105eb21 +size 29667 diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Images/HDRPAsset_VolumetricSettings.png b/com.unity.render-pipelines.high-definition/Documentation~/Images/HDRPAsset_VolumetricSettings.png new file mode 100644 index 00000000000..27ad785639b --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Documentation~/Images/HDRPAsset_VolumetricSettings.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d563b16226565f648639b62b87fca175f17607d2742426f20c14b9f8ee3c043 +size 11986 diff --git a/com.unity.render-pipelines.high-definition/Documentation~/whats-new-11.md b/com.unity.render-pipelines.high-definition/Documentation~/whats-new-11.md index feda265206c..25295784287 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/whats-new-11.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/whats-new-11.md @@ -54,6 +54,16 @@ public class ExampleComponent : VolumeComponent } ``` +### Density Volume Improvements + +Density Volumes masks now support using 3D RenderTextures as masks. 3D mask textures now also use all four RGBA channel which allows volumetric fog to have different colors and density based on the 3D Texture. + +The size limit of 32x32x32 for the mask textures has also been replaced by a setting in the HDRP asset called "Max Density Volume Resolution", under the Lighting > Volumetrics section. The upper limit for mask textures is now 256x256x256, an info box below the field tells you how much memory is allocated to store these textures. Note that increasing the resolution of the mask texture doesn't necessarily improve the quality of the volumetric, what's important is to have a good balance between the **Volumetrics** quality and the density volume resolution. + +There is a new field to change the falloff HDRP applies when it blends the volume using the Blend Distance property. You can choose either Linear which is the default and previous technique, or Exponential which is more realistic. + +Finally, the minimal value of the **Fog Distance** parameter was lowered to 0.05 instead of 1 and now allows thicker fog effects to be created. + ### Cloud System ![](Images/HDRPFeatures-CloudLayer.png) diff --git a/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/DensityVolumeUI.Drawer.cs b/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/DensityVolumeUI.Drawer.cs index 20f66d22017..089ff804aae 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/DensityVolumeUI.Drawer.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/DensityVolumeUI.Drawer.cs @@ -154,6 +154,8 @@ static void Drawer_VolumeContent(SerializedDensityVolume serialized, Editor owne serialized.editorNegativeFade.vector3Value = negFade; } + EditorGUILayout.PropertyField(serialized.falloffMode, Styles.s_FalloffMode); + EditorGUILayout.Space(); EditorGUILayout.PropertyField(serialized.invertFade, Styles.s_InvertFadeLabel); @@ -177,7 +179,20 @@ static void Drawer_VolumeContent(SerializedDensityVolume serialized, Editor owne static void Drawer_DensityMaskTextureContent(SerializedDensityVolume serialized, Editor owner) { + EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(serialized.volumeTexture, Styles.s_VolumeTextureLabel); + if (EditorGUI.EndChangeCheck()) + { + var newTexture = serialized.volumeTexture.objectReferenceValue; + if (newTexture != null) + { + if (!(newTexture is RenderTexture rt && rt.dimension == UnityEngine.Rendering.TextureDimension.Tex3D || newTexture is Texture3D)) + { + Debug.LogError($"Can't assign texture '{newTexture}' to the Density Volume because the dimension doesn't match the expected Texture3D dimension."); + serialized.volumeTexture.objectReferenceValue = null; + } + } + } EditorGUILayout.PropertyField(serialized.textureScroll, Styles.s_TextureScrollLabel); EditorGUILayout.PropertyField(serialized.textureTile, Styles.s_TextureTileLabel); } diff --git a/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/DensityVolumeUI.Skin.cs b/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/DensityVolumeUI.Skin.cs index a9460538748..1b850bdba68 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/DensityVolumeUI.Skin.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/DensityVolumeUI.Skin.cs @@ -16,14 +16,15 @@ internal static class Styles }; public static readonly GUIContent s_Size = new GUIContent("Size", "Modify the size of this Density Volume. This is independent of the Transform's Scale."); - public static readonly GUIContent s_AlbedoLabel = new GUIContent("Single Scattering Albedo", "The color this fog scatteres light to."); + public static readonly GUIContent s_AlbedoLabel = new GUIContent("Single Scattering Albedo", "The color this fog scatters light to."); public static readonly GUIContent s_MeanFreePathLabel = new GUIContent("Fog Distance", "Density at the base of the fog. Determines how far you can see through the fog in meters."); public static readonly GUIContent s_VolumeTextureLabel = new GUIContent("Texture", "The fog Texture for the Density Mask. Generate this Texture type using the Density Volume Texture Tool."); public static readonly GUIContent s_TextureScrollLabel = new GUIContent("Scroll Speed", "Modify the speed for each axis at which HDRP scrolls the fog Texture."); public static readonly GUIContent s_TextureTileLabel = new GUIContent("Tiling", "Modify the tiling of the fog Texture on each axis individually."); public static readonly GUIContent s_BlendLabel = new GUIContent("Blend Distance", "Interior distance from the Size where the fog fades in completely."); public static readonly GUIContent s_InvertFadeLabel = new GUIContent("Invert Blend", "Inverts blend values so 0 becomes the new maximum value and the original maximum value becomes 0."); - public static readonly GUIContent s_ManipulatonTypeContent = EditorGUIUtility.TrTextContent("Per Axis Control", "When checked, each face can be manipulated separatly. This also include fading options."); + public static readonly GUIContent s_FalloffMode = new GUIContent("Falloff Mode", "When Blend Distance is above 0, controls which kind of falloff is applied to the transition area."); + public static readonly GUIContent s_ManipulatonTypeContent = EditorGUIUtility.TrTextContent("Per Axis Control", "When checked, each face can be manipulated separately. This also include fading options."); public static readonly GUIContent s_DistanceFadeStartLabel = new GUIContent("Distance Fade Start"); public static readonly GUIContent s_DistanceFadeEndLabel = new GUIContent("Distance Fade End"); diff --git a/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/SerializedDensityVolume.cs b/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/SerializedDensityVolume.cs index 11ebeae73c0..60915799fc8 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/SerializedDensityVolume.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricLighting/SerializedDensityVolume.cs @@ -1,4 +1,5 @@ using UnityEngine; +using UnityEngine.Rendering.HighDefinition; namespace UnityEditor.Rendering.HighDefinition { @@ -25,6 +26,8 @@ class SerializedDensityVolume public SerializedProperty distanceFadeStart; public SerializedProperty distanceFadeEnd; + public SerializedProperty falloffMode; + SerializedObject m_SerializedObject; public SerializedDensityVolume(SerializedObject serializedObject) @@ -54,6 +57,8 @@ public SerializedDensityVolume(SerializedObject serializedObject) distanceFadeStart = densityParams.FindPropertyRelative("distanceFadeStart"); distanceFadeEnd = densityParams.FindPropertyRelative("distanceFadeEnd"); + + falloffMode = densityParams.FindPropertyRelative(nameof(DensityVolumeArtistParameters.falloffMode)); } public void Apply() diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs index 9716567ee78..1cfc90ef0c1 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs @@ -30,6 +30,7 @@ public class GeneralSection public static readonly GUIContent lightingQualitySettings = EditorGUIUtility.TrTextContent("Lighting Quality Settings"); public static readonly GUIContent lightLayerSubTitle = EditorGUIUtility.TrTextContent("Light Layers"); + public static readonly GUIContent volumetricSubTitle = EditorGUIUtility.TrTextContent("Volumetrics"); public static readonly GUIContent cookiesSubTitle = EditorGUIUtility.TrTextContent("Cookies"); public static readonly GUIContent reflectionsSubTitle = EditorGUIUtility.TrTextContent("Reflections"); public static readonly GUIContent skySubTitle = EditorGUIUtility.TrTextContent("Sky"); @@ -137,6 +138,8 @@ public class GeneralSection internal const string probeVolumeInfo = "Warning: Probe Volumes is a highly experimental feature.\nIt is disabled by default for this reason.\nIt's functionality is subject to breaking changes and whole sale removal.\nIt is not recommended for use outside of for providing feedback.\nIt should not be used in production.\nTo enable, set:\nEnableProbeVolumes = 1\ninside of ShaderConfig.cs\and inside of the editor run:\nEdit->Render Pipeline->Generate Shader Includes\nProbe Volumes feature must also be enabled here."; internal static readonly GUIContent probeVolumeAtlasResolution = EditorGUIUtility.TrTextContent("Atlas Resolution", "Resolution of the 3D texture atlas containing visible ProbeVolumes."); internal static readonly GUIContent probeVolumeAtlasOctahedralDepthResolution = EditorGUIUtility.TrTextContent("Octahedral Depth Atlas Resolution", "Resolution of the 2D texture atlas containing visible ProbeVolumes octahedral depth data."); + public static readonly GUIContent maxDensityVolumeSizeStyle = EditorGUIUtility.TrTextContent("Max Density Volume Size", "Specifies the maximum size for the individual 3D density volume texture that HDRP uses for Density Volumes. This settings will affect your memory consumption."); + public static readonly GUIContent maxDensityVolumesOnScreenStyle = EditorGUIUtility.TrTextContent("Max Density Volumes On Screen", "Sets the maximum number of density volume HDRP can handle on screen at once. This settings will affect your memory consumption."); public const string cacheErrorFormat = "This configuration will lead to more than 2 GB reserved for this cache at runtime! ({0} requested) Only {1} element will be reserved instead."; 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 4c8c3bc927b..1e14f3a618f 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs @@ -41,7 +41,8 @@ enum Expandable LightingQuality = 1 << 25, SSRQuality = 1 << 26, VirtualTexturing = 1 << 27, - FogQuality = 1 << 28 + FogQuality = 1 << 28, + Volumetric = 1 << 29, } static readonly ExpandedState k_ExpandedState = new ExpandedState(Expandable.CameraFrameSettings | Expandable.General, "HDRP"); @@ -80,6 +81,7 @@ static HDRenderPipelineUI() ), CED.FoldoutGroup(Styles.lightingSectionTitle, Expandable.Lighting, k_ExpandedState, CED.Group(GroupOption.Indent, Drawer_SectionLightingUnsorted), + CED.FoldoutGroup(Styles.volumetricSubTitle, Expandable.Volumetric, k_ExpandedState, FoldoutOption.Indent | FoldoutOption.SubFoldout, Drawer_Volumetric), CED.FoldoutGroup(Styles.cookiesSubTitle, Expandable.Cookie, k_ExpandedState, FoldoutOption.Indent | FoldoutOption.SubFoldout, Drawer_SectionCookies), CED.FoldoutGroup(Styles.reflectionsSubTitle, Expandable.Reflection, k_ExpandedState, FoldoutOption.Indent | FoldoutOption.SubFoldout, Drawer_SectionReflection), CED.FoldoutGroup(Styles.skySubTitle, Expandable.Sky, k_ExpandedState, FoldoutOption.Indent | FoldoutOption.SubFoldout, Drawer_SectionSky), @@ -226,6 +228,52 @@ static void Drawer_SectionGeneral(SerializedHDRenderPipelineAsset serialized, Ed } } + static void Drawer_Volumetric(SerializedHDRenderPipelineAsset serialized, Editor owner) + { + EditorGUILayout.PropertyField(serialized.renderPipelineSettings.supportVolumetrics, Styles.supportVolumetricContent); + + using (new EditorGUI.DisabledGroupScope(!serialized.renderPipelineSettings.supportVolumetrics.boolValue)) + { + var lightSettings = serialized.renderPipelineSettings.lightLoopSettings; + EditorGUILayout.PropertyField(lightSettings.maxDensityVolumeSize, Styles.maxDensityVolumeSizeStyle); + EditorGUILayout.PropertyField(lightSettings.maxDensityVolumesOnScreen, Styles.maxDensityVolumesOnScreenStyle); + + // Clamp values + lightSettings.maxDensityVolumeSize.intValue = Mathf.Clamp(lightSettings.maxDensityVolumeSize.intValue, (int)DensityVolumeResolution.Resolution32, (int)DensityVolumeResolution.Resolution256); + lightSettings.maxDensityVolumesOnScreen.intValue = Mathf.Clamp(lightSettings.maxDensityVolumesOnScreen.intValue, 1, HDRenderPipeline.k_MaxVisibleDensityVolumeCount); + + if (lightSettings.maxDensityVolumeSize.hasMultipleDifferentValues || lightSettings.maxDensityVolumesOnScreen.hasMultipleDifferentValues) + EditorGUILayout.HelpBox(Styles.multipleDifferenteValueMessage, MessageType.Info); + else + { + long currentCache = Texture3DAtlas.GetApproxCacheSizeInByte( + lightSettings.maxDensityVolumeSize.intValue, + lightSettings.maxDensityVolumesOnScreen.intValue, + DensityVolumeManager.densityVolumeAtlasFormat, + true + ); + + if (currentCache > HDRenderPipeline.k_MaxCacheSize) + { + int count = Texture3DAtlas.GetMaxElementCountForWeightInByte( + HDRenderPipeline.k_MaxCacheSize, + lightSettings.maxDensityVolumeSize.intValue, + lightSettings.maxDensityVolumesOnScreen.intValue, + DensityVolumeManager.densityVolumeAtlasFormat, + true + ); + string message = string.Format(Styles.cacheErrorFormat, HDEditorUtils.HumanizeWeight(currentCache), count); + EditorGUILayout.HelpBox(message, MessageType.Error); + } + else + { + string message = string.Format(Styles.cacheInfoFormat, HDEditorUtils.HumanizeWeight(currentCache)); + EditorGUILayout.HelpBox(message, MessageType.Info); + } + } + } + } + static void Drawer_SectionCookies(SerializedHDRenderPipelineAsset serialized, Editor owner) { EditorGUILayout.PropertyField(serialized.renderPipelineSettings.lightLoopSettings.cookieAtlasSize, Styles.cookieAtlasSizeContent); @@ -967,8 +1015,6 @@ static void Drawer_SectionLightingUnsorted(SerializedHDRenderPipelineAsset seria EditorGUILayout.PropertyField(serialized.renderPipelineSettings.supportSSAO, Styles.supportSSAOContent); EditorGUILayout.PropertyField(serialized.renderPipelineSettings.supportSSGI, Styles.supportSSGIContent); - EditorGUILayout.PropertyField(serialized.renderPipelineSettings.supportVolumetrics, Styles.supportVolumetricContent); - EditorGUILayout.PropertyField(serialized.renderPipelineSettings.supportLightLayers, Styles.supportLightLayerContent); if (ShaderConfig.s_EnableProbeVolumes == 1) diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedGlobalLightLoopSettings.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedGlobalLightLoopSettings.cs index 9c25dabe355..d6e9dc8a54e 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedGlobalLightLoopSettings.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedGlobalLightLoopSettings.cs @@ -29,6 +29,8 @@ class SerializedGlobalLightLoopSettings public SerializedProperty maxDecalsOnScreen; public SerializedProperty maxPlanarReflectionOnScreen; public SerializedProperty maxLightsPerClusterCell; + public SerializedProperty maxDensityVolumeSize; + public SerializedProperty maxDensityVolumesOnScreen; public SerializedGlobalLightLoopSettings(SerializedProperty root) { @@ -60,6 +62,9 @@ public SerializedGlobalLightLoopSettings(SerializedProperty root) maxDecalsOnScreen = root.Find((GlobalLightLoopSettings s) => s.maxDecalsOnScreen); maxPlanarReflectionOnScreen = root.Find((GlobalLightLoopSettings s) => s.maxPlanarReflectionOnScreen); maxLightsPerClusterCell = root.Find((GlobalLightLoopSettings s) => s.maxLightsPerClusterCell); + + maxDensityVolumeSize = root.Find((GlobalLightLoopSettings s) => s.maxDensityVolumeSize); + maxDensityVolumesOnScreen = root.Find((GlobalLightLoopSettings s) => s.maxDensityVolumesOnScreen); } } } diff --git a/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.cs b/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.cs index 63192e2bd1a..f125cb407e4 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.cs @@ -1468,6 +1468,39 @@ void RegisterLightingDebug() }); } + list.Add(new DebugUI.BoolField { displayName = "Display Density Volume Atlas", getter = () => data.lightingDebugSettings.displayDensityVolumeAtlas, setter = value => data.lightingDebugSettings.displayDensityVolumeAtlas = value, onValueChanged = RefreshLightingDebug}); + if (data.lightingDebugSettings.displayDensityVolumeAtlas) + { + list.Add(new DebugUI.Container + { + children = + { + new DebugUI.UIntField { displayName = "Slice", getter = () => data.lightingDebugSettings.densityVolumeAtlasSlice, setter = value => data.lightingDebugSettings.densityVolumeAtlasSlice = value, min = () => 0, max = () => GetDensityVolumeSliceCount()}, + new DebugUI.BoolField { displayName = "Use Selection", getter = () => data.lightingDebugSettings.densityVolumeUseSelection, setter = value => data.lightingDebugSettings.densityVolumeUseSelection = value, flags = DebugUI.Flags.EditorOnly, onValueChanged = RefreshLightingDebug}, + } + }); + } + + uint GetDensityVolumeSliceCount() + { +#if UNITY_EDITOR + if (data.lightingDebugSettings.densityVolumeUseSelection) + { + var selectedGO = UnityEditor.Selection.activeGameObject; + if (selectedGO != null && selectedGO.TryGetComponent(out var densityVolume)) + { + var texture = densityVolume.parameters.volumeMask; + + if (texture != null) + return (uint)(texture is RenderTexture rt ? rt.volumeDepth : texture is Texture3D t3D ? t3D.depth : 1) - 1; + } + return 0; + } + else +#endif + return (uint)DensityVolumeManager.manager.volumeAtlas.GetAtlas().volumeDepth - 1; + } + list.Add(new DebugUI.FloatField { displayName = "Debug Overlay Screen Ratio", getter = () => data.debugOverlayRatio, setter = v => data.debugOverlayRatio = v, min = () => 0.1f, max = () => 1f}); m_DebugLightingItems = list.ToArray(); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Debug/LightingDebug.cs b/com.unity.render-pipelines.high-definition/Runtime/Debug/LightingDebug.cs index aa9a7385892..1a4df3a336c 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Debug/LightingDebug.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Debug/LightingDebug.cs @@ -361,6 +361,13 @@ public bool IsDebugDisplayEnabled() /// True if reflection probes lights should be displayed in the scene. public bool showReflectionProbe = true; + /// Display the density volume atlas. + public bool displayDensityVolumeAtlas = false; + /// Density volume atlas slice. + public uint densityVolumeAtlasSlice = 0; + /// True if Density Volume Atlas debug mode should be displayed for the currently selected Density Volume. + public bool densityVolumeUseSelection = false; + /// Tile and Cluster debug mode. public TileClusterDebug tileClusterDebug = TileClusterDebug.None; /// Category for tile and cluster debug mode. diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/GlobalLightLoopSettings.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/GlobalLightLoopSettings.cs index 0b1a09b1b08..aacdbf9769d 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/GlobalLightLoopSettings.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/GlobalLightLoopSettings.cs @@ -113,6 +113,22 @@ public enum CubeCookieResolution CubeCookieResolution4096 = 4096 } + /// + /// Possible values for one element of the density volume atlas. + /// + [Serializable] + public enum DensityVolumeResolution + { + /// 3D volume of 32x32x32 voxels. + Resolution32 = 32, + /// 3D volume of 64x64x64 voxels. + Resolution64 = 64, + /// 3D volume of 128x128x128 voxels. + Resolution128 = 128, + /// 3D volume of 256x256x256 voxels. + Resolution256 = 256, + } + /// /// Global Light Loop Settings. /// @@ -148,6 +164,8 @@ public struct GlobalLightLoopSettings maxDecalsOnScreen = 512, maxPlanarReflectionOnScreen = 16, maxLightsPerClusterCell = 8, + maxDensityVolumeSize = DensityVolumeResolution.Resolution32, + maxDensityVolumesOnScreen = 64, // 8MB texture atlas allocated by default }; /// Cookie atlas resolution. @@ -199,5 +217,10 @@ public struct GlobalLightLoopSettings public int maxPlanarReflectionOnScreen; /// Maximum number of lights per ray tracing light cluster cell. public int maxLightsPerClusterCell; + + /// Maximum size of one density volume texture. + public DensityVolumeResolution maxDensityVolumeSize; + /// Maximum number of density volumes at the same time on screen. + public int maxDensityVolumesOnScreen; } } diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs index 95139eac6ed..c7c3d7d4771 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.cs @@ -637,6 +637,7 @@ enum ClusterDepthSource : int Material[] m_deferredLightingMaterial; Material m_DebugViewTilesMaterial; Material m_DebugHDShadowMapMaterial; + Material m_DebugDensityVolumeMaterial; Material m_DebugBlitMaterial; Material m_DebugDisplayProbeVolumeMaterial; @@ -761,6 +762,7 @@ void InitializeLightLoop(IBLFilterBSDF[] iBLFilterBSDFArray) m_DebugViewTilesMaterial = CoreUtils.CreateEngineMaterial(defaultResources.shaders.debugViewTilesPS); m_DebugHDShadowMapMaterial = CoreUtils.CreateEngineMaterial(defaultResources.shaders.debugHDShadowMapPS); + m_DebugDensityVolumeMaterial = CoreUtils.CreateEngineMaterial(defaultResources.shaders.debugDensityVolumeAtlasPS); m_DebugBlitMaterial = CoreUtils.CreateEngineMaterial(defaultResources.shaders.debugBlitQuad); m_DebugDisplayProbeVolumeMaterial = CoreUtils.CreateEngineMaterial(defaultResources.shaders.debugDisplayProbeVolumePS); @@ -942,6 +944,7 @@ void CleanupLightLoop() CoreUtils.Destroy(m_DebugViewTilesMaterial); CoreUtils.Destroy(m_DebugHDShadowMapMaterial); + CoreUtils.Destroy(m_DebugDensityVolumeMaterial); CoreUtils.Destroy(m_DebugBlitMaterial); CoreUtils.Destroy(m_DebugDisplayProbeVolumeMaterial); } @@ -3809,6 +3812,7 @@ struct LightLoopDebugOverlayParameters public int debugSelectedLightShadowIndex; public int debugSelectedLightShadowCount; public Material debugShadowMapMaterial; + public Material debugDensityVolumeMaterial; public Material debugBlitMaterial; public LightCookieManager cookieManager; public PlanarReflectionProbeCache planarProbeCache; @@ -3823,6 +3827,7 @@ LightLoopDebugOverlayParameters PrepareLightLoopDebugOverlayParameters() parameters.debugSelectedLightShadowIndex = m_DebugSelectedLightShadowIndex; parameters.debugSelectedLightShadowCount = m_DebugSelectedLightShadowCount; parameters.debugShadowMapMaterial = m_DebugHDShadowMapMaterial; + parameters.debugDensityVolumeMaterial = m_DebugDensityVolumeMaterial; parameters.debugBlitMaterial = m_DebugBlitMaterial; parameters.cookieManager = m_TextureCaches.lightCookieManager; parameters.planarProbeCache = m_TextureCaches.reflectionPlanarProbeCache; @@ -3930,6 +3935,45 @@ static void RenderLightLoopDebugOverlay(in DebugParameters debugParameters, debugParameters.debugOverlay.Next(); } } + + if (lightingDebug.displayDensityVolumeAtlas) + { + using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.DisplayDensityVolumeAtlas))) + { + var atlas = DensityVolumeManager.manager.volumeAtlas; + var atlasTexture = atlas.GetAtlas(); + m_LightLoopDebugMaterialProperties.SetTexture(HDShaderIDs._InputTexture, atlasTexture); + m_LightLoopDebugMaterialProperties.SetFloat("_Slice", (float)lightingDebug.densityVolumeAtlasSlice); + m_LightLoopDebugMaterialProperties.SetVector("_Offset", Vector3.zero); + m_LightLoopDebugMaterialProperties.SetVector("_TextureSize", new Vector3(atlasTexture.width, atlasTexture.height, atlasTexture.volumeDepth)); + +#if UNITY_EDITOR + if (lightingDebug.densityVolumeUseSelection) + { + var obj = UnityEditor.Selection.activeGameObject; + + if (obj != null && obj.TryGetComponent(out var densityVolume)) + { + var texture = densityVolume.parameters.volumeMask; + + if (texture != null) + { + float textureDepth = texture is RenderTexture rt ? rt.volumeDepth : texture is Texture3D t3D ? t3D.depth : 0; + m_LightLoopDebugMaterialProperties.SetVector("_TextureSize", new Vector3(texture.width, texture.height, textureDepth)); + m_LightLoopDebugMaterialProperties.SetVector("_Offset", atlas.GetTextureOffset(texture)); + } + } + } +#endif + + debugParameters.debugOverlay.SetViewport(cmd); + cmd.DrawProcedural(Matrix4x4.identity, parameters.debugDensityVolumeMaterial, 0, MeshTopology.Triangles, 3, 1, m_LightLoopDebugMaterialProperties); + debugParameters.debugOverlay.Next(); + debugParameters.debugOverlay.SetViewport(cmd); + cmd.DrawProcedural(Matrix4x4.identity, parameters.debugDensityVolumeMaterial, 1, MeshTopology.Triangles, 3, 1, m_LightLoopDebugMaterialProperties); + debugParameters.debugOverlay.Next(); + } + } } static void RenderShadowsDebugOverlay(in DebugParameters debugParameters, in HDShadowManager.ShadowDebugAtlasTextures atlasTextures, CommandBuffer cmd, MaterialPropertyBlock mpb) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DebugDensityVolumeAtlas.shader b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DebugDensityVolumeAtlas.shader new file mode 100644 index 00000000000..dabf776c89d --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DebugDensityVolumeAtlas.shader @@ -0,0 +1,88 @@ +Shader "Hidden/HDRP/DebugDensityVolumeAtlas" +{ + SubShader + { + Tags{ "RenderPipeline" = "HDRenderPipeline" } + + HLSLINCLUDE + #pragma target 4.5 + #pragma only_renderers d3d11 playstation xboxone vulkan metal switch + #pragma vertex Vert + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + + TEXTURE3D(_InputTexture); + SAMPLER(sampler_InputTexture); + float _Slice; + float3 _Offset; + float3 _TextureSize; + + struct Attributes + { + uint vertexID : SV_VertexID; + }; + + struct Varyings + { + float4 positionCS : SV_POSITION; + float2 texcoord : TEXCOORD0; + }; + + Varyings Vert(Attributes input) + { + Varyings output; + output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID); + output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID); + + return output; + } + + float3 GetUVs(float2 texcoords) + { + return float3(texcoords * float2(1, _TextureSize.x / _TextureSize.y) * _TextureSize, _Slice) + _Offset; + } + + float4 Color(Varyings input) : SV_Target + { + float3 uv = GetUVs(input.texcoord.xy); + + return float4(LOAD_TEXTURE3D_LOD(_InputTexture, uv, 0).rgb, 1); + } + + float4 Alpha(Varyings input) : SV_Target + { + float3 uv = GetUVs(input.texcoord.xy); + + return float4(LOAD_TEXTURE3D_LOD(_InputTexture, uv, 0).aaa, 1); + } + + ENDHLSL + + Pass + { + ZWrite On + ZTest Always + Blend Off + Cull Off + + HLSLPROGRAM + #pragma fragment Color + ENDHLSL + } + + Pass + { + ZWrite On + ZTest Always + Blend Off + Cull Off + + HLSLPROGRAM + #pragma fragment Alpha + ENDHLSL + } + } + Fallback Off +} diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DebugDensityVolumeAtlas.shader.meta b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DebugDensityVolumeAtlas.shader.meta new file mode 100644 index 00000000000..9cfa7025104 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DebugDensityVolumeAtlas.shader.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 8371b763f09c7304889c22aa97ebdfd2 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DensityVolume.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DensityVolume.cs index 14519de5f4e..b5583e8df44 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DensityVolume.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DensityVolume.cs @@ -16,7 +16,7 @@ public partial struct DensityVolumeArtistParameters public float anisotropy; // . Not currently available for density volumes /// Texture containing density values. - public Texture3D volumeMask; + public Texture volumeMask; /// Scrolling speed of the density texture. public Vector3 textureScrollingSpeed; /// Tiling rate of the density texture. @@ -47,12 +47,16 @@ public partial struct DensityVolumeArtistParameters public float distanceFadeStart; /// Distance at which density fading ends. public float distanceFadeEnd; - [SerializeField] - internal int textureIndex; /// Allows translation of the tiling density texture. [SerializeField, FormerlySerializedAs("volumeScrollingAmount")] public Vector3 textureOffset; + /// When Blend Distance is above 0, controls which kind of falloff is applied to the transition area. + public DensityVolumeFalloffMode falloffMode; + + /// Minimum fog distance you can set in the meanFreePath parameter + internal const float kMinFogDistance = 0.05f; + /// Constructor. /// Single scattering albedo. /// Mean free path. @@ -64,7 +68,6 @@ public DensityVolumeArtistParameters(Color color, float _meanFreePath, float _an anisotropy = _anisotropy; volumeMask = null; - textureIndex = -1; textureScrollingSpeed = Vector3.zero; textureTiling = Vector3.one; textureOffset = textureScrollingSpeed; @@ -78,6 +81,8 @@ public DensityVolumeArtistParameters(Color color, float _meanFreePath, float _an distanceFadeStart = 10000; distanceFadeEnd = 10000; + falloffMode = DensityVolumeFalloffMode.Linear; + m_EditorPositiveFade = Vector3.zero; m_EditorNegativeFade = Vector3.zero; m_EditorUniformFade = 0; @@ -104,7 +109,7 @@ internal void Constrain() albedo.b = Mathf.Clamp01(albedo.b); albedo.a = 1.0f; - meanFreePath = Mathf.Clamp(meanFreePath, 1.0f, float.MaxValue); + meanFreePath = Mathf.Clamp(meanFreePath, kMinFogDistance, float.MaxValue); anisotropy = Mathf.Clamp(anisotropy, -1.0f, 1.0f); @@ -119,9 +124,16 @@ internal DensityVolumeEngineData ConvertToEngineData() DensityVolumeEngineData data = new DensityVolumeEngineData(); data.extinction = VolumeRenderingUtils.ExtinctionFromMeanFreePath(meanFreePath); - data.scattering = VolumeRenderingUtils.ScatteringFromExtinctionAndAlbedo(data.extinction, (Vector3)(Vector4)albedo); - - data.textureIndex = textureIndex; + data.scattering = VolumeRenderingUtils.ScatteringFromExtinctionAndAlbedo(data.extinction, (Vector4)albedo); + + var atlas = DensityVolumeManager.manager.volumeAtlas.GetAtlas(); + data.atlasOffset = DensityVolumeManager.manager.volumeAtlas.GetTextureOffset(volumeMask); + data.atlasOffset.x /= (float)atlas.width; + data.atlasOffset.y /= (float)atlas.height; + data.atlasOffset.z /= (float)atlas.volumeDepth; + data.useVolumeMask = volumeMask != null ? 1 : 0; + float volumeMaskSize = volumeMask != null ? (float)volumeMask.width : 0.0f; // Volume Mask Textures are always cubic + data.maskSize = new Vector4(volumeMaskSize / atlas.width, volumeMaskSize / atlas.height, volumeMaskSize / atlas.volumeDepth, volumeMaskSize); data.textureScroll = textureOffset; data.textureTiling = textureTiling; @@ -138,6 +150,7 @@ internal DensityVolumeEngineData ConvertToEngineData() data.rcpNegFaceFade.z = Mathf.Min(1.0f / negativeFade.z, float.MaxValue); data.invertFade = invertFade ? 1 : 0; + data.falloffMode = falloffMode; float distFadeLen = Mathf.Max(distanceFadeEnd - distanceFadeStart, 0.00001526f); @@ -157,7 +170,7 @@ public partial class DensityVolume : MonoBehaviour /// Density volume parameters. public DensityVolumeArtistParameters parameters = new DensityVolumeArtistParameters(Color.white, 10.0f, 0.0f); - private Texture3D previousVolumeMask = null; + private Texture previousVolumeMask = null; #if UNITY_EDITOR private int volumeMaskHash = 0; #endif @@ -178,6 +191,9 @@ internal void PrepareParameters(bool animate, float time) if (updated) { + if (parameters.volumeMask != null) + DensityVolumeManager.manager.AddTextureIntoAtlas(parameters.volumeMask); + NotifyUpdatedTexure(); previousVolumeMask = parameters.volumeMask; #if UNITY_EDITOR @@ -202,12 +218,12 @@ private void OnEnable() #if UNITY_EDITOR // Handle scene visibility - UnityEditor.SceneVisibilityManager.visibilityChanged += UpdateDecalVisibility; + UnityEditor.SceneVisibilityManager.visibilityChanged += UpdateDensityVolumeVisibility; #endif } #if UNITY_EDITOR - void UpdateDecalVisibility() + void UpdateDensityVolumeVisibility() { if (UnityEditor.SceneVisibilityManager.instance.IsHidden(gameObject)) { @@ -228,7 +244,7 @@ private void OnDisable() DensityVolumeManager.manager.DeRegisterVolume(this); #if UNITY_EDITOR - UnityEditor.SceneVisibilityManager.visibilityChanged -= UpdateDecalVisibility; + UnityEditor.SceneVisibilityManager.visibilityChanged -= UpdateDensityVolumeVisibility; #endif } diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DensityVolumeManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DensityVolumeManager.cs index 0786c33445a..8927159c156 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DensityVolumeManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/DensityVolumeManager.cs @@ -1,115 +1,131 @@ using System.Collections.Generic; +using UnityEngine.Experimental.Rendering; namespace UnityEngine.Rendering.HighDefinition { class DensityVolumeManager { - static private DensityVolumeManager _instance = null; + public static readonly GraphicsFormat densityVolumeAtlasFormat = GraphicsFormat.R8G8B8A8_UNorm; + static DensityVolumeManager m_Manager; public static DensityVolumeManager manager { get { - if (_instance == null) + if (m_Manager == null) + m_Manager = new DensityVolumeManager(); + return m_Manager; + } + } + + Texture3DAtlas m_VolumeAtlas = null; + public Texture3DAtlas volumeAtlas + { + get + { + if (m_VolumeAtlas == null) { - _instance = new DensityVolumeManager(); + var settings = HDRenderPipeline.currentAsset.currentPlatformRenderPipelineSettings.lightLoopSettings; + + // Prevent allocating too big textures: + int elementCount = Texture3DAtlas.GetMaxElementCountForWeightInByte( + HDRenderPipeline.k_MaxCacheSize, + (int)settings.maxDensityVolumeSize, + settings.maxDensityVolumesOnScreen, + densityVolumeAtlasFormat, + true + ); + + elementCount = Mathf.Clamp(elementCount, 1, settings.maxDensityVolumesOnScreen); + + m_VolumeAtlas = new Texture3DAtlas(densityVolumeAtlasFormat, (int)settings.maxDensityVolumeSize, elementCount); + + // When HDRP is initialized and this atlas created, some density volume may have been initialized before so we add them here. + foreach (var volume in m_Volumes) + { + if (volume.parameters.volumeMask != null) + AddTextureIntoAtlas(volume.parameters.volumeMask); + } } - return _instance; + + return m_VolumeAtlas; } } - public Texture3DAtlas volumeAtlas = null; - private bool atlasNeedsRefresh = false; + List m_Volumes = null; - //TODO: hardcoded size....:-( - public static int volumeTextureSize = 32; - - private DensityVolumeManager() + DensityVolumeManager() { - volumes = new List(); - - volumeAtlas = new Texture3DAtlas(TextureFormat.Alpha8, volumeTextureSize); - - volumeAtlas.OnAtlasUpdated += AtlasUpdated; + m_Volumes = new List(); } - private List volumes = null; - public void RegisterVolume(DensityVolume volume) { - volumes.Add(volume); + m_Volumes.Add(volume); - volume.OnTextureUpdated += TriggerVolumeAtlasRefresh; + // In case the density volume format is not support (which is impossible because all HDRP target supports R8G8B8A8_UNorm) + // we avoid doing operations on the atlas. + // This happens in the CI on linux when an editor using OpenGL is building a player for Vulkan. + if (!SystemInfo.IsFormatSupported(densityVolumeAtlasFormat, FormatUsage.LoadStore)) + return; if (volume.parameters.volumeMask != null) { - volumeAtlas.AddTexture(volume.parameters.volumeMask); + if (volumeAtlas.IsTextureValid(volume.parameters.volumeMask)) + { + AddTextureIntoAtlas(volume.parameters.volumeMask); + } } } + internal void AddTextureIntoAtlas(Texture volumeTexture) + { + if (!volumeAtlas.AddTexture(volumeTexture)) + Debug.LogError($"No more space in the density volume atlas, consider increasing the max density volume on screen in the HDRP asset."); + } + public void DeRegisterVolume(DensityVolume volume) { - if (volumes.Contains(volume)) - { - volumes.Remove(volume); - } + if (m_Volumes.Contains(volume)) + m_Volumes.Remove(volume); - volume.OnTextureUpdated -= TriggerVolumeAtlasRefresh; + // In case the density volume format is not support (which is impossible because all HDRP target supports R8G8B8A8_UNorm) + // we avoid doing operations on the atlas. + // This happens in the CI on linux when an editor using OpenGL is building a player for Vulkan. + if (!SystemInfo.IsFormatSupported(densityVolumeAtlasFormat, FormatUsage.LoadStore)) + return; if (volume.parameters.volumeMask != null) { - volumeAtlas.RemoveTexture(volume.parameters.volumeMask); + // Avoid to alloc the atlas to remove a texture if it's not allocated yet. + if (m_VolumeAtlas != null) + volumeAtlas.RemoveTexture(volume.parameters.volumeMask); } - - //Upon removal we have to refresh the texture list. - TriggerVolumeAtlasRefresh(); } - public bool ContainsVolume(DensityVolume volume) => volumes.Contains(volume); + public bool ContainsVolume(DensityVolume volume) => m_Volumes.Contains(volume); public List PrepareDensityVolumeData(CommandBuffer cmd, HDCamera currentCam, float time) { //Update volumes bool animate = currentCam.animateMaterials; - foreach (DensityVolume volume in volumes) - { + foreach (DensityVolume volume in m_Volumes) volume.PrepareParameters(animate, time); - } - if (atlasNeedsRefresh) + using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.UpdateDensityVolumeAtlas))) { - atlasNeedsRefresh = false; - VolumeAtlasRefresh(); + volumeAtlas.Update(cmd); } - volumeAtlas.GenerateAtlas(cmd); - - return volumes; + return m_Volumes; } - private void VolumeAtlasRefresh() + // Note that this function will not release the manager itself as it have to live outside of HDRP to handle density volume components + internal void ReleaseAtlas() { - volumeAtlas.ClearTextures(); - foreach (DensityVolume volume in volumes) - { - if (volume.parameters.volumeMask != null) - { - volumeAtlas.AddTexture(volume.parameters.volumeMask); - } - } - } - - public void TriggerVolumeAtlasRefresh() - { - atlasNeedsRefresh = true; - } - - private void AtlasUpdated() - { - foreach (DensityVolume volume in volumes) - { - volume.parameters.textureIndex = volumeAtlas.GetTextureIndex(volume.parameters.volumeMask); - } + // Release the atlas so next time the manager is used, it is reallocated with new HDRP settings. + volumeAtlas.Release(); + m_VolumeAtlas = null; } } } diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/Texture3DAtlas.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/Texture3DAtlas.cs deleted file mode 100644 index 5d764c93b7e..00000000000 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/Texture3DAtlas.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace UnityEngine.Rendering.HighDefinition -{ - class Texture3DAtlas - { - private List m_textures = new List(); - - private Texture3D m_atlas; - private TextureFormat m_format; - - private bool m_updateAtlas = false; - private int m_atlasSize = 0; - - public delegate void AtlasUpdated(); - public AtlasUpdated OnAtlasUpdated = null; - - - void NotifyAtlasUpdated() - { - if (OnAtlasUpdated != null) - { - OnAtlasUpdated(); - } - } - - public Texture3DAtlas(TextureFormat format, int textureSize) - { - m_format = format; - m_atlasSize = textureSize; - } - - public void AddTexture(Texture3D tex) - { - if (m_textures.Contains(tex)) - { - return; - } - - if (tex.width != m_atlasSize || tex.height != m_atlasSize || tex.depth != m_atlasSize) - { - Debug.LogError(String.Format("3D Texture Atlas: Added texture {4} size {0}x{1}x{2} does not match size of atlas {3}x{3}x{3}", tex.width, tex.height, tex.depth, m_atlasSize, tex.name)); - return; - } - - if (tex.format != m_format) - { - Debug.LogError(String.Format("3D Texture Atlas: Added texture {2} format {0} does not match format of atlas {1}", tex.format, m_format, tex.name)); - return; - } - - m_textures.Add(tex); - - m_updateAtlas = true; - } - - public void RemoveTexture(Texture3D tex) - { - if (m_textures.Contains(tex)) - { - m_textures.Remove(tex); - m_updateAtlas = true; - } - } - - public void ClearTextures() - { - m_textures.Clear(); - m_updateAtlas = true; - } - - public int GetTextureIndex(Texture3D tex) - { - return m_textures.IndexOf(tex); - } - - public void GenerateAtlas(CommandBuffer cmd) - { - if (!m_updateAtlas) - { - return; - } - - if (m_textures.Count > 0) - { - int textureSliceSize = m_atlasSize * m_atlasSize * m_atlasSize; - int totalTextureSize = textureSliceSize * m_textures.Count; - - Color[] colorData = new Color[totalTextureSize]; - m_atlas = new Texture3D(m_atlasSize, m_atlasSize, m_atlasSize * m_textures.Count, m_format, true); - - //Iterate through all the textures and append their texture data to the texture array - //Once CopyTexture works for 3D textures we can replace this with a series of copy texture calls - for (int i = 0; i < m_textures.Count; i++) - { - Texture3D tex = m_textures[i]; - Color[] texData = tex.GetPixels(); - Array.Copy(texData, 0, colorData, textureSliceSize * i, texData.Length); - } - - m_atlas.SetPixels(colorData); - m_atlas.Apply(); - } - else - { - m_atlas = null; - } - - NotifyAtlasUpdated(); - - m_updateAtlas = false; - } - - public Texture3D GetAtlas() - { - return m_atlas; - } - } -} 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 e33043bd767..ccaaac66af6 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 @@ -22,6 +22,8 @@ #define GROUP_SIZE_1D 8 #define SOFT_VOXELIZATION 1 // Hack which attempts to determine partial coverage of the voxel +#define EXPONENTIAL_FALLOFF_EXPONENT 2.2 + //-------------------------------------------------------------------------------------------------- // Included headers //-------------------------------------------------------------------------------------------------- @@ -61,7 +63,7 @@ struct JitteredRay float ComputeFadeFactor(float3 coordNDC, float dist, float3 rcpPosFaceFade, float3 rcpNegFaceFade, bool invertFade, - float rcpDistFadeLen, float endTimesRcpDistFadeLen) + float rcpDistFadeLen, float endTimesRcpDistFadeLen, int falloffMode) { // We have to account for handedness. coordNDC.z = 1 - coordNDC.z; @@ -71,24 +73,20 @@ float ComputeFadeFactor(float3 coordNDC, float dist, float dstF = Remap10(dist, rcpDistFadeLen, endTimesRcpDistFadeLen); float fade = posF.x * posF.y * posF.z * negF.x * negF.y * negF.z; - return dstF * (invertFade ? (1 - fade) : fade); -} - -float SampleVolumeMask(DensityVolumeEngineData volumeData, float3 voxelCenterNDC, float3 duvw_dx, float3 duvw_dy, float3 duvw_dz) -{ - // Scale and bias the UVWs and then take fractional part, will be in [0,1] range. - float3 voxelCenterUVW = frac(voxelCenterNDC * volumeData.textureTiling + volumeData.textureScroll); + // We only apply exponential falloff on the Blend Distance and not Distance Fade + if (falloffMode == DENSITYVOLUMEFALLOFFMODE_EXPONENTIAL) + fade = PositivePow(fade, EXPONENTIAL_FALLOFF_EXPONENT); - float rcpNumTextures = _VolumeMaskDimensions.x; - float textureWidth = _VolumeMaskDimensions.y; - float textureDepth = _VolumeMaskDimensions.z; - float maxLod = _VolumeMaskDimensions.w; + fade = dstF * (invertFade ? (1 - fade) : fade); - float offset = volumeData.textureIndex * rcpNumTextures; - voxelCenterUVW.z = voxelCenterUVW.z * rcpNumTextures + offset; + return fade; +} +float4 SampleVolumeMask(DensityVolumeEngineData volumeData, float3 voxelCenterNDC, float3 duvw_dx, float3 duvw_dy, float3 duvw_dz) +{ + float maxLod = log2(volumeData.maskSize.w); // TODO: expose the LoD bias parameter. - float lod = ComputeTextureLOD(duvw_dx, duvw_dy, duvw_dz, textureWidth); + float lod = ComputeTextureLOD(duvw_dx, duvw_dy, duvw_dz, volumeData.maskSize.w); lod = clamp(lod, 0, maxLod); // TODO: bugfix. @@ -99,13 +97,20 @@ float SampleVolumeMask(DensityVolumeEngineData volumeData, float3 voxelCenterNDC // If you use ceil(lod), the upper LoD effectively loses a texel at the border, which may break tileable textures. // For now, we choose the second option. // We support texture filtering across the wrap in Z in neither case. - int textureSize = (int)textureDepth; + int textureSize = (int)volumeData.maskSize.w; int mipSize = textureSize >> (int)ceil(lod); float halfTexelSize = 0.5f * rcp(mipSize); - voxelCenterUVW.z = clamp(voxelCenterUVW.z, offset + halfTexelSize, offset + rcpNumTextures - halfTexelSize); + + // Scale and bias the UVWs and then take fractional part, will be in [0,1] range. + float3 voxelCenterUVW = frac(voxelCenterNDC * volumeData.textureTiling + volumeData.textureScroll); + voxelCenterUVW = clamp(voxelCenterUVW, halfTexelSize, 1 - halfTexelSize); + + // And then a scale depending on the atlas resolution. + // Note that the z coordinate is never scaled or offseted because we don't store textures in thsi direction. + voxelCenterUVW = voxelCenterUVW * volumeData.maskSize.xyz + volumeData.atlasOffset; // Reminder: still no filtering across the the wrap in Z. - return SAMPLE_TEXTURE3D_LOD(_VolumeMaskAtlas, s_trilinear_repeat_sampler, voxelCenterUVW, lod).a; + return SAMPLE_TEXTURE3D_LOD(_VolumeMaskAtlas, s_trilinear_repeat_sampler, voxelCenterUVW, lod); } void FillVolumetricDensityBuffer(PositionInputs posInput, uint tileIndex, JitteredRay ray) @@ -275,20 +280,24 @@ void FillVolumetricDensityBuffer(PositionInputs posInput, uint tileIndex, Jitter _VolumeData[volumeIndex].rcpNegFaceFade, _VolumeData[volumeIndex].invertFade, _VolumeData[volumeIndex].rcpDistFadeLen, - _VolumeData[volumeIndex].endTimesRcpDistFadeLen); + _VolumeData[volumeIndex].endTimesRcpDistFadeLen, + _VolumeData[volumeIndex].falloffMode); - // Sample the volumeMask. - if (_VolumeData[volumeIndex].textureIndex != -1) + float3 scatteringMultiplier = 1; + // Sample the volume Mask + Scattering color. + if (_VolumeData[volumeIndex].useVolumeMask > 0) { float3 xDerivUVW = (0.5 * t) * voxelAxisRightBS * rcp(obbExtents); float3 yDerivUVW = (0.5 * t) * voxelAxisUpBS * rcp(obbExtents); float3 zDerivUVW = (0.5 * dt) * voxelAxisForwardBS * rcp(obbExtents); - overlapFraction *= SampleVolumeMask(_VolumeData[volumeIndex], voxelCenterNDC, xDerivUVW, yDerivUVW, zDerivUVW); + float4 volumeMask = SampleVolumeMask(_VolumeData[volumeIndex], voxelCenterNDC, xDerivUVW, yDerivUVW, zDerivUVW); + overlapFraction *= volumeMask.a; + scatteringMultiplier *= volumeMask.rgb; } // There is an overlap. Sample the 3D texture, or load the constant value. - voxelScattering += overlapFraction * _VolumeData[volumeIndex].scattering; + voxelScattering += overlapFraction * _VolumeData[volumeIndex].scattering * scatteringMultiplier; voxelExtinction += overlapFraction * _VolumeData[volumeIndex].extinction; } } 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 0c85a85f87b..71073b330b4 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 @@ -13,13 +13,16 @@ struct DensityVolumeEngineData public Vector3 scattering; // [0, 1] public float extinction; // [0, 1] public Vector3 textureTiling; - public int textureIndex; - public Vector3 textureScroll; public int invertFade; // bool... - public Vector3 rcpPosFaceFade; + public Vector3 textureScroll; public float rcpDistFadeLen; - public Vector3 rcpNegFaceFade; + public Vector3 rcpPosFaceFade; public float endTimesRcpDistFadeLen; + public Vector3 rcpNegFaceFade; + public int useVolumeMask; // bool + public Vector3 atlasOffset; // coordinates in the atlas in pixels + public DensityVolumeFalloffMode falloffMode; + public Vector4 maskSize; // xyz: atlas size / mask size, w: mask size in pixels public static DensityVolumeEngineData GetNeutralValues() { @@ -27,7 +30,7 @@ public static DensityVolumeEngineData GetNeutralValues() data.scattering = Vector3.zero; data.extinction = 0; - data.textureIndex = -1; + data.atlasOffset = Vector3.zero; data.textureTiling = Vector3.one; data.textureScroll = Vector3.zero; data.rcpPosFaceFade = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); @@ -35,6 +38,9 @@ public static DensityVolumeEngineData GetNeutralValues() data.invertFade = 0; data.rcpDistFadeLen = 0; data.endTimesRcpDistFadeLen = 1; + data.useVolumeMask = 0; + data.maskSize = Vector4.zero; + data.falloffMode = DensityVolumeFalloffMode.Linear; return data; } @@ -74,6 +80,15 @@ unsafe struct ShaderVariablesVolumetric public uint _Pad1_SVV; } + /// + [GenerateHLSL] + public enum DensityVolumeFalloffMode + { + /// + Linear, + /// + Exponential, + } class VolumeRenderingUtils { @@ -205,7 +220,7 @@ public partial class HDRenderPipeline List m_VisibleVolumeBounds = null; List m_VisibleVolumeData = null; - const int k_MaxVisibleVolumeCount = 512; + internal const int k_MaxVisibleDensityVolumeCount = 512; // Static keyword is required here else we get a "DestroyBuffer can only be called from the main thread" ComputeBuffer m_VisibleVolumeBoundsBuffer = null; @@ -572,8 +587,8 @@ internal void CreateVolumetricLightingBuffers() 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))); + m_VisibleVolumeBoundsBuffer = new ComputeBuffer(k_MaxVisibleDensityVolumeCount, Marshal.SizeOf(typeof(OrientedBBox))); + m_VisibleVolumeDataBuffer = new ComputeBuffer(k_MaxVisibleDensityVolumeCount, Marshal.SizeOf(typeof(DensityVolumeEngineData))); // Allocate the smallest possible 3D texture. // We will perform rescaling manually, in a custom manner, based on volume parameters. @@ -742,7 +757,7 @@ DensityVolumeList PrepareVisibleDensityVolumeList(HDCamera hdCamera, CommandBuff // Collect all visible finite volume data, and upload it to the GPU. var volumes = DensityVolumeManager.manager.PrepareDensityVolumeData(cmd, hdCamera, time); - for (int i = 0; i < Math.Min(volumes.Count, k_MaxVisibleVolumeCount); i++) + for (int i = 0; i < Math.Min(volumes.Count, k_MaxVisibleDensityVolumeCount); i++) { DensityVolume volume = volumes[i]; @@ -785,7 +800,7 @@ struct VolumeVoxelizationParameters public int viewCount; public bool tiledLighting; - public Texture3D volumeAtlas; + public Texture volumeAtlas; public ShaderVariablesVolumetric volumetricCB; public ShaderVariablesLightList lightListCB; @@ -833,10 +848,10 @@ unsafe void UpdateShaderVariableslVolumetrics(ref ShaderVariablesVolumetric cb, cb._VolumeMaskDimensions = Vector4.zero; if (DensityVolumeManager.manager.volumeAtlas.GetAtlas() != null) { - cb._VolumeMaskDimensions.x = (float)volumeAtlas.width / volumeAtlas.depth; // 1 / number of textures - cb._VolumeMaskDimensions.y = volumeAtlas.width; - cb._VolumeMaskDimensions.z = volumeAtlas.depth; - cb._VolumeMaskDimensions.w = Mathf.Log(volumeAtlas.width, 2); // Max LoD + cb._VolumeMaskDimensions.x = volumeAtlas.width; // 1 / number of textures + cb._VolumeMaskDimensions.y = volumeAtlas.height; + cb._VolumeMaskDimensions.z = volumeAtlas.volumeDepth; + cb._VolumeMaskDimensions.w = 0; // Not used } SetPreconvolvedAmbientLightProbe(ref cb, hdCamera, fog); 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 06f40f7f870..e3b0e94022f 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 @@ -4,6 +4,12 @@ #ifndef VOLUMETRICLIGHTING_CS_HLSL #define VOLUMETRICLIGHTING_CS_HLSL +// +// UnityEngine.Rendering.HighDefinition.DensityVolumeFalloffMode: static fields +// +#define DENSITYVOLUMEFALLOFFMODE_LINEAR (0) +#define DENSITYVOLUMEFALLOFFMODE_EXPONENTIAL (1) + // Generated from UnityEngine.Rendering.HighDefinition.DensityVolumeEngineData // PackingRules = Exact struct DensityVolumeEngineData @@ -11,13 +17,16 @@ struct DensityVolumeEngineData float3 scattering; float extinction; float3 textureTiling; - int textureIndex; - float3 textureScroll; int invertFade; - float3 rcpPosFaceFade; + float3 textureScroll; float rcpDistFadeLen; - float3 rcpNegFaceFade; + float3 rcpPosFaceFade; float endTimesRcpDistFadeLen; + float3 rcpNegFaceFade; + int useVolumeMask; + float3 atlasOffset; + int falloffMode; + float4 maskSize; }; // Generated from UnityEngine.Rendering.HighDefinition.ShaderVariablesVolumetric @@ -61,33 +70,45 @@ float3 GetTextureTiling(DensityVolumeEngineData value) { return value.textureTiling; } -int GetTextureIndex(DensityVolumeEngineData value) +int GetInvertFade(DensityVolumeEngineData value) { - return value.textureIndex; + return value.invertFade; } float3 GetTextureScroll(DensityVolumeEngineData value) { return value.textureScroll; } -int GetInvertFade(DensityVolumeEngineData value) +float GetRcpDistFadeLen(DensityVolumeEngineData value) { - return value.invertFade; + return value.rcpDistFadeLen; } float3 GetRcpPosFaceFade(DensityVolumeEngineData value) { return value.rcpPosFaceFade; } -float GetRcpDistFadeLen(DensityVolumeEngineData value) +float GetEndTimesRcpDistFadeLen(DensityVolumeEngineData value) { - return value.rcpDistFadeLen; + return value.endTimesRcpDistFadeLen; } float3 GetRcpNegFaceFade(DensityVolumeEngineData value) { return value.rcpNegFaceFade; } -float GetEndTimesRcpDistFadeLen(DensityVolumeEngineData value) +int GetUseVolumeMask(DensityVolumeEngineData value) { - return value.endTimesRcpDistFadeLen; + return value.useVolumeMask; +} +float3 GetAtlasOffset(DensityVolumeEngineData value) +{ + return value.atlasOffset; +} +int GetFalloffMode(DensityVolumeEngineData value) +{ + return value.falloffMode; +} +float4 GetMaskSize(DensityVolumeEngineData value) +{ + return value.maskSize; } #endif diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDProfileId.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDProfileId.cs index 799da5afb51..06949675547 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDProfileId.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDProfileId.cs @@ -73,6 +73,7 @@ internal enum HDProfileId DisplayPlanarReflectionProbeAtlas, BlitTextureInPotAtlas, AreaLightCookieConvolution, + DisplayDensityVolumeAtlas, UpdateSkyEnvironmentConvolution, RenderSkyToCubemap, @@ -88,6 +89,7 @@ internal enum HDProfileId VolumetricLighting, VolumetricLightingFiltering, PrepareVisibleDensityVolumeList, + UpdateDensityVolumeAtlas, // RT Cluster RaytracingBuildCluster, diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs index e3327bd1423..f19ad74f37f 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs @@ -204,7 +204,8 @@ void RenderLightLoopDebugOverlay(RenderGraph renderGraph, in DebugParameters deb var lightingDebug = debugParameters.debugDisplaySettings.data.lightingDebugSettings; if (lightingDebug.tileClusterDebug == TileClusterDebug.None && !lightingDebug.displayCookieAtlas - && !lightingDebug.displayPlanarReflectionProbeAtlas) + && !lightingDebug.displayPlanarReflectionProbeAtlas + && !lightingDebug.displayDensityVolumeAtlas) return; using (var builder = renderGraph.AddRenderPass("RenderLightLoopDebugOverlay", out var passData)) 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 c739c0f4472..cb343cbc3f1 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -900,6 +900,8 @@ protected override void Dispose(bool disposing) CustomPassVolume.Cleanup(); + DensityVolumeManager.manager.ReleaseAtlas(); + CleanupPrepass(); CoreUtils.Destroy(m_ColorResolveMaterial); CoreUtils.Destroy(m_MotionVectorResolve); 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 e4584589e4b..4415ebfc9e2 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs @@ -929,6 +929,15 @@ static class HDShaderIDs public static readonly int _AtlasTextureOctahedralDepthScaleBias = Shader.PropertyToID("_AtlasTextureOctahedralDepthScaleBias"); public static readonly int _ValidRange = Shader.PropertyToID("_ValidRange"); public static readonly int _ProbeVolumeAtlasSliceMode = Shader.PropertyToID("_ProbeVolumeAtlasSliceMode"); + + // 3D Atlas + public static readonly int _Dst3DTexture = Shader.PropertyToID("_Dst3DTexture"); + public static readonly int _Src3DTexture = Shader.PropertyToID("_Src3DTexture"); + public static readonly int _AlphaOnlyTexture = Shader.PropertyToID("_AlphaOnlyTexture"); + public static readonly int _SrcSize = Shader.PropertyToID("_SrcSize"); + public static readonly int _SrcMip = Shader.PropertyToID("_SrcMip"); + public static readonly int _SrcScale = Shader.PropertyToID("_SrcScale"); + public static readonly int _SrcOffset = Shader.PropertyToID("_SrcOffset"); } /// diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPipelineResources.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPipelineResources.cs index a0114e7a2ba..011d5fea80e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPipelineResources.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPipelineResources.cs @@ -102,6 +102,9 @@ public sealed class ShaderResources [Reload("Runtime/Material/SubsurfaceScattering/CombineLighting.shader")] public Shader combineLightingPS; + [Reload("Runtime/Lighting/VolumetricLighting/DebugDensityVolumeAtlas.shader")] + public Shader debugDensityVolumeAtlasPS; + // General [Reload("Runtime/RenderPipeline/RenderPass/MotionVectors/CameraMotionVectors.shader")] public Shader cameraMotionVectorsPS; @@ -186,6 +189,8 @@ public sealed class ShaderResources public Shader customPassUtils; [Reload("Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassRenderersUtils.shader")] public Shader customPassRenderersUtils; + [Reload("Runtime/RenderPipeline/Utility/Texture3DAtlas.compute")] + public ComputeShader texture3DAtlasCS; // XR [Reload("Runtime/ShaderLibrary/XRMirrorView.shader")] diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.compute b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.compute new file mode 100644 index 00000000000..a28336235b9 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.compute @@ -0,0 +1,51 @@ +#pragma kernel Copy +#pragma kernel GenerateMipMap +#pragma only_renderers d3d11 playstation xboxone vulkan metal switch + +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + +Texture3D _Src3DTexture; +RWTexture3D _Dst3DTexture; +float3 _DstOffset; +float _SrcMip; +float _AlphaOnlyTexture; +uint _SrcSize; + +[numthreads(8,8,8)] +void Copy(uint3 id : SV_DispatchThreadID) +{ + if (any(id >= _SrcSize)) + return; + + float4 value = LOAD_TEXTURE3D_LOD(_Src3DTexture, id, _SrcMip); + + if (_AlphaOnlyTexture) + _Dst3DTexture[id + _DstOffset] = float4(1, 1, 1, value.a); + else + _Dst3DTexture[id + _DstOffset] = value; +} + +float3 _SrcScale; +float3 _SrcOffset; +SAMPLER(s_linear_clamp_sampler); + +[numthreads(8, 8, 8)] +void GenerateMipMap(uint3 id : SV_DispatchThreadID) +{ + if (any(id >= _SrcSize)) + return; + + float3 uvw = float3(id) / _SrcSize + rcp(_SrcSize * 2); + + // Apply scale and bias when we sample from the atlas + uvw *= _SrcScale; + uvw += _SrcOffset; + + // Then we use the bilinear filter to interpolate the value of the next mip level + float4 value = SAMPLE_TEXTURE3D_LOD(_Src3DTexture, s_linear_clamp_sampler, uvw, _SrcMip); + + if (_AlphaOnlyTexture) + _Dst3DTexture[id + _DstOffset] = float4(1, 1, 1, value.a); + else + _Dst3DTexture[id + _DstOffset] = value; +} diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.compute.meta b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.compute.meta new file mode 100644 index 00000000000..806095afa59 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.compute.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 81522e314a83afd4a8ed43bd00757051 +ComputeShaderImporter: + externalObjects: {} + currentAPIMask: 4 + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.cs new file mode 100644 index 00000000000..1d89cf6e6ed --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.cs @@ -0,0 +1,545 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using UnityEngine.Experimental.Rendering; + +namespace UnityEngine.Rendering.HighDefinition +{ + /// + /// Texture 3D atlas. It can only stores power of two cubic textures. + /// In this atlas, texture are guaranteed to be aligned with a power of two grid. + /// + class Texture3DAtlas + { + // For the packing in 3D, we use an algorithm that packs the 3D textures in an octree + // where the top level elements are divided into piece of maxElementSize size. + // Due to the hardware limitation of max 2048 pixels in one dimension of a Texture3D, + // the atlas uses first the x axis and then y to place the volumes. + // The z dimension of the atlas will always have the size of maxElementSize. + // Here's a 2D representation of a possible atlas layout with 5 volumes: + // +-----+-----+-----+-----+ + // | |B |C | | | + // | A +-----+ E | | + // | |D | | | | + // +-----+--+--+-----+-----+ + // As you can see the second cell is divided to place smaller POT elements in the atlas. + // When an element is removed, the cell is marked as free. When the last leaf of a cell + // is removed, all the leaves are removed to form a cell of maxElementSize again. + class AtlasElement + { + public Vector3Int position; + public int size; + public Texture texture; + public int hash; + + public AtlasElement[] children = null; + public AtlasElement parent = null; + + // If the texture is null, then it means this space is free + public bool IsFree() => texture == null && children == null; + + public AtlasElement(Vector3Int position, int size, Texture texture = null) + { + this.position = position; + this.size = size; + this.texture = texture; + this.hash = 0; + } + + // Subdivide the current cell in 8 cubes of equal size + public void PopulateChildren() + { + children = new AtlasElement[8]; + + int halfSize = size / 2; + // Down Front left corner + children[0] = new AtlasElement(position + new Vector3Int(0, 0, 0), halfSize); + // Down Front right corner + children[1] = new AtlasElement(position + new Vector3Int(halfSize, 0, 0), halfSize); + // Down Back left corner + children[2] = new AtlasElement(position + new Vector3Int(0, 0, halfSize), halfSize); + // Down Back right corner + children[3] = new AtlasElement(position + new Vector3Int(halfSize, 0, halfSize), halfSize); + // Up Front left corner + children[4] = new AtlasElement(position + new Vector3Int(0, halfSize, 0), halfSize); + // Up Front right corner + children[5] = new AtlasElement(position + new Vector3Int(halfSize, halfSize, 0), halfSize); + // Up Back left corner + children[6] = new AtlasElement(position + new Vector3Int(0, halfSize, halfSize), halfSize); + // Up Back right corner + children[7] = new AtlasElement(position + new Vector3Int(halfSize, halfSize, halfSize), halfSize); + + foreach (var child in children) + child.parent = this; + } + + public void RemoveChildrenIfEmpty() + { + bool remove = true; + foreach (var child in children) + if (child.texture != null) + remove = false; + + if (remove) + children = null; + } + + public override string ToString() => $"3D Atlas Element, pos: {position}, size: {size}, texture:{texture}, children: {children != null}"; + } + + List m_Elements = new List(); + // We keep track of cached texture in a map because it's faster to traverse than the element tree when looking for a texture + Dictionary m_TextureElementsMap = new Dictionary(); + + RenderTexture m_Atlas; + RenderTexture m_MipMapGenerationTemp; + GraphicsFormat m_format; + ComputeShader m_Texture3DAtlasCompute; + int m_CopyKernel; + int m_GenerateMipKernel; + Vector3Int m_KernelGroupSize; + + int m_MaxElementSize = 0; + int m_MaxElementCount = 0; + bool m_HasMipMaps = false; + + const float k_MipmapFactorApprox = 1.33f; + + public Texture3DAtlas(GraphicsFormat format, int maxElementSize, int maxElementCount, bool hasMipMaps = true) + { + m_format = format; + m_MaxElementSize = maxElementSize; + m_MaxElementCount = maxElementCount; + m_HasMipMaps = hasMipMaps; + + // Texture 3D are limited to 2048 resolution in every axis, so wen need to create the atlas in x and y axis: + const int maxTexture3DSize = 2048; // TODO replace this by SystemInfo.maxTexture3DSize when it will be available. + + int maxElementCountPerDimension = maxTexture3DSize / maxElementSize; + int xElementCount = Mathf.Min(maxElementCount, maxElementCountPerDimension); + int yElementCount = maxElementCount < maxElementCountPerDimension ? 1 : Mathf.CeilToInt(maxElementCount / maxElementCountPerDimension); + + m_Atlas = new RenderTexture(xElementCount * maxElementSize, yElementCount * maxElementSize, 0, format) + { + volumeDepth = maxElementSize, + dimension = TextureDimension.Tex3D, + hideFlags = HideFlags.HideAndDontSave, + enableRandomWrite = true, + useMipMap = hasMipMaps, + autoGenerateMips = false, + name = $"Texture 3D Atlas - {xElementCount * maxElementSize}x{yElementCount * maxElementSize}x{maxElementSize}", + }; + m_Atlas.Create(); + + // Quarter res temp texture used for the mip generation + m_MipMapGenerationTemp = new RenderTexture(maxElementSize / 4, maxElementSize / 4, 0, format) + { + volumeDepth = maxElementSize / 4, + dimension = TextureDimension.Tex3D, + hideFlags = HideFlags.HideAndDontSave, + enableRandomWrite = true, + useMipMap = hasMipMaps, + autoGenerateMips = false, + name = $"Texture 3D MipMap Temp - {maxElementSize / 4}x{maxElementSize / 4}x{maxElementSize / 4}", + }; + m_MipMapGenerationTemp.Create(); + + // Fill the atlas with empty elements: + for (int i = 0; i < maxElementCount; i++) + { + Vector3Int pos = new Vector3Int((i % xElementCount) * maxElementSize, (int)(Mathf.FloorToInt(i / (float)xElementCount) * maxElementSize), 0); + var elem = new AtlasElement(pos, maxElementSize); + m_Elements.Add(elem); + } + + m_Texture3DAtlasCompute = HDRenderPipeline.defaultAsset.renderPipelineResources.shaders.texture3DAtlasCS; + m_CopyKernel = m_Texture3DAtlasCompute.FindKernel("Copy"); + m_GenerateMipKernel = m_Texture3DAtlasCompute.FindKernel("GenerateMipMap"); + m_Texture3DAtlasCompute.GetKernelThreadGroupSizes(m_CopyKernel, out var groupThreadX, out var groupThreadY, out var groupThreadZ); + m_KernelGroupSize = new Vector3Int((int)groupThreadX, (int)groupThreadY, (int)groupThreadZ); + } + + int GetTextureDepth(Texture t) + { + if (t is Texture3D volume) + return volume.depth; + else if (t is RenderTexture rt) + return rt.volumeDepth; + return 0; + } + + protected int GetTextureHash(Texture texture) + { + int hash = texture.GetHashCode(); + + unchecked + { +#if UNITY_EDITOR + hash = 23 * hash + texture.imageContentsHash.GetHashCode(); +#endif + hash = 23 * hash + texture.GetInstanceID().GetHashCode(); + hash = 23 * hash + texture.graphicsFormat.GetHashCode(); + hash = 23 * hash + texture.width.GetHashCode(); + hash = 23 * hash + texture.height.GetHashCode(); + hash = 23 * hash + texture.updateCount.GetHashCode(); + } + + return hash; + } + + public bool IsTextureValid(Texture tex) + { + if (tex.width != tex.height || tex.height != GetTextureDepth(tex)) + { + Debug.LogError($"3D Texture Atlas: Added texture {tex} is not doesn't have a cubic size {tex.width}x{tex.height}x{GetTextureDepth(tex)}."); + return false; + } + + if (tex.width > m_MaxElementSize) + { + Debug.LogError($"3D Texture Atlas: Added texture {tex} size {tex.width} is bigger than the max element atlas size {m_MaxElementSize}."); + return false; + } + + if (tex.width < 1) + { + Debug.LogError($"3D Texture Atlas: Added texture {tex} size {tex.width} is smaller than 1."); + return false; + } + + if (!Mathf.IsPowerOfTwo(tex.width)) + { + Debug.LogError($"3D Texture Atlas: Added texture {tex} size {tex.width} is not power of two."); + return false; + } + + return true; + } + + public bool AddTexture(Texture tex) + { + if (m_TextureElementsMap.ContainsKey(tex)) + return true; + + if (!IsTextureValid(tex)) + return false; + + if (!TryAddTextureToTree(tex)) + return false; + + return true; + } + + bool TryAddTextureToTree(Texture tex) + { + // For texture that have the max size in the atlas, we just have to find the first empty element. + if (tex.width == m_MaxElementSize) + { + var freeElem = m_Elements.FirstOrDefault(e => e.IsFree()); + if (freeElem != null) + { + SetTextureToElem(freeElem, tex); + return true; + } + } + else // Otherwise, we traverse the tree in depth to find a suitable position + { + // Find free element by looking at children + var freeElem = FindFreeElementWithSize(tex.width); + + if (freeElem != null) + { + SetTextureToElem(freeElem, tex); + return true; + } + else + { + // If we didn't found any empty element of the same size as the texture, then we have to create a new one + freeElem = m_Elements.FirstOrDefault(e => e.IsFree()); + + // No more space in the atlas + if (freeElem == null) + return true; + + while (freeElem.size > tex.width) + { + freeElem.PopulateChildren(); + freeElem = freeElem.children[0]; + } + + SetTextureToElem(freeElem, tex); + return true; + } + } + + void SetTextureToElem(AtlasElement element, Texture texture) + { + element.texture = texture; + m_TextureElementsMap.Add(texture, element); + } + + return false; + } + + AtlasElement FindFreeElementWithSize(int size) + { + AtlasElement FindFreeElement(int size, AtlasElement elem) + { + if (elem.size == size) + { + if (elem.IsFree()) + return elem; + else + return null; + } + + if (elem.children == null) + return null; + + foreach (var child in elem.children) + { + if (child.children != null && child.size >= size) + { + var cell = FindFreeElement(size, child); + if (cell != null) + return cell; + } + else if (child.IsFree()) + return child; + } + return null; + } + + foreach (var elem in m_Elements) + { + var result = FindFreeElement(size, elem); + if (result != null) + return result; + } + + return null; + } + + public void RemoveTexture(Texture tex) + { + if (m_TextureElementsMap.TryGetValue(tex, out var element)) + { + element.texture = null; + if (element.parent != null) + element.parent.RemoveChildrenIfEmpty(); + + m_TextureElementsMap.Remove(tex); + } + } + + public void ClearTextures() + { + foreach (var elem in m_Elements) + { + elem.texture = null; + elem.children = null; + } + m_TextureElementsMap.Clear(); + } + + public Vector3 GetTextureOffset(Texture tex) + { + if (tex != null && m_TextureElementsMap.TryGetValue(tex, out var element)) + return (Vector3)element.position; + else + return -Vector3.one; + } + + public void Update(CommandBuffer cmd) + { + if (m_TextureElementsMap.Count == 0) + return; + + // First pass to remove / add textures that changed resolution, it can happens if a 3D render texture is resized + foreach (var element in m_Elements) + { + var texture = element.texture; + + if (texture == null) + continue; + + if (texture.width != element.size) + { + RemoveTexture(texture); + AddTexture(texture); + continue; + } + } + + // Second pass to update elements where the texture content have changed + foreach (var element in m_TextureElementsMap.Values) + { + int newHash = GetTextureHash(element.texture); + + if (element.hash != newHash) + { + element.hash = newHash; + + CopyTexture(cmd, element); + } + } + } + + struct MipGenerationSwapData + { + public RenderTexture target; + public Vector3Int offset; + public int mipOffset; + } + + void CopyTexture(CommandBuffer cmd, AtlasElement element) + { + // Copy mip 0 of the texture + CopyMip(cmd, element.texture, 0, m_Atlas, element.position, 0); + + // If we need mip maps, we either copy them from the source if it has mip maps or we generate them. + if (m_HasMipMaps) + { + int mipMapCount = m_HasMipMaps ? Mathf.FloorToInt(Mathf.Log(element.texture.width, 2)) + 1 : 1; + bool sourceHasMipMaps = element.texture.mipmapCount > 1; + + // If the source 3D texture has mipmaps, we can just copy them + if (sourceHasMipMaps) + CopyMips(cmd, element.texture, m_Atlas, element.position); + else // Otherwise, we need to generate them + { + // TODO: handle texture that are smaller than m_MipMapGenerationTemp! + + // Generating the first mip from the source texture into the atlas to save a copy. + GenerateMip(cmd, element.texture, Vector3Int.zero, 0, m_Atlas, element.position, 1); + + MipGenerationSwapData source = new MipGenerationSwapData { target = m_Atlas, offset = element.position, mipOffset = 0}; + // m_MipMapGenerationTemp is allocated in quater res to save memory so we need to apply a mip offset when writing to it. + int tempMipOffset = (int)Mathf.Log((m_MipMapGenerationTemp.width / (element.size >> 2)), 2); + MipGenerationSwapData destination = new MipGenerationSwapData { target = m_MipMapGenerationTemp, offset = Vector3Int.zero, mipOffset = tempMipOffset - 2}; + + for (int i = 2; i < mipMapCount; i++) + { + GenerateMip(cmd, source.target, source.offset, i + source.mipOffset - 1, destination.target, destination.offset, i + destination.mipOffset); + + // Swap rt settings + var temp = source; + source = destination; + destination = temp; + } + + // Copy back the mips from the temp target to the atlas + for (int i = 2; i < mipMapCount; i += 2) + { + var mipPos = new Vector3Int((int)element.position.x >> i, (int)element.position.y >> i, (int)element.position.z >> i); + CopyMip(cmd, m_MipMapGenerationTemp, i - 2 + tempMipOffset, m_Atlas, mipPos, i); + } + } + } + } + + void CopyMips(CommandBuffer cmd, Texture source, Texture destination, Vector3Int destinationOffset) + { + int mipMapCount = Mathf.FloorToInt(Mathf.Log(source.width, 2)) + 1; + + for (int i = 1; i < mipMapCount; i++) + { + var mipPos = new Vector3Int((int)destinationOffset.x >> i, (int)destinationOffset.y >> i, (int)destinationOffset.z >> i); + CopyMip(cmd, source, i, destination, mipPos, i); + } + } + + void CopyMip(CommandBuffer cmd, Texture source, int sourceMip, Texture destination, Vector3Int destinationOffset, int destinationMip) + { + cmd.SetComputeTextureParam(m_Texture3DAtlasCompute, m_CopyKernel, HDShaderIDs._Src3DTexture, source); + cmd.SetComputeFloatParam(m_Texture3DAtlasCompute, HDShaderIDs._SrcMip, sourceMip); + + cmd.SetComputeTextureParam(m_Texture3DAtlasCompute, m_CopyKernel, HDShaderIDs._Dst3DTexture, destination, destinationMip); + cmd.SetComputeVectorParam(m_Texture3DAtlasCompute, HDShaderIDs._DstOffset, (Vector3)destinationOffset); + + // Previous volume texture only used the alpha channel so when we copy them, we put a white color to avoid having a black texture + bool alphaOnly = (source is Texture3D t) && t.format == TextureFormat.Alpha8; + cmd.SetComputeFloatParam(m_Texture3DAtlasCompute, HDShaderIDs._AlphaOnlyTexture, alphaOnly ? 1 : 0); + + int mipMapSize = (int)source.width >> sourceMip; // We assume that the texture is POT + cmd.SetComputeIntParam(m_Texture3DAtlasCompute, HDShaderIDs._SrcSize, mipMapSize); + + cmd.DispatchCompute( + m_Texture3DAtlasCompute, + m_CopyKernel, + Mathf.Max(mipMapSize / m_KernelGroupSize.x, 1), + Mathf.Max(mipMapSize / m_KernelGroupSize.y, 1), + Mathf.Max(mipMapSize / m_KernelGroupSize.z, 1) + ); + } + + void GenerateMip(CommandBuffer cmd, Texture source, Vector3Int sourceOffset, int sourceMip, Texture destination, Vector3Int destinationOffset, int destinationMip) + { + // Compute the source scale and offset in UV space: + Vector3 offset = new Vector3(sourceOffset.x / (float)source.width, sourceOffset.y / (float)source.height, sourceOffset.z / (float)GetTextureDepth(source)); + Vector3Int dstOffset = new Vector3Int(destinationOffset.x >> destinationMip, destinationOffset.y >> destinationMip, destinationOffset.z >> destinationMip); + + Vector3Int minSourceSize = new Vector3Int(Mathf.Min(source.width, destination.width), Mathf.Min(source.height, destination.height), Mathf.Min(GetTextureDepth(source), GetTextureDepth(destination))); + // Vector3Int sourceTextureMipSize = new Vector3Int(minSourceSize.x >> sourceMip, minSourceSize.y >> sourceMip, minSourceSize.z >> sourceMip); + Vector3Int destinationTextureMipSize = new Vector3Int(destination.width >> destinationMip, destination.height >> destinationMip, GetTextureDepth(destination) >> destinationMip); + + Vector3 scale = Vector3.one; + + Vector3Int sourceMipSize = new Vector3Int(source.width >> (sourceMip + 1), source.height >> (sourceMip + 1), GetTextureDepth(source) >> (sourceMip + 1)); + Vector3Int destinationMipSize = new Vector3Int(destination.width >> destinationMip, destination.height >> destinationMip, GetTextureDepth(destination) >> destinationMip); + // if (source.width > destination.width) + // { + scale = new Vector3( + Mathf.Min((float)destinationMipSize.x / sourceMipSize.x, 1), + Mathf.Min((float)destinationMipSize.y / sourceMipSize.y, 1), + Mathf.Min((float)destinationMipSize.z / sourceMipSize.z, 1) + ); + // } + + cmd.SetComputeTextureParam(m_Texture3DAtlasCompute, m_GenerateMipKernel, HDShaderIDs._Src3DTexture, source); + cmd.SetComputeVectorParam(m_Texture3DAtlasCompute, HDShaderIDs._SrcScale, scale); + cmd.SetComputeVectorParam(m_Texture3DAtlasCompute, HDShaderIDs._SrcOffset, offset); + cmd.SetComputeFloatParam(m_Texture3DAtlasCompute, HDShaderIDs._SrcMip, sourceMip); + + cmd.SetComputeTextureParam(m_Texture3DAtlasCompute, m_GenerateMipKernel, HDShaderIDs._Dst3DTexture, destination, destinationMip); + cmd.SetComputeVectorParam(m_Texture3DAtlasCompute, HDShaderIDs._DstOffset, (Vector3)dstOffset); + + // This is not correct when the atlas is the destination, we can compute it using the min of mip source size and dest mip side. + int mipMapSize = Mathf.Min(GetTextureDepth(source) >> (sourceMip + 1), GetTextureDepth(destination) >> (destinationMip)); + cmd.SetComputeIntParam(m_Texture3DAtlasCompute, HDShaderIDs._SrcSize, mipMapSize); + + bool alphaOnly = (source is Texture3D t) && t.format == TextureFormat.Alpha8; + cmd.SetComputeFloatParam(m_Texture3DAtlasCompute, HDShaderIDs._AlphaOnlyTexture, alphaOnly ? 1 : 0); + + cmd.DispatchCompute( + m_Texture3DAtlasCompute, + m_GenerateMipKernel, + Mathf.Max(mipMapSize / m_KernelGroupSize.x, 1), + Mathf.Max(mipMapSize / m_KernelGroupSize.y, 1), + Mathf.Max(mipMapSize / m_KernelGroupSize.z, 1) + ); + } + + public RenderTexture GetAtlas() => m_Atlas; + + public void Release() + { + ClearTextures(); + m_Atlas.Release(); + } + + public static long GetApproxCacheSizeInByte(int elementSize, int elementCount, GraphicsFormat format, bool hasMipMaps) + { + int formatInBytes = HDUtils.GetFormatSizeInBytes(format); + long elementSizeInBytes = (long)(elementSize * elementSize * elementSize * formatInBytes * (hasMipMaps ? k_MipmapFactorApprox : 1.0f)); + + return elementSizeInBytes * elementCount; + } + + public static int GetMaxElementCountForWeightInByte(long weight, int elementSize, int elementCount, GraphicsFormat format, bool hasMipMaps) + { + long elementSizeInByte = (long)((long)elementSize * elementSize * elementSize * HDUtils.GetFormatSizeInBytes(format) * (hasMipMaps ? k_MipmapFactorApprox : 1.0f)); + return (int)Mathf.Clamp(weight / elementSizeInByte, 1, elementCount); + } + } +} diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/Texture3DAtlas.cs.meta b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.cs.meta similarity index 100% rename from com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/Texture3DAtlas.cs.meta rename to com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Utility/Texture3DAtlas.cs.meta diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineResources.asset b/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineResources.asset index 074f3c0c9b4..2006d675749 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineResources.asset +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineResources.asset @@ -12,205 +12,130 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8b6f86e1523e69a4282e92d393be89a4, type: 3} m_Name: HDRenderPipelineResources m_EditorClassIdentifier: - m_Version: 4 shaders: defaultPS: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3} - debugDisplayLatlongPS: {fileID: 4800000, guid: c1d1d149a043a5349ba367da6c2051ba, - type: 3} - debugViewMaterialGBufferPS: {fileID: 4800000, guid: 439949ea1bfa91b4ba0d04269fcde33d, - type: 3} + debugDisplayLatlongPS: {fileID: 4800000, guid: c1d1d149a043a5349ba367da6c2051ba, type: 3} + debugViewMaterialGBufferPS: {fileID: 4800000, guid: 439949ea1bfa91b4ba0d04269fcde33d, type: 3} debugViewTilesPS: {fileID: 4800000, guid: c7c2bd17b06ceb4468e14081aaf1b96f, type: 3} debugFullScreenPS: {fileID: 4800000, guid: e874aca2df8300a488258738c31f85cf, type: 3} - debugColorPickerPS: {fileID: 4800000, guid: 8137b807709e178498f22ed710864bb0, - type: 3} + debugColorPickerPS: {fileID: 4800000, guid: 8137b807709e178498f22ed710864bb0, type: 3} debugExposurePS: {fileID: 4800000, guid: 0ef322534f047a34c96d29419d56d17a, type: 3} - debugLightVolumePS: {fileID: 4800000, guid: 8e706c0e71fcec34a8f5c9713e5e2943, - type: 3} - debugLightVolumeCS: {fileID: 7200000, guid: f5d5d21faef5cf445ac2c5d8ff9c4184, - type: 3} + debugLightVolumePS: {fileID: 4800000, guid: 8e706c0e71fcec34a8f5c9713e5e2943, type: 3} + debugLightVolumeCS: {fileID: 7200000, guid: f5d5d21faef5cf445ac2c5d8ff9c4184, type: 3} debugBlitQuad: {fileID: 4800000, guid: cf5ca5b6ef18b3f429ed707ee9ceac9f, type: 3} - debugViewVirtualTexturingBlit: {fileID: 4800000, guid: 55d195396b03b804eb78c92d468e3c8e, - type: 3} + debugViewVirtualTexturingBlit: {fileID: 4800000, guid: 55d195396b03b804eb78c92d468e3c8e, type: 3} materialError: {fileID: 4800000, guid: 79a966a5200a456188dec0d48d805614, type: 3} deferredPS: {fileID: 4800000, guid: 00dd221e34a6ab349a1196b0f2fab693, type: 3} colorPyramidPS: {fileID: 4800000, guid: 2fcfb8d92f45e4549b3f0bad5d0654bf, type: 3} depthPyramidCS: {fileID: 7200000, guid: 64a553bb564274041906f78ffba955e4, type: 3} maxZCS: {fileID: 7200000, guid: e95abf8c7230c344595f41c4dd5ff517, type: 3} copyChannelCS: {fileID: 7200000, guid: a4d45eda75e8e474dbe24a31f741f3b4, type: 3} - screenSpaceReflectionsCS: {fileID: 7200000, guid: d1de9ac7d9016204da289affe9677942, - type: 3} + screenSpaceReflectionsCS: {fileID: 7200000, guid: d1de9ac7d9016204da289affe9677942, type: 3} applyDistortionPS: {fileID: 4800000, guid: 02ae56f4306413c4a96dcf005cde1971, type: 3} - clearDispatchIndirectCS: {fileID: 7200000, guid: fc1f553acb80a6446a32d33e403d0656, - type: 3} + clearDispatchIndirectCS: {fileID: 7200000, guid: fc1f553acb80a6446a32d33e403d0656, type: 3} clearLightListsCS: {fileID: 7200000, guid: 743eb3491795b9545955695d591195a1, type: 3} - buildDispatchIndirectCS: {fileID: 7200000, guid: 4eb1b418be7044c40bb5200496c50f14, - type: 3} + buildDispatchIndirectCS: {fileID: 7200000, guid: 4eb1b418be7044c40bb5200496c50f14, type: 3} buildScreenAABBCS: {fileID: 7200000, guid: 728dce960f8a9c44bbc3abb3b851d8f6, type: 3} - buildPerTileLightListCS: {fileID: 7200000, guid: 65af3444cbf4b3747a4dead7ee00cfee, - type: 3} - buildPerBigTileLightListCS: {fileID: 7200000, guid: 5ee1f9d6e09abe045b2f5e0b784b9072, - type: 3} - buildPerVoxelLightListCS: {fileID: 7200000, guid: 0bb1b7e0ddcd5c44baf3ddc7456eb196, - type: 3} - lightListClusterClearAtomicIndexCS: {fileID: 7200000, guid: 1e3472a94b14a334a93230bbc700d7b2, - type: 3} - buildMaterialFlagsCS: {fileID: 7200000, guid: fb3eda953cd6e634e877fb777be2cd08, - type: 3} + buildPerTileLightListCS: {fileID: 7200000, guid: 65af3444cbf4b3747a4dead7ee00cfee, type: 3} + buildPerBigTileLightListCS: {fileID: 7200000, guid: 5ee1f9d6e09abe045b2f5e0b784b9072, type: 3} + buildPerVoxelLightListCS: {fileID: 7200000, guid: 0bb1b7e0ddcd5c44baf3ddc7456eb196, type: 3} + lightListClusterClearAtomicIndexCS: {fileID: 7200000, guid: 1e3472a94b14a334a93230bbc700d7b2, type: 3} + buildMaterialFlagsCS: {fileID: 7200000, guid: fb3eda953cd6e634e877fb777be2cd08, type: 3} deferredCS: {fileID: 7200000, guid: 0b64f79746d2daf4198eaf6eab9af259, type: 3} contactShadowCS: {fileID: 7200000, guid: 3e6900e06dc185a4380af4dacb4db0a4, type: 3} - volumeVoxelizationCS: {fileID: 7200000, guid: c20b371db720da244b73830ec74a343a, - type: 3} - volumetricLightingCS: {fileID: 7200000, guid: b4901a10df2d1e24282725e9fbc77c97, - type: 3} - volumetricLightingFilteringCS: {fileID: 7200000, guid: ef9a910d0ec6ebb41ae3f5c7a69daf46, - type: 3} + volumeVoxelizationCS: {fileID: 7200000, guid: c20b371db720da244b73830ec74a343a, type: 3} + volumetricLightingCS: {fileID: 7200000, guid: b4901a10df2d1e24282725e9fbc77c97, type: 3} + volumetricLightingFilteringCS: {fileID: 7200000, guid: ef9a910d0ec6ebb41ae3f5c7a69daf46, type: 3} deferredTilePS: {fileID: 4800000, guid: dedaf4ea0d134ca4aad1d95a558c46e5, type: 3} - screenSpaceShadowPS: {fileID: 4800000, guid: bfa43a48695613b4ea19c58858ae1a61, - type: 3} - probeVolumeAtlasBlitCS: {fileID: 7200000, guid: 07f429bf534edb44eb5a0e4b2c65b108, - type: 3} - probeVolumeAtlasOctahedralDepthBlitCS: {fileID: 7200000, guid: f60c895d3a3061848844b36ccf9e44a9, - type: 3} - probeVolumeAtlasOctahedralDepthConvolveCS: {fileID: 7200000, guid: 7ef71ce05401a4c4081039b475d3b9ee, - type: 3} - debugDisplayProbeVolumePS: {fileID: 4800000, guid: e7c19cfee7a88394fbb53652b9644cc0, - type: 3} - subsurfaceScatteringCS: {fileID: 7200000, guid: b06a7993621def248addd55d0fe931b1, - type: 3} + screenSpaceShadowPS: {fileID: 4800000, guid: bfa43a48695613b4ea19c58858ae1a61, type: 3} + probeVolumeAtlasBlitCS: {fileID: 7200000, guid: 07f429bf534edb44eb5a0e4b2c65b108, type: 3} + probeVolumeAtlasOctahedralDepthBlitCS: {fileID: 7200000, guid: f60c895d3a3061848844b36ccf9e44a9, type: 3} + probeVolumeAtlasOctahedralDepthConvolveCS: {fileID: 7200000, guid: 7ef71ce05401a4c4081039b475d3b9ee, type: 3} + debugDisplayProbeVolumePS: {fileID: 4800000, guid: e7c19cfee7a88394fbb53652b9644cc0, type: 3} + subsurfaceScatteringCS: {fileID: 7200000, guid: b06a7993621def248addd55d0fe931b1, type: 3} combineLightingPS: {fileID: 4800000, guid: 2e37131331fbdca449b1a2bc47a639ca, type: 3} - cameraMotionVectorsPS: {fileID: 4800000, guid: 035941b63024d1943af48811c1db20d9, - type: 3} - clearStencilBufferPS: {fileID: 4800000, guid: 8ea49ef16606acd489439e676ab84040, - type: 3} - copyStencilBufferPS: {fileID: 4800000, guid: 3d1574f1cdfa0ce4995f9bc79ed7f8ec, - type: 3} + debugDensityVolumeAtlasPS: {fileID: 4800000, guid: 8371b763f09c7304889c22aa97ebdfd2, type: 3} + cameraMotionVectorsPS: {fileID: 4800000, guid: 035941b63024d1943af48811c1db20d9, type: 3} + clearStencilBufferPS: {fileID: 4800000, guid: 8ea49ef16606acd489439e676ab84040, type: 3} + copyStencilBufferPS: {fileID: 4800000, guid: 3d1574f1cdfa0ce4995f9bc79ed7f8ec, type: 3} copyDepthBufferPS: {fileID: 4800000, guid: 42dfcc8fe803ece4096c58630689982f, type: 3} blitPS: {fileID: 4800000, guid: 370f7a9cc4e362d488af024d371091e8, type: 3} - blitColorAndDepthPS: {fileID: 4800000, guid: c6e57f5bdbd2a284a86a3097c03884c8, - type: 3} + blitColorAndDepthPS: {fileID: 4800000, guid: c6e57f5bdbd2a284a86a3097c03884c8, type: 3} downsampleDepthPS: {fileID: 4800000, guid: 67d6171b0acc6554aad48c845ec7e67f, type: 3} - upsampleTransparentPS: {fileID: 4800000, guid: 2ad7ce40f0dbaf64dadef1f58d8524d3, - type: 3} + upsampleTransparentPS: {fileID: 4800000, guid: 2ad7ce40f0dbaf64dadef1f58d8524d3, type: 3} resolveStencilCS: {fileID: 7200000, guid: 65b89cac5f286b043a31bf8041776ee7, type: 3} blitCubemapPS: {fileID: 4800000, guid: d05913e251bed7a4992c921c62e1b647, type: 3} - buildProbabilityTablesCS: {fileID: 7200000, guid: b9f26cf340afe9145a699753531b2a4c, - type: 3} - computeGgxIblSampleDataCS: {fileID: 7200000, guid: 764a24bb47ef5ba4781d9ae82ca07445, - type: 3} + buildProbabilityTablesCS: {fileID: 7200000, guid: b9f26cf340afe9145a699753531b2a4c, type: 3} + computeGgxIblSampleDataCS: {fileID: 7200000, guid: 764a24bb47ef5ba4781d9ae82ca07445, type: 3} GGXConvolvePS: {fileID: 4800000, guid: 123ed592ad5c2494b8aed301fd609e7b, type: 3} charlieConvolvePS: {fileID: 4800000, guid: 5685fd17e71045e4ca9fefca38a7c177, type: 3} - opaqueAtmosphericScatteringPS: {fileID: 4800000, guid: 32f724728cf19904291226f239ec16f0, - type: 3} + opaqueAtmosphericScatteringPS: {fileID: 4800000, guid: 32f724728cf19904291226f239ec16f0, type: 3} hdriSkyPS: {fileID: 4800000, guid: 9bd32a6ece529fd4f9408b8d7e00c10d, type: 3} - integrateHdriSkyPS: {fileID: 4800000, guid: 48db2705cf2856d4e893eb30a6892d1b, - type: 3} + integrateHdriSkyPS: {fileID: 4800000, guid: 48db2705cf2856d4e893eb30a6892d1b, type: 3} skyboxCubemapPS: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} gradientSkyPS: {fileID: 4800000, guid: 2b5d4f1b26f03dc4a873b093e0c4adb1, type: 3} - ambientProbeConvolutionCS: {fileID: 7200000, guid: 6d048f7b1bd45e840b4e79ec92639fa8, - type: 3} - groundIrradiancePrecomputationCS: {fileID: 7200000, guid: eb6ae6f326207ee4d987a3e5adddf63a, - type: 3} - inScatteredRadiancePrecomputationCS: {fileID: 7200000, guid: 70c69d514688f8545855680760d77418, - type: 3} - physicallyBasedSkyPS: {fileID: 4800000, guid: a06934a4863e778498be65d8f865b7a4, - type: 3} - planarReflectionFilteringCS: {fileID: 7200000, guid: 9f3f8a01b8caaaa4595591dc96d43dd2, - type: 3} - cloudLayerPS: {fileID: 4800000, guid: 001a47fa123e95a4bba13ecb0442d944, - type: 3} - bakeCloudTextureCS: {fileID: 7200000, guid: 09a7f6850ee9fb4439e5ebd632127da5, - type: 3} - bakeCloudShadowsCS: {fileID: 7200000, guid: 3e7317e0800c066448ee07a3e47f102b, - type: 3} - preIntegratedFGD_GGXDisneyDiffusePS: {fileID: 4800000, guid: 123f13d52852ef547b2962de4bd9eaad, - type: 3} - preIntegratedFGD_CharlieFabricLambertPS: {fileID: 4800000, guid: 3b3bf235775cf8b4baae7f3306787ab0, - type: 3} - preIntegratedFGD_WardPS: {fileID: 4800000, guid: d279c46a545b0af4f9f0c4fa82cd489e, - type: 3} - preIntegratedFGD_CookTorrancePS: {fileID: 4800000, guid: a6402c19b020b4a4fb7073aaa2e26aba, - type: 3} + ambientProbeConvolutionCS: {fileID: 7200000, guid: 6d048f7b1bd45e840b4e79ec92639fa8, type: 3} + groundIrradiancePrecomputationCS: {fileID: 7200000, guid: eb6ae6f326207ee4d987a3e5adddf63a, type: 3} + inScatteredRadiancePrecomputationCS: {fileID: 7200000, guid: 70c69d514688f8545855680760d77418, type: 3} + physicallyBasedSkyPS: {fileID: 4800000, guid: a06934a4863e778498be65d8f865b7a4, type: 3} + planarReflectionFilteringCS: {fileID: 7200000, guid: 9f3f8a01b8caaaa4595591dc96d43dd2, type: 3} + cloudLayerPS: {fileID: 4800000, guid: 001a47fa123e95a4bba13ecb0442d944, type: 3} + bakeCloudTextureCS: {fileID: 7200000, guid: 09a7f6850ee9fb4439e5ebd632127da5, type: 3} + bakeCloudShadowsCS: {fileID: 7200000, guid: 3e7317e0800c066448ee07a3e47f102b, type: 3} + preIntegratedFGD_GGXDisneyDiffusePS: {fileID: 4800000, guid: 123f13d52852ef547b2962de4bd9eaad, type: 3} + preIntegratedFGD_CharlieFabricLambertPS: {fileID: 4800000, guid: 3b3bf235775cf8b4baae7f3306787ab0, type: 3} + preIntegratedFGD_WardPS: {fileID: 4800000, guid: d279c46a545b0af4f9f0c4fa82cd489e, type: 3} + preIntegratedFGD_CookTorrancePS: {fileID: 4800000, guid: a6402c19b020b4a4fb7073aaa2e26aba, type: 3} encodeBC6HCS: {fileID: 7200000, guid: aa922d239de60304f964e24488559eeb, type: 3} cubeToPanoPS: {fileID: 4800000, guid: 595434cc3b6405246b6cd3086d0b6f7d, type: 3} - blitCubeTextureFacePS: {fileID: 4800000, guid: d850d0a2481878d4bbf17e5126b04163, - type: 3} - filterAreaLightCookiesPS: {fileID: 4800000, guid: c243aac96dda5fa40bed693ed5ba02c4, - type: 3} - clearUIntTextureCS: {fileID: 7200000, guid: d067ad4b88af51c498875426894aef76, - type: 3} + blitCubeTextureFacePS: {fileID: 4800000, guid: d850d0a2481878d4bbf17e5126b04163, type: 3} + filterAreaLightCookiesPS: {fileID: 4800000, guid: c243aac96dda5fa40bed693ed5ba02c4, type: 3} + clearUIntTextureCS: {fileID: 7200000, guid: d067ad4b88af51c498875426894aef76, type: 3} customPassUtils: {fileID: 4800000, guid: 7e3722d0388000848acb25fd3cc8c088, type: 3} - customPassRenderersUtils: {fileID: 4800000, guid: cef5ba33ee5063d4c8b495d2292e394d, - type: 3} + customPassRenderersUtils: {fileID: 4800000, guid: cef5ba33ee5063d4c8b495d2292e394d, type: 3} + texture3DAtlasCS: {fileID: 7200000, guid: 81522e314a83afd4a8ed43bd00757051, type: 3} xrMirrorViewPS: {fileID: 4800000, guid: e6255f98cf405eb45ab6f9006cf11e1f, type: 3} xrOcclusionMeshPS: {fileID: 4800000, guid: 46a45b32bb110604fb36216b63bcdb81, type: 3} shadowClearPS: {fileID: 4800000, guid: e3cab24f27741f44d8af1e94d006267c, type: 3} evsmBlurCS: {fileID: 7200000, guid: fb36979473602464fa32deacb9630c08, type: 3} - debugHDShadowMapPS: {fileID: 4800000, guid: 93d40cc9a6e13994f86f576a624efa18, - type: 3} + debugHDShadowMapPS: {fileID: 4800000, guid: 93d40cc9a6e13994f86f576a624efa18, type: 3} momentShadowsCS: {fileID: 7200000, guid: 4dea53e2ff15ed0448817c2aa4246e53, type: 3} - decalNormalBufferPS: {fileID: 4800000, guid: fd532bf1795188c4daaa66ea798b8b0a, type: 3} - decalClearPropertyMaskBufferCS: {fileID: 7200000, guid: 1076a08965d4a91479b72599724f7fd6, type: 3} - decalNormalBufferPS: {fileID: 4800000, guid: fd532bf1795188c4daaa66ea798b8b0a, - type: 3} shadowBlitPS: {fileID: 4800000, guid: ca059f1af4587a24b9a9eed3b66cff0f, type: 3} decalNormalBufferPS: {fileID: 4800000, guid: fd532bf1795188c4daaa66ea798b8b0a, type: 3} - decalClearPropertyMaskBufferCS: {fileID: 7200000, guid: 1076a08965d4a91479b72599724f7fd6, type: 3} GTAOCS: {fileID: 7200000, guid: 6710b06492bd58c4bb8aec0fdc1fced3, type: 3} - GTAOSpatialDenoiseCS: {fileID: 7200000, guid: 2cb33c21587d12b4388d7866ab6c65f6, - type: 3} - GTAOTemporalDenoiseCS: {fileID: 7200000, guid: 31e0ca4c210f97c468037d11a5b832bb, - type: 3} + GTAOSpatialDenoiseCS: {fileID: 7200000, guid: 2cb33c21587d12b4388d7866ab6c65f6, type: 3} + GTAOTemporalDenoiseCS: {fileID: 7200000, guid: 31e0ca4c210f97c468037d11a5b832bb, type: 3} GTAOCopyHistoryCS: {fileID: 7200000, guid: 7f43be57ffd12ff469d4fc175c00c4b4, type: 3} - GTAOBlurAndUpsample: {fileID: 7200000, guid: 9eb1abde882538a4ea46fa23e49ab9fa, - type: 3} - screenSpaceGlobalIlluminationCS: {fileID: 7200000, guid: 96170a954eb538b40a5ff369552c3629, - type: 3} + GTAOBlurAndUpsample: {fileID: 7200000, guid: 9eb1abde882538a4ea46fa23e49ab9fa, type: 3} + screenSpaceGlobalIlluminationCS: {fileID: 7200000, guid: 96170a954eb538b40a5ff369552c3629, type: 3} depthValuesPS: {fileID: 4800000, guid: 6e6a4a3dbb788234594aa74f2d6aeb6f, type: 3} colorResolvePS: {fileID: 4800000, guid: dd7047092f3c82b40b3a07868f9c4de2, type: 3} - resolveMotionVecPS: {fileID: 4800000, guid: ea18ca9826385e943979c46cf98968cc, - type: 3} + resolveMotionVecPS: {fileID: 4800000, guid: ea18ca9826385e943979c46cf98968cc, type: 3} copyAlphaCS: {fileID: 7200000, guid: c2c7eb6611725264187721ef9df0354b, type: 3} nanKillerCS: {fileID: 7200000, guid: 83982f199acf927499576a99abc9bea9, type: 3} exposureCS: {fileID: 7200000, guid: 976d7bce54fae534fb9ec67e9c18570c, type: 3} - histogramExposureCS: {fileID: 7200000, guid: 222da48299136f34b8e3fb75ae9f8ac7, - type: 3} + histogramExposureCS: {fileID: 7200000, guid: 222da48299136f34b8e3fb75ae9f8ac7, type: 3} applyExposureCS: {fileID: 7200000, guid: 1a6fea1dc099b984d8f2b27d504dc096, type: 3} - debugImageHistogramCS: {fileID: 7200000, guid: 52cc17ef5a5ffc443a5c142f9b745a85, - type: 3} + debugImageHistogramCS: {fileID: 7200000, guid: 52cc17ef5a5ffc443a5c142f9b745a85, type: 3} uberPostCS: {fileID: 7200000, guid: f1bf52f7c71bffd4f91e6cd90d12a4f7, type: 3} lutBuilder3DCS: {fileID: 7200000, guid: 37f2b1b0ecd6f1c439e4c1b4f2fdb524, type: 3} - depthOfFieldKernelCS: {fileID: 7200000, guid: 7869415cc3e4eaa4d82ac21a752a2780, - type: 3} + depthOfFieldKernelCS: {fileID: 7200000, guid: 7869415cc3e4eaa4d82ac21a752a2780, type: 3} depthOfFieldCoCCS: {fileID: 7200000, guid: 048b235b54fbfaa4d80ec85ea847d4f8, type: 3} - depthOfFieldCoCReprojectCS: {fileID: 7200000, guid: 4980decaa3878d6448569489f5fc7931, - type: 3} - depthOfFieldDilateCS: {fileID: 7200000, guid: 1c93af4338c0c1b42b92464992eebc10, - type: 3} + depthOfFieldCoCReprojectCS: {fileID: 7200000, guid: 4980decaa3878d6448569489f5fc7931, type: 3} + depthOfFieldDilateCS: {fileID: 7200000, guid: 1c93af4338c0c1b42b92464992eebc10, type: 3} depthOfFieldMipCS: {fileID: 7200000, guid: d3ef53de069ded64e8377cba6eb951fa, type: 3} - depthOfFieldMipSafeCS: {fileID: 7200000, guid: 2d24ee7b2c804d947a5c371c12ed46bd, - type: 3} - depthOfFieldPrefilterCS: {fileID: 7200000, guid: f2b89d19910854346b792fe7177ce634, - type: 3} - depthOfFieldTileMaxCS: {fileID: 7200000, guid: 84f84585ea8a7a849bea4a581adb93a7, - type: 3} - depthOfFieldGatherCS: {fileID: 7200000, guid: 486be52dddc4e054fb10a7b9b78788c2, - type: 3} - depthOfFieldCombineCS: {fileID: 7200000, guid: c8049ca85c4c7d047ba28f34d800c663, - type: 3} - depthOfFieldPreCombineFarCS: {fileID: 7200000, guid: 3b4a2acd03d1ce2438d93c325d588735, - type: 3} - depthOfFieldClearIndirectArgsCS: {fileID: 7200000, guid: 69905045e1d0a65458b205d6ab55502b, - type: 3} - paniniProjectionCS: {fileID: 7200000, guid: 0ddbf72c8fbb6e44b983f470c8384ef6, - type: 3} - motionBlurMotionVecPrepCS: {fileID: 7200000, guid: ed9438fa777911d48933402087203b15, - type: 3} - motionBlurGenTileCS: {fileID: 7200000, guid: 336e1fdbb3a1b8647b06208415f87804, - type: 3} - motionBlurMergeTileCS: {fileID: 7200000, guid: cd14ddf849edeed43b0e3ccf66023038, - type: 3} - motionBlurNeighborhoodTileCS: {fileID: 7200000, guid: 5ea9865df3e53b448856785b88f8e7b9, - type: 3} + depthOfFieldMipSafeCS: {fileID: 7200000, guid: 2d24ee7b2c804d947a5c371c12ed46bd, type: 3} + depthOfFieldPrefilterCS: {fileID: 7200000, guid: f2b89d19910854346b792fe7177ce634, type: 3} + depthOfFieldTileMaxCS: {fileID: 7200000, guid: 84f84585ea8a7a849bea4a581adb93a7, type: 3} + depthOfFieldGatherCS: {fileID: 7200000, guid: 486be52dddc4e054fb10a7b9b78788c2, type: 3} + depthOfFieldCombineCS: {fileID: 7200000, guid: c8049ca85c4c7d047ba28f34d800c663, type: 3} + depthOfFieldPreCombineFarCS: {fileID: 7200000, guid: 3b4a2acd03d1ce2438d93c325d588735, type: 3} + depthOfFieldClearIndirectArgsCS: {fileID: 7200000, guid: 69905045e1d0a65458b205d6ab55502b, type: 3} + paniniProjectionCS: {fileID: 7200000, guid: 0ddbf72c8fbb6e44b983f470c8384ef6, type: 3} + motionBlurMotionVecPrepCS: {fileID: 7200000, guid: ed9438fa777911d48933402087203b15, type: 3} + motionBlurGenTileCS: {fileID: 7200000, guid: 336e1fdbb3a1b8647b06208415f87804, type: 3} + motionBlurMergeTileCS: {fileID: 7200000, guid: cd14ddf849edeed43b0e3ccf66023038, type: 3} + motionBlurNeighborhoodTileCS: {fileID: 7200000, guid: 5ea9865df3e53b448856785b88f8e7b9, type: 3} motionBlurCS: {fileID: 7200000, guid: 2af5c49c7865edb4b823826970ec176a, type: 3} bloomPrefilterCS: {fileID: 7200000, guid: 243b24008041aaa4a91800690f63c684, type: 3} bloomBlurCS: {fileID: 7200000, guid: 133a68380d324de4ea8d3ff8657b02d8, type: 3} @@ -219,23 +144,18 @@ MonoBehaviour: finalPassPS: {fileID: 4800000, guid: 5ac9ef0c50282754b93c7692488e7ee7, type: 3} clearBlackPS: {fileID: 4800000, guid: 3330c1503ea8c6d4d9408df3f64227eb, type: 3} SMAAPS: {fileID: 4800000, guid: 9655f4aa89a469c49aceaceabf9bc77b, type: 3} - temporalAntialiasingPS: {fileID: 4800000, guid: 3dd9fd928fdb83743b1f27d15df22179, - type: 3} - dofCircleOfConfusion: {fileID: 7200000, guid: 75332b7b315c80d4babe506820aa0bfd, - type: 3} + temporalAntialiasingPS: {fileID: 4800000, guid: 3dd9fd928fdb83743b1f27d15df22179, type: 3} + dofCircleOfConfusion: {fileID: 7200000, guid: 75332b7b315c80d4babe506820aa0bfd, type: 3} dofGatherCS: {fileID: 7200000, guid: 1e6b16a7970a1494db74b1d3d007d1cc, type: 3} DoFCoCPyramidCS: {fileID: 7200000, guid: df41a69211c03fe479b63a8bed3bfbb4, type: 3} - contrastAdaptiveSharpenCS: {fileID: 7200000, guid: 560896aec2f412c48995be35551a4ac6, - type: 3} - VTFeedbackDownsample: {fileID: 7200000, guid: 32d963548086c2c439aeb23a93e9a00a, - type: 3} + contrastAdaptiveSharpenCS: {fileID: 7200000, guid: 560896aec2f412c48995be35551a4ac6, type: 3} + VTFeedbackDownsample: {fileID: 7200000, guid: 32d963548086c2c439aeb23a93e9a00a, type: 3} accumulationCS: {fileID: 7200000, guid: ed80add7a217efa468d137d6f7c668f3, type: 3} alphaInjectionPS: {fileID: 4800000, guid: 4edd96259a5e8b44c90479928f0cd11e, type: 3} chromaKeyingPS: {fileID: 4800000, guid: 49feb6b111e82ec4eb6d3d08e4b6903e, type: 3} customClearPS: {fileID: 4800000, guid: 9cef3686fa32c8840947ed99b561195c, type: 3} ssGIDenoiserCS: {fileID: 7200000, guid: a435d803bc32d0845ba1a713b7a1c8b1, type: 3} - bilateralUpsampleCS: {fileID: 7200000, guid: 68e831c555284d741b985e05369f0e63, - type: 3} + bilateralUpsampleCS: {fileID: 7200000, guid: 68e831c555284d741b985e05369f0e63, type: 3} textures: debugFontTex: {fileID: 2800000, guid: a3ad2df0e49aaa341a3b3a80f93b3f66, type: 3} colorGradient: {fileID: 2800000, guid: 4ea52e665573c1644bf05dd9b11fd2a4, type: 3} @@ -306,20 +226,15 @@ MonoBehaviour: - {fileID: 2800000, guid: 7641a2b116fafd64d9c3d6459fdfe801, type: 3} - {fileID: 2800000, guid: c6a5e40e6746fef4fa486e8f620ee8d4, type: 3} - {fileID: 2800000, guid: fd4189357c6dfb94fa2d36afbce72086, type: 3} - owenScrambledRGBATex: {fileID: 2800000, guid: b0fe077c1ee7d80428f3d8dfa28a027d, - type: 3} - owenScrambled256Tex: {fileID: 2800000, guid: 2a205358e67aa9e4a94a128ac9362f4e, - type: 3} + owenScrambledRGBATex: {fileID: 2800000, guid: b0fe077c1ee7d80428f3d8dfa28a027d, type: 3} + owenScrambled256Tex: {fileID: 2800000, guid: 2a205358e67aa9e4a94a128ac9362f4e, type: 3} scramblingTex: {fileID: 2800000, guid: bf25cd6288e2c8d43854a61a8496a830, type: 3} rankingTile1SPP: {fileID: 2800000, guid: f2fe0251f704c4c478a8063775cffedb, type: 3} - scramblingTile1SPP: {fileID: 2800000, guid: 6185473f62ad3e74da4acac5d482917a, - type: 3} + scramblingTile1SPP: {fileID: 2800000, guid: 6185473f62ad3e74da4acac5d482917a, type: 3} rankingTile8SPP: {fileID: 2800000, guid: af4bd638a4b3eb14781e6441adcdfbb9, type: 3} - scramblingTile8SPP: {fileID: 2800000, guid: 152f8b933250a7b448fc2d4d301b9944, - type: 3} + scramblingTile8SPP: {fileID: 2800000, guid: 152f8b933250a7b448fc2d4d301b9944, type: 3} rankingTile256SPP: {fileID: 2800000, guid: 1e604a266c415cd46b36d97cd9220aa8, type: 3} - scramblingTile256SPP: {fileID: 2800000, guid: 882fb55d7b3e7c94598a318df9376e32, - type: 3} + scramblingTile256SPP: {fileID: 2800000, guid: 882fb55d7b3e7c94598a318df9376e32, type: 3} filmGrainTex: - {fileID: 2800000, guid: 284a1ac236869fa4eacf377d73c7dff8, type: 3} - {fileID: 2800000, guid: bd74961b009b93145a998ae93a5fc186, type: 3} @@ -336,8 +251,7 @@ MonoBehaviour: defaultHDRISky: {fileID: 8900000, guid: 8253d41e6e8b11a4cbe77a4f8f82934d, type: 3} defaultCloudMap: {fileID: 2800000, guid: 57a33fc2476a01644865bfde5f06e2f4, type: 3} assets: - defaultDiffusionProfile: {fileID: 11400000, guid: 2b7005ba3a4d8474b8cdc34141ad766e, - type: 2} - emissiveCylinderMesh: {fileID: 2534964839176971238, guid: accb6d90f0d50fe4ca0f68159b4323de, - type: 3} + defaultDiffusionProfile: {fileID: 11400000, guid: 2b7005ba3a4d8474b8cdc34141ad766e, type: 2} + emissiveCylinderMesh: {fileID: 2534964839176971238, guid: accb6d90f0d50fe4ca0f68159b4323de, type: 3} emissiveQuadMesh: {fileID: 4300000, guid: 1d5a8595286f94f4bb54171d49f473c3, type: 3} + m_Version: 4