在一个vbo中绘制多个形状

时间:2015-01-14 15:13:30

标签: c++ qt opengl

我想从一个vbo渲染多个3D立方体。每个立方体具有均匀的颜色。 这时,我创建了一个vbo,其中每个顶点都有一个颜色信息。

只为一个形状(垂直列表)上传一种颜色是否可行?

我还希望在同一着色器的GL_TRIANGLES - 方法中混合使用GL_LINESglDrawElements。它可以吗?

//编辑:我只有OpenGL 2.1。后来我想在Android上构建这个项目。

//编辑2: 我想渲染大量的立方体(高达150.000)。一个立方体有24个几何和颜色的顶点和34个索引。现在我的想法是创建一些vbo(可能是50)并将多维数据集分享给vbo。我希望这可以最大限度地减少开销。

3 个答案:

答案 0 :(得分:4)

绘制大量立方体

是的,如果你想绘制一堆立方体,你可以为每个立方体指定一次颜色。

  1. 创建一个包含一个立方体顶点的VBO。

    // cube = 36 vertexes with glDrawArrays(GL_TRIANGLES)
    vbo1 = [v1] [v2] [v3] ... [v36]
    
  2. 使用每个多维数据集的视图矩阵和颜色创建另一个VBO,并使用属性除数为1.(您可以使用相同的vbo,但我会使用单独的一个。)

    vbo2 = [cube 1 mat, color] [cube 2 mat, color] ... [cube N mat, color]
    
  3. 致电glDrawElementsInstanced()glDrawArraysInstanced()。这将一遍又一遍地绘制立方体。

  4. 或者,您可以对每个多维数据集使用glUniform(),但这会限制您可以绘制的多维数据集的数量。上面的方法可以让你轻松绘制数千个。

    混合GL_TRIANGLESGL_LINES

    您必须为每种原语调用glDraw????()一次。如果您愿意,可以同时使用相同的着色器。

答案 1 :(得分:1)

关于你的问题:

是否可以只为一种形状上传一种颜色?

是的,你可以使用统一而不是顶点属性(ofc这意味着更多地方的变化)。但是,您需要为每个形状设置制服,并为每个不同颜色的形状设置不同的drawcall。

是否可以在glDrawElements中混合使用GL_TRIANGLES和GL_LINES?

是和否。是的,但你需要一个新的drawcall(很明显)。你不能在同一个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

答案 2 :(得分:1)

使用OpenGL 2.1,我不认为每个多维数据集只能指定一次颜色的合理方式,并且仍然可以在一次绘制调用中绘制所有内容。

最直接的方法是,不是在VBO中使用color属性,而是在绘制调用之前直接指定它。假设您正在使用通用顶点属性,那么您目前拥有:

glEnableVertexAttribArray(colorLoc);
glVertexAttripPointer(colorLoc, ...);

你这样做:

glDisableVertexAttribArray(colorLoc);
glVertexAttrib3f(colorLoc, r, g, b);

只有先前为该位置启用了数组时才需要glDisableVertexAttribArray()

最大的缺点是你只能在一次绘制调用中绘制具有相同颜色的立方体。在极端情况下,每个立方体有一个绘图调用。当然,如果你有多个具有相同颜色的立方体,你仍然可以将它们分批到一个绘图调用中。

您想知道这是否比VBO中每个顶点的颜色更有效?总的来说不可能说。在这样的情况下,您总会得到相同的答案:尝试两者,并进行基准测试。我怀疑你会觉得它有益。根据我的经验,将顶点数据作为主要性能瓶颈的情况相当罕见。因此,删除一个属性可能不会给你带来太大的收益。另一方面,进行许多小的平局调用绝对会(通常会)损害性能。

您可以使用一种类似混合的选项。我不一定推荐它,只是为了集思广益。如果使用相当有限数量的颜色,则可以在VBO中使用单个标量属性来编码"颜色索引"。然后在顶点着色器中,您可以使用纹理查找来转换"颜色索引"到实际的颜色。

真正好的选择超出了OpenGL 2.1。 @DietrichEpp很好地解释了实例化渲染,这对于像这样的情况来说是一个优雅的解决方案。

不,你可以在同一个绘图调用中有行和三角形。即使是在OpenGL 4.x中最灵活的绘制调用,如glDrawElementsIndirect(),仍然只采用一种基本类型。