Как правильно сделать следующее:
- Рендеринг сцены в текстуру с помощью FBO (fbo-a)
- Затем примените эффект, используя текстуру (tex-a), и преобразуйте его в другую текстуру (tex-b), используя тот же fbo (fbo-a).
- Затем визуализируйте эту вторую текстуру с примененным эффектом (tex-b) как полноэкранный четырехугольник.
Мой подход таков, но он дает мне текстуру, заполненную «шумом» в окне + примененный эффект (все пиксели случайным образом окрашены в красный, зеленый, синий, белый, черный цвета).
- Я использую один FBO с двумя текстурами, установленными на GL_COLOR_ATTACHENT0 (tex-a) и GL_COLOR_ATTACHMENT1 (tex-b)
- Я привязываю свой fbo, убеждаюсь, что он отображается в tex-a с помощью glDrawBuffer (GL_COLOR_ATTACHMENT0)
- Затем я применяю эффект в шейдере с привязкой 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;
}
}
Я прочитал эту статью о FBO на opengl.org, где они описывают цикл обратной связи на внизу статьи. Описание мне не совсем понятно, и мне интересно, делаю ли я именно то, что там описывают.
Обновление 1:
Обновление 2:
Когда я впервые устанавливаю gl_FragColor.rgb = vec3(0.0, 0.0, 0.0);
перед тем, как начать цикл выборки (с NUM_SAMPLES), он работает find. Хотя понятия не имею, почему.