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:

enter image description here

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.

+3


source to share


3 answers


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.



+3


source


I removed:

glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(RESTART_INDEX);

      

while passing the pass and this is the result:



enter image description here

which is closer to the desired result.

+1


source


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?

+1


source







All Articles