What is the correct way of doing the following:
- Render a scene into a texture using a FBO (fbo-a)
- Then apply an effect using the texture (tex-a) and render this into another texture (tex-b) using the same fbo (fbo-a)
- Then render this second texture, with the applied effect (tex-b) as a full screen quad.
My approach is this, but this gives me a texture filled with "noise" on window + the applied effect (all pixels are randomly colored red, green, blue white, black).
- I'm using one FBO, with two textures set to GL_COLOR_ATTACHENT0 (tex-a) and GL_COLOR_ATTACHMENT1 (tex-b)
- I bind my fbo, make sure it's rendered into the tex-a using glDrawBuffer(GL_COLOR_ATTACHMENT0)
- Then I apply the effect in a shader with tex-a bound and set as 'sampler2D'. Using texture unit 1, and switch to the second color attachment (glDrawBuffer(GL_COLOR_ATTACHMENT1)). and render a full screen quad. Everything is now rendered into tex-b
- Then I switch back to the default FBO (0) and use tex-b with a full screen quad to render the result.
Example of the result when applying my shader
This is the shader I'm using. I'm not aware this could be what is causing this, but maybe the noise is caused by a overflow?
Vertex shader
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;
}
Fragment shader
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;
}
}
I've read this FBO article on opengl.org, where they describe a feedback loop at the bottom of the article. The description is not completely clear to me and I'm wondering if I'm exactly doing what they describe there.
Update 1:
Update 2:
When I first set gl_FragColor.rgb = vec3(0.0, 0.0, 0.0);
before I start the sampling loop (with NUM_SAMPLES), it works find. No idea why though.