Mar 23, 2009
Optimizing the Alchemy Particle Emitter
30,000 simultaneously moving particles with a decent frame rate. Not bad at all.
Improving the performance of my Particle Systems API port involved completely rewriting the way data was being marshaled from C++ to AS. The original emitter passed two ByteArrays, one for positions and one for colors, and had AS step through each to draw individual pixels as well as handle 2D projection. This resulted in a steady 20fps (on my Macbook Pro) with roughly 5,000 simultaneous particles.
In order to improve speed, I needed to have C++ handle all the projection and pixel positioning operations. Using a technique Ralph Hauwert implemented for his particle experiment, which manipulates the memory Alchemy uses in the runtime instead of passing value sets, I had C++ do all the heavy lifting. The main difference from Ralph's project is that I had C++ deal with all the projection math instead of PixelBender since the vertices are being generated from Particle System API.
Here is the main AS loop:
-
rotX += (vmouse.x-rotX)*0.1;
-
rotY += (vmouse.y-rotY)*0.1;
-
-
projectionMatrix.identity();
-
projectionMatrix.appendRotation(rotX, Vector3D.Y_AXIS);
-
projectionMatrix.appendRotation(rotY, Vector3D.X_AXIS);
-
projectionMatrix.appendTranslation(0, 0, 100);
-
projectionMatrix.toArray(projectionArray);
-
-
alchemyMemory.position = alcBitmapPointer;
-
alchemyMemory.writeBytes(clearBA,0,clearBA.length);
-
alcLib.emit(
-
projectionArray[0],
-
projectionArray[1],
-
projectionArray[4],
-
projectionArray[5],
-
projectionArray[8],
-
projectionArray[9],
-
projectionArray[12],
-
projectionArray[13]
-
);
-
alchemyMemory.position = alcBitmapPointer;
-
bitmapData.setPixels(bitmapData.rect, alchemyMemory);
The emit method AS is calling, which is handling all the positioning and projection, looks like this:
-
AS3_Val emit(void *data, AS3_Val args)
-
{
-
switch(DemoNum) {
-
case 0: Orbit2(ft); break;
-
case 1: Sphere(ft); break;
-
case 2: Swirl(ft); break;
-
case 3: Fireflies(ft); break;
-
case 4: FlameThrower(ft); break;
-
case 5: Atom(ft); break;
-
case 6: JetSpray(ft); break;
-
default: Orbit2(ft); break; }
-
ft = false;
-
-
double p0,p1,p4,p5,p8,p9,p12,p13;
-
-
AS3_ArrayValue(args,"DoubleType, DoubleType, DoubleType, DoubleType, DoubleType, DoubleType, DoubleType, DoubleType",
-
&p0, &p1, &p4, &p5, &p8, &p9, &p12, &p13);
-
-
cnt = P.GetGroupCount();
-
float *ppos = new float[cnt * 3];
-
float *pcol = new float[cnt * 4];
-
P.GetParticles(0, cnt, ppos, pcol);
-
-
int ct = 0;
-
int length = cnt*3;
-
int pos;
-
float x,y,z;
-
int new_x,new_y;
-
-
int r,g,b,a;
-
int c;
-
-
for(ct=0; ct <length; ct+=3 ){
-
x = ppos[ct]*32;
-
y = ppos[ct+1]*32;
-
z = ppos[ct+2]*32;
-
-
new_x = x * p0 + y * p4 + z * p8 + p12 + resX/2;
-
new_y = x * p1 + y * p5 + z * p9 + p13 + resY/2;
-
-
r = (float)pcol[((ct/3)*4)]*255;
-
g = (float)pcol[((ct/3)*4)+1]*255;
-
b = (float)pcol[((ct/3)*4)+2]*255;
-
a = (float)pcol[((ct/3)*4)+3]*255;
-
c = a<<24 | r<<16 | g<<8 | b;
-
-
if(new_x> 0 && new_x <resX && new_y> 0 && new_y <resY){
-
pos = new_y*resX+new_x;
-
tBuffer[pos] = c;
-
}
-
}
-
-
delete ppos;
-
delete pcol;
-
-
return 0;
-
}



Impressive!
Very cool!
Wow that is really amazing and fast. Nice work. This instantly reminded me of those java based galaxy simulators, these are highly popular and are very fun because it is a new experience every time. Keep it up, Alchemy is a new path to travel.
this is a great experiment…
im learning c++ at the moment and this is very exciting for increasing the potential of flash.
keep up the great work!
[...] FP10’s Drawing API http://www.peternitsch.net/blog/?p=139 Optimizing the Alchemy Particle Emitter http://www.peternitsch.net/blog/?p=166 [...]
[...] Peter Nitsch – Alchemy Particles [...]
nice. looking forward to seeing the code
hi, im just researching in ways of using alchemy to speed up a particle system made of type. although all the examples ive seen have been rendering to a pixel array using alchemy and then loading those pixels into a bitmap data in flash.
is there any way of controlling the XYZ vector of a particle in flash using alchemy and simply get flash just to render a movie clip at that position?
L.