2014-09-21 78 views
0

我想在OpenGL中绘制2个对象。窗口/视口是(0,0,950,1050)。我不确定这是否是正确的做法,但我是这么认为的。我认为这个想法是为每个对象创建一个VBO/VAO,绑定它,设置数据,并为每个对象重复该操作。在OpenGL4中绘制两个对象?

然后,当物体被绘制:

  • 设置着色器
  • 绑定的第一个对象的数据,我们想用它的VBO(比如vbo1)
  • 做绘图调用绘制
  • 绑定的下一个对象的数据,我们想用它的VBO绘制(比如vbo2)
  • 做绘图调用
  • ...

当我这样做时,我只能得到第二个对象在屏幕上绘制的点,但是第一个对象的颜色(它是蓝色而不是红色)。

我的错误对任何专家都是显而易见的。我错过了什么?

// BLUE ----------------------------------- 
GLuint vbo1, vao1; 
glGenBuffers(1, &vbo1); 
glBindBuffer(GL_ARRAY_BUFFER, vbo1); 
float arr1[] = { 10, 10, 10, 110, 110, 110, 110, 10 }; 
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr1, GL_STATIC_DRAW); 

glGenVertexArrays(1, &vao1); 
glBindVertexArray(vao1); 
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
glEnableVertexAttribArray(0); 

// RED ----------------------------------- 
GLuint vbo2, vao2; 
glGenBuffers(1, &vbo2); 
glBindBuffer(GL_ARRAY_BUFFER, vbo2); 
float arr2[] = { 400, 400, 400, 800, 800, 800, 800, 400 }; 
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr2, GL_STATIC_DRAW); 

glGenVertexArrays(1, &vao2); 
glBindVertexArray(vao2); 
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
glEnableVertexAttribArray(0); 

while (!glfwWindowShouldClose(window)) 
{ 
    glClearColor(1, 1, 1, 0.1); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glUseProgram(pointShader); 

    GLint loc; 
    loc = glGetUniformLocation(pointShader, "pointColor"); 

    // it draws this one but with the color blue! 
    glBindBuffer(GL_ARRAY_BUFFER, vbo2); 
    float ptColor2[3] = { 1, 0, 0 }; 
    glUniform3fv(loc, 1, ptColor2); 
    glDrawArrays(GL_POINTS, 0, 4); 

    // it doesn't draw this one??? 
    glBindBuffer(GL_ARRAY_BUFFER, vbo1); 
    float ptColor1[3] = { 0, 0, 1 }; 
    glUniform3fv(loc, 1, ptColor1); 
    glDrawArrays(GL_POINTS, 0, 4); 

    glfwSwapBuffers(window); 
    glfwWaitEvents(); 
} 

enter image description here

EDIT 2工作代码

非常感谢您对雷托Koradi和Datenwolf两者。结合答案,有助于得出正确的答案。很遗憾,这些东西在书本上没有正确解释。希望这篇文章能够帮助其他初学者(对不起,如果结果有点误导,我在问问题的时候换了颜色,以及我什么时候得到答案)。

// RED ----------------------------------- 
GLuint vbo1, vao1; 

glGenVertexArrays(1, &vao1); 
glBindVertexArray(vao1); 

glGenBuffers(1, &vbo1); 
glBindBuffer(GL_ARRAY_BUFFER, vbo1); 
float arr1[] = { 10, 10, 10, 110, 110, 110, 110, 10 }; 
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr1, GL_STATIC_DRAW); 

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
glEnableVertexAttribArray(0); 

// BLUE ----------------------------------- 
GLuint vbo2, vao2; 

glGenVertexArrays(1, &vao2); 
glBindVertexArray(vao2); 

glGenBuffers(1, &vbo2); 
glBindBuffer(GL_ARRAY_BUFFER, vbo2); 
float arr2[] = { 400, 400, 400, 800, 800, 800, 800, 400 }; 
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr2, GL_STATIC_DRAW); 

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
glEnableVertexAttribArray(0); 

while (!glfwWindowShouldClose(window)) 
{ 
    float ratio; 
    int width, height; 
    glfwGetFramebufferSize(window, &width, &height); 

    glClearColor(1, 1, 1, 0.1); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glUseProgram(pointShader); 

    GLint loc; 
    loc = glGetUniformLocation(pointShader, "pointColor"); 

    // red 
    glBindVertexArray(vao1); 
    float ptColor1[3] = { 1, 0, 0 }; 
    glUniform3fv(loc, 1, ptColor1); 
    glDrawArrays(GL_POINTS, 0, 4); 

    // blue 
    glBindVertexArray(vao2); 
    float ptColor2[3] = { 0, 0, 1 }; 
    glUniform3fv(loc, 1, ptColor2); 
    glDrawArrays(GL_POINTS, 0, 4); 

    glfwSwapBuffers(window); 
    glfwWaitEvents(); 
} 

enter image description here

编辑3

注意,虽然从对VAO/VBO顺序声明的第一个代码片段的顺序也将工作。所以低于上述版本和一个都是有效的:

// RED ----------------------------------- 
GLuint vbo1, vao1; 

glGenBuffers(1, &vbo1); 
glBindBuffer(GL_ARRAY_BUFFER, vbo1); 
float arr1[] = { 10, 10, 10, 110, 110, 110, 110, 10 }; 
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr1, GL_STATIC_DRAW); 
glGenVertexArrays(1, &vao1); 
glBindVertexArray(vao1); 
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
glEnableVertexAttribArray(0); 

// BLUE ----------------------------------- 
GLuint vbo2, vao2; 

glGenBuffers(1, &vbo2); 
glBindBuffer(GL_ARRAY_BUFFER, vbo2); 
float arr2[] = { 400, 400, 400, 800, 800, 800, 800, 400 }; 
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr2, GL_STATIC_DRAW); 
glGenVertexArrays(1, &vao2); 
glBindVertexArray(vao2); 
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
glEnableVertexAttribArray(0); 

这是真正的代码唯一缺少的是glBindVertexArray

回答

2

的问题是在你的平局循环,在那里你拨打:

glBindBuffer(GL_ARRAY_BUFFER, vbo2); 

不要紧,当你做绘图调用GL_ARRAY_BUFFER当前绑定。当您拨打glVertexAttribPointer()时,需要绑定正确的缓冲区,您在设置代码中正确执行了此操作。

VAO追踪您的所有顶点设置状态。因此,每个绘制调用之前,你需要通过调用glBindVertexArray()到相应的VAO绑定的,而不是你在发布代码有glBindBuffer()电话,:

glBindVertexArray(vao2); 
glUniform3fv(...); 
glDrawArrays(...); 

glBindVertexArray(vao1); 
glUniform3fv(...); 
glDrawArrays(...); 
+0

谢谢辉煌,我将编辑我的代码,以工作代码为例。非常感谢你。 – user18490 2014-09-21 17:15:15

+0

我不认为有任何需要更改代码的设置部分。这看起来非常好,你有它的方式。您可以使用数据填充缓冲区,而无需绑定VAO。 VAO只需在'glVertexAttribPointer()'和'glEnableVertexAttribArray()'过程中进行绑定,这样做就是正确的。 – 2014-09-21 17:30:02

+0

是的,这是真的。与您的更改的原始代码实际上工作。不过,我已经做出了改变,并且懒得恢复原状。为了完整起见,我现在将添加它。 – user18490 2014-09-21 18:00:44

2

在指定顶点属性数据位置(glVertexAttribPointer)之前,您必须创建并绑定顶点数组对象。当进行这些呼叫时,VAO类型拥有属于VBO当前绑定的数据的所有权。

(编辑无意中提交的同时仍然打字)

假设你有一个核心文件环境中,当您试图创建第一个缓冲区对象,没有VAO绑定它来还,所以整个创作的BO的失败。因此,当您尝试绘制它时,根本没有任何东西被绘制。但是你看到的是你打算绑定到第二个VAO的BO,但是由于你的操作顺序错误,它会在第一个VAO中结束。

+0

我猜你是专家;)谢谢你这是非常好的,和我不得不说,这从来没有在书中得到妥善解释。不过,我做了你建议的更改(请参阅上面的编辑),但我仍然无法正常工作。这些更改是否正确?这就是你在说的。第二个对象现在用正确的颜色绘制,但我仍然看不到第一个对象。 – user18490 2014-09-21 17:12:33

+0

这听起来不准确。你可以绑定VBOs而不必绑定VAO。在VAO中不跟踪'GL_ARRAY_BUFFER'绑定。只有'GL_ELEMENT_ARRAY_BUFFER'绑定是VAO状态的一部分。 – 2014-09-21 17:21:53

+0

@ReetoKoradi:我不好,我说它沉闷了,我应该停止这样做。我重申了我的答案。 – datenwolf 2014-09-21 17:45:59