用统一块渲染到fbo会导致某些对象闪烁

问题描述

我想为我的游戏引擎实现阴影映射,因此必须将深度视图渲染为fbo。我已经绘制了深度纹理并缩放了值,以使纹理看起来不完全是白色,并且结果看起来正确。但是,场景中的某些对象每隔一帧就会消失一次,这是以前从未发生过的事情。我简化了代码,现在看起来类似于以下内容;

  1. 更新统一缓冲区对象
  2. 绑定fbo
  3. 渲染为fbo
  4. 绑定默认fbo
  5. 照常渲染场景

在以下情况下,物体的闪烁消失:

渲染到fbo时使用的着色器中的统一块已删除,即使从未访问过。

我们从不绑定fbo(我们从简化的伪代码中删除了步骤(2))

我们在步骤(5)中交换一些渲染调用的顺序

我们在渲染到fbo之后更新统一缓冲区对象,即将步骤(1)移动到步骤(3)之后的某个位置。我们仅在步骤(1)内更新ubo的某些元素,但是无论更新了哪些元素,在移动该步骤时问题都会消失。请注意,完全删除步骤并不能消除错误。

我们从不渲染fbo(我们删除了步骤(3))

请注意,在步骤(5)的绘制调用的着色器内部访问了统一块。我创建了一个相同的统一缓冲区对象,并在渲染到fbo时使用的着色器内部访问了该对象,而闪烁消失了,所以看起来问题是我在渲染到fbo时正在访问同一ubo就像我渲染到默认帧缓冲区时一样。但是,据我所知这不是问题。我正在使用统一块内的所有变量,因此似乎已正确初始化。

编辑: 我已尽力简化了代码。在简化了一个着色器之后,渲染的对象将完全消失而不是闪烁,但这并不能使问题变得更好。不可见的渲染调用是“渲染调用B”。以上所有观察仍然成立。在下面的代码中已经进行了一些新的观察,并对此进行了注释。

完整的源代码:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <assert.h>

static void AttachShader(unsigned int program,GLenum type,const std::string& source)
{
    unsigned int shader = glCreateShader(type);
    const char* cString = source.c_str();
    glShaderSource(shader,1,&cString,NULL);
    glCompileShader(shader);

    int status;
    glGetShaderiv(shader,GL_COMPILE_STATUS,&status);
    assert(status);
    glAttachShader(program,shader);
}

int main(void)
{
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640,480,"Hello World",NULL,NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    GLenum err = glewInit();
    assert(GLEW_OK == err);

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        static bool first = true;
        static unsigned int vao;
        static unsigned int framebuffer;
        static unsigned int shadowMapTexture;
        static unsigned int uniformBuffer;
        static unsigned int programA;
        static unsigned int programB;
        static float identity[16] =
        { 1.0f,0.0f,1.0f,1.0f };

        if (first)
        {
            first = false;

            //Creating program A
            {
                programA = glCreateProgram();
                AttachShader(programA,GL_VERTEX_SHADER,"#version 450 core\n\
            \n\
            //If the data block gets commented the issue goes away\n\
            layout(std140,binding = 0) uniform DataBlock\n\
            {\n\
                mat4 identity;\n\
            }dataBlock;\n\
            \n\
            \n\
            void main()\n\
            {\n\
                vec3 positions[3] = { vec3(-0.5,-0.25,-0.2),vec3(0.0,vec3(-0.25,0.25,-0.2) };\n\
                gl_Position = vec4(positions[gl_VertexID],1.0);\n\
            }");
                AttachShader(programA,GL_FRAGMENT_SHADER,"#version 450 core\n\
            out vec4 colour;\n\
            \n\
            void main()\n\
            {\n\
                colour = vec4(1.0,1.0,0.0,1.0);\n\
            }");
                glLinkProgram(programA);

                int status;
                glGetProgramiv(programA,GL_LINK_STATUS,&status);
                assert(status);
            }

            //Creating program B
            {
                programB = glCreateProgram();
                AttachShader(programB,"#version 450 core\n\
\n\
            layout(location = 0) in int index;\n\
            layout(location = 1) uniform mat4[2] matrices;\n\
\n\
            layout(std140,binding = 0) uniform DataBlock\n\
            {\n\
                mat4 identity;\n\
            }dataBlock;\n\
\n\
            void main()\n\
            {\n\
\n\
                vec3 positions[3] = { vec3(-0.25,vec3(0.25,-0.2) };\n\
\n\
                vec4 pos = vec4(positions[gl_VertexID],1.0);\n\
\n\
                //If \"index\" is substituted by \"0\" the problem goes away\n\
                vec4 secondPos = matrices[index] * pos;\n\
\n\
                //If \"secondPos\" is substituted by \"pos\" the problem remains\n\
                //If we remove \"dataBlock.identity *\" the problem goes away\n\
                gl_Position = dataBlock.identity*secondPos;\n\
            }");
                AttachShader(programB,"#version 450 core\n\
\n\
            out vec4 colour;\n\
\n\
            void main()\n\
            {\n\
                colour = vec4(0.0,1.0);\n\
            }");
                glLinkProgram(programB);

                int status;
                glGetProgramiv(programB,&status);
                assert(status);
            }

            //Creating the vao used inside shader "B"
            {
                glCreateVertexArrays(1,&vao);

                unsigned int vertexBuffer;
                glCreateBuffers(1,&vertexBuffer);
                int vertexData[3] = { 0,0 };
                glNamedBufferData(vertexBuffer,sizeof(int) * 3,vertexData,GL_STATIC_DRAW);
                glVertexArrayVertexBuffer(vao,vertexBuffer,sizeof(int));
                glVertexArrayAttribBinding(vao,0);
                glVertexArrayAttribIFormat(vao,GL_INT,0);
                glEnableVertexArrayAttrib(vao,0);
            }

            //Creating the framebuffer
            {
                glCreateFramebuffers(1,&framebuffer);
                glBindFramebuffer(GL_FRAMEBUFFER,framebuffer);

                glGenTextures(1,&shadowMapTexture);
                glBindTexture(GL_TEXTURE_2D,shadowMapTexture);
                glTexStorage2D(GL_TEXTURE_2D,GL_DEPTH_COMPONENT32F,512,512);
                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

                glFramebufferTexture(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,shadowMapTexture,0);

                unsigned int drawBuffers[] = { GL_NONE };
                glDrawBuffers(1,drawBuffers);

                assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
            }

            //Creating the uniform buffer object
            {
                glCreateBuffers(1,&uniformBuffer);
                glNamedBufferStorage(uniformBuffer,sizeof(float)*16,GL_DYNAMIC_STORAGE_BIT);
                glBindBufferBase(GL_UNIFORM_BUFFER,uniformBuffer);
                glNamedBufferSubData(uniformBuffer,sizeof(float) * 16,identity);
            }

            //Creating and binding a vao for compatability with the core profile
            static unsigned int emptyVao;
            glCreateVertexArrays(1,&emptyVao);
            glBindVertexArray(emptyVao);
        }

        //Step 2,binding the fbo
        glBindFramebuffer(GL_FRAMEBUFFER,framebuffer);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_DEPTH_TEST);
        //End of step 2

        //Step 3,rendering to fbo
        {
            glUseProgram(programA);
            glDrawArrays(GL_TRIANGLES,3);
        }

        //If we update the uniform buffer here the issue disappears,i.e. if the following line gets uncommented 
        {
            //glNamedBufferSubData(uniformBuffer,identity);
        }

        //Step 4,binding the default fbo
        glBindFramebuffer(GL_FRAMEBUFFER,0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //If the following line gets uncommented the issue goes away
        //glUseProgram(programB);


        //Render call A
        glUseProgram(programA);
        glDrawArrays(GL_TRIANGLES,3);

        //Render call B
        glBindVertexArray(vao);
        glUseProgram(programB);
        float* matrices = new float[sizeof(float) * 16 * 2];

        for (size_t i = 0; i < 2; ++i)
        {
            memcpy((char*)matrices + i * sizeof(float) * 16,(char*)identity,sizeof(float) * 16);
        }
        glUniformMatrix4fv(1,2,GL_FALSE,matrices);
        glDrawArrays(GL_TRIANGLES,3);

        assert(glGetError() == 0);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

程序A:

顶点着色器:

#version 450 core

//If the data block gets commented the issue goes away
layout(std140,binding = 0) uniform DataBlock
{
    mat4 identity;
}dataBlock;


void main()
{
    vec3 positions[3] = { vec3(-0.5,-0.2) };
    gl_Position = vec4(positions[gl_VertexID],1.0);
}

片段着色器:

#version 450 core
out vec4 colour;

void main()
{
    colour = vec4(1.0,1.0);

}

程序B:

顶点着色器:

#version 450 core


layout(location = 0) in int index;
layout(location = 1) uniform mat4[2] matrices;



layout(std140,binding = 0) uniform DataBlock
{
    mat4 identity;
}dataBlock;


void main()
{

    vec3 positions[3] = { vec3(-0.25,-0.2) };
    
    vec4 pos = vec4(positions[gl_VertexID],1.0);
    
    //If "index" is substituted by "0" the problem goes away
    vec4 secondPos = matrices[index] * pos;
    
    //If "secondPos" is substituted by "pos" the problem remains
    //If we remove "dataBlock.identity *" the problem goes away
    gl_Position = dataBlock.identity*secondPos;
}

片段着色器:

#version 450 core

out vec4 colour;

void main()
{
    colour = vec4(0.0,1.0);
}

glGetError()仅返回零。我完全迷路了,不知道如何进行。非常感谢您的帮助。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...