Jump to content
  • Advertisement
Sign in to follow this  

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

This topic is 2591 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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 gl_PrimitiveIDIn 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 simplified 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;

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


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 arbitrary 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:

  • 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)
    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
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!