1

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

  1. 使用 FBO (fbo-a) 将场景渲染为纹理
  2. 然后使用纹理 (tex-a) 应用效果并使用相同的 fbo (fbo-a) 将其渲染到另一个纹理 (tex-b)
  3. 然后渲染第二个纹理,应用效果 (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; 
    } 

}

我在 opengl.org 上阅读了这篇FBO 文章,他们在文章底部描述了一个反馈循环。描述对我来说并不完全清楚,我想知道我是否在做他们在那里描述的事情。

更新1:

链接到源代码

更新 2:

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

4

1 回答 1

3

问题是你没有初始化gl_FragColor,你正在用这些行修改它

gl_FragColor += sample;

gl_FragColor *= u_exposure;

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

于 2012-07-16T18:38:30.763 回答