5
votes

I want to draw a square from point data with the geometry shader.

In the vertex shader, I emit a single point.

#version 330 core
void main() {
    gl_Position = vec4(0, 0, 0, 1.0);
}

In the geometry shader, I want to create a triangle strip forming a square.

The size is irrelevant at the moment so the model should have a size of 1 (ranging from (-0.5, -0.5) from the initial point position to (+0.5, +0.5).

I need help to calculate the position of the emitted vertices, as visible in the code:

#version 330 core

layout(points) in;
layout(triangle_strip, max_vertices=4) out;

out vec2 tex_coord;

uniform mat4x4 model;
uniform mat4x4 view;
uniform mat4x4 projection;

void main() {
    int i;
    for(i = 0; i < gl_in.length(); ++i) {
        mat4x4 trans;

        trans = //???
        gl_Position = projection * view * model * trans * gl_in[i].gl_Position;
        tex_coord = vec2(0, 0);
        EmitVertex();

        trans = //???
        gl_Position = projection * view * model * trans * gl_in[i].gl_Position;
        tex_coord = vec2(1, 0);
        EmitVertex();

        trans = //???
        gl_Position = projection * view * model * trans * gl_in[i].gl_Position;
        tex_coord = vec2(1, 1);
        EmitVertex();

        trans = //???
        gl_Position = projection * view * model * trans * gl_in[i].gl_Position;
        tex_coord = vec2(0, 1));
        EmitVertex();
    }
    EndPrimitive();
}

I thought to use trans to translate the initial point to the desired coordinates. How would I realize this?

Edit for clarity

I want to generate from a single point what else would be given by the vertex buffer; a single plane:

float vertex[] {
        -0.5,  0.5, 0.0,
         0.5,  0.5, 0.0,
         0.5, -0.5, 0.0,    
        -0.5, -0.5, 0.0
}

Instead I give only a point in the middle of these points and want to generate the real points by subtracting and adding the differences to the center (0.5 and -0.5 etc.). All I need is to know how to apply this transformation in the code (where the ??? are).

1
Might I inquire exactly why you want to do this? Point sprites (generally) accomplish the same thing producing a screen-aligned square, though the range of sizes can be limited. Otherwise, all you need to do is implement billboarding in the geometry shader.Andon M. Coleman
@genpfault As far as I understand your comment, that way I wouldn't still have to specify each vertex manually and therefore render the geometry shader useless for this case?Appleshell
@AndonM.Coleman I am not after a screen aligned sprite, I want to create the square in model space (as if I specified 4 vertices ranging from (-0.5, -0.5) to (0.5, 0.5) as vertex attribute) and then process it as if it were a regular 2-triangle square. Therefore I do the pvm manipulation in the geometry shader.Appleshell
I am a little more confused in this case, because you have no reference plane to orient the square in. Before you can generate the points, you need to know the plane they will all lie in.Andon M. Coleman
@AndonM.Coleman I want to generate what normally would be given by the vertex attribute; See my editAppleshell

1 Answers

4
votes

Judging by your updated question, I think this pseudo-code should get you pointed in the right direction. It seems to me that all you want to do is offset the x and y coordinates of your point by a constant amount, so an array is the perfect way to do this.

const vec3 offset [4] =
  vec3 [] ( vec3 (-0.5,  0.5, 0.0),
            vec3 ( 0.5,  0.5, 0.0),
            vec3 ( 0.5, -0.5, 0.0),
            vec3 (-0.5, -0.5, 0.0) );

const vec2 tc     [4] =
  vec2 [] ( vec2 (0.0, 0.0),
            vec2 (1.0, 0.0),
            vec2 (1.0, 1.0),
            vec2 (0.0, 1.0) );

void
main (void)
{
  int i;
  for (i = 0; i < gl_in.length (); ++i) {
    gl_Position = projection * view * model * (gl_in [i].gl_Position + offset [0]);
    tex_coord   = tc [0];
    EmitVertex   ();

    gl_Position = projection * view * model * (gl_in [i].gl_Position + offset [1]);
    tex_coord   = tc [1];
    EmitVertex   ();

    gl_Position = projection * view * model * (gl_in [i].gl_Position + offset [2]);
    tex_coord   = tc [2];
    EmitVertex   ();

    gl_Position = projection * view * model * (gl_in [i].gl_Position + offset [3]);
    tex_coord   = tc [3];
    EmitVertex   ();
  }
  EndPrimitive ();
}