在一个 vbo 中绘制多个形状
Draw multiple shapes in one vbo
我想从一个 vbo 渲染多个 3D 立方体。每个立方体都有统一的颜色。
这时,我创建了一个vbo,其中每个顶点都有一个颜色信息。
是否可以为一种形状(顶点列表)只上传一种颜色?
我还想在同一着色器的 glDrawElements
方法中混合使用 GL_TRIANGLES
和 GL_LINES
。可能吗?
//编辑:我只有 OpenGL 2.1。稍后我想在 Android 上构建这个项目。
//编辑2:
我想渲染大量立方体(最多 150.000)。一个立方体有 24 个几何和颜色的顶点和 34 个索引。现在我的想法是创建一些 vbo(也许 50 个)并将多维数据集共享给 vbo。我希望这可以最大限度地减少开销。
关于您的问题:
是否可以为一种形状只上传一种颜色?
是的,你可以使用一个统一的而不是一个顶点属性(当然这意味着更多地方的变化)。但是,您需要为每个形状设置制服,并为每个不同颜色的形状设置不同的绘制调用。
是否可以在 glDrawElements 中混合使用 GL_TRIANGLES 和 GL_LINES?
是也不是。是的,但您将需要一个新的绘图调用(这是显而易见的)。你不能在同一个 drawcall 上做一些形状 GL_TRIANGLES 和一些形状 GL_LINES.
在伪代码中,这将如下所示:
draw shapes 1,2,10 from the vbo using color red and GL_TRIANGLES
draw shapes 3,4,6 from the vbo using color blue and GL_LINES
draw shapes 7,8,9 from the vb using color blue and GL_TRIANGLES
画很多立方体
是的,如果你想画一堆立方体,你可以为每个立方体指定一次颜色。
创建一个包含一个立方体顶点的 VBO。
// cube = 36 vertexes with glDrawArrays(GL_TRIANGLES)
vbo1 = [v1] [v2] [v3] ... [v36]
为每个立方体创建另一个具有视图矩阵和颜色的 VBO,并使用 1 的属性除数。(您可以使用相同的 vbo,但我会使用单独的。)
vbo2 = [cube 1 mat, color] [cube 2 mat, color] ... [cube N mat, color]
呼叫glDrawElementsInstanced()
或glDrawArraysInstanced()
。这将一遍又一遍地绘制立方体。
或者,您可以对每个立方体使用 glUniform()
,但这会限制您可以绘制的立方体数量。以上方法,让你轻松画出万千
混合 GL_TRIANGLES
和 GL_LINES
您必须为每种类型的基元调用一次 glDraw????()
。如果愿意,您可以两次使用相同的着色器。
对于 OpenGL 2.1,我认为没有一种合理的方法可以让每个立方体只指定一次颜色,并且仍然在一次绘制调用中绘制所有内容。
最直接的方法是,不要在 VBO 中使用颜色属性,而是在绘制调用之前直接指定它。假设您正在使用通用顶点属性,您当前将拥有:
glEnableVertexAttribArray(colorLoc);
glVertexAttripPointer(colorLoc, ...);
你这样做:
glDisableVertexAttribArray(colorLoc);
glVertexAttrib3f(colorLoc, r, g, b);
其中 glDisableVertexAttribArray()
仅在先前为该位置启用阵列时才需要。
最大的缺点是您只能在一次绘制调用中绘制具有相同颜色的立方体。在极端情况下,每个立方体一个绘制调用。当然,如果您有多个颜色相同的立方体,您仍然可以将它们批处理到一个绘制调用中。
您想知道这是否比为 VBO 中的每个顶点设置颜色更有效?不能笼统地说。在这种情况下,您总是会得到相同的答案:尝试两者,然后进行基准测试。我怀疑你会发现它有益。根据我的经验,获取顶点数据很少会成为主要的性能瓶颈。因此,删除一个属性可能不会给你带来太大的好处。另一方面,进行许多小的绘图调用绝对会(而且经常会)损害性能。
您可以使用一个混合选项。我不一定推荐它,只是为了集思广益。如果您使用的颜色数量相当有限,则可以在编码 "color index" 的 VBO 中使用单个标量属性。然后在顶点着色器中,您可以使用纹理查找将 "color index" 转换为实际颜色。
真正好的选择超出了 OpenGL 2.1。 @DietrichEpp 很好地解释了实例化渲染,对于这种情况,这是一个优雅的解决方案。
不,您可以不在同一个绘图调用中有直线和三角形。即使是 OpenGL 4.x 中最灵活的绘制调用,如 glDrawElementsIndirect()
,仍然只采用一种基元类型。
我想从一个 vbo 渲染多个 3D 立方体。每个立方体都有统一的颜色。 这时,我创建了一个vbo,其中每个顶点都有一个颜色信息。
是否可以为一种形状(顶点列表)只上传一种颜色?
我还想在同一着色器的 glDrawElements
方法中混合使用 GL_TRIANGLES
和 GL_LINES
。可能吗?
//编辑:我只有 OpenGL 2.1。稍后我想在 Android 上构建这个项目。
//编辑2: 我想渲染大量立方体(最多 150.000)。一个立方体有 24 个几何和颜色的顶点和 34 个索引。现在我的想法是创建一些 vbo(也许 50 个)并将多维数据集共享给 vbo。我希望这可以最大限度地减少开销。
关于您的问题:
是否可以为一种形状只上传一种颜色?
是的,你可以使用一个统一的而不是一个顶点属性(当然这意味着更多地方的变化)。但是,您需要为每个形状设置制服,并为每个不同颜色的形状设置不同的绘制调用。
是否可以在 glDrawElements 中混合使用 GL_TRIANGLES 和 GL_LINES?
是也不是。是的,但您将需要一个新的绘图调用(这是显而易见的)。你不能在同一个 drawcall 上做一些形状 GL_TRIANGLES 和一些形状 GL_LINES.
在伪代码中,这将如下所示:
draw shapes 1,2,10 from the vbo using color red and GL_TRIANGLES
draw shapes 3,4,6 from the vbo using color blue and GL_LINES
draw shapes 7,8,9 from the vb using color blue and GL_TRIANGLES
画很多立方体
是的,如果你想画一堆立方体,你可以为每个立方体指定一次颜色。
创建一个包含一个立方体顶点的 VBO。
// cube = 36 vertexes with glDrawArrays(GL_TRIANGLES) vbo1 = [v1] [v2] [v3] ... [v36]
为每个立方体创建另一个具有视图矩阵和颜色的 VBO,并使用 1 的属性除数。(您可以使用相同的 vbo,但我会使用单独的。)
vbo2 = [cube 1 mat, color] [cube 2 mat, color] ... [cube N mat, color]
呼叫
glDrawElementsInstanced()
或glDrawArraysInstanced()
。这将一遍又一遍地绘制立方体。
或者,您可以对每个立方体使用 glUniform()
,但这会限制您可以绘制的立方体数量。以上方法,让你轻松画出万千
混合 GL_TRIANGLES
和 GL_LINES
您必须为每种类型的基元调用一次 glDraw????()
。如果愿意,您可以两次使用相同的着色器。
对于 OpenGL 2.1,我认为没有一种合理的方法可以让每个立方体只指定一次颜色,并且仍然在一次绘制调用中绘制所有内容。
最直接的方法是,不要在 VBO 中使用颜色属性,而是在绘制调用之前直接指定它。假设您正在使用通用顶点属性,您当前将拥有:
glEnableVertexAttribArray(colorLoc);
glVertexAttripPointer(colorLoc, ...);
你这样做:
glDisableVertexAttribArray(colorLoc);
glVertexAttrib3f(colorLoc, r, g, b);
其中 glDisableVertexAttribArray()
仅在先前为该位置启用阵列时才需要。
最大的缺点是您只能在一次绘制调用中绘制具有相同颜色的立方体。在极端情况下,每个立方体一个绘制调用。当然,如果您有多个颜色相同的立方体,您仍然可以将它们批处理到一个绘制调用中。
您想知道这是否比为 VBO 中的每个顶点设置颜色更有效?不能笼统地说。在这种情况下,您总是会得到相同的答案:尝试两者,然后进行基准测试。我怀疑你会发现它有益。根据我的经验,获取顶点数据很少会成为主要的性能瓶颈。因此,删除一个属性可能不会给你带来太大的好处。另一方面,进行许多小的绘图调用绝对会(而且经常会)损害性能。
您可以使用一个混合选项。我不一定推荐它,只是为了集思广益。如果您使用的颜色数量相当有限,则可以在编码 "color index" 的 VBO 中使用单个标量属性。然后在顶点着色器中,您可以使用纹理查找将 "color index" 转换为实际颜色。
真正好的选择超出了 OpenGL 2.1。 @DietrichEpp 很好地解释了实例化渲染,对于这种情况,这是一个优雅的解决方案。
不,您可以不在同一个绘图调用中有直线和三角形。即使是 OpenGL 4.x 中最灵活的绘制调用,如 glDrawElementsIndirect()
,仍然只采用一种基元类型。