OpenGL双通着色器效果与FBO渲染到纹理仅在Windows上产生噪点

时间:2012-07-16 10:16:05

标签: opengl glsl shader textures fbo

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

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

    • 我正在使用一个FBO,其中两个纹理设置为GL_COLOR_ATTACHENT0(tex-a)和GL_COLOR_ATTACHMENT1(tex-b)
    • 我绑定了我的fbo,确保使用glDrawBuffer(GL_COLOR_ATTACHMENT0)将其渲染到tex-a中
    • 然后我在带有tex-a bound的着色器中应用效果并设置为'sampler2D'。使用纹理单元1,并切换到第二个颜色附件(glDrawBuffer(GL_COLOR_ATTACHMENT1))。并渲染全屏四边形。现在一切都被渲染成了tex-b
    • 然后我切换回默认的FBO(0)并使用tex-b和全屏四边形来渲染结果。

    应用我的着色器时的结果示例 enter noise

    这是我正在使用的着色器。我不知道这可能是造成这种情况的原因,但噪音可能是由溢出造成的?

    顶点着色器

    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; 
        } 
    
    }
    

    我在opengl.org上看过这个FBO article,他们在文章的底部描述了一个反馈循环。这个描述对我来说并不完全清楚,我想知道我是否正在做他们在那里所描述的内容。

    更新1:

    Link to source code

    更新2:

    当我在开始采样循环(使用NUM_SAMPLES)之前首次设置gl_FragColor.rgb = vec3(0.0, 0.0, 0.0);时,它可以找到。不知道为什么。

1 个答案:

答案 0 :(得分:3)

问题在于你没有初始化gl_FragColor,而是用行修改它

gl_FragColor += sample;

gl_FragColor *= u_exposure;

两者都取决于gl_FragColor的先前值。所以你得到了一些随机垃圾(无论发生在着色器编译器决定用于gl_FragColor计算的寄存器中)。这很有可能在一些驱动程序/硬件组合上正常工作(因为编译器决定了)使用由于某种原因始终为0的寄存器而不是其他寄存器。