执行以下操作的正确方法是什么:
- 使用 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;
}
}
我在 opengl.org 上阅读了这篇FBO 文章,他们在文章底部描述了一个反馈循环。描述对我来说并不完全清楚,我想知道我是否在做他们在那里描述的事情。
更新1:
更新 2:
当我gl_FragColor.rgb = vec3(0.0, 0.0, 0.0);
在开始采样循环(使用 NUM_SAMPLES)之前第一次设置时,它可以找到。不知道为什么。