Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am playing with a geometry shader and I am wondering why it doesn't generate geometry for each vertex in all meshes?

  • I don't think this is a Cull problem because the same vertices generate geometry as you rotate around and setting Cull Off changes nothing.
  • Another problem could be a multiply by zero somewhere but I tried to eliminate as many variables as possible and still have the issue.
  • A third unlikely issue could be limiting the output amount somewhere. I didn't set anything explicitly to hinder that.

I notice the problem on a Cube(5/8) and Quad(2/4) but seems to generate all the geometry fine on a plane, cylinder, etc. The following are some results from using the bare-bones geometry shader.

Cube (closest: Unity default, further back: Cinema 4D exported .fbx cube):

Quad:

It seems to work fine on a plane (update: It is actually missing a whole row on each axis)

Unity Shader Code GeometryShaderTest1.shader:

Note: If you are testing out the shader and nothing is displaying; Rotate your camera around so the normals are facing the right direction to show up.

Shader "Custom/GeometryShaderTest1" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _Amount ("Height Adjustment", Float) = 0.0
    }
    SubShader {
        Pass {
            Tags { "RenderType"="Opaque" }
            LOD 200

            CGPROGRAM
            #pragma target 5.0
            //#pragma addshadow
            #pragma vertex vert
            #pragma geometry GS_Main
            #pragma fragment frag
            #include "UnityCG.cginc"

            // Vert to geo
            struct v2g
            {
                float4 pos: POSITION;
            };

            // geo to frag
            struct g2f
            {
                float4 pos: POSITION;
            };


            // Vars
            fixed4 _Color;
            float _Amount;


            // Vertex modifier function
            v2g vert(appdata_base v) {

                v2g output = (v2g)0;
                output.pos = mul(_Object2World, v.vertex);
                // Just testing whether all vertices affected
                output.pos.y -= _Amount;

                return output;
            }

            // GS_Main(point v2g p[1], inout TriangleStream<g2f> triStream)
            // GS_Main(line v2g p[2], inout TriangleStream<g2f> triStream)
            // GS_Main(triangle v2g p[3], inout TriangleStream<g2f> triStream)
            [maxvertexcount(4)]
            void GS_Main(point v2g p[1], inout TriangleStream<g2f> triStream)
            {
                float4 v[4];

                float3 asdfUp = float3(0, 1, 0);
                float3 asdfRight = float3(0, 0, 1);
                v[0] = float4(p[0].pos + 0.25 * asdfRight - 0.25 * asdfUp, 1.0f);
                v[1] = float4(p[0].pos + 0.25 * asdfRight + 0.25 * asdfUp, 1.0f);
                v[2] = float4(p[0].pos - 0.25 * asdfRight - 0.25 * asdfUp, 1.0f);
                v[3] = float4(p[0].pos - 0.25 * asdfRight + 0.25 * asdfUp, 1.0f);

                float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
                g2f pIn;
                pIn.pos = mul(vp, v[0]);
                triStream.Append(pIn);

                pIn.pos = mul(vp, v[1]);
                triStream.Append(pIn);

                pIn.pos = mul(vp, v[2]);
                triStream.Append(pIn);

                pIn.pos = mul(vp, v[3]);
                triStream.Append(pIn);
            }

            fixed4 frag(g2f input) : COLOR {
                return float4(1.0, 0.0, 0.0, 1.0); 
            }

            ENDCG
        }


    }

    FallBack "Diffuse"
}

Geometry shader resources:

share|improve this question

1 Answer 1

up vote 2 down vote accepted

From the OpenGL wiki:

The input_primitive​ type must match the primitive type used with the drawing command that renders with this shader program.

Given, Unity is probably using DirectX on Windows, but the same thing should hold true. Because your shader is asking for a point, it is only taking the first point from each primitive and ignoring the rest.

Assuming Unity draws with triangles, you need to change the first parameter to receive that, set maxvertexcount to 12, and generate three quads instead of one. Quick example:

[maxvertexcount(12)]
void GS_Main(triangle v2g p[3], inout TriangleStream<g2f> triStream)
{
    for(int i = 0; i < 3; i++)
    {
        // generate a quad with p[i]

        triStream.RestartStrip();
    }
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.