【问题标题】:Unity Shader highlighting overlapsUnity Shader 突出显示重叠
【发布时间】:2016-06-05 02:16:06
【问题描述】:

我正在尝试为统一编写一个着色器,以突出显示网格的重叠片段。它应该适用于重叠自身的一个对象以及多个对象。

结果应该看起来像附加图像。

首先我尝试通过碰撞检测来实现这一点,但我认为最好的方法是编写着色器。

我对着色器不是很熟悉,所以如果有人能帮助我,我将不胜感激。

我认为这可以通过使用模板着色器来完成,例如http://docs.unity3d.com/Manual/SL-Stencil.html 但是这个着色器只渲染两个对象的交集而不渲染整个对象。

我还发现了基于深度 (https://chrismflynn.wordpress.com/2012/09/06/fun-with-shaders-and-the-depth-buffer/) 的着色器,但这也适用于两个对象,并且不适用于一个自身重叠的网格

关于@Zze 对两个Pass 的想法的评论,我现在有两个着色器。当一个有一个着色器而另一个有第二个着色器时,它适用于两个对象。

也许任何人都可以帮助我如何将它组合成一个着色器,该着色器也适用于自身重叠的对象?

ShaderOne

Shader "Custom/ShaderOne"
{
    SubShader {
        Tags { "RenderType"="Opaque" "Queue"="Geometry"}
        Pass {
            Stencil {
                Ref 2
                Comp always
                Pass keep 
                Fail decrWrap 
                ZFail keep
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            struct appdata {
                float4 vertex : POSITION;
            };
            struct v2f {
                float4 pos : SV_POSITION;
            };
            v2f vert(appdata v) {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                return o;
            }
            half4 frag(v2f i) : SV_Target {
                return half4(0,1,0,1);
            }
            ENDCG
        }
        Pass {
            Stencil {
                Ref 2
                Comp equal
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            struct appdata {
                float4 vertex : POSITION;
            };
            struct v2f {
                float4 pos : SV_POSITION;
            };
            v2f vert(appdata v) {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                return o;
            }
            half4 frag(v2f i) : SV_Target {
                return half4(0,0,1,1);
            }
            ENDCG
        }

    } 
}

着色器二

Shader "Custom/ShaderTwo"
{
    SubShader {
        Tags { "RenderType"="Opaque" "Queue"="Geometry"}
        Pass {
            Stencil {
                Ref 2
                Comp always
                Pass replace
                ZFail keep
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            struct appdata {
                float4 vertex : POSITION;
            };
            struct v2f {
                float4 pos : SV_POSITION;
            };
            v2f vert(appdata v) {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                return o;
            }
            half4 frag(v2f i) : SV_Target {
                return half4(1,0,0,1);
            }
            ENDCG
        }
    } 
}

结果看起来像附加图片

【问题讨论】:

  • 如果模板着色器渲染交点,那你为什么不做一个着色器有2遍,第一个正常绘制,然后第二个模仿模板着色器的结果?
  • 您可能想看看深度剥离的概念。请参阅herehere。还有你打算拥有多少个对象。如果不是很多,您可能希望将每个对象渲染为纹理,然后像累积缓冲区一样组合它们。
  • @mrVoid 我认为深度测试只能在相机顶视图的情况下工作 - 但是当它是透视时,这不起作用?我为此头疼。也许你可以给我一些使用示例代码的例子?
  • 好的@seek。看来我误解了你的目标。所以它不是一个 2D 自上而下的视图,它是一个 3D 模型视图,其中绘制了某种透明层是吗?我问你将拥有多少几何图形。如果不实现一些代码来精确计算几何布尔运算,这可能是不可行的。

标签: opengl unity3d shader


【解决方案1】:

这个问题可以在 Stencil 缓冲区和一两遍着色器的帮助下解决。 思路如下:

  • 第一次将模板缓冲区中的值与 0 进行比较。在这两种情况下(通过/失败)都增加缓冲区中的值。
  • 第二遍将模板缓冲区中的值与 1 进行比较。如果参考值小于 1,则我们通过并突​​出显示重叠像素。

您可能希望添加更多与第二个相同但具有不同参考值的通道,以突出显示重叠两次、三次等的区域。

在 Unity 的 shaderlab 表示法中,它应该是这样的:

    Pass
    {
        Stencil {
            Ref 0
            Comp Equal
            Pass IncrSat 
            Fail IncrSat 
        }

        // Shader for not overlapping regions goes here.
    }

    Pass
    {
        Stencil {
            Ref 1
            Comp Less
        }

        // Shader for one-time overlapping regions goes here.
    }

    Pass
    {
        Stencil {
            Ref 2
            Comp Less
        }

        // Shader for two-time overlapping regions goes here.
    }

例子:

着色器:

Shader "Unlit/Stencil"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            Stencil {
                Ref 0
                Comp Equal
                Pass IncrSat 
                Fail IncrSat 
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = fixed4(0.0, 0.0, 1.0, 1.0);
                return col;
            }
            ENDCG
        }

        Pass
        {
            Stencil {
                Ref 1
                Comp Less
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = fixed4(1.0, 1.0, 0.0, 1.0);
                return col;
            }
            ENDCG
        }

        Pass
        {
            Stencil {
                Ref 2
                Comp Less
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = fixed4(1.0, 0.0, 0.0, 1.0);
                return col;
            }
            ENDCG
        }
    }
}

【讨论】:

  • 效果很好!。这正是我一直在寻找的。请告诉我这个着色器渲染在其他着色器的顶部,是否可以将队列添加到这个?另一件事是否也可以将其渲染为双面?
  • > 请告诉我这个着色器渲染在其他着色器的顶部,是否可以在其中添加队列?不确定我是否正确理解了问题。您可以将每个 Pass 中的着色器替换为您自己的,以获得重叠和不重叠区域的不同着色器。您可以使用 Queue 将其呈现在其他之上。您也可以渲染双面。你只需要设置Cull Off
  • 我的意思是我的场景中有其他对象应该用你的着色器渲染在这个对象的顶部。
  • @seek,你能举个例子吗?您可以使用相同的着色器以任何顺序渲染多个对象,它应该可以工作。
  • 例如场景中的其他对象有着色器 Unlit/Color,我需要这个对象应该在你的着色器对象之上。现在每个具有不同着色器的对象都使用您的着色器在这些对象后面渲染。
猜你喜欢
  • 2021-11-16
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2021-06-06
  • 2017-04-01
  • 2011-03-13
  • 2016-03-13
  • 2018-02-11
相关资源
最近更新 更多