带有FBO渲染到纹理的OpenGL双过程着色器效果仅在窗口上产生噪波

带有FBO渲染到纹理的OpenGL双过程着色器效果仅在窗口上产生噪波,opengl,glsl,shader,textures,fbo,Opengl,Glsl,Shader,Textures,Fbo,执行以下操作的正确方法是什么: 使用FBO(FBO-a)将场景渲染为纹理 然后使用纹理(tex-a)应用效果,并使用相同的fbo(fbo-a)将其渲染为另一个纹理(tex-b) 然后使用应用效果(tex-b)将第二个纹理渲染为全屏四边形 我的方法是这样的,但这给了我一个在窗口上填充“噪波”的纹理+应用效果(所有像素都随机着色为红色、绿色、蓝白色和黑色) 我使用的是一个FBO,两个纹理分别设置为GL_COLOR_ATTACHENT0(tex-a)和GL_COLOR_ATTACHMENT1(tex

执行以下操作的正确方法是什么:

  • 使用FBO(FBO-a)将场景渲染为纹理
  • 然后使用纹理(tex-a)应用效果,并使用相同的fbo(fbo-a)将其渲染为另一个纹理(tex-b)
  • 然后使用应用效果(tex-b)将第二个纹理渲染为全屏四边形
  • 我的方法是这样的,但这给了我一个在窗口上填充“噪波”的纹理+应用效果(所有像素都随机着色为红色、绿色、蓝白色和黑色)

    • 我使用的是一个FBO,两个纹理分别设置为GL_COLOR_ATTACHENT0(tex-a)和GL_COLOR_ATTACHMENT1(tex-b)
    • 我绑定我的fbo,确保它使用glDrawBuffer(GL_COLOR_ATTACHMENT0)渲染到tex-a中
    • 然后,我在一个具有tex-a边界的着色器中应用该效果,并将其设置为“sampler2D”。使用纹理单元1,并切换到第二个颜色附件(glDrawBuffer(GL_color_ATTACHMENT1))。并渲染一个全屏四边形。现在,所有内容都渲染为tex-b
    • 然后我切换回默认的FBO(0),并使用tex-b和全屏四边形渲染结果
    应用“我的着色器”时的结果示例

    这是我正在使用的着色器。我不知道这可能是什么原因造成的,但也许噪音是由溢出引起的

    顶点着色器

    attribute vec4 a_pos; 
    attribute vec2 a_tex; 
    varying vec2 v_tex; 
    
    void main() { 
        mat4 ident = mat4(1.0); 
        v_tex = a_tex; 
        gl_Position = ident * a_pos; 
    }
    
    uniform int u_mode; 
    uniform sampler2D u_texture; 
    uniform float u_exposure; 
    uniform float u_decay; 
    uniform float u_density; 
    uniform float u_weight; 
    uniform float u_light_x; 
    uniform float u_light_y; 
    const int NUM_SAMPLES = 100; 
    varying vec2 v_tex; 
    void main() { 
        if (u_mode == 0) { 
            vec2 pos_on_screen = vec2(u_light_x, u_light_y); 
            vec2 delta_texc = vec2(v_tex.st - pos_on_screen.xy); 
            vec2 texc = v_tex; 
            delta_texc *= 1.0 / float(NUM_SAMPLES) * u_density; 
            float illum_decay = 1.0; 
            for(int i = 0; i < NUM_SAMPLES; i++) { 
                texc -= delta_texc; 
                vec4 sample = texture2D(u_texture, texc); 
                sample *= illum_decay * u_weight; 
                gl_FragColor += sample; 
                illum_decay *= u_decay; 
            } 
            gl_FragColor *= u_exposure; 
        } 
        else if(u_mode == 1) { 
            gl_FragColor = texture2D(u_texture, v_tex); 
            gl_FragColor.a = 1.0; 
        } 
    
    }
    
    片段着色器

    attribute vec4 a_pos; 
    attribute vec2 a_tex; 
    varying vec2 v_tex; 
    
    void main() { 
        mat4 ident = mat4(1.0); 
        v_tex = a_tex; 
        gl_Position = ident * a_pos; 
    }
    
    uniform int u_mode; 
    uniform sampler2D u_texture; 
    uniform float u_exposure; 
    uniform float u_decay; 
    uniform float u_density; 
    uniform float u_weight; 
    uniform float u_light_x; 
    uniform float u_light_y; 
    const int NUM_SAMPLES = 100; 
    varying vec2 v_tex; 
    void main() { 
        if (u_mode == 0) { 
            vec2 pos_on_screen = vec2(u_light_x, u_light_y); 
            vec2 delta_texc = vec2(v_tex.st - pos_on_screen.xy); 
            vec2 texc = v_tex; 
            delta_texc *= 1.0 / float(NUM_SAMPLES) * u_density; 
            float illum_decay = 1.0; 
            for(int i = 0; i < NUM_SAMPLES; i++) { 
                texc -= delta_texc; 
                vec4 sample = texture2D(u_texture, texc); 
                sample *= illum_decay * u_weight; 
                gl_FragColor += sample; 
                illum_decay *= u_decay; 
            } 
            gl_FragColor *= u_exposure; 
        } 
        else if(u_mode == 1) { 
            gl_FragColor = texture2D(u_texture, v_tex); 
            gl_FragColor.a = 1.0; 
        } 
    
    }
    
    uniformintu\u模式;
    均匀的二维u_纹理;
    均匀浮动u__曝光;
    均匀浮u_衰减;
    均匀浮球密度;
    均匀浮球重量;
    均匀浮动u___x;
    均匀浮球;
    const int NUM_SAMPLES=100;
    可变矢量2 v_tex;
    void main(){
    如果(u_mode==0){
    屏幕上的vec2位置=vec2(u灯x、u灯y);
    vec2 delta_texc=vec2(v_tex.st-pos_on_screen.xy);
    vec2 texc=v_tex;
    delta_texc*=1.0/浮点数(样本数)*u密度;
    浮动照明衰减=1.0;
    对于(int i=0;i
    我在opengl.org上读过这篇文章,他们在文章的底部描述了一个反馈循环。这个描述对我来说并不完全清楚,我想知道我是否在做他们描述的事情

    更新1:

    更新2:


    当我第一次设置
    gl_FragColor.rgb=vec3(0.0,0.0,0.0)在启动采样循环(使用NUM_SAMPLES)之前,它可以工作。不知道为什么。

    问题是您没有初始化gl\u FragColor
    ,而是用行修改它

    gl_FragColor += sample;
    


    两者都取决于gl_FragColor的先前值。因此,您将得到一些随机垃圾(着色器编译器决定用于gl_FragColor计算的寄存器中发生的任何东西)添加到中。这很有可能在某些驱动程序/硬件组合上运行良好(因为编译器出于某种原因决定使用始终为0的寄存器),而在其他组合上运行不好。

    这看起来可能是一个绑定错误的纹理,你能发布你的FBO/纹理设置代码吗?Stugray,我在帖子底部添加了链接。Stugray,还添加了一个修复。。。虽然没有回答。谢谢克里斯!我确实通过设置gl_FragColor修复了它。