opengl - Unity Shader 高亮重叠

标签 opengl unity3d shader

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

结果应该看起来像附加的图像。 enter image description here

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

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

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

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

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

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

着色器

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
        }
    } 
}

结果看起来像附加图像 enter image description here

最佳答案

这个问题可以借助 Stencil 缓冲区和一、两遍着色器来解决。
想法如下:

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

  • 您可能想要添加更多与第二个相同但具有不同引用值的 channel ,以突出显示重叠两次、三次等的区域。

    在 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.
        }
    

    例子:

    enter image description 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
            }
        }
    }
    

    关于opengl - Unity Shader 高亮重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35574227/

    相关文章:

    OpenGL 立方体无法正确渲染

    c++ - 如何读取当前发送到 OpenGL 进行渲染的所有面

    c - 为什么 GLfloat 需要全局作用域?

    c# - 在 Update() 函数中完成后如何停止方法? - C# - Unity3D

    .net - 可以在 Unity3D 中使用 lua 代码

    c++ - GLSL - GLSL 1.2 中的统一位置和着色器中的深度测试

    c# - 在 Unity 中使用 Shells 技术实现 Fur

    linux - glUseProgram() GL_INVALID_OPERATION 1282 在 Ubuntu Gnome 17.04 Intel HD4000 上

    c# - 动画和图形设计选择

    unity-game-engine - 为什么我的 VFX 编辑器中没有 "Graph Shader"参数