Files
2026-11-01 23:39:55 +02:00

445 lines
16 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.ProjectWindowCallback;
using ShaderKeywordFilter = UnityEditor.ShaderKeywordFilter;
#endif
using System;
using UnityEngine.Scripting.APIUpdating;
using UnityEngine.Assertions;
using UnityEngine.Experimental.Rendering;
namespace UnityEngine.Rendering.Universal
{
/// <summary>
/// Defines if Unity will copy the depth that can be bound in shaders as _CameraDepthTexture after the opaques pass or after the transparents pass.
/// </summary>
public enum CopyDepthMode
{
/// <summary>Depth will be copied after the opaques pass</summary>
AfterOpaques,
/// <summary>Depth will be copied after the transparents pass</summary>
AfterTransparents,
/// <summary>Depth will be written by a depth prepass</summary>
ForcePrepass
}
/// <summary>
/// Render path exposed as flags to allow compatibility to be expressed with multiple options.
/// </summary>
[Flags]
public enum RenderPathCompatibility
{
/// <summary>Forward Rendering Path</summary>
Forward = 1 << 0,
/// <summary>Deferred Rendering Path</summary>
Deferred = 1 << 1,
/// <summary>Forward+ Rendering Path</summary>
ForwardPlus = 1 << 2,
/// <summary>Forward+ Rendering Path</summary>
DeferredPlus = 1 << 3,
/// <summary>All Rendering Paths</summary>
All = Forward | Deferred | ForwardPlus | DeferredPlus
}
[AttributeUsage(AttributeTargets.Field)]
sealed class RenderPathCompatibleAttribute : Attribute
{
public RenderPathCompatibility renderPath;
public RenderPathCompatibleAttribute(RenderPathCompatibility renderPath)
{
this.renderPath = renderPath;
}
}
/// <summary>
/// Dept format options for the depth texture and depth attachment.
/// Each option is marked with all the render paths its compatible with.
/// </summary>
public enum DepthFormat
{
/// <summary>
/// Default format for Android and Switch platforms is <see cref="GraphicsFormat.D24_UNorm_S8_UInt"/> and <see cref="GraphicsFormat.D32_SFloat_S8_UInt"/> for other platforms
/// </summary>
[RenderPathCompatible(RenderPathCompatibility.All)]
Default,
/// <summary>
/// Format containing 16 unsigned normalized bits in depth component. Corresponds to <see cref="GraphicsFormat.D16_UNorm"/>.
/// </summary>
[RenderPathCompatible(RenderPathCompatibility.Forward | RenderPathCompatibility.ForwardPlus)]
Depth_16 = GraphicsFormat.D16_UNorm,
/// <summary>
/// Format containing 24 unsigned normalized bits in depth component. Corresponds to <see cref="GraphicsFormat.D24_UNorm"/>.
/// </summary>
[RenderPathCompatible(RenderPathCompatibility.Forward | RenderPathCompatibility.ForwardPlus)]
Depth_24 = GraphicsFormat.D24_UNorm,
/// <summary>
/// Format containing 32 signed float bits in depth component. Corresponds to <see cref="GraphicsFormat.D32_SFloat"/>.
/// </summary>
[RenderPathCompatible(RenderPathCompatibility.Forward | RenderPathCompatibility.ForwardPlus)]
Depth_32 = GraphicsFormat.D32_SFloat,
/// <summary>
/// Format containing 16 unsigned normalized bits in depth component and 8 unsigned integer bits in stencil. Corresponds to <see cref="GraphicsFormat.D16_UNorm_S8_UInt"/>.
/// </summary>
[RenderPathCompatible(RenderPathCompatibility.All)]
Depth_16_Stencil_8 = GraphicsFormat.D16_UNorm_S8_UInt,
/// <summary>
/// Format containing 24 unsigned normalized bits in depth component and 8 unsigned integer bits in stencil. Corresponds to <see cref="GraphicsFormat.D24_UNorm_S8_UInt"/>.
/// </summary>
[RenderPathCompatible(RenderPathCompatibility.All)]
Depth_24_Stencil_8 = GraphicsFormat.D24_UNorm_S8_UInt,
/// <summary>
/// Format containing 32 signed float bits in depth component and 8 unsigned integer bits in stencil. Corresponds to <see cref="GraphicsFormat.D32_SFloat_S8_UInt"/>.
/// </summary>
[RenderPathCompatible(RenderPathCompatibility.All)]
Depth_32_Stencil_8 = GraphicsFormat.D32_SFloat_S8_UInt,
}
/// <summary>
/// Class containing resources needed for the <c>UniversalRenderer</c>.
/// </summary>
[Serializable, ReloadGroup, ExcludeFromPreset]
[URPHelpURL("urp/urp-universal-renderer")]
public partial class UniversalRendererData : ScriptableRendererData, ISerializationCallbackReceiver
{
#if UNITY_EDITOR
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812")]
internal class CreateUniversalRendererAsset : AssetCreationEndAction
{
public override void Action(EntityId entityId, string pathName, string resourceFile)
{
var instance = UniversalRenderPipelineAsset.CreateRendererAsset(pathName, RendererType.UniversalRenderer, false) as UniversalRendererData;
Selection.activeObject = instance;
}
}
[MenuItem("Assets/Create/Rendering/URP Universal Renderer", priority = CoreUtils.Sections.section3 + CoreUtils.Priorities.assetsCreateRenderingMenuPriority + 2)]
static void CreateUniversalRendererData()
{
var icon = CoreUtils.GetIconForType<ScriptableRendererData>();
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(EntityId.None, CreateInstance<CreateUniversalRendererAsset>(), "New Custom Universal Renderer Data.asset", icon, null);
}
#endif
/// <summary>
/// Resources needed for Post Processing.
/// </summary>
public PostProcessData postProcessData = null;
const int k_LatestAssetVersion = 3;
[SerializeField] int m_AssetVersion = 0;
[SerializeField] LayerMask m_PrepassLayerMask = -1;
[SerializeField] LayerMask m_OpaqueLayerMask = -1;
[SerializeField] LayerMask m_TransparentLayerMask = -1;
[SerializeField] StencilStateData m_DefaultStencilState = new StencilStateData() { passOperation = StencilOp.Replace }; // This default state is compatible with deferred renderer.
[SerializeField] bool m_ShadowTransparentReceive = true;
[SerializeField] RenderingMode m_RenderingMode = RenderingMode.Forward;
[SerializeField] DepthPrimingMode m_DepthPrimingMode = DepthPrimingMode.Disabled; // Default disabled because there are some outstanding issues with Text Mesh rendering.
[SerializeField] CopyDepthMode m_CopyDepthMode = CopyDepthMode.AfterTransparents;
[SerializeField] DepthFormat m_DepthAttachmentFormat = DepthFormat.Default;
[SerializeField] DepthFormat m_DepthTextureFormat = DepthFormat.Default;
#if UNITY_EDITOR
// Do not strip accurateGbufferNormals on Mobile Vulkan as some GPUs do not support R8G8B8A8_SNorm, which then force us to use accurateGbufferNormals
[ShaderKeywordFilter.ApplyRulesIfNotGraphicsAPI(GraphicsDeviceType.Vulkan)]
[ShaderKeywordFilter.RemoveIf(false, keywordNames: ShaderKeywordStrings._GBUFFER_NORMALS_OCT)]
#endif
[SerializeField]
bool m_AccurateGbufferNormals = false;
[SerializeField] IntermediateTextureMode m_IntermediateTextureMode = IntermediateTextureMode.Auto;
[SerializeField] bool m_TileOnlyMode = false;
/// <inheritdoc/>
protected override ScriptableRenderer Create()
{
if (!Application.isPlaying)
{
ReloadAllNullProperties();
}
return new UniversalRenderer(this);
}
/// <summary>
/// Use this to configure how to filter prepass objects.
/// </summary>
public LayerMask prepassLayerMask
{
get => m_PrepassLayerMask;
set
{
SetDirty();
m_PrepassLayerMask = value;
}
}
/// <summary>
/// Use this to configure how to filter opaque objects.
/// </summary>
public LayerMask opaqueLayerMask
{
get => m_OpaqueLayerMask;
set
{
SetDirty();
m_OpaqueLayerMask = value;
}
}
/// <summary>
/// Use this to configure how to filter transparent objects.
/// </summary>
public LayerMask transparentLayerMask
{
get => m_TransparentLayerMask;
set
{
SetDirty();
m_TransparentLayerMask = value;
}
}
/// <summary>
/// The default stencil state settings.
/// </summary>
public StencilStateData defaultStencilState
{
get => m_DefaultStencilState;
set
{
SetDirty();
m_DefaultStencilState = value;
}
}
/// <summary>
/// True if transparent objects receive shadows.
/// </summary>
public bool shadowTransparentReceive
{
get => m_ShadowTransparentReceive;
set
{
SetDirty();
m_ShadowTransparentReceive = value;
}
}
/// <summary>
/// Rendering mode.
/// </summary>
public RenderingMode renderingMode
{
get => m_RenderingMode;
set
{
SetDirty();
m_RenderingMode = value;
}
}
/// <summary>
/// Depth priming mode.
/// </summary>
public DepthPrimingMode depthPrimingMode
{
get => m_DepthPrimingMode;
set
{
SetDirty();
m_DepthPrimingMode = value;
}
}
/// <summary>
/// Copy depth mode.
/// </summary>
public CopyDepthMode copyDepthMode
{
get => m_CopyDepthMode;
set
{
SetDirty();
m_CopyDepthMode = value;
}
}
/// <summary>
/// Depth format used for CameraDepthAttachment
/// </summary>
public DepthFormat depthAttachmentFormat
{
get
{
if (m_DepthAttachmentFormat != DepthFormat.Default && !SystemInfo.IsFormatSupported((GraphicsFormat)m_DepthAttachmentFormat, GraphicsFormatUsage.Render))
{
Debug.LogWarning("Selected Depth Attachment Format is not supported on this platform, falling back to Default");
return DepthFormat.Default;
}
return m_DepthAttachmentFormat;
}
set
{
SetDirty();
if (renderingMode == RenderingMode.Deferred && !GraphicsFormatUtility.IsStencilFormat((GraphicsFormat)value))
{
Debug.LogWarning("Depth format without stencil is not supported on Deferred renderer, falling back to Default");
m_DepthAttachmentFormat = DepthFormat.Default;
}
else
{
m_DepthAttachmentFormat = value;
}
}
}
/// <summary>
/// Depth format used for CameraDepthTexture
/// </summary>
public DepthFormat depthTextureFormat
{
get
{
if (m_DepthTextureFormat != DepthFormat.Default && !SystemInfo.IsFormatSupported((GraphicsFormat) m_DepthTextureFormat, GraphicsFormatUsage.Render))
{
Debug.LogWarning($"Selected Depth Texture Format {m_DepthTextureFormat.ToString()} is not supported on this platform, falling back to Default");
return DepthFormat.Default;
}
return m_DepthTextureFormat;
}
set
{
SetDirty();
m_DepthTextureFormat = value;
}
}
/// <summary>
/// Use Octahedron normal vector encoding for gbuffer normals.
/// The overhead is negligible from desktop GPUs, while it should be avoided for mobile GPUs.
/// </summary>
public bool accurateGbufferNormals
{
get => m_AccurateGbufferNormals;
set
{
SetDirty();
m_AccurateGbufferNormals = value;
}
}
/// <summary>
/// Controls when URP renders via an intermediate texture.
/// </summary>
public IntermediateTextureMode intermediateTextureMode
{
get => m_IntermediateTextureMode;
set
{
SetDirty();
m_IntermediateTextureMode = value;
}
}
/// <summary>
/// Tile-Only Mode restricts render passes to avoid memory load/store of main camera targets, keeping them in on‑chip tile memory.
/// It activates additional RenderGaph validation. Some features may be disabled or fall back. See docs for details.
/// This is a potential GPU performance optimization on Tile-Based GPU architectures.
/// </summary>
public bool tileOnlyMode
{
get => m_TileOnlyMode;
set
{
if (m_TileOnlyMode == value)
return;
SetDirty();
m_TileOnlyMode = value;
}
}
/// <summary>
/// Returns true if the renderer uses a deferred lighting pass and GBuffers.
/// This is true for the Deferred and Deferred+ rendering paths.
/// </summary>
public bool usesDeferredLighting => m_RenderingMode == RenderingMode.Deferred ||
m_RenderingMode == RenderingMode.DeferredPlus;
/// <summary>
/// Returns true if the renderer uses a spatially clustered/tiled light list.
/// This is true for the Forward+ and Deferred+ rendering paths.
/// </summary>
public bool usesClusterLightLoop => m_RenderingMode == RenderingMode.ForwardPlus ||
m_RenderingMode == RenderingMode.DeferredPlus;
internal override bool stripShadowsOffVariants
{
get => m_StripShadowsOffVariants;
set => m_StripShadowsOffVariants = value;
}
internal override bool stripAdditionalLightOffVariants
{
get => m_StripAdditionalLightOffVariants;
set => m_StripAdditionalLightOffVariants = value;
}
[NonSerialized]
bool m_StripShadowsOffVariants = true;
[NonSerialized]
bool m_StripAdditionalLightOffVariants = true;
/// <inheritdoc/>
protected override void OnEnable()
{
base.OnEnable();
ReloadAllNullProperties();
}
private void ReloadAllNullProperties()
{
// Upon asset creation, OnEnable is called and `shaders` reference is not yet initialized
// We need to call the OnEnable for data migration when updating from old versions of UniversalRP that
// serialized resources in a different format. Early returning here when OnEnable is called
// upon asset creation is fine because we guarantee new assets get created with all resources initialized.
#if UNITY_EDITOR
ResourceReloader.TryReloadAllNullIn(this, UniversalRenderPipelineAsset.packagePath);
if (postProcessData != null)
postProcessData.Populate();
#endif
}
/// <inheritdoc/>
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
m_AssetVersion = k_LatestAssetVersion;
}
/// <inheritdoc/>
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (m_AssetVersion <= 1)
{
// To avoid breaking existing projects, keep the old AfterOpaques behaviour. The new AfterTransparents default will only apply to new projects.
m_CopyDepthMode = CopyDepthMode.AfterOpaques;
}
if (m_AssetVersion <= 2)
{
m_PrepassLayerMask = m_OpaqueLayerMask;
}
m_AssetVersion = k_LatestAssetVersion;
}
}
}