【问题标题】:OpenGL, Java, LWJGL - Drawing multiple triangles using IBOs, VBOs and VAOsOpenGL、Java、LWJGL - 使用 IBO、VBO 和 VAO 绘制多个三角形
【发布时间】:2020-07-21 21:45:57
【问题描述】:

我试图一次在屏幕上渲染两个三角形,使用两个不同的 VBO,以便以后可以添加纹理(据我了解,如果要添加不同的纹理,您必须制作两个 VBO?)。 我尝试过使用 VAO(两个示例)以及 VAO 和 IBO(第一个示例)的组合。

编辑:由于 Stackoverflow 无法识别标签,我想澄清一下 IBO 代表索引缓冲区对象

在这两种情况下,我都会看到一个空白的红色屏幕。

我以前只使用一个 VBO 和一个 IBO,但没有使用 VAO,将所有顶点都放在一个 VBO 中,但我觉得我需要学习如何绘制多个 VBO,因为我之前设法在屏幕上绘制了四个三角形,因为随着对象数量的增加,将所有内容都放在一个 VBO 中会变得麻烦且效率低下。

我已经查阅了其他相关问题以及几个教程,但未能在其中找到我要查找的信息(教程往往只描述绘制一项)

https://learnopengl.com/Getting-started/OpenGL

https://www.lwjgl.org/guide

OpenGL - VAO, VBO, IBO, glDrawElements not displaying

What is the role of glBindVertexArrays vs glBindBuffer and what is their relationship?

Textured triangles with OpenGL using VBO/IBO

这是我的源代码:

渲染循环

private void setupLoop() {
        GL.createCapabilities();
        debugProc = GLUtil.setupDebugMessageCallback();

        // Set the clear color
        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

        while (!glfwWindowShouldClose(window)) {
            Engine.makeAndDrawBuffersForTwoTriangles();

            renderLoop();
        }
    }

    private void renderLoop() {
        // Run the rendering loop until the user has attempted to close
        // the window or has pressed the ESCAPE key.
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

        glViewport(0, 0, width, height);
        glMatrixMode(GL_PROJECTION);
        float aspect = (float) width / height;
        glLoadIdentity();
        glOrtho(-aspect, aspect, -1, 1, -1, 1);

        glfwSwapBuffers(window); // swap the color buffers

        // Poll for window events.
        glfwPollEvents();
    }

定义我的顶点并声明我的 ID

static int vbo_left;
static int vao_left;
static int ibo_left;
static float left_vertices[] = { -0.5f, 0f, -0.25f, 0.5f, 0f, 0f };
static int left_indices[] = { 0, 1, 2, 3, 4, 5 };

static int vbo_right;
static int vao_right;
static int ibo_right;
static float right_vertices[] = { 0f, 0f, 0.25f, -0.5f, 0.5f, 0f };
static int right_indices[] = { 0, 1, 2, 3, 4, 5 };

第一个引擎类

public static void makeAndDrawBuffersForTwoTriangles() {
    // VBO
    vbo_left = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_left);
    glBufferData(GL_ARRAY_BUFFER, left_vertices, GL_STATIC_DRAW);
    // IBO
    ibo_left = glGenBuffers();
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_left);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
            (IntBuffer) BufferUtils.createIntBuffer(left_indices.length).put(left_indices).flip(), GL_STATIC_DRAW);
    glVertexPointer(2, GL_FLOAT, 0, 0L);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    // VAO
    vao_left = glGenVertexArrays();
    glBindVertexArray(vao_left);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_left);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, false, 2, 0);
    glBindVertexArray(0);

    // VBO
    vbo_right = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_right);
    glBufferData(GL_ARRAY_BUFFER, right_vertices, GL_STATIC_DRAW);
    // IBO
    ibo_right = glGenBuffers();
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_right);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
            (IntBuffer) BufferUtils.createIntBuffer(right_indices.length).put(right_indices).flip(),
            GL_STATIC_DRAW);
    glVertexPointer(2, GL_FLOAT, 0, 0L);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    // VAO
    vao_right = glGenVertexArrays();
    glBindVertexArray(vao_right);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_right);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, false, 2, 0);
    glBindVertexArray(0);

    // Unbind all
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // Draw elements
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_left);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_left);
    glVertexAttribPointer(0, 2, GL_FLOAT, false, 2, 0);
    glDrawElements(GL_TRIANGLES, left_indices.length, GL_UNSIGNED_INT, 0L);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_right);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_right);
    glVertexAttribPointer(0, 2, GL_FLOAT, false, 2, 0);
    glDrawElements(GL_TRIANGLES, right_indices.length, GL_UNSIGNED_INT, 0L);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    /*
    // Draw Arrays
    glBindVertexArray(vao_left);
    glDrawArrays(GL_TRIANGLES, 0, left_indices.length);
    glBindVertexArray(vao_right);
    glDrawArrays(GL_TRIANGLES, 0, right_indices.length);
    glBindVertexArray(0);
    */

第二引擎类

    public static void makeAndDrawBuffersForTwoTriangles() {
        vbo_left = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vbo_left);
        glBufferData(GL_ARRAY_BUFFER, left_vertices, GL_STATIC_DRAW);

        vao_left = glGenVertexArrays();
        glBindVertexArray(vao_left);
        glBindBuffer(GL_ARRAY_BUFFER, vao_left);
        glVertexAttribPointer(vao_left, 2, GL_FLOAT, false, 2, 0);
        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        vbo_left = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vbo_left);
        glBufferData(GL_ARRAY_BUFFER, left_vertices, GL_STATIC_DRAW);

        vao_left = glGenVertexArrays();
        glBindVertexArray(vao_left);
        glBindBuffer(GL_ARRAY_BUFFER, vao_left);
        glVertexAttribPointer(vao_left, 2, GL_FLOAT, false, 2, 0);
        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(vao_left);
        glDrawArrays(GL_TRIANGLES, 0, left_vertices.length);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(vao_right);
        glDrawArrays(GL_TRIANGLES, 0, right_vertices.length);

    }

【问题讨论】:

    标签: java opengl lwjgl vbo vao


    【解决方案1】:

    Index buffers 绑定在Vertex Array Object 中声明。调用 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 会破坏索引缓冲区与 VAO 的绑定。
    你必须删除glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);。 此外,顶点规范存储在 VAO 中,因此必须在指定通用顶点属性数据数组和绑定索引缓冲区之前绑定 VAO:

    // VBO
    vbo_left = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_left);
    glBufferData(GL_ARRAY_BUFFER, left_vertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    // IBO
    ibo_left = glGenBuffers();
    
    // VAO
    vao_left = glGenVertexArrays();
    glBindVertexArray(vao_left);
    
    // IBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_left);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
        (IntBuffer) BufferUtils.createIntBuffer(left_indices.length).put(left_indices).flip(), GL_STATIC_DRAW);
    
    // vertex specification
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_left);
    glVertexAttribPointer(0, 2, GL_FLOAT, false, 2, 0);
    

    注意,与索引缓冲区相比,数组缓冲区绑定是全局状态。
    在 VAO 状态向量中陈述的每个属性都可以引用不同的ARRAY_BUFFER。此引用在调用glVertexAttribPointer(分别为glVertexPointer)时存储。然后将当前绑定到目标ARRAY_BUFFER 的缓冲区与属性相关联,并将对象的名称(值)存储在 VAO 的状态向量中。
    但索引缓冲区是 VAO 的一种状态。当一个缓冲区绑定到目标ELEMENT_ARRAY_BUFFER时,这个缓冲区就会关联到当前绑定的顶点数组对象。

    【讨论】:

      猜你喜欢
      • 2017-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-02
      相关资源
      最近更新 更多