1

I'm new to writing shaders and I'm working on a practice geometry shader. The goal of the shader is to make the "normal" pass produce transparent pixels such that the object is invisible, while the "geometry" pass will take each triangle, redraw in the same place as the original but colored black. Thus, I expect the output to be the original object, but black. However, my geometry pass seems to not produce any output I can see:

enter image description here

Here is the code I currently have for the shader.

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

Since all I'm doing is taking the same triangles I've been given and appending them to the triangle stream I'm not sure what I could be doing wrong to cause nothing to appear. Anyone know why this is happening?

Valevalorin
  • 390
  • 1
  • 3
  • 18

1 Answers1

1

I notice that you don't call triStrem.RestartStrip(); after feeding in 3 vertices of a triangle in your geometry shader.

This informs the stream that a particular triangle strip has ended, and a new triangle strip will begin. If you don't do this, each (single) vertex passed to the stream will add on to the existing triangle strip, using the triangle strip pattern: https://en.wikipedia.org/wiki/Triangle_strip

I'm fairly new to geo-shaders myself, so I'm not sure if this is your issue or not, I don't THINK the RestartStrip function is called automatically at the end of each geomerty-shader, but have not tested this. Rather I think it gets called automatically only when you you reach the maxvertexcount. For a single triangle, I would set the maxvertexcount to 3, not the 12 you have now. (I also know it can be tough to get ANY shader answers so figgured I'd try to help.)

Glurth
  • 290
  • 1
  • 17
  • I actually really appreciate this. I'm not sure this will fix it, as I opted to move in a different direction to get the effect I wanted without a geometry shader, but that is a very important piece of information about triangles and I'll be sure to remember it in the future. – Valevalorin Apr 11 '16 at 16:01
  • didn't address that options, but if your end-goal is "I expect the output to be the original object, but black." Why not just output float4(0,0,0,1) (black), from your fragment shader? – Glurth Apr 11 '16 at 16:20
  • At the time I didn't realize that just by adding a second "Pass" to the shader could I generate another image. I thought I had to explicitly create a geometry shader in order to create an additional image. – Valevalorin Apr 11 '16 at 17:22