2017-08-09 10 views
-1

J'ai une configuration OpenGL très spécifique où la géométrie 3D de la scène n'est pas rendue. Il y a un état lié à la profondeur dans le contexte OpenGL qui m'influe.Le tampon de profondeur OpenGL ou le test de profondeur ne fonctionne pas lors du rendu avec un contexte partagé

Ceci est dans un moteur de production au travail où nous avons ajouté la prise en charge du contexte partagé avec plusieurs contextes de fenêtre. Nous effectuons le rendu vers un objet framebuffer appartenant au contexte partagé, puis nous passons le renderbuffer de la pièce jointe couleur à une fenêtre en utilisant un contexte différent. La couleur claire est montrée dans le blit résultant à la fenêtre, mais pas la géométrie de la scène 3D elle-même, donc nous savons que les objets framebuffer et renderbuffer sont au moins partiellement corrects. Pour illustrer, j'ai refactored un échantillon du site Web LearnOpenGL pour illustrer mon bogue. Ça se voit là aussi, alors je suis clair que c'est quelque chose qui me manque.

Voici le projet GitHub où j'ai fait trois commits à un échantillon framebuffer de travail afin qu'il a rendu au framebuffer en utilisant un contexte partagé et Blits le résultat: Framebuffer Shared Context Experiment

est ici la plupart du code source qui produit le résultat buggy. J'ai coupé quelques sections qui sont restées inchangées.

// glfw dummy window creation 
    // -------------------- 
    GLFWwindow* dummy = NULL; 
#if USE_SHARED_CONTEXT 
    dummy = glfwCreateWindow(1, 1, "Dummy", NULL, NULL); 
    if (dummy == NULL) 
    { 
     std::cout << "Failed to create dummy GLFW window" << std::endl; 
     glfwTerminate(); 
     return -1; 
    } 
    glfwMakeContextCurrent(dummy); 
#endif 

    // glfw window creation 
    // -------------------- 
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, dummy); 
    if (window == NULL) 
    { 
     std::cout << "Failed to create GLFW window" << std::endl; 
     glfwTerminate(); 
     return -1; 
    } 
    glfwShowWindow(window); 
#if !USE_SHARED_CONTEXT 
    glfwMakeContextCurrent(window); 
#endif 

    // <snip creation of shared resources> 
    // <snip creation of un-shared vertex array> 

    // framebuffer configuration 
    // ------------------------- 
    unsigned int framebuffer; 
    glGenFramebuffers(1, &framebuffer); 
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 

#if 1 
    // create a color attachment render buffer 
    unsigned int Colorbuffer; 
    glGenRenderbuffers(1, &Colorbuffer); 
    glBindRenderbuffer(GL_RENDERBUFFER, Colorbuffer); 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer. 
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, Colorbuffer); // now actually attach it 
#else 
    // create a color attachment texture 
    unsigned int textureColorbuffer; 
    glGenTextures(1, &textureColorbuffer); 
    glBindTexture(GL_TEXTURE_2D, textureColorbuffer); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorbuffer, 0); 
#endif 

    // create a renderbuffer object for depth and stencil attachment (we won't be sampling these) 
    unsigned int rbo; 
    glGenRenderbuffers(1, &rbo); 
    glBindRenderbuffer(GL_RENDERBUFFER, rbo); 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer. 
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // now actually attach it 
    // now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now 
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
     cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl; 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); 

    // render loop 
    // ----------- 
    while (!glfwWindowShouldClose(window)) 
    { 
     // <snip timing and input> 

    #if USE_SHARED_CONTEXT 
     // use shared context because that is what is holding our framebuffer and vao. 
     // ----- 
     glfwMakeContextCurrent(dummy); 
    #endif 

     // render 
     // ------ 
     // bind to framebuffer and draw scene as we normally would to color texture 
     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 
     glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad) 

     // make sure we clear the framebuffer's content 
     glClearColor(1.0f, 0.1f, 0.1f, 1.0f); 
     glClearDepth(1.0f); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

     // following render is unchanged 
     shader.use(); 
     glm::mat4 model; 
     glm::mat4 view = camera.GetViewMatrix(); 
     glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH/(float)SCR_HEIGHT, 0.1f, 100.0f); 
     shader.setMat4("view", view); 
     shader.setMat4("projection", projection); 
     // cubes 
     glBindVertexArray(cubeVAO); 
     glActiveTexture(GL_TEXTURE0); 
     glBindTexture(GL_TEXTURE_2D, cubeTexture); 
     model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f)); 
     shader.setMat4("model", model); 
     glDrawArrays(GL_TRIANGLES, 0, 36); 
     model = glm::mat4(); 
     model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f)); 
     shader.setMat4("model", model); 
     glDrawArrays(GL_TRIANGLES, 0, 36); 
     // floor 
     glBindVertexArray(planeVAO); 
     glBindTexture(GL_TEXTURE_2D, floorTexture); 
     shader.setMat4("model", glm::mat4()); 
     glDrawArrays(GL_TRIANGLES, 0, 6); 
     glBindVertexArray(0); 

#if 1 
    #if USE_SHARED_CONTEXT 
     // use window context for presentation via blit. 
     // ----- 
     glfwMakeContextCurrent(window); 

     // temorary framebuffer for visible window since framebuffers are not shared 
     // ------------------------- 
     unsigned int readFramebuffer; 
     glGenFramebuffers(1, &readFramebuffer); 
     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer); 
     glBindRenderbuffer(GL_RENDERBUFFER, Colorbuffer); 
     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SCR_WIDTH, SCR_HEIGHT); 
     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, Colorbuffer); 
    #endif 

     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 
     glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); 

    #if USE_SHARED_CONTEXT 
     glDeleteFramebuffers(1, &readFramebuffer); 
    #endif 
#else 
     // now bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture 
     glBindFramebuffer(GL_FRAMEBUFFER, 0); 
     glDisable(GL_DEPTH_TEST); // disable depth test so screen-space quad isn't discarded due to depth test. 
     // clear all relevant buffers 
     glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways) 
     glClear(GL_COLOR_BUFFER_BIT); 

     screenShader.use(); 
     glBindVertexArray(quadVAO); 
     glBindTexture(GL_TEXTURE_2D, textureColorbuffer); // use the color attachment texture as the texture of the quad plane 
     glDrawArrays(GL_TRIANGLES, 0, 6); 
#endif 

     // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) 
     // ------------------------------------------------------------------------------- 
     glfwSwapBuffers(window); 
     glfwPollEvents(); 
    } 
// <snip epilog> 

Vous pouvez activer ou désactiver le commutateur de compilation USE_SHARED_CONTEXT pour enlever le peu de code qui affiche à l'aide d'un contexte partagé.

Répondre

1

Il me manquait un appel à glViewport pour le contexte de rendu partagé.

La valeur de la fenêtre d'affichage était par défaut (0, 0) -> (largeur, hauteur) pour le contexte utilisé par la fenêtre visible. Le contexte de rendu partagé a été défini par défaut sur (0, 0) -> (1, 1) car j'ai utilisé une largeur et une hauteur de 1 pour la fenêtre GLFW non visible.