Unity Shader突出显示重叠

see*_*eek 15 opengl shader unity-game-engine

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

结果应该看起来像附加图像.在此输入图像描述

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

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

我认为它可以通过使用类似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
        }

    } 
}
Run Code Online (Sandbox Code Playgroud)

ShaderTwo

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
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

结果看起来像附加图像 在此输入图像描述

Pod*_*kiy 6

这个问题可以借助 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.
    }
Run Code Online (Sandbox Code Playgroud)

例子:

在此处输入图片说明

着色器:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • > 请告诉我这个着色器是在其他着色器的顶部渲染的,是否可以添加队列?不确定我是否正确理解了问题。您可以用自己的着色器替换每个通道中的着色器,以获得重叠和不重叠区域的不同着色器。您可以使用 Queue 将其呈现在其他人之上。您也可以渲染双面。您只需要设置“剔除”即可。 (2认同)