GLSL для цикла для ошибки вычисления соседа сетки
Для небольшого фона это для выполнения столкновений частиц с текстурами поиска на GPU. Я прочитал текстуру положения с помощью javascript и создал текстуру сетки, которая содержит частицы, которые находятся в соответствующей ячейке сетки. Рабочий пример, упомянутый в посте, можно посмотреть здесь: https://pacific-hamlet-84784.herokuapp.com/
Причина, по которой мне нужна система контейнеров, заключается в том, что она позволит мне выполнять гораздо меньше проверок, и количество проверок не будет увеличиваться с увеличением количества частиц.
Для актуального описания проблемы:
Я пытаюсь прочитать текстуру поиска с центром вокруг пикселя (скажем, у меня есть текстура 10x10, и я хочу прочитать пиксели вокруг (4,2), я бы прочитал
(3,1),(3,2)(3,3)
(4,1),(4,2)(4,3)
(5,1),(5,2)(5,3)
Цикл немного сложнее, но это общая идея. Если я сделаю цикл выглядеть следующим образом
float xcenter = 5.0;
float ycenter = 5.0;
for(float i = -5.0; i < 5.0; i++){
for(float j = -5.0; j < 5.0; j++){
}
}
Это работает (однако это распространяется на все частицы, которые побеждают цель), однако, если я вычисляю значение динамически (что мне нужно), то я получаю действительно странное поведение. Это проблема с GLSL или проблема с моим кодом? Я вывожу значения в изображение и читаю значения в пикселях, и все они оказываются в нужном диапазоне. Проблема заключается в использовании переменных цикла for (i,j) для изменения индекса сегмента, который вычисляется вне цикла, и использования этой переменной для индексации текстуры.
Весь код шейдера можно увидеть здесь: (если я удаляю жестко закодированный код 70 и удаляю комментарии, которые он разбивает, но все эти значения находятся в диапазоне от 0 до 144. Это то, где я запутался. Я чувствую, что этот код все еще должен работают нормально.).
uniform sampler2D pos;
uniform sampler2D buckets;
uniform vec2 res;
uniform vec2 screenSize;
uniform float size;
uniform float bounce;
const float width = &WIDTH;
const float height = &HEIGHT;
const float cellSize = &CELLSIZE;
const float particlesPerCell = &PPC;
const float bucketsWidth = &BW;
const float bucketsHeight = &BH;
$rand
void main(){
vec2 uv = gl_FragCoord.xy / res;
vec4 posi = texture2D( pos , uv );
float x = posi.x;
float y = posi.y;
float z = posi.z;
float target = 1.0 * size;
float x_bkt = floor( (x + (screenSize.x/2.0) )/cellSize);
float y_bkt = floor( (y + (screenSize.y/2.0) )/cellSize);
float x_bkt_ind_start = 70.0; //x_bkt * particlesPerCell;
float y_bkt_ind_start =70.0; //y_bkt * particlesPerCell;
//this is the code that is acting weirdly
for(float j = -144.0 ; j < 144.0; j++){
for(float i = -144.0 ; i < 144.0; i++){
float x_bkt_ind = (x_bkt_ind_start + i)/bucketsWidth;
float y_bkt_ind = (y_bkt_ind_start + j)/bucketsHeight;
vec4 ind2 = texture2D( buckets , vec2(x_bkt_ind,y_bkt_ind) );
if( abs(ind2.z - 1.0) > 0.00001 || x_bkt_ind < 0.0 || x_bkt_ind > 1.0 || y_bkt_ind < 0.0 || y_bkt_ind > 1.0 ){
continue;
}
vec4 pos2 = texture2D( pos , vec2(ind2.xy)/res );
vec2 diff = posi.xy - pos2.xy;
float dist = length(diff);
vec2 uvDiff = ind2.xy - gl_FragCoord.xy ;
float uvDist = abs(length(uvDiff));
if(dist <= target && uvDist >= 0.5){
float factor = (dist-target)/dist;
x = x - diff.x * factor * 0.5;
y = y - diff.y * factor * 0.5;
}
}
}
gl_FragColor = vec4( x, y, x_bkt_ind_start , y_bkt_ind_start);
}
РЕДАКТИРОВАТЬ: Чтобы прояснить мою проблему, происходит то, что, когда я делаю первый поиск текстуры, я получаю положение частицы:
vec2 uv = gl_FragCoord.xy / res;
vec4 posi = texture2D( pos , uv );
После этого я вычисляю область, в которой находится частица:
float x_bkt = floor( (x + (screenSize.x/2.0) )/cellSize);
float y_bkt = floor( (y + (screenSize.y/2.0) )/cellSize);
float x_bkt_ind_start = x_bkt * particlesPerCell;
float y_bkt_ind_start = y_bkt * particlesPerCell;
Все это правильно. Как будто я получаю правильные значения, и если я устанавливаю их как выходные значения шейдера и считываю пиксели, они являются правильными значениями. Я также немного изменил свою реализацию, и этот код работает нормально.
Чтобы написать текст в цикле for, я заменил координаты поиска пикселей в сетке на позиции пикселей. Я адаптировал код, и он работает нормально, однако мне приходится пересчитывать сегменты несколько раз за кадр, чтобы код был не очень эффективным. Если вместо сохранения положений пикселей я сохраняю координаты uv пикселей, а затем выполняю поиск с использованием этих положений uv:
//get the texture coordinate that is offset by the for loop
float x_bkt_ind = (x_bkt_ind_start + i)/bucketsWidth;
float y_bkt_ind = (y_bkt_ind_start + j)/bucketsHeight;
//use the texture coordinates to get the stored texture coordinate in the actual position table from the bucket table
vec4 ind2 = texture2D( buckets , vec2(x_bkt_ind,y_bkt_ind) );
и тогда я на самом деле получить должность
vec4 pos2 = texture2D( pos , vec2(ind2.xy)/res );
это значение pos2 будет неправильным. Я почти уверен, что значение ind2 является правильным, потому что если вместо сохранения пиксельной координаты в этой таблице сегментов я сохраню значения положения и удаляю второй поиск текстуры, код работает нормально. Но использование второго поиска приводит к сбою кода.
В исходном сообщении, если я установил для сегмента значение любого значения, скажем, в середине текстуры, и перебрал все возможные координаты сегмента вокруг пикселя, он работает нормально. Однако, если я вычисляю положение сегмента и перебираю каждый пиксель, это не так. Интересно, имеет ли это отношение к тому, что glsl компилирует шейдеры, и что какая-то оптимизация, которую он делает, заставляет поиск двойных текстур прервать поиск. Или это просто ошибка в моем коде. Мне удалось получить один текстурный поиск в цикле for, работающем, когда я просто сохранял значения положения в текстуре корзины.