2013-02-26 4 views
1

Я пытаюсь достичь следующей задачи:Texture приводом частиц в WebGL/OpenGL с использованием шейдеров

  • Я решетчатый (план) NxM указывает
  • Я текстуру, которая каждый пиксель представляет собой силовое поле для позиции X, Y
  • Я хотел бы итеративно обновить исходную сетку, используя текстуры силового поля (и затенение)

Я думаю, мы могли бы довольно легко сделать это с помощью " геометрический шейдер ", однако это не присутствует в WebGL. Поэтому, как я мог использовать программу, управляемую GLSL, чтобы обновить положение вершин в моей сетке? Как я понял, регулярный вершинный шейдер превращает источник в что-то еще за один проход, теперь есть способ подавать этот вывод обратно в шейдер во время следующей итерации?

[edit] Возможный способ, который я могу видеть прямо сейчас, может состоять в использовании фрагментарного шейдера, результат которого затем может быть сохранен в текстуре, которую я мог бы повторить на следующем шаге.

ответ

2

Да, используйте фрагментарный шейдер. Сохраните состояние сетки в текстуре (для большинства удобностей - текстура с плавающей точкой, хотя для этого требуется расширение), и используйте шейдер фрагмента для вычисления новой текстуры, которая является следующей итерацией. Затем, когда на самом деле рисует, вершинный шейдер считывает текстуру, чтобы определить отображаемые координаты вершин.

У меня implemented a particle system using this technique. Вот фрагмент шейдера, который обновляет состояние, поэтому вы можете получить представление о том, как он работает. Для каждой частицы пара соседних текселей (с 8 поплавками) сохраняет свое положение и скорость.

#ifdef GL_ES 
precision highp float; 
#endif 

uniform sampler2D uState; 
uniform float uResolution; 
uniform float uDT; 
uniform float uHarmonicAccel; 

vec4 lookup(float offset) { 
    return texture2D(uState, (gl_FragCoord.xy + vec2(offset, 0.0))/uResolution); 
} 

void main(void) { 
    bool updatingPosition = mod(gl_FragCoord.x, 2.0) < 1.0; 
    vec4 posp, velp; 
    if (updatingPosition) { 
    posp = lookup(0.0); 
    velp = lookup(1.0); 
    } else { 
    posp = lookup(-1.0); 
    velp = lookup(0.0); 
    } 
    vec3 pos = vec3(posp); 
    vec3 vel = vec3(velp); 

    // velocity update is applied to position as well 
    vel += uHarmonicAccel * uDT * normalize(pos); 

    if (updatingPosition) { 
    gl_FragColor = vec4(pos + uDT * vel, posp[3]); 
    } else { 
    gl_FragColor = vec4(vel, velp[3]); 
    } 
} 
+0

Использование размерной текстуры N x 2 x Vec4 было бы легче обрабатывать, чем 2 соседних текста. Хороший трюк btw :-) –

+0

@FlavienVolken Это осторожно об использовании текстуры, которая чрезвычайно велика в одном измерении. У меня такое впечатление, что иногда это может не поддерживаться. –

Смежные вопросы