PDA

View Full Version : Lines to rectangles in Geometry Shader

Zyx_2000
10-19-2010, 11:56 AM
Hi, I have a beginner question about GLSL here. What I want to do is create a geometry shader with GLSL 3.30 that takes line primitives as input, and for each line outputs a triangle strip consisting of two triangles. Those two triangles should together make a rectangle, where the diagonal is the inputted line. Will this code do the job right? If not, how can I accomplish it?

#version 330

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

void main() {
vec2 p0 = gl_in[0].gl_Position;
vec2 p1 = gl_in[1].gl_Position;

gl_Position = vec4(p0, 0.0, 1.0);
EmitVertex();
gl_Position = vec4(p0.x, p1.y, 0.0, 1.0);
EmitVertex();
gl_Position = vec4(p1, 0.0, 1.0);
EmitVertex();
EndPrimitive();
gl_Position = vec4(p1.x, p0.y, 0.0, 1.0);
}

david_f_knight
10-19-2010, 08:26 PM
Without actually having tried to compile it, here are a few thoughts I have:

You have:
vec2 p0 = gl_in[0].gl_Position;
vec2 p1 = gl_in[1].gl_Position;
But gl_Position is a vec4, so you'll need something like:
vec2 p0 = gl_in[0].gl_Position.xy;

Also, I suspect you should not have EndPrimitive() where it is. I'm not sure, but I think EndPrimitive() will end the first triangle strip, which consists of just three vertices, and then you will emit your final vertex by itself which isn't enough to define a new triangle strip. If so, you should be able to just throw out the EndPrimitive() call altogether, or more properly put it at the end of your geometry shader, after the fourth gl_Position assignment statement.

Zyx_2000
10-20-2010, 03:03 AM
Well, if EndPrimitive() works that way, it makes a lot more sense. And since gl_Position is a vec4, I could also use points instead of lines to pass all the coordinates of the rectangle I want, right?

david_f_knight
10-20-2010, 05:04 PM
Yes, as long as you want to make axis-aligned rectangles (as you have in your example), and all the Z coordinates have a value of zero (as you have in your example), then you could just pass the geometry shader points, and turn them into rectangles, like this:

vec2 p0 = gl_in[0].gl_Position.xy;
vec2 p1 = gl_in[1].gl_Position.zw;
However, if you do that, then you should not perform any transformations on your points in the vertex shader... unless you do something like this:

vec2 p0 = gl_in[0].gl_Position.xy;
vec2 p1 = p0 + gl_in[1].gl_Position.zw;
In this example, gl_Position.z and gl_Position.w contain offsets rather than absolute positions, so you could transform your points in the vertex shader as long as you never modify the Z or W components (or do so with great thought about how to do what you really want).