opengl - 如何将大型四边形基元数组转换为三角形基元?

标签 opengl glsl shader triangulation

我有一个现有的系统,它提供 3D 网格。提供的数据是一个包含 3 个分量 (x, y, z) 的顶点坐标数组和一个索引列表。
问题是索引列表是一个连续的四元组数组。
必须使用核心配置文件使系统可运行 OpenGL Context首先,然后也是 OpenGL ES 3.x。

我知道所有四边形都具有相同的缠绕顺序(逆时针方向),但我没有关于四边形的更多信息。我对他们的关系或邻接一无所知。

由于我想使用核心配置文件 Context对于渲染,我不能使用 GL_QUAD原始类型。我必须将四边形转换为三角形。

当然,四边形索引数组可以轻松转换为三角形索引数组:

std::vector<unsigned int> triangles;
triangles.reserve( no_of_indices * 6 / 4 );
for ( int i = 0; i < no_of_indices; i += 4 )
{
    int tri[] = { quad[i], quad[i+1], quad[i+2], quad[i], quad[i+2], quad[i+3] };
    triangles.insert(triangles.end(), tri, tri+6 );
}

如果只需要完成一次,那么这就是解决方案。但是网格数据不是静态的。数据可以动态变化。
数据并不是每次都连续变化,而是不可预测的随机变化。

另一个简单的解决方案是创建一个顶点数组对象,它直接引用带有四边形的元素数组缓冲区,并使用 GL_TRIANGLE_FAN 在循环中绘制它们。原始类型:
for ( int i = 0; i < no_of_indices; i += 4 )
    glDrawElements( GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * 4) );

但我希望有更好的解决方案。我正在寻找一种可能性,可以通过一次绘制调用来绘制四边形,或者在 GPU 上将四边形转换为三角形。

最佳答案

If that has to be done only once, then that would be the solution. But the mesh data are not static.



网格数据可能是动态的,但该列表的拓扑结构是相同的。每 4 个顶点是一个四边形,因此每 4 个顶点代表三角形 (0, 1, 2) 和 (0, 2, 3)。

因此,您可以构建一个任意大的静态索引缓冲区,其中包含这些数字(0、1、2、0、2、3、4、5、6、4、6、7 等)的不断增加的序列。你甚至可以use baseVertex rendering偏移它们以使用相同的索引缓冲区渲染不同系列的四边形。

我的建议是让索引缓冲区使用 GLushort作为索引类型。这样,您的索引数据每个四边形仅占用 12 个字节。使用 shorts 在单个绘图命令中限制为 16384 个四边形,但您可以重用相同的索引缓冲区来绘制多个系列的四边形 baseVertex渲染:
constexpr GLushort batchSize = 16384;
constexpr unsigned int vertsPerQuad = 6;
void drawQuads(GLuint quadCount)
{
  //Assume VAO is set up.
  int baseVertex = 0;
  while(quadCount > batchSize)
  {
    glDrawElementsBaseVertex(GL_TRIANGLES​, batchSize * vertsPerQuad, GL_UNSIGNED_SHORT, 0, baseVertex​ * 4);
    baseVertex += batchSize;
    quadCount -= batchSize;
  }
  glDrawElementsBaseVertex(GL_TRIANGLES​, quadCount * vertsPerQuad, GL_UNSIGNED_SHORT, 0, baseVertex​ * 4);
}

如果你想要稍微少一点的索引数据,你可以使用 primitive restart indices .这允许您指定一个索引来表示“重新启动原语”。这允许您使用 GL_TRIANGLE_STRIP基元并将基元分解成碎片,同时仍然只有一个绘制调用。因此,不是每个四边形有 6 个索引,而是 5 个,第 5 个是重启索引。所以现在你的 GLushort索引每个四边形仅占用 10 个字节。然而,batchSize现在必须是 16383,因为索引 0xFFFF 是为重新启动保留的。和 vertsPerQuad必须是 5。

当然,baseVertex 渲染在图元重启时也能正常工作,所以上面的代码也能正常工作。

关于opengl - 如何将大型四边形基元数组转换为三角形基元?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49137481/

相关文章:

c++ - 将帧缓冲区附加到纹理错误

linux - 我的电脑支持 OpenGL 2.1 吗?

c - 如何在 opengl 中正确地构造四边形

javascript - WebGL alpha 取决于与原点的距离

java - OpenGL 3D 中的平滑模型移动

macos - 如何在 mac os x 上安装 libGL?

java - Mac 上的 GLSL 着色器错误,但不是 Windows : cannot convert from 'const int' to '4-component vector of float'

c++ - D3D10 HLSL : How do I bind a texture to a global Texture2D via reflection?

optimization - GLSL 着色器中 cos() 和 sin() 函数的速度?

android - Perlin 噪声着色器