Boids в вычислительном шейдере: как избежать стабильного состояния при параллельной обработке всех boid?

Я хочу реализовать простой старинный алгоритм boid в 2D, но в качестве вычислительного шейдера в HLSL (хост-программа - VVVV). Теперь моя проблема: во всех найденных мной примерах 2D-приложений boids обновляются по одному. Это приводит к некоторому дрожанию, которое приводит к типичным "случайным" результатам. Изменение направления и т. Д.

Я не уверен, верна ли моя реализация, но если я проверю каждое правило индивидуально, мои результаты будут похожи на другие ссылки. Однако, если я применяю правила вместе (практически в любой комбинации), очень скоро мои боиды войдут в стабильное состояние, где они образуют фиксированную формацию и просто летят в определенном направлении. Изменение радиуса обзора влияет на размер и количество образований, но не вносит ничего "хаотичного" или подобного скоплениям, только статические сгустки через пару секунд.

Есть ли проблема с реализацией или это просто свойство параллельных вычислений, которое вам нужно компенсировать (как-то?

Соответствующий код:

void CS(uint3 tid : SV_DispatchThreadID){
if (tid.x >= elementCount)
    return;
            

if(reset){
    OutputBuffer[tid.x].x =  random(float2(rand.x + 12,tid.x-4)); // PosXY
    OutputBuffer[tid.x].y =  random(float2(tid.x + 16,rand.y*6));
    OutputBuffer[tid.x].z =  random(float2(tid.x,tid.x * 2)) / 100; //VelXY
    OutputBuffer[tid.x].w =  random(float2(tid.x * 16, tid.x / 4))/ 100; 
}else{  
    
float maxSpeed = 0.01;      
float2 myPos = OutputBuffer[tid.x].xy;
float2 myVel = OutputBuffer[tid.x].zw;
float2 myAcc = 0;

float2 steerAlign = 0;
float2 steerCohesion = 0;
float2 steerAvoid = 0;
    
int    alignCount = 0;
int    cohesionCount = 0;
int    avoidCount = 0;
                
for(uint i = 0; i < elementCount; i++){ 
    if(i != tid.x){
        float2 iPos = OutputBuffer[i].xy;
        float2 iVel = OutputBuffer[i].wz;
    
        float dist = distance(iPos,myPos);  
        
        if(dist < range / 2){
            steerAlign += iVel;
            alignCount++;
        }
        
        if(dist < range * 3){
            steerCohesion += iPos - myPos;
            cohesionCount++;
        }
        
        if(dist < range){
            float2 diff = myPos - iPos;
            diff /= dist * dist;
            steerAvoid += diff;
            avoidCount++;
        }
    }   
}
    
    if(alignCount > 0 && steerAlign.x != 0){
        steerAlign /= alignCount;
        steerAlign = normalize(steerAlign) * maxForce;
    }
    
    if(cohesionCount > 0){
        steerCohesion /= cohesionCount;
        steerCohesion = normalize(steerCohesion) * maxForce;
    }
    
    if(avoidCount > 0){
        steerAvoid /= avoidCount;
        steerAvoid = normalize(steerAvoid) * maxForce;
    }

            
    if(myPos.x < -1){
        myPos.x = 1;
    }
    
    if(myPos.x > 1){
        myPos.x = -1;
    }
    
    if(myPos.y < -1){
        myPos.y = 1;
    }
    
    if(myPos.y > 1){
        myPos.y = -1;
    }
    
    myAcc = (steerAlign * alignFx) + (steerCohesion * cohesionFx) + (steerAvoid * seperationFx);
    myAcc = clamp(myAcc, -maxForce, maxForce);
    
    myVel += myAcc;
    myVel = clamp(myVel,-maxSpeed,maxSpeed);
    myPos += myVel;
    
OutputBuffer[tid.x].xy = myPos;
OutputBuffer[tid.x].zw = myVel;             
}

}

0 ответов

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