2014-09-21 75 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