OpenGL,Java,LWJGL – 使用IBO,VBO和VAO绘制多个三角形

huangapple go评论81阅读模式
英文:

OpenGL, Java, LWJGL - Drawing multiple triangles using IBOs, VBOs and VAOs

问题

以下是您提供的源代码的翻译部分:

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

    // 设置清除颜色
    glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
    
    while (!glfwWindowShouldClose(window)) {
        Engine.makeAndDrawBuffersForTwoTriangles();

        renderLoop();
    }
}

private void renderLoop() {
    // 执行渲染循环,直到用户尝试关闭窗口或按下 ESC 键。
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除帧缓冲区

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

    glfwSwapBuffers(window); // 交换颜色缓冲区

    // 轮询窗口事件。
    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 };

第一个 Engine 类:

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);

    // 解绑所有
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // 绘制元素
    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);
    /*
    // 绘制数组
    glBindVertexArray(vao_left);
    glDrawArrays(GL_TRIANGLES, 0, left_indices.length);
    glBindVertexArray(vao_right);
    glDrawArrays(GL_TRIANGLES, 0, right_indices.length);
    glBindVertexArray(0);
    */
}

第二个 Engine 类:

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);
}
英文:

I am trying to render two triangles on the screen at once, using two different VBOs so that I can add textures later (to my understanding, if you want to add different textures, you must make two VBOs?).
I have tried using a combination of VAOs (both examples) and VAOs and IBOs (1st example).

Edit: As Stackoverflow doesn't recognise the tag, I'd like to clarify that IBO stands for Index Buffer Object

In both cases, I get a blank red screen.

I have previously managed to draw four triangles onto the screen using only one VBO and one IBO, but no VAO, putting all of the vertices into the one VBO, however I feel I need to learn how to draw multiple VBOs, as having everything in one VBO will become cumbersome and inefficient as greater numbers of objects are added.

I have already consulted other related questions as well as several tutorials, but have failed to find the information I am looking for in them (the tutorials tending to only describe drawing one item)

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

https://www.lwjgl.org/guide

https://stackoverflow.com/questions/11662030/opengl-vao-vbo-ibo-gldrawelements-not-displaying

https://stackoverflow.com/questions/21652546/what-is-the-role-of-glbindvertexarrays-vs-glbindbuffer-and-what-is-their-relatio

https://stackoverflow.com/questions/35258272/textured-triangles-with-opengl-using-vbo-ibo

Here is my source code:

Render loop

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();
}

Defining my vertices and declaring my ids

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 };

1st Engine class

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);
*/

2nd Engine class

	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);
}

答案1

得分: 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);

// 顶点规范
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 时,此缓冲与当前绑定的顶点数组对象相关联。

英文:

The Index buffers binding is stated in the Vertex Array Object. Invoking glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); breaks the binding of the index buffer to the VAO.
You have to delete glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);.
Furthermore, the vertex specification is stored in the VAO, so the VAO has to be bound, before the array of generic vertex attribute data is specified and the index buffer is bound:

// 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);

Note, in compare to the index buffer, the array buffer binding is a global state.
Each attribute which is stated in the VAOs state vector may refer to a different ARRAY_BUFFER. This reference is stored when glVertexAttribPointer (respectively glVertexPointer) is called. Then the buffer which is currently bound to the target ARRAY_BUFFER is associated to the attribute and the name (value) of the object is stored in the state vector of the VAO.
But the index buffer is a state of the VAO. When a buffer is bound to the target ELEMENT_ARRAY_BUFFER, then this buffer is associated to the vertex array object which is currently bound.

huangapple
  • 本文由 发表于 2020年4月9日 17:49:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/61118343.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定