2016-01-30 6 views
3

Я работаю над посылочным шейдером GLSL (ES) для 2D-ударных волн. Легко исказить текстуру немного по кругу, и она уже работает для одиночных ударных волн. Теперь мне нужна поддержка нескольких волн в одно и то же время. Мои идеи:Динамический объем работы в шейдере фрагмента GLSL

1-я идея: Выполнение постобработки (привязка FBO -> привязка предыдущей текстуры -> вызов рисования) для каждой волны. Легкая реализация, но много изменений состояния и привлечения вызовов.

вторая идея: Добавить текстуру данных со всей информацией для всех волн и одной форме с числом волн, так что я могу сделать что-то вроде этого:

uniform int count; 
uniform sampler2D dataTex; 
const float dataTexSize = 32; 
[...] 
    vec4 pixel; 
    for(int i = 0; i < count; i++) 
    { 
     vec2 dataTexPos = vec2(i/dataTexSize, 0); 
     pixel += shockwave(texture2D(dataTex, dataTexPos)); 
    } 
    pixel /= float(count); 
[...] 

Но, видимо, графические процессоры не нравятся петли с непостоянным выражением, и драйвер не может развернуть.

Есть ли лучшая практика, чтобы дать шейдерам «динамическое количество работы»? Моя версия OpenGL 2.0 ES.

+0

Вы можете попробовать выполнить профилирование обеих реализаций на любом оборудовании, к которому у вас есть доступ. –

+0

Проблема в том, что вторая идея вообще не работает, потому что я не могу скомпилировать шейдер с циклом for для не константы. Я хотел бы знать, есть ли способ сделать это. –

+0

"* Но, по-видимому, графические процессоры не любят циклы с не постоянным выражением *« Нет, * crappy * GPU не нравится. ES 2.0 не допускает непостоянного цикла, но на самом деле современные графические процессоры отлично справляются с этим. Desktop GL 3.0 отбросил такие требования почти десять лет назад. В мобильном пространстве GL ES 3.0 отбросила эти требования. –

ответ

1

Есть только несколько графических процессоров ES2.0 (доступных в любых разумных количествах), которые не поддерживают динамическую петлю в фрагментарных шейдерах. Два, о которых я специально знаю, это Tegra 2 (Android GLSL fragment shader on NVIDIA tegra2 - но он довольно старый) и Broadcom VC4 (малина Pi и Amazon FireTV Stick). Спецификация ES 2.0 не требует поддержки, но, как отметил @Nicol Bolas, подавляющее большинство мобильных графических процессоров поддерживают ее. Итак, если вы не нацеливаетесь на какой-либо из этих фишек, вы, скорее всего, просто используете шейдер.

К сожалению, нет расширения GLES для рекламы поддержки динамического цикла. Вам просто нужно скомпилировать шейдер с динамическим циклом и посмотреть, удастся ли ему это сделать. В случае, если ваша цель не поддерживает его, вы можете «подделать» динамический цикл, скомпилировав несколько шейдеров с постоянным выражением цикла, вместо использования униформы. Например:

int count = %d; 
uniform sampler2D dataTex; 
const float dataTexSize = 32; 
[...] 
    vec4 pixel; 
    for(int i = 0; i < count; i++) 
    { 
     vec2 dataTexPos = vec2(i/dataTexSize, 0); 
     pixel += shockwave(texture2D(dataTex, dataTexPos)); 
    } 
    pixel /= float(count); 
[...] 

Каждый раз, когда вы столкнулись с ситуацией, когда вам нужно другое количество петель, замените %d с желаемым счетчиком цикла и составить новый шейдер. Пока count имеет достаточно небольшое количество возможных значений, вы не получите столько шейдеров.

+1

Я проверил скорость чтения/записи текстуры, по-видимому, мой настольный GPU-драйвер оптимизирует for-loop с выражением const с динамическим, если внутри отлично. К счастью, моя целевая аудитория - только пользователь настольного компьютера. Благодаря! –