pazduha
pazduha

Reputation: 147

GLSL geometry shader matrices

I have the following vertex shader:

#version 150 core

attribute vec4 vertex;
varying vec3 vert;
varying float zdepth;

uniform mat4 projMatrix;
uniform mat4 mvMatrix;

void main() {
   vert = vertex.xyz;
   zdepth = -(mvMatrix * vertex).z;
   gl_Position = projMatrix * mvMatrix * vertex;
}

and geometry shader:

#version 150 core


uniform mat4 projMatrix;
uniform mat4 mvMatrix;

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

void main() {



    vec4 p0 = gl_in[0].gl_Position;
    vec4 p1 = gl_in[1].gl_Position;
    vec4 p2 = gl_in[2].gl_Position;
    vec4 p3 = gl_in[3].gl_Position;

    vec4 v0 = normalize(p1-p0);
    vec4 v1 = normalize(p2-p1);
    vec4 v2 = normalize(p3-p2);

    vec4 n11 = normalize(v1-v0);
    vec4 n12 = -n11;

    vec4 n21 = normalize(v2-v1);
    vec4 n22 = -n21;

    gl_Position = p1+n11*0.2;
    EmitVertex();
    gl_Position = p1+n12*0.2;
    EmitVertex();
    gl_Position = p2+n21*0.2;
    EmitVertex();
    gl_Position = p2+n22*0.2;
    EmitVertex();

    EndPrimitive();
}

The task of the geometry shader is to convert a line strip into triangle strip. This is what I get for a line strip spiral:

spiral triangle strip

I want to have the triangle strip normal always pointing in the viewer direction and get a even thickness. Of course it has to be less thick further away.

I need to rotate the n11,n12,n21,n22 so they are parallel to the view plane: normals

I would probably need to manipulate v0,v1,v2 with projMatrix and mvMatrix? Thanks!

Upvotes: 0

Views: 488

Answers (2)

pazduha
pazduha

Reputation: 147

I don't get good results with this code. I guess it has something to do with the mvMatrix applied in the vertex shader and then using it again in right and up vectors.

I come up with a new code that works relatively well:

Vertex shader:

#version 150 core

attribute vec4 vertex;
varying vec3 vert;


uniform mat4 projMatrix;
uniform mat4 mvMatrix;
uniform vec3 camPos;

void main() {
   vert = vertex.xyz;

   gl_Position = vertex;
}

Geometry shader:

#version 150 core


uniform mat4 projMatrix;
uniform mat4 mvMatrix;
uniform vec3 camPos;

layout(lines_adjacency) in;
layout(triangle_strip, max_vertices = 6) out;

void main() {


    vec4 p0 = gl_in[0].gl_Position;
    vec4 p1 = gl_in[1].gl_Position;
    vec4 p2 = gl_in[2].gl_Position;
    vec4 p3 = gl_in[3].gl_Position;

    vec3 forward1 = normalize(camPos - p1.xyz);
    vec3 forward2 = normalize(camPos - p2.xyz);

    vec3 v0 = normalize(vec3(p1-p0));
    vec3 v1 = normalize(vec3(p2-p1));
    vec3 v2 = normalize(vec3(p3-p2));

    vec3 v0p1 = normalize(v0-(dot(v0,forward1))*forward1);
    vec3 v1p1 = normalize(v1-(dot(v1,forward1))*forward1);

    vec3 v1p2 = normalize(v1-(dot(v1,forward2))*forward2);
    vec3 v2p2 = normalize(v2-(dot(v2,forward2))*forward2);


    vec3 n0p1 = normalize(cross(v0p1,forward1));
    vec3 n1p1 = normalize(cross(v1p1,forward1));

    vec3 n1p2 = normalize(cross(v1p2,forward2));
    vec3 n2p2 = normalize(cross(v2p2,forward2));


    vec3 n11 = normalize(n0p1+n1p1);
    vec3 n12 = -n11;

    //if (n11[0]<0){
        //n11 = n12;
        //n12 = -n11;
   // }

    vec3 n21 = normalize(n1p2+n2p2);
    vec3 n22 = -n21;

    //if (n21[0]<0){
       // n21 = n22;
        //n22 = -n21;
   // }

    gl_Position =  projMatrix * mvMatrix * vec4(p1.xyz+n11*0.2,1.0);
    EmitVertex();
    gl_Position =  projMatrix * mvMatrix * vec4(p1.xyz+n12*0.2,1.0);
    EmitVertex();

//    EndPrimitive();

    gl_Position =  projMatrix * mvMatrix * vec4(p2.xyz+n21*0.2,1.0);
    EmitVertex();
    gl_Position =  projMatrix * mvMatrix * vec4(p2.xyz+n22*0.2,1.0);
    EmitVertex ();

    EndPrimitive();

//    gl_Position =  projMatrix * mvMatrix * p1;
//    EmitVertex();
//    gl_Position =  projMatrix * mvMatrix * p2;
//    EmitVertex ();

//    EndPrimitive();


}

I work without the matrixes applied. And I basiclly just included eye to point vector. So everything on screen seems turned to the eye.

Upvotes: 0

Andon M. Coleman
Andon M. Coleman

Reputation: 43389

The projection matrix should not be applied to the vertex shader, I would do this all in view-space and then transform the final result into clip-space in the geometry shader. This avoids having to divide everything by W in the geometry shader.

You want to screen-align each of your triangles, which is very easy to do in a geometry shader (this is effectively billboarding). Pull the right/up vectors out of your ModelView matrix and then use those to calculate the offset in X and Y.

Geometry Shader Pseudo-code:

// Right = Column 0
vec3 right = vec3 (mvMatrix [0][0], 
                   mvMatrix [1][0], 
                   mvMatrix [2][0]);

// Up = Column 1
vec3 up = vec3 (mvMatrix [0][1], 
                mvMatrix [1][1], 
                mvMatrix [2][1]);


//
// Screen-align everything, and give a width of 0.4
//

gl_Position = projMatrix * ((p1+n11*0.2) - vec4 ((right + up) * 0.2, 0.0));
EmitVertex();
gl_Position = projMatrix * ((p1+n12*0.2) - vec4 ((right - up) * 0.2, 0.0));
EmitVertex();
gl_Position = projMatrix * ((p2+n21*0.2) + vec4 ((right - up) * 0.2, 0.0));
EmitVertex();
gl_Position = projMatrix * ((p2+n22*0.2) + vec4 ((right + up) * 0.2, 0.0));
EmitVertex ();

Upvotes: 1

Related Questions