Эффект двухпроходного шейдера OpenGL с рендерингом FBO в текстуру дает шум только в Windows

Как правильно сделать следующее:

  1. Рендеринг сцены в текстуру с помощью FBO (fbo-a)
  2. Затем примените эффект, используя текстуру (tex-a), и преобразуйте его в другую текстуру (tex-b), используя тот же fbo (fbo-a).
  3. Затем визуализируйте эту вторую текстуру с примененным эффектом (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 с полноэкранным квадратом для рендеринга результата.

Пример результата при применении моего шейдера 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; 
    } 

}

Я прочитал эту статью о FBO на opengl.org, где они описывают цикл обратной связи на внизу статьи. Описание мне не совсем понятно, и мне интересно, делаю ли я именно то, что там описывают.

Обновление 1:

Ссылка на исходный код

Обновление 2:

Когда я впервые устанавливаю gl_FragColor.rgb = vec3(0.0, 0.0, 0.0); перед тем, как начать цикл выборки (с NUM_SAMPLES), он работает find. Хотя понятия не имею, почему.


person pollux    schedule 16.07.2012    source источник
comment
Похоже, это может быть неправильно связанная текстура, не могли бы вы опубликовать свой код настройки FBO / текстуры?   -  person StuGrey    schedule 16.07.2012
comment
StuGrey, ссылку внизу поста добавил.   -  person pollux    schedule 16.07.2012
comment
StuGrey, тоже исправление добавил ... правда ответа нет.   -  person pollux    schedule 16.07.2012


Ответы (1)


Проблема в том, что вы не инициализируете gl_FragColor, а изменяете его строками

gl_FragColor += sample;

и

gl_FragColor *= u_exposure;

оба зависят от предыдущего значения gl_FragColor. Таким образом, вы получаете какой-то случайный мусор (что бы ни случилось в регистре, который компилятор шейдера решил использовать для вычисления gl_FragColor), добавленный. Это имеет большую вероятность нормально работать с некоторыми комбинациями драйвера / оборудования (потому что компилятор решил использовать регистр, который по какой-то причине всегда был 0), а не для других.

person Chris Dodd    schedule 16.07.2012
comment
Спасибо, Крис! Я действительно исправил это, установив gl_FragColor. - person pollux; 16.07.2012