Sign in to follow this  
arthurw

Per-face data in a GLSL geometry shader (GLSL 1.5)

Recommended Posts

GLSL newbie question: how do pass per-face data to a GLSL geometry shader? I'm targeting GLSL 1.5.

What I'm trying to do specifically is decide whether to use the vertex normals or generate a face normal (via the cross product) for each face in the object. I have this working across the entire object via a uniform variable (i.e. toggle between smooth and flat shading); however, I'd like to pass a per-face flag to allow finer grain control. Is there some way I should be using [b]gl_PrimitiveIDIn [/b]to accomplish this? I'm fairly confident in how to pass down per-vertex arrays of data and using uniforms, but I'm not sure of the middle ground of per-face data works. I realize I could duplicate vertices between faces and simply pass per-face data as redundant per-vertex data, but I'd prefer not use that approach if there are other options.

For reference, below is a [i]simplified [/i]version of the geometry shader I currently have that uses a uniform for the whole object rather than per-face basis. In other words, what I'm trying to do if replace that "unifFlatNormals" variable with a per-face variable.

[source lang="cpp]

uniform int unifFlatNormals;

in vec3 geomVertexEc[]; // Vertex position in eye coordinates from the vertex shader
in vec3 geomNormalEc[]; // Vertex normal in eye coordinates from the vertex shader

varying out vec3 fragNormalEc;

vec3 computeNormal (vec3 v0, vec3 v1, vec3 v2)
{
vec3 a = v2 - v1;
vec3 b = v1 - v0;
return normalize( cross (b, a) );
}

void main()
{
vec3 n = computeNormal(geomVertexEc[0], geomVertexEc[1], geomVertexEc[2]);

for (int i = 0; i < gl_VerticesIn; i++)
{
gl_Position = gl_PositionIn[i];

if (unifFlatNormals == 1)
fragNormalEc = n; // Replace the per-vertex data with a uniform normal across the entire primitive
else
fragNormalEc = normalize(geomNormalEc[i]); // Pass the per-vertex data directly

EmitVertex();
}
EndPrimitive();
}
[/source]

Share this post


Link to post
Share on other sites
You should give it a version number such as #version 140
so that the compiler will know what you are targeting.

To send per face data, you would use the "flat" qualifier.
It would look like this
flat in vec2 Texcoord;

and notice how "varying" is illegal in version 140

If you want smoothness, then
smooth in vec2 Texcoord;

Share this post


Link to post
Share on other sites
Following up on my own post...

V-man, thanks - I appreciate the reply. However, I was looking to do something a bit different. I didn’t want to control the interpolation level (the smooth/flat shading example for a poor one on my part, sorry); I wanted to figure out how to pass down [i]arbitrary [/i]data on a per-face basis to the geometry shader. Some effects could be done via per-vertex attributes and the “flat” keyword, but would require figuring out a unique provoking vertex for each face to know where to assign those face attributes - a complication which I wanted to avoid.

The solution for what I wanted I realized was quite easy:

[list][*]Create a 1D texture of width = number of faces[*]Fill the texture so that each texel represents the data for one face[*]Index the texture in the geometry shader by (gl_PrimitiveIDIn + .5) / textureSize(sampler, 0)[/list]
That got me exactly what I was looking for. Again, thanks for the initial reply - just wanted to follow up in case others were interested.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this