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, работающем, когда я просто сохранял значения положения в текстуре корзины.

0 ответов

Другие вопросы по тегам