粒子系统运行缓慢

时间:2015-11-26 03:33:41

标签: three.js particle-system

这里是更新功能。一旦我更新我的程序变慢。我甚至无法一次渲染25000个粒子。体素是三维阵列。如何更改我的更新功能,以便更快地完成计算。我希望能够渲染至少100000个粒子。

function update(){

newTime = Date.now();
elapsedTime = newTime - oldTime;
oldTime = newTime;


for(var index =0 ; index < particles.vertices.length; index++){

    //particle's old position
    var oldPosition = particles.vertices[index];

    //making sure particles do not og out of boundary 
    if (oldPosition.x > screenSquareLength || oldPosition.x < -screenSquareLength){
        oldPosition.x =  2 * screenSquareLength * Math.random() - screenSquareLength;
    }
    if (oldPosition.y > screenSquareLength || oldPosition.y < -screenSquareLength){
        oldPosition.y =  2 * screenSquareLength * Math.random() - screenSquareLength;   
    }
    if (oldPosition.z > screenSquareDepth/2 || oldPosition.z < -screenSquareDepth/2){
        oldPosition.z =  screenSquareDepth * Math.random() - screenSquareDepth/2;
    }


    var oldVelocity = particlesExtraInfo[index].velocity;
    var fieldVelocity;
    var xIndex, yIndex, zIndex;


    try{
        //calculating index of voxel
        xIndex = Math.floor(( oldPosition.x + screenSquareLength ) / voxelSize);
        yIndex = Math.floor(( oldPosition.y  + screenSquareLength ) / voxelSize);
        zIndex = Math.floor(( screenSquareDepth / 2  - oldPosition.z) / voxelSize);


        //getting velocity, color for particle  and if voxel is
        fieldVelocity = voxels[zIndex][xIndex][yIndex].userData["velocity"];
        particleColor = voxels[zIndex][xIndex][yIndex].userData["color"];
        activeVoxel = voxels[zIndex][xIndex][yIndex].userData["visible"];

    }catch (e){
        console.log("indexX = "+xIndex + " \t Yindex = "+ yIndex+" \t zIndex = "+ zIndex);
    }


    var particleColor;
    var activeVoxel;



    try{

        var vx = ((oldVelocity.x + fieldVelocity.x) * elapsedTime);
        var vy = ((oldVelocity.y + fieldVelocity.y) * elapsedTime);
        var vz = ((oldVelocity.z + fieldVelocity.z) * elapsedTime);
        var magnitude = Math.abs(vx) + Math.abs(vy) + Math.abs(vz); //Math.sqrt(vx*vx + vy*vy+ vz*vz);
        var normalized = new THREE.Vector3(vx / magnitude, vy / magnitude, vz / magnitude);



        if((particles.vertices[index].x < 0.1 && particles.vertices[index].x > -0.1) && (particles.vertices[index].y < 0.1 && particles.vertices[index].y > -0.1) && (particles.vertices[index].z < 0.1 && particles.vertices[index].z > -0.1) ){
            particles.vertices[index].x = 2 * screenSquareLength * Math.random() - screenSquareLength;;
            particles.vertices[index].y = 2 * screenSquareLength * Math.random() - screenSquareLength;;
            particles.vertices[index].z = 2 * screenSquareLength * Math.random() - screenSquareLength;;
        }



        //if voxel is not part of the model update particle postion and velocity
        if( activeVoxel == 0){
            particles.colors[index] = new THREE.Color(particleColor);//new THREE.Color(0, 0, 1);
            particles.colorsNeedUpdate = true;

            particles.vertices[index].x += normalized.x/slowingFactor;
            particles.vertices[index].y += normalized.y/slowingFactor;
            particles.vertices[index].z += normalized.z/slowingFactor;
            particles.verticesNeedUpdate = true;
            particlesExtraInfo[index].velocity = normalized;
        }else{
            //voxel is part of particle so update color property of particle
            particles.colors[index] = new THREE.Color(0, 0, 1);
            particles.colorsNeedUpdate = true;



            particles.vertices[index].x += normalized.x/(slowingFactor * 200);
            particles.vertices[index].y += normalized.y/(slowingFactor * 200);
            particles.vertices[index].z += normalized.z/(slowingFactor * 200);

            particles.verticesNeedUpdate = true;

            particlesExtraInfo[index].velocity = new THREE.Vector3( normalized.x/slowingFactor, normalized.y/slowingFactor, normalized.z/slowingFactor );

        }
    }catch(e){

    }
}

}

1 个答案:

答案 0 :(得分:0)

我不太了解更新这样的缓冲区时会发生什么,但我知道它可能很慢。

虽然25k可能对你正在尝试做的事情很重要(我用5k试验并遇到麻烦)但是没有理由为什么你不能在尝试将所有内容移到gpu之前优化你的JS (例如)。

var foo = 0;

foo+= normalized.x / someFactor;

//better done this way:
var invSomeFactor = 1/someFactor;

// now you avoid dividing the same thing many times in your loop
foo += normalized.x * invSomeFactor;

Math.random()非常昂贵,您可以创建一个查找表(一个大表)并从中获取这些预先计算的值。

var myLookupTable = [];
var MAX_VALUES = 2048;

for ( var i = 0 ; i < MAX_VALUES ; i ++ ){
     myLookupTable.push(Math.random());
}

//and then you can have a stride for example
var RAND_STRIDE = 0;

//and in the loop
    someVec.x += something.x * myLookupTable[ RAND_STRIDE ++ ];

    RAND_STRIDE %= MAX_VALUES; //read from the beginning

最后,您可以编写一个片段着色器,它将从缓冲区读取,并写入另一个缓冲区,在该过程中执行所有这些逻辑。每个片段都是你的粒子,一旦你运行这个传递并计算你的位置,你需要能够在粒子顶点着色器中读取缓冲区并只分配这些位置。