diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/Examples/Blit.shader b/Packages/com.unity.render-pipelines.core/Documentation~/Examples/Blit.shader new file mode 100644 index 00000000000..e71072b4883 --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Documentation~/Examples/Blit.shader @@ -0,0 +1,364 @@ +Shader "Hidden/Universal/CoreBlit" +{ + HLSLINCLUDE + #pragma target 2.0 + #pragma editor_sync_compilation + // Core.hlsl for XR dependencies + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" + // DebuggingFullscreen.hlsl for URP debug draw + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/DebuggingFullscreen.hlsl" + // Color.hlsl for color space conversion + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" + + // Specialized blit with URP debug draw support and color space conversion support + half4 FragmentURPBlit(Varyings input, SamplerState blitsampler) + { + half4 color = FragBlit(input, blitsampler); + + #ifdef _LINEAR_TO_SRGB_CONVERSION + color = LinearToSRGB(color); + #endif + + #if defined(DEBUG_DISPLAY) + half4 debugColor = 0; + float2 uv = input.texcoord; + if (CanDebugOverrideOutputColor(color, uv, debugColor)) + { + return debugColor; + } + #endif + + return color; + } + ENDHLSL + + SubShader + { + Tags{ "RenderPipeline" = "UniversalPipeline" } + + // 0: Nearest + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "Nearest" + + HLSLPROGRAM + #pragma vertex Vert + #pragma fragment FragNearest + ENDHLSL + } + + // 1: Bilinear + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "Bilinear" + + HLSLPROGRAM + #pragma vertex Vert + #pragma fragment FragBilinear + ENDHLSL + } + + // 2: Nearest quad + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "NearestQuad" + + HLSLPROGRAM + #pragma vertex VertQuad + #pragma fragment FragNearest + ENDHLSL + } + + // 3: Bilinear quad + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "BilinearQuad" + + HLSLPROGRAM + #pragma vertex VertQuad + #pragma fragment FragBilinear + ENDHLSL + } + + // 4: Nearest quad with padding + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "NearestQuadPadding" + + HLSLPROGRAM + #pragma vertex VertQuadPadding + #pragma fragment FragNearest + ENDHLSL + } + + // 5: Bilinear quad with padding + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "BilinearQuadPadding" + + HLSLPROGRAM + #pragma vertex VertQuadPadding + #pragma fragment FragBilinear + ENDHLSL + } + + // 6: Nearest quad with padding and repeat + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "NearestQuadPaddingRepeat" + + HLSLPROGRAM + #pragma vertex VertQuadPadding + #pragma fragment FragNearestRepeat + ENDHLSL + } + + // 7: Bilinear quad with padding and repeat + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "BilinearQuadPaddingRepeat" + + HLSLPROGRAM + #pragma vertex VertQuadPadding + #pragma fragment FragBilinearRepeat + ENDHLSL + } + + // 8: Bilinear quad with padding (for OctahedralTexture) + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "BilinearQuadPaddingOctahedral" + + HLSLPROGRAM + #pragma vertex VertQuadPadding + #pragma fragment FragOctahedralBilinearRepeat + ENDHLSL + } + + /// Version 4, 5, 6, 7 with Alpha Blending 0.5 + // 9: Nearest quad with padding alpha blend (4 with alpha blend) + Pass + { + ZWrite Off ZTest Always Blend DstColor Zero Cull Off + Name "NearestQuadPaddingAlphaBlend" + + HLSLPROGRAM + #pragma vertex VertQuadPadding + #pragma fragment FragNearest + #define WITH_ALPHA_BLEND + ENDHLSL + } + + // 10: Bilinear quad with padding alpha blend (5 with alpha blend) + Pass + { + ZWrite Off ZTest Always Blend DstColor Zero Cull Off + Name "BilinearQuadPaddingAlphaBlend" + + HLSLPROGRAM + #pragma vertex VertQuadPadding + #pragma fragment FragBilinear + #define WITH_ALPHA_BLEND + ENDHLSL + } + + // 11: Nearest quad with padding alpha blend repeat (6 with alpha blend) + Pass + { + ZWrite Off ZTest Always Blend DstColor Zero Cull Off + Name "NearestQuadPaddingAlphaBlendRepeat" + + HLSLPROGRAM + #pragma vertex VertQuadPadding + #pragma fragment FragNearestRepeat + #define WITH_ALPHA_BLEND + ENDHLSL + } + + // 12: Bilinear quad with padding alpha blend repeat (7 with alpha blend) + Pass + { + ZWrite Off ZTest Always Blend DstColor Zero Cull Off + Name "BilinearQuadPaddingAlphaBlendRepeat" + + HLSLPROGRAM + #pragma vertex VertQuadPadding + #pragma fragment FragBilinearRepeat + #define WITH_ALPHA_BLEND + ENDHLSL + } + + // 13: Bilinear quad with padding alpha blend (for OctahedralTexture) (8 with alpha blend) + Pass + { + ZWrite Off ZTest Always Blend DstColor Zero Cull Off + Name "BilinearQuadPaddingAlphaBlendOctahedral" + + HLSLPROGRAM + #pragma vertex VertQuadPadding + #pragma fragment FragOctahedralBilinearRepeat + #define WITH_ALPHA_BLEND + ENDHLSL + } + + // 14. Project Cube to Octahedral 2d quad + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "CubeToOctahedral" + + HLSLPROGRAM + #pragma vertex VertQuad + #pragma fragment FragOctahedralProject + ENDHLSL + } + + // 15. Project Cube to Octahedral 2d quad with luminance (grayscale), RGBA to YYYY + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "CubeToOctahedralLuminance" + + HLSLPROGRAM + #pragma vertex VertQuad + #pragma fragment FragOctahedralProjectLuminance + ENDHLSL + } + + // 16. Project Cube to Octahedral 2d quad with with A to RGBA (AAAA) + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "CubeToOctahedralAlpha" + + HLSLPROGRAM + #pragma vertex VertQuad + #pragma fragment FragOctahedralProjectAlphaToRGBA + ENDHLSL + } + + // 17. Project Cube to Octahedral 2d quad with with R to RGBA (RRRR) + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "CubeToOctahedralRed" + + HLSLPROGRAM + #pragma vertex VertQuad + #pragma fragment FragOctahedralProjectRedToRGBA + ENDHLSL + } + + // 18. Bilinear quad with luminance (grayscale), RGBA to YYYY + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "BilinearQuadLuminance" + + HLSLPROGRAM + #pragma vertex VertQuad + #pragma fragment FragBilinearLuminance + ENDHLSL + } + + // 19. Bilinear quad with A to RGBA (AAAA) + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "BilinearQuadAlpha" + + HLSLPROGRAM + #pragma vertex VertQuad + #pragma fragment FragBilinearAlphaToRGBA + ENDHLSL + } + + // 20. Bilinear quad with R to RGBA (RRRR) + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "BilinearQuadRed" + + HLSLPROGRAM + #pragma vertex VertQuad + #pragma fragment FragBilinearRedToRGBA + ENDHLSL + } + + // 21. Nearest project cube to octahedral 2d quad with padding + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "NearestCubeToOctahedralPadding" + + HLSLPROGRAM + #pragma multi_compile_local _ BLIT_DECODE_HDR + #pragma vertex VertQuadPadding + #pragma fragment FragOctahedralProjectNearestRepeat + ENDHLSL + } + + // 22. Bilinear project cube to octahedral 2d quad with padding + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "BilinearCubeToOctahedralPadding" + + HLSLPROGRAM + #pragma multi_compile_local _ BLIT_DECODE_HDR + #pragma vertex VertQuadPadding + #pragma fragment FragOctahedralProjectBilinearRepeat + ENDHLSL + } + + // 23: Bilinear blit with debug draw and color space conversion support + Pass + { + Name "BilinearDebugDraw" + ZWrite Off ZTest Always Blend Off Cull Off + + HLSLPROGRAM + #pragma vertex Vert + #pragma fragment FragmentURPBlitBilinearSampler + #pragma multi_compile_fragment _ _LINEAR_TO_SRGB_CONVERSION + #pragma multi_compile_fragment _ DEBUG_DISPLAY + + half4 FragmentURPBlitBilinearSampler(Varyings input) : SV_Target + { + return FragmentURPBlit(input, sampler_LinearClamp); + } + ENDHLSL + } + + // 24: Nearest blit with debug draw and color space conversion support + Pass + { + Name "NearestDebugDraw" + ZWrite Off ZTest Always Blend Off Cull Off + + HLSLPROGRAM + #pragma vertex Vert + #pragma fragment FragmentURPBlitPointSampler + #pragma multi_compile_fragment _ _LINEAR_TO_SRGB_CONVERSION + #pragma multi_compile_fragment _ DEBUG_DISPLAY + + half4 FragmentURPBlitPointSampler(Varyings input) : SV_Target + { + return FragmentURPBlit(input, sampler_PointClamp); + } + ENDHLSL + } + } + + Fallback Off +} diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/Examples/BlitColorAndDepth.shader b/Packages/com.unity.render-pipelines.core/Documentation~/Examples/BlitColorAndDepth.shader new file mode 100644 index 00000000000..cc99e427ec6 --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Documentation~/Examples/BlitColorAndDepth.shader @@ -0,0 +1,41 @@ +Shader "Hidden/Universal/CoreBlitColorAndDepth" +{ + HLSLINCLUDE + #pragma target 2.0 + #pragma editor_sync_compilation + // Core.hlsl for XR dependencies + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/BlitColorAndDepth.hlsl" + ENDHLSL + + SubShader + { + Tags{ "RenderPipeline" = "UniversalPipeline" } + + // 0: Color Only + Pass + { + ZWrite Off ZTest Always Blend Off Cull Off + Name "ColorOnly" + + HLSLPROGRAM + #pragma vertex Vert + #pragma fragment FragColorOnly + ENDHLSL + } + + // 1: Color Only and Depth + Pass + { + ZWrite On ZTest Always Blend Off Cull Off + Name "ColorAndDepth" + + HLSLPROGRAM + #pragma vertex Vert + #pragma fragment FragColorAndDepth + ENDHLSL + } + } + + Fallback Off +} diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_BlitOctohedralWithPadding.svg b/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_BlitOctohedralWithPadding.svg new file mode 100644 index 00000000000..d210b10c3aa --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_BlitOctohedralWithPadding.svg @@ -0,0 +1,1247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +SourceDestinationscaleBiasTex.yscaleBiasTex.xscaleBiasRT.xscaleBiasTex.zwscaleBiasRT.zwscaleBiasRT.yscaleBiasTex.x * textureSize.xtextureSize.x + paddingInPixelsscaleBiasTex.y * textureSize.ytextureSize.y + paddingInPixelsscaleBiasTex.x * paddingInPixelstextureSize.x + paddingInPixelsscaleBiasTex.y * paddingInPixelstextureSize.y + paddingInPixels diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_BlitQuadWithPadding.svg b/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_BlitQuadWithPadding.svg new file mode 100644 index 00000000000..d6151d174eb --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_BlitQuadWithPadding.svg @@ -0,0 +1,1127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +SourceDestinationscaleBiasTex.yscaleBiasTex.xscaleBiasRT.xscaleBiasTex.zwscaleBiasRT.zwscaleBiasRT.yscaleBiasTex.x * textureSize.xtextureSize.x + paddingInPixelsscaleBiasTex.y * textureSize.ytextureSize.y + paddingInPixelsscaleBiasTex.x * paddingInPixelstextureSize.x + paddingInPixelsscaleBiasTex.y * paddingInPixelstextureSize.y + paddingInPixels diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_octohedron.png b/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_octohedron.png new file mode 100644 index 00000000000..19607d2f99b Binary files /dev/null and b/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_octohedron.png differ diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_texture_example.jpg b/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_texture_example.jpg new file mode 100644 index 00000000000..a832c80cc57 Binary files /dev/null and b/Packages/com.unity.render-pipelines.core/Documentation~/Images/Blitter_texture_example.jpg differ diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/Images/customsettings-addsetting.png b/Packages/com.unity.render-pipelines.core/Documentation~/Images/customsettings-addsetting.png new file mode 100644 index 00000000000..8c887e4c16f Binary files /dev/null and b/Packages/com.unity.render-pipelines.core/Documentation~/Images/customsettings-addsetting.png differ diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/Images/customsettings-settingsgroup.png b/Packages/com.unity.render-pipelines.core/Documentation~/Images/customsettings-settingsgroup.png new file mode 100644 index 00000000000..f014e83f122 Binary files /dev/null and b/Packages/com.unity.render-pipelines.core/Documentation~/Images/customsettings-settingsgroup.png differ diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/TableOfContents.md b/Packages/com.unity.render-pipelines.core/Documentation~/TableOfContents.md index 510bc01d3eb..6adc3f35232 100644 --- a/Packages/com.unity.render-pipelines.core/Documentation~/TableOfContents.md +++ b/Packages/com.unity.render-pipelines.core/Documentation~/TableOfContents.md @@ -20,11 +20,13 @@ * [RTHandle fundamentals](rthandle-system-fundamentals.md) * [Using the RTHandle system](rthandle-system-using.md) * [Custom Material Inspector](custom-material-inspector.md) -* [Custom settings](settings.md) +* [Custom graphics settings](settings.md) * [Adding properties in the menu](adding-properties.md) - * [Add custom graphics settings](add-custom-graphics-settings.md) + * [Add a settings group](add-custom-graphics-settings.md) + * [Add a setting](add-custom-graphics-setting.md) + * [Customize the UI of a setting](customize-ui-for-a-setting.md) * [Get custom graphics settings](get-custom-graphics-settings.md) - * [Include or excude a setting in your build](choose-whether-unity-includes-a-graphics-setting-in-your-build.md) + * [Include or exclude a setting in your build](choose-whether-unity-includes-a-graphics-setting-in-your-build.md) * [Shaders](shaders.md) * [Use shader methods from the SRP Core shader library](built-in-shader-methods.md) * [Synchronizing shader code and C#](generating-shader-includes.md) diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/add-custom-graphics-setting.md b/Packages/com.unity.render-pipelines.core/Documentation~/add-custom-graphics-setting.md new file mode 100644 index 00000000000..d3a57390314 --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Documentation~/add-custom-graphics-setting.md @@ -0,0 +1,60 @@ +# Add a setting + +Add a simple property or a reference property to a [custom graphics settings group](add-custom-graphics-settings.md). You can change the values of the setting in the Unity Editor while you're editing your project. + +Unity serializes the graphics settings you add. For more information, refer to [Script serialization](xref:um-script-serialization). + +**Note:** The value of a custom setting is static in a built project. You can't change the setting at runtime. + +## Add a simple property + +To add a simple property, add a field to your `IRenderPipelineGraphicsSettings` class using the `[SerializeField]` attribute. For example: + +```c# +using System; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +[Serializable] +[SupportedOnRenderPipeline(typeof(UniversalRenderPipelineAsset))] + +// Create a new settings group by implementing the IRenderPipelineGraphicsSettings interface +public class MySettings : IRenderPipelineGraphicsSettings +{ + // Add a private field for the version property + int internalVersion = 1; + + // Implement the public version property + public int version => internalVersion; + + // Add a float setting + [SerializeField] + private float mySetting = 1.0f; + + // Add a Material reference property + [SerializeField] + public Material myMaterial; +} +``` +![](Images/customsettings-addsetting.png)
+The **Edit** > **Project Settings** > **Graphics** window with the new custom setting from the example script. + +## Set the default asset for a reference property + +To set a default asset for a [reference property](xref:um-editing-value-properties#references), for example a material, add a [`[ResourcePath]`](https://docs.unity3d.com/6000.1/Documentation/ScriptReference/Rendering.ResourcePathAttribute.html) attribute. For example: + +```c# +public class MySettings: IRenderPipelineGraphicsSettings +{ + ... + [SerializeField] + [ResourcePath('path-to-default-file')] + public Material myMaterial; +} +``` + +## Additional resources + +- [SerializeField](xref:UnityEngine.SerializeField) +- [Reference properties](xref:EditingValueProperties#references) diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/add-custom-graphics-settings.md b/Packages/com.unity.render-pipelines.core/Documentation~/add-custom-graphics-settings.md index 7b646446f42..1365a8648f4 100644 --- a/Packages/com.unity.render-pipelines.core/Documentation~/add-custom-graphics-settings.md +++ b/Packages/com.unity.render-pipelines.core/Documentation~/add-custom-graphics-settings.md @@ -1,24 +1,26 @@ -# Add custom graphics settings +# Add a settings group -You can add custom graphics settings to the **Edit** > **Project Settings** > **Graphics** window, then use the values of the settings to customize your build. +To add a custom graphics settings group to a Scriptable Render Pipeline, implement the `IRenderPipelineGraphicsSettings` interface. -You can change the values of settings while you're editing your project. Unity makes the values static when it builds your project, so you can't change them at runtime. +Follow these steps: -## Add a setting +1. Create a class that implements the `IRenderPipelineGraphicsSettings` interface, then add a `[Serializable]` attribute. -To add a setting, follow these steps: - -1. Create a class that implements the `IRenderPipelineGraphicsSettings` interface, and add a `[Serializable]` attribute. This becomes a new settings group in the **Graphics** settings window. 2. To set which render pipeline the setting applies to, add a `[SupportedOnRenderPipeline]` attribute and pass in a `RenderPipelineAsset` type. -3. Add a property. This becomes a setting. -4. Implement the `version` field and set it to `0`. Unity doesn't currently use the `version` field, but you must implement it. -For example, the following script adds a setting called **My Value** in a settings group called **My Settings**, in the graphics settings for the Universal Render Pipeline (URP). + **Note:** If you don't add a `[SupportedOnRenderPipeline]` attribute, the setting applies to any Scriptable Render Pipeline. However each Scriptable Render Pipeline stores its own value for the setting. + +3. Implement the `version` property. Unity doesn't currently use the `version` property, but you must implement it. + +Unity adds the new settings group to the **Edit** > **Project Settings** > **Graphics** window. + +For example, the following script adds a settings group called **My Settings** in the **Graphics** settings window of the Universal Render Pipeline (URP). ```c# +using System; using UnityEngine; using UnityEngine.Rendering; -using System; +using UnityEngine.Rendering.Universal; [Serializable] [SupportedOnRenderPipeline(typeof(UniversalRenderPipelineAsset))] @@ -26,67 +28,30 @@ using System; // Create a new settings group by implementing the IRenderPipelineGraphicsSettings interface public class MySettings : IRenderPipelineGraphicsSettings { - // Implement the version field - public int version => 0; + // Add a private field for the version property + int internalVersion = 1; + + // Implement the public version property + public int version => internalVersion; - // Create a new setting and set its default value to 100. - public int myValue = 100; } ``` -## Add a reference property - -[Reference properties](https://docs.unity3d.com/2023.3/Documentation/Manual/EditingValueProperties.html#references) take compatible project assets or GameObjects in the scene as inputs. +![](Images/customsettings-settingsgroup.png)
+The **Edit** > **Project Settings** > **Graphics** window with the new custom settings group from the example script. -To add a reference property, follow these steps: +## Change the display order of settings groups -1. Create a class that implements the `IRenderPipelineResources` interface. This becomes a new settings group in the Graphics Settings window. -2. Add a property. This becomes a reference property. -3. Implement the `version` field and set it to `0`. Unity doesn't currently use the `version` field, but you must implement it. - -For example, the following script adds a reference property called **My Material** that references a material. +To change where a settings group appears, use the `[UnityEngine.Categorization.CategoryInfo]` attribute. For example, the following code gives the settings group the name **My Settings** and moves the group to the top of the graphics settings window. ```c# -using UnityEngine; -using UnityEngine.Rendering; -using System; - -[Serializable] -[SupportedOnRenderPipeline(typeof(UniversalRenderPipelineAsset))] - -// Create a new reference property group by implementing the IRenderPipelineResources interface -public class MySettings: IRenderPipelineResources +[UnityEngine.Categorization.CategoryInfo(Name = "My Settings", Order = 0)] +public class MySettings : IRenderPipelineGraphicsSettings { - // Implement the version field - public int version => 0; - - // Create a new reference property that references a material - [SerializeField] public Material myMaterial; + ... } ``` -To set a default asset, use a [`[ResourcePath]`](https://docs.unity3d.com/2023.3/Documentation/ScriptReference/Rendering.ResourcePathAttribute.html) attribute above the reference property. For example, in the example, add the following line above `public Material myMaterial`. - -```c# -[ResourcePath('path-to-default-file')] -``` - -## Change the name and layout of a settings group - -To change the name of a settings group in the **Graphics** settings window, follow these steps: - -1. Add `using System.ComponentModel` to your script. -2. Add a `[Category]` attribute to your script. For example, `[Category("My Category")]`. - -You can also use the [PropertyDrawer](https://docs.unity3d.com/ScriptReference/PropertyDrawer.html) API to further customize the layout of custom settings. - -## Set which render pipeline a setting applies to - -To set which render pipeline a setting applies to, use the `[SupportedOnRenderPipeline]` attribute and pass in a `RenderPipelineAsset` type. - -For example, if your project uses the Universal Rendering Pipeline (URP) and you want your setting to appear only in the **URP** tab of the **Graphics** settings window, use the following code: - -```c# -[SupportedOnRenderPipeline(typeof(UniversalRenderPipelineAsset))] -``` +## Additional resources +- [Add a setting](add-custom-graphics-setting.md) diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/choose-whether-unity-includes-a-graphics-setting-in-your-build.md b/Packages/com.unity.render-pipelines.core/Documentation~/choose-whether-unity-includes-a-graphics-setting-in-your-build.md index 28095123bd3..fe06da1d100 100644 --- a/Packages/com.unity.render-pipelines.core/Documentation~/choose-whether-unity-includes-a-graphics-setting-in-your-build.md +++ b/Packages/com.unity.render-pipelines.core/Documentation~/choose-whether-unity-includes-a-graphics-setting-in-your-build.md @@ -1,31 +1,35 @@ # Include or exclude a setting in your build -By default, Unity doesn't include a setting ("strips" the setting) in your built project. For example, if you create a custom reference property where you set a shader asset, Unity doesn't include that property in your build. +By default, Unity doesn't include a setting ("strips" the setting) in your built project to optimize performance and reduce build size. For example, if you create a custom reference property that points to a shader asset, by default Unity doesn't include that property in your build. -You can choose to include a setting in your build instead. You can then get the value of the setting at runtime. The value is read-only. +You can choose to include a setting in your build instead. The value of the property is read-only at runtime. ## Include a setting in your build -To include a setting in your build by default, set the `IsAvailableInPlayerBuild` property of your [settings class](add-custom-graphics-settings.md) to `true`. +To include a setting in your build by default, set the `IsAvailableInPlayerBuild` property of your [settings group class](add-custom-graphics-settings.md) to `true`. -For example, add the following line: +For example: ```c# -public bool IsAvailableInPlayerBuild => true; +public class MySettings: IRenderPipelineGraphicsSettingsStripper +{ + ... + // Make settings in this class available in your build + public bool IsAvailableInPlayerBuild => true; +} ``` ## Create your own stripping code -You can override the `IsAvailableInPlayerBuild` property by implementing the `IRenderPipelineGraphicsSettingsStripper` interface, and writing code that conditionally strips or keeps the setting. +To conditionally control whether Unity includes or excludes a setting in your build, override the `IsAvailableInPlayerBuild` property by implementing the `IRenderPipelineGraphicsSettingsStripper` interface. Follow these steps: 1. Create a class that implements the `IRenderPipelineGraphicsSettingsStripper` interface, and pass in your [settings class](add-custom-graphics-settings.md). 2. Implement the `active` property. If you set `active` to `false`, the code in the class doesn't run. -3. Implement the `CanRemoveSettings` method with your own code that decides whether to include the setting. -4. In your code, return either `true` or `false` to strip or keep the setting. +3. Implement the `CanRemoveSettings` method with your own code that decides whether to include the setting. Return `true` to strip the setting, or `false` to include the setting. -For example, in the following code, the `CanRemoveSettings` method returns `true` and strips the setting if the value of the setting is larger than 100. +For example: ```c# using UnityEngine; @@ -41,8 +45,8 @@ class SettingsStripper : IRenderPipelineGraphicsSettingsStripper // Implement the CanRemoveSettings method with our own code public bool CanRemoveSettings(MySettings settings) { - // Strip the setting (return true) if the value is larger than 100 - return settings.myValue > 100; + // Strip the setting (return true) if useMyFeature is false + return !settings.useMyFeature; } } ``` @@ -55,8 +59,9 @@ You can check if a setting exists at runtime. A setting might not exist at runti - Unity didn't include the setting in your build. - The current pipeline doesn't support the setting. +- The setting is in an assembly that Unity doesn't include in your build. Refer to [Organizing scripts into assemblies](xref:um-script-compilation-assembly-definition-files) for more information. -Use `TryGetRenderPipelineSettings` to check if the setting exists. `TryGetRenderPipelineSettings` puts the setting in an `out` variable if it exists. Otherwise it returns `false`. +To check if the setting exists, use the `TryGetRenderPipelineSettings` API. `TryGetRenderPipelineSettings` puts the setting in an `out` variable if the setting exists. Otherwise it returns `false`. For example, the following code checks whether a settings group called `MySettings` exists at runtime: @@ -65,3 +70,7 @@ if (GraphicsSettings.TryGetRenderPipelineSettings(out var mySetting) Debug.Log("The setting is in the build and its value is {mySetting.myValue}"); } ``` + +## Additional resources + +- [Organizing scripts into assemblies](xref:um-script-compilation-assembly-definition-files) diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/customize-ui-for-a-setting.md b/Packages/com.unity.render-pipelines.core/Documentation~/customize-ui-for-a-setting.md new file mode 100644 index 00000000000..bf340bb3b79 --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Documentation~/customize-ui-for-a-setting.md @@ -0,0 +1,77 @@ +# Customize the UI of custom settings + +To change the look of custom settings in the **Graphics** settings window, use the `PropertyDrawer` API. + +Follow these steps: + +1. Create a class that inherits from the [`PropertyDrawer`](xref:UnityEditor.PropertyDrawer) class. +2. Add the `[CustomPropertyDrawer]` attribute to the class, with a reference to your settings class. +3. Override the `PropertyDrawer.CreatePropertyGUI` method, and return a `VisualElement` object that contains the UI elements you want to display. + +The following example creates a custom UI for a `MySettings` class that contains a Boolean and a float field. The Graphics settings window displays the float only when the Boolean field is enabled. + +For more information, refer to [PropertyDrawer](xref:UnityEditor.PropertyDrawer). + +```c# +using UnityEngine; +using UnityEditor; +using UnityEngine.UIElements; + +// Create a custom UI for the properties in the MySettings class +[CustomPropertyDrawer(typeof(MySettings))] +public class MySettingsPropertyDrawer : PropertyDrawer +{ + // Override the CreatePropertyGUI method to define the custom UI + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + // Create a container to hold the UI elements + var container = new VisualElement(); + + // Find the properties to display + var useProperty = property.FindPropertyRelative("m_UseMyFeature"); + var intensityProperty = property.FindPropertyRelative("m_MyFeatureIntensity"); + + // Create property fields for each property + var usePropertyField = new PropertyField(useProperty); + var intensityPropertyField = new PropertyField(intensityProperty); + + // Enable or disable the intensity field based on the value of m_UseMyFeature + usePropertyField.RegisterValueChangeCallback(evt => + { + intensityPropertyField.SetEnabled(useProperty.boolValue); + }); + + // Add the property fields to the container + container.Add(usePropertyField); + container.Add(intensityPropertyField); + + // Return the container to be displayed in the Graphics settings window + return container; + } +} +``` + +## Customize the More (⋮) menu of a settings group + +To add items to the **More** (⋮) menu of a settings group, follow these steps: + +1. Create a class that implements the [`IRenderPipelineGraphicsSettingsContextMenu`](https://docs.unity3d.com/6000.1/Documentation/ScriptReference/Rendering.IRenderPipelineGraphicsSettingsContextMenu.html) interface. +2. Implement the `PopulateContextMenu` method. +3. To add an item, use the `AddItem` API. + +For example: + +```c# +public class MySettingsContextMenu : IRenderPipelineGraphicsSettingsContextMenu +{ + void IRenderPipelineGraphicsSettingsContextMenu.PopulateContextMenu(MySettings setting, PropertyDrawer _, ref GenericMenu menu) + { + menu.AddItem(new GUIContent("My custom menu item"), false, () => { Debug.Log("Menu item was selected."); }); + } +} +``` + +## Additional resources + +- [PropertyDrawer](xref:UnityEditor.PropertyDrawer) +- [IRenderPipelineGraphicsSettingsContextMenu](https://docs.unity3d.com/6000.1/Documentation/ScriptReference/Rendering.IRenderPipelineGraphicsSettingsContextMenu.html) diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/get-custom-graphics-settings.md b/Packages/com.unity.render-pipelines.core/Documentation~/get-custom-graphics-settings.md index 1b30039b513..8cbff7e4c59 100644 --- a/Packages/com.unity.render-pipelines.core/Documentation~/get-custom-graphics-settings.md +++ b/Packages/com.unity.render-pipelines.core/Documentation~/get-custom-graphics-settings.md @@ -2,9 +2,7 @@ To get a custom setting and read its value, use the `GetRenderPipelineSettings` method. -If you want to get a setting at runtime, you must [include the setting in your build](choose-whether-unity-includes-a-graphics-setting-in-your-build.md). - -For example, the following script gets the `MySettings` settings class from the example in the [Add custom graphics settings](add-custom-graphics-settings.md) page, then logs the value of the `MyValue` setting: +For example, the following script gets the `MySettings` settings class from the example in the [Add a setting](add-custom-graphics-setting.md) page, then logs the value of the `mySetting` setting: ```c# using UnityEngine; @@ -19,16 +17,16 @@ public class LogMySettingsValue : MonoBehaviour var mySettings = GraphicsSettings.GetRenderPipelineSettings(); // Log the value of the MyValue setting - Debug.Log(mySettings.myValue); + Debug.Log(mySettings.mySetting); } } ``` -## Detect when a setting changes +## Get a notification when a setting changes -You can configure a property so it notifies other scripts when its value changes. This only works while you're editing your project, not at runtime. +To configure a property so it notifies other scripts when its value changes, use the `SetValueAndNotify` method. You can use this to debug, update UI elements, or trigger other actions when a setting changes. -You can use this to fetch the value only when it changes, instead of every frame in the `Update()` method. +This only works while you're editing your project, not at runtime. If you use `SetValueAndModify` in a built application, Unity throws an exception. Follow these steps: @@ -63,8 +61,6 @@ Follow these steps: } ``` - If you use `SetValueAndModify' in a standalone application, Unity throws an exception. - 3. Use the `GraphicsSettings.Subscribe` method to subscribe to notifications from the setting, and call an `Action` when the setting changes. For example: @@ -101,4 +97,6 @@ To stop calling a method when a setting changes, use the `GraphicsSettings.Unsub GraphicsSettings.Unsubscribe(onSettingChanged); ``` +## Additional resources +- [`IRenderPipelineGraphicsSettings`](https://docs.unity3d.com/6000.1/Documentation/ScriptReference/Rendering.IRenderPipelineGraphicsSettings.html) diff --git a/Packages/com.unity.render-pipelines.core/Documentation~/settings.md b/Packages/com.unity.render-pipelines.core/Documentation~/settings.md index 28e67b49180..edc8c94bece 100644 --- a/Packages/com.unity.render-pipelines.core/Documentation~/settings.md +++ b/Packages/com.unity.render-pipelines.core/Documentation~/settings.md @@ -1,10 +1,16 @@ -# Custom settings +# Custom graphics settings -Add custom properties and settings to a Scriptable Render Pipeline. +Add, store, and manage custom settings that control rendering features and behaviours in a Scriptable Render Pipeline. For example, quality or shader settings. |Page|Description| |-|-| |[Adding properties in the menu](adding-properties.md)|Add properties in the **Core Render Pipeline** settings section.| -|[Add custom graphics settings](add-custom-graphics-settings.md)|Add custom graphics settings to the **Edit** > **Project Settings** > **Graphics** window, then use the values of the settings to customize your build.| +|[Add a settings group](add-custom-graphics-settings.md)|To add custom graphics settings to a Scriptable Render Pipeline, implement the `IRenderPipelineGraphicsSettings` interface. | +|[Add a setting](add-custom-graphics-setting.md)|Add a simple property or a reference property to a custom graphics settings group.| +|[Customize the UI of a setting](customize-ui-for-a-setting.md)|Customize how a setting displays in the graphics settings window, or add items to the **More** (⋮) menu of a settings group.| |[Get custom graphics settings](get-custom-graphics-settings.md)|Get a custom graphics setting and read its value, or detect when a setting changes.| |[Include or exclude a setting in your build](choose-whether-unity-includes-a-graphics-setting-in-your-build.md)|Choose whether Unity includes or strips a graphics setting in your build, and check if a build includes a setting.| + +## Additional resources + +- [Graphics settings](xref:class-GraphicsSettings) in the Unity manual diff --git a/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CoreBuildData.cs b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CoreBuildData.cs index a6455d25afb..08e01d12352 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CoreBuildData.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CoreBuildData.cs @@ -19,6 +19,11 @@ public class CoreBuildData : IDisposable /// public static CoreBuildData instance => m_Instance ??= CreateInstance(); + /// + /// Returns if the build is done for debug + /// + public bool isDevelopmentBuild { get; set; } + /// /// If the target build has an SRP configured /// @@ -39,24 +44,32 @@ public class CoreBuildData : IDisposable internal bool pipelineSupportGPUResidentDrawer { get; private set; } = false; internal bool playerNeedGPUResidentDrawer { get; private set; } = false; - private CoreBuildData(BuildTarget buildTarget) - { - m_Instance = this; + /// + /// Initializes a new instance of the class for the core library. + /// This constructor may also be invoked when building Asset Bundles. + /// + /// The target platform for the build (e.g., Standalone, iOS, Android). + /// Indicates whether the build is a development build. If true, the build includes debugging and logging features. + public CoreBuildData(BuildTarget buildTarget, bool isDevelopmentBuild) - if (!buildTarget.TryGetRenderPipelineAssets(renderPipelineAssets)) - return; + { + if (buildTarget.TryGetRenderPipelineAssets(renderPipelineAssets)) + { + buildingPlayerForRenderPipeline = true; - buildingPlayerForRenderPipeline = true; + //We can check only the first as we don't support multiple pipeline type in player + var asset = renderPipelineAssets[0]; + currentRenderPipelineAssetType = asset.GetType(); - //We can check only the first as we don't support multiple pipeline type in player - var asset = renderPipelineAssets[0]; - currentRenderPipelineAssetType = asset.GetType(); + CheckGPUResidentDrawerUsage(); + } - CheckGPUResidentDrawerUsage(); + this.isDevelopmentBuild = isDevelopmentBuild; + m_Instance = this; } private static CoreBuildData CreateInstance() - => new(EditorUserBuildSettings.activeBuildTarget); + => new(EditorUserBuildSettings.activeBuildTarget, Debug.isDebugBuild); private void CheckGPUResidentDrawerUsage() { diff --git a/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CorePreprocessBuild.cs b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CorePreprocessBuild.cs index 066461e1dda..54c9eae7730 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CorePreprocessBuild.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/CorePreprocessBuild.cs @@ -3,7 +3,7 @@ namespace UnityEditor.Rendering { - //Make CoreBuildData constructed and kept till end of build + // Make CoreBuildData constructed and keep the instance until the end of build class CorePreprocessBuild : IPreprocessBuildWithReport, IPostprocessBuildWithReport { int IOrderedCallback.callbackOrder => int.MinValue + 50; @@ -13,7 +13,8 @@ class CorePreprocessBuild : IPreprocessBuildWithReport, IPostprocessBuildWithRep void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report) { m_BuildData?.Dispose(); - m_BuildData = CoreBuildData.instance; + bool isDevelopmentBuild = (report.summary.options & BuildOptions.Development) != 0; + m_BuildData = new CoreBuildData(EditorUserBuildSettings.activeBuildTarget, isDevelopmentBuild); } void IPostprocessBuildWithReport.OnPostprocessBuild(BuildReport report) diff --git a/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/SettingsStrippers/RenderingDebuggerRuntimeResourcesStripper.cs b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/SettingsStrippers/RenderingDebuggerRuntimeResourcesStripper.cs new file mode 100644 index 00000000000..8d8de53132f --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/SettingsStrippers/RenderingDebuggerRuntimeResourcesStripper.cs @@ -0,0 +1,17 @@ +using UnityEngine.Rendering; + +namespace UnityEditor.Rendering +{ + class RenderingDebuggerRuntimeResourcesStripper : IRenderPipelineGraphicsSettingsStripper + { + public bool active => true; + + public bool CanRemoveSettings(RenderingDebuggerRuntimeResources settings) + { + // When building for any SRP, we assume that we support the Rendering Debugger + // But, if we are building for retail builds, we strip those runtime UI resources from the final player + if (!CoreBuildData.instance.buildingPlayerForRenderPipeline) return true; + return !CoreBuildData.instance.isDevelopmentBuild; + } + } +} diff --git a/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/SettingsStrippers/RenderingDebuggerRuntimeResourcesStripper.cs.meta b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/SettingsStrippers/RenderingDebuggerRuntimeResourcesStripper.cs.meta new file mode 100644 index 00000000000..100a6dca5a2 --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Editor/BuildProcessors/SettingsStrippers/RenderingDebuggerRuntimeResourcesStripper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6e822da6eeb446d6b972b3dd976f906e +timeCreated: 1736862653 \ No newline at end of file diff --git a/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugUIDrawer.Builtins.cs b/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugUIDrawer.Builtins.cs index cb89a14027a..f5bed0d0d3d 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugUIDrawer.Builtins.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugUIDrawer.Builtins.cs @@ -830,7 +830,10 @@ public override bool OnGUI(DebugUI.Widget widget, DebugState state) rowRect.xMin += 2; rowRect.xMax -= 2; - EditorGUI.LabelField(rowRect, GUIContent.none, EditorGUIUtility.TrTextContent(row.displayName), DebugWindow.Styles.centeredLeft); + + bool isAlternate = r % 2 == 0; + + EditorGUI.LabelField(rowRect, GUIContent.none, EditorGUIUtility.TrTextContent(row.displayName),isAlternate ? DebugWindow.Styles.centeredLeft : DebugWindow.Styles.centeredLeftAlternate); rowRect.xMin -= 2; rowRect.xMax += 2; @@ -841,7 +844,7 @@ public override bool OnGUI(DebugUI.Widget widget, DebugState state) rowRect.x += rowRect.width; rowRect.width = columns[visible[c]].width; if (!row.isHidden) - DisplayChild(rowRect, row.children[visible[c] - 1]); + DisplayChild(rowRect, row.children[visible[c] - 1], isAlternate); } rowRect.y += rowRect.height; } @@ -884,7 +887,7 @@ internal Rect DrawOutline(Rect rect) return new Rect(rect.x + size, rect.y + size, rect.width - 2 * size, rect.height - 2 * size); } - internal void DisplayChild(Rect rect, DebugUI.Widget child) + internal void DisplayChild(Rect rect, DebugUI.Widget child, bool isAlternate) { rect.xMin += 2; rect.xMax -= 2; @@ -898,7 +901,7 @@ internal void DisplayChild(Rect rect, DebugUI.Widget child) if (child.GetType() == typeof(DebugUI.Value)) { var widget = Cast(child); - EditorGUI.LabelField(rect, GUIContent.none, EditorGUIUtility.TrTextContent(widget.GetValue().ToString())); + EditorGUI.LabelField(rect, GUIContent.none, EditorGUIUtility.TrTextContent(widget.GetValue().ToString()), isAlternate ? DebugWindow.Styles.centeredLeft : DebugWindow.Styles.centeredLeftAlternate); } else if (child.GetType() == typeof(DebugUI.ColorField)) { diff --git a/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.cs b/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.cs index 4de92d66a93..c8eae3cd2f3 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Debugging/DebugWindow.cs @@ -11,7 +11,6 @@ using UnityEngine; using UnityEngine.Assertions; using UnityEngine.Rendering; - using PackageInfo = UnityEditor.PackageManager.PackageInfo; namespace UnityEditor.Rendering @@ -626,6 +625,7 @@ public class Styles public readonly Color skinBackgroundColor; public static GUIStyle centeredLeft = new GUIStyle(EditorStyles.label) { alignment = TextAnchor.MiddleLeft }; + public static GUIStyle centeredLeftAlternate = new GUIStyle(EditorStyles.label) { alignment = TextAnchor.MiddleLeft }; public static float singleRowHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; public static int foldoutColumnWidth = 70; @@ -637,6 +637,12 @@ public Styles() Color backgroundColorDarkSkin = new Color32(38, 38, 38, 128); Color backgroundColorLightSkin = new Color32(128, 128, 128, 96); + centeredLeftAlternate.normal.background = CoreEditorUtils.CreateColoredTexture2D( + EditorGUIUtility.isProSkin + ? new Color(63 / 255.0f, 63 / 255.0f, 63 / 255.0f, 255 / 255.0f) + : new Color(202 / 255.0f, 202 / 255.0f, 202 / 255.0f, 255 / 255.0f), + "centeredLeftAlternate Background"); + sectionScrollView = new GUIStyle(sectionScrollView); sectionScrollView.overflow.bottom += 1; @@ -650,6 +656,15 @@ public Styles() skinBackgroundColor = EditorGUIUtility.isProSkin ? backgroundColorDarkSkin : backgroundColorLightSkin; labelWithZeroValueStyle.normal.textColor = Color.gray; + + // Make sure that textures are unloaded on domain reloads. + void OnBeforeAssemblyReload() + { + UnityEngine.Object.DestroyImmediate(centeredLeftAlternate.normal.background); + AssemblyReloadEvents.beforeAssemblyReload -= OnBeforeAssemblyReload; + } + + AssemblyReloadEvents.beforeAssemblyReload += OnBeforeAssemblyReload; } } diff --git a/Packages/com.unity.render-pipelines.core/Editor/Deprecated.cs b/Packages/com.unity.render-pipelines.core/Editor/Deprecated.cs index e1bdc6b6989..e24459166bf 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Deprecated.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Deprecated.cs @@ -15,25 +15,47 @@ public sealed class SetAdditionalPropertiesVisibilityAttribute : Attribute } /// - /// This attributes tells a class which type of - /// it's an editor for. - /// When you make a custom editor for a component, you need put this attribute on the editor - /// class. + /// This attribute tells the class which type of + /// it is an editor for. It is used to associate a custom editor + /// with a specific volume component, enabling the editor to handle its custom properties and settings. /// + /// + /// When creating a custom editor for a , this attribute must be applied + /// to the editor class to ensure it targets the appropriate component. This functionality has been deprecated, + /// and developers are encouraged to use the attribute instead for newer versions. + /// + /// The attribute specifies which type the editor class is responsible for. + /// Typically, it is used in conjunction with custom editor UI drawing and handling logic for the specified volume component. + /// This provides a way for developers to create custom editing tools for their volume components in the Unity Inspector. + /// + /// Since Unity 2022.2, this functionality has been replaced by the attribute, and as such, + /// it is advised to update any existing custom editors to use the newer approach. + /// /// + /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] [Obsolete("VolumeComponentEditor property has been deprecated. Please use CustomEditor. #from(2022.2)")] public sealed class VolumeComponentEditorAttribute : CustomEditor { /// - /// A type derived from . + /// A type derived from that this editor is responsible for. /// + /// + /// This field holds the type of the volume component that the editor class will handle. + /// The type should be a subclass of and is used to associate the editor + /// with the specific component type. + /// public readonly Type componentType; /// /// Creates a new instance. /// - /// A type derived from + /// A type derived from that the editor is responsible for. + /// + /// This constructor initializes the attribute with the component type that the editor will target. + /// The component type is a subclass of and provides the necessary + /// context for the editor class to function properly within the Unity Editor. + /// public VolumeComponentEditorAttribute(Type componentType) : base(componentType, true) { @@ -41,6 +63,7 @@ public VolumeComponentEditorAttribute(Type componentType) } } + /// /// Interface that should be used with [ScriptableRenderPipelineExtension(type))] attribute to dispatch ContextualMenu calls on the different SRPs /// diff --git a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Serialization.cs b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Serialization.cs index d0dadf25dc2..12733d3cc13 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Serialization.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/Lighting/ProbeVolume/ProbeGIBaking.Serialization.cs @@ -1031,7 +1031,7 @@ unsafe static void WriteBakingCells(BakingCell[] bakingCells) AssetDatabase.SaveAssets(); // Explicitly make sure the binary output files are writable since we write them using the C# file API (i.e. check out Perforce files if applicable) - var outputPaths = new List(new[] { cellDataFilename, cellBricksDataFilename, cellSharedDataFilename, cellSupportDataFilename, cellOptionalDataFilename }); + var outputPaths = new List(new[] { cellDataFilename, cellBricksDataFilename, cellSharedDataFilename, cellSupportDataFilename, cellOptionalDataFilename, cellProbeOcclusionDataFilename }); if (!AssetDatabase.MakeEditable(outputPaths.ToArray())) Debug.LogWarning($"Failed to make one or more probe volume output file(s) writable. This could result in baked data not being properly written to disk. {string.Join(",", outputPaths)}"); @@ -1046,9 +1046,13 @@ unsafe static void WriteBakingCells(BakingCell[] bakingCells) { WriteNativeArray(fs, probesL2); } - using (var fs = new System.IO.FileStream(cellProbeOcclusionDataFilename, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite)) + if (probeOcclusion.Length > 0) { - WriteNativeArray(fs, probeOcclusion); + // Write the probe occlusion data file, only if this data was baked (shadowmask mode) - UUM-85411 + using (var fs = new System.IO.FileStream(cellProbeOcclusionDataFilename, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite)) + { + WriteNativeArray(fs, probeOcclusion); + } } using (var fs = new System.IO.FileStream(cellSharedDataFilename, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite)) { diff --git a/Packages/com.unity.render-pipelines.core/Editor/RenderGraph/RenderGraphViewer.SidePanel.cs b/Packages/com.unity.render-pipelines.core/Editor/RenderGraph/RenderGraphViewer.SidePanel.cs index 37419dc3794..8ae75375ebe 100644 --- a/Packages/com.unity.render-pipelines.core/Editor/RenderGraph/RenderGraphViewer.SidePanel.cs +++ b/Packages/com.unity.render-pipelines.core/Editor/RenderGraph/RenderGraphViewer.SidePanel.cs @@ -39,9 +39,8 @@ static partial class Classes public const string kCustomFoldoutArrow = "custom-foldout-arrow"; } - static readonly System.Text.RegularExpressions.Regex k_TagRegex = new ("<[^>]*>"); - const string k_SelectionColorBeginTag = ""; - const string k_SelectionColorEndTag = ""; + internal const string k_SelectionColorBeginTag = ""; + internal const string k_SelectionColorEndTag = ""; TwoPaneSplitView m_SidePanelSplitView; bool m_ResourceListExpanded = true; @@ -109,12 +108,37 @@ void InitializeSidePanel() passSearchField.RegisterValueChangedCallback(evt => OnSearchFilterChanged(m_PassDescendantCache, evt.newValue)); } - bool IsSearchFilterMatch(string str, string searchString, out int startIndex, out int endIndex) + static bool IsInsideTag(string input, int index) + { + int openTagIndex = input.LastIndexOf('<', index); + int closeTagIndex = input.LastIndexOf('>', index); + return openTagIndex > closeTagIndex; + } + + static bool IsSearchFilterMatch(string str, string searchString, out int startIndex, out int endIndex) { startIndex = -1; endIndex = -1; - startIndex = str.IndexOf(searchString, 0, StringComparison.CurrentCultureIgnoreCase); + if (searchString.Length == 0) + return true; + + int searchStartIndex = 0; + for (;;) + { + startIndex = str.IndexOf(searchString, searchStartIndex, StringComparison.CurrentCultureIgnoreCase); + + // If we found a match but it is inside another tag, ignore it and continue + if (startIndex != -1 && IsInsideTag(str, startIndex)) + { + searchStartIndex = startIndex + 1; + continue; + } + + // Either valid match (not inside another tag) or no match + break; + } + if (startIndex == -1) return false; @@ -134,6 +158,9 @@ void OnSearchFilterChanged(Dictionary> elementC Debug.LogWarning("[Render Graph Viewer] Search string limit exceeded: " + k_SearchStringLimit); } + // Sanitize to not match rich text tags + searchString = searchString.Replace("<", string.Empty).Replace(">", string.Empty); + // If the search string hasn't changed, avoid repeating the same search if (m_PendingSearchString == searchString) return; @@ -147,12 +174,12 @@ void OnSearchFilterChanged(Dictionary> elementC .schedule .Execute(() => { - PerformSearchAsync(elementCache, searchString); + PerformSearch(elementCache, searchString); }) .StartingIn(5); // Avoid spamming multiple search if the user types really fast } - private void PerformSearchAsync(Dictionary> elementCache, string searchString) + internal static void PerformSearch(Dictionary> elementCache, string searchString) { // Display filter foreach (var (foldout, descendants) in elementCache) @@ -160,20 +187,28 @@ private void PerformSearchAsync(Dictionary> ele bool anyDescendantMatchesSearch = false; foreach (var elem in descendants) { - // Remove any existing highlight var text = elem.text; - var hasHighlight = k_TagRegex.IsMatch(text); - text = k_TagRegex.Replace(text, string.Empty); + + // Remove existing match highlight tags + var hasHighlight = text.IndexOf(k_SelectionColorBeginTag, StringComparison.Ordinal) >= 0; + if (hasHighlight) + { + text = text.Replace(k_SelectionColorBeginTag, string.Empty); + text = text.Replace(k_SelectionColorEndTag, string.Empty); + } + if (!IsSearchFilterMatch(text, searchString, out int startHighlight, out int endHighlight)) { - if (hasHighlight) - elem.text = text; + // Reset original text + elem.text = text; continue; } - - text = text.Insert(startHighlight, k_SelectionColorBeginTag); - text = text.Insert(endHighlight + k_SelectionColorBeginTag.Length + 1, k_SelectionColorEndTag); + if (startHighlight >= 0 && endHighlight >= 0) + { + text = text.Insert(startHighlight, k_SelectionColorBeginTag); + text = text.Insert(endHighlight + k_SelectionColorBeginTag.Length + 1, k_SelectionColorEndTag); + } elem.text = text; anyDescendantMatchesSearch = true; } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/CommandBuffers/BaseCommandBufer.cs b/Packages/com.unity.render-pipelines.core/Runtime/CommandBuffers/BaseCommandBufer.cs index 966c22cb1c2..047f8da0945 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/CommandBuffers/BaseCommandBufer.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/CommandBuffers/BaseCommandBufer.cs @@ -50,7 +50,7 @@ protected internal void ThrowIfGlobalStateNotAllowed() [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")] protected internal void ThrowIfRasterNotAllowed() { - if (m_ExecutingPass != null && !m_ExecutingPass.HasRenderAttachments()) throw new InvalidOperationException($"{m_ExecutingPass.name}: Using raster commands from a pass with no active render targets is not allowed as it will use an undefined render target state. Please set-up the pass's render targets using SetRenderAttachments."); + if (m_ExecutingPass != null && !m_ExecutingPass.HasRenderAttachments()) throw new InvalidOperationException($"{m_ExecutingPass.name}: Using raster commands from a pass with no active render target is not allowed as it will use an undefined render target state. Please set up pass render targets using SetRenderAttachments."); } /// @@ -71,13 +71,13 @@ protected internal void ValidateTextureHandle(TextureHandle h) if (h.IsBuiltin()) return; - if (!m_ExecutingPass.IsRead(h.handle) && !m_ExecutingPass.IsWritten(h.handle)) + if (!m_ExecutingPass.IsRead(h.handle) && !m_ExecutingPass.IsWritten(h.handle) && !m_ExecutingPass.IsTransient(h.handle)) { - throw new Exception("Pass '" + m_ExecutingPass.name + "' is trying to use a texture on the command buffer that was never registered with the pass builder. Please indicate the texture use to the pass builder."); + throw new Exception($"Pass '{m_ExecutingPass.name}' is trying to bind a texture on the command buffer that is not registered by its builder. Please indicate to the pass builder how the texture is used (UseTexture/CreateTransientTexture)."); } if (m_ExecutingPass.IsAttachment(h)) { - throw new Exception("Pass '" + m_ExecutingPass.name + "' is using a texture as a fragment attachment (SetRenderAttachment/SetRenderAttachmentDepth) but is also trying to bind it as regular texture. Please fix this pass. "); + throw new Exception($"Pass '{m_ExecutingPass.name}' is trying to bind a texture on the command buffer that is already set as a fragment attachment (SetRenderAttachment/SetRenderAttachmentDepth). A texture cannot be used as both in one pass, please fix its usage in the pass builder."); } } } @@ -93,17 +93,17 @@ protected internal void ValidateTextureHandle(TextureHandle h) [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")] protected internal void ValidateTextureHandleRead(TextureHandle h) { - if(RenderGraph.enableValidityChecks) + if (RenderGraph.enableValidityChecks) { if (m_ExecutingPass == null) return; - if (!m_ExecutingPass.IsRead(h.handle)) + if (!m_ExecutingPass.IsRead(h.handle) && !m_ExecutingPass.IsTransient(h.handle)) { - throw new Exception("Pass '" + m_ExecutingPass.name + "' is trying to read a texture on the command buffer that was never registered with the pass builder. Please indicate the texture as read to the pass builder."); + throw new Exception($"Pass '{m_ExecutingPass.name}' is trying to read a texture on the command buffer that is not registered by its builder. Please indicate to the pass builder that the texture is read (UseTexture/CreateTransientTexture)."); } if (m_ExecutingPass.IsAttachment(h)) { - throw new Exception("Pass '" + m_ExecutingPass.name + "' is using a texture as a fragment attachment (SetRenderAttachment/SetRenderAttachmentDepth) but is also trying to bind it as regular texture. Please fix this pass. "); + throw new Exception($"Pass '{m_ExecutingPass.name}' is trying to bind a texture on the command buffer that is already set as a fragment attachment (SetRenderAttachment/SetRenderAttachmentDepth). A texture cannot be used as both in one pass, please fix its usage in the pass builder."); } } } @@ -129,13 +129,14 @@ protected internal void ValidateTextureHandleWrite(TextureHandle h) throw new Exception("Pass '" + m_ExecutingPass.name + "' is trying to write to a built-in texture. This is not allowed built-in textures are small default resources like `white` or `black` that cannot be written to."); } - if (!m_ExecutingPass.IsWritten(h.handle)) + if (!m_ExecutingPass.IsWritten(h.handle) && !m_ExecutingPass.IsTransient(h.handle)) { - throw new Exception("Pass '" + m_ExecutingPass.name + "' is trying to write a texture on the command buffer that was never registered with the pass builder. Please indicate the texture as written to the pass builder."); + throw new Exception($"Pass '{m_ExecutingPass.name}' is trying to write a texture on the command buffer that is not registered by its builder. Please indicate to the pass builder that the texture is written (UseTexture/CreateTransientTexture)."); } if (m_ExecutingPass.IsAttachment(h)) { - throw new Exception("Pass '" + m_ExecutingPass.name + "' is using a texture as a fragment attachment (SetRenderAttachment/SetRenderAttachmentDepth) but is also trying to bind it as regular texture. Please fix this pass. "); + throw new Exception($"Pass '{m_ExecutingPass.name}' is trying to bind a texture on the command buffer that is already set as a fragment attachment (SetRenderAttachment/SetRenderAttachmentDepth). A texture cannot be used as both in one pass, please fix its usage in the pass builder."); + } } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/CommandBuffers/CommandBufferHelpers.cs b/Packages/com.unity.render-pipelines.core/Runtime/CommandBuffers/CommandBufferHelpers.cs index 3db10803ec5..3f7ddbc3310 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/CommandBuffers/CommandBufferHelpers.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/CommandBuffers/CommandBufferHelpers.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; using UnityEngine.VFX; namespace UnityEngine.Rendering @@ -17,6 +18,7 @@ public struct CommandBufferHelpers /// /// The CommandBuffer the RasterCommandBuffer should record it's commands to. /// A RasterCommandBuffer that will record its commands to the given buffer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static RasterCommandBuffer GetRasterCommandBuffer(CommandBuffer baseBuffer) { rasterCmd.m_WrappedCommandBuffer = baseBuffer; @@ -28,6 +30,7 @@ public static RasterCommandBuffer GetRasterCommandBuffer(CommandBuffer baseBuffe /// /// The CommandBuffer the RasterCommandBuffer should record it's commands to. /// A ComputeCommandBuffer that will record its commands to the given buffer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ComputeCommandBuffer GetComputeCommandBuffer(CommandBuffer baseBuffer) { computeCmd.m_WrappedCommandBuffer = baseBuffer; @@ -39,6 +42,7 @@ public static ComputeCommandBuffer GetComputeCommandBuffer(CommandBuffer baseBuf /// /// The CommandBuffer the UnsafeCommandBuffer should record its commands to. /// A UnsafeCommandBuffer that will record its commands to the given buffer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static UnsafeCommandBuffer GetUnsafeCommandBuffer(CommandBuffer baseBuffer) { unsafeCmd.m_WrappedCommandBuffer = baseBuffer; @@ -51,6 +55,7 @@ public static UnsafeCommandBuffer GetUnsafeCommandBuffer(CommandBuffer baseBuffe /// /// The UnsafeCommandBuffer you want to get the engine commandbuffer from. /// A CommandBuffer that will record its commands to the given buffer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static CommandBuffer GetNativeCommandBuffer(UnsafeCommandBuffer baseBuffer) { return baseBuffer.m_WrappedCommandBuffer; diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugDisplaySettingsVolumes.cs b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugDisplaySettingsVolumes.cs index eb34eeaf04d..f7f88572b5f 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugDisplaySettingsVolumes.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugDisplaySettingsVolumes.cs @@ -39,16 +39,19 @@ static class Strings public static readonly string camera = "Camera"; public static readonly string parameter = "Parameter"; public static readonly string component = "Component"; - public static readonly string debugViewNotSupported = "Debug view not supported"; + public static readonly string debugViewNotSupported = "N/A"; + public static readonly string parameterNotOverrided = "-"; public static readonly string volumeInfo = "Volume Info"; + public static readonly string gameObject = "GameObject"; public static readonly string resultValue = "Result"; public static readonly string resultValueTooltip = "The interpolated result value of the parameter. This value is used to render the camera."; - public static readonly string globalDefaultValue = "Default"; + public static readonly string globalDefaultValue = "Graphics Settings"; public static readonly string globalDefaultValueTooltip = "Default value for this parameter, defined by the Default Volume Profile in Global Settings."; - public static readonly string qualityLevelValue = "SRP Asset"; + public static readonly string qualityLevelValue = "Quality Settings"; public static readonly string qualityLevelValueTooltip = "Override value for this parameter, defined by the Volume Profile in the current SRP Asset."; public static readonly string global = "Global"; public static readonly string local = "Local"; + public static readonly string volumeProfile = "Volume Profile"; } const string k_PanelTitle = "Volume"; @@ -107,40 +110,26 @@ public static DebugUI.ObjectPopupField CreateCameraSelector(SettingsPanel panel, }; } - static DebugUI.Widget CreateVolumeParameterWidget(string name, VolumeParameter param, Func isHiddenCallback = null) + static DebugUI.Widget CreateVolumeParameterWidget(string name, bool isResultParameter, VolumeParameter param, Func isHiddenCallback = null) { - if (param == null) - return new DebugUI.Value() { displayName = name, getter = () => "-" }; - - var parameterType = param.GetType(); - - // Special overrides - if (parameterType == typeof(ColorParameter)) +#if UNITY_EDITOR || DEVELOPMENT_BUILD + if (param != null) { - var p = (ColorParameter)param; - return new DebugUI.ColorField() + var parameterType = param.GetType(); + if (parameterType == typeof(ColorParameter)) { - displayName = name, - hdr = p.hdr, - showAlpha = p.showAlpha, - getter = () => p.value, - setter = value => p.value = value, - isHiddenCallback = isHiddenCallback - }; - } - else if (parameterType == typeof(BoolParameter)) - { - var p = (BoolParameter)param; - return new DebugUI.BoolField() - { - displayName = name, - getter = () => p.value, - setter = value => p.value = value, - isHiddenCallback = isHiddenCallback - }; - } - else - { + var p = (ColorParameter)param; + return new DebugUI.ColorField() + { + displayName = name, + hdr = p.hdr, + showAlpha = p.showAlpha, + getter = () => p.value, + setter = value => p.value = value, + isHiddenCallback = isHiddenCallback + }; + } + var typeInfo = parameterType.GetTypeInfo(); var genericArguments = typeInfo.BaseType.GenericTypeArguments; if (genericArguments.Length > 0 && genericArguments[0].IsArray) @@ -152,247 +141,201 @@ static DebugUI.Widget CreateVolumeParameterWidget(string name, VolumeParameter p type = parameterType }; } - } - // For parameters that do not override `ToString` - var property = param.GetType().GetProperty("value"); - var toString = property.PropertyType.GetMethod("ToString", Type.EmptyTypes); - if ((toString == null) || (toString.DeclaringType == typeof(object)) || (toString.DeclaringType == typeof(UnityEngine.Object))) - { - // Check if the parameter has a name - var nameProp = property.PropertyType.GetProperty("name"); - if (nameProp == null) - return new DebugUI.Value() { displayName = name, getter = () => Strings.debugViewNotSupported }; - - // Return the parameter name return new DebugUI.Value() { displayName = name, getter = () => { - var value = property.GetValue(param); - if (value == null || value.Equals(null)) - return Strings.none; - var valueString = nameProp.GetValue(value); - return valueString ?? Strings.none; + var property = param.GetType().GetProperty("value"); + if (property == null) + return "-"; + + if (isResultParameter || param.overrideState) + { + var value = property.GetValue(param); + var propertyType = property.PropertyType; + if (value == null || value.Equals(null)) + return Strings.none + $" ({propertyType.Name})"; + + var toString = propertyType.GetMethod("ToString", Type.EmptyTypes); + if ((toString == null) || (toString.DeclaringType == typeof(object)) || (toString.DeclaringType == typeof(UnityEngine.Object))) + { + // Check if the parameter has a name + var nameProp = property.PropertyType.GetProperty("name"); + if (nameProp == null) + return Strings.debugViewNotSupported; + + var valueString = nameProp.GetValue(value); + return valueString ?? Strings.none; + } + + return value.ToString(); + } + + return Strings.parameterNotOverrided; }, isHiddenCallback = isHiddenCallback }; } - - // Call the ToString method - return new DebugUI.Value() - { - displayName = name, - getter = () => - { - var value = property.GetValue(param); - return value == null ? Strings.none : value.ToString(); - }, - isHiddenCallback = isHiddenCallback - }; + #endif + return new DebugUI.Value(); } static DebugUI.Value s_EmptyDebugUIValue = new DebugUI.Value { getter = () => string.Empty }; - public static DebugUI.Table CreateVolumeTable(DebugDisplaySettingsVolume data) + struct VolumeParameterChain { - var table = new DebugUI.Table() + public DebugUI.Widget.NameAndTooltip nameAndTooltip; + public VolumeProfile volumeProfile; + public VolumeComponent volumeComponent; + public Volume volume; + } + + static VolumeComponent GetSelectedVolumeComponent(VolumeProfile profile, Type selectedType) + { + if (profile != null) { - displayName = Strings.parameter, - isReadOnly = true, - isHiddenCallback = () => data.volumeDebugSettings.selectedComponent == 0 - }; + foreach (var component in profile.components) + if (component.GetType() == selectedType) + return component; + } + return null; + } + + static List GetResolutionChain(DebugDisplaySettingsVolume data) + { + List chain = new List(); Type selectedType = data.volumeDebugSettings.selectedComponentType; if (selectedType == null) - return table; + return chain; var volumeManager = VolumeManager.instance; var stack = data.volumeDebugSettings.selectedCameraVolumeStack ?? volumeManager.stack; var stackComponent = stack.GetComponent(selectedType); if (stackComponent == null) - return table; - - var volumes = data.volumeDebugSettings.GetVolumes(); + return chain; - // First row for volume info - var row1 = new DebugUI.Table.Row() + var result = new VolumeParameterChain() { - displayName = Strings.volumeInfo, - opened = true, // Open by default for the in-game view - children = + nameAndTooltip = new DebugUI.Widget.NameAndTooltip() { - new DebugUI.Value() - { - displayName = Strings.resultValue, - tooltip = Strings.resultValueTooltip, - getter = () => string.Empty - } - } - }; - - // Second row, links to volume gameobjects - var row2 = new DebugUI.Table.Row() - { - displayName = "GameObject", - children = { s_EmptyDebugUIValue } - }; - - // Third row, links to volume profile assets - var row3 = new DebugUI.Table.Row() - { - displayName = "Volume Profile", - children = { s_EmptyDebugUIValue } + name = Strings.resultValue, + tooltip = Strings.resultValueTooltip, + }, + volumeComponent = stackComponent, }; - // Fourth row, empty (to separate from actual data) - var row4 = new DebugUI.Table.Row() - { - displayName = string.Empty , - children = { s_EmptyDebugUIValue } - }; + chain.Add(result); + // Add volume components that override default values + var volumes = data.volumeDebugSettings.GetVolumes(); foreach (var volume in volumes) { var profile = volume.HasInstantiatedProfile() ? volume.profile : volume.sharedProfile; - row1.children.Add(new DebugUI.Value() + var overrideComponent = GetSelectedVolumeComponent(profile, selectedType); + if (overrideComponent != null) { - displayName = profile.name, - tooltip = $"Override value for this parameter, defined by {profile.name}", - getter = () => + var overrideVolume = new VolumeParameterChain() { - var scope = volume.isGlobal ? Strings.global : Strings.local; - var weight = data.volumeDebugSettings.GetVolumeWeight(volume); - return scope + " (" + (weight * 100f) + "%)"; - } - }); - row2.children.Add(new DebugUI.ObjectField() { displayName = string.Empty, getter = () => volume }); - row3.children.Add(new DebugUI.ObjectField() { displayName = string.Empty, getter = () => profile }); - row4.children.Add(s_EmptyDebugUIValue); + nameAndTooltip = new DebugUI.Widget.NameAndTooltip() + { + name = profile.name, + tooltip = profile.name, + }, + volumeProfile = profile, + volumeComponent = overrideComponent, + volume = volume + }; + chain.Add(overrideVolume); + } } - // Default value profiles - var globalDefaultComponent = GetSelectedVolumeComponent(volumeManager.globalDefaultProfile); - var qualityDefaultComponent = GetSelectedVolumeComponent(volumeManager.qualityDefaultProfile); - List<(VolumeProfile, VolumeComponent)> customDefaultComponents = new(); + // Add custom default profiles if (volumeManager.customDefaultProfiles != null) { foreach (var customProfile in volumeManager.customDefaultProfiles) { - var customDefaultComponent = GetSelectedVolumeComponent(customProfile); - if (customDefaultComponent != null) - customDefaultComponents.Add((customProfile, customDefaultComponent)); + var customProfileComponent = GetSelectedVolumeComponent(customProfile, selectedType); + if (customProfileComponent != null) + { + var overrideVolume = new VolumeParameterChain() + { + nameAndTooltip = new DebugUI.Widget.NameAndTooltip() + { + name = customProfile.name, + tooltip = customProfile.name, + }, + volumeProfile = customProfile, + volumeComponent = customProfileComponent, + }; + chain.Add(overrideVolume); + } } } - foreach (var (customProfile, _) in customDefaultComponents) - { - row1.children.Add(new DebugUI.Value() { displayName = customProfile.name, getter = () => string.Empty }); - row2.children.Add(s_EmptyDebugUIValue); - row3.children.Add(new DebugUI.ObjectField() { displayName = string.Empty, getter = () => customProfile }); - row4.children.Add(s_EmptyDebugUIValue); - } - - row1.children.Add(new DebugUI.Value() { displayName = Strings.qualityLevelValue, tooltip = Strings.qualityLevelValueTooltip, getter = () => string.Empty }); - row2.children.Add(s_EmptyDebugUIValue); - row3.children.Add(new DebugUI.ObjectField() { displayName = string.Empty, getter = () => volumeManager.qualityDefaultProfile }); - row4.children.Add(s_EmptyDebugUIValue); - - row1.children.Add(new DebugUI.Value() { displayName = Strings.globalDefaultValue, tooltip = Strings.globalDefaultValueTooltip, getter = () => string.Empty }); - row2.children.Add(s_EmptyDebugUIValue); - row3.children.Add(new DebugUI.ObjectField() { displayName = string.Empty, getter = () => volumeManager.globalDefaultProfile }); - row4.children.Add(s_EmptyDebugUIValue); - - table.children.Add(row1); - table.children.Add(row2); - table.children.Add(row3); - table.children.Add(row4); - - VolumeComponent GetSelectedVolumeComponent(VolumeProfile profile) + // Add Quality Settings + if (volumeManager.globalDefaultProfile != null) { - if (profile != null) + var qualitySettingsComponent = GetSelectedVolumeComponent(volumeManager.qualityDefaultProfile, selectedType); + if (qualitySettingsComponent != null) { - foreach (var component in profile.components) - if (component.GetType() == selectedType) - return component; + var overrideVolume = new VolumeParameterChain() + { + nameAndTooltip = new DebugUI.Widget.NameAndTooltip() + { + name = Strings.qualityLevelValue, + tooltip = Strings.qualityLevelValueTooltip, + }, + volumeProfile = volumeManager.qualityDefaultProfile, + volumeComponent = qualitySettingsComponent, + }; + chain.Add(overrideVolume); } - return null; } - // Build rows - recursively handles nested parameters - var rows = new List(); - int AddParameterRows(Type type, string baseName = null, int skip = 0) + // Add Graphics Settings + if (volumeManager.globalDefaultProfile != null) { - void AddRow(FieldInfo f, string prefix, int skip) + var graphicsSettingsComponent = GetSelectedVolumeComponent(volumeManager.globalDefaultProfile, selectedType); + if (graphicsSettingsComponent != null) { - var fieldName = prefix + f.Name; - var attr = (DisplayInfoAttribute[])f.GetCustomAttributes(typeof(DisplayInfoAttribute), true); - if (attr.Length != 0) - fieldName = prefix + attr[0].name; -#if UNITY_EDITOR - // Would be nice to have the equivalent for the runtime debug. - else - fieldName = UnityEditor.ObjectNames.NicifyVariableName(fieldName); -#endif - - int currentParam = rows.Count + skip; - DebugUI.Table.Row row = new DebugUI.Table.Row() + var overrideVolume = new VolumeParameterChain() { - displayName = fieldName, - children = { CreateVolumeParameterWidget(Strings.resultValue, stackComponent.parameterList[currentParam]) }, + nameAndTooltip = new DebugUI.Widget.NameAndTooltip() + { + name = Strings.globalDefaultValue, + tooltip = Strings.globalDefaultValueTooltip, + }, + volumeProfile = volumeManager.globalDefaultProfile, + volumeComponent = graphicsSettingsComponent, }; - - foreach (var volume in volumes) - { - VolumeParameter param = null; - var profile = volume.HasInstantiatedProfile() ? volume.profile : volume.sharedProfile; - if (profile.TryGet(selectedType, out VolumeComponent component)) - param = component.parameterList[currentParam]; - row.children.Add(CreateVolumeParameterWidget(volume.name + " (" + profile.name + ")", param, () => !component.parameterList[currentParam].overrideState)); - } - - foreach (var (customProfile, customComponent) in customDefaultComponents) - row.children.Add(CreateVolumeParameterWidget(customProfile.name, - customComponent != null ? customComponent.parameterList[currentParam] : null)); - - row.children.Add(CreateVolumeParameterWidget(Strings.qualityLevelValue, - qualityDefaultComponent != null ? qualityDefaultComponent.parameterList[currentParam] : null)); - - row.children.Add(CreateVolumeParameterWidget(Strings.globalDefaultValue, - globalDefaultComponent != null ? globalDefaultComponent.parameterList[currentParam] : null)); - - rows.Add(row); - } - - var fields = type - .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) - .OrderBy(t => t.MetadataToken); - foreach (var field in fields) - { - if (field.GetCustomAttributes(typeof(ObsoleteAttribute), false).Length != 0) - { - skip++; - continue; - } - var fieldType = field.FieldType; - if (fieldType.IsSubclassOf(typeof(VolumeParameter))) - AddRow(field, baseName ?? string.Empty, skip); - else if (!fieldType.IsArray && fieldType.IsClass) - skip += AddParameterRows(fieldType, baseName ?? (field.Name + " "), skip); + chain.Add(overrideVolume); } - return skip; } - AddParameterRows(selectedType); - foreach (var r in rows.OrderBy(t => t.displayName)) - table.children.Add(r); + return chain; + } + + public static DebugUI.Table CreateVolumeTable(DebugDisplaySettingsVolume data) + { + var table = new DebugUI.Table() + { + displayName = Strings.parameter, + isReadOnly = true, + isHiddenCallback = () => data.volumeDebugSettings.selectedComponent == 0 + }; + + var resolutionChain = GetResolutionChain(data); + if (resolutionChain.Count == 0) + return table; - data.volumeDebugSettings.RefreshVolumes(volumes); - for (int i = 0; i < volumes.Length; i++) - table.SetColumnVisibility(i + 1, data.volumeDebugSettings.VolumeHasInfluence(volumes[i])); + GenerateTableRows(table, resolutionChain); + GenerateTableColumns(table, data, resolutionChain); float timer = 0.0f, refreshRate = 0.2f; + var volumes = data.volumeDebugSettings.GetVolumes(); table.isHiddenCallback = () => { timer += Time.deltaTime; @@ -400,16 +343,9 @@ void AddRow(FieldInfo f, string prefix, int skip) { if (data.volumeDebugSettings.selectedCamera != null) { - var newVolumes = data.volumeDebugSettings.GetVolumes(); - if (!data.volumeDebugSettings.RefreshVolumes(newVolumes)) - { - for (int i = 0; i < newVolumes.Length; i++) - { - var visible = data.volumeDebugSettings.VolumeHasInfluence(newVolumes[i]); - table.SetColumnVisibility(i + 1, visible); - } - } + SetTableColumnVisibility(data, table); + var newVolumes = data.volumeDebugSettings.GetVolumes(); if (!volumes.SequenceEqual(newVolumes)) { volumes = newVolumes; @@ -424,6 +360,139 @@ void AddRow(FieldInfo f, string prefix, int skip) return table; } + + private static void SetTableColumnVisibility(DebugDisplaySettingsVolume data, DebugUI.Table table) + { + var newResolutionChain = GetResolutionChain(data); + for (int i = 1; i < newResolutionChain.Count; i++) // We always skip the interpolated stack that is in index 0 + { + bool visible = true; + if (newResolutionChain[i].volume != null) + { + visible = data.volumeDebugSettings.VolumeHasInfluence(newResolutionChain[i].volume); + } + else + { + visible = newResolutionChain[i].volumeComponent.active; + + if (visible) + { + bool atLeastOneParameterIsOverriden = false; + foreach (var parameter in newResolutionChain[i].volumeComponent.parameterList) + { + if (parameter.overrideState == true) + { + atLeastOneParameterIsOverriden = true; + break; + } + } + + visible &= atLeastOneParameterIsOverriden; + } + } + + table.SetColumnVisibility(i, visible); + } + } + + private static void GenerateTableColumns(DebugUI.Table table, DebugDisplaySettingsVolume data, List resolutionChain) + { + for (int i = 0; i < resolutionChain.Count; ++i) + { + var chain = resolutionChain[i]; + int iRowIndex = -1; + + if (chain.volume != null) + { + ((DebugUI.Table.Row)table.children[++iRowIndex]).children.Add(new DebugUI.Value() + { + nameAndTooltip = chain.nameAndTooltip, + getter = () => + { + var scope = chain.volume.isGlobal ? Strings.global : Strings.local; + var weight = data.volumeDebugSettings.GetVolumeWeight(chain.volume); + return scope + " (" + (weight * 100f) + "%)"; + }, + refreshRate = 0.2f + }); + ((DebugUI.Table.Row)table.children[++iRowIndex]).children.Add(new DebugUI.ObjectField() { displayName = string.Empty, getter = () => chain.volume }); + } + else + { + ((DebugUI.Table.Row)table.children[++iRowIndex]).children.Add(new DebugUI.Value() + { + nameAndTooltip = chain.nameAndTooltip, + getter = () => string.Empty + }); + ((DebugUI.Table.Row)table.children[++iRowIndex]).children.Add(s_EmptyDebugUIValue); + } + + ((DebugUI.Table.Row)table.children[++iRowIndex]).children.Add(chain.volumeProfile != null ? new DebugUI.ObjectField() { displayName = string.Empty, getter = () => chain.volumeProfile } : + s_EmptyDebugUIValue); + + ((DebugUI.Table.Row)table.children[++iRowIndex]).children.Add(s_EmptyDebugUIValue); + + bool isResultParameter = i == 0; + for (int j = 0; j < chain.volumeComponent.parameterList.Count; ++j) + { + var parameter = chain.volumeComponent.parameterList[j]; + ((DebugUI.Table.Row)table.children[++iRowIndex]).children.Add(CreateVolumeParameterWidget(chain.nameAndTooltip.name, isResultParameter, parameter)); + } + } + } + + private static void GenerateTableRows(DebugUI.Table table, List resolutionChain) + { + // First row for volume info + var volumeInfoRow = new DebugUI.Table.Row() + { + displayName = Strings.volumeInfo, + opened = true, // Open by default for the in-game view + }; + + table.children.Add(volumeInfoRow); + + // Second row, links to volume gameobjects + var gameObjectRow = new DebugUI.Table.Row() + { + displayName = Strings.gameObject, + }; + + table.children.Add(gameObjectRow); + + // Third row, links to volume profile assets + var volumeProfileRow = new DebugUI.Table.Row() + { + displayName = Strings.volumeProfile, + }; + table.children.Add(volumeProfileRow); + + var separatorRow = new DebugUI.Table.Row() + { + displayName = string.Empty , + }; + + table.children.Add(separatorRow); + + var results = resolutionChain[0].volumeComponent; + for (int i = 0; i < results.parameterList.Count; ++i) + { + var parameter = results.parameterList[i]; + +#if UNITY_EDITOR + string displayName = UnityEditor.ObjectNames.NicifyVariableName(parameter.debugId); // In the editor, make the name more readable +#elif DEVELOPMENT_BUILD + string displayName = parameter.debugId; // In the development player, just the debug id +#else + string displayName = i.ToString(); // Everywhere else, just a dummy id ( TODO: The Volume panel code should be stripped completely in nom-development builds ) +#endif + + table.children.Add(new DebugUI.Table.Row() + { + displayName = displayName + }); + } + } } [DisplayInfo(name = k_PanelTitle, order = int.MaxValue)] diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.UIState.cs b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.UIState.cs index f80b0058759..857292f35ba 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.UIState.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.UIState.cs @@ -99,17 +99,22 @@ public bool displayRuntimeUI { if (value) { - m_Root = UnityObject.Instantiate(Resources.Load("DebugUICanvas")).gameObject; - m_Root.name = "[Debug Canvas]"; - m_Root.transform.localPosition = Vector3.zero; - m_RootUICanvas = m_Root.GetComponent(); + if (GraphicsSettings.TryGetRenderPipelineSettings( + out var runtimeUIResources)) + { + m_Root = UnityObject.Instantiate(runtimeUIResources.debugUIHandlerCanvasPrefab).gameObject; + m_Root.name = "[Debug Canvas]"; + m_Root.transform.localPosition = Vector3.zero; + m_RootUICanvas = m_Root.GetComponent(); #if UNITY_ANDROID || UNITY_IPHONE || UNITY_TVOS || UNITY_SWITCH var canvasScaler = m_Root.GetComponent(); canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; #endif - m_Root.SetActive(true); + m_Root.SetActive(true); + } + } else { diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.cs b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.cs index b90eed0d6da..57e571cf871 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.cs @@ -16,7 +16,7 @@ namespace UnityEngine.Rendering /// /// /// Use the `IDebugData` interface to register custom debug data. You can reset the data when necessary, which makes it suitable for debugging scenarios - /// where you need to clear or reset specific data. For example, when the application state changes or during gameplay session resets, + /// where you need to clear or reset specific data. For example, when the application state changes or during gameplay session resets, /// or when the **Reset** button is selected in the **Rendering Debugger** window in the Editor or at runtime. /// /// @@ -68,7 +68,7 @@ public interface IDebugData /// new DebugUI.Value { displayName = "Light Color", getter = () => Color.white, setter = value => Debug.Log($"Light Color set to {value}") } /// }; /// var items = list.ToArray(); - /// + /// /// /// Obtain the panel from the DebugManager instance, and add the Widgets that we want to display there. /// var panel = DebugManager.instance.GetPanel("Lighting", true); /// panel.children.AddRange(items); @@ -231,9 +231,13 @@ void EnsurePersistentCanvas() if (uiManager == null) { - m_PersistentRoot = UnityObject.Instantiate(Resources.Load("DebugUIPersistentCanvas")).gameObject; - m_PersistentRoot.name = "[Debug Canvas - Persistent]"; - m_PersistentRoot.transform.localPosition = Vector3.zero; + if (GraphicsSettings.TryGetRenderPipelineSettings( + out var runtimeUIResources)) + { + m_PersistentRoot = UnityObject.Instantiate(runtimeUIResources.debugUIPersistentCanvasPrefab).gameObject; + m_PersistentRoot.name = "[Debug Canvas - Persistent]"; + m_PersistentRoot.transform.localPosition = Vector3.zero; + } } else { diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Scripts/DebugUIHandlerCanvas.cs b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Scripts/DebugUIHandlerCanvas.cs index 155eb18319d..a9cd19bca5f 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Scripts/DebugUIHandlerCanvas.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Scripts/DebugUIHandlerCanvas.cs @@ -91,9 +91,7 @@ void Rebuild() } m_UIPanels.Clear(); - m_DebugTreeState = DebugManager.instance.GetState(); - var panels = DebugManager.instance.panels; #if UNITY_ANDROID || UNITY_IPHONE // Mobile device safe area @@ -107,15 +105,20 @@ void Rebuild() var safeAreaOffsetTop = -safeAreaRect.yMin * scaleRatio; Vector2 safeAreaOffset = new Vector2(safeAreaOffsetLeft, safeAreaOffsetTop) + margin; #endif + var panels = DebugManager.instance.panels; + var panelsCount = panels.Count; - DebugUIHandlerWidget selectedWidget = null; - foreach (var panel in panels) + if (panelsCount > 0) { - if (panel.isEditorOnly || panel.children.Count(x => !x.isEditorOnly && !x.isHidden) == 0) - continue; + DebugUIHandlerWidget selectedWidget = null; + for (int i = 0; i < panelsCount; i++) + { + var panel = panels[i]; + if (panel.isEditorOnly || panel.children.Count(x => !x.isEditorOnly && !x.isHidden) == 0) + continue; - var go = Instantiate(panelPrefab, transform, false).gameObject; - go.name = panel.displayName; + var go = Instantiate(panelPrefab, transform, false).gameObject; + go.name = panel.displayName; #if UNITY_ANDROID || UNITY_IPHONE RectTransform rectTransform = go.GetComponent(); @@ -123,21 +126,22 @@ void Rebuild() rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, safeAreaRect.height * scaleRatio + 2 * safeAreaOffsetTop); #endif - var uiPanel = go.GetComponent(); - uiPanel.SetPanel(panel); - uiPanel.Canvas = this; - m_UIPanels.Add(uiPanel); - var container = go.GetComponent(); - DebugUIHandlerWidget selected = null; - Traverse(panel, container.contentHolder, null, ref selected); - - if (selected != null && selected.GetWidget().queryPath.Contains(panel.queryPath)) - { - selectedWidget = selected; + var uiPanel = go.GetComponent(); + uiPanel.SetPanel(panel); + uiPanel.Canvas = this; + m_UIPanels.Add(uiPanel); + var container = go.GetComponent(); + DebugUIHandlerWidget selected = null; + Traverse(panel, container.contentHolder, null, ref selected); + + if (selected != null && selected.GetWidget().queryPath.Contains(panel.queryPath)) + { + selectedWidget = selected; + } } - } - ActivatePanel(m_SelectedPanel, selectedWidget); + ActivatePanel(m_SelectedPanel, selectedWidget); + } } void Traverse(DebugUI.IContainer container, Transform parentTransform, DebugUIHandlerWidget parentUIHandler, ref DebugUIHandlerWidget selectedHandler) diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources.meta b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources.meta similarity index 77% rename from Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources.meta rename to Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources.meta index a06e81047c3..448d0f9172c 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources.meta +++ b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 3774a3e29f7c59445ba79c15769126fd +guid: 773aa3153bd13404186ca11c4d564ee4 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources/DebugUICanvas.prefab b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources/DebugUICanvas.prefab similarity index 100% rename from Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources/DebugUICanvas.prefab rename to Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources/DebugUICanvas.prefab diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources/DebugUICanvas.prefab.meta b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources/DebugUICanvas.prefab.meta similarity index 100% rename from Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources/DebugUICanvas.prefab.meta rename to Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources/DebugUICanvas.prefab.meta diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources/DebugUIPersistentCanvas.prefab b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources/DebugUIPersistentCanvas.prefab similarity index 100% rename from Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources/DebugUIPersistentCanvas.prefab rename to Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources/DebugUIPersistentCanvas.prefab diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources/DebugUIPersistentCanvas.prefab.meta b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources/DebugUIPersistentCanvas.prefab.meta similarity index 100% rename from Packages/com.unity.render-pipelines.core/Runtime/Debugging/Prefabs/Resources/DebugUIPersistentCanvas.prefab.meta rename to Packages/com.unity.render-pipelines.core/Runtime/Debugging/Runtime UI Resources/DebugUIPersistentCanvas.prefab.meta diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/VolumeDebugSettings.cs b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/VolumeDebugSettings.cs index ca423bffbed..d2310ebd81b 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Debugging/VolumeDebugSettings.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Debugging/VolumeDebugSettings.cs @@ -73,7 +73,10 @@ public IEnumerable cameras if (camera.cameraType != CameraType.Preview && camera.cameraType != CameraType.Reflection) { - if (camera.TryGetComponent(out T additionalData)) + if (!camera.TryGetComponent(out T additionalData)) + additionalData = camera.gameObject.AddComponent(); + + if (additionalData != null) m_Cameras.Add(camera); } } @@ -262,21 +265,9 @@ public bool RefreshVolumes(Volume[] newVolumes) /// The weight of the volume public float GetVolumeWeight(Volume volume) { - if (weights == null) - return 0; - - float total = 0f, weight = 0f; - for (int i = 0; i < volumes.Length; i++) - { - weight = weights[i]; - weight *= 1f - total; - total += weight; - - if (volumes[i] == volume) - return weight; - } - - return 0f; + // TODO: Store the calculated weight in the stack for the volumes that have influence and return it here + var triggerPos = selectedCameraPosition; + return ComputeWeight(volume, triggerPos); } /// @@ -286,14 +277,9 @@ public float GetVolumeWeight(Volume volume) /// If the volume has influence public bool VolumeHasInfluence(Volume volume) { - if (weights == null) - return false; - - int index = Array.IndexOf(volumes, volume); - if (index == -1) - return false; - - return weights[index] != 0f; + // TODO: Store the calculated weight in the stack for the volumes that have influence and return it here + var triggerPos = selectedCameraPosition; + return ComputeWeight(volume, triggerPos) > 0.0f; } } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawer.Validator.cs b/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawer.Validator.cs index 91a5c2cfba0..f76c930b549 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawer.Validator.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawer.Validator.cs @@ -81,6 +81,11 @@ internal static bool IsGPUResidentDrawerSupportedBySRP(GPUResidentDrawerSettings message = Strings.allowInEditModeDisabled; return false; } + + // Disable GRD in any external AssetImporter child process. GRD isn't made for AssetImporter workflow/lifetime + // Avoid memory leak warning messages and also some future issues (UUM-90039) + if (AssetDatabase.IsAssetImportWorkerProcess()) + return false; #endif // If we are forcing the system, no need to perform further checks if (IsForcedOnViaCommandLine()) diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Streaming.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Streaming.cs index 37613e48df2..c956c8e9057 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Streaming.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Streaming.cs @@ -114,6 +114,7 @@ internal class CellStreamingScratchBuffer public CellStreamingScratchBuffer(int chunkCount, int chunkSize, bool allocateGraphicsBuffers) { this.chunkCount = chunkCount; + this.chunkSize = chunkSize; // With a stride of 4 (one uint) // Number of elements for chunk data: chunkCount * chunkSize / 4 @@ -152,6 +153,7 @@ public void Dispose() public GraphicsBuffer buffer => m_GraphicsBuffers[m_CurrentBuffer]; public NativeArray stagingBuffer; // Contains data streamed from disk. To be copied into the graphics buffer. public int chunkCount { get; } + public int chunkSize { get; } int m_CurrentBuffer; GraphicsBuffer[] m_GraphicsBuffers = new GraphicsBuffer[2]; diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeScratchBufferPool.cs b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeScratchBufferPool.cs index bdee7c19097..f5404a10aec 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeScratchBufferPool.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumeScratchBufferPool.cs @@ -232,6 +232,12 @@ public bool AllocateScratchBuffer(int chunkCount, out CellStreamingScratchBuffer public void ReleaseScratchBuffer(CellStreamingScratchBuffer scratchBuffer) { + if (scratchBuffer.chunkSize != chunkSize) + { + scratchBuffer.Dispose(); + return; + } + s_ChunkCount = scratchBuffer.chunkCount; var pool = m_Pools.Find((o) => o.chunkCount == s_ChunkCount); Debug.Assert(pool != null); diff --git a/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareCommonSRP.cs b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareCommonSRP.cs index 49c57b5e4a6..8d8b04591af 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareCommonSRP.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareCommonSRP.cs @@ -6,8 +6,17 @@ namespace UnityEngine.Rendering { /// - /// Common code for all Data-Driven Lens Flare used + /// Provides methods for implementing lens flares in a render pipeline. /// + /// + /// The High Definition Render Pipeline (HDRP) and Universal Render Pipeline (URP) use this class for their lens flare implementation. The class supports both screen space lens flares and quad-based lens flares. + /// You must call the methods of `LensFlareCommonSRP` at several places inside the Scriptable Render Pipeline (SRP). At minimum, you must call the method. + /// You can use any of these methods in a `Monobehaviour` script. + /// + /// . + /// + /// Note that only one `LensFlareCommonSRP` can be alive at any point. To call members of this class, use the property. + /// public sealed class LensFlareCommonSRP { private static LensFlareCommonSRP m_Instance = null; @@ -38,7 +47,7 @@ internal LensFlareCompInfo(int idx, LensFlareComponentSRP cmp) private static List m_AvailableIndicies = new List(); /// - /// Max lens-flares-with-occlusion supported + /// Defines how many lens flare with occlusion are supported in the view at any time. /// public static int maxLensFlareWithOcclusion = 128; @@ -134,8 +143,11 @@ static GraphicsFormat GetOcclusionRTFormat() } /// - /// Initialization function which must be called by the SRP. + /// Initializes the lens flares. You must call this method. /// + /// + /// You usually call `Initialize` in the constructor. + /// static public void Initialize() { frameIdx = 0; @@ -150,7 +162,7 @@ static public void Initialize() width: maxLensFlareWithOcclusion, height: Mathf.Max(mergeNeeded * (maxLensFlareWithOcclusionTemporalSample + 1), 1), format: GetOcclusionRTFormat(), - slices: TextureXR.slices, + slices: TextureXR.slices, enableRandomWrite: true, dimension: TextureDimension.Tex2DArray); } @@ -158,8 +170,11 @@ static public void Initialize() } /// - /// Disposal function, must be called by the SRP to release all internal textures. + /// Releases all internal textures. /// + /// + /// Usually, `Dispose` is called in the function. + /// static public void Dispose() { if (IsOcclusionRTCompatible()) @@ -173,8 +188,11 @@ static public void Dispose() } /// - /// Current unique instance + /// Current unique instance. /// + /// + /// Use this property to call other members of this class and make sure that only one lens flare system is running at any time. + /// public static LensFlareCommonSRP Instance { get @@ -196,9 +214,18 @@ public static LensFlareCommonSRP Instance private System.Collections.Generic.List Data { get { return LensFlareCommonSRP.m_Data; } } /// - /// Check if we have at least one Lens Flare added on the pool + /// Checks if at least one lens flare has been added to the pool. /// - /// true if no Lens Flare were added + /// + /// You can use this method to check if there are any lens flares to render before rendering the lens flares. + /// + /// + /// if (!LensFlareCommonSRP.Instance.IsEmpty()) + /// { + /// LensFlareCommonSRP.DoLensFlareDataDrivenCommon(...); + /// } + /// + /// `true` if no lens flare were added public bool IsEmpty() { return Data.Count == 0; @@ -217,8 +244,12 @@ int GetNextAvailableIndex() } /// - /// Add a new lens flare component on the pool. + /// Adds a new lens flare component for rendering. /// + /// + /// When is used, this method is called automatically when the lens flare is enabled. + /// You don't need to call this function unless you're manually removing lens flare data using . + /// /// The new data added public void AddData(LensFlareComponentSRP newData) { @@ -231,8 +262,11 @@ public void AddData(LensFlareComponentSRP newData) } /// - /// Remove a lens flare data which exist in the pool. + /// Removes a lens flare data from rendering. /// + /// + /// When is used, this method is called automatically when the lens flare is disabled. + /// /// The data which exist in the pool public void RemoveData(LensFlareComponentSRP data) { @@ -251,8 +285,44 @@ public void RemoveData(LensFlareComponentSRP data) /// - /// Attenuation by Light Shape for Point Light + /// Obtains the attenuation for a point light. /// + /// + /// This method can be used to help compute the light attenuation to pass to + /// + /// + /// + /// To handle more than one light type, write a dedicated function to compute the attenuation using these helpers + /// + /// + /// static float GetLensFlareLightAttenuation(Light light, Camera cam, Vector3 wo) + /// { + /// switch (light.type) + /// { + /// case LightType.Directional: + /// return LensFlareCommonSRP.ShapeAttenuationDirLight(light.transform.forward, cam.transform.forward); + /// case LightType.Point: + /// // Do nothing point are omnidirectional for the lens flare + /// return LensFlareCommonSRP.ShapeAttenuationPointLight(); + /// case LightType.Spot: + /// float innerSpotPercent01 = 1; + /// return LensFlareCommonSRP.ShapeAttenuationSpotConeLight(light.transform.forward, wo, light.spotAngle, light.innerSpotAngle / 180.0f); + /// case LightType.Pyramid: + /// return LensFlareCommonSRP.ShapeAttenuationSpotPyramidLight(light.transform.forward, wo); + /// case LightType.Box: + /// return LensFlareCommonSRP.ShapeAttenuationSpotBoxLight(light.transform.forward, wo); + /// case LightType.Rectangle: + /// return LensFlareCommonSRP.ShapeAttenuationAreaRectangleLight(light.transform.forward, wo); + /// case LightType.Tube: + /// float shapeWidth = 1; // Get this data from an external source if our render pipeline supports tube lights. + /// return LensFlareCommonSRP.ShapeAttenuationAreaTubeLight(light.transform.position, light.transform.right, shapeWidth, cam); + /// case LightType.Disc: + /// return LensFlareCommonSRP.ShapeAttenuationAreaDiscLight(light.transform.forward, wo); + /// default: throw new Exception($"GetLensFlareLightAttenuation HDLightType Unknown {typeof(LightType)}: {light.type}"); + /// } + /// } + /// + /// /// Attenuation Factor static public float ShapeAttenuationPointLight() { @@ -260,24 +330,96 @@ static public float ShapeAttenuationPointLight() } /// - /// Attenuation by Light Shape for Directional Light + /// Obtains the attenuation for a directional light. /// /// Forward Vector of Directional Light /// Vector pointing to the eye /// Attenuation Factor + /// + /// This method can be used to help compute the light attenuation to pass to + /// + /// + /// + /// To handle more than one light type, write a dedicated function to compute the attenuation using these helpers + /// + /// + /// static float GetLensFlareLightAttenuation(Light light, Camera cam, Vector3 wo) + /// { + /// switch (light.type) + /// { + /// case LightType.Directional: + /// return LensFlareCommonSRP.ShapeAttenuationDirLight(light.transform.forward, cam.transform.forward); + /// case LightType.Point: + /// // Do nothing point are omnidirectional for the lens flare + /// return LensFlareCommonSRP.ShapeAttenuationPointLight(); + /// case LightType.Spot: + /// float innerSpotPercent01 = 1; + /// return LensFlareCommonSRP.ShapeAttenuationSpotConeLight(light.transform.forward, wo, light.spotAngle, light.innerSpotAngle / 180.0f); + /// case LightType.Pyramid: + /// return LensFlareCommonSRP.ShapeAttenuationSpotPyramidLight(light.transform.forward, wo); + /// case LightType.Box: + /// return LensFlareCommonSRP.ShapeAttenuationSpotBoxLight(light.transform.forward, wo); + /// case LightType.Rectangle: + /// return LensFlareCommonSRP.ShapeAttenuationAreaRectangleLight(light.transform.forward, wo); + /// case LightType.Tube: + /// float shapeWidth = 1; // Get this data from an external source if our render pipeline supports tube lights. + /// return LensFlareCommonSRP.ShapeAttenuationAreaTubeLight(light.transform.position, light.transform.right, shapeWidth, cam); + /// case LightType.Disc: + /// return LensFlareCommonSRP.ShapeAttenuationAreaDiscLight(light.transform.forward, wo); + /// default: throw new Exception($"GetLensFlareLightAttenuation HDLightType Unknown {typeof(LightType)}: {light.type}"); + /// } + /// } + /// + /// static public float ShapeAttenuationDirLight(Vector3 forward, Vector3 wo) { return Mathf.Max(Vector3.Dot(-forward, wo), 0.0f); } /// - /// Attenuation by Light Shape for Spot Light with Cone Shape + /// Obtains the attenuation for a cone spot light. /// /// Forward Vector of Directional Light /// Vector pointing to the eye /// The angle of the light's spotlight cone in degrees. /// Get the inner spot radius between 0 and 1. /// Attenuation Factor + /// + /// This method can be used to help compute the light attenuation to pass to + /// + /// + /// + /// To handle more than one light type, write a dedicated function to compute the attenuation using these helpers + /// + /// + /// static float GetLensFlareLightAttenuation(Light light, Camera cam, Vector3 wo) + /// { + /// switch (light.type) + /// { + /// case LightType.Directional: + /// return LensFlareCommonSRP.ShapeAttenuationDirLight(light.transform.forward, cam.transform.forward); + /// case LightType.Point: + /// // Do nothing point are omnidirectional for the lens flare + /// return LensFlareCommonSRP.ShapeAttenuationPointLight(); + /// case LightType.Spot: + /// float innerSpotPercent01 = 1; + /// return LensFlareCommonSRP.ShapeAttenuationSpotConeLight(light.transform.forward, wo, light.spotAngle, light.innerSpotAngle / 180.0f); + /// case LightType.Pyramid: + /// return LensFlareCommonSRP.ShapeAttenuationSpotPyramidLight(light.transform.forward, wo); + /// case LightType.Box: + /// return LensFlareCommonSRP.ShapeAttenuationSpotBoxLight(light.transform.forward, wo); + /// case LightType.Rectangle: + /// return LensFlareCommonSRP.ShapeAttenuationAreaRectangleLight(light.transform.forward, wo); + /// case LightType.Tube: + /// float shapeWidth = 1; // Get this data from an external source if our render pipeline supports tube lights. + /// return LensFlareCommonSRP.ShapeAttenuationAreaTubeLight(light.transform.position, light.transform.right, shapeWidth, cam); + /// case LightType.Disc: + /// return LensFlareCommonSRP.ShapeAttenuationAreaDiscLight(light.transform.forward, wo); + /// default: throw new Exception($"GetLensFlareLightAttenuation HDLightType Unknown {typeof(LightType)}: {light.type}"); + /// } + /// } + /// + /// static public float ShapeAttenuationSpotConeLight(Vector3 forward, Vector3 wo, float spotAngle, float innerSpotPercent01) { float outerDot = Mathf.Max(Mathf.Cos(0.5f * spotAngle * Mathf.Deg2Rad), 0.0f); @@ -287,35 +429,143 @@ static public float ShapeAttenuationSpotConeLight(Vector3 forward, Vector3 wo, f } /// - /// Attenuation by Light Shape for Spot Light with Box Shape + /// Obtains the attenuation for a box spot light. /// /// Forward Vector of Directional Light /// Vector pointing to the eye /// Attenuation Factor + /// + /// This method can be used to help compute the light attenuation to pass to + /// + /// + /// + /// To handle more than one light type, write a dedicated function to compute the attenuation using these helpers + /// + /// + /// static float GetLensFlareLightAttenuation(Light light, Camera cam, Vector3 wo) + /// { + /// switch (light.type) + /// { + /// case LightType.Directional: + /// return LensFlareCommonSRP.ShapeAttenuationDirLight(light.transform.forward, cam.transform.forward); + /// case LightType.Point: + /// // Do nothing point are omnidirectional for the lens flare + /// return LensFlareCommonSRP.ShapeAttenuationPointLight(); + /// case LightType.Spot: + /// float innerSpotPercent01 = 1; + /// return LensFlareCommonSRP.ShapeAttenuationSpotConeLight(light.transform.forward, wo, light.spotAngle, light.innerSpotAngle / 180.0f); + /// case LightType.Pyramid: + /// return LensFlareCommonSRP.ShapeAttenuationSpotPyramidLight(light.transform.forward, wo); + /// case LightType.Box: + /// return LensFlareCommonSRP.ShapeAttenuationSpotBoxLight(light.transform.forward, wo); + /// case LightType.Rectangle: + /// return LensFlareCommonSRP.ShapeAttenuationAreaRectangleLight(light.transform.forward, wo); + /// case LightType.Tube: + /// float shapeWidth = 1; // Get this data from an external source if our render pipeline supports tube lights. + /// return LensFlareCommonSRP.ShapeAttenuationAreaTubeLight(light.transform.position, light.transform.right, shapeWidth, cam); + /// case LightType.Disc: + /// return LensFlareCommonSRP.ShapeAttenuationAreaDiscLight(light.transform.forward, wo); + /// default: throw new Exception($"GetLensFlareLightAttenuation HDLightType Unknown {typeof(LightType)}: {light.type}"); + /// } + /// } + /// + /// static public float ShapeAttenuationSpotBoxLight(Vector3 forward, Vector3 wo) { return Mathf.Max(Mathf.Sign(Vector3.Dot(forward, wo)), 0.0f); } /// - /// Attenuation by Light Shape for Spot Light with Pyramid Shape + /// Obtains the attenuation for a pyramid spot light. /// /// Forward Vector of Directional Light /// Vector pointing to the eye /// Attenuation Factor + /// + /// This method can be used to help compute the light attenuation to pass to + /// + /// + /// + /// To handle more than one light type, write a dedicated function to compute the attenuation using these helpers + /// + /// + /// static float GetLensFlareLightAttenuation(Light light, Camera cam, Vector3 wo) + /// { + /// switch (light.type) + /// { + /// case LightType.Directional: + /// return LensFlareCommonSRP.ShapeAttenuationDirLight(light.transform.forward, cam.transform.forward); + /// case LightType.Point: + /// // Do nothing point are omnidirectional for the lens flare + /// return LensFlareCommonSRP.ShapeAttenuationPointLight(); + /// case LightType.Spot: + /// float innerSpotPercent01 = 1; + /// return LensFlareCommonSRP.ShapeAttenuationSpotConeLight(light.transform.forward, wo, light.spotAngle, light.innerSpotAngle / 180.0f); + /// case LightType.Pyramid: + /// return LensFlareCommonSRP.ShapeAttenuationSpotPyramidLight(light.transform.forward, wo); + /// case LightType.Box: + /// return LensFlareCommonSRP.ShapeAttenuationSpotBoxLight(light.transform.forward, wo); + /// case LightType.Rectangle: + /// return LensFlareCommonSRP.ShapeAttenuationAreaRectangleLight(light.transform.forward, wo); + /// case LightType.Tube: + /// float shapeWidth = 1; // Get this data from an external source if our render pipeline supports tube lights. + /// return LensFlareCommonSRP.ShapeAttenuationAreaTubeLight(light.transform.position, light.transform.right, shapeWidth, cam); + /// case LightType.Disc: + /// return LensFlareCommonSRP.ShapeAttenuationAreaDiscLight(light.transform.forward, wo); + /// default: throw new Exception($"GetLensFlareLightAttenuation HDLightType Unknown {typeof(LightType)}: {light.type}"); + /// } + /// } + /// + /// static public float ShapeAttenuationSpotPyramidLight(Vector3 forward, Vector3 wo) { return ShapeAttenuationSpotBoxLight(forward, wo); } /// - /// Attenuation by Light Shape for Area Light with Tube Shape + /// Obtains the attenuation for a tube light. /// /// World Space position of the Light /// Vector pointing to the side (right or left) or the light /// Width (half extent) of the tube light /// Camera rendering the Tube Light /// Attenuation Factor + /// + /// This method can be used to help compute the light attenuation to pass to + /// + /// + /// + /// To handle more than one light type, write a dedicated function to compute the attenuation using these helpers + /// + /// + /// static float GetLensFlareLightAttenuation(Light light, Camera cam, Vector3 wo) + /// { + /// switch (light.type) + /// { + /// case LightType.Directional: + /// return LensFlareCommonSRP.ShapeAttenuationDirLight(light.transform.forward, cam.transform.forward); + /// case LightType.Point: + /// // Do nothing point are omnidirectional for the lens flare + /// return LensFlareCommonSRP.ShapeAttenuationPointLight(); + /// case LightType.Spot: + /// float innerSpotPercent01 = 1; + /// return LensFlareCommonSRP.ShapeAttenuationSpotConeLight(light.transform.forward, wo, light.spotAngle, light.innerSpotAngle / 180.0f); + /// case LightType.Pyramid: + /// return LensFlareCommonSRP.ShapeAttenuationSpotPyramidLight(light.transform.forward, wo); + /// case LightType.Box: + /// return LensFlareCommonSRP.ShapeAttenuationSpotBoxLight(light.transform.forward, wo); + /// case LightType.Rectangle: + /// return LensFlareCommonSRP.ShapeAttenuationAreaRectangleLight(light.transform.forward, wo); + /// case LightType.Tube: + /// float shapeWidth = 1; // Get this data from an external source if our render pipeline supports tube lights. + /// return LensFlareCommonSRP.ShapeAttenuationAreaTubeLight(light.transform.position, light.transform.right, shapeWidth, cam); + /// case LightType.Disc: + /// return LensFlareCommonSRP.ShapeAttenuationAreaDiscLight(light.transform.forward, wo); + /// default: throw new Exception($"GetLensFlareLightAttenuation HDLightType Unknown {typeof(LightType)}: {light.type}"); + /// } + /// } + /// + /// static public float ShapeAttenuationAreaTubeLight(Vector3 lightPositionWS, Vector3 lightSide, float lightWidth, Camera cam) { // Ref: https://hal.archives-ouvertes.fr/hal-02155101/document @@ -383,22 +633,94 @@ static float ShapeAttenuateForwardLight(Vector3 forward, Vector3 wo) } /// - /// Attenuation by Light Shape for Area Light with Rectangular Shape + /// Obtains the attenuation for a rectangle light. /// /// Forward Vector of Directional Light /// Vector pointing to the eye /// Attenuation Factor + /// + /// This method can be used to help compute the light attenuation to pass to + /// + /// + /// + /// To handle more than one light type, write a dedicated function to compute the attenuation using these helpers + /// + /// + /// static float GetLensFlareLightAttenuation(Light light, Camera cam, Vector3 wo) + /// { + /// switch (light.type) + /// { + /// case LightType.Directional: + /// return LensFlareCommonSRP.ShapeAttenuationDirLight(light.transform.forward, cam.transform.forward); + /// case LightType.Point: + /// // Do nothing point are omnidirectional for the lens flare + /// return LensFlareCommonSRP.ShapeAttenuationPointLight(); + /// case LightType.Spot: + /// float innerSpotPercent01 = 1; + /// return LensFlareCommonSRP.ShapeAttenuationSpotConeLight(light.transform.forward, wo, light.spotAngle, light.innerSpotAngle / 180.0f); + /// case LightType.Pyramid: + /// return LensFlareCommonSRP.ShapeAttenuationSpotPyramidLight(light.transform.forward, wo); + /// case LightType.Box: + /// return LensFlareCommonSRP.ShapeAttenuationSpotBoxLight(light.transform.forward, wo); + /// case LightType.Rectangle: + /// return LensFlareCommonSRP.ShapeAttenuationAreaRectangleLight(light.transform.forward, wo); + /// case LightType.Tube: + /// float shapeWidth = 1; // Get this data from an external source if our render pipeline supports tube lights. + /// return LensFlareCommonSRP.ShapeAttenuationAreaTubeLight(light.transform.position, light.transform.right, shapeWidth, cam); + /// case LightType.Disc: + /// return LensFlareCommonSRP.ShapeAttenuationAreaDiscLight(light.transform.forward, wo); + /// default: throw new Exception($"GetLensFlareLightAttenuation HDLightType Unknown {typeof(LightType)}: {light.type}"); + /// } + /// } + /// + /// static public float ShapeAttenuationAreaRectangleLight(Vector3 forward, Vector3 wo) { return ShapeAttenuateForwardLight(forward, wo); } /// - /// Attenuation by Light Shape for Area Light with Disc Shape + /// Obtains the attenuation for a disc light. /// /// Forward Vector of Directional Light /// Vector pointing to the eye /// Attenuation Factor + /// + /// This method can be used to help compute the light attenuation to pass to + /// + /// + /// + /// To handle more than one light type, write a dedicated function to compute the attenuation using these helpers + /// + /// + /// static float GetLensFlareLightAttenuation(Light light, Camera cam, Vector3 wo) + /// { + /// switch (light.type) + /// { + /// case LightType.Directional: + /// return LensFlareCommonSRP.ShapeAttenuationDirLight(light.transform.forward, cam.transform.forward); + /// case LightType.Point: + /// // Do nothing point are omnidirectional for the lens flare + /// return LensFlareCommonSRP.ShapeAttenuationPointLight(); + /// case LightType.Spot: + /// float innerSpotPercent01 = 1; + /// return LensFlareCommonSRP.ShapeAttenuationSpotConeLight(light.transform.forward, wo, light.spotAngle, light.innerSpotAngle / 180.0f); + /// case LightType.Pyramid: + /// return LensFlareCommonSRP.ShapeAttenuationSpotPyramidLight(light.transform.forward, wo); + /// case LightType.Box: + /// return LensFlareCommonSRP.ShapeAttenuationSpotBoxLight(light.transform.forward, wo); + /// case LightType.Rectangle: + /// return LensFlareCommonSRP.ShapeAttenuationAreaRectangleLight(light.transform.forward, wo); + /// case LightType.Tube: + /// float shapeWidth = 1; // Get this data from an external source if our render pipeline supports tube lights. + /// return LensFlareCommonSRP.ShapeAttenuationAreaTubeLight(light.transform.position, light.transform.right, shapeWidth, cam); + /// case LightType.Disc: + /// return LensFlareCommonSRP.ShapeAttenuationAreaDiscLight(light.transform.forward, wo); + /// default: throw new Exception($"GetLensFlareLightAttenuation HDLightType Unknown {typeof(LightType)}: {light.type}"); + /// } + /// } + /// + /// static public float ShapeAttenuationAreaDiscLight(Vector3 forward, Vector3 wo) { return ShapeAttenuateForwardLight(forward, wo); @@ -420,7 +742,7 @@ static bool IsLensFlareSRPHidden(Camera cam, LensFlareComponentSRP comp, LensFla } /// - /// Compute internal parameters needed to render single flare + /// Computes the internal parameters needed to render a single flare. /// /// The screen position of the flare. /// The scale of translation applied to the flare. @@ -512,8 +834,11 @@ static Vector3 WorldToViewportDistance(Camera cam, Vector3 positionWS) } /// - /// Check if at least one LensFlareComponentSRP request occlusion from background clouds + /// Checks if at least one `LensFlareComponentSRP` requests occlusion from environment effects. /// + /// + /// Environment occlusion can be enabled by setting to true. + /// /// Camera /// true if cloud occlusion is requested static public bool IsCloudLayerOpacityNeeded(Camera cam) @@ -594,9 +919,9 @@ static bool IsCurrentPrefabLensFlareComponent(GameObject go, LensFlareComponentS #endif /// - /// Effective Job of drawing the set of Lens Flare registered + /// Renders the set of lens flare registered. /// - /// Lens Flare material (HDRP or URP shader) + /// lens flare material (HDRP or URP shader) /// Camera /// XR Infos /// Index of the SinglePass XR @@ -646,9 +971,9 @@ static public void ComputeOcclusion(Material lensFlareShader, Camera cam, XRPass } /// - /// Effective Job of drawing the set of Lens Flare registered + /// Renders the set of lens flare registered. /// - /// Lens Flare material (HDRP or URP shader) + /// lens flare material (HDRP or URP shader) /// Camera /// XRPass data. /// XR multipass ID. @@ -684,9 +1009,9 @@ static public void ComputeOcclusion(Material lensFlareShader, Camera cam, XRPass } /// - /// Effective Job of drawing the set of Lens Flare registered + /// Renders the set of lens flare registered. /// - /// Lens Flare material (HDRP or URP shader) + /// lens flare material (HDRP or URP shader) /// Camera /// XRPass data. /// XR multipass ID. @@ -741,9 +1066,9 @@ static bool ForceSingleElement(LensFlareDataElementSRP element) } /// - /// Effective Job of drawing the set of Lens Flare registered + /// Computes the occlusion of lens flare using the depth buffer and additional occlusion textures if not null. /// - /// Lens Flare material (HDRP or URP shader) + /// Lens flare material (HDRP or URP shader) /// Camera /// XRPass data. /// XR multipass ID. @@ -977,8 +1302,11 @@ static public void ComputeOcclusion(Material lensFlareShader, Camera cam, XRPass } /// - /// Function that process a single element of a LensFlareDataSRP, this function is used on scene/game view and on the inspector for the thumbnail. + /// Renders a single element of a LensFlareDataSRP, this function is used on scene/game view and on the inspector for the thumbnail. /// + /// + /// Can be used to draw aa single lens flare for editor or preview purpose. + /// /// Single LensFlare asset we need to process. /// Command Buffer. /// Color Modulation from Component? @@ -987,7 +1315,7 @@ static public void ComputeOcclusion(Material lensFlareShader, Camera cam, XRPass /// Scale from component /// Shader used on URP or HDRP. /// Screen Position - /// Allow Lens Flare offscreen + /// Allow lens flare offscreen /// Screen Ratio /// _FlareData1 used internally by the shader. /// true if we are on preview on the inspector @@ -1322,9 +1650,9 @@ static void ProcessLensFlareSRPElements(ref LensFlareDataElementSRP[] elements, } /// - /// Effective Job of drawing the set of Lens Flare registered + /// Renders the set of lens flare registered. /// - /// Lens Flare material (HDRP or URP shader) + /// Lens flare material (HDRP or URP shader) /// Camera /// Viewport used for rendering and XR applied. /// XRPass data. @@ -1356,7 +1684,7 @@ static void ProcessLensFlareSRPElements(ref LensFlareDataElementSRP[] elements, /// ShaderID for the FlareData2 /// ShaderID for the FlareData3 /// ShaderID for the FlareData4 - /// Debug View which setup black background to see only Lens Flare + /// Debug View which setup black background to see only lens flare [Obsolete("Use DoLensFlareDataDrivenCommon without _FlareOcclusionRemapTex.._FlareData4 parameters.")] static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera cam, Rect viewport, XRPass xr, int xrIndex, float actualWidth, float actualHeight, @@ -1387,9 +1715,12 @@ static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera } /// - /// Effective Job of drawing the set of Lens Flare registered + /// Renders all visible lens flares. /// - /// Lens Flare material (HDRP or URP shader) + /// + /// Call this function during the post processing phase of the Render Pipeline. + /// + /// Lens flare material (HDRP or URP shader) /// Camera /// Viewport used for rendering and XR applied. /// XRPass data. @@ -1409,7 +1740,7 @@ static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera /// Sun Occlusion Texture from VolumetricCloud on HDRP or null /// Source Render Target which contains the Color Buffer /// Delegate to which return return the Attenuation of the light based on their shape which uses the functions ShapeAttenuation...(...), must reimplemented per SRP - /// Debug View which setup black background to see only Lens Flare + /// Debug View which setup black background to see only lens flare static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera cam, Rect viewport, XRPass xr, int xrIndex, float actualWidth, float actualHeight, bool usePanini, float paniniDistance, float paniniCropToFit, @@ -1436,9 +1767,9 @@ static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera } /// - /// Effective Job of drawing the set of Lens Flare registered + /// Renders the set of lens flare registered. /// - /// Lens Flare material (HDRP or URP shader) + /// Lens flare material (HDRP or URP shader) /// Camera /// Viewport used for rendering and XR applied. /// XRPass data. @@ -1470,7 +1801,7 @@ static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera /// ShaderID for the FlareData2 /// ShaderID for the FlareData3 /// ShaderID for the FlareData4 - /// Debug View which setup black background to see only Lens Flare + /// Debug View which setup black background to see only lens flare [Obsolete("Use DoLensFlareDataDrivenCommon without _FlareOcclusionRemapTex.._FlareData4 parameters.")] static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera cam, Rect viewport, XRPass xr, int xrIndex, float actualWidth, float actualHeight, @@ -1501,9 +1832,12 @@ static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera } /// - /// Effective Job of drawing the set of Lens Flare registered + /// Renders all visible lens flares. /// - /// Lens Flare material (HDRP or URP shader) + /// + /// Call this function during the post processing phase of the Render Pipeline. + /// + /// Lens flare material (HDRP or URP shader) /// Camera /// Viewport used for rendering and XR applied. /// XRPass data. @@ -1523,7 +1857,7 @@ static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera /// Sun Occlusion Texture from VolumetricCloud on HDRP or null /// Source Render Target which contains the Color Buffer /// Delegate to which return return the Attenuation of the light based on their shape which uses the functions ShapeAttenuation...(...), must reimplemented per SRP - /// Debug View which setup black background to see only Lens Flare + /// Debug View which setup black background to see only lens flare static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera cam, Rect viewport, XRPass xr, int xrIndex, float actualWidth, float actualHeight, bool usePanini, float paniniDistance, float paniniCropToFit, @@ -1739,9 +2073,12 @@ static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera } /// - /// Effective Job of drawing Lens Flare Screen Space. + /// Renders the screen space lens flare effect. /// - /// Lens Flare material (HDRP or URP shader) + /// + /// Call this function during the post processing of the render pipeline after the bloom. + /// + /// Lens flare material (HDRP or URP shader) /// Camera /// Width actually used for rendering after dynamic resolution and XR is applied. /// Height actually used for rendering after dynamic resolution and XR is applied. @@ -1757,7 +2094,7 @@ static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera /// streaksIntensity, streaksLength, streaksOrientation, streaksThreshold /// downsampleStreak, warpedFlareScaleX, warpedFlareScaleY, freeSlot /// UnsafeCommandBuffer - /// Result RT for the Lens Flare Screen Space + /// Result RT for the lens flare Screen Space /// Information if we are in debug mode or not static public void DoLensFlareScreenSpaceCommon( Material lensFlareShader, @@ -1801,9 +2138,12 @@ static public void DoLensFlareScreenSpaceCommon( } /// - /// Effective Job of drawing Lens Flare Screen Space. + /// Renders the screen space lens flare effect. /// - /// Lens Flare material (HDRP or URP shader) + /// + /// Call this function during the post processing of the render pipeline after the bloom. + /// + /// Lens flare material (HDRP or URP shader) /// Camera /// Width actually used for rendering after dynamic resolution and XR is applied. /// Height actually used for rendering after dynamic resolution and XR is applied. @@ -1819,7 +2159,7 @@ static public void DoLensFlareScreenSpaceCommon( /// streaksIntensity, streaksLength, streaksOrientation, streaksThreshold /// downsampleStreak, warpedFlareScaleX, warpedFlareScaleY, freeSlot /// Command Buffer - /// Result RT for the Lens Flare Screen Space + /// Result RT for the lens flare Screen Space /// ShaderID for the original bloom texture /// ShaderID for the LensFlareScreenSpaceResultTexture texture /// ShaderID for the LensFlareScreenSpaceSpectralLut texture @@ -1886,9 +2226,12 @@ static public void DoLensFlareScreenSpaceCommon( } /// - /// Effective Job of drawing Lens Flare Screen Space. + /// Renders the screen space lens flare effect. /// - /// Lens Flare material (HDRP or URP shader) + /// + /// Call this function during the post processing of the render pipeline after the bloom. + /// + /// Lens flare material (HDRP or URP shader) /// Camera /// Width actually used for rendering after dynamic resolution and XR is applied. /// Height actually used for rendering after dynamic resolution and XR is applied. @@ -1904,7 +2247,7 @@ static public void DoLensFlareScreenSpaceCommon( /// streaksIntensity, streaksLength, streaksOrientation, streaksThreshold /// downsampleStreak, warpedFlareScaleX, warpedFlareScaleY, freeSlot /// Command Buffer - /// Result RT for the Lens Flare Screen Space + /// Result RT for the lens flare Screen Space /// Information if we are in debug mode or not static public void DoLensFlareScreenSpaceCommon( Material lensFlareShader, diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/NativePassCompiler.Debug.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/NativePassCompiler.Debug.cs index 25c61409a1c..c3d6ec3dd89 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/NativePassCompiler.Debug.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/NativePassCompiler.Debug.cs @@ -164,6 +164,22 @@ internal void GenerateNativeCompilerDebugData(ref RenderGraph.DebugData debugDat resourceWriteLists[pair].Add(renderGraphPass.index); } } + foreach (var read in renderGraphPass.transientResourceList[type]) + { + if (read.type == (RenderGraphResourceType)type && read.index == resIndex) + { + // Transient resources are assumed to be read and write + + var pair = ((RenderGraphResourceType)type, resIndex); + if (!resourceReadLists.ContainsKey(pair)) + resourceReadLists[pair] = new List(); + resourceReadLists[pair].Add(renderGraphPass.index); + + if (!resourceWriteLists.ContainsKey(pair)) + resourceWriteLists[pair] = new List(); + resourceWriteLists[pair].Add(renderGraphPass.index); + } + } } } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/PassesData.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/PassesData.cs index f82c151f6b7..e7d1b458483 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/PassesData.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/PassesData.cs @@ -1216,13 +1216,19 @@ public static PassBreakAudit TryMerge(CompilerContextData contextData, int activ ref var existingAttach = ref nativePass.fragments[i]; if (PassFragmentData.SameSubResource(existingAttach, newAttach)) { - // Update the attached version access flags and version - existingAttach.accessFlags |= newAttach.accessFlags; + var newAttachAccessFlags = newAttach.accessFlags; + // If the existing attachment accessFlag has Discard flag, remove Read flag from newAttach flags, as the content has not to be Loaded + if (existingAttach.accessFlags.HasFlag(AccessFlags.Discard)) + newAttachAccessFlags = newAttachAccessFlags & ~AccessFlags.Read; + + existingAttach.accessFlags |= newAttachAccessFlags; + #if DEVELOPMENT_BUILD || UNITY_EDITOR if (existingAttach.resource.version > newAttach.resource.version) throw new Exception("Adding an older version while a higher version is already registered with the pass."); #endif - existingAttach.resource.version = newAttach.resource.version; + var prevAttachRes = existingAttach.resource; + existingAttach.resource = new ResourceHandle(prevAttachRes, newAttach.resource.version); alreadyAttached = true; break; } @@ -1243,13 +1249,19 @@ public static PassBreakAudit TryMerge(CompilerContextData contextData, int activ ref var existingAttach = ref nativePass.fragments[i]; if (PassFragmentData.SameSubResource(existingAttach, newAttach)) { - // Update the attached version access flags and version - existingAttach.accessFlags |= newAttach.accessFlags; + var newAttachAccessFlags = newAttach.accessFlags; + // If the existing attachment accessFlag has Discard flag, remove Read flag from newAttach flags, as the content has not to be Loaded + if (existingAttach.accessFlags.HasFlag(AccessFlags.Discard)) + newAttachAccessFlags = newAttachAccessFlags & ~AccessFlags.Read; + + existingAttach.accessFlags |= newAttachAccessFlags; + #if DEVELOPMENT_BUILD || UNITY_EDITOR if (existingAttach.resource.version > newAttach.resource.version) throw new Exception("Adding an older version while a higher version is already registered with the pass."); #endif - existingAttach.resource.version = newAttach.resource.version; + var prevAttachRes = existingAttach.resource; + existingAttach.resource = new ResourceHandle(prevAttachRes, newAttach.resource.version); alreadyAttached = true; break; } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs index fed5297b1be..2ac5a1ad1d6 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphDefaultResources.cs @@ -38,7 +38,7 @@ internal RenderGraphDefaultResources() { m_BlackTexture2D = RTHandles.Alloc(Texture2D.blackTexture); m_WhiteTexture2D = RTHandles.Alloc(Texture2D.whiteTexture); - m_ShadowTexture2D = RTHandles.Alloc(1, 1, Experimental.Rendering.GraphicsFormat.D32_SFloat, isShadowMap: true, name: "DefaultShadowTexture"); + m_ShadowTexture2D = RTHandles.Alloc(1, 1, CoreUtils.GetDefaultDepthStencilFormat(), isShadowMap: true, name: "DefaultShadowTexture"); } internal void Cleanup() diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphGlobalSettings.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphGlobalSettings.cs index 8dbdd727f0f..8e142638c05 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphGlobalSettings.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphGlobalSettings.cs @@ -3,8 +3,33 @@ namespace UnityEngine.Rendering { /// - /// Render Graph global settings class. + /// A graphics settings container for settings related to the Render Graph for all Scriptable Render Pipelines. /// + /// + /// To change those settings, go to Editor > Project Settings in the Graphics tab. + /// Changing this through the API is only allowed in the Editor. In the Player, this raises an error. + /// + /// + /// + /// This example demonstrates how to determine if your project uses RenderGraph's compilation caching. + /// + /// using UnityEngine.Rendering; + /// + /// public static class RenderGraphHelper + /// { + /// public static bool enableCompilationCaching + /// { + /// get + /// { + /// var gs = GraphicsSettings.GetRenderPipelineSettings<RenderGraphGlobalSettings>(); + /// if (gs == null) //not in SRP + /// return false; + /// return gs.enableCompilationCaching; + /// } + /// } + /// } + /// + /// [Serializable] [SupportedOnRenderPipeline] [Categorization.CategoryInfo(Name = "Render Graph", Order = 50)] diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs index 5e602e26f6a..391e0de039f 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphPass.cs @@ -127,7 +127,15 @@ public bool HasRenderAttachments() [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsTransient(in ResourceHandle res) { - return transientResourceList[res.iType].Contains(res); + // Versioning doesn't matter much for transient resources as they are only used within a single pass + for (int i = 0; i < transientResourceList[res.iType].Count; i++) + { + if (transientResourceList[res.iType][i].index == res.index) + { + return true; + } + } + return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResources.cs b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResources.cs index df4c4ccc562..4fa36d7a241 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResources.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphResources.cs @@ -13,7 +13,9 @@ internal enum RenderGraphResourceType Count } - internal struct ResourceHandle : IEquatable + // For performance reasons, ResourceHandle is readonly. + // To update an existing instance with a new version, recreate it using its copy constructor + internal readonly struct ResourceHandle : IEquatable { // Note on handles validity. // PassData classes used during render graph passes are pooled and because of that, when users don't fill them completely, @@ -24,9 +26,10 @@ internal struct ResourceHandle : IEquatable const uint kValidityMask = 0xFFFF0000; const uint kIndexMask = 0xFFFF; - uint m_Value; - int m_Version; // A freshly created resource always starts at version 0 the first write should bring it to v1 - + private readonly uint m_Value; + private readonly int m_Version; + private readonly RenderGraphResourceType m_Type; + static uint s_CurrentValidBit = 1 << 16; static uint s_SharedResourceValidBit = 0x7FFF << 16; @@ -44,23 +47,25 @@ public int version { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return m_Version; } + } + public RenderGraphResourceType type + { [MethodImpl(MethodImplOptions.AggressiveInlining)] - set { m_Version = value; } + get { return m_Type; } } - public RenderGraphResourceType type { get; private set; } internal ResourceHandle(int value, RenderGraphResourceType type, bool shared) { Debug.Assert(value <= 0xFFFF); m_Value = ((uint)value & kIndexMask) | (shared ? s_SharedResourceValidBit : s_CurrentValidBit); - this.type = type; - this.m_Version = -1; + m_Type = type; + m_Version = -1; } internal ResourceHandle(in ResourceHandle h, int version) { this.m_Value = h.m_Value; - this.type = h.type; + this.m_Type = h.type; this.m_Version = version; } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Settings/IncludeRenderPipelineAsset.cs b/Packages/com.unity.render-pipelines.core/Runtime/Settings/IncludeRenderPipelineAsset.cs index 4474d014f2c..03eb7a2e02e 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Settings/IncludeRenderPipelineAsset.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Settings/IncludeRenderPipelineAsset.cs @@ -3,9 +3,39 @@ namespace UnityEngine.Rendering { /// - /// Define the RPAsset inclusion at build time, for your pipeline. - /// Default: only RPAsset in QualitySettings are embedded on build + /// A graphics settings container for settings related to additional inclusion at build time. /// + /// + /// These settings are not editable through the editor's UI but can be changed through the API for advanced usage. + /// Changing this through the API is only allowed in the Editor. In the Player, this raises an error. + /// + /// By default, only RPAsset, in Quality Settings, is embedded in the build. This allows you to add assets. + /// Add any render pipeline assets you use in your project either through this or directly in Quality Settings. They contain data listing what resources need to be embedded in the build. + /// It is highly recommended not to change it unless you know what you are doing. Otherwise, this may lead to unexpected changes in your Player. + /// + /// + /// + /// Here is an example of how to determine what label to use to embed additional assets. + /// + /// using UnityEngine.Rendering; + /// + /// public static class RPAssetIncludedHelper + /// { + /// public static string label + /// { + /// get + /// { + /// var gs = GraphicsSettings.GetRenderPipelineSettings<IncludeAdditionalRPAssets>(); + /// if (gs == null) //not in SRP + /// return null; + /// if (!gs.includeAssetsByLabel) + /// return null; + /// return gs.labelToInclude; + /// } + /// } + /// } + /// + /// [Serializable] [SupportedOnRenderPipeline] [Categorization.CategoryInfo(Name = "H: RP Assets Inclusion", Order = 990), HideInInspector] diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Settings/RenderingDebuggerRuntimeResources.cs b/Packages/com.unity.render-pipelines.core/Runtime/Settings/RenderingDebuggerRuntimeResources.cs new file mode 100644 index 00000000000..9760bdbc468 --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Runtime/Settings/RenderingDebuggerRuntimeResources.cs @@ -0,0 +1,42 @@ +using System; + +namespace UnityEngine.Rendering +{ + [Serializable, HideInInspector] + [SupportedOnRenderPipeline] + [Categorization.CategoryInfo(Name = "R : Rendering Debugger Resources", Order = 100)] + [Categorization.ElementInfo(Order = 0)] + class RenderingDebuggerRuntimeResources : IRenderPipelineResources + { + enum Version + { + Initial, + + Count, + Last = Count - 1 + } + [SerializeField, HideInInspector] + private Version m_version = Version.Last; + int IRenderPipelineGraphicsSettings.version => (int)m_version; + + [SerializeField, ResourcePath("Runtime/Debugging/Runtime UI Resources/DebugUICanvas.prefab")] + private GameObject m_DebugUIHandlerCanvasPrefab; + + /// Panel Settings + public GameObject debugUIHandlerCanvasPrefab + { + get => m_DebugUIHandlerCanvasPrefab; + set => this.SetValueAndNotify(ref m_DebugUIHandlerCanvasPrefab, value, nameof(m_DebugUIHandlerCanvasPrefab)); + } + + [SerializeField, ResourcePath("Runtime/Debugging/Runtime UI Resources/DebugUIPersistentCanvas.prefab")] + private GameObject m_DebugUIPersistentCanvasPrefab; + + /// Panel Settings + public GameObject debugUIPersistentCanvasPrefab + { + get => m_DebugUIPersistentCanvasPrefab; + set => this.SetValueAndNotify(ref m_DebugUIPersistentCanvasPrefab, value, nameof(m_DebugUIPersistentCanvasPrefab)); + } + } +} diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Settings/RenderingDebuggerRuntimeResources.cs.meta b/Packages/com.unity.render-pipelines.core/Runtime/Settings/RenderingDebuggerRuntimeResources.cs.meta new file mode 100644 index 00000000000..499cf662046 --- /dev/null +++ b/Packages/com.unity.render-pipelines.core/Runtime/Settings/RenderingDebuggerRuntimeResources.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5dcd7bd9464c47caa62a9c418a69a1a5 +timeCreated: 1736856030 \ No newline at end of file diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Settings/ShaderStrippingSetting.cs b/Packages/com.unity.render-pipelines.core/Runtime/Settings/ShaderStrippingSetting.cs index 8625c4d095c..72910851581 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Settings/ShaderStrippingSetting.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Settings/ShaderStrippingSetting.cs @@ -21,8 +21,33 @@ public enum ShaderVariantLogLevel } /// - /// Class that stores shader stripping settings shared between all pipelines + /// This is a Graphics Settings container for settings related to shader stripping for all scriptable render pipelines. /// + /// + /// To change those settings, go to Editor > Project Settings in the Graphics tab. + /// Changing this through the API is only allowed in the Editor. In the Player, this raises an error. + /// + /// + /// + /// Here is an example of how to check if your project strips variant shaders when building a Player using URP. + /// + /// using UnityEngine.Rendering; + /// + /// public static class ShaderStrippingHelper + /// { + /// public static bool exportLog + /// { + /// get + /// { + /// var gs = GraphicsSettings.GetRenderPipelineSettings<ShaderStrippingSetting>(); + /// if (gs == null) //not in any SRP + /// return false; + /// return gs.exportShaderVariants; + /// } + /// } + /// } + /// + /// [Serializable] [SupportedOnRenderPipeline] [Categorization.CategoryInfo(Name = "Additional Shader Stripping Settings", Order = 40)] @@ -38,7 +63,7 @@ internal enum Version : int [SerializeField] [HideInInspector] private Version m_Version = Version.Initial; - /// Current version. + /// Current version of the settings container. Used only for project upgrades. public int version => (int)m_Version; #endregion diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blitter.cs b/Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blitter.cs index 27d7fa2be8d..1013ff02985 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blitter.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blitter.cs @@ -13,6 +13,19 @@ namespace UnityEngine.Rendering /// /// Various blit (texture copy) utilities for the Scriptable Render Pipelines. /// + /// + /// The Blitter class works on textures and targets identified with , + /// but most importantly with . This enables + /// copying to / from textures managed by the . + /// + /// To use the Blitter functionality in the context of custom Scriptable Render Pipelines, you must first create + /// a blit shader that implements various passes covering the blit variants. To facilitate this, you can create a + /// modified version of the Universal Render Pipeline CoreBlit.shader as displayed in the documentation of the + /// method. + /// + /// Prior to using the Blitter, you must call once. When the render pipeline is to + /// be disposed, you must call the method to dispose of resources created by the Blitter. + /// public static class Blitter { static Material s_Copy; @@ -43,6 +56,7 @@ static class BlitShaderIDs } // This enum needs to be in sync with the shader pass names and indices of the Blit.shader in every pipeline. + // Keep in sync also with the documentation for the Initialize method below. enum BlitShaderPassNames { Nearest = 0, @@ -83,10 +97,51 @@ enum BlitColorAndDepthPassNames static int[] s_BlitColorAndDepthShaderPassIndicesMap; /// - /// Initialize Blitter resources. Must be called once before any use + /// Initializes the Blitter resources. This must be called once before any use. /// - /// Blit shader - /// Blit shader + /// The shader to use when using the blitting / copying methods which operate only on color. + /// The shader to use when using the BlitColorAndDepth methods which operate on both color and depth. + /// + /// Shaders sent to the blitPS parameter should support multiple passes with the corresponding name: + /// + /// Nearest + /// Bilinear + /// NearestQuad + /// BilinearQuad + /// NearestQuadPadding + /// BilinearQuadPadding + /// NearestQuadPaddingRepeat + /// BilinearQuadPaddingRepeat + /// BilinearQuadPaddingOctahedral + /// NearestQuadPaddingAlphaBlend + /// BilinearQuadPaddingAlphaBlend + /// NearestQuadPaddingAlphaBlendRepeat + /// BilinearQuadPaddingAlphaBlendRepeat + /// BilinearQuadPaddingAlphaBlendOctahedral + /// CubeToOctahedral + /// CubeToOctahedralLuminance + /// CubeToOctahedralAlpha + /// CubeToOctahedralRed + /// BilinearQuadLuminance + /// BilinearQuadAlpha + /// BilinearQuadRed + /// NearestCubeToOctahedralPadding + /// BilinearCubeToOctahedralPadding + /// + /// Basic vertex and fragment shader functions are available in Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl for each of these pass types. + /// Similarly, the shaders for the blitColorAndDepthPS parameter should support two passes with these names: + /// + /// ColorOnly + /// ColorAndDepth + /// + /// + /// + /// Blit color shader for URP which implements all the above passes with a user defined FragmentURPBlit fragment function to support debug passes + /// and color space conversion. + /// + /// Blit color and depth shader for URP. + /// + /// public static void Initialize(Shader blitPS, Shader blitColorAndDepthPS) { if (s_Blit != null) @@ -207,7 +262,7 @@ static Vector2[] GetQuadTexCoord() } /// - /// Release Blitter resources. + /// Releases all the internal Blitter resources. Must be called when the Blitter object is to be disposed. /// public static void Cleanup() { @@ -228,11 +283,12 @@ public static void Cleanup() } /// - /// Returns the default blit material. + /// Returns the default blit material constructed from the blit shader passed as the first argument of + /// the method. /// /// Dimension of the texture to blit, either 2D or 2D Array. /// Blit only a single slice of the array if applicable. - /// The default blit material for specified arguments. + /// The default blit material for the specified arguments. static public Material GetBlitMaterial(TextureDimension dimension, bool singleSlice = false) { var material = (dimension == TextureDimension.Tex2DArray) @@ -288,7 +344,7 @@ internal static bool CanCopyMSAA() } /// - /// Copy a texture to another texture using framebuffer fetch. + /// Copies a texture to another texture using framebuffer fetch. /// /// Command Buffer used for rendering. internal static void CopyTexture(RasterCommandBuffer cmd, bool isMSAA) @@ -297,10 +353,10 @@ internal static void CopyTexture(RasterCommandBuffer cmd, bool isMSAA) } /// - /// Blit a RTHandle texture. + /// Blits a RTHandle texture. /// /// Command Buffer used for rendering. - /// Source RTHandle. + /// RTHandle of the source texture to copy from. /// Scale and bias for sampling the input texture. /// Mip level to blit from source. /// Source texture slice index. @@ -311,10 +367,10 @@ internal static void BlitTexture(CommandBuffer cmd, RTHandle source, Vector4 sca } /// - /// Blit a RTHandle texture. + /// Blits a RTHandle texture. /// /// Command Buffer used for rendering. - /// Source RTHandle. + /// RTHandle of the source texture to copy from. /// Scale and bias for sampling the input texture. /// Mip level to blit from source. /// Source texture slice index. @@ -326,26 +382,81 @@ internal static void BlitTexture(CommandBuffer cmd, RTHandle source, Vector4 sca } /// - /// Blit a RTHandle texture. + /// Adds in a a command to copy an XR compatible texture identified by its into + /// the currently bound render target's color buffer. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Scale and bias for sampling the input texture. - /// Mip level to blit. - /// Enable bilinear filtering. + /// + /// Copying is performed using the blit shader passed as the first argument of + /// the method. + /// + /// This overload is meant for textures and render targets which depend on XR output modes by proper handling, when + /// necessary, of left / right eye data copying. This generally correspond to textures which represent full screen + /// + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// Scale and bias for sampling the source texture. + /// Mip level of the source texture to copy from. + /// Enable bilinear filtering when copying. + /// + /// + /// public static void BlitTexture(RasterCommandBuffer cmd, RTHandle source, Vector4 scaleBias, float mipLevel, bool bilinear) { BlitTexture(cmd.m_WrappedCommandBuffer, source, scaleBias, mipLevel, bilinear); } /// - /// Blit a RTHandle texture. + /// Adds in a a command to copy an XR compatible texture identified by its into + /// the currently bound render target's color buffer. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Scale and bias for sampling the input texture. - /// Mip level to blit. - /// Enable bilinear filtering. + /// + /// Copying is performed using the blit shader passed as the first argument of + /// the method. + /// + /// This overload is meant for textures and render targets which depend on XR output modes by proper handling, when + /// necessary, of left / right eye data copying. This generally correspond to textures which represent full screen + /// data that may differ between eyes. + /// + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// Scale and bias for sampling the source texture. + /// Mip level of the source texture to copy from. + /// Enable bilinear filtering when copying. + /// + /// + /// public static void BlitTexture(CommandBuffer cmd, RTHandle source, Vector4 scaleBias, float mipLevel, bool bilinear) { s_PropertyBlock.SetFloat(BlitShaderIDs._BlitMipLevel, mipLevel); @@ -353,26 +464,74 @@ public static void BlitTexture(CommandBuffer cmd, RTHandle source, Vector4 scale } /// - /// Blit a RTHandle texture 2D. + /// Adds in a a command to copy a texture identified by its into + /// the currently bound render target's color buffer. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Scale and bias for sampling the input texture. - /// Mip level to blit. - /// Enable bilinear filtering. + /// + /// Copying is performed using the blit shader passed as the first argument of + /// the method. + /// + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// Scale and bias for sampling the source texture. + /// Mip level of the source texture to copy from. + /// Enable bilinear filtering when copying. + /// + /// + /// public static void BlitTexture2D(RasterCommandBuffer cmd, RTHandle source, Vector4 scaleBias, float mipLevel, bool bilinear) { BlitTexture2D(cmd.m_WrappedCommandBuffer, source, scaleBias, mipLevel, bilinear); } /// - /// Blit a RTHandle texture 2D. + /// Adds in a a command to copy a texture identified by its into + /// the currently bound render target's color buffer. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Scale and bias for sampling the input texture. - /// Mip level to blit. - /// Enable bilinear filtering. + /// + /// Copying is performed using the blit shader passed as the first argument of + /// the method. + /// + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// Scale and bias for sampling the source texture. + /// Mip level of the source texture to copy from. + /// Enable bilinear filtering when copying. + /// + /// + /// public static void BlitTexture2D(CommandBuffer cmd, RTHandle source, Vector4 scaleBias, float mipLevel, bool bilinear) { s_PropertyBlock.SetFloat(BlitShaderIDs._BlitMipLevel, mipLevel); @@ -380,28 +539,90 @@ public static void BlitTexture2D(CommandBuffer cmd, RTHandle source, Vector4 sca } /// - /// Blit a 2D texture and depth buffer. + /// Adds in a a command to copy two XR compatible color and depth textures into + /// the currently bound render target's respective color and depth buffer. /// - /// Command Buffer used for rendering. - /// Source Texture for color. - /// Source RenderTexture for depth. - /// Scale and bias for sampling the input texture. - /// Mip level to blit. - /// Enable depth blit. + /// + /// Although the depth render texture can be passed as a parameter, the copying of the depth information is + /// optional and must be enabled with the blitDepth parameter. + /// The copying is done using the blitColorAndDepth shader passed as the second argument of + /// the method. + /// + /// This overload is meant for textures and render targets which depend on XR output modes by proper handling, when + /// necessary, of left / right eye data copying. This generally corresponds to textures which represent full screen + /// data that may differ between eyes. + /// + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// Source color texture to copy from. + /// Source depth render texture to copy from. + /// Scale and bias for sampling the source texture. + /// Mip level of the source texture to copy from. + /// Enable copying of the source depth texture. + /// + /// + /// public static void BlitColorAndDepth(RasterCommandBuffer cmd, Texture sourceColor, RenderTexture sourceDepth, Vector4 scaleBias, float mipLevel, bool blitDepth) { BlitColorAndDepth(cmd.m_WrappedCommandBuffer, sourceColor, sourceDepth, scaleBias, mipLevel, blitDepth); } /// - /// Blit a 2D texture and depth buffer. + /// Adds in a a command to copy two XR compatible color and depth textures into + /// the currently bound render target's respective color and depth buffer. /// - /// Command Buffer used for rendering. - /// Source Texture for color. - /// Source RenderTexture for depth. - /// Scale and bias for sampling the input texture. - /// Mip level to blit. - /// Enable depth blit. + /// + /// Although the depth render texture can be passed as a parameter, the copying of the depth information is + /// optional and must be enabled with the blitDepth parameter. + /// The copying is done using the blitColorAndDepth shader passed as the second argument of + /// the method. + /// + /// This overload is meant for textures and render targets which depend on XR output modes by proper handling, when + /// necessary, of left / right eye data copying. This generally corresponds to textures which represent full screen + /// data that may differ between eyes. + /// + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// Source color texture to copy from. + /// Source depth render texture to copy from. + /// Scale and bias for sampling the source texture. + /// Mip level of the source texture to copy from. + /// Enable copying of the source depth texture. + /// + /// + /// public static void BlitColorAndDepth(CommandBuffer cmd, Texture sourceColor, RenderTexture sourceDepth, Vector4 scaleBias, float mipLevel, bool blitDepth) { s_PropertyBlock.SetFloat(BlitShaderIDs._BlitMipLevel, mipLevel); @@ -413,26 +634,72 @@ public static void BlitColorAndDepth(CommandBuffer cmd, Texture sourceColor, Ren } /// - /// Blit a RTHandle texture + /// Adds in a a command to copy a texture identified by its into + /// the currently bound render target's color buffer, using a user material and specific shader pass. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Scale and bias for sampling the input texture. - /// Material to invoke when blitting. - /// Pass idx within the material to invoke. + /// + /// The source texture will be bound to the "_BlitTexture" shader property. + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// Scale and bias for sampling the source texture. + /// The material to use for writing to the destination target. + /// The index of the pass to use in the material's shader. + /// + /// + /// public static void BlitTexture(RasterCommandBuffer cmd, RTHandle source, Vector4 scaleBias, Material material, int pass) { BlitTexture(cmd.m_WrappedCommandBuffer, source, scaleBias, material, pass); } /// - /// Blit a RTHandle texture + /// Adds in a a command to copy a texture identified by its into + /// the currently bound render target's color buffer, using a user material and specific shader pass. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Scale and bias for sampling the input texture. - /// Material to invoke when blitting. - /// Pass idx within the material to invoke. + /// + /// The source texture will be bound to the "_BlitTexture" shader property. + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// Scale and bias for sampling the source texture. + /// The material to use for writing to the destination target. + /// The index of the pass to use in the material's shader. + /// + /// + /// public static void BlitTexture(CommandBuffer cmd, RTHandle source, Vector4 scaleBias, Material material, int pass) { s_PropertyBlock.SetVector(BlitShaderIDs._BlitScaleBias, scaleBias); @@ -441,26 +708,72 @@ public static void BlitTexture(CommandBuffer cmd, RTHandle source, Vector4 scale } /// - /// Blit a RTHandle texture + /// Adds in a a command to copy a texture identified by its RenderTargetIdentifier into + /// the currently bound render target's color buffer, using a user material and specific shader pass. /// - /// Command Buffer used for rendering. - /// Source render target. - /// Scale and bias for sampling the input texture. - /// Material to invoke when blitting. - /// Pass idx within the material to invoke. + /// + /// The source texture will be bound to the "_BlitTexture" shader property. + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RenderTargetIdentifier of the source texture to copy from. + /// Scale and bias for sampling the source texture. + /// The material to use for writing to the destination target. + /// The index of the pass to use in the material's shader. + /// + /// + /// public static void BlitTexture(RasterCommandBuffer cmd, RenderTargetIdentifier source, Vector4 scaleBias, Material material, int pass) { BlitTexture(cmd.m_WrappedCommandBuffer, source, scaleBias, material, pass); } /// - /// Blit a RTHandle texture + /// Adds in a a command to copy a texture identified by its RenderTargetIdentifier into + /// the currently bound render target's color buffer, using a user material and specific shader pass. /// - /// Command Buffer used for rendering. - /// Source render target. - /// Scale and bias for sampling the input texture. - /// Material to invoke when blitting. - /// Pass idx within the material to invoke. + /// + /// The source texture will be bound to the "_BlitTexture" shader property. + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RenderTargetIdentifier of the source texture to copy from. + /// Scale and bias for sampling the source texture. + /// The material to use for writing to the destination target. + /// The index of the pass to use in the material's shader. + /// + /// + /// public static void BlitTexture(CommandBuffer cmd, RenderTargetIdentifier source, Vector4 scaleBias, Material material, int pass) { s_PropertyBlock.Clear(); @@ -472,13 +785,28 @@ public static void BlitTexture(CommandBuffer cmd, RenderTargetIdentifier source, } /// - /// Blit a Texture with a specified material. The reference name "_BlitTexture" will be used to bind the input texture. + /// Adds in a a command to copy a texture identified by its RenderTargetIdentifier into + /// a destination render target, using a user material and specific shader pass. /// - /// Command Buffer used for rendering. - /// Source render target. - /// Destination render target. - /// Material to invoke when blitting. - /// Pass idx within the material to invoke. + /// + /// he source texture will be bound to the "_BlitTexture" shader property. + /// + /// This overload is equivalent + /// to + /// with the loadAction set to and the storeAction set to . + /// + /// Command Buffer used for recording the action. + /// RenderTargetIdentifier of the source texture to copy from. + /// RenderTargetIdentifier of the destination render target to copy to. + /// The material to use for writing to the destination target. + /// The index of the pass to use in the material's shader. + /// + /// + /// public static void BlitTexture(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material, int pass) { s_PropertyBlock.Clear(); @@ -491,15 +819,27 @@ public static void BlitTexture(CommandBuffer cmd, RenderTargetIdentifier source, } /// - /// Blit a Texture with a specified material. The reference name "_BlitTexture" will be used to bind the input texture. + /// Adds in a a command to copy a texture identified by its RenderTargetIdentifier into + /// a destination render target, using a user material, specific shader pass and specific load / store actions. /// - /// Command Buffer used for rendering. - /// Source render target. - /// Destination render target. - /// Load action. - /// Store action. - /// Material to invoke when blitting. - /// Pass idx within the material to invoke. + /// + /// The source texture will be bound to the "_BlitTexture" shader property. + /// + /// Command Buffer used for recording the action. + /// RenderTargetIdentifier of the source texture to copy from. + /// RenderTargetIdentifier of the destination render target to copy to. + /// Load action to perform on the destination render target prior to the copying. + /// Store action to perform on the destination render target after the copying. + /// The material to use for writing to the destination target. + /// The index of the pass to use in the material's shader. + /// + /// + /// public static void BlitTexture(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier destination, RenderBufferLoadAction loadAction, RenderBufferStoreAction storeAction, Material material, int pass) { s_PropertyBlock.Clear(); @@ -512,25 +852,32 @@ public static void BlitTexture(CommandBuffer cmd, RenderTargetIdentifier source, } /// - /// Blit a quad with a given Material. Set the destination parameter before using this method. + /// Adds in a a command to draw a full screen quad, using a user material and specific shader pass. /// - /// Command Buffer used for rendering. - /// Scale and bias values for sampling the input texture. - /// Material to invoke when blitting. - /// Pass index within the Material to invoke. + /// + /// This method gives you freedom on how to write your blit shader by just taking a material, assumed to + /// be properly configured with input textures already bound to the material. In this method, the "_BlitScaleBias" shader + /// property will be set on the material to the scaleBias parameter, prior to the draw. + /// + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// Scale and bias for sampling the source texture. + /// The material to use for writing to the destination target. + /// The index of the pass to use in the material's shader. public static void BlitTexture(CommandBuffer cmd, Vector4 scaleBias, Material material, int pass) { s_PropertyBlock.SetVector(BlitShaderIDs._BlitScaleBias, scaleBias); DrawTriangle(cmd, material, pass); } + /// /// - /// Blit a quad with a given Material. Set the destination parameter before using this method. + /// Adds in a a command to draw a full screen quad, using a user material and specific shader pass. /// - /// Command Buffer used for rendering. - /// Scale and bias values for sampling the input texture. - /// Material to invoke when blitting. - /// Pass index within the Material to invoke. public static void BlitTexture(RasterCommandBuffer cmd, Vector4 scaleBias, Material material, int pass) { s_PropertyBlock.SetVector(BlitShaderIDs._BlitScaleBias, scaleBias); @@ -538,14 +885,32 @@ public static void BlitTexture(RasterCommandBuffer cmd, Vector4 scaleBias, Mater } /// - /// Blit a RTHandle to another RTHandle. - /// This will properly account for partial usage (in term of resolution) of the texture for the current viewport. + /// Adds in a a command to copy a camera related XR compatible texture identified by + /// its into a destination render target. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Destination RTHandle. - /// Mip level to blit. - /// Enable bilinear filtering. + /// + /// Camera related textures are created with + /// using or + /// to + /// automatically determine their resolution relative to the camera's render target resolution. Compared to the + /// various and methods, this function automatically handles the + /// scaleBias parameter. The copy operation will always write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// RTHandle of the destination render target to copy to. + /// Mip level of the source texture to copy from. + /// Enable bilinear filtering when copying. + /// + /// + /// public static void BlitCameraTexture(CommandBuffer cmd, RTHandle source, RTHandle destination, float mipLevel = 0.0f, bool bilinear = false) { Vector2 viewportScale = source.useScaling ? new Vector2(source.rtHandleProperties.rtHandleScale.x, source.rtHandleProperties.rtHandleScale.y) : Vector2.one; @@ -555,14 +920,32 @@ public static void BlitCameraTexture(CommandBuffer cmd, RTHandle source, RTHandl } /// - /// Blit a RThandle Texture2D RTHandle to another RTHandle. - /// This will properly account for partial usage (in term of resolution) of the texture for the current viewport. + /// Adds in a a command to copy a camera related texture identified by + /// its into a destination render target. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Destination RTHandle. - /// Mip level to blit. - /// Enable bilinear filtering. + /// + /// Camera related textures are created with the + /// method using or + /// to + /// automatically determine their resolution relative to the camera's render target resolution. Compared to the + /// various and methods, this function automatically handles the + /// scaleBias parameter. The copy operation will always write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// RTHandle of the destination render target to copy to. + /// Mip level of the source texture to copy from. + /// Enable bilinear filtering when copying. + /// + /// + /// public static void BlitCameraTexture2D(CommandBuffer cmd, RTHandle source, RTHandle destination, float mipLevel = 0.0f, bool bilinear = false) { Vector2 viewportScale = source.useScaling ? new Vector2(source.rtHandleProperties.rtHandleScale.x, source.rtHandleProperties.rtHandleScale.y) : Vector2.one; @@ -572,15 +955,40 @@ public static void BlitCameraTexture2D(CommandBuffer cmd, RTHandle source, RTHan } /// - /// Blit a RTHandle to another RTHandle. - /// This will properly account for partial usage (in term of resolution) of the texture for the current viewport. - /// This overloads allows the user to override the default blit shader + /// Adds in a a command to copy a camera related texture identified by + /// its into a destination render target, using a user material and specific shader pass. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Destination RTHandle. - /// The material to use when blitting - /// pass to use of the provided material + /// + /// Camera related textures are created with the + /// method using or + /// to + /// automatically determine their resolution relative to the camera's render target resolution. Compared to the + /// various and methods, this function automatically handles the + /// scaleBias parameter of these methods. The copy operation will always write to the full destination render target rectangle. + /// + /// The "_BlitTexture" shader property will be set to the source texture and the "_BlitScaleBias" shader + /// property will be set to the appropriate parameter, prior to the draw. + /// + /// This overload is equivalent + /// to + /// with the loadAction set to and the storeAction set + /// to . + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// RTHandle of the destination render target to copy to. + /// The material to use for writing to the destination target. + /// The index of the pass to use in the material's shader. + /// + /// + /// public static void BlitCameraTexture(CommandBuffer cmd, RTHandle source, RTHandle destination, Material material, int pass) { Vector2 viewportScale = source.useScaling ? new Vector2(source.rtHandleProperties.rtHandleScale.x, source.rtHandleProperties.rtHandleScale.y) : Vector2.one; @@ -590,17 +998,38 @@ public static void BlitCameraTexture(CommandBuffer cmd, RTHandle source, RTHandl } /// - /// Blit a RTHandle to another RTHandle. - /// This will properly account for partial usage (in term of resolution) of the texture for the current viewport. - /// This overloads allows the user to override the default blit shader + /// Adds in a a command to copy a camera related texture identified by + /// its into a destination render target, using a user material, specific shader pass and specific load / store actions. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Destination RTHandle. - /// Load action. - /// Store action. - /// The material to use when blitting - /// pass to use of the provided material + /// + /// Camera related textures are created with the + /// method using or + /// to + /// automatically determine their resolution relative to the camera's render target resolution. Compared to the + /// various and methods, this function automatically handles the + /// scaleBias parameter. The copy operation will always write to the full destination render target rectangle. + /// + /// The "_BlitTexture" shader property will be set to the source texture and the "_BlitScaleBias" shader + /// property will be set to the appropriate value, prior to the draw. + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// RTHandle of the destination render target to copy to. + /// Load action to perform on the destination render target prior to the copying. + /// Store action to perform on the destination render target after the copying. + /// The material to use for writing to the destination target. + /// The index of the pass to use in the material's shader. + /// + /// + /// public static void BlitCameraTexture(CommandBuffer cmd, RTHandle source, RTHandle destination, RenderBufferLoadAction loadAction, RenderBufferStoreAction storeAction, Material material, int pass) { Vector2 viewportScale = source.useScaling ? new Vector2(source.rtHandleProperties.rtHandleScale.x, source.rtHandleProperties.rtHandleScale.y) : Vector2.one; @@ -610,16 +1039,32 @@ public static void BlitCameraTexture(CommandBuffer cmd, RTHandle source, RTHandl } /// - /// Blit a RTHandle to another RTHandle. - /// This will properly account for partial usage (in term of resolution) of the texture for the current viewport. - /// This overload allows user to override the scale and bias used when sampling the input RTHandle. + /// Adds in a a command to copy a camera related XR compatible texture identified by + /// its into a destination render target, using a user defined scale and bias. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Destination RTHandle. - /// Scale and bias used to sample the input RTHandle. - /// Mip level to blit. - /// Enable bilinear filtering. + /// + /// The scaleBias parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. The operation will always + /// write to the full destination render target rectangle. + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// RTHandle of the destination render target to copy to. + /// Scale and bias for sampling the source texture. + /// Mip level of the source texture to copy from. + /// Enable bilinear filtering when copying. + /// + /// + /// public static void BlitCameraTexture(CommandBuffer cmd, RTHandle source, RTHandle destination, Vector4 scaleBias, float mipLevel = 0.0f, bool bilinear = false) { // Will set the correct camera viewport as well. @@ -628,16 +1073,33 @@ public static void BlitCameraTexture(CommandBuffer cmd, RTHandle source, RTHandl } /// - /// Blit a RTHandle to another RTHandle. - /// This will properly account for partial usage (in term of resolution) of the texture for the current viewport. - /// This overload allows user to override the viewport of the destination RTHandle. + /// Adds in a a command to copy a camera related XR compatible texture identified by + /// its into a destination render target using a custom destination viewport. /// - /// Command Buffer used for rendering. - /// Source RTHandle. - /// Destination RTHandle. - /// Viewport of the destination RTHandle. - /// Mip level to blit. - /// Enable bilinear filtering. + /// + /// Camera related textures are created with the + /// method using or + /// to + /// automatically determine their resolution relative to the camera's render target resolution. Compared to the + /// various and methods, this function automatically handles the + /// scaleBias parameter. The copy operation will write to the destViewport viewport . + /// + /// Command Buffer used for recording the action. + /// RTHandle of the source texture to copy from. + /// RTHandle of the destination render target to copy to. + /// Rect of the destination viewport to write to. + /// Mip level of the source texture to copy from. + /// Enable bilinear filtering when copying. + /// + /// + /// public static void BlitCameraTexture(CommandBuffer cmd, RTHandle source, RTHandle destination, Rect destViewport, float mipLevel = 0.0f, bool bilinear = false) { Vector2 viewportScale = source.useScaling ? new Vector2(source.rtHandleProperties.rtHandleScale.x, source.rtHandleProperties.rtHandleScale.y) : Vector2.one; @@ -647,14 +1109,32 @@ public static void BlitCameraTexture(CommandBuffer cmd, RTHandle source, RTHandl } /// - /// Blit a texture using a quad in the current render target. + /// Adds in a a command to copy an XR compatible texture onto a portion of the current render target. /// - /// Command buffer used for rendering. - /// Source texture. - /// Scale and bias for the input texture. - /// Scale and bias for the output texture. - /// Mip level to blit. + /// + /// The scaleBiasTex parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. + /// + /// Similarly, the scaleBiasRT parameter controls the rectangle of pixels in the render target to write to by manipulating + /// the destination quad coordinates. The X and Y coordinates store the scaling factor to apply to texture + /// coordinates, while the Z and W coordinates store the coordinate offsets. + /// + /// Command Buffer used for recording the action. + /// The source texture to copy from. + /// Scale and bias for sampling the source texture. + /// Scale and bias for the destination quad. + /// Mip level of the source texture to sample. /// Enable bilinear filtering. + /// + /// + /// public static void BlitQuad(CommandBuffer cmd, Texture source, Vector4 scaleBiasTex, Vector4 scaleBiasRT, int mipLevelTex, bool bilinear) { s_PropertyBlock.SetTexture(BlitShaderIDs._BlitTexture, source); @@ -666,16 +1146,53 @@ public static void BlitQuad(CommandBuffer cmd, Texture source, Vector4 scaleBias } /// - /// Blit a texture using a quad in the current render target. + /// Adds in a a command to copy an XR compatible texture onto a portion of the current render target + /// with support for padding on the destination rect. /// - /// Command buffer used for rendering. - /// Source texture. - /// Source texture size. - /// Scale and bias for sampling the input texture. - /// Scale and bias for the output texture. - /// Mip level to blit. + /// + /// ![Diagram of the padding parameters](../manual/images/Blitter_BlitQuadWithPadding.svg) + ///
Diagram detailing the use of the padding, textureSize, scaleBiasTex and scaleBiasRT. + /// + /// The source rect is copied to the destination rect along with extra padding pixels taken from the source texture + /// using the texture's . Both source rect pixels and padding pixels are copied inside the + /// destination rect. + /// + /// The scaleBiasTex parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. + /// + /// Similarly, the scaleBiasRT parameter controls the rectangle of pixels in the render target to write to by manipulating + /// the destination quad coordinates. The X and Y coordinates store the scaling factor to apply to texture + /// coordinates, while the Z and W coordinates store the coordinate offsets. + ///
+ /// Command Buffer used for recording the action. + /// The source texture to copy from. + /// Source texture size in pixels. + /// Scale and bias for sampling the source texture. + /// Scale and bias for the destination quad. + /// Mip level of the source texture to sample. /// Enable bilinear filtering. - /// Padding in pixels. + /// Padding in pixels to add in the destination rect. + /// This is the total padding on an axis so to have N pixels added to the left, and N pixels to the right, paddingInPixels should be set to 2N. + /// + /// + /// public static void BlitQuadWithPadding(CommandBuffer cmd, Texture source, Vector2 textureSize, Vector4 scaleBiasTex, Vector4 scaleBiasRT, int mipLevelTex, bool bilinear, int paddingInPixels) { s_PropertyBlock.SetTexture(BlitShaderIDs._BlitTexture, source); @@ -691,16 +1208,50 @@ public static void BlitQuadWithPadding(CommandBuffer cmd, Texture source, Vector } /// - /// Blit a texture using a quad in the current render target, by performing an alpha blend with the existing content on the render target. + /// Adds in a a command to blit an XR compatible texture onto a portion of the current render target + /// with a multiply blend and support for padding on the destination rect. /// - /// Command buffer used for rendering. - /// Source texture. - /// Source texture size. - /// Scale and bias for sampling the input texture. - /// Scale and bias for the output texture. - /// Mip level to blit. + /// + /// The source rect is blended to the destination rect with a multiplicative blend, along with extra padding pixels taken from the source texture + /// using the texture's . Both source rect pixels and padding pixels are blitted inside the + /// destination rect. See for a diagram of how padding is applied. + /// + /// The scaleBiasTex parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. + /// + /// Similarly, the scaleBiasRT parameter controls the rectangle of pixels in the render target to write to by manipulating + /// the destination quad coordinates. The X and Y coordinates store the scaling factor to apply to texture + /// coordinates, while the Z and W coordinates store the coordinate offsets. + /// + /// Command Buffer used for recording the action. + /// The source texture to copy from. + /// Source texture size in pixels. + /// Scale and bias for sampling the source texture. + /// Scale and bias for the destination quad. + /// Mip level of the source texture to sample. /// Enable bilinear filtering. - /// Padding in pixels. + /// Padding in pixels to add in the destination rect. + /// This is the total padding on an axis so to have N pixels added to the left, and N pixels to the right, paddingInPixels should be set to 2N. + /// + /// + /// public static void BlitQuadWithPaddingMultiply(CommandBuffer cmd, Texture source, Vector2 textureSize, Vector4 scaleBiasTex, Vector4 scaleBiasRT, int mipLevelTex, bool bilinear, int paddingInPixels) { s_PropertyBlock.SetTexture(BlitShaderIDs._BlitTexture, source); @@ -716,16 +1267,53 @@ public static void BlitQuadWithPaddingMultiply(CommandBuffer cmd, Texture source } /// - /// Blit a texture (which is a Octahedral projection) using a quad in the current render target. + /// Adds in a a command to copy an XR compatible octahedral environment texture + /// onto a portion of the current render target with support for padding on the destination rect. /// - /// Command buffer used for rendering. - /// Source texture. - /// Source texture size. - /// Scale and bias for sampling the input texture. - /// Scale and bias for the output texture. - /// Mip level to blit. + /// + /// ![Diagram of the padding parameters](../manual/images/Blitter_BlitOctohedralWithPadding.svg) + ///
Diagram detailing the use of the padding, textureSize, scaleBiasTex and scaleBiasRT. + /// + /// The source rect is copied to the destination rect along with extra padding pixels taken from the source texture + /// but, compared to , using a specific octahedral mirror repeat mode. Both source rect pixels + /// and padding pixels are blitted inside the destination rect. + /// + /// The scaleBiasTex parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. + /// + /// Similarly, the scaleBiasRT parameter controls the rectangle of pixels in the render target to write to by manipulating + /// the destination quad coordinates. The X and Y coordinates store the scaling factor to apply to texture + /// coordinates, while the Z and W coordinates store the coordinate offsets. + ///
+ /// Command Buffer used for recording the action. + /// The source texture to copy from. + /// Source texture size in pixels. + /// Scale and bias for sampling the source texture. + /// Scale and bias for the destination quad. + /// Mip level of the source texture to sample. /// Enable bilinear filtering. - /// Padding in pixels. + /// Padding in pixels to add in the destination rect. + /// This is the total padding on an axis so to have N pixels added to the left, and N pixels to the right, paddingInPixels should be set to 2N. + /// + /// + /// public static void BlitOctahedralWithPadding(CommandBuffer cmd, Texture source, Vector2 textureSize, Vector4 scaleBiasTex, Vector4 scaleBiasRT, int mipLevelTex, bool bilinear, int paddingInPixels) { s_PropertyBlock.SetTexture(BlitShaderIDs._BlitTexture, source); @@ -738,16 +1326,50 @@ public static void BlitOctahedralWithPadding(CommandBuffer cmd, Texture source, } /// - /// Blit a texture (which is a Octahedral projection) using a quad in the current render target, by performing an alpha blend with the existing content on the render target. + /// Adds in a a command to copy an XR compatible octahedral environment texture + /// onto a portion of the current render target with a multiply blend and support for padding on the destination rect. /// - /// Command buffer used for rendering. - /// Source texture. - /// Source texture size. - /// Scale and bias for sampling the input texture. - /// Scale and bias for the output texture. - /// Mip level to blit. + /// + /// The source rect is blended onto the destination rect with a multiplicative blend, with extra padding pixels taken + /// from the source texture but, compared to , using a specific octahedral mirror + /// repeat mode. Both source rect pixels and padding pixels are blitted inside the destination rect. See + /// for a diagram of how padding is applied to the destination. + /// + /// The scaleBiasTex parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. + /// + /// Similarly, the scaleBiasRT parameter controls the rectangle of pixels in the render target to write to by manipulating + /// the destination quad coordinates. The X and Y coordinates store the scaling factor to apply to texture + /// coordinates, while the Z and W coordinates store the coordinate offsets. + /// + /// Command Buffer used for recording the action. + /// The source texture to copy from. + /// Source texture size in pixels. + /// Scale and bias for sampling the source texture. + /// Scale and bias for the destination quad. + /// Mip level of the source texture to sample. /// Enable bilinear filtering. - /// Padding in pixels. + /// Padding in pixels to add in all directions to the source rect. + /// + /// + /// public static void BlitOctahedralWithPaddingMultiply(CommandBuffer cmd, Texture source, Vector2 textureSize, Vector4 scaleBiasTex, Vector4 scaleBiasRT, int mipLevelTex, bool bilinear, int paddingInPixels) { s_PropertyBlock.SetTexture(BlitShaderIDs._BlitTexture, source); @@ -760,12 +1382,33 @@ public static void BlitOctahedralWithPaddingMultiply(CommandBuffer cmd, Texture } /// - /// Blit a cube texture into 2d texture as octahedral quad. (projection) + /// Adds in a a command to copy a cube map texture onto a portion of the current render target + /// using octahedral mapping for the destination. /// - /// Command buffer used for rendering. - /// Source cube texture. - /// Mip level to sample. - /// Scale and bias for the output texture. + /// + /// The scaleBiasRT parameter controls the rectangle of pixels in the render target to write to by manipulating + /// the destination quad coordinates. The X and Y coordinates store the scaling factor to apply to texture + /// coordinates, while the Z and W coordinates store the coordinate offsets. + /// + /// Command Buffer used for recording the action. + /// The source cube texture to copy from. + /// Scale and bias for the destination quad. + /// Mip level of the source texture to sample. + /// + /// | | X | | + /// // | | + + - +---+ - + + /// // | | / | | | | + /// // +-------+ + - + - + - + + /// Vector4 center3by3 = new Vector4(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f); + /// Blitter.BlitCubeToOctahedral2DQuad(cmd, source, center3by3, 2); + /// ]]> + /// public static void BlitCubeToOctahedral2DQuad(CommandBuffer cmd, Texture source, Vector4 scaleBiasRT, int mipLevelTex) { s_PropertyBlock.SetTexture(BlitShaderIDs._BlitCubeTexture, source); @@ -776,16 +1419,49 @@ public static void BlitCubeToOctahedral2DQuad(CommandBuffer cmd, Texture source, } /// - /// Blit a cube texture into 2d texture as octahedral quad with padding. (projection) + /// Adds in a a command to copy a cube map texture onto a portion of the current render target + /// using octahedral mapping for the destination + /// with extra padding on the destination rect. /// - /// Command buffer used for rendering. - /// Source cube texture. - /// Source texture size. - /// Mip level to sample. - /// Scale and bias for the output texture. + /// + /// The source cube map pixels are copied onto the destination rect with extra padding pixels taken from the source texture + /// but using a specific octahedral mirror repeat mode. Both source rect pixels and padding pixels are blitted inside the destination rect. + /// See for a diagram of how padding is applied to the destination. + /// + /// The scaleBiasRT parameter controls the rectangle of pixels in the render target to write to by manipulating + /// the destination quad coordinates. The X and Y coordinates store the scaling factor to apply to texture + /// coordinates, while the Z and W coordinates store the coordinate offsets. + /// + /// Command Buffer used for recording the action. + /// The source cube texture to copy from. + /// Source texture size in pixels. + /// Scale and bias for the destination quad. + /// Mip level of the source texture to sample. /// Enable bilinear filtering. - /// Padding in pixels. + /// Padding in pixels to add in all directions to the source rect. /// The purpose of this parameter is to blit HDR-encoded values to a non HDR texture. Use values from API that produce HDR-encoded values, for example . If this parameter is null, HDR decoding is disabled. + /// + /// | | X | | + /// // | | + + - +---+ - + + /// // | | / | | | | + /// // +-------+ + - + - + - + + /// // Desired padding on the destination rect + /// int paddingInPixelsOneDirection = 16; + /// // Multiply by two for the total padding along an axis. + /// int paddingInPixels = 2 * paddingInPixelsOneDirection; + /// Vector4 center3by3 = new Vector4(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f); + /// Vector2 subTextureSize = new Vector2(sourceWidth, sourceHeight); + /// // HDR to non-HDR decoding is not necessary here so drop the + /// // last parameter. + /// Blitter.BlitCubeToOctahedral2DQuadWithPadding(cmd, source, subTextureSize, center3by3, 2, paddingInPixels); + /// ]]> + /// public static void BlitCubeToOctahedral2DQuadWithPadding(CommandBuffer cmd, Texture source, Vector2 textureSize, Vector4 scaleBiasRT, int mipLevelTex, bool bilinear, int paddingInPixels, Vector4? decodeInstructions = null) { var material = GetBlitMaterial(source.dimension); @@ -808,16 +1484,40 @@ public static void BlitCubeToOctahedral2DQuadWithPadding(CommandBuffer cmd, Text } /// - /// Blit a cube texture into 2d texture as octahedral quad. (projection) - /// Conversion between single and multi channel formats. - /// RGB(A) to YYYY (luminance). - /// R to RRRR. - /// A to AAAA. + /// Adds in a a command to perform a single channel copy of a cube map texture onto a portion of the current render target + /// using octahedral mapping for the destination. /// - /// Command buffer used for rendering. - /// Source texture. - /// Scale and bias for the output texture. - /// Mip level to blit. + /// + /// The conversion to a single channel output depends on the source texture's format: + /// + /// Texture FormatOutput conversion + /// RGB(A)the RGB luminance is written to the destination in all channels. + /// Redthe red value is written to the destination in all channels. + /// Alphathe alpha value is written to the destination in all channels. + /// + /// The scaleBiasRT parameter controls the rectangle of pixels in the render target to write to by manipulating + /// the destination quad coordinates. The X and Y coordinates store the scaling factor to apply to texture + /// coordinates, while the Z and W coordinates store the coordinate offsets. + /// + /// Command Buffer used for recording the action. + /// The source cube texture to copy from. + /// Scale and bias for the destination quad. + /// Mip level of the source texture to sample. + /// + /// | | X | | + /// // | | + + - +---+ - + + /// // | | / | | | | + /// // +-------+ + - + - + - + + /// Vector4 center3by3 = new Vector4(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f); + /// Blitter.BlitCubeToOctahedral2DQuadSingleChannel(cmd, source, center3by3, 2); + /// ]]> + /// public static void BlitCubeToOctahedral2DQuadSingleChannel(CommandBuffer cmd, Texture source, Vector4 scaleBiasRT, int mipLevelTex) { int pass = 15; @@ -838,17 +1538,40 @@ public static void BlitCubeToOctahedral2DQuadSingleChannel(CommandBuffer cmd, Te } /// - /// Bilinear Blit a texture using a quad in the current render target. - /// Conversion between single and multi channel formats. - /// RGB(A) to YYYY (luminance). - /// R to RRRR. - /// A to AAAA. + /// Adds in a a command to perform a single channel copy off an XR compatible texture onto a + /// portion of the current render target. /// - /// Command buffer used for rendering. - /// Source texture. - /// Scale and bias for the input texture. - /// Scale and bias for the output texture. - /// Mip level to blit. + /// + /// The conversion to a single channel output depends on the source texture's format: + /// + /// Texture FormatOutput conversion + /// RGB(A)the RGB luminance is written to the destination in all channels. + /// Redthe red value is written to the destination in all channels. + /// Alphathe alpha value is written to the destination in all channels. + /// + /// + /// The scaleBiasTex parameter controls the rectangle of pixels in the source texture to copy by manipulating + /// the source texture coordinates. The X and Y coordinates store the scaling factor to apply to these texture + /// coordinates, while the Z and W coordinates store the texture coordinate offsets. + /// + /// Similarly, the scaleBiasRT parameter controls the rectangle of pixels in the render target to write to by manipulating + /// the destination quad coordinates. The X and Y coordinates store the scaling factor to apply to texture + /// coordinates, while the Z and W coordinates store the coordinate offsets. + /// + /// Command Buffer used for recording the action. + /// The source texture to copy from. + /// Scale and bias for sampling the source texture. + /// Scale and bias for the destination quad. + /// Mip level of the source texture to sample. + /// + /// + /// public static void BlitQuadSingleChannel(CommandBuffer cmd, Texture source, Vector4 scaleBiasTex, Vector4 scaleBiasRT, int mipLevelTex) { int pass = 18; diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Utilities/CoreUtils.cs b/Packages/com.unity.render-pipelines.core/Runtime/Utilities/CoreUtils.cs index c949dcb100d..98f4fce1a70 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Utilities/CoreUtils.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Utilities/CoreUtils.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Collections.Generic; using UnityEngine.Experimental.Rendering; +using System.Runtime.CompilerServices; namespace UnityEngine.Rendering { @@ -1814,5 +1815,33 @@ public static Vector3[] CalculateViewSpaceCorners(Matrix4x4 proj, float z) return outCorners; } + + /// + /// Return the GraphicsFormat of DepthStencil RenderTarget preferred for the current platform. + /// + /// The GraphicsFormat of DepthStencil RenderTarget preferred for the current platform. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static GraphicsFormat GetDefaultDepthStencilFormat() + { +#if UNITY_SWITCH || UNITY_EMBEDDED_LINUX || UNITY_QNX || UNITY_ANDROID + return GraphicsFormat.D24_UNorm_S8_UInt; +#else + return GraphicsFormat.D32_SFloat_S8_UInt; +#endif + } + + /// + /// Return the number of DepthStencil RenderTarget depth bits preferred for the current platform. + /// + /// The number of DepthStencil RenderTarget depth bits preferred for the current platform. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static DepthBits GetDefaultDepthBufferBits() + { +#if UNITY_SWITCH || UNITY_EMBEDDED_LINUX || UNITY_QNX || UNITY_ANDROID + return DepthBits.Depth24; +#else + return DepthBits.Depth32; +#endif + } } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Volume/IVolume.cs b/Packages/com.unity.render-pipelines.core/Runtime/Volume/IVolume.cs index 1a696cd3cdf..37a9949f8b3 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Volume/IVolume.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Volume/IVolume.cs @@ -3,18 +3,40 @@ namespace UnityEngine.Rendering { /// - /// An interface for Volumes + /// Defines the basic structure for a Volume, providing the necessary properties for determining + /// whether the volume should be applied globally to the scene or to specific colliders. /// + /// + /// This interface serves as a contract for systems that implement volume logic, enabling + /// reusable code for volume-based behaviors such as rendering effects, post-processing, or scene-specific logic. + /// The interface is commonly implemented by components that define volumes in a scene, + /// allowing for flexibility in determining how the volume interacts with the scene. A volume can either be global + /// (affecting the entire scene) or local (restricted to specific colliders). + /// This interface is also helpful for drawing gizmos in the scene view, as it allows for visual representation + /// of volumes in the editor based on their settings. + /// public interface IVolume { /// - /// Specifies whether to apply the Volume to the entire Scene or not. + /// Gets or sets a value indicating whether the volume applies to the entire scene. + /// If true, the volume is global and affects all objects within the scene. + /// If false, the volume is local and only affects the objects within the specified colliders. /// + /// + /// When set to true, the volume's effects will be applied universally across the scene, + /// without considering individual colliders. When false, the volume will interact only with + /// the objects inside the colliders defined in . + /// bool isGlobal { get; set; } /// - /// The colliders of the volume if is false + /// A list of colliders that define the area of influence of the volume when is set to false. /// + /// + /// This property holds the colliders that restrict the volume's effects to specific areas of the scene. + /// It is only relevant when is false, and defines the boundaries of where the volume is applied. + /// List colliders { get; } } + } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeComponent.cs b/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeComponent.cs index 70a4d89d30d..17fb6b19b34 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeComponent.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeComponent.cs @@ -7,10 +7,19 @@ namespace UnityEngine.Rendering { /// - /// This attribute allows you to add commands to the Add Override popup menu - /// on Volumes. - /// To filter VolumeComponentMenu based on current Render Pipeline, add SupportedOnRenderPipeline attribute to the class alongside with this attribute. - /// + /// This attribute is used to set up a path in the Add Override popup menu in Unity's Volume system. + /// It allows you to organize and categorize your Volume components into submenus for easier access and management within the editor. + ///
+ /// Specify the name of the menu entry, and use slashes ("/") to create hierarchical submenus in the popup. This is useful for organizing large or complex sets of Volume components. + /// To further filter the menu entries based on the active Render Pipeline, you can combine this attribute with the attribute. + /// This enables conditional display of Volume components depending on the Render Pipeline being used in the project. + /// + /// + /// + /// [VolumeComponentMenu("MyVolumeCategory/LightingEffects")] + /// public class CustomLightingVolume : VolumeComponent { ... } + /// + /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class VolumeComponentMenu : Attribute { @@ -33,14 +42,14 @@ public VolumeComponentMenu(string menu) } /// - /// This attribute allows you to add commands to the Add Override popup menu - /// on Volumes and specify for which render pipelines will be supported + /// This attribute allows you to add commands to the Add Override popup menu on Volumes, + /// while also specifying the render pipeline(s) for which the command will be supported. /// - [Obsolete(@"VolumeComponentMenuForRenderPipelineAttribute is deprecated. Use VolumeComponentMenu with SupportedOnCurrentPipeline instead. #from(2023.1)", false)] + [Obsolete(@"VolumeComponentMenuForRenderPipelineAttribute is deprecated. Use VolumeComponentMenu with SupportedOnRenderPipeline instead. #from(2023.1)", false)] public class VolumeComponentMenuForRenderPipeline : VolumeComponentMenu { /// - /// The list of pipeline types that the target class supports + /// The list of pipeline types that the target class supports. /// public Type[] pipelineTypes { get; } @@ -49,14 +58,15 @@ public class VolumeComponentMenuForRenderPipeline : VolumeComponentMenu /// /// The name of the entry in the override list. You can use slashes to /// create sub-menus. - /// The list of pipeline types that the target class supports + /// The list of pipeline types that the target class supports. + /// Thrown when the pipelineTypes is null or the types do not inherit from . public VolumeComponentMenuForRenderPipeline(string menu, params Type[] pipelineTypes) : base(menu) { if (pipelineTypes == null) - throw new Exception("Specify a list of supported pipeline"); + throw new Exception("Specify a list of supported pipeline."); - // Make sure that we only allow the class types that inherit from the render pipeline + // Ensure that we only allow class types that inherit from RenderPipeline foreach (var t in pipelineTypes) { if (!typeof(RenderPipeline).IsAssignableFrom(t)) @@ -69,20 +79,40 @@ public VolumeComponentMenuForRenderPipeline(string menu, params Type[] pipelineT } + /// - /// An attribute to hide the volume component to be added through `Add Override` button on the volume component list + /// This attribute prevents the component from being included in the list of available + /// overrides in the Volume Inspector via the Add Override button. /// [AttributeUsage(AttributeTargets.Class)] - [Obsolete("VolumeComponentDeprecated has been deprecated (UnityUpgradable) -> [UnityEngine] UnityEngine.HideInInspector", false)] + [Obsolete("VolumeComponentDeprecated has been deprecated (UnityUpgradable) -> [UnityEngine] UnityEngine.HideInInspector #from(2023.1)", false)] public sealed class VolumeComponentDeprecated : Attribute { } + /// - /// The base class for all the components that can be part of a . - /// The Volume framework automatically handles and interpolates any members found in this class. + /// The base class for all components that can be part of a . + /// This class serves as the foundation for creating and managing volume components in Unity's + /// volume system, enabling the handling of various types in a unified way. /// + /// The class is automatically integrated into the volume framework, + /// which handles interpolation and blending of members at runtime. + /// It ensures that parameter values can be adjusted and smoothly transitioned based on different factors, + /// such as render pipeline settings, quality settings, or user-defined parameters. + /// + /// Due to the need to store multiple types in a single collection, + /// this base class provides a mechanism to handle them generically. It allows for easy management and + /// manipulation of parameters of varying types, ensuring consistency across different volume components. + /// + /// - Stores and manages a collection of objects.. + /// - Integrates seamlessly into for enhanced control over rendering and post-processing effects. + /// /// + /// + /// You can create a custom volume component by inheriting from this base class and defining your own. + /// fields. The will handle the interpolation and blending for you. + /// /// /// using UnityEngine.Rendering; /// @@ -92,6 +122,12 @@ public sealed class VolumeComponentDeprecated : Attribute /// public ClampedFloatParameter intensity = new ClampedFloatParameter(0f, 0f, 1f); /// } /// + /// + /// + /// In the example above, the custom component `ExampleComponent` extends `VolumeComponent` and defines a parameter + /// (`intensity`) that can be manipulated within the volume framework. The `ClampedFloatParameter` is a type of + /// that ensures the value remains within a specified range. + /// /// [Serializable] public partial class VolumeComponent : ScriptableObject @@ -164,6 +200,17 @@ internal static void FindParameters(object o, List parameters, if (filter?.Invoke(field) ?? true) { VolumeParameter volumeParameter = (VolumeParameter)field.GetValue(o); +#if UNITY_EDITOR || DEVELOPMENT_BUILD + var attr = (DisplayInfoAttribute[])field.GetCustomAttributes(typeof(DisplayInfoAttribute), true); + if (attr.Length != 0) + { + volumeParameter.debugId = attr[0].name; + } + else + { + volumeParameter.debugId = field.Name; + } +#endif parameters.Add(volumeParameter); } } diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeManager.cs b/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeManager.cs index 0402bb496db..421eadd82a3 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeManager.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeManager.cs @@ -15,9 +15,30 @@ namespace UnityEngine.Rendering { /// - /// A global manager that tracks all the Volumes in the currently loaded Scenes and does all the - /// interpolation work. + /// The is a global manager responsible for tracking and managing all Volume settings across the currently loaded Scenes. + /// It handles interpolation and blending of Volume settings at runtime, ensuring smooth transitions between different states of the volumes. + /// This includes managing post-processing effects, lighting settings, and other environmental effects based on volume profiles. /// + /// + /// + /// The is initialized with two VolumeProfiles: + /// 1. The default VolumeProfile defined in the Graphics Settings. + /// 2. The default VolumeProfile defined in the Quality Settings. + /// + /// These profiles represent the baseline state of all volume parameters, and the VolumeManager interpolates values between them to create a final blended VolumeStack for each camera. + /// Every frame, the VolumeManager updates the parameters of local and global VolumeComponents attached to game objects and ensures that the correct interpolation is applied across different volumes. + /// The VolumeManager acts as the central "point of truth" for all VolumeComponent parameters in a scene. + /// It provides default states for volume settings and dynamically interpolates between different VolumeProfiles to manage changes during runtime. This system is used to handle dynamic environmental and post-processing effects in Unity, ensuring smooth transitions across scene changes and camera views. + /// + /// The VolumeManager integrates seamlessly with Unity's Scriptable Render Pipelines, applying the appropriate settings for rendering effects such as lighting, bloom, exposure, etc., in real time. + /// + /// + /// + /// + /// + /// + /// + /// public sealed partial class VolumeManager { static readonly ProfilerMarker k_ProfilerMarkerUpdate = new ("VolumeManager.Update"); diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeParameter.cs b/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeParameter.cs index 110e5c7e338..723f21e4bd1 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeParameter.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeParameter.cs @@ -8,16 +8,31 @@ namespace UnityEngine.Rendering { - // We need this base class to be able to store a list of VolumeParameter in collections as we - // can't store VolumeParameter with variable T types in the same collection. As a result some - // of the following is a bit hacky... - /// - /// The base class for all parameters types stored in a . + /// The base class for all parameter types stored in a . + /// + /// This class serves as a base for different parameter types that are used within the Volume system, such as those controlling post-processing effects, lighting settings, and other volume-related parameters. + /// + /// The class implements the interface, enabling cloning of the parameter's values for later use or manipulation. /// + /// + /// The class is an abstract base class, and cannot be instantiated directly. + /// Derived classes like represent specific parameter types, such as float, vector, or color values, and can be used to configure individual settings in a Volume component. + /// + /// It is important to note that this class is designed to allow various parameter types to be stored and managed collectively. + /// This mechanism enables developers to create complex and configurable Volume components that can be customized with different parameter types (e.g., sliders for float values, color pickers for color values, etc.). + /// + /// + /// /// + /// + /// public abstract class VolumeParameter : ICloneable { +#if UNITY_EDITOR || DEVELOPMENT_BUILD + internal string debugId { get; set; } +#endif + /// /// A beautified string for debugger output. This is set on a DebuggerDisplay on every /// parameter types. diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeStack.cs b/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeStack.cs index fc9e3dfdf44..1f5afc23906 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeStack.cs +++ b/Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeStack.cs @@ -4,11 +4,32 @@ namespace UnityEngine.Rendering { /// - /// Holds the state of a Volume blending update. A global stack is - /// available by default in but you can also create your own using - /// if you need to update the manager with specific - /// settings and store the results for later use. + /// Represents the state of a Volume blending update within the Volume system. /// + /// + /// + /// This class is responsible for storing the blending of Volume components across multiple scenes and cameras, + /// By default, a global volume stack is provided by the to handle the blending of Volume data across your project. + /// This global stack simplifies managing and blending volume data at a project-wide level. However, if you require more granular control over + /// the blending process or want to store and manage the blending results separately (e.g., per camera or scene), you can create custom volume + /// stacks using . + /// The blending of volumes is based on a combination of several factors: + /// - **Volume Weight:** Determines how strongly a particular volume influences the final result. + /// - **Volume Parameters:** These can be visual settings such as post-processing effects, lighting adjustments, or other specialized effects defined + /// in the Volume components. + /// - **Camera Volume Stack:** Volume blending can vary per camera, allowing different volumes to be blended for different camera views or scenes. + /// + /// While the default global volume stack works for most use cases, custom stacks provide greater flexibility and control, allowing developers + /// to manage and store volume blending results at a per-scene or per-camera level. This can be particularly useful in complex rendering setups + /// or when you want to apply different volume blends for different gameplay contexts or visual effects. + /// + /// Keep in mind that frequent updates to the volume blending process (e.g., every frame) may have an impact on performance, especially when + /// dealing with large numbers of volumes or complex blending operations. + /// + /// + /// + /// + /// public sealed class VolumeStack : IDisposable { // Holds the state of _all_ component types you can possibly add on volumes diff --git a/Packages/com.unity.render-pipelines.core/Runtime/Vrs/Shaders/VrsVisualization.shader b/Packages/com.unity.render-pipelines.core/Runtime/Vrs/Shaders/VrsVisualization.shader index 5eb683d0eb7..a00e2cc6327 100644 --- a/Packages/com.unity.render-pipelines.core/Runtime/Vrs/Shaders/VrsVisualization.shader +++ b/Packages/com.unity.render-pipelines.core/Runtime/Vrs/Shaders/VrsVisualization.shader @@ -41,4 +41,6 @@ Shader "Hidden/Core/VrsVisualization" ENDHLSL } } + + Fallback Off } diff --git a/Packages/com.unity.render-pipelines.core/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl b/Packages/com.unity.render-pipelines.core/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl index 507635aaffe..53ad393b7f1 100644 --- a/Packages/com.unity.render-pipelines.core/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl +++ b/Packages/com.unity.render-pipelines.core/ShaderLibrary/Shadow/ShadowSamplingTent.hlsl @@ -1,5 +1,6 @@ #ifndef SHADOW_SAMPLING_TENT_INCLUDED #define SHADOW_SAMPLING_TENT_INCLUDED + // ------------------------------------------------------------------ // PCF Filtering Tent Functions // ------------------------------------------------------------------ @@ -140,108 +141,121 @@ void SampleShadow_ComputeSamples_Tent_3x3(real4 shadowMapTexture_TexelSize, real } // 5x5 Tent filter (45 degree sloped triangles in U and V) +#define SampleShadow_ComputeSamples_Tent_Filter_5x5(Type, shadowMapTexelSize, coord, fetchesWeights, fetchesUV) \ +{ \ + /* Tent base is 5x5 base thus covering from 25 to 36 texels, thus we need 9 bilinear PCF fetches */ \ + Type##2 tentCenterInTexelSpace = (coord).xy * (shadowMapTexelSize).zw; \ + Type##2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5); \ + Type##2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace; \ + \ + /* Find the weight of each texel based on the area of a 45-degree sloped tent above each of them */ \ + Type##3 texelsWeightsU_A, texelsWeightsU_B; \ + Type##3 texelsWeightsV_A, texelsWeightsV_B; \ + SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B); \ + SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B); \ + \ + /* Each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels */ \ + Type##3 fetchesWeightsU = Type##3(texelsWeightsU_A.xz, texelsWeightsU_B.y) + Type##3(texelsWeightsU_A.y, texelsWeightsU_B.xz); \ + Type##3 fetchesWeightsV = Type##3(texelsWeightsV_A.xz, texelsWeightsV_B.y) + Type##3(texelsWeightsV_A.y, texelsWeightsV_B.xz); \ + \ + /* Move the PCF bilinear fetches to respect texels weights */ \ + Type##3 fetchesOffsetsU = Type##3(texelsWeightsU_A.y, texelsWeightsU_B.xz) / fetchesWeightsU.xyz + Type##3(-2.5, -0.5, 1.5); \ + Type##3 fetchesOffsetsV = Type##3(texelsWeightsV_A.y, texelsWeightsV_B.xz) / fetchesWeightsV.xyz + Type##3(-2.5, -0.5, 1.5); \ + fetchesOffsetsU *= (shadowMapTexelSize).xxx; \ + fetchesOffsetsV *= (shadowMapTexelSize).yyy; \ + \ + Type##2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * (shadowMapTexelSize).xy; \ + (fetchesUV)[0] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.x, fetchesOffsetsV.x); \ + (fetchesUV)[1] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.y, fetchesOffsetsV.x); \ + (fetchesUV)[2] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.z, fetchesOffsetsV.x); \ + (fetchesUV)[3] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.x, fetchesOffsetsV.y); \ + (fetchesUV)[4] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.y, fetchesOffsetsV.y); \ + (fetchesUV)[5] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.z, fetchesOffsetsV.y); \ + (fetchesUV)[6] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.x, fetchesOffsetsV.z); \ + (fetchesUV)[7] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.y, fetchesOffsetsV.z); \ + (fetchesUV)[8] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.z, fetchesOffsetsV.z); \ + \ + (fetchesWeights)[0] = fetchesWeightsU.x * fetchesWeightsV.x; \ + (fetchesWeights)[1] = fetchesWeightsU.y * fetchesWeightsV.x; \ + (fetchesWeights)[2] = fetchesWeightsU.z * fetchesWeightsV.x; \ + (fetchesWeights)[3] = fetchesWeightsU.x * fetchesWeightsV.y; \ + (fetchesWeights)[4] = fetchesWeightsU.y * fetchesWeightsV.y; \ + (fetchesWeights)[5] = fetchesWeightsU.z * fetchesWeightsV.y; \ + (fetchesWeights)[6] = fetchesWeightsU.x * fetchesWeightsV.z; \ + (fetchesWeights)[7] = fetchesWeightsU.y * fetchesWeightsV.z; \ + (fetchesWeights)[8] = fetchesWeightsU.z * fetchesWeightsV.z; \ +} + void SampleShadow_ComputeSamples_Tent_5x5(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[9], out real2 fetchesUV[9]) { - // tent base is 5x5 base thus covering from 25 to 36 texels, thus we need 9 bilinear PCF fetches - real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw; - real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5); - real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace; + SampleShadow_ComputeSamples_Tent_Filter_5x5(real, shadowMapTexture_TexelSize, coord, fetchesWeights, fetchesUV); +} - // find the weight of each texel based on the area of a 45 degree slop tent above each of them. - real3 texelsWeightsU_A, texelsWeightsU_B; - real3 texelsWeightsV_A, texelsWeightsV_B; - SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B); - SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B); - // each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels - real3 fetchesWeightsU = real3(texelsWeightsU_A.xz, texelsWeightsU_B.y) + real3(texelsWeightsU_A.y, texelsWeightsU_B.xz); - real3 fetchesWeightsV = real3(texelsWeightsV_A.xz, texelsWeightsV_B.y) + real3(texelsWeightsV_A.y, texelsWeightsV_B.xz); +// 7x7 Tent filter (45 degree sloped triangles in U and V) +#define SampleShadow_ComputeSamples_Tent_Filter_7x7(Type, shadowMapTexelSize, coord, fetchesWeights, fetchesUV) \ +{ \ + /* Tent base is 7x7 base thus covering from 49 to 64 texels, thus we need 16 bilinear PCF fetches */ \ + Type##2 tentCenterInTexelSpace = (coord).xy * (shadowMapTexelSize).zw; \ + Type##2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5); \ + Type##2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace; \ + \ + /* Find the weight of each texel based on the area of a 45 degree slop tent above each of them. */ \ + Type##4 texelsWeightsU_A, texelsWeightsU_B; \ + Type##4 texelsWeightsV_A, texelsWeightsV_B; \ + SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B); \ + SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B); \ + \ + /* Each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels */ \ + Type##4 fetchesWeightsU = Type##4(texelsWeightsU_A.xz, texelsWeightsU_B.xz) + Type##4(texelsWeightsU_A.yw, texelsWeightsU_B.yw); \ + Type##4 fetchesWeightsV = Type##4(texelsWeightsV_A.xz, texelsWeightsV_B.xz) + Type##4(texelsWeightsV_A.yw, texelsWeightsV_B.yw); \ + \ + /* Move the PCF bilinear fetches to respect texels weights */ \ + Type##4 fetchesOffsetsU = Type##4(texelsWeightsU_A.yw, texelsWeightsU_B.yw) / fetchesWeightsU.xyzw + Type##4(-3.5, -1.5, 0.5, 2.5); \ + Type##4 fetchesOffsetsV = Type##4(texelsWeightsV_A.yw, texelsWeightsV_B.yw) / fetchesWeightsV.xyzw + Type##4(-3.5, -1.5, 0.5, 2.5); \ + fetchesOffsetsU *= (shadowMapTexelSize).xxxx; \ + fetchesOffsetsV *= (shadowMapTexelSize).yyyy; \ + \ + Type##2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * (shadowMapTexelSize).xy; \ + (fetchesUV)[0] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.x, fetchesOffsetsV.x); \ + (fetchesUV)[1] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.y, fetchesOffsetsV.x); \ + (fetchesUV)[2] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.z, fetchesOffsetsV.x); \ + (fetchesUV)[3] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.w, fetchesOffsetsV.x); \ + (fetchesUV)[4] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.x, fetchesOffsetsV.y); \ + (fetchesUV)[5] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.y, fetchesOffsetsV.y); \ + (fetchesUV)[6] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.z, fetchesOffsetsV.y); \ + (fetchesUV)[7] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.w, fetchesOffsetsV.y); \ + (fetchesUV)[8] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.x, fetchesOffsetsV.z); \ + (fetchesUV)[9] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.y, fetchesOffsetsV.z); \ + (fetchesUV)[10] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.z, fetchesOffsetsV.z); \ + (fetchesUV)[11] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.w, fetchesOffsetsV.z); \ + (fetchesUV)[12] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.x, fetchesOffsetsV.w); \ + (fetchesUV)[13] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.y, fetchesOffsetsV.w); \ + (fetchesUV)[14] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.z, fetchesOffsetsV.w); \ + (fetchesUV)[15] = bilinearFetchOrigin + Type##2(fetchesOffsetsU.w, fetchesOffsetsV.w); \ + \ + (fetchesWeights)[0] = fetchesWeightsU.x * fetchesWeightsV.x; \ + (fetchesWeights)[1] = fetchesWeightsU.y * fetchesWeightsV.x; \ + (fetchesWeights)[2] = fetchesWeightsU.z * fetchesWeightsV.x; \ + (fetchesWeights)[3] = fetchesWeightsU.w * fetchesWeightsV.x; \ + (fetchesWeights)[4] = fetchesWeightsU.x * fetchesWeightsV.y; \ + (fetchesWeights)[5] = fetchesWeightsU.y * fetchesWeightsV.y; \ + (fetchesWeights)[6] = fetchesWeightsU.z * fetchesWeightsV.y; \ + (fetchesWeights)[7] = fetchesWeightsU.w * fetchesWeightsV.y; \ + (fetchesWeights)[8] = fetchesWeightsU.x * fetchesWeightsV.z; \ + (fetchesWeights)[9] = fetchesWeightsU.y * fetchesWeightsV.z; \ + (fetchesWeights)[10] = fetchesWeightsU.z * fetchesWeightsV.z; \ + (fetchesWeights)[11] = fetchesWeightsU.w * fetchesWeightsV.z; \ + (fetchesWeights)[12] = fetchesWeightsU.x * fetchesWeightsV.w; \ + (fetchesWeights)[13] = fetchesWeightsU.y * fetchesWeightsV.w; \ + (fetchesWeights)[14] = fetchesWeightsU.z * fetchesWeightsV.w; \ + (fetchesWeights)[15] = fetchesWeightsU.w * fetchesWeightsV.w; \ +} - // move the PCF bilinear fetches to respect texels weights - real3 fetchesOffsetsU = real3(texelsWeightsU_A.y, texelsWeightsU_B.xz) / fetchesWeightsU.xyz + real3(-2.5,-0.5,1.5); - real3 fetchesOffsetsV = real3(texelsWeightsV_A.y, texelsWeightsV_B.xz) / fetchesWeightsV.xyz + real3(-2.5,-0.5,1.5); - fetchesOffsetsU *= shadowMapTexture_TexelSize.xxx; - fetchesOffsetsV *= shadowMapTexture_TexelSize.yyy; - real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy; - fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x); - fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x); - fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x); - fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y); - fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y); - fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y); - fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z); - fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z); - fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z); - fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x; - fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x; - fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x; - fetchesWeights[3] = fetchesWeightsU.x * fetchesWeightsV.y; - fetchesWeights[4] = fetchesWeightsU.y * fetchesWeightsV.y; - fetchesWeights[5] = fetchesWeightsU.z * fetchesWeightsV.y; - fetchesWeights[6] = fetchesWeightsU.x * fetchesWeightsV.z; - fetchesWeights[7] = fetchesWeightsU.y * fetchesWeightsV.z; - fetchesWeights[8] = fetchesWeightsU.z * fetchesWeightsV.z; -} - -// 7x7 Tent filter (45 degree sloped triangles in U and V) void SampleShadow_ComputeSamples_Tent_7x7(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[16], out real2 fetchesUV[16]) { - // tent base is 7x7 base thus covering from 49 to 64 texels, thus we need 16 bilinear PCF fetches - real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw; - real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5); - real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace; - - // find the weight of each texel based on the area of a 45 degree slop tent above each of them. - real4 texelsWeightsU_A, texelsWeightsU_B; - real4 texelsWeightsV_A, texelsWeightsV_B; - SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B); - SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B); - - // each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels - real4 fetchesWeightsU = real4(texelsWeightsU_A.xz, texelsWeightsU_B.xz) + real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw); - real4 fetchesWeightsV = real4(texelsWeightsV_A.xz, texelsWeightsV_B.xz) + real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw); - - // move the PCF bilinear fetches to respect texels weights - real4 fetchesOffsetsU = real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw) / fetchesWeightsU.xyzw + real4(-3.5,-1.5,0.5,2.5); - real4 fetchesOffsetsV = real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw) / fetchesWeightsV.xyzw + real4(-3.5,-1.5,0.5,2.5); - fetchesOffsetsU *= shadowMapTexture_TexelSize.xxxx; - fetchesOffsetsV *= shadowMapTexture_TexelSize.yyyy; - - real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy; - fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x); - fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x); - fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x); - fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.x); - fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y); - fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y); - fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y); - fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.y); - fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z); - fetchesUV[9] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z); - fetchesUV[10] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z); - fetchesUV[11] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.z); - fetchesUV[12] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.w); - fetchesUV[13] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.w); - fetchesUV[14] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.w); - fetchesUV[15] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.w); - - fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x; - fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x; - fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x; - fetchesWeights[3] = fetchesWeightsU.w * fetchesWeightsV.x; - fetchesWeights[4] = fetchesWeightsU.x * fetchesWeightsV.y; - fetchesWeights[5] = fetchesWeightsU.y * fetchesWeightsV.y; - fetchesWeights[6] = fetchesWeightsU.z * fetchesWeightsV.y; - fetchesWeights[7] = fetchesWeightsU.w * fetchesWeightsV.y; - fetchesWeights[8] = fetchesWeightsU.x * fetchesWeightsV.z; - fetchesWeights[9] = fetchesWeightsU.y * fetchesWeightsV.z; - fetchesWeights[10] = fetchesWeightsU.z * fetchesWeightsV.z; - fetchesWeights[11] = fetchesWeightsU.w * fetchesWeightsV.z; - fetchesWeights[12] = fetchesWeightsU.x * fetchesWeightsV.w; - fetchesWeights[13] = fetchesWeightsU.y * fetchesWeightsV.w; - fetchesWeights[14] = fetchesWeightsU.z * fetchesWeightsV.w; - fetchesWeights[15] = fetchesWeightsU.w * fetchesWeightsV.w; + SampleShadow_ComputeSamples_Tent_Filter_7x7(real, shadowMapTexture_TexelSize, coord, fetchesWeights, fetchesUV); } #endif diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/NativePassCompilerRenderGraphTests.cs b/Packages/com.unity.render-pipelines.core/Tests/Editor/NativePassCompilerRenderGraphTests.cs index 3ad5f36cfb1..34dcf8760e4 100644 --- a/Packages/com.unity.render-pipelines.core/Tests/Editor/NativePassCompilerRenderGraphTests.cs +++ b/Packages/com.unity.render-pipelines.core/Tests/Editor/NativePassCompilerRenderGraphTests.cs @@ -293,6 +293,183 @@ public void MergeDifferentDepthFormatsBreaksPass() Assert.AreEqual(Rendering.RenderGraphModule.NativeRenderPassCompiler.PassBreakReason.DifferentDepthTextures, passes[0].breakAudit.reason); } + [Test] + public void MergePassWithWriteAllPass() + { + var g = AllocateRenderGraph(); + + var buffers = ImportAndCreateBuffers(g); + + // Render something to depth + using (var builder = g.AddRasterRenderPass("TestPass0", out var passData)) + { + builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + } + // Merge pass, render with WriteAll in extra 0 + using (var builder = g.AddRasterRenderPass("TestPass1", out var passData)) + { + builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.WriteAll); + builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + } + + var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); + var passes = result.contextData.GetNativePasses(); + + Assert.AreEqual(1, passes.Count); + Assert.AreEqual(2, passes[0].numGraphPasses); + + // Validate attachments + Assert.AreEqual(buffers.depthBuffer.handle.index, passes[0].attachments[0].handle.index); + Assert.AreEqual(buffers.extraBuffers[0].handle.index, passes[0].attachments[1].handle.index); + + ref var depthAttachment = ref passes[0].attachments[0]; + Assert.AreEqual(RenderBufferLoadAction.Load, depthAttachment.loadAction); + + ref var extraAttachment = ref passes[0].attachments[1]; + Assert.AreEqual(RenderBufferLoadAction.DontCare, extraAttachment.loadAction); + } + + [Test] + public void MergeWriteAllPassWithReadPass() + { + var g = AllocateRenderGraph(); + + var buffers = ImportAndCreateBuffers(g); + + // Render something to extra 0 + using (var builder = g.AddRasterRenderPass("TestPass0", out var passData)) + { + builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); + builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.WriteAll); + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + } + // Read from extra 0 + using (var builder = g.AddRasterRenderPass("TestPass1", out var passData)) + { + builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); + builder.SetInputAttachment(buffers.extraBuffers[0], 0, AccessFlags.Read); + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + } + + var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); + var passes = result.contextData.GetNativePasses(); + + Assert.AreEqual(1, passes.Count); + Assert.AreEqual(2, passes[0].numGraphPasses); + + // Validate attachments + Assert.AreEqual(buffers.depthBuffer.handle.index, passes[0].attachments[0].handle.index); + Assert.AreEqual(buffers.extraBuffers[0].handle.index, passes[0].attachments[1].handle.index); + + ref var depthAttachment = ref passes[0].attachments[0]; + Assert.AreEqual(RenderBufferLoadAction.Load, depthAttachment.loadAction); + + ref var extraAttachment = ref passes[0].attachments[1]; + Assert.AreEqual(RenderBufferLoadAction.DontCare, extraAttachment.loadAction); + } + + [Test] + public void MergeReadPassWithWriteAllPass() + { + var g = AllocateRenderGraph(); + + var buffers = ImportAndCreateBuffers(g); + + // Render something to 0,1 + using (var builder = g.AddRasterRenderPass("TestPass0", out var passData)) + { + builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); + builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Read); + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + } + // Render to final buffer + using (var builder = g.AddRasterRenderPass("TestPass1", out var passData)) + { + builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); + builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.WriteAll); + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + } + + var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); + var passes = result.contextData.GetNativePasses(); + + Assert.AreEqual(1, passes.Count); + Assert.AreEqual(2, passes[0].numGraphPasses); + + // Validate attachments + Assert.AreEqual(buffers.depthBuffer.handle.index, passes[0].attachments[0].handle.index); + Assert.AreEqual(buffers.extraBuffers[0].handle.index, passes[0].attachments[1].handle.index); + + ref var depthAttachment = ref passes[0].attachments[0]; + Assert.AreEqual(RenderBufferLoadAction.Load, depthAttachment.loadAction); + + // LoadAction is Clear because it was not used by another pass before, in other case it should be Load + ref var extraAttachment = ref passes[0].attachments[1]; + Assert.AreEqual(RenderBufferLoadAction.Clear, extraAttachment.loadAction); + } + + [Test] + public void MergeDiscardPassWithWrite() + { + var g = AllocateRenderGraph(); + + var buffers = ImportAndCreateBuffers(g); + + // Discard extra 0 + using (var builder = g.AddRasterRenderPass("TestPass0", out var passData)) + { + builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); + builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Discard); + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + } + // Read extra 0 + using (var builder = g.AddRasterRenderPass("TestPass1", out var passData)) + { + builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); + builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Read); + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + } + // Write to extra 0 + using (var builder = g.AddRasterRenderPass("TestPass2", out var passData)) + { + builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); + builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + } + // break pass using another depth, Read extra 0 + using (var builder = g.AddRasterRenderPass("TestPass1", out var passData)) + { + builder.SetRenderAttachmentDepth(buffers.extraDepthBuffer, AccessFlags.Write); + builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Read); + builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); + } + + var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); + var passes = result.contextData.GetNativePasses(); + + Assert.AreEqual(2, passes.Count); + Assert.AreEqual(3, passes[0].numGraphPasses); + + // Validate attachments + Assert.AreEqual(buffers.depthBuffer.handle.index, passes[0].attachments[0].handle.index); + Assert.AreEqual(buffers.extraBuffers[0].handle.index, passes[0].attachments[1].handle.index); + Assert.AreEqual(buffers.extraBuffers[0].handle.index, passes[1].attachments[1].handle.index); + + ref var depthAttachment = ref passes[0].attachments[0]; + Assert.AreEqual(RenderBufferLoadAction.Load, depthAttachment.loadAction); + + // As we have a discard flag in the pass the LoadAction is DontCare, but as it has also a Write flag it should Store the result for the next pass + ref var extraAttachmentPass0 = ref passes[0].attachments[1]; + Assert.AreEqual(RenderBufferLoadAction.DontCare, extraAttachmentPass0.loadAction); + Assert.AreEqual(RenderBufferStoreAction.Store, extraAttachmentPass0.storeAction); + + ref var extraAttachmentPass1 = ref passes[1].attachments[1]; + Assert.AreEqual(RenderBufferLoadAction.Load, extraAttachmentPass1.loadAction); + + } + [Test] public void VerifyMergeStateAfterMergingPasses() { diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/RenderGraphTests.cs b/Packages/com.unity.render-pipelines.core/Tests/Editor/RenderGraphTests.cs index 3da32153632..111cd611c27 100644 --- a/Packages/com.unity.render-pipelines.core/Tests/Editor/RenderGraphTests.cs +++ b/Packages/com.unity.render-pipelines.core/Tests/Editor/RenderGraphTests.cs @@ -41,6 +41,10 @@ class RenderGraphTests RenderGraphTestPipelineAsset m_RenderGraphTestPipeline; RenderGraphTestGlobalSettings m_RenderGraphTestGlobalSettings; + // We need a camera to execute the render graph and a game object to attach a camera + GameObject m_GameObject; + Camera m_Camera; + // For the testing of the following RG steps: Execute and Submit (native) with camera rendering, use this custom RenderGraph render pipeline // through a camera render call to test the RG with a real ScriptableRenderContext class RenderGraphTestPipelineAsset : RenderPipelineAsset @@ -128,6 +132,14 @@ public void Setup() // Getting the RG from the custom asset pipeline m_RenderGraph = m_RenderGraphTestPipeline.renderGraph; + + // We need a real ScriptableRenderContext and a camera to execute the Render Graph + m_GameObject = new GameObject("testGameObject") + { + hideFlags = HideFlags.HideAndDontSave + }; + m_GameObject.tag = "MainCamera"; + m_Camera = m_GameObject.AddComponent(); } [OneTimeTearDown] @@ -147,6 +159,10 @@ public void Cleanup() EditorGraphicsSettings.SetRenderPipelineGlobalSettingsAsset(null); #endif Object.DestroyImmediate(m_RenderGraphTestGlobalSettings); + + GameObject.DestroyImmediate(m_GameObject); + m_GameObject = null; + m_Camera = null; } [SetUp] @@ -1030,16 +1046,6 @@ public void ImportingBuiltinRenderTextureTypeWithInfoHasNoDesc() [Test] public void CreateLegacyRendererLists() { - // We need a real ScriptableRenderContext and a camera to call correctly the legacy RendererLists API - - // add the default camera - var gameObject = new GameObject("testGameObject") - { - hideFlags = HideFlags.HideAndDontSave - }; - gameObject.tag = "MainCamera"; - var camera = gameObject.AddComponent(); - // record and execute render graph calls m_RenderGraphTestPipeline.recordRenderGraphBody = (context, camera, cmd) => { @@ -1061,23 +1067,12 @@ public void CreateLegacyRendererLists() rendererListHandle = m_RenderGraph.CreateSkyboxRendererList(camera, Matrix4x4.identity, Matrix4x4.identity, Matrix4x4.identity, Matrix4x4.identity); Assert.IsTrue(rendererListHandle.IsValid()); }; - camera.Render(); - - GameObject.DestroyImmediate(gameObject); + m_Camera.Render(); } [Test] public void RenderPassWithNoRenderFuncThrows() { - // We need a real ScriptableRenderContext and a camera to execute the render graph - // add the default camera - var gameObject = new GameObject("testGameObject") - { - hideFlags = HideFlags.HideAndDontSave - }; - gameObject.tag = "MainCamera"; - var camera = gameObject.AddComponent(); - // record and execute render graph calls m_RenderGraphTestPipeline.recordRenderGraphBody = (context, camera, cmd) => { @@ -1090,9 +1085,7 @@ public void RenderPassWithNoRenderFuncThrows() }; LogAssert.Expect(LogType.Error, "Render Graph Execution error"); LogAssert.Expect(LogType.Exception, "InvalidOperationException: RenderPass TestPassWithNoRenderFunc was not provided with an execute function."); - camera.Render(); - - GameObject.DestroyImmediate(gameObject); + m_Camera.Render(); } /* @@ -1167,15 +1160,6 @@ public void RequestAsyncReadbackIntoNativeArrayWorks() const int kHeight = 4; const GraphicsFormat format = GraphicsFormat.R8G8B8A8_SRGB; - // We need a real ScriptableRenderContext and a camera to execute the render graph - // add the default camera - var gameObject = new GameObject("testGameObject") - { - hideFlags = HideFlags.HideAndDontSave, - tag = "MainCamera" - }; - var camera = gameObject.AddComponent(); - NativeArray pixels = default; bool passExecuted = false; @@ -1208,7 +1192,7 @@ public void RequestAsyncReadbackIntoNativeArrayWorks() } }; - camera.Render(); + m_Camera.Render(); AsyncGPUReadback.WaitAllRequests(); @@ -1223,7 +1207,6 @@ public void RequestAsyncReadbackIntoNativeArrayWorks() } pixels.Dispose(); - GameObject.DestroyImmediate(gameObject); } void RenderGraphTest_AsyncReadbackCallback(AsyncGPUReadbackRequest request) @@ -1286,14 +1269,6 @@ class TestBuffersImport [Test, ConditionalIgnore("IgnoreGraphicsAPI", "Compute Shaders are not supported for this Graphics API.")] public void ImportingBufferWorks() { - // We need a real ScriptableRenderContext and a camera to execute the render graph - // add the default camera - var gameObject = new GameObject("testGameObject") - { - hideFlags = HideFlags.HideAndDontSave, - tag = "MainCamera" - }; - var camera = gameObject.AddComponent(); #if UNITY_EDITOR var computeShader = AssetDatabase.LoadAssetAtPath(kPathToComputeShader); #else @@ -1344,7 +1319,7 @@ public void ImportingBufferWorks() } }; - camera.Render(); + m_Camera.Render(); // Read back the data from the buffer float[] result2 = new float[bufferSize]; @@ -1358,5 +1333,47 @@ public void ImportingBufferWorks() Assert.IsTrue(result2[i] == 1.0f); } } + + class RenderGraphTransientTestData + { + public TextureHandle transientTexture; + public TextureHandle whiteTexture; + } + + private static readonly int k_DefaultWhiteTextureID = Shader.PropertyToID("_DefaultWhiteTex"); + + [Test] + public void TransientHandleAreValidatedByCommandBufferSafetyLayer() + { + m_RenderGraphTestPipeline.recordRenderGraphBody = (context, camera, cmd) => + { + using (var builder = m_RenderGraph.AddUnsafePass("TransientPass", out var passData)) + { + builder.AllowPassCulling(false); + + var texDesc = new TextureDesc(Vector2.one, false, false) + { + width = 1920, + height = 1080, + format = GraphicsFormat.B10G11R11_UFloatPack32, + clearBuffer = true, + clearColor = Color.red, + name = "Transient Texture" + }; + passData.transientTexture = builder.CreateTransientTexture(texDesc); + passData.whiteTexture = m_RenderGraph.defaultResources.whiteTexture; + + builder.SetRenderFunc((RenderGraphTransientTestData data, UnsafeGraphContext context) => + { + // Will ensure the transient texture is valid or throw an exception otherwise + Assert.DoesNotThrow(delegate { context.cmd.SetGlobalTexture(k_DefaultWhiteTextureID, data.transientTexture); }); + // Put back white instead + context.cmd.SetGlobalTexture(k_DefaultWhiteTextureID, data.whiteTexture); + }); + } + }; + + m_Camera.Render(); + } } } diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/RenderGraphViewerTests.cs b/Packages/com.unity.render-pipelines.core/Tests/Editor/RenderGraphViewerTests.cs index 1ee84a66c2e..411c21ec8a2 100644 --- a/Packages/com.unity.render-pipelines.core/Tests/Editor/RenderGraphViewerTests.cs +++ b/Packages/com.unity.render-pipelines.core/Tests/Editor/RenderGraphViewerTests.cs @@ -4,6 +4,7 @@ using System.Runtime.CompilerServices; using NUnit.Framework; using UnityEngine; +using UnityEngine.UIElements; namespace UnityEditor.Rendering.Tests { @@ -25,7 +26,7 @@ static IEnumerable ScriptPathToAssetPathTestCases() // Script in project ( "Assets/File.cs", "Assets/File.cs" ), - // Script in package (this will work regardless of where the package is located, + // Script in package (this will work regardless of where the package is located, // i.e. in Library, embedded in Packages folder, via "file:" dependency or Git URL) ( $"{relativePackagePath}/File.cs".Replace(@"\", "/"), $"{packageInfo.assetPath}/File.cs" ), @@ -52,7 +53,7 @@ static IEnumerable ScriptPathToAssetPathTestCases() yield return new TestCaseData($"./{inputPath}".Replace("/", @"\"), expectedResult); // Absolute paths, Windows separators - yield return new TestCaseData($"{projectPath}/{inputPath}".Replace("/", @"\"), expectedResult); + yield return new TestCaseData($"{projectPath}/{inputPath}".Replace("/", @"\"), expectedResult); #endif } } @@ -76,5 +77,51 @@ public void CallerFilePathToRelative() } string GetCallerFilePath([CallerFilePath] string filePath = null) => filePath; + + static readonly Foldout k_FoldoutElement = new Foldout(); + static IEnumerable SearchFilterTestCases() + { + // To simplify the test, we use square brackets "[]" to indicate search match highlight. + string FormatWithSearchTag(string str) => + str.Replace("[", RenderGraphViewer.k_SelectionColorBeginTag).Replace("]", RenderGraphViewer.k_SelectionColorEndTag); + + TestCaseData MakeTestCase(string content, string searchString, string result, bool isMatch) + { + var dict = new Dictionary>(); + dict[k_FoldoutElement] = new List() { new() { text = content } }; + var testCase = new TestCaseData(dict, searchString, new List { FormatWithSearchTag(result) }, isMatch); + testCase.SetName($"Searching \"{content}\" for \"{searchString}\" results in \"{result}\" (match={isMatch})"); + return testCase; + } + + // Basic string matches + yield return MakeTestCase("Text", "Te", "[Te]xt", true); + yield return MakeTestCase("Text", "xt", "Te[xt]", true); + yield return MakeTestCase("Text", "Foo", "Text", false); + yield return MakeTestCase("Text", "", "Text", true); + // Only first match per string is highlighted + yield return MakeTestCase("Text Text Text", "Text", "[Text] Text Text", true); + // Verify tags inside target text don't get broken + yield return MakeTestCase("Bold Text", "Text", "Bold [Text]", true); + yield return MakeTestCase("Bold Text", "b", "[B]old Text", true); + yield return MakeTestCase("No Match Here", "b", "No Match Here", false); + yield return MakeTestCase("Multiple Tags", "i", "Mult[i]ple Tags", true); + yield return MakeTestCase("Many Tags", "i", "Many Tags", false); + yield return MakeTestCase("Text
On
Three Lines", "On", "Text
[On]
Three Lines", true); + + } + + [Test, TestCaseSource(nameof(SearchFilterTestCases))] + public void SearchFiltering(Dictionary> content, string searchString, List expectedResults, bool isMatch) + { + RenderGraphViewer.PerformSearch(content, searchString); + + var elements = content[k_FoldoutElement]; + for (int i = 0; i < elements.Count; i++) + { + Assert.AreEqual(elements[i].text, expectedResults[i]); + Assert.AreEqual(k_FoldoutElement.style.display.value, isMatch ? DisplayStyle.Flex : DisplayStyle.None); + } + } } } diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Menu-Items.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Menu-Items.md index 033b60a08e0..0fbfa4cb7be 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Menu-Items.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Menu-Items.md @@ -21,6 +21,8 @@ This section includes all the menu items under the **Edit > Rendering > Renderin This section includes all the menu items under the **Edit > Rendering > Materials** menu fold-out. +For more information, refer to [Convert materials and shaders](convert-from-built-in-convert-materials-and-shaders.md). + | **Item** | **Description** | |-------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Generate Material Resources** | Generate look-up table resources for all HDRP Materials. The generated resources will be placed in the directory **Assets/HDRPDefaultResources/Generated**. | diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Path-Tracing-Example.cs b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Path-Tracing-Example.cs new file mode 100644 index 00000000000..3d82073a245 --- /dev/null +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Path-Tracing-Example.cs @@ -0,0 +1,57 @@ +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.HighDefinition; + +// Class to modify or add a Volume Override from a script +public class ModifyVolumeComponent : MonoBehaviour +{ + public VolumeProfile volumeProfile; // Set this in the inspector + + // Start is called once before the first execution of Update after the MonoBehaviour is created + void Start() + { + // Check that a Volume Profile is set in the Inspector + if (volumeProfile != null) + { + // Get or create the path tracing Volume Override in the Volume Profile + GetOrCreateComponent(volumeProfile, out PathTracing pathTracingComponent); + + // Make sure that the Volume Override is active + pathTracingComponent.active = true; + + // Enable the path tracing effect + pathTracingComponent.enable.value = true; + + // Override the state of the enable field + pathTracingComponent.enable.overrideState = true; + + // Set the value for the maximumDepth field + pathTracingComponent.maximumDepth.value = 4; + + // Override the state of the maximumDepth field + pathTracingComponent.maximumDepth.overrideState = true; + } + } + + // Get a Volume Override from a Volume Profile. Create it if it doesn't exist + private static void GetOrCreateComponent(in VolumeProfile volumeProfile, out T component) where T : VolumeComponent + { + if (volumeProfile == null) + { + component = null; + return; + } + + // Try to get the component of type T from the Volume Profile + if (!volumeProfile.TryGet(out component)) + { + Debug.Log($"{typeof(T).Name} component not found. Creating a new component."); + + // Add the component if it does not exist + volumeProfile.Add(true); + + // Try to get the component again + volumeProfile.TryGet(out component); + } + } +} diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Ray-Tracing-Getting-Started.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Ray-Tracing-Getting-Started.md index acd737dc55f..19bd8c84fc3 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/Ray-Tracing-Getting-Started.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/Ray-Tracing-Getting-Started.md @@ -209,6 +209,8 @@ HDRP ray tracing in Unity isn't compatible with the following features: - [Orthographic projection](hdrp-camera-component-reference.md). If you enable orthographic projection mode, you might experience rendering problems with transparent materials, volumetrics, and planar reflections. - Ray Traced and Screen Space effects. These don't appear recursively in [Ray Traced Reflections](Ray-Traced-Reflections.md), [Ray Traced Global Illumination](Ray-Traced-Global-Illumination.md) or [Recursive Ray Tracing](Ray-Tracing-Recursive-Rendering.md). This means, for example, you can't see [Screen Space Global Illumination](Override-Screen-Space-GI.md) in [ray-traced reflections](Ray-Traced-Reflections.md). - Fully accurate shadow culling. You might see missing shadows in ray-traced effects. You can use **Extend Shadow Culling** to improve accuracy. See [Ray Tracing Settings](Ray-Tracing-Settings.md) for more information. +- Data-Oriented Technology Stack (DOTS) +- Entity Component System (ECS) #### Reflection Probes diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/configure-a-project-using-the-hdrp-config-package.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/configure-a-project-using-the-hdrp-config-package.md index f19b7083099..4c9d66c59e3 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/configure-a-project-using-the-hdrp-config-package.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/configure-a-project-using-the-hdrp-config-package.md @@ -15,7 +15,7 @@ For example, you can use it to: To use the HDRP Config package in your HDRP Project, you need to create a local copy of it and make your Project's package manifest reference it. You can either do this manually or use the [HDRP Wizard](Render-Pipeline-Wizard.md). * **Manual**: In your Project's directory, move and rename the folder "**/Library/PackageCache/com.unity.render-pipelines.high-definition-config@[versionnumber]**" to "**/Packages/com.unity.render-pipelines.high-definition-config**". -* **HDRP Wizard**: Open the HDRP Wizard (**Windows > Rendering > HDRP Wizard**) and click the **Install Configuration Editable Package**. This creates a **LocalPackage** folder at the root of your Project and populates it with a compatible HDRP config package. +* **HDRP Wizard**: Open the HDRP Wizard (**Windows > Rendering > HDRP Wizard**) and click the **Embed Configuration Editable Package**. This creates a **LocalPackage** folder at the root of your Project and populates it with a compatible HDRP config package. **Note**: Using the Package Manager to upgrade your HDRP package does not automatically upgrade the local config package. To manually upgrade the local config package: diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/convert-from-built-in-convert-materials-and-shaders.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/convert-from-built-in-convert-materials-and-shaders.md index fd855704ad6..1be9d338547 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/convert-from-built-in-convert-materials-and-shaders.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/convert-from-built-in-convert-materials-and-shaders.md @@ -14,6 +14,7 @@ To upgrade the Materials in your Scene to HDRP-compatible Materials: The automatic upgrade options described above can't upgrade all Materials to HDRP correctly: * You can't automatically upgrade custom Materials or Shaders to HDRP. You must [convert custom Materials and Shaders manually](#ManualConversion). +* HDRP can only convert materials from the **Assets** folder of your project. HDRP uses the [error shader](xref:shader-error) for GameObjects that use the default read-only material from the Built-In Render Pipeline, for example [primitives](xref:um-primitive-objects). * Height mapped Materials might look incorrect. This is because HDRP supports more height map displacement techniques and decompression options than the Built-in Render Pipeline. To upgrade a Material that uses a heightmap, modify the Material's **Amplitude** and **Base** properties until the result more closely matches the Built-in Render Pipeline version. * You can't upgrade particle shaders. HDRP doesn't support particle shaders, but it does provide Shader Graphs that are compatible with the [Built-in Particle System](https://docs.unity3d.com/Manual/Built-inParticleSystem.html). These Shader Graphs work in a similar way to the built-in particle shaders. To use these Shader Graphs, import the **Particle System Shader Samples** sample: diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/custom-post-processing-dynamic-resolution-dlss.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/custom-post-processing-dynamic-resolution-dlss.md index b5ef01a2f7b..28ed1b6f885 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/custom-post-processing-dynamic-resolution-dlss.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/custom-post-processing-dynamic-resolution-dlss.md @@ -3,7 +3,7 @@ If you want to use DLSS or dynamic resolution with a custom post-processing pass, and need to interpolate or sample UVs from color, normal, or velocity, use the following functions to calculate the correct UVs: ```glsl -#include "Packages/com.unity.render-pipelines.high-dynamic/Runtime/ShaderLibrary/ShaderVariables.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" //... diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/dots-instancing-shaders-macros.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/dots-instancing-shaders-macros.md index a57bb62925f..59fcb9f6f61 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/dots-instancing-shaders-macros.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/dots-instancing-shaders-macros.md @@ -4,7 +4,7 @@ Unity provides the following access macros: | **Access macro** | **Description** | | ------------------------------------------------------------ | ------------------------------------------------------------ | -| `UNITY_ACCESS_DOTS_INSTANCED_PROP(PropertyType, PropertyName)` | Returns the value loaded from `unity_DOTSInstanceData` using the layout described above. Shaders that Unity provides use this version for DOTS Instanced built-in properties that don’t have a default value to fall back on. | +| `UNITY_ACCESS_DOTS_INSTANCED_PROP(PropertyType, PropertyName)` | Returns the value loaded from `unity_DOTSInstanceData`. Refer to [Declare DOTS Instancing properties in a custom shader](dots-instancing-shaders-declare) for more information. Shaders that Unity provides use this version for DOTS Instanced built-in properties that don’t have a default value to fall back on. | | `UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(PropertyType, PropertyName)` | Returns the same as `UNITY_ACCESS_DOTS_INSTANCED_PROP`, except if the most significant bit of the metadata value is zero, it returns a default value. The default value is the value of the regular material property with the same name as the DOTS Instanced property, which is why Shaders that Unity provides use the convention where DOTS Instanced properties have the same name as regular material properties. When using the default value, the access macro doesn't access `unity_DOTSInstanceData` at all. Shaders that Unity provides use this access macro for DOTS Instanced material properties, so the loads fall back to the value set on the material. | | `UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_CUSTOM_DEFAULT(PropertyType, PropertyName, DefaultValue)` | Returns the same as `UNITY_ACCESS_DOTS_INSTANCED_PROP` unless the most significant bit of the metadata value is zero, in which case this macroreturns `DefaultValue` instead, and doesn't access `unity_DOTSInstanceData`. | | `UNITY_DOTS_INSTANCED_METADATA_NAME(PropertyType, PropertyName)` | Returns the metadata value directly without accessing anything. This is useful for custom instance data loading schemes. | diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/reference-light-component.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/reference-light-component.md index eb941d397ac..099d5adb25b 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/reference-light-component.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/reference-light-component.md @@ -70,13 +70,15 @@ These settings define the area this Light affects. Each Light **Type** has its o #### Area Light -| **Property** | **Description** | -| ------------ | ------------------------------------------------------------ | -| **Shape** | HDRP Area Lights can use three shapes.
• **Rectangle** : Projects light from a rectangle shape at the GameObject’s position and orientation, in perpendicular direction, out to a certain **Range**.
• **Tube** : Projects light from a single line at the GameObject’s position in every direction, out to a certain **Range**. This shape is only for **Realtime Mode** at the moment.
• **Disc** : Projects light from a disc shape at the GameObject’s position and orientation, in perpendicular direction, out to a certain **Range**. This shape is only for **Baked Mode** at the moment. | -| **Size X** | For **Rectangle**. Defines the horizontal size of the Rectangle Light. | -| **Size Y** | For **Rectangle**. Defines the vertical size of the Rectangle Light. | -| **Length** | For **Tube**. Defines the length of the Tube Light. The center of the Light is the Transform Position and the Light itself extends out from the center symmetrically. The **Length** is the distance from one end of the tube to the other. | -| **Radius** | For **Disc**. Define the radius of the Disc Light. | +| **Property** | **Description** | +|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Shape** | HDRP Area Lights can use three shapes.
• **Rectangle** : Projects light from a rectangle shape at the GameObject’s position and orientation, perpendicularly, out to a certain **Range**.
• **Tube** : Projects light from a single line at the GameObject’s position in every direction, out to a certain **Range**. This shape is only for **Realtime Mode** at the moment.
• **Disc** : Projects light from a disc shape at the GameObject’s position and orientation, perpendicularly, out to a certain **Range**. This shape is only for **Baked Mode** at the moment. | +| **Size X** | For **Rectangle**. Defines the horizontal size of the Rectangle Light. | +| **Size Y** | For **Rectangle**. Defines the vertical size of the Rectangle Light. | +| **Barn Door Angle** | For **Rectangle**. Defines the angle of the barn door effect. The barn door shader option needs to be enabled in the render pipeline config package for this property to affect the light. You can install the config package by following the instructions in the [config package documentation](configure-a-project-using-the-hdrp-config-package.md). | +| **Barn Door Length** | For **Rectangle**. Defines the length of the barn door sides. The barn door shader option needs to be enabled in the render pipeline config package for this property to affect the light. You can install the config package by following the instructions in the [config package documentation](configure-a-project-using-the-hdrp-config-package.md). | +| **Length** | For **Tube**. Defines the length of the Tube Light. The center of the Light is the Transform Position and the Light itself extends out from the center symmetrically. The **Length** is the distance from one end of the tube to the other. | +| **Radius** | For **Disc**. Define the radius of the Disc Light. | diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/reference-screen-space-reflection.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/reference-screen-space-reflection.md index febbc9ce467..51359e00b8d 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/reference-screen-space-reflection.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/reference-screen-space-reflection.md @@ -2,6 +2,11 @@ [!include[](snippets/Volume-Override-Enable-Properties.md)] +For more information, refer to the following: + +- [Use the screen space reflection (SSR) override](override-screen-space-reflection.md) +- [Understand reflection in HDRP](reflection-understand.md) + ### Screen-space | **Property** | **Description** | diff --git a/Packages/com.unity.render-pipelines.high-definition/Documentation~/water-underwater-view.md b/Packages/com.unity.render-pipelines.high-definition/Documentation~/water-underwater-view.md index f00854334d4..15a2b1762af 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Documentation~/water-underwater-view.md +++ b/Packages/com.unity.render-pipelines.high-definition/Documentation~/water-underwater-view.md @@ -6,9 +6,21 @@ The underwater view is rendered as a full-screen post-processing effect. The vie * If volumetric fog is enabled, the underwater view is included in the volumetric buffer and rendered using volumetric lighting, supporting light shafts and light shafts from shadows. -To view non-infinite water surfaces from underwater, you have to specify a [collider](https://docs.unity3d.com/Manual/Glossary.html#Collider). You can either use the box collider HDRP automatically provides or select a box collider in the scene to use for this purpose. +## Define the underwater area -To view infinite water surfaces from underwater, you have to specify a **Volume Depth**. The **Volume Depth** property is only available in Ocean water body types, so this feature is limited to underwater views of infinite Ocean surfaces. +To change the area where the camera displays an underwater view for a non-infinite water surface, use the **Volume Bounds** setting. Follow these steps: + +1. Create a GameObject with a collider component, for example a cube with a **Box Collider** component. +2. Place the GameObject where you want the underwater view to be visible. +3. In the collider component, select **Edit Collider** to set the size of the visible underwater area. +4. Select the water GameObject. +5. In the **Inspector** window, under **Appearance**, under **Underwater**, set **Volume Bounds** to the GameObject you created. + +To set the area of the underwater view for an ocean, follow these steps: + +1. Select the ocean GameObject. +2. In the **Inspector** window, under **Appearance**, enable **Underwater**. +3. Adjust **Volume Depth**. # Water line diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/HDScreenSpaceReflectionEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/HDScreenSpaceReflectionEditor.cs index 06809f179be..d2d3258948f 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/HDScreenSpaceReflectionEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/HDScreenSpaceReflectionEditor.cs @@ -188,7 +188,7 @@ void RayTracedReflectionGUI(RayCastingMode tracingMode) { HDRenderPipelineAsset currentAsset = HDRenderPipeline.currentAsset; - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing, "RayTracing"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing); if (RenderPipelineManager.currentPipeline is not HDRenderPipeline { rayTracingSupported: true }) HDRenderPipelineUI.DisplayRayTracingSupportBox(); @@ -261,7 +261,7 @@ public override void OnInspectorGUI() PropertyField(m_Enable, k_EnabledOpaque); if (!notSupported) - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.SSR, "Screen Space Reflection"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.SSR); bool transparentSSRSupported = currentAsset.currentPlatformRenderPipelineSettings.supportSSR && currentAsset.currentPlatformRenderPipelineSettings.supportSSRTransparent @@ -269,7 +269,7 @@ public override void OnInspectorGUI() if (transparentSSRSupported) { PropertyField(m_EnableTransparent, k_EnabledTransparent); - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.TransparentSSR, "Transparent"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.TransparentSSR); } else { diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/ScreenSpaceRefractionEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/ScreenSpaceRefractionEditor.cs index 656826674c0..1764e5b5325 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/ScreenSpaceRefractionEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/ScreenSpaceRefractionEditor.cs @@ -17,7 +17,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Refraction, "Refraction"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Refraction); PropertyField(m_ScreenFadeDistance, k_ScreenFadeDistance); } diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/ScreenSpaceAmbientOcclusionEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/ScreenSpaceAmbientOcclusionEditor.cs index f79114ddb50..529f881118c 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/ScreenSpaceAmbientOcclusionEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/ScreenSpaceAmbientOcclusionEditor.cs @@ -101,7 +101,7 @@ private static class Styles public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.SSAO, "Screen Space Ambient Occlusion"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.SSAO); HDRenderPipelineAsset currentAsset = HDRenderPipeline.currentAsset; bool notSupported = currentAsset != null && !currentAsset.currentPlatformRenderPipelineSettings.supportSSAO; if (notSupported) @@ -118,7 +118,7 @@ public override void OnInspectorGUI() if (m_RayTracing.overrideState.boolValue && m_RayTracing.value.boolValue) { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing, "RayTracing"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing); // If ray tracing is supported display the content of the volume component if (RenderPipelineManager.currentPipeline is not HDRenderPipeline { rayTracingSupported: true }) HDRenderPipelineUI.DisplayRayTracingSupportBox(); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs index c18e5fd0442..aca2b43db85 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs @@ -40,7 +40,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.ContactShadows, "Contact Shadows"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.ContactShadows); PropertyField(m_Enable, EditorGUIUtility.TrTextContent("State", "When enabled, HDRP processes Contact Shadows for this Volume.")); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/HDShadowSettingsEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/HDShadowSettingsEditor.cs index 25f96f97601..68d02832c86 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/HDShadowSettingsEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/HDShadowSettingsEditor.cs @@ -45,7 +45,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.ShadowMaps, "Shadow Maps"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.ShadowMaps); PropertyField(m_MaxShadowDistance, EditorGUIUtility.TrTextContent("Max Distance", "In Meter")); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricClouds/VolumetricCloudsEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricClouds/VolumetricCloudsEditor.cs index b7d9ba1dd16..9dd5d931daf 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricClouds/VolumetricCloudsEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Lighting/VolumetricClouds/VolumetricCloudsEditor.cs @@ -523,7 +523,7 @@ public override void OnInspectorGUI() PropertyField(m_Enable, EditorGUIUtility.TrTextContent("State")); if (m_Enable.value.boolValue && !notSupported) - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.VolumetricClouds, "Volumetric Clouds"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.VolumetricClouds); EditorGUILayout.Space(); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Material/TerrainLit/TerrainLitGUI.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Material/TerrainLit/TerrainLitGUI.cs index 3995b330302..4d47228f8ab 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Material/TerrainLit/TerrainLitGUI.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Material/TerrainLit/TerrainLitGUI.cs @@ -98,7 +98,7 @@ protected void FindMaterialProperties(MaterialProperty[] props) heightTransition = prop; else if (prop.name == kEnableInstancedPerPixelNormal) enableInstancedPerPixelNormal = prop; - else if ((prop.flags & (MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData)) == 0) + else if ((prop.propertyFlags & (ShaderPropertyFlags.HideInInspector | ShaderPropertyFlags.PerRendererData)) == 0) customProperties.Add(prop); } } diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs index a6bff21b9c2..0c58027544e 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs @@ -39,7 +39,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Bloom, "Bloom"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Bloom); base.OnInspectorGUI(); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ChromaticAberrationEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ChromaticAberrationEditor.cs index eb057b82abf..f5ec875557c 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ChromaticAberrationEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ChromaticAberrationEditor.cs @@ -24,7 +24,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.ChromaticAberration, "Chromatic Aberration"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.ChromaticAberration); PropertyField(m_SpectralLUT); PropertyField(m_Intensity); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs index 1e8d19c6766..3165410858a 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs @@ -86,7 +86,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.DepthOfField, "Depth Of Field"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.DepthOfField); PropertyField(m_FocusMode, Styles.k_DepthOfFieldMode); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/FilmGrainEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/FilmGrainEditor.cs index d54b478d79a..edeec55e89d 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/FilmGrainEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/FilmGrainEditor.cs @@ -24,7 +24,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.FilmGrain, "Film Grain"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.FilmGrain); PropertyField(m_Type); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs index 648275afaf1..b7cc830db95 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs @@ -41,7 +41,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.MotionBlur, "Motion Blur"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.MotionBlur); PropertyField(m_Intensity); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/PaniniProjectionEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/PaniniProjectionEditor.cs index 85f32a97fc2..4424309d9c4 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/PaniniProjectionEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/PaniniProjectionEditor.cs @@ -22,7 +22,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.PaniniProjection, "Panini Projection"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.PaniniProjection); PropertyField(m_Distance); PropertyField(m_CropToFit); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ScreenSpaceLensFlareEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ScreenSpaceLensFlareEditor.cs index 141cccf671d..e7b9023d6ed 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ScreenSpaceLensFlareEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ScreenSpaceLensFlareEditor.cs @@ -78,18 +78,9 @@ public override void OnEnable() public override void OnInspectorGUI() { - // We loop through each camera and displaying a message if there's any bloom intensity = 0 preventing lens flare to render. - foreach (HDCamera hdCamera in HDEditorUtils.GetAllCameras()) - { - var bloomComponent = hdCamera.volumeStack.GetComponent(); - if (bloomComponent != null && !bloomComponent.IsActive()) - { - EditorGUILayout.HelpBox("One or more Bloom override has an intensity set to 0. This prevents Screen Space Lens Flare to render.", MessageType.Warning); - break; - } - } - - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.LensFlareScreenSpace, "Screen Space Lens Flare"); + // We loop through each camera and displaying a message if there's any bloom intensity = 0 preventing lens flare to render. + HDEditorUtils.EnsureVolume((Bloom bloom) => !bloom.IsActive() ? "One or more Bloom override has an intensity set to 0. This prevents Screen Space Lens Flare to render." : null); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.LensFlareScreenSpace); if (!HDRenderPipeline.currentAsset?.currentPlatformRenderPipelineSettings.supportScreenSpaceLensFlare ?? false) { diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/TonemappingEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/TonemappingEditor.cs index 6ce8e473334..8ca9b7c030a 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/TonemappingEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/TonemappingEditor.cs @@ -85,7 +85,7 @@ internal bool HDROutputIsActive() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Tonemapping, "Tonemapping"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Tonemapping); bool hdrInPlayerSettings = UnityEditor.PlayerSettings.allowHDRDisplaySupport; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/VignetteEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/VignetteEditor.cs index eac7d7e3805..970dd53fd5d 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/VignetteEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/PostProcessing/VignetteEditor.cs @@ -39,7 +39,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Vignette, "Vignette"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Vignette); PropertyField(m_Mode); PropertyField(m_Color); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDEditorUtils.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDEditorUtils.cs index 9d2f7122f9e..d0162da14c9 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDEditorUtils.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDEditorUtils.cs @@ -321,7 +321,7 @@ static bool DataDrivenLensFlareHelpBox() return false; } - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.LensFlareDataDriven, "Lens Flare Data Driven"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.LensFlareDataDriven); return true; } @@ -336,76 +336,76 @@ static void OpenRenderingDebugger(string panelName) } } - static void HighlightInDebugger(HDCamera hdCamera, FrameSettingsField field, string displayName) + static void HighlightInDebugger(Camera camera, FrameSettingsField field, string displayName) { - OpenRenderingDebugger(hdCamera.camera.name); + OpenRenderingDebugger(camera.name); // Doesn't work for some reason //CoreEditorUtils.Highlight("Rendering Debugger", displayName, HighlightSearchMode.Auto); //GUIUtility.ExitGUI(); } - internal static void FrameSettingsHelpBox(HDCamera hdCamera, FrameSettingsField field, string displayName) + static IEnumerable GetAllCameras() { - var data = HDUtils.TryGetAdditionalCameraDataOrDefault(hdCamera.camera); - var defaults = GraphicsSettings.GetRenderPipelineSettings().GetDefaultFrameSettings(FrameSettingsRenderType.Camera); - - var type = MessageType.Warning; - var attribute = FrameSettingsExtractedDatas.GetFieldAttribute(field); - - bool disabledInGlobal = !defaults.IsEnabled(field); - bool disabledByCamera = data.renderingPathCustomFrameSettingsOverrideMask.mask[(uint)field] && - !data.renderingPathCustomFrameSettings.IsEnabled(field); - bool disabledByDependency = !attribute.dependencies.All(hdCamera.frameSettings.IsEnabled); - - var historyContainer = hdCamera.camera.cameraType == CameraType.SceneView - ? FrameSettingsHistory.sceneViewFrameSettingsContainer - : HDUtils.TryGetAdditionalCameraDataOrDefault(hdCamera.camera); - bool disabledByDebug = FrameSettingsHistory.enabled && !historyContainer.frameSettingsHistory.debug.IsEnabled(field) && historyContainer.frameSettingsHistory.sanitazed.IsEnabled(field); - - var textBase = $"The FrameSetting required to render this effect in the {(hdCamera.camera.cameraType == CameraType.SceneView ? "Scene" : "Game")} view "; - - if (disabledByDebug) - CoreEditorUtils.DrawFixMeBox(textBase + "is disabled in the Rendering Debugger.", type, "Open", () => HighlightInDebugger(hdCamera, field, displayName)); - else if (disabledByCamera) - CoreEditorUtils.DrawFixMeBox(textBase + "is disabled on a Camera.", type, "Open", () => EditorUtility.OpenPropertyEditor(hdCamera.camera)); - else if (disabledInGlobal) - GlobalSettingsHelpBox(textBase + "is disabled in the HDRP Global Settings.", type, field, displayName); - else if (disabledByDependency) - GlobalSettingsHelpBox(textBase + "depends on a disabled FrameSetting.", type, field, displayName); + foreach (SceneView sceneView in SceneView.sceneViews) + yield return sceneView.camera; + foreach (Camera camera in Camera.allCameras) + if (camera.cameraType == CameraType.Game) + yield return camera; } - - internal static HDCamera[] GetAllCameras() + + static IEnumerable<(Camera camera, FrameSettings @default, IFrameSettingsHistoryContainer historyContainer)> SelectFrameSettingsStages(IEnumerable cameras) { - HashSet cameras = new(); + var supportedFeatures = HDRenderPipeline.currentAsset.currentPlatformRenderPipelineSettings; + var defaultSettings = GraphicsSettings.GetRenderPipelineSettings().GetDefaultFrameSettings(FrameSettingsRenderType.Camera); - // Looping through all the scene views - foreach (SceneView sceneView in SceneView.sceneViews) + foreach (var camera in cameras) { - if (!sceneView.hasFocus) continue; - cameras.Add(HDCamera.GetOrCreate(sceneView.camera)); + var additionalCameraData = HDUtils.TryGetAdditionalCameraDataOrDefault(camera); + var historyContainer = camera.cameraType == CameraType.SceneView ? FrameSettingsHistory.sceneViewFrameSettingsContainer : additionalCameraData; + + FrameSettings dummy = default; + FrameSettingsHistory.AggregateFrameSettings(ref dummy, camera, historyContainer, ref defaultSettings, supportedFeatures); + yield return (camera, defaultSettings, historyContainer); } + } + + static void FrameSettingsHelpBox(Camera camera, FrameSettingsField field, FrameSettings @default, IFrameSettingsHistoryContainer historyContainer) + { + FrameSettingsHistory history = historyContainer.frameSettingsHistory; + bool finalValue = history.debug.IsEnabled(field); + if (finalValue) return; //must be false to call this method - // Looping through all the game views - foreach (var camera in HDCamera.GetHDCameras()) - { - if (camera == null || camera.camera == null) - continue; + bool defaultValue = @default.IsEnabled(field); + bool cameraOverrideState = historyContainer.hasCustomFrameSettings && history.customMask.mask[(uint)field]; + bool cameraOverridenValue = history.overridden.IsEnabled(field); + bool cameraSanitizedValue = history.sanitazed.IsEnabled(field); - if (camera.camera.cameraType == CameraType.Game) - cameras.Add(camera); - } + var attribute = FrameSettingsExtractedDatas.GetFieldAttribute(field); + bool dependenciesSanitizedValueOk = attribute.dependencies.All(fs => attribute.IsNegativeDependency(fs) ? !history.sanitazed.IsEnabled(fs) : history.sanitazed.IsEnabled(fs)); + + bool disabledByDefault = !defaultValue && !cameraOverrideState; + bool disabledByCameraOverride = cameraOverrideState && !cameraOverridenValue; - return cameras.ToArray(); + var textBase = $"The FrameSetting required to render this effect in the {(camera.cameraType == CameraType.SceneView ? "Scene" : "Game")} view (by {camera.name}) "; + + if (disabledByDefault) + GlobalSettingsHelpBox(textBase + "is disabled in the HDRP Global Settings.", MessageType.Warning, field, attribute.displayedName); + else if (disabledByCameraOverride) + CoreEditorUtils.DrawFixMeBox(textBase + $"is disabled on the Camera.", MessageType.Warning, "Open", () => EditorUtility.OpenPropertyEditor(camera)); + else if (!dependenciesSanitizedValueOk) + GlobalSettingsHelpBox(textBase + "depends on a disabled FrameSetting.", MessageType.Warning, field, attribute.displayedName); + else if (!finalValue) + CoreEditorUtils.DrawFixMeBox(textBase + "is disabled in the Rendering Debugger.", MessageType.Warning, "Open", () => HighlightInDebugger(camera, field, attribute.displayedName)); } - internal static bool EnsureFrameSetting(FrameSettingsField field, string displayName) + internal static bool EnsureFrameSetting(FrameSettingsField field) { - foreach (var camera in GetAllCameras()) + foreach ((Camera camera, FrameSettings @default, IFrameSettingsHistoryContainer historyContainer) in SelectFrameSettingsStages(GetAllCameras())) { - if (!camera.frameSettings.IsEnabled(field)) + if (!historyContainer.frameSettingsHistory.debug.IsEnabled(field)) { - FrameSettingsHelpBox(camera, field, displayName); + FrameSettingsHelpBox(camera, field, @default, historyContainer); EditorGUILayout.Space(); return false; } @@ -413,31 +413,34 @@ internal static bool EnsureFrameSetting(FrameSettingsField field, string display return true; } - - internal static bool EnsureVolumeAndFrameSetting(Func volumeValidator, FrameSettingsField field, string displayName) where T : UnityEngine.Rendering.VolumeComponent + + static IEnumerable<(Camera camera, T component)> SelectVolumeComponent(IEnumerable cameras) where T : VolumeComponent { // Wait for volume system to be initialized if (VolumeManager.instance.baseComponentTypeArray == null) - return true; - - var cameras = GetAllCameras(); + yield break; - foreach (var camera in cameras) + foreach (var camera in GetAllCameras()) { - var errorString = volumeValidator(camera.volumeStack.GetComponent()); - if (!string.IsNullOrEmpty(errorString)) - { - EditorGUILayout.HelpBox(errorString, MessageType.Warning); - EditorGUILayout.Space(); - return false; - } + if (!HDCamera.TryGet(camera, out var hdCamera)) + continue; + + T component = hdCamera.volumeStack.GetComponent(); + if (component == null) + continue; + + yield return (camera, component); } + } - foreach (var camera in cameras) + internal static bool EnsureVolume(Func volumeValidator) where T : VolumeComponent + { + foreach ((Camera camera, T component) in SelectVolumeComponent(GetAllCameras())) { - if (!camera.frameSettings.IsEnabled(field)) + var errorString = volumeValidator(component); + if (!string.IsNullOrEmpty(errorString)) { - FrameSettingsHelpBox(camera, field, displayName); + EditorGUILayout.HelpBox(errorString, MessageType.Warning); EditorGUILayout.Space(); return false; } diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs index 528130a568b..b2a8067c37f 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.Skin.cs @@ -354,8 +354,8 @@ public class Styles public static readonly GUIContent volumeProfileLabel = EditorGUIUtility.TrTextContent("Volume Profile", "Settings that will override the values defined in the Default Volume Profile set in the Render Pipeline Global settings. Local Volumes inside scenes may override these settings further."); public static System.Lazy volumeProfileContextMenuStyle = new(() => new GUIStyle(CoreEditorStyles.contextMenuStyle) { margin = new RectOffset(0, 1, 3, 0) }); - public static readonly GUIContent[] shadowBitDepthNames = { new GUIContent("32 bit"), new GUIContent("16 bit") }; - public static readonly int[] shadowBitDepthValues = { (int)DepthBits.Depth32, (int)DepthBits.Depth16 }; + public static readonly GUIContent[] shadowBitDepthNames = { new GUIContent("32 bit"), new GUIContent("16 bit"), new GUIContent("24 bit") }; + public static readonly int[] shadowBitDepthValues = { (int)DepthBits.Depth32, (int)DepthBits.Depth16, (int)DepthBits.Depth24 }; public static readonly GUIContent gpuResidentDrawerMode = EditorGUIUtility.TrTextContent("GPU Resident Drawer", "Enables draw submission through the GPU Resident Drawer, which can improve CPU performance"); public static readonly GUIContent smallMeshScreenPercentage = EditorGUIUtility.TrTextContent("Small-Mesh Screen-Percentage", "Default minimum screen percentage (0-20%) gpu-driven Renderers can cover before getting culled. If a Renderer is part of a LODGroup, this will be ignored."); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/LineRendering/HDRenderPipeline.LineRendering.VolumeComponentEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/LineRendering/HDRenderPipeline.LineRendering.VolumeComponentEditor.cs index 9557052ba7f..f7589519388 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/LineRendering/HDRenderPipeline.LineRendering.VolumeComponentEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/LineRendering/HDRenderPipeline.LineRendering.VolumeComponentEditor.cs @@ -30,7 +30,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.HighQualityLineRendering, "High Quality Line Rendering"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.HighQualityLineRendering); HDRenderPipelineAsset currentAsset = HDRenderPipeline.currentAsset; bool notSupported = currentAsset != null && !currentAsset.currentPlatformRenderPipelineSettings.supportHighQualityLineRendering; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/PathTracing/PathTracingEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/PathTracing/PathTracingEditor.cs index d6f8e2494df..6dfee7b980c 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/PathTracing/PathTracingEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/PathTracing/PathTracingEditor.cs @@ -58,7 +58,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing, "Path tracing"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing); HDRenderPipelineAsset currentAsset = HDRenderPipeline.currentAsset; bool notSupported = currentAsset != null && !currentAsset.currentPlatformRenderPipelineSettings.supportRayTracing; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/GlobalIlluminationEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/GlobalIlluminationEditor.cs index 2a519601b93..12a4573e6c6 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/GlobalIlluminationEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/GlobalIlluminationEditor.cs @@ -167,7 +167,7 @@ void RayTracingQualityModeGUI() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.SSGI, "Screen Space Global Illumination"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.SSGI); HDRenderPipelineAsset currentAsset = HDRenderPipeline.currentAsset; bool notSupported = !currentAsset?.currentPlatformRenderPipelineSettings.supportSSGI ?? false; @@ -197,7 +197,7 @@ public override void OnInspectorGUI() { if (rayTracingSettingsDisplayed) { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing, "RayTracing"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing); if (RenderPipelineManager.currentPipeline is not HDRenderPipeline { rayTracingSupported: true }) HDRenderPipelineUI.DisplayRayTracingSupportBox(); diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/LightClusterEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/LightClusterEditor.cs index 68c5333cf2d..db48e44a337 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/LightClusterEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/LightClusterEditor.cs @@ -10,7 +10,7 @@ class LightClusterEditor : VolumeComponentEditor { public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing, "Raytracing"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing); HDRenderPipelineAsset currentAsset = HDRenderPipeline.currentAsset; bool notSupported = currentAsset != null && !currentAsset.currentPlatformRenderPipelineSettings.supportRayTracing; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/RayTracingSettingsEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/RayTracingSettingsEditor.cs index 8538075a55c..1ad4ed61aeb 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/RayTracingSettingsEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/RayTracingSettingsEditor.cs @@ -40,7 +40,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing, "Raytracing"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing); HDRenderPipelineAsset currentAsset = HDRenderPipeline.currentAsset; bool notSupported = currentAsset != null && !currentAsset.currentPlatformRenderPipelineSettings.supportRayTracing; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/RecursiveRenderingEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/RecursiveRenderingEditor.cs index 476e16a576d..a1235987836 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/RecursiveRenderingEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/RecursiveRenderingEditor.cs @@ -37,7 +37,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing, "Raytracing"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing); HDRenderPipelineAsset currentAsset = HDRenderPipeline.currentAsset; bool notSupported = currentAsset != null && !currentAsset.currentPlatformRenderPipelineSettings.supportRayTracing; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/SubSurfaceScatteringEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/SubSurfaceScatteringEditor.cs index ce2b3974e8f..88e690d4bbc 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/SubSurfaceScatteringEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/SubSurfaceScatteringEditor.cs @@ -20,7 +20,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing, "Raytracing"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.RayTracing); HDRenderPipelineAsset currentAsset = HDRenderPipeline.currentAsset; bool notSupported = currentAsset != null && !currentAsset.currentPlatformRenderPipelineSettings.supportRayTracing; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs index f0ac7f77513..8f4a2a826f0 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs @@ -82,7 +82,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.AtmosphericScattering, "Fog"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.AtmosphericScattering); PropertyField(m_Enabled, s_Enabled); @@ -124,7 +124,7 @@ public override void OnInspectorGUI() { PropertyField(m_EnableVolumetricFog, s_EnableVolumetricFog); - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Volumetrics, "Volumetric Fog"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Volumetrics); using (new IndentLevelScope()) { diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Sky/HDLightingWindowEnvironmentSection.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Sky/HDLightingWindowEnvironmentSection.cs index 3a38e9109e0..64a0878a82a 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Sky/HDLightingWindowEnvironmentSection.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Sky/HDLightingWindowEnvironmentSection.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; namespace UnityEditor.Rendering.HighDefinition { @@ -16,16 +17,7 @@ class HDLightingWindowEnvironmentSectionEditor : LightingWindowEnvironmentSectio { class Styles { - public static GUIStyle headerStyle; - static Styles() - { - headerStyle = new GUIStyle(EditorStyles.foldoutHeader); - headerStyle.fontStyle = FontStyle.Bold; - headerStyle.fontSize = 12; - headerStyle.margin = new RectOffset(17, 0, 0, 0); - headerStyle.padding = new RectOffset(16, 1, 0, 0); - headerStyle.fixedHeight = 21; - } + public static readonly GUIStyle inspectorTitle = "IN Title"; } class SerializedStaticLightingSky @@ -81,6 +73,8 @@ bool toggleValue } } + static MethodInfo k_FoldoutTitlebar; + public override void OnEnable() { m_SerializedActiveSceneLightingSky = new SerializedStaticLightingSky(GetStaticLightingSkyForScene(EditorSceneManager.GetActiveScene())); @@ -151,35 +145,20 @@ public override void OnInspectorGUI() void DrawGUI() { - Rect mainSeparator = EditorGUILayout.GetControlRect(GUILayout.Height(1)); - mainSeparator.xMin -= 3; - mainSeparator.xMax += 4; - EditorGUI.DrawRect(mainSeparator, EditorGUIUtility.isProSkin - ? new Color32(26, 26, 26, 255) - : new Color32(127, 127, 127, 255)); - - Rect line = EditorGUILayout.GetControlRect(); - line.xMin -= 3; - line.xMax += 4; - line.y -= 2; - line.yMax += 4; + if (k_FoldoutTitlebar == null) + { + var flags = BindingFlags.NonPublic | BindingFlags.Static; + Type[] args = new Type[] { typeof(Rect), typeof(GUIContent), typeof(bool), typeof(bool) }; + k_FoldoutTitlebar = typeof(EditorGUI).GetMethod("FoldoutTitlebar", flags, null, args, null); + } - toggleValue = EditorGUI.Foldout(line, toggleValue, EditorGUIUtility.TrTextContent("Environment (HDRP)", "Sky lighting environment for active Scene"), Styles.headerStyle); + var labelRect = GUILayoutUtility.GetRect(GUIContent.none, Styles.inspectorTitle, GUILayout.ExpandWidth(true)); + var label = EditorGUIUtility.TrTextContent("Environment (HDRP)", "Sky lighting environment for active Scene"); - EditorGUI.DrawRect(line, EditorGUIUtility.isProSkin - ? new Color(1f, 1f, 1f, 0.03f) - : new Color(1f, 1f, 1f, 0.2f)); + toggleValue = (bool)k_FoldoutTitlebar.Invoke(null, new object[] { labelRect, label, toggleValue, true }); if (m_ToggleValue) { - Rect separator = EditorGUILayout.GetControlRect(GUILayout.Height(1)); - separator.xMin -= 3; - separator.xMax += 4; - separator.y -= 1; - EditorGUI.DrawRect(separator, EditorGUIUtility.isProSkin - ? new Color32(48, 48, 48, 255) - : new Color32(186, 186, 186, 255)); - ++EditorGUI.indentLevel; //cannot use SerializeProperty due to logic in the property diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/VFXGraph/Outputs/VFXDecalHDRPOutput.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/VFXGraph/Outputs/VFXDecalHDRPOutput.cs index da95e5c8d98..52bbfcfc175 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/VFXGraph/Outputs/VFXDecalHDRPOutput.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/VFXGraph/Outputs/VFXDecalHDRPOutput.cs @@ -260,7 +260,7 @@ public override IEnumerable additionalDefines yield return "AFFECT_AMBIENT_OCCLUSION"; if (affectSmoothness) yield return "AFFECT_SMOOTHNESS"; - if (useEmissiveColor || useEmissiveMap) + if (useEmissiveColor || useEmissiveMap || (colorMode & ColorMode.Emissive) != 0) yield return "NEEDS_FORWARD_EMISSIVE_PASS"; } } diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Water/WaterRenderingEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Water/WaterRenderingEditor.cs index 46b468e3702..6852e8092b8 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Water/WaterRenderingEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Water/WaterRenderingEditor.cs @@ -33,7 +33,7 @@ public override void OnEnable() public override void OnInspectorGUI() { - HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Water, "Water"); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Water); HDRenderPipelineAsset currentAsset = HDRenderPipeline.currentAsset; bool notSupported = currentAsset != null && !currentAsset.currentPlatformRenderPipelineSettings.supportWater; if (notSupported) diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Water/WaterSurface/WaterSurfaceEditor.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Water/WaterSurface/WaterSurfaceEditor.cs index c1862aa4d30..d1425cbfb30 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Water/WaterSurface/WaterSurfaceEditor.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Water/WaterSurface/WaterSurfaceEditor.cs @@ -292,8 +292,8 @@ public override void OnInspectorGUI() return; } - Func validator = (water) => !water.enable.value ? "Water Surface Rendering is not enabled in the Volume System." : null; - HDEditorUtils.EnsureVolumeAndFrameSetting(validator, FrameSettingsField.Water, "Water"); + HDEditorUtils.EnsureVolume((WaterRendering water) => !water.enable.value ? "Water Surface Rendering is not enabled in the Volume System." : null); + HDEditorUtils.EnsureFrameSetting(FrameSettingsField.Water); if (target is WaterSurface surface && surface.surfaceIndex == -1) { diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Wizard/HDWizard.Configuration.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Wizard/HDWizard.Configuration.cs index 494b89b572e..94db4490e1e 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Wizard/HDWizard.Configuration.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Wizard/HDWizard.Configuration.cs @@ -24,6 +24,13 @@ enum InclusiveMode enum QualityScope { Global, CurrentQuality } + enum Result + { + Failed, + OK, + Pending, + } + static class InclusiveScopeExtention { public static bool Contains(this InclusiveMode thisScope, InclusiveMode scope) @@ -109,14 +116,14 @@ struct Entry public readonly QualityScope scope; public readonly InclusiveMode inclusiveScope; public readonly Style.ConfigStyle configStyle; - public readonly Func check; + public readonly Func check; public readonly Action fix; public readonly int indent; public readonly bool forceDisplayCheck; public readonly bool skipErrorIcon; public readonly bool displayAssetName; - public Entry(QualityScope scope, InclusiveMode mode, Style.ConfigStyle configStyle, Func check, + public Entry(QualityScope scope, InclusiveMode mode, Style.ConfigStyle configStyle, Func check, Action fix, int indent = 0, bool forceDisplayCheck = false, bool skipErrorIcon = false, bool displayAssetName = false) { this.scope = scope; @@ -125,7 +132,21 @@ public Entry(QualityScope scope, InclusiveMode mode, Style.ConfigStyle configSty this.check = check; this.fix = fix; this.forceDisplayCheck = forceDisplayCheck; - this.indent = mode == InclusiveMode.XRManagement ? 1 : indent; + this.indent = indent; + this.skipErrorIcon = skipErrorIcon; + this.displayAssetName = displayAssetName; + } + + public Entry(QualityScope scope, InclusiveMode mode, Style.ConfigStyle configStyle, Func check, + Action fix, int indent = 0, bool forceDisplayCheck = false, bool skipErrorIcon = false, bool displayAssetName = false) + { + this.scope = scope; + this.inclusiveScope = mode; + this.configStyle = configStyle; + this.check = () => check() ? Result.OK : Result.Failed; + this.fix = fix; + this.forceDisplayCheck = forceDisplayCheck; + this.indent = indent; this.skipErrorIcon = skipErrorIcon; this.displayAssetName = displayAssetName; } @@ -177,8 +198,8 @@ Entry[] BuildEntryList() new Entry(QualityScope.Global, InclusiveMode.HDRP, Style.hdrpShadowmask, IsShadowmaskCorrect, FixShadowmask), new Entry(QualityScope.Global, InclusiveMode.HDRP, Style.hdrpMigratableAssets, IsMigratableAssetsCorrect, FixMigratableAssets), new Entry(QualityScope.Global, InclusiveMode.VR, Style.vrXRManagementPackage, IsVRXRManagementPackageInstalledCorrect, FixVRXRManagementPackageInstalled), - new Entry(QualityScope.Global, InclusiveMode.XRManagement, Style.vrOculusPlugin, () => false, null), - new Entry(QualityScope.Global, InclusiveMode.XRManagement, Style.vrSinglePassInstancing, () => false, null), + new Entry(QualityScope.Global, InclusiveMode.XRManagement, Style.vrOculusPlugin, () => false, null, indent: 1), + new Entry(QualityScope.Global, InclusiveMode.XRManagement, Style.vrSinglePassInstancing, () => false, null, indent: 1), new Entry(QualityScope.Global, InclusiveMode.VR, Style.vrLegacyHelpersPackage, IsVRLegacyHelpersCorrect, FixVRLegacyHelpers), new Entry(QualityScope.CurrentQuality, InclusiveMode.HDRP, Style.hdrpAssetQualityAssigned, IsHdrpAssetQualityUsedCorrect, FixHdrpAssetQualityUsed), new Entry(QualityScope.CurrentQuality, InclusiveMode.HDRP, Style.hdrpBatcher, IsSRPBatcherCorrect, FixSRPBatcher), @@ -255,7 +276,7 @@ bool IsAFixAvailableInScope(InclusiveMode scope) { if (!scope.Contains(e.inclusiveScope) || e.check == null || e.fix == null) continue; - if (!e.check()) + if (e.check() == Result.Failed) return false; } @@ -272,7 +293,7 @@ void FixAllEntryInScope(InclusiveMode scope) m_Fixer.Add(() => { - if (!e.check()) + if (e.check() == Result.Failed) e.fix(true); }); } @@ -621,13 +642,14 @@ void FixMigratableAssets(bool fromAsyncUnused) #region HDRP_VR_FIXES - bool vrXRManagementInstalledCheck = false; - bool IsVRXRManagementPackageInstalledCorrect() + Result m_vrXRManagementInstalledCheck = Result.Pending; + Result IsVRXRManagementPackageInstalledCorrect() => m_vrXRManagementInstalledCheck; + void UpdateVRXRManagementInstalledCheck() { + m_vrXRManagementInstalledCheck = Result.Pending; m_UsedPackageRetriever.ProcessAsync( k_XRanagementPackageName, - (installed, info) => vrXRManagementInstalledCheck = installed); - return vrXRManagementInstalledCheck; + (installed, info) => m_vrXRManagementInstalledCheck = installed ? Result.OK : Result.Failed); } void FixVRXRManagementPackageInstalled(bool fromAsync) @@ -637,13 +659,14 @@ void FixVRXRManagementPackageInstalled(bool fromAsync) m_PackageInstaller.ProcessAsync(k_XRanagementPackageName, null); } - bool vrLegacyHelpersInstalledCheck = false; - bool IsVRLegacyHelpersCorrect() + Result m_vrLegacyHelpersInstalledCheck = Result.Pending; + Result IsVRLegacyHelpersCorrect() => m_vrLegacyHelpersInstalledCheck; + void UpdateVRLegacyHelpersInstalledCheck() { + m_vrLegacyHelpersInstalledCheck = Result.Pending; m_UsedPackageRetriever.ProcessAsync( k_LegacyInputHelpersPackageName, - (installed, info) => vrLegacyHelpersInstalledCheck = installed); - return vrLegacyHelpersInstalledCheck; + (installed, info) => m_vrLegacyHelpersInstalledCheck = installed ? Result.OK : Result.Failed); } void FixVRLegacyHelpers(bool fromAsync) @@ -926,26 +949,25 @@ void EmbedConfigPackage(bool installed, string name, Action onCompletion) void InstallLocalConfigurationPackage(Action onCompletion) { m_UsedPackageRetriever.ProcessAsync( - k_HdrpConfigPackageName, - (installed, info) => - { - // Embedding a package requires it to be an explicit direct dependency in the manifest. - // If it's not, we add it first. - if (!info.isDirectDependency) + k_HdrpConfigPackageName, + (installed, info) => { - m_PackageInstaller.ProcessAsync(k_HdrpConfigPackageName, () => m_UsedPackageRetriever.ProcessAsync( - k_HdrpConfigPackageName, - (installed, info) => - { - EmbedConfigPackage(installed, info.name, onCompletion); - - })); - } - else - { - EmbedConfigPackage(installed, info.name, onCompletion); - } - }); + // Embedding a package requires it to be an explicit direct dependency in the manifest. + // If it's not, we add it first. + if (!info.isDirectDependency) + { + m_PackageInstaller.ProcessAsync(k_HdrpConfigPackageName, () => m_UsedPackageRetriever.ProcessAsync( + k_HdrpConfigPackageName, + (installed, info) => + { + EmbedConfigPackage(installed, info.name, onCompletion); + })); + } + else + { + EmbedConfigPackage(installed, info.name, onCompletion); + } + }); } @@ -963,6 +985,16 @@ void RefreshDisplayOfConfigPackageArea() IsLocalConfigurationPackageEmbeddedAsync(present => UpdateDisplayOfConfigPackageArea(present ? ConfigPackageState.Present : ConfigPackageState.Missing)); } + static void CheckPackages(PackageRegistrationEventArgs args) + { + if (EditorWindow.HasOpenInstances() && !EditorApplication.isPlayingOrWillChangePlaymode) + { + HDWizard window = EditorWindow.GetWindow(Style.title.text); + window.UpdateVRXRManagementInstalledCheck(); + window.UpdateVRLegacyHelpersInstalledCheck(); + } + } + class UsedPackageRetriever { PackageManager.Requests.ListRequest m_CurrentRequest; diff --git a/Packages/com.unity.render-pipelines.high-definition/Editor/Wizard/HDWizard.UIElement.cs b/Packages/com.unity.render-pipelines.high-definition/Editor/Wizard/HDWizard.UIElement.cs index d6c6d116d21..a4cab89d5fa 100644 --- a/Packages/com.unity.render-pipelines.high-definition/Editor/Wizard/HDWizard.UIElement.cs +++ b/Packages/com.unity.render-pipelines.high-definition/Editor/Wizard/HDWizard.UIElement.cs @@ -169,11 +169,11 @@ void CreateOrLoad(Action onCancel, Action onObjectChanged) abstract class VisualElementUpdatable : VisualElement { - protected Func m_Tester; + protected Func m_Tester; bool m_HaveFixer; - public bool currentStatus { get; private set; } + public Result currentStatus { get; private set; } - protected VisualElementUpdatable(Func tester, bool haveFixer) + protected VisualElementUpdatable(Func tester, bool haveFixer) { m_Tester = tester; m_HaveFixer = haveFixer; @@ -181,7 +181,7 @@ protected VisualElementUpdatable(Func tester, bool haveFixer) public virtual void CheckUpdate() { - bool wellConfigured = m_Tester(); + var wellConfigured = m_Tester(); if (wellConfigured != currentStatus) currentStatus = wellConfigured; @@ -190,27 +190,7 @@ public virtual void CheckUpdate() public void Init() => UpdateDisplay(currentStatus, m_HaveFixer); - public abstract void UpdateDisplay(bool statusOK, bool haveFixer); - } - - class HiddableUpdatableContainer : VisualElementUpdatable - { - public HiddableUpdatableContainer(Func tester, bool haveFixer = false) : base(tester, haveFixer) { } - - public override void CheckUpdate() - { - base.CheckUpdate(); - if (currentStatus) - { - foreach (VisualElementUpdatable updatable in Children().Where(e => e is VisualElementUpdatable)) - updatable.CheckUpdate(); - } - } - - new public void Init() => base.Init(); - - public override void UpdateDisplay(bool visible, bool haveFixer) - => style.display = visible ? DisplayStyle.Flex : DisplayStyle.None; + public abstract void UpdateDisplay(Result status, bool haveFixer); } class ConfigInfoLine : VisualElementUpdatable @@ -224,6 +204,7 @@ static class Style readonly bool m_SkipErrorIcon; private Image m_StatusOk; private Image m_StatusKO; + private Image m_StatusPending; private Button m_Resolver; private HelpBox m_HelpBox; public ConfigInfoLine(Entry entry) @@ -232,7 +213,7 @@ public ConfigInfoLine(Entry entry) m_VisibleStatus = entry.configStyle.messageType == MessageType.Error || entry.forceDisplayCheck; m_SkipErrorIcon = entry.skipErrorIcon; - var testLabel = new UnityEngine.UIElements.Label(entry.configStyle.label) + var testLabel = new Label(entry.configStyle.label) { name = "TestLabel", style = @@ -271,8 +252,19 @@ public ConfigInfoLine(Entry entry) width = 16 } }; + m_StatusPending = new Image() + { + image = CoreEditorStyles.iconPending, + name = "StatusPending", + style = + { + height = 16, + width = 16 + } + }; testRow.Add(m_StatusOk); testRow.Add(m_StatusKO); + testRow.Add(m_StatusPending); Add(testRow); var kind = entry.configStyle.messageType switch @@ -293,7 +285,7 @@ public ConfigInfoLine(Entry entry) } m_HelpBox = new HelpBox(error, kind); - m_HelpBox.Q().style.flexGrow = 1; + m_HelpBox.Q