2012-07-16 2 views
1

Что такое правильный способ сделать следующее:OpenGL два прохода шейдера эффект с FBO рендеринга в текстуру дает шум в результате на Windows, только

  1. визуализации сцены в текстуру, используя FBO (FBO-а)
  2. Затем примените эффект, используя текстуру (tex-a), и отрисуйте ее в другую текстуру (tex-b), используя тот же fbo (fbo-a)
  3. Затем визуализируйте эту вторую текстуру с применением эффекта (tex -b) как полноэкранный четырехъядерный.

Мой подход заключается в этом, но это дает мне текстуру, заполненную «шумом» на окне + применяемый эффект (все пиксели случайным образом окрашены в красный цвет, зеленый, синий, черный).

  • Я использую один FBO, с двумя текстурами, установленными в GL_COLOR_ATTACHENT0 (текс-а) и GL_COLOR_ATTACHMENT1 (текс-б)
  • Я связываю свою FBO, убедитесь, что он оказывается в текс-с использованием glDrawBuffer (GL_COLOR_ATTACHMENT0)
  • Затем я применяю эффект в шейдере с текс-привязкой и задан как «sampler2D». Используя текстурный блок 1 и переключитесь на второе вложение цвета (glDrawBuffer (GL_COLOR_ATTACHMENT1)). и сделать полноэкранный квадрат. Теперь все превращается в tex-b
  • Затем я возвращаюсь к стандартным FBO (0) и использую tex-b с полноэкранным четырехъядерным экраном для рендеринга результата.

Пример результата при применении моего шейдер enter noise

Это шейдер я использую. Я не знаю, что это может быть причиной этого, но, может быть, шум вызван переполнением?

Vertex шейдер

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 article на OpenGL.org, где они описывают петлю обратной связи в нижней части статьи. Описание не совсем понятно для меня, и мне интересно, не делаю ли я то, что они там описывают.

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

Link to source code

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

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

+0

Похоже, что это может быть некорректно связанная текстура, вы можете опубликовать свой код настройки FBO/текстуры? – StuGrey

+0

StuGrey, я добавил ссылку в нижней части сообщения. – pollux

+0

StuGrey, также добавил исправление ... хотя ответа нет. – pollux

ответ

3

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

gl_FragColor += sample; 

и

gl_FragColor *= u_exposure; 

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

+0

Спасибо Крису! Я исправил это, установив gl_FragColor. – pollux