Silhouette detection (geometry shader) for edges that only connect one triangle
I want to draw the silhouette of a mesh using a geometry shader (line_strip).
The problem occurs when the mesh has edges with only one triangle (for example, the edge of the fabric). Closed (all edges connect 2 triangles) meshes work.
I built an adjacency index buffer using RESTART_INDEX where the adjacent vertex did not exist, during rendering I tried to use:
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(RESTART_INDEX); // RESTART_INDEX = ushort(-1)
Result:
As you can see the head, legs, arms are all right, there are not many other parts of the model.
// silhouette.gs.glsl
void main(void) {
vec3 e1 = gs_in[2].vPosition - gs_in[0].vPosition; // 1 ---- 2 ----- 3
vec3 e2 = gs_in[4].vPosition - gs_in[0].vPosition; // \ / \ /
vec3 e3 = gs_in[1].vPosition - gs_in[0].vPosition; // \ e1 \ /
vec3 e4 = gs_in[3].vPosition - gs_in[2].vPosition; // \ / \ /
vec3 e5 = gs_in[4].vPosition - gs_in[2].vPosition; // 0 -e2-- 4
vec3 e6 = gs_in[5].vPosition - gs_in[0].vPosition; // \ /
// // \ /
vec3 vN = cross(e1, e2); // \ /
vec3 vL = u_vLightPos - gs_in[0].vPosition; // 5
How does gs handle vertices when it encounters a primitive restart index? Example: for some triangles 1,3 or 5 should not have vertices.
source to share
If the edge of the triangle is not part of any other triangle, it is still adjacent to the back face of its own triangle. For example: if there is no other triangle attached to e1 in the diagram, you can use the third vertex of the triangle (4 in this case, since e1 consists of 0 and 2) instead of 1. This will not require any additional check of the geometry shader.
source to share
Another possible solution to this problem would be to build an adjacency index buffer.
// for every mesh
// for every triangle in the mesh // first pass - edges & neighbors
...
// for every triangle in the mesh // second pass - build indices
const triangle_t* triangle = &tcache[ti]; // unique index triangles
for(i = 0; i < 3; ++i) // triangle = 3 edges
{
edge_t edge(triangle->index[i], triangle->index[(i+1) % 3]); // get edge
neighbors_t neighbors = oEdgeMap[edge]; // get edge neighbors
ushort tj = getOther(neighbors, ti); // get the opposite triangle index
ushort index = RESTART_INDEX; // = ushort(-1)
if(tj != (ushort)(-1))
{
const triangle_t& opposite = tcache[tj]; // opposite triangle
index = getOppositeIndex(opposite, edge) // opposite vertex from other triangle
}
else
{
index = triangle->index[i];
}
indices[ii+i*2+0] = triangle->index[i];
indices[ii+i*2+1] = index;
}
Instead of using RESTART_INDEX as mentioned in the first post, use the same vertex. Triangles of a triangle will have an adjacent triangle with an edge of length 0 (built from the same vertices). I think this needs to be checked during gs.
Is the geometry shader fire in front of a triangle with incomplete adjacency information?
source to share