CG/Unity:用于复制对象的玩具着色器

CG/Unity: Toy Shader For Duplicating Object

我刚开始编写着色器,正在练习几何着色器。着色器的目标是使 "normal" 通道产生透明像素,使对象不可见,而 "geometry" 通道将获取每个三角形,在与原始相同的位置重绘但颜色为黑色。因此,我希望输出是原始对象,但是是黑色的。然而,我的几何通道似乎没有产生任何我能看到的输出:

这是我目前拥有的着色器代码。

Shader "Outlined/Silhouette2" {
    Properties
    {
        _Color("Color", Color) = (0,0,0,1)
        _MainColor("Main Color", Color) = (1,1,1,1)
        _Thickness("Thickness", float) = 4
        _MainTex("Main Texture", 2D) = "white" {}
    }
    SubShader
    {

        Tags{ "Queue" = "Geometry" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha
        Cull Back
        ZTest always
        Pass
        {
            Stencil{
                Ref 1
                Comp always
                Pass replace
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct v2g
            {
                float4  pos : SV_POSITION;
                float2  uv : TEXCOORD0;
                float3 viewT : TANGENT;
                float3 normals : NORMAL;
            };

            struct g2f
            {
                float4  pos : SV_POSITION;
                float2  uv : TEXCOORD0;
                float3  viewT : TANGENT;
                float3  normals : NORMAL;
            };

            float4 _LightColor0;
            sampler2D _MainTex;
            float4 _MainColor;

            v2g vert(appdata_base v)
            {
                v2g OUT;
                OUT.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                OUT.uv = v.texcoord;
                OUT.normals = v.normal;
                OUT.viewT = ObjSpaceViewDir(v.vertex);

                return OUT;
            }

            half4 frag(g2f IN) : COLOR
            {
                //this renders nothing, if you want the base mesh and color
                //fill this in with a standard fragment shader calculation

                float4 texColor = tex2D(_MainTex, IN.uv);
                float3 normal = mul(float4(IN.normals, 0.0), _Object2World).xyz;
                float3 normalDirection = normalize(normal);
                float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz * -1);
                float3 diffuse = _LightColor0.rgb * _MainColor.rgb * max(0.0, dot(normalDirection, lightDirection));

                texColor = float4(diffuse,1) * texColor;

                //
                //return texColor;
                return float4(0, 0, 0, 0);
            }
            ENDCG
        }

        Pass
        {
            Stencil{
                Ref 0
                Comp equal
            }

            CGPROGRAM
            #include "UnityCG.cginc"
            #pragma target 4.0
            #pragma vertex vert
            #pragma geometry geom
            #pragma fragment frag


            half4 _Color;
            float _Thickness;

            struct v2g
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
                float4 local_pos: TEXCOORD1;
                float3 viewT : TANGENT;
                float3 normals : NORMAL;
            };

            struct g2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 viewT : TANGENT;
                float3 normals : NORMAL;
            };

            v2g vert(appdata_base v)
            {
                v2g OUT;
                OUT.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                OUT.local_pos = v.vertex;

                OUT.uv = v.texcoord;
                OUT.normals = v.normal;
                OUT.viewT = ObjSpaceViewDir(v.vertex);

                return OUT;
            }

            [maxvertexcount(12)]
            void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream)
            {
                g2f OUT;
                OUT.pos = IN[0].pos;
                OUT.uv = IN[0].uv;
                OUT.viewT = IN[0].viewT;
                OUT.normals = IN[0].normals;
                triStream.Append(OUT);

                OUT.pos = IN[1].pos;
                OUT.uv = IN[1].uv;
                OUT.viewT = IN[1].viewT;
                OUT.normals = IN[1].normals;
                triStream.Append(OUT);

                OUT.pos = IN[2].pos;
                OUT.uv = IN[2].uv;
                OUT.viewT = IN[2].viewT;
                OUT.normals = IN[2].normals;
                triStream.Append(OUT);
            }

            half4 frag(g2f IN) : COLOR
            {
                _Color.a = 1;
                return _Color;
            }
            ENDCG

        }
    }
    FallBack "Diffuse"
}

因为我所做的只是获取相同的三角形,并将它们附加到三角形流中,所以我不确定我可能做错了什么导致什么都没有出现。有人知道为什么会这样吗?

我注意到你不打电话 triStrem.RestartStrip(); 在几何着色器中输入三角形的 3 个顶点后。

这会通知流一个特定的三角形带已经结束,一个新的三角形带将开始。如果你不这样做,传递给流的每个(单个)顶点将添加到现有的三角形带上,使用三角形带模式:https://en.wikipedia.org/wiki/Triangle_strip

我自己对地理着色器还很陌生,所以我不确定这是否是你的问题,我不认为 RestartStrip 函数会在每个几何着色器结束时自动调用,但还没有测试过这个。相反,我认为只有当您到达 maxvertexcount 时才会自动调用它。对于单个三角形,我会将 maxvertexcount 设置为 3,而不是现在的 12。 (我也知道很难获得任何着色器答案,所以我想我会尽力提供帮助。)