GL_DEPTH_TEST导致闪烁

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GL_DEPTH_TEST导致闪烁相关的知识,希望对你有一定的参考价值。

我在OpenGL中遇到了一个奇怪的问题。首先是一些背景:在我的程序中,我正在实现一个bloom效果,使用两个纹理和完整的mipmap。每个mipmap级别都附加到FBO,以便我可以在每个级别上执行2部分高斯模糊,然后重新组合它们以进行布隆。这部分都很好用,我可以渲染一个漂亮的旋转发光物体。

当我尝试实施深度测试时,问题就出现了。

我向与每个纹理的0级相对应的FBO添加了深度图。然后我启用了GL_DEPTH_TEST。一旦启用GL_DEPTH_TEST,屏幕就会开始闪烁,对象不再旋转。

我已经将代码削减到最简单,并且似乎只有在我启用了GL_DEPTH_TEST的情况下渲染到FBO时才会发生。如果我在启用GL_DEPTH_TEST的情况下渲染到默认帧缓冲区,则不会发生此问题。如果我在禁用GL_DEPTH_TEST的情况下渲染到FBO,则不会发生此问题。

下面的代码是我的代码的简化版本,只是为了说明似乎重新创建此问题的OpenGL调用的顺序。请

我是否正确地将深度缓冲区添加到FBO?

// Create a set of framebuffers, one for each mipmap level of a texture.
void FrameBuffer::Initialise(int xs, int ys)
{    
    xSizeTexture = PowerOfTwoAboveOrEqualTo(xs);
    ySizeTexture = PowerOfTwoAboveOrEqualTo(ys);
    numLevels = Log2(max(xSizeTexture, ySizeTexture));

    // Generate one FB for each texture level
    glGenFramebuffers(numLevels, frameBufferID);

    glGenTextures(1, &textureID);
    glBindTexture(  GL_TEXTURE_2D, textureID);
    glTexImage2D(   GL_TEXTURE_2D, 0, GL_RGB, xSizeTexture, ySizeTexture, 0, GL_RGB, GL_BYTE, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, numLevels-1);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
    glGenerateMipmap(GL_TEXTURE_2D);

    // Bind each texture level to one FB
    for (int i = 0; i < numLevels; i++)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID[i]);
        glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, i);
    }

    attachment = GL_COLOR_ATTACHMENT0;
    glDrawBuffers(1, &attachment);

    // Add a depth buffer to the top FB
    glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID[0]);
    glGenRenderbuffers(1, &depthrenderbufferID);
    glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbufferID);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, xSizeTexture, ySizeTexture);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbufferID);


    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        cout << "Failed to create frame buffer" << endl;
    else
        cout << "Created buffer OK" << endl;

    // Also initialise vertex array VAO
    // ...
}

void FrameBuffer::Use()
{
    glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID[0]);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBindTexture(GL_TEXTURE_2D, 0);
}

void FrameBuffer::CopyToMain()
{
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, textureID);

    glViewport(0, 0, 1024, 1024);
    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindVertexArray(0);
}

void MainClass::Initialise()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    framebuffer.Initialise(1024, 1024);
}

void MainClass::Render()
{
    if (!initialised)
    {
        Initialise();
        initialised = true;
    }

    framebuffer.Use();
    glViewport(0, 0, 1024, 1024);
    glUseProgram(0);
    glEnable(GL_DEPTH_TEST);        // Causes problems
    //glDisable(GL_DEPTH_TEST);     // Works fine

    t += 0.05;
    glLoadIdentity();
    glRotatef(sin(t) * 10, 0, 0, 1);
    glLineWidth(2.0);

    glBegin(GL_LINE_LOOP);
        glColor3f(1.0, 0.1, 0.1); glVertex3f(-0.5, -0.5, 0.0);
        glColor3f(0.1, 1.0, 0.1); glVertex3f( 0.5, -0.5, 0.0);
        glColor3f(0.1, 0.1, 1.0); glVertex3f( 0.5,  0.5, 0.0);
        glColor3f(0.1, 0.1, 0.1); glVertex3f(-0.5,  0.5, 0.0);
    glEnd();

    framebuffer.CopyToMain();
}

我没有得到glGetError()报告的错误。

请原谅C ++代码的略微伪代码性质。它只是为了说明所做的OpenGL调用的顺序。

答案

你有没有尝试过opengl Debug功能?

在这里你绑定一个指针(数组名称),而不是gl名称,应该是frameBufferID [0],我想。

glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);
另一答案

你忘了包括:

glDepthFunc(GL_LEQUAL);

以上是关于GL_DEPTH_TEST导致闪烁的主要内容,如果未能解决你的问题,请参考以下文章

覆盖javascript以消除闪烁

Android SurfaceView导致屏幕闪烁

调用 replace() 方法后片段闪烁/闪烁

sh HBA和驱动器固件闪烁片段

[self.tableview reloadData];导致闪烁

android,在先做了popStack之后,如何避免用FragmentTransaction替换片段时出现闪烁