Geometry shader for cycle problem

Hi,
I’m new in this forum and I’m new to openGL and shading languages.

I’m writing in GLSL a geometry shader that pick a line strip vertices and transform it to looks like a filled stroke, it’s like a tape; it’s a triangles strip.

I started my work from this shader https://github.com/openframeworks/openFr…aders/geom.glsl

THE PROBLEM: the problem is that now my shader scale the width of the strip processing it segment by segment; the scaling is based on the length of the segment; but this approach cause a big eye gap between small and big segment.
To solve this I thought to do a little buffer with the last segment width and start the next segment and to do a little control at the first vertex to don’t fall in error assigning it a width which doesn’t exists.
It doesn’t work.
I don’t manage why, the control point always think we are at the first vertex. Is not a simple error I think, I checked also after a walk with the dog :slight_smile: .

Here is the shader:


///////////////////////////////
// GLSL shaders
// PARAMETERS PASSED TO SHADERS
// float thickness default=0.1
// float limiter default=0.2
// vec3 lightDir default= 0.0 0.04 1.0
// line_strip vertices

////////////////
// VERTEX SHADER

#version 120

uniform float limiter;

void main(void)
{
    // just bit waving
    vec4 wave = vec4(gl_Vertex[0],gl_Vertex[1],gl_Vertex[2]*sin(gl_Vertex[0]),gl_Vertex[3]);
	gl_FrontColor =  gl_Color;
	gl_Position = wave;
}
//////////////////
// GEOMETRY SHADER
// input type: GL_LINES
// output type: GL_TRIANGLE_STRIP
// vertices out: 4

/***********************************************
 *  
 *  Based on:
 *  Geometry shader to convert lines into triangle strips
 *  Memo Akten
 *  www.memo.tv

************************************************/

#version 120
#extension GL_EXT_geometry_shader4 : enable

uniform float thickness;
uniform vec3 lightDir;
uniform float limiter;

void main(void) {
    // actual working vertices
    vec3 p0;
    vec3 p1;

    vec3 dir; // normalized direction vector from p0 to p1

    vec3 thick; // thick vector
    vec3 oldthick; // old thick vector
    float thickM; // thick modifier

    vec3 norm;
    
    // distance calculation stuff
    vec2 P;
    vec2 Q;
    
    // color stuff
    float fColMult;
    vec4 colMult;
    
    
    // loop stuff
    int i;
    bool first = true;
    
    vec3 up = vec3(0, 0, 1); // arbitrary up vector
    
    // go trought the vertices and do the transformation
    for(i=0; i<gl_VerticesIn; i++){
        if (first == true) { // maybe isn't a good way do a big control like this but is for debugging
            first = false; // seems this doesn't work
            // set working vertices
            p0 = gl_PositionIn[i].xyz;
            p1 = gl_PositionIn[i+1].xyz;
            
            // some calculations
            dir = normalize(p1 - p0);
            thick = normalize(cross(dir, up));
            norm = cross(thick, dir);
            
            fColMult = abs(dot(norm, lightDir)); // simple lighting
            
            P = vec2(p0[0],p0[1]);
            Q = vec2(p1[0],p1[1]);
            thickM = distance(P,Q)+0.02; // the lenght of the segment influeces his thickness
            
            if (thickM > limiter) { // clipping
                thickM = limiter;
            }
            thick *= thickness*thickM; // set calculated thickness
            
            gl_Position = gl_ModelViewProjectionMatrix * vec4(p0 - thick, 1.0);
            gl_FrontColor = vec4(gl_FrontColorIn[i].rgb * fColMult, 1.0);
            EmitVertex();
            
            gl_Position = gl_ModelViewProjectionMatrix * vec4(p0 + thick, 1.0);
            gl_FrontColor = vec4(gl_FrontColorIn[i].rgb * fColMult, 1.0);
            EmitVertex();
            
            gl_Position = gl_ModelViewProjectionMatrix * vec4(p1 - thick, 1.0);
            gl_FrontColor = vec4(gl_FrontColorIn[i+1].rgb * fColMult, 1.0);
            EmitVertex();
            
            gl_Position = gl_ModelViewProjectionMatrix * vec4(p1 + thick, 1.0);
            gl_FrontColor = vec4(gl_FrontColorIn[i+1].rgb * fColMult, 1.0);
            EmitVertex();
            
            oldthick = thick;
        } else {
            p0 = gl_PositionIn[i].xyz;
            p1 = gl_PositionIn[i+1].xyz;
            
            dir = normalize(p1 - p0);
            thick = normalize(cross(dir, up));
            norm = cross(thick, dir);
            
            fColMult = abs(dot(norm, lightDir)); // simple lighting
            
            P = vec2(p0[0],p0[1]);
            Q = vec2(p1[0],p1[1]);
            thickM = distance(P,Q)+0.02; // the lenght of the segment influeces his thickness
            
            if (thickM > limiter) { // clipping
                thickM = limiter;
            }
            thick *= thickness*thickM; // set calculated thickness
            
            gl_Position = gl_ModelViewProjectionMatrix * vec4(p0 - oldthick, 1.0);
            //gl_FrontColor = gl_FrontColorIn[i] * fColMult;
            gl_FrontColor = vec4(1.0,0.0,0.0,1.0); // if the is processed i surely see this
            EmitVertex();
            
            gl_Position = gl_ModelViewProjectionMatrix * vec4(p0 + oldthick, 1.0);
            //gl_FrontColor = gl_FrontColorIn[i] * fColMult;
            gl_FrontColor = vec4(1.0,0.0,0.0,1.0); // if the is processed i surely see this
            EmitVertex();
            
            gl_Position = gl_ModelViewProjectionMatrix * vec4(p1 - thick, 1.0);
            //gl_FrontColor = gl_FrontColorIn[i+1] * fColMult;
            gl_FrontColor = vec4(1.0,0.0,0.0,1.0); // if the is processed i surely see this
            EmitVertex();
            
            gl_Position = gl_ModelViewProjectionMatrix * vec4(p1 + thick, 1.0);
            //gl_FrontColor = gl_FrontColorIn[i+1] * fColMult;
            gl_FrontColor = vec4(1.0,0.0,0.0,1.0); // if the is processed i surely see this
            EmitVertex();
            
            oldthick = thick; // update the starting dimension
        }
    }
}

//////////////////
// FRAGMENT SHADER

void main (void)  // do nothing
{  
    gl_FragColor = gl_Color;
}

What is wrong? This is my first approach to opengl and shading and I’m learning everything via web.
You are my masters.

Thank you for the attention.

I’ve understood, I’m trying to do ham with carrots, right?

I’m in wrong because I didn’t studied WHAT a geometry shader is. It can not recognize old segments or old variables. Is always refreshing the processing each segment.
RIGHT?

Please tell me that I’m a donkey.

And sorry for my English.

I’m in wrong because I didn’t studied WHAT a geometry shader is. It can not recognize old segments or old variables. Is always refreshing the processing each segment.

What do you mean by that? A geometry shader operates on a single incoming primitive, just as a vertex shader operates on a single incoming vertex, and a fragment shader operates on a single incoming fragment. And the output values from a GS are made undefined after every Emit call, so you need to fill all of them in for every vertex you write.

If you’re drawing a line strip with 10 segments and you draw these as a GL_LINE_STRIP, then each segment will be processed independently as a 2 vertex primitive.

If you were to draw the line strip as GL_LINE_STRIP_ADJACENCY, you will have 4 vertices available to you in the geometry shader. This will give you read access to the previous and next line segments’ vertices while you process the current strip, though you won’t have access to previously computed values. That should be enough to smoothly blend the segments together.

You’ll need two extra vertices at the beginning and end of the strip for a line-adjacency primitive (12 total for a 10 segment line strip) which you can add by simply doubling the first and last vertex - 0,0,1,2,3,4,5,6,7,8,9,9. You can also linearly extrapolate the first and last vertex from the first and last line segments if that makes the geometry shader computation easier.

Yes, is what I’ve understood, thank for confirmation.

The only thing I did not understood is this: if I declare a variable outside the main it is always made undefined after every main() execution?

There are 3 variable declarations outside of main - uniforms, varying inputs and varying outputs. Uniforms will maintain their constant value, varying inputs will be filled with the new vertices to process, and varying outputs will be undefined.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.