Случайные скорости при использовании симуляционного шейдера
Я пытаюсь реализовать симуляцию Fruchterman Reingold с использованием шейдеров. Перед реализацией части вычислений в шейдере я написал ее в javascript. Это работает именно так, как я ожидаю, как видно здесь:
http://jaredmcqueen.github.io/gpgpu-force-direction/canvas_app.html
При реализации вычислительной части в шейдере я получаю стабильную структуру, которая случайно перемещается по экрану. Я не могу понять, какие силы отталкивания / притяжения вызывают непредсказуемое плавание моих графиков:
http://jaredmcqueen.github.io/gpgpu-force-direction/gpgpu_app.html
ядром физики являются функции отталкивания / притяжения:
//fr(x) = (k*k)/x;
vec3 addRepulsion(vec3 self, vec3 neighbor){
vec3 diff = self - neighbor;
float x = length( diff );
float f = ( k * k ) / x;
return normalize(diff) * f;
}
//fa(x) = (x*x)/k;
vec3 addAttraction(vec3 self, vec3 neighbor){
vec3 diff = self - neighbor;
float x = length( diff );
float f = ( x * x ) / k;
return normalize(diff) * f;
}
Любое понимание того, почему gpgpu, шейдеры, основанные на симуляции, ведут себя на первый взгляд случайным образом, будет с благодарностью.
2 ответа
Оказывается, я неправильно перебирал грани. Вот моя новая краевая итерация:
float idx = selfEdgeIndices.x;
float idy = selfEdgeIndices.y;
float idz = selfEdgeIndices.z;
float idw = selfEdgeIndices.w;
float start = idx * 4.0 + idy;
float end = idz * 4.0 + idw;
if(! ( idx == idz && idy == idw ) ){
float edgeIndex = 0.0;
for(float y = 0.0; y < edgesTexWidth; y++){
for(float x = 0.0; x < edgesTexWidth; x++){
vec2 ref = vec2( x + 0.5 , y + 0.5 ) / vec2(edgesTexWidth,edgesTexWidth);
vec4 pixel = texture2D(edgeData,ref);
if (edgeIndex >= start && edgeIndex < end){
nodePosition = getNeighbor(pixel.x);
nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
}
edgeIndex++;
if (edgeIndex >= start && edgeIndex < end){
nodePosition = getNeighbor(pixel.y);
nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
}
edgeIndex++;
if (edgeIndex >= start && edgeIndex < end){
nodePosition = getNeighbor(pixel.z);
nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
}
edgeIndex++;
if (edgeIndex >= start && edgeIndex < end){
nodePosition = getNeighbor(pixel.w);
nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
}
edgeIndex++;
}
}
}
Это не кажется случайным, конструкция стабилизируется в, казалось бы, правильном состоянии и движется в постоянном направлении.
Похоже, что вы применяете силу в шейдере, а затем обновляете позицию вашей модели на стороне ЦП, и эта глобальная позиция модели должна оставаться постоянной, либо должна была быть обновлена другим значением.
Из того, что я видел в коде, я рекомендую исключить компиляцию с плавающей запятой (compareNodePosition.w == -1.0 || 0.0) и продолжить оператор. Скажите, пожалуйста, помогло ли это. Я еще не изучал логику алгоритмов.