2017-08-29 43 views
0

我有一個代碼,最初有一個着色器(ourShader),一個VAO和一個VBO。它將使用模板測試渲染具有紋理立方體的場景以及它在地面上的反射。現在,我想添加一個幀緩衝器進行後期處理,所以我需要第二個着色器。我添加了第二個着色器(screenShader)和第二個VBO。我還沒有在我的繪圖中使用它們,但是我添加它們的簡單事實使得我的代碼渲染了一個黑色的紅色三角形,而不是通常的場景。OpenGL:第二個VBO破壞第一個VBO

我的代碼如下所示:

Shader ourShader(string("core.vs"), string("core.frag")); // shader class creating a shader program from vertex shader and fragment shader source files. 
    Shader screenShader(string("core2.vs"), string("core2.frag")); 

    // Setting up attributes, VAO, VBO 
    GLuint VAO; 
    array<GLuint, 2> VBO; 
    glGenVertexArrays(1, &VAO); 
    glGenBuffers(2, &VBO[0]); 

    glBindVertexArray(VAO); 

    // Data for first shader and first VBO 
    glBindBuffer(GL_ARRAY_BUFFER, VBO[0]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticesCube), verticesCube, GL_STATIC_DRAW); 

    GLint posAttribLoc = glGetAttribLocation(ourShader.Program, "position"); 
    glVertexAttribPointer(posAttribLoc, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); // specify (to the active VAO) how to retrieve the values for the attribute "position" from the data stored ("vertices" here) on the active VBO (GPU) 
    glEnableVertexAttribArray(posAttribLoc); // enable attribute for rendering 

    GLint colAttribLoc = glGetAttribLocation(ourShader.Program, "color"); 
    glVertexAttribPointer(colAttribLoc, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); 
    glEnableVertexAttribArray(colAttribLoc); 

    GLint texAttribLoc = glGetAttribLocation(ourShader.Program, "texCoord"); 
    glVertexAttribPointer(texAttribLoc, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); 
    glEnableVertexAttribArray(texAttribLoc); 

    // ##### PART GIVING A WEIRD RESULT ##### 
    // Data for second shader and second VBO 
    glBindBuffer(GL_ARRAY_BUFFER, VBO[1]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticesRectangle), verticesRectangle, GL_STATIC_DRAW); 

    GLint posAttribLoc2 = glGetAttribLocation(screenShader.Program, "position"); 
    glVertexAttribPointer(posAttribLoc2, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0); // specify (to the active VAO) how to retrieve the values for the attribute "position" from the data stored ("vertices" here) on the active VBO (GPU) 
    glEnableVertexAttribArray(posAttribLoc2); // enable attribute for rendering 

    GLint texAttribLoc2 = glGetAttribLocation(screenShader.Program, "texCoord"); 
    glVertexAttribPointer(texAttribLoc2, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat))); 
    glEnableVertexAttribArray(texAttribLoc2); 
    // ##### END ##### 

    // Setting up texture that will be used for the first shader 
    GLuint texture; 
    int width, height; 
    glGenTextures(1, &texture); 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, texture); // makes "texture" the current texture and attaches it to texture unit 0 

    // Set the wrapping 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 

    // Set the filtering 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

    unsigned char* image = SOIL_load_image("res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); 
    glGenerateMipmap(GL_TEXTURE_2D); 
    SOIL_free_image_data(image); 

    // Unbind VBO, texture before main loop 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindTexture(GL_TEXTURE_2D, 0); 
    glfwSwapInterval(1); 
    glfwSetKeyCallback(window, Input::keyCallback); // Input is a singleton class handling inputs. It works well. 
    glfwSetCursorPosCallback(window, Input::mouseCallback); 
    glfwSetScrollCallback(window, Input::scrollCallback); 

    while (glfwWindowShouldClose(window) == GLFW_FALSE) { 
     // MAIN LOOP 
     // ... 
    } 
    glDeleteVertexArrays(1, &VAO); 
    glDeleteBuffers(2, &VBO[0]); 

主循環並不重要,我認爲。我想說的是,如果我刪除處理第二個VBO的幾條線,那麼場景呈現良好。否則,我會得到一個奇怪的三角形。

而我的兩個着色器將這些源文件用於各自的頂點着色器和片段着色器。順便說一句,我沒有從我的着色器編譯錯誤。

core.vs:

#version 330 core 
in vec3 position; 
in vec2 texCoord; 
in vec3 color; 

out vec2 TexCoord; 
out vec3 Color; 

uniform mat4 model; 
uniform mat4 view; 
uniform mat4 projection; 

void main() 
{ 
    gl_Position = projection*view*model*vec4(position, 1.0); 
    TexCoord = vec2(texCoord.x, 1.0 - texCoord.y); 
    Color = color; 
} 

core.frag:

#version 330 core 
in vec2 TexCoord; 
in vec3 Color; 

out vec4 outColor; 
uniform sampler2D ourTexture0; 

void main() 
{ 
    outColor = vec4(Color, 1)*texture(ourTexture0, TexCoord); 
} 

core2.vs:

#version 330 core 
in vec2 position; 
in vec2 texCoord; 
out vec2 TexCoord; 
void main() 
{ 
    gl_Position = vec4(position, 0.0, 1.0); 
    TexCoord = texCoord; 
} 

core2.frag:

#version 330 core 
in vec2 TexCoord; 
out vec4 outColor; 
uniform sampler2D texFramebuffer; 
void main() 
{ 
    outColor = texture(texFramebuffer, TexCoord); 
} 

個頂點看起來像這樣(但只有這樣看他們是很重要的):

GLfloat verticesRectangle[] = { 
     // position  // texture coordinates 
     -0.5f, -0.5f, 0.0f, 0.0f,  
     0.5f, -0.5f, 1.0f, 0.0f,  
     -0.5f, 0.5f, 0.0f, 1.0f,  
     0.5f, 0.5f,  1.0f, 1.0f  
    }; 

    GLfloat verticesCube[] = { 
     // position   // color   // texture coordinates 
     -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 
     0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 
     0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 
     0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 
     -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 
     -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 

     -0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 
     0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 
     0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 
     0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 
     -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 
     -0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 

     -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 
     -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 
     -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 
     -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 
     -0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 
     -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 

     0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 
     0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 
     0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 
     0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 
     0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 
     0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 

     -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 
     0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 
     0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 
     0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 
     -0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 
     -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 

     -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 
     0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 
     0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 
     0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 
     -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 
     -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 

     -1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // reflection surface // not a part of the cube itself 
     -1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 
     1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 
     1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 
     -1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 
     1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f 
    }; 

我已經看過Binding a second vertex buffer seems to spoil my first vertex buffer, OpenGL OES ios 5.1而是因爲他沒有正確的使用他的VAO的人有這個問題。

+0

什麼是使用VAOs如果你只有一個點? – Frank

回答

2

很可能兩個屬性位置具有相同的值。由於您僅使用一個VAO,因此您會覆蓋一些綁定。使用多個獨立幾何的正確方法是在每個幾何圖形上使用VAO。

正確的代碼以某種方式是這樣的:

glBindVertexArray(vao1); 
glBindBuffer(VBO[0]) 
glVertexAttribPointer... 
glEnableVertexAttribArray... 
//Setup all attributes for first VBO 

glBindVertexArray(vao2); 
glBindBuffer(VBO[1]) 
glVertexAttribPointer... 
glEnableVertexAttribArray... 
//Setup all attributes for second VBO 

當渲染做到以下幾點:

glBindVertexArray(vao1); 
glDraw*... //Draw VAO1 

glBindVertexArray(vao2); 
glDraw*.... //Draw VAO2 
+0

請注意,你並不需要2個VBO。如果頂點格式相同,則所有對象都可以存儲在同一個VBO中。您確實需要2個VAO,指向綁定的VBO緩衝區中的正確位置。 – StarShine

+1

如果格式不相同,它也可以存儲在同一個緩衝區中。緩衝區只是原始數據。 – BDL