Skip to content

Commit 2dc53dc

Browse files
committed
Performance related tuning. Now manipulating pixel data directly. We lose performance at lower pixel counts but have huge gains with larger systems.
1 parent e7e0fcf commit 2dc53dc

File tree

5 files changed

+111
-36
lines changed

5 files changed

+111
-36
lines changed

index.htm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,15 @@
7878
<li>Max Particles :</li>
7979
<li id="maxParticles">
8080
<button value="10"/>10</button>
81-
<button value="500"/>500</button>
8281
<button value="2000"/>2k</button>
8382
<button value="5000"/>5k</button>
8483
<button value="10000"/>10k</button>
84+
<button value="20000"/>20k</button>
8585
</li>
8686
<li>Particle Style</li>
8787
<li id="particleStyle">
8888
<button value="basic"/>Basic</button>
89+
<button value="variable"/>Colors</button>
8990
<button value="fancy"/>Fancy</button>
9091
</li>
9192
</ul>
@@ -101,7 +102,7 @@
101102
<button class="loadExample" id="example3">Example 3</button>
102103
<button class="loadExample" id="example4">Example 4</button>
103104
<button class="loadExample" id="example5">Example 5</button>
104-
<button class="loadExample" id="bonus">Bonus</button>
105+
<button class="loadExample" id="bonus">Candle</button>
105106
<button class="loadExample" id="3alt">Ex. 3 Alt</button>
106107
</div>
107108
<div id="floatingControls" class="closable">

js/particleController.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ var particleSystem = null;
33
var examples = {
44
example1 : '0,basic:Sv1(2000|1|0|0|1|E360,230:2,0:8:-1:0.10:4|F700,230:-140:8)',
55
// example2 : '0,basic:Sv1(2000|1|0|0|1|E388,158:2,0:8:-1:0.10:4|F497,233:500|F442,240:-37)',
6-
example2 : '0,basic:Sv1(2000|1|0|0|1|E388,158:2,0:8:-1:0.10:4|F443,211:500)',
6+
example2 : '0,variable:Sv1(5000|1|0|0|1|E388,158:2,0:8:-1:0.10:4|F443,211:500)',
77
example3 : '0,basic:Sv1(2000|0|0|0|1|E500,275:1.3,-0:8:-1:3.14:4|F650,275:-250|F350,275:-250|F500,125:-250|F500,425:-250|F606,381:-250|F606,169:-250|F397,381:-250|F397,169:-250)',
8-
example4 : '0,basic:Sv1(2000|1|0|0|1|E217,453:1.913,-0.585:8:-1:0.10:4|F337,472:-140|F533,327:500|F672,393:-140|F284,347:-140)',
8+
example4 : '0,variable:Sv1(2000|1|0|0|1|E217,453:1.913,-0.585:8:-1:0.10:4|F337,472:-140|F533,327:500|F672,393:-140|F284,347:-140)',
99
example5 : '1,basic:Sv1(2000|0|1|0|0|E500,275:2,0:8:-1:3.14:4|F650,275:-140:8|F350,275:-140:8|F500,125:-140:8|F500,425:-140:8|F606,381:-140:8|F606,169:-140:8|F397,381:-140:8|F397,169:-140:8)',
1010
'3alt' : '0,basic:Sv1(2000|1|0|0|1|E500,250:4,0:8:-1:3.14:4|F500,250:80)',
11-
bonus : '0,fancy:Sv1(2000|0|0|0|1|E502,277:0.005,-0.3:15:130:3.14:4|F650,275:-250:8|F350,275:-250:8|F500,425:-250:8|F606,381:-250:8|F606,169:-250:8|F397,381:-250:8|F397,169:-250:8)'
11+
bonus : '0,fancy:Sv1(5000|0|0|0|1|E502,277:0.005,-0.3:15:130:3.14:4|F650,275:-250:8|F350,275:-250:8|F500,425:-250:8|F606,381:-250:8|F606,169:-250:8|F397,381:-250:8|F397,169:-250:8)'
1212
};
1313
var particleStyle = 'basic';
1414
var programmaticUpdate = false;
@@ -111,8 +111,8 @@ function registerButtons() {
111111
$('#accelerations').click(toggleAccelerations);
112112
$('#velocities').click(toggleVelocities);
113113
$('#particles').click(toggleParticles);
114-
$('#maxParticles > button').click(function(){particleSystem.maxParticles = $(this).val();});
115-
$('#particleStyle > button').click(function(){changeParticleDrawStyle($(this).val());});
114+
$('#maxParticles > button').click(function(){particleSystem.maxParticles = $(this).val();updateHash();});
115+
$('#particleStyle > button').click(function(){changeParticleDrawStyle($(this).val());updateHash();});
116116
//http://www.facebook.com/share.php?u=<;url>
117117
$('#fbShare').click(function(){
118118
var url = location;
@@ -167,14 +167,17 @@ function changeParticleDrawStyle(style) {
167167
particleStyle = style || 'basic';
168168
var styles = {
169169
basic : function() {
170-
display.context.globalCompositeOperation = "source-over"
171-
Particle.globalDrawColor = "#437EDE";
172-
Particle.prototype.draw = Particle.prototype.drawQuick;
170+
Particle.GLOBAL_DRAW_COLOR = [255,80,40,255];
171+
Particle.prototype.draw = Particle.prototype.drawBasic;
172+
},
173+
variable : function() {
174+
// Particle.GLOBAL_DRAW_COLOR = [66,167,222,255];
175+
Particle.GLOBAL_DRAW_COLOR = [66,167,180,255];
176+
Particle.prototype.draw = Particle.prototype.drawVariable;
173177
},
174178
fancy : function() {
175-
display.context.globalCompositeOperation = "lighter";
176-
Particle.globalDrawColor = "rgba(166,67,0,.7)";
177-
Particle.prototype.draw = Particle.prototype.drawSize;
179+
Particle.GLOBAL_DRAW_COLOR = [166,67,0,255];
180+
Particle.prototype.draw = Particle.prototype.drawSoft;
178181
}
179182
};
180183
if (styles[particleStyle]) {

js/particleSystem/Display.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ function Display(canvas) {
33

44
self.canvas = canvas;
55
self.context = undefined;
6-
self.framerate = 80;
6+
self.framerate = 100;
77
self.numFrames = 0;
88
self.paused = true;
99
self.nextRedraw = 0;
@@ -20,11 +20,12 @@ function Display(canvas) {
2020
runningFrameTime : 0
2121
};
2222

23-
self.init = function(){
23+
self.init = function(){
2424
if(!self.canvas.getContext){
2525
self.error("No Context");
2626
return;
2727
}
28+
2829
self.context = self.canvas.getContext( "2d" );
2930
self.context.scale(self.scale,self.scale);
3031

@@ -36,6 +37,11 @@ function Display(canvas) {
3637
self.canvas.onmouseover = function(evt) {self.fireEvent('mouseOver',evt)};
3738
self.canvas.onmousemove = function(evt) {self.fireEvent('mouseMove',evt)};
3839

40+
window.requestAnimFrame = window.requestAnimationFrame ||
41+
window.webkitRequestAnimationFrame ||
42+
window.mozRequestAnimationFrame ||
43+
window.oRequestAnimationFrame ||
44+
window.msRequestAnimationFrame;
3945

4046
self.addListener('draw', self);
4147
self.addListener('afterDraw', self);
@@ -64,7 +70,11 @@ function Display(canvas) {
6470
if (!self.paused) {
6571
self.nextFrame();
6672
}
67-
self.nextRedraw = setTimeout( function(){ self.main(); }, 1000/self.framerate );
73+
if (window.requestAnimFrame) {
74+
window.requestAnimFrame(function(){ self.main(); });
75+
} else {
76+
self.nextRedraw = setTimeout( function(){ self.main(); }, 1000/self.framerate );
77+
}
6878
};
6979

7080
self.nextFrame = function() {

js/particleSystem/Particle.js

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ function Particle(point,velocity){
22
this.position = point;
33
this.velocity = velocity;
44
this.acceleration = new Vector(0,0);
5-
this.size = 3;
65
this.ttl = -1;
76
this.lived = 0;
87
}
98

10-
Particle.globalDrawColor = "#437EDE";
9+
Particle.GLOBAL_DRAW_COLOR = [66,167,222,255];
10+
//Particle.GLOBAL_DRAW_COLOR = [166,67,0,255];
1111

1212
Particle.prototype.submitToFields = function(fields) {
1313
var totalAccelerationX = 0;
@@ -33,14 +33,75 @@ Particle.prototype.move = function() {
3333
this.position.y += this.velocity.y;
3434
};
3535

36-
Particle.prototype.drawSize = function(display) {
37-
var halfSize = this.size / 2;
38-
display.context.fillRect(this.position.x - halfSize,this.position.y - halfSize,this.size,this.size);
36+
Particle.prototype.drawVariable = function(pixels,width,height) {
37+
var baseIndex = 4 * (~~this.position.y * width + ~~this.position.x);
38+
var velocity = this.velocity.getMagnitude();
39+
var r = Particle.GLOBAL_DRAW_COLOR[0] * velocity;
40+
var g = Particle.GLOBAL_DRAW_COLOR[1];
41+
var b = Particle.GLOBAL_DRAW_COLOR[2] * .5/velocity;
42+
var a = Particle.GLOBAL_DRAW_COLOR[3];
43+
pixels[baseIndex] += r;
44+
pixels[baseIndex + 1] += g;
45+
pixels[baseIndex + 2] += b;
46+
pixels[baseIndex + 3] = a;
3947
}
4048

41-
Particle.prototype.drawQuick = function(display) {
42-
display.context.moveTo(this.position.x, this.position.y);
43-
display.context.lineTo(this.position.x+.8, this.position.y+.8);
49+
Particle.prototype.drawBasic = function(pixels,width,height) {
50+
var baseIndex = 4 * (~~this.position.y * width + ~~this.position.x);
51+
var r = Particle.GLOBAL_DRAW_COLOR[0];
52+
var g = Particle.GLOBAL_DRAW_COLOR[1];
53+
var b = Particle.GLOBAL_DRAW_COLOR[2];
54+
var a = Particle.GLOBAL_DRAW_COLOR[3];
55+
pixels[baseIndex] += r;
56+
pixels[baseIndex + 1] += g;
57+
pixels[baseIndex + 2] += b;
58+
pixels[baseIndex + 3] = a;
4459
}
4560

46-
Particle.prototype.draw = Particle.prototype.drawQuick;
61+
Particle.prototype.drawSoft = function(pixels,width,height) {
62+
var baseIndex = 4 * (~~this.position.y * width + ~~this.position.x);
63+
var r = Particle.GLOBAL_DRAW_COLOR[0];
64+
var g = Particle.GLOBAL_DRAW_COLOR[1];
65+
var b = Particle.GLOBAL_DRAW_COLOR[2];
66+
var a = Particle.GLOBAL_DRAW_COLOR[3];
67+
pixels[baseIndex - 4] += r*.80;
68+
pixels[baseIndex - 3] += g*.80;
69+
pixels[baseIndex - 2] += b*.80;
70+
pixels[baseIndex - 1] = a;
71+
pixels[baseIndex] += r*.80;
72+
pixels[baseIndex + 1] += g*.80;
73+
pixels[baseIndex + 2] += b*.80;
74+
pixels[baseIndex + 3] = a;
75+
pixels[baseIndex + 4] += r*.80;
76+
pixels[baseIndex + 5] += g*.80;
77+
pixels[baseIndex + 6] += b*.80;
78+
pixels[baseIndex + 7] = a;
79+
baseIndex += width * 4;
80+
pixels[baseIndex - 4] += r*.80;
81+
pixels[baseIndex - 3] += g*.80;
82+
pixels[baseIndex - 2] += b*.80;
83+
pixels[baseIndex - 1] = a;
84+
pixels[baseIndex] += r;
85+
pixels[baseIndex + 1] += g;
86+
pixels[baseIndex + 2] += b;
87+
pixels[baseIndex + 3] = a;
88+
pixels[baseIndex + 4] += r*.80;
89+
pixels[baseIndex + 5] += g*.80;
90+
pixels[baseIndex + 6] += b*.80;
91+
pixels[baseIndex + 7] = a;
92+
baseIndex += width * 4;
93+
pixels[baseIndex - 4] += r*.80;
94+
pixels[baseIndex - 3] += g*.80;
95+
pixels[baseIndex - 2] += b*.80;
96+
pixels[baseIndex - 1] = a;
97+
pixels[baseIndex] += r*.80;
98+
pixels[baseIndex + 1] += g*.80;
99+
pixels[baseIndex + 2] += b*.80;
100+
pixels[baseIndex + 3] = a;
101+
pixels[baseIndex + 4] += r*.80;
102+
pixels[baseIndex + 5] += g*.80;
103+
pixels[baseIndex + 6] += b*.80;
104+
pixels[baseIndex + 7] = a;
105+
}
106+
107+
Particle.prototype.draw = Particle.prototype.drawBasic;

js/particleSystem/ParticleSystem.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ function ParticleSystem(){
177177
var oldParticles = self.particles;
178178
var fields = self.fields;
179179
var updatedParticles = [];
180-
for(var i = 0, l = oldParticles.length; i < l; i++) {
181-
var particle = oldParticles[i];
180+
var particle;
181+
while(particle = oldParticles.pop()) {
182182
if (particle.ttl > 0) {
183183
if (++particle.lived >= particle.ttl) {
184-
continue;
184+
continue; // particle dies.
185185
}
186186
}
187187
particle.submitToFields(fields);
@@ -197,14 +197,14 @@ function ParticleSystem(){
197197
};
198198

199199
self.drawParticles = function(display) {
200-
display.context.beginPath();
201-
display.strokeStyle(Particle.globalDrawColor);
202-
display.fillStyle(Particle.globalDrawColor);
203-
for( var i = 0, l = self.particles.length; i < l; i++ ){
204-
self.particles[i].draw(display);
205-
}
206-
display.context.stroke();
207-
200+
var imageData = display.context.getImageData(0,0,display.width,display.height);
201+
var pixels = imageData.data;
202+
var width = display.width;
203+
var particle, i = -1;
204+
while(particle = self.particles[++i]){
205+
particle.draw(pixels,display.width,display.height);
206+
}
207+
display.context.putImageData(imageData,0,0);
208208
};
209209

210210
self.drawAccelerations = function(display) {

0 commit comments

Comments
 (0)