1

The effect I want to achieve is vertex color with sharp contours. So inside the triangle the fragment shader should use the color of whatever vertex is closest to that fragment.

Now when thinking about it, the only solution I can come up with is assigning tex coords 1,0,0 0,1,0 and 0,0,1 to the three vertices and have 2 (reoordered) duplicates of the vertex color array and then choose from the color aray of which the corresponding tex coord is highest. This method would at least add 9 more floats to each vertex. Which will slow down the application as my meshes are changing quit often and increase the memory footprint significantly.

Is there a better/easier way to achieve this?

Roest
  • 826
  • 6
  • 16
  • Well. If you want to decide on the color in the fragment shader, you need to have access to all 3 vertices' colors. However, that does not mean that you have to duplicate that data in the input attribute arrays. You could use a geometry shader to duplicate the data on the fly. OTOH, you would probably be better off by generating a triange fan out of 3 triangles for each input triangle and don't interpolate colors in them at all, avoiding the per-fragment decision completely. – derhass Aug 21 '14 at 19:32
  • Yes I know that if I want to do it in the fragment shader I need access to all 3 colors. I think traingle fan won't work as it splits the original triangle in a way that the vertices are now corners of two triangles in the fan. – Roest Aug 21 '14 at 19:44
  • The tex coords would just be [barycentric coordinates](http://en.wikipedia.org/wiki/Barycentric_coordinate_system). I wonder whether this is the wrong center. I think you're looking for the circumcenter, not the barycenter. – Stefan Hanke Aug 22 '14 at 04:11

1 Answers1

1

[replaced incorrect original]

This should actually work...

//vert
out vec3 colour;
...

//geom
//simple passthrough but dupe colours to separate and include barycentric coord
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in vec3 colour[];
flat out vec3 colours[3];
out vec3 coord;
...
for (int i = 0; i < 3; ++i)
    colours[i] = colour[i];
for (int i = 0; i < 3; ++i)
{
    coord = vec3(0.0);
    coord[i] = 1.0;
    gl_Position = gl_in[i].gl_Position;
    EmitVertex();
}

//frag
flat in vec3 colours[3]; //triangle's 3 vertex colours
in vec3 coord; //barycentric weights as a result of interp
...
//get index of biggest coord
int i = (coord.x > cood.y && coord.x > coord.z) ? 0 :
    ((coord.y > coord.z) ? 1 : 2);
//choose that colour
vec3 fragColour = colours[i];
jozxyqk
  • 16,424
  • 12
  • 91
  • 180
  • Thanks. That's surprisingly simple. Though I still have small problem with it. Some triangles seem to slip through http://imgur.com/QRKb9Bt After staring at the code for one hour I still don't see why and how – Roest Aug 28 '14 at 17:58
  • @Roest Actually, I'm not sure what I was thinking not using the geometry shader. I'm surprised it kinda worked. I guess it'd be ok with `glDrawArrays(GL_TRIANGLES,...)` but for indices you'd really want a geometry shader. I'll update it. – jozxyqk Aug 28 '14 at 18:12
  • Yea I figured it out now. The reason it doesn't work is I'm using indices. I still like it because it's really simple. – Roest Aug 28 '14 at 18:15
  • @Roest It makes for an interesting challenge. Will ponder it tomorrow after some sleep. I guess you'd need enough varying vec3s to remove the chance of a collision with another vertex in the same triangle. Worst case is pretty bad. – jozxyqk Aug 28 '14 at 18:29