半透明混合之背景问题

文章讲述了作者在项目中遇到半透角色颜色差异问题,通过创建临时RenderTexture处理背景混合,保留圆环效果。涉及使用RenderFeature、混合Shader和特定的渲染设置,包括MSAA对内存的影响。
摘要由CSDN通过智能技术生成

前言:        

        这段时间一直在处理项目中有关半透的问题,其中就遇到了,由于半透明混合的关系,导致角色在不同背景下颜色存在差异的问题。

        仔细查看了下腿部使用URP内置的Lit.Shader,解决方法也比较简单,由于Lit.Shader默认为SrcAlpha,1-SrcAlpha的混合模式,因此只需要修改为SrcAlpha,Zero。

        如果colorbuffer中的颜色我们都不需要是可以如上来处理背景混合问题,但。。。我的项目中美术需要在腿内部保留一个圆环,如下图所示:

        因此无法使用上面的方法来解决该问题,稍微花些时间想了想:既然背景不能用来混合,那就创建一张RT颜色清空为纯0,用来写入color,圆环和半透都往这张RT写入,最后在和背景混合的时候:使用假设RT上存在像素不为0,则使用RT,否则使用背景色,那么问题就可以迎刃而解

下面进入正式的编码:

创建一个RenderFeature,创建RT,并且将圆环和半透写入到这张RT中,最后混合输出到URP的ColorRT(管线部分比较简单,下面直接贴出pass内执行的部分)。

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
            using (new ProfilingScope(cmd, m_ProfilingSampler))
            {
                var sortFlags =  SortingCriteria.CommonTransparent;
                var drawSettings = CreateDrawingSettings(m_ShaderTagIdList, ref renderingData, sortFlags);
                var drawSettings_Opache = CreateDrawingSettings(m_ShaderTagIdList_Opache, ref renderingData, SortingCriteria.CommonOpaque);
                
                var filterSettings = m_FilteringSettings_Transparent;
                
                cmd.Clear();

                cmd.SetRenderTarget(tempColor.id, m_depth);
                context.ExecuteCommandBuffer(cmd);
                cmd.Clear();
                
                
                //渲染Opache Color
                context.DrawRenderers(renderingData.cullResults, ref drawSettings_Opache, ref m_FilteringSettings_Opache, ref m_RenderStateBlock_Transparent);
                cmd.Clear();

                //渲染Transparent color
                context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref m_FilteringSettings_Transparent, ref m_RenderStateBlock_Transparent);
                cmd.Clear();
                
                cmd.SetGlobalTexture("_TranparentMain", m_color);
                context.ExecuteCommandBuffer(cmd);
                cmd.Clear();
                
                Blit(cmd, tempColor.Identifier(), tempColor2.Identifier(), m_BlendMaterial);
                Blit(cmd, tempColor2.Identifier(), m_color);
                context.ExecuteCommandBuffer(cmd);
            }

            CommandBufferPool.Release(cmd);
        }

解释:tempColor为那张RT,指定好LightMode,指定好需要渲染到RT的物件的layer(rendererQuality那边需要过滤该Layer),指定好RenderTarget为tempColor与DepthTexture(需要Depth是由于需要其用来参与深度写入与测试),调用Contex.DrawRenderers来渲染指定的物件,最后使用Blit混合后在Blit回ColorRT

混合shader的Frag:

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                fixed4 mainColor = tex2D(_TranparentMain, i.uv);

                fixed3 finnal;
                if(col.a > 0)
                {
                    finnal = col.a * col.rgb;
                }
                else
                {
                    finnal =  mainColor.rgb;
                }
                return fixed4(finnal, 1);
            }

总结:

        需要额外两张RT,以及开启CopyDepth(如果开启MSAA的话,URP7.7会需要执行prepass,由于关闭了相关layer,变成圆环未写入到prepass的RT中,这样其实会出问题,所以是需要MSAA是需要 稍微定制下prepass那块),内存开销还是比较大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值