• HDRP(SRP) 渲染一个摄像机剔除遮罩外的物体


    设置一个被剔除的图层

    在这里插入图片描述

    编写一个 CustomPass

    AggregateCullingParameters 中,额外包含了目标图层,以进行接下来的渲染。

    Execute() 中,这个 Pass 主要做了以下事情:

    1. 对目标图层进行完整渲染。(cameraColorBuffer
    2. 对目标图层写入Motion Vector。(cameraMotionVectorsBuffer
    using UnityEngine;
    using UnityEngine.Rendering.HighDefinition;
    using UnityEngine.Rendering;
    using UnityEngine.Experimental.Rendering;
    using System.Collections.Generic;
    using System;
    
    /// 
    /// DrawRenderers Custom Pass
    /// 
    [System.Serializable]
    public class ViewingObjectPass : CustomPass
    {
        /// 
        /// HDRP Shader passes
        /// 
        public enum ShaderPass
        {
            // Ordered by frame time in HDRP
            ///Object Depth pre-pass, only the depth of the object will be rendered.
            DepthPrepass = 1,
            ///Forward pass, render the object color.
            Forward = 0,
        }
    
        // Used only for the UI to keep track of the toggle state
        [SerializeField] internal bool filterFoldout;
        [SerializeField] internal bool rendererFoldout;
    
        //Filter settings
        /// 
        /// Render Queue filter to select which kind of object to render.
        /// 
        public RenderQueueType renderQueueType = RenderQueueType.AllOpaque;
        /// 
        /// Layer Mask filter, select which layer to render.
        /// 
        public LayerMask layerMask = 1; // Layer mask Default enabled
        /// 
        /// Sorting flags of the objects to render.
        /// 
        public SortingCriteria sortingCriteria = SortingCriteria.CommonOpaque;
    
        /// 
        /// When true, overrides the depth state of the objects.
        /// 
        public bool overrideDepthState = false;
        /// 
        /// Overrides the Depth comparison function, only used when overrideDepthState is true.
        /// 
        public CompareFunction depthCompareFunction = CompareFunction.LessEqual;
        /// 
        /// Overrides the Depth write, only used when overrideDepthState is true.
        /// 
        public bool depthWrite = true;
    
        /// 
        /// Set the shader pass to use when the override material is null
        /// 
        public ShaderPass shaderPass = ShaderPass.Forward;
    
        int fadeValueId;
    
        static ShaderTagId[] forwardShaderTags;
        static ShaderTagId[] depthShaderTags;
    
        // Cache the shaderTagIds so we don't allocate a new array each frame
        ShaderTagId[] cachedShaderTagIDs;
    
        [SerializeField, HideInInspector]
        Shader motionVectorShader;
        Material motionVector;
    
        /// 
        /// Called before the first execution of the pass occurs.
        /// Allow you to allocate custom buffers.
        /// 
        /// The render context
        /// Current command buffer of the frame
        protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
        {
            fadeValueId = Shader.PropertyToID("_FadeValue");
    
            // In case there was a pass index assigned, we retrieve the name of this pass
            //if (String.IsNullOrEmpty(overrideMaterialPassName) && overrideMaterial != null)
            //    overrideMaterialPassName = overrideMaterial.GetPassName(overrideMaterialPassIndex);
    
            forwardShaderTags = new ShaderTagId[]
            {
                HDShaderPassNames.s_ForwardName,            // HD Lit shader
                HDShaderPassNames.s_ForwardOnlyName,        // HD Unlit shader
                HDShaderPassNames.s_SRPDefaultUnlitName,    // Cross SRP Unlit shader
                HDShaderPassNames.s_EmptyName,              // Add an empty slot for the override material
            };
    
            depthShaderTags = new ShaderTagId[]
            {
                HDShaderPassNames.s_DepthForwardOnlyName,
                HDShaderPassNames.s_DepthOnlyName,
                HDShaderPassNames.s_EmptyName,              // Add an empty slot for the override material
            };
    
            
            motionVectorShader = Shader.Find("Hidden/HDRP/MotionVectors");
            motionVector = CoreUtils.CreateEngineMaterial(motionVectorShader);
        }
    
        /// 
        /// Use this method if you want to draw objects that are not visible in the camera.
        /// For example if you disable a layer in the camera and add it in the culling parameters, then the culling result will contains your layer.
        /// 
        /// Aggregate the parameters in this property (use |= for masks fields, etc.)
        /// The camera where the culling is being done
        protected override void AggregateCullingParameters(ref ScriptableCullingParameters cullingParameters, HDCamera hdCamera)
        {
            cullingParameters.cullingMask |= (uint)(int)layerMask;
        }
    
        ShaderTagId[] GetShaderTagIds()
        {
            if (shaderPass == ShaderPass.DepthPrepass)
                return depthShaderTags;
            else
                return forwardShaderTags;
        }
    
        /// 
        /// Execute the DrawRenderers with parameters setup from the editor
        /// 
        /// The context of the custom pass. Contains command buffer, render context, buffer, etc.
        protected override void Execute(CustomPassContext ctx)
        {
            var shaderPasses = GetShaderTagIds();
            //if (overrideMaterial != null)
            //{
            //    shaderPasses[shaderPasses.Length - 1] = new ShaderTagId(overrideMaterialPassName);
            //    overrideMaterial.SetFloat(fadeValueId, fadeValue);
            //}
    
            if (shaderPasses.Length == 0)
            {
                Debug.LogWarning("Attempt to call DrawRenderers with an empty shader passes. Skipping the call to avoid errors");
                return;
            }
    
            var mask = overrideDepthState ? RenderStateMask.Depth : 0;
            mask |= overrideDepthState && !depthWrite ? RenderStateMask.Stencil : 0;
            var stateBlock = new RenderStateBlock(mask)
            {
                depthState = new DepthState(depthWrite, depthCompareFunction),
                // We disable the stencil when the depth is overwritten but we don't write to it, to prevent writing to the stencil.
                stencilState = new StencilState(false),
            };
    
            PerObjectData renderConfig = ctx.hdCamera.frameSettings.IsEnabled(FrameSettingsField.Shadowmask)
                ? HDUtils.GetBakedLightingWithShadowMaskRenderConfig()
                : HDUtils.GetBakedLightingRenderConfig();
    
    
            var result = new UnityEngine.Rendering.RendererUtils.RendererListDesc(shaderPasses, ctx.cullingResults, ctx.hdCamera.camera)
            {
                rendererConfiguration = renderConfig,
                renderQueueRange = GetRenderQueueRange(renderQueueType),
                sortingCriteria = sortingCriteria,
                excludeObjectMotionVectors = false,
                stateBlock = stateBlock,
                layerMask = layerMask,
            };
    
            var renderCtx = ctx.renderContext;
            CoreUtils.SetRenderTarget(ctx.cmd, ctx.cameraColorBuffer, ctx.cameraDepthBuffer, ClearFlag.None);
            CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, renderCtx.CreateRendererList(result));
    
            result = new UnityEngine.Rendering.RendererUtils.RendererListDesc(HDShaderPassNames.s_MotionVectorsName, ctx.cullingResults, ctx.hdCamera.camera)
            {
                rendererConfiguration = PerObjectData.MotionVectors,
                renderQueueRange = GetRenderQueueRange(renderQueueType),
                sortingCriteria = sortingCriteria,
                excludeObjectMotionVectors = false,
                stateBlock = stateBlock,
                layerMask = layerMask,
            };
    
            CoreUtils.SetRenderTarget(ctx.cmd, ctx.cameraMotionVectorsBuffer, ctx.cameraDepthBuffer, ClearFlag.None);
            CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, renderCtx.CreateRendererList(result));
        }
    
        protected override void Cleanup()
        {
            CoreUtils.Destroy(motionVector);
        }
    }
    

    把 Pass 挂起来,如图进行配置

    在这里插入图片描述

    效果

    理论上不出bug的话跟正常渲染没啥区别(
    在这里插入图片描述

    可能会有奇怪的地方出BUG,比如SSAO(这个我直接禁用了),比如运动模糊和TAA(已经修复,即代码中的写入Motion Vector),欢迎留言讨论。
    抛砖引玉,恳请批评指正!

    参考文献:

    Unity SRP 中渲染 Motion Vector 的正确姿势 - SardineFish - https://www.sardinefish.com/blog/458

  • 相关阅读:
    剑指 Offer 12. 矩阵中的路径【中等难度】
    【poi导出excel之XSSFWorkbook】
    性能测试 —— 吞吐量和并发量的关系? 有什么区别?
    vue实现【接口数据渲染随机显示】和【仅显示前五条数据】
    基础设施建设-企业级全栈测试平台的最佳实践
    蓝桥集训(附加面试题)第七天
    G2O学习 - 曲线拟合实例
    提升--09-1--AQS底层逻辑实现
    C- 内联汇编实现puts函数
    一篇解决Elasticsearch全部问题。
  • 原文地址:https://blog.csdn.net/qq_15505341/article/details/126939516