仅连接一个三角形的边缘的轮廓检测(几何着色器)

Posted

技术标签:

【中文标题】仅连接一个三角形的边缘的轮廓检测(几何着色器)【英文标题】:Silhouette detection (geometry shader) for edges that connect only one triangle 【发布时间】:2015-07-03 11:45:10 【问题描述】:

我想使用几何着色器(line_strip)绘制网格轮廓。

当网格的边缘只有一个三角形(如布的边缘)时,就会出现问题。封闭(所有边连接 2 个三角形)网格工作。

我使用 RESTART_INDEX 构建邻接索引缓冲区,其中相邻顶点不存在,在渲染期间我尝试使用:

glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(RESTART_INDEX); // RESTART_INDEX = ushort(-1)

结果:

如你所见,头、脚、手都还可以,模型的其他部分就没有那么多了。

// 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

gs 在遇到原始重启索引时如何管理顶点?示例:对于某些三角形,1,3 或 5 不应有任何顶点。

【问题讨论】:

【参考方案1】:

如果三角形边不属于任何其他三角形,则它仍然与其自己三角形的背面相邻。例如:如果图表中没有附加到 e1 的其他三角形,则可以使用三角形的第三个顶点(在本例中为 4,因为 e1 由 0 和 2 组成)代替 1。这不需要任何额外的检查几何着色器。

【讨论】:

我想就是这样。谢谢。【参考方案2】:

我删除了:

glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(RESTART_INDEX);

在绘制过程中,结果如下:

更接近预期的结果。

【讨论】:

但是如果我这样做,最后一个三角形(到布料边缘的那个,边缘只有一个邻居的那个)不会被检测到边缘。【参考方案3】:

在构建邻接索引缓冲区时可以解决此问题的另一种可能解决方案。

// 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;
        

不要使用第一篇文章中提到的 RESTART_INDEX,而是使用相同的顶点。边三角形将有一个长度为 0 的相邻三角形(由相同的顶点构建)。我认为这需要在 gs 期间进行检查。

几何着色器是否会触发邻接信息不完整的前三角形?

【讨论】:

以上是关于仅连接一个三角形的边缘的轮廓检测(几何着色器)的主要内容,如果未能解决你的问题,请参考以下文章

图像轮廓(1)

使用openCV进行边缘检测二值化轮廓轮廓检测BGR灰度图二值化,专栏:各种openCV实践的案例

opencv——轮廓发现与轮廓分析

从图像边缘到物体轮廓

渲染期间模型的三角形计数加倍

opencv---(腐蚀膨胀边缘检测轮廓检索凸包多边形拟合)