当您的立方体的顶点数据主要用于 GL_TRIANGLES 时,尝试将绘图模式切换到 GL_LINE、GL_LINE_STRIP 或 GL_LINE_LOOP 会显示一些有趣的结果,但没有一个可以提供立方体的良好线框表示。
有没有办法构造立方体的顶点和索引数据,以便简单地在 GL_LINES/GL_LINE_STRIP/GL_LINE_LOOP 和 GL_TRIANGLES 之间切换绘制模式提供很好的结果?或者是获得一个好的线框来重新创建专门用于其中一种线模式的顶点的唯一方法?
最实用的方法很可能是最简单的方法:使用单独的索引数组进行线和三角形渲染。当然没有必要复制顶点属性,但是用相同的索引绘制完全不同的图元类型听起来很成问题。
要实现这一点,您可以使用两个不同的索引 ( GL_ELEMENT_ARRAY_BUFFER
) 缓冲区。或者,更优雅的恕我直言,使用单个缓冲区,并将两组索引都存储在其中。假设您需要triIdxCount
用于三角形渲染和lineIdxCount
线渲染的索引。然后,您可以使用以下命令设置索引缓冲区:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
(triIdxCount + lineIdxCount) * sizeof(GLushort), 0,
GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
0, triIdxCount * sizeof(GLushort), triIdxArray);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
triIdxCount * sizeof(GLushort), lineIdxCount * sizeof(GLushort),
lineIdxArray);
然后,当您准备好绘制时,设置所有状态,包括索引缓冲区绑定(理想情况下使用 VAO 进行所有状态设置),然后有条件地渲染:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
if (renderTri) {
glDrawElements(GL_TRIANGLES, triIndexCount, GL_UNSIGNED_SHORT, 0);
} else {
glDrawElements(GL_LINES, lineIdxCount, GL_UNSIGNED_SHORT,
triIndexCount * sizeof(GLushort));
}
从内存使用的角度来看,拥有两组索引的开销适中。实际的顶点属性数据通常比索引数据大很多,这里的关键是属性数据没有被复制。
如果您不严格要渲染线条,而只是对线框类型的渲染有要求,那么还有其他选择。例如,有一种优雅的方法(我自己从未实现过,但看起来很聪明),您只绘制靠近多边形边界的像素,并根据到多边形边缘的距离丢弃片段着色器中的内部像素。这个问题(我提供了一个答案)详细说明了该方法:Wireframe shader - Issue with Barycentric coordinates when using shared vertices。