using System; using System.Collections.Generic; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering.RenderGraphModule; using UnityEngine.Scripting.APIUpdating; namespace UnityEngine.Rendering.Universal { /// /// The scriptable render pass used with the render objects renderer feature. /// [MovedFrom(true, "UnityEngine.Experimental.Rendering.Universal")] public class RenderObjectsPass : ScriptableRenderPass { RenderQueueType renderQueueType; FilteringSettings m_FilteringSettings; RenderObjects.CustomCameraSettings m_CameraSettings; /// /// The override material to use. /// public Material overrideMaterial { get; set; } /// /// The pass index to use with the override material. /// public int overrideMaterialPassIndex { get; set; } /// /// The override shader to use. /// public Shader overrideShader { get; set; } /// /// The pass index to use with the override shader. /// public int overrideShaderPassIndex { get; set; } List m_ShaderTagIdList = new List(); private PassData m_PassData; /// /// Sets the write and comparison function for depth. /// /// Sets whether it should write to depth or not. /// The depth comparison function to use. [Obsolete("Use SetDepthState instead", true)] public void SetDetphState(bool writeEnabled, CompareFunction function = CompareFunction.Less) { SetDepthState(writeEnabled, function); } /// /// Sets the write and comparison function for depth. /// /// Sets whether it should write to depth or not. /// The depth comparison function to use. public void SetDepthState(bool writeEnabled, CompareFunction function = CompareFunction.Less) { m_RenderStateBlock.mask |= RenderStateMask.Depth; m_RenderStateBlock.depthState = new DepthState(writeEnabled, function); } /// /// Sets up the stencil settings for the pass. /// /// The stencil reference value. /// The comparison function to use. /// The stencil operation to use when the stencil test passes. /// The stencil operation to use when the stencil test fails. /// The stencil operation to use when the stencil test fails because of depth. public void SetStencilState(int reference, CompareFunction compareFunction, StencilOp passOp, StencilOp failOp, StencilOp zFailOp) { StencilState stencilState = StencilState.defaultValue; stencilState.enabled = true; stencilState.SetCompareFunction(compareFunction); stencilState.SetPassOperation(passOp); stencilState.SetFailOperation(failOp); stencilState.SetZFailOperation(zFailOp); m_RenderStateBlock.mask |= RenderStateMask.Stencil; m_RenderStateBlock.stencilReference = reference; m_RenderStateBlock.stencilState = stencilState; } RenderStateBlock m_RenderStateBlock; /// /// The constructor for render objects pass. /// /// The profiler tag used with the pass. /// Controls when the render pass executes. /// List of shader tags to render with. /// The queue type for the objects to render. /// The layer mask to use for creating filtering settings that control what objects get rendered. /// The settings for custom cameras values. public RenderObjectsPass(string profilerTag, RenderPassEvent renderPassEvent, string[] shaderTags, RenderQueueType renderQueueType, int layerMask, RenderObjects.CustomCameraSettings cameraSettings) { profilingSampler = new ProfilingSampler(profilerTag); Init(renderPassEvent, shaderTags, renderQueueType, layerMask, cameraSettings); } internal RenderObjectsPass(URPProfileId profileId, RenderPassEvent renderPassEvent, string[] shaderTags, RenderQueueType renderQueueType, int layerMask, RenderObjects.CustomCameraSettings cameraSettings) { profilingSampler = ProfilingSampler.Get(profileId); Init(renderPassEvent, shaderTags, renderQueueType, layerMask, cameraSettings); } internal void Init(RenderPassEvent renderPassEvent, string[] shaderTags, RenderQueueType renderQueueType, int layerMask, RenderObjects.CustomCameraSettings cameraSettings) { m_PassData = new PassData(); this.renderPassEvent = renderPassEvent; this.renderQueueType = renderQueueType; this.overrideMaterial = null; this.overrideMaterialPassIndex = 0; this.overrideShader = null; this.overrideShaderPassIndex = 0; RenderQueueRange renderQueueRange = (renderQueueType == RenderQueueType.Transparent) ? RenderQueueRange.transparent : RenderQueueRange.opaque; m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask); if (shaderTags != null && shaderTags.Length > 0) { foreach (var tag in shaderTags) m_ShaderTagIdList.Add(new ShaderTagId(tag)); } else { m_ShaderTagIdList.Add(new ShaderTagId("SRPDefaultUnlit")); m_ShaderTagIdList.Add(new ShaderTagId("UniversalForward")); m_ShaderTagIdList.Add(new ShaderTagId("UniversalForwardOnly")); } m_RenderStateBlock = new RenderStateBlock(RenderStateMask.Nothing); m_CameraSettings = cameraSettings; } /// [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)] public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { UniversalRenderingData universalRenderingData = renderingData.frameData.Get(); UniversalCameraData cameraData = renderingData.frameData.Get(); UniversalLightData lightData = renderingData.frameData.Get(); var cmd = CommandBufferHelpers.GetRasterCommandBuffer(renderingData.commandBuffer); using (new ProfilingScope(cmd, profilingSampler)) { InitPassData(cameraData, ref m_PassData); InitRendererLists(universalRenderingData, lightData, ref m_PassData, context, default(RenderGraph), false); ExecutePass(m_PassData, cmd , m_PassData.rendererList, renderingData.cameraData.IsCameraProjectionMatrixFlipped()); } } private static void ExecutePass(PassData passData, RasterCommandBuffer cmd, RendererList rendererList, bool isYFlipped) { Camera camera = passData.cameraData.camera; // In case of camera stacking we need to take the viewport rect from base camera Rect pixelRect = passData.cameraData.pixelRect; float cameraAspect = (float)pixelRect.width / (float)pixelRect.height; if (passData.cameraSettings.overrideCamera) { if (passData.cameraData.xr.enabled) { Debug.LogWarning("RenderObjects pass is configured to override camera matrices. While rendering in stereo camera matrices cannot be overridden."); } else { Matrix4x4 projectionMatrix = Matrix4x4.Perspective(passData.cameraSettings.cameraFieldOfView, cameraAspect, camera.nearClipPlane, camera.farClipPlane); projectionMatrix = GL.GetGPUProjectionMatrix(projectionMatrix, isYFlipped); Matrix4x4 viewMatrix = passData.cameraData.GetViewMatrix(); Vector4 cameraTranslation = viewMatrix.GetColumn(3); viewMatrix.SetColumn(3, cameraTranslation + passData.cameraSettings.offset); RenderingUtils.SetViewAndProjectionMatrices(cmd, viewMatrix, projectionMatrix, false); } } var activeDebugHandler = GetActiveDebugHandler(passData.cameraData); if (activeDebugHandler != null) { passData.debugRendererLists.DrawWithRendererList(cmd); } else { cmd.DrawRendererList(rendererList); } if (passData.cameraSettings.overrideCamera && passData.cameraSettings.restoreCamera && !passData.cameraData.xr.enabled) { RenderingUtils.SetViewAndProjectionMatrices(cmd, passData.cameraData.GetViewMatrix(), GL.GetGPUProjectionMatrix(passData.cameraData.GetProjectionMatrix(0), isYFlipped), false); } } private class PassData { internal RenderObjects.CustomCameraSettings cameraSettings; internal RenderPassEvent renderPassEvent; internal TextureHandle color; internal RendererListHandle rendererListHdl; internal DebugRendererLists debugRendererLists; internal UniversalCameraData cameraData; // Required for code sharing purpose between RG and non-RG. internal RendererList rendererList; } private void InitPassData(UniversalCameraData cameraData, ref PassData passData) { passData.cameraSettings = m_CameraSettings; passData.renderPassEvent = renderPassEvent; passData.cameraData = cameraData; } private void InitRendererLists(UniversalRenderingData renderingData, UniversalLightData lightData, ref PassData passData, ScriptableRenderContext context, RenderGraph renderGraph, bool useRenderGraph) { SortingCriteria sortingCriteria = (renderQueueType == RenderQueueType.Transparent) ? SortingCriteria.CommonTransparent : passData.cameraData.defaultOpaqueSortFlags; DrawingSettings drawingSettings = RenderingUtils.CreateDrawingSettings(m_ShaderTagIdList, renderingData, passData.cameraData, lightData, sortingCriteria); drawingSettings.overrideMaterial = overrideMaterial; drawingSettings.overrideMaterialPassIndex = overrideMaterialPassIndex; drawingSettings.overrideShader = overrideShader; drawingSettings.overrideShaderPassIndex = overrideShaderPassIndex; var activeDebugHandler = GetActiveDebugHandler(passData.cameraData); var filterSettings = m_FilteringSettings; if (useRenderGraph) { if (activeDebugHandler != null) { passData.debugRendererLists = activeDebugHandler.CreateRendererListsWithDebugRenderState(renderGraph, ref renderingData.cullResults, ref drawingSettings, ref m_FilteringSettings, ref m_RenderStateBlock); } else { RenderingUtils.CreateRendererListWithRenderStateBlock(renderGraph, ref renderingData.cullResults, drawingSettings, m_FilteringSettings, m_RenderStateBlock, ref passData.rendererListHdl); } } else { if (activeDebugHandler != null) { passData.debugRendererLists = activeDebugHandler.CreateRendererListsWithDebugRenderState(context, ref renderingData.cullResults, ref drawingSettings, ref m_FilteringSettings, ref m_RenderStateBlock); } else { RenderingUtils.CreateRendererListWithRenderStateBlock(context, ref renderingData.cullResults, drawingSettings, m_FilteringSettings, m_RenderStateBlock, ref passData.rendererList); } } } /// public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { UniversalCameraData cameraData = frameData.Get(); UniversalRenderingData renderingData = frameData.Get(); UniversalLightData lightData = frameData.Get(); using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData, profilingSampler)) { UniversalResourceData resourceData = frameData.Get(); InitPassData(cameraData, ref passData); passData.color = resourceData.activeColorTexture; builder.SetRenderAttachment(resourceData.activeColorTexture, 0, AccessFlags.Write); builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture, AccessFlags.Write); TextureHandle mainShadowsTexture = resourceData.mainShadowsTexture; TextureHandle additionalShadowsTexture = resourceData.additionalShadowsTexture; if (mainShadowsTexture.IsValid()) builder.UseTexture(mainShadowsTexture, AccessFlags.Read); if (additionalShadowsTexture.IsValid()) builder.UseTexture(additionalShadowsTexture, AccessFlags.Read); TextureHandle[] dBufferHandles = resourceData.dBuffer; for (int i = 0; i < dBufferHandles.Length; ++i) { TextureHandle dBuffer = dBufferHandles[i]; if (dBuffer.IsValid()) builder.UseTexture(dBuffer, AccessFlags.Read); } TextureHandle ssaoTexture = resourceData.ssaoTexture; if (ssaoTexture.IsValid()) builder.UseTexture(ssaoTexture, AccessFlags.Read); InitRendererLists(renderingData, lightData, ref passData, default(ScriptableRenderContext), renderGraph, true); var activeDebugHandler = GetActiveDebugHandler(passData.cameraData); if (activeDebugHandler != null) { passData.debugRendererLists.PrepareRendererListForRasterPass(builder); } else { builder.UseRendererList(passData.rendererListHdl); } builder.AllowPassCulling(false); builder.AllowGlobalStateModification(true); if (cameraData.xr.enabled) builder.EnableFoveatedRasterization(cameraData.xr.supportsFoveatedRendering && cameraData.xrUniversal.canFoveateIntermediatePasses); builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) => { var isYFlipped = data.cameraData.IsRenderTargetProjectionMatrixFlipped(data.color); ExecutePass(data, rgContext.cmd, data.rendererListHdl, isYFlipped); }); } } } }