【问题标题】:Questions on OpenGL VBOs关于 OpenGL VBO 的问题
【发布时间】:2013-09-13 23:19:37
【问题描述】:

我目前正在尝试制作一个具有立方体地形的基本游戏,类似于 Minecraft 经典版。我的第一个问题:

如何在 VBO 中存储多维数据集列表,然后在更改数据时重新构建列表?我目前渲染立方体是这样的:

vertices = BufferUtils.createFloatBuffer(3 * 4 * 6);
    vertices.put(new float[] {
            -1.0f, -1.0f, 1.0f,
            1.0f, -1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            -1.0f, 1.0f, 1.0f,

            -1.0f, -1.0f, -1.0f,
            -1.0f, 1.0f, -1.0f,
            1.0f, 1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,

            -1.0f, 1.0f, -1.0f,
            -1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, -1.0f,

            -1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, 1.0f,
            -1.0f, -1.0f, 1.0f,

            1.0f, -1.0f, -1.0f,
            1.0f, 1.0f, -1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, -1.0f, 1.0f,

            -1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f, 1.0f,
            -1.0f, 1.0f, 1.0f,
            -1.0f, 1.0f, -1.0f});
    vertices.rewind();

    vertexBufferID = createVBOID();
    bufferData(vertexBufferID, vertices);

         public static int createVBOID() {
        if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object) {
            IntBuffer buffer = BufferUtils.createIntBuffer(1);
            ARBVertexBufferObject.glGenBuffersARB(buffer);
            return buffer.get(0);
        }
        return 0;
    }

 public static void bufferData(int id, FloatBuffer buffer) {
        ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, id);
        ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_DYNAMIC_DRAW_ARB);
    } 

public void renderGL() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
    glViewport(0, 0, Display.getWidth(), Display.getHeight());
    glLoadIdentity();

    glRotatef(xrot, 1.0f, 0.0f, 0.0f);
    glRotatef(yrot, 0.f, 1.0f, 0.0f);
    glTranslated(-xpos, -ypos - 19, -zpos - 5);

    glEnableClientState(GL_VERTEX_ARRAY);
    ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, vertexBufferID);
    glVertexPointer(3, GL_FLOAT, 0, 0);

    for (int y = 0; y < 16; y++) {
        for (int x = 0; x < 16; x++) {
            for (int z = 0; z < 16; z++) {
                glPushMatrix();
                glTranslatef(x, y, z);
                glDrawArrays(GL_QUADS, 0, 24);
                glPopMatrix();
            }
        }

    }
    glDisableClientState(GL_VERTEX_ARRAY);
}

我知道我需要使用glMapBuffer 和glUnMapBuffer 来修改VBO,但是如何存储立方体并在需要时将其移除?我应该使用 ArrayList 吗?另外,有人告诉我我渲染立方体的方式是错误的,因为每个人都说我只用新坐标渲染一个立方体。他们说我的顶点数据保持不变,这是什么意思?

所以基本上我的问题是, 1. 如何使用数组来保存立方体列表并将它们加载到 VBO 中,然后删除一些立方体? 2. 如何更改我的顶点数据,以便我渲染不同的立方体,而不仅仅是一个立方体?

【问题讨论】:

  • 我只会制作一个 vbo 并将其翻译到不同的地方。

标签: java opengl lwjgl vbo


【解决方案1】:
  1. 正如 antonijn 所写,您可以将 1 个立方体作为 VBO 并转换其模型视图矩阵
    • 翻译有时会变慢(当立方体太多时)。
    • 转换甚至可以在着色器内部通过一些统一的偏移量完成,这比矩阵转换快一点
  2. 更快的方法是让所有的立方体都在 VBO
    • 它会浪费内存,但立方体并没有那么大(仅限 6 个面)
  3. 我会将多维数据集永久存储在 CPU 可访问内存中
    • 当场景更改时,将其复制到 VBO 进行渲染。
    • 不要在 CPU 之间传输数据GPU 来回传输
    • 仅将数据从 CPU 复制到 GPU。
  4. 也最好使用非索引 VBO(drawarrays 不是 drawelements)
    • 索引不是很好支持
    • 通常会减慢速度,甚至在坏驱动程序上崩溃

代码看这里:https://stackoverflow.com/a/18672821/2521214 但是该帖子将 VAO+VBO 用于 GLSL,因此如果您不使用 GLSL,则需要进行一些更改。

【讨论】:

    【解决方案2】:

    大多数情况下,您有场景的 CPU 表示(在您的情况下是立方体列表)和 GPU 表示(即顶点缓冲区等)

    在您的情况下,立方体仅由其位置定义。它们都具有相同的大小等等。以下是一些如何渲染多个立方体的选项:

    1. 在您的顶点着色器中定义一个统一的位置变量并将其添加到顶点位置。如果不使用着色器,请将偏移量指定为模型视图矩阵中的平移矩阵。使用不同的矩阵/偏移多次渲染相同的顶点缓冲区。

    2. 让 GPU 在其几何着色器中创建立方体。因此,您只需指定立方体在顶点缓冲区中的位置。当您映射一个顶点缓冲区时,您将获得一个指向数据的指针,您可以将新数据复制到其中。

    3. 使用实例化。为着色器提供一组位置并以实例化模式渲染立方体。使用实例 id 来确定偏移向量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多