仅连接一个三角形的边的轮廓检测(几何着色器)
Silhouette detection (geometry shader) for edges that connect only one triangle
我想使用几何着色器绘制网格轮廓(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 不应该有任何顶点。
我删除了:
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(RESTART_INDEX);
在抽签过程中,这是结果:
更接近期望的结果。
在构建邻接索引缓冲区时可以解决此问题的另一种可能解决方案。
// 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;
}
不要使用第一个 post 中提到的 RESTART_INDEX,而是使用相同的顶点。边三角形将有一个边长为 0 的相邻三角形(由相同的顶点构建)。我认为这需要在 gs 期间检查。
几何着色器是否触发邻接信息不完整的前三角形?
如果一个三角形的边不属于任何其他三角形,那么它仍然与它自己的三角形的背面相邻。例如:如果图中没有其他三角形附加到 e1,则可以使用三角形的第三个顶点(在本例中为 4,因为 e1 由 0 和 2 组成)代替 1。这不需要任何额外的检查几何着色器。
我想使用几何着色器绘制网格轮廓(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 不应该有任何顶点。
我删除了:
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(RESTART_INDEX);
在抽签过程中,这是结果:
更接近期望的结果。
在构建邻接索引缓冲区时可以解决此问题的另一种可能解决方案。
// 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;
}
不要使用第一个 post 中提到的 RESTART_INDEX,而是使用相同的顶点。边三角形将有一个边长为 0 的相邻三角形(由相同的顶点构建)。我认为这需要在 gs 期间检查。
几何着色器是否触发邻接信息不完整的前三角形?
如果一个三角形的边不属于任何其他三角形,那么它仍然与它自己的三角形的背面相邻。例如:如果图中没有其他三角形附加到 e1,则可以使用三角形的第三个顶点(在本例中为 4,因为 e1 由 0 和 2 组成)代替 1。这不需要任何额外的检查几何着色器。