Search code examples
c++openglglslgeometry-shader

Passing Data Through GLSL Shaders


I'm having some trouble passing data through my shaders, notably the Geometry shader. I've never used a Geometry Shader before so I'm having a little trouble understanding the way it passes data.

Basically, before the Geometry shader, I'd pass data from the Vertex Shader to the Fragment simply using in/out qualifiers. Like I'd have:

Vertex Shader!

out vec3 worldNormal;
out vec3 worldView;

Fragment Shader:

in vec3 ex_worldNorm;
in vec3 ex_worldView;

So, for the Geometry Shader, would I have to do something like this to pass data?

in vec3 ex_worldNorm[];
in vec3 ex_worldView[];

out vec3 ex_worldNorm[];
out vec3 ex_worldNorm[];

My question is, how do I pass data between each Shader properly? Like, is this the way to do it? (because it's not working for me!)


Solution

  • The unbounded arrays for the input are correct for a Geomtery Shader (the size will be determined by input type in the layout qualifier), but the output cannot be an array.

    You output vertices one at a time by writing values to all of the output variables and then calling EmitVertex (...). Any output variable that is not written to between calls to EmitVertex (...) will be undefined.


    Here is a very simple example Geometry Shader that does what you want:

    #version 330
    
    
    layout (triangles) in; // This will automatically size your two arrays to 3, and also
                           //   defines the value of `gl_in.length ()`
    
    in vec3 worldNormal [];
    in vec3 worldView   [];
    
    // ^^^ Names match up with Vertex Shader output
    
    
    layout (triangle_strip, max_vertices = 3) out;
    
    out vec3 ex_worldNorm;
    out vec3 ex_worldView;
    
    // ^^^ Names match up with Fragment Shader input
    
    
    void main (void)
    {
      // For each input vertex, spit one out
      for (int i = 0; i < gl_in.length (); i++) {
        ex_worldNorm = worldNormal [i];
        ex_worldView = worldView   [i];
        EmitVertex ();
      }
    }