Skip to content

Commit 01ff226

Browse files
committed
Particle Renderer
1 parent e0ffba2 commit 01ff226

2 files changed

Lines changed: 216 additions & 0 deletions

File tree

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
var BindVertexArray = require('../utils/BindVertexArray');
2+
var CreateProgram = require('../utils/CreateProgram');
3+
var CreateShader = require('../utils/CreateShader');
4+
var CreateBuffer = require('../utils/CreateBuffer');
5+
var CreateAttribDesc = require('../utils/CreateAttribDesc');
6+
var VertexBuffer = require('../utils/VertexBuffer');
7+
var IndexBuffer = require('../utils/IndexBuffer');
8+
var VertexArray = require('../utils/VertexArray');
9+
var CONST = require('../../const');
10+
11+
var ParticleRenderer = function ()
12+
{
13+
this.glContext = null;
14+
this.maxParticles = null;
15+
this.vertShader = null;
16+
this.fragShader = null;
17+
this.program = null;
18+
this.vertexArray = null;
19+
this.indexBufferObject = null;
20+
this.vertexDataBuffer = null;
21+
this.indexDataBuffer = null;
22+
this.elementCount = 0;
23+
this.currentTexture2D = null;
24+
this.viewMatrixLocation = null;
25+
this.type = CONST.WEBGL;
26+
this.view = game.canvas;
27+
this.resolution = game.config.resolution;
28+
this.init();
29+
};
30+
31+
// VERTEX_SIZE = sizeof(vec2) + sizeof(vec2)
32+
ParticleRenderer.VERTEX_SIZE = 16;
33+
ParticleRenderer.INDEX_SIZE = 2;
34+
ParticleRenderer.PARTICLE_VERTEX_COUNT = 4;
35+
ParticleRenderer.PARTICLE_INDEX_COUNT = 6;
36+
37+
// How many 32-bit components does the vertex have.
38+
ParticleRenderer.PARTICLE_VERTEX_COMPONENT_COUNT = 4;
39+
40+
// Can't be bigger since index are 16-bit
41+
ParticleRenderer.MAX_PARTICLES = 10000;
42+
ParticleRenderer.VERTEX_SHADER_SOURCE = [
43+
'uniform mat4 u_view_matrix;',
44+
'attribute vec2 a_position;',
45+
'attribute vec2 a_tex_coord;',
46+
'varying vec2 v_tex_coord;',
47+
'void main () {',
48+
' gl_Position = u_view_matrix * vec4(a_position, 1.0, 1.0);',
49+
' v_tex_coord = a_tex_coord;',
50+
'}'
51+
].join('\n');
52+
ParticleRenderer.FRAGMENT_SHADER_SOURCE = [
53+
'precision lowp float;',
54+
'uniform sampler2D u_sampler2D;',
55+
'varying vec2 v_tex_coord;',
56+
'void main() {',
57+
' gl_FragColor = texture2D(u_sampler2D, v_tex_coord);',
58+
'}'
59+
].join('\n');
60+
61+
ParticleRenderer.prototype.init = function ()
62+
{
63+
if (this.glContext === null)
64+
{
65+
var gl = this.view.getContext('webgl', this.config.WebGLContextOptions) || this.view.getContext('experimental-webgl', this.config.WebGLContextOptions);
66+
var vertexDataBuffer = new VertexBuffer(ParticleRenderer.VERTEX_SIZE * ParticleRenderer.PARTICLE_VERTEX_COUNT * ParticleRenderer.MAX_PARTICLES);
67+
var indexDataBuffer = new IndexBuffer(ParticleRenderer.INDEX_SIZE * ParticleRenderer.PARTICLE_INDEX_COUNT * ParticleRenderer.MAX_PARTICLES);
68+
var vertShader = CreateShader(gl, ParticleRenderer.VERTEX_SHADER_SOURCE, gl.VERTEX_SHADER);
69+
var fragShader = CreateShader(gl, ParticleRenderer.FRAGMENT_SHADER_SOURCE, gl.FRAGMENT_SHADER_SOURCE);
70+
var program = CreateProgram(gl, vertShader, fragShader);
71+
var indexBufferObject = CreateBuffer(gl, gl.ELEMENT_ARRAY_BUFFER, gl.STATIC_DRAW, null, indexDataBuffer.getByteCapacity());
72+
var vertexArray = new VertexArray(gl,
73+
CreateBuffer(gl, gl.ARRAY_BUFFER, gl.STREAM_DRAW, null, vertexDataBuffer.getByteCapacity()),
74+
[
75+
CreateAttributeDesc(gl, program, 'a_position', 2, gl.FLOAT, false, ParticleRendererRenderer.VERTEX_SIZE, 0),
76+
CreateAttributeDesc(gl, program, 'a_tex_coord', 2, gl.FLOAT, false, ParticleRendererRenderer.VERTEX_SIZE, 8)
77+
]
78+
);
79+
var viewMatrixLocation = gl.getUniformLocation(program, 'u_view_matrix');
80+
var view = this.view;
81+
this.vertexDataBuffer = vertexDataBuffer;
82+
this.indexDataBuffer = indexDataBuffer;
83+
this.vertShader = vertShader;
84+
this.fragShader = fragShader;
85+
this.program = program;
86+
this.indexBufferObject = indexBufferObject;
87+
this.vertexArray = vertexArray;
88+
this.glContext = gl;
89+
gl.uniformMatrix4fv(
90+
viewMatrixLocation,
91+
false,
92+
new Float32Array([
93+
2 / view.width, 0, 0, 0,
94+
0, -2 / view.height, 0, 0,
95+
0, 0, 1, 1,
96+
-1, 1, 0, 0
97+
])
98+
);
99+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBufferObject);
100+
var indexBuffer = indexDataBuffer.wordView;
101+
for (var indexA = indexB = 0;
102+
indexA < ParticleRenderer.MAX_PARTICLES * ParticleRenderer.PARTICLE_INDEX_COUNT;
103+
indexA += ParticleRenderer.PARTICLE_INDEX_COUNT, indexB += ParticleRenderer.PARTICLE_VERTEX_COUNT)
104+
{
105+
indexBuffer[indexA + 0] = indexB + 0;
106+
indexBuffer[indexA + 1] = indexB + 1;
107+
indexBuffer[indexA + 2] = indexB + 2;
108+
indexBuffer[indexA + 3] = indexB + 0;
109+
indexBuffer[indexA + 4] = indexB + 2;
110+
indexBuffer[indexA + 5] = indexB + 3;
111+
}
112+
}
113+
else
114+
{
115+
console.error('ParticleRenderer already initialized');
116+
}
117+
};
118+
119+
ParticleRenderer.prototype.destroy = function ()
120+
{
121+
var gl = this.glContext;
122+
if (gl)
123+
{
124+
gl.deleteShader(this.vertShader);
125+
gl.deleteShader(this.fragShader);
126+
gl.deleteProgram(this.program);
127+
gl.deleteBuffer(this.indexBufferObject);
128+
gl.deleteBuffer(this.vertexArray.buffer);
129+
}
130+
};
131+
132+
ParticleRenderer.prototype.isFull = function ()
133+
{
134+
var vertexDataBuffer = this.vertexDataBuffer;
135+
return (vertexDataBuffer.getByteLength() >= vertexDataBuffer.getByteCapacity());
136+
};
137+
138+
ParticleRenderer.prototype.add = function (x, y, width, height, umin, vmin, umax, vmax)
139+
{
140+
// The user must check if the buffers are full before flushing
141+
// this is to give freedom of when should the renderer flush.
142+
var vertexDataBuffer = this.vertexDataBuffer;
143+
var indexDataBuffer = this.indexDataBuffer;
144+
var vertexBuffer = vertexDataBuffer.floatView;
145+
var vertexOffset = vertexDataBuffer.allocate(ParticleRenderer.PARTICLE_VERTEX_COMPONENT_COUNT * ParticleRenderer.PARTICLE_VERTEX_COUNT);
146+
147+
vertexBuffer[vertexOffset++] = x;
148+
vertexBuffer[vertexOffset++] = y;
149+
vertexBuffer[vertexOffset++] = umin;
150+
vertexBuffer[vertexOffset++] = vmin;
151+
152+
vertexBuffer[vertexOffset++] = x;
153+
vertexBuffer[vertexOffset++] = y + height;
154+
vertexBuffer[vertexOffset++] = umin;
155+
vertexBuffer[vertexOffset++] = vmax;
156+
157+
vertexBuffer[vertexOffset++] = x + width;
158+
vertexBuffer[vertexOffset++] = y + height;
159+
vertexBuffer[vertexOffset++] = umax;
160+
vertexBuffer[vertexOffset++] = vmax;
161+
162+
vertexBuffer[vertexOffset++] = x + width;
163+
vertexBuffer[vertexOffset++] = y;
164+
vertexBuffer[vertexOffset++] = umax;
165+
vertexBuffer[vertexOffset++] = vmin;
166+
167+
this.elementCount += ParticleRenderer.PARTICLE_INDEX_COUNT;
168+
};
169+
170+
ParticleRenderer.prototype.setTexture2D = function (texture2D)
171+
{
172+
var gl = this.glContext;
173+
if (this.currentTexture2D != texture2D)
174+
{
175+
this.flush();
176+
gl.activeTexture(gl.TEXTURE0);
177+
gl.bindTexture(gl.TEXTURE_2D, texture2D);
178+
}
179+
};
180+
181+
ParticleRenderer.prototype.bind = function ()
182+
{
183+
var gl = this.glContext;
184+
gl.clearColor(0, 0, 0, 1);
185+
gl.enable(gl.BLEND);
186+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
187+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBufferObject);
188+
BindVertexArray(this.vertexArray);
189+
};
190+
191+
ParticleRenderer.prototype.unbind = function ()
192+
{
193+
var gl = this.glContext;
194+
gl.disable(gl.BLEND);
195+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
196+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
197+
};
198+
199+
ParticleRenderer.prototype.flush = function ()
200+
{
201+
var gl = this.glContext;
202+
var vertexDataBuffer = this.vertexDataBuffer;
203+
gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertexDataBuffer.getUsedBufferAsFloat());
204+
gl.drawElements(gl.TRIANGLES, this.elementCount, gl.UNSIGNED_SHORT, 0);
205+
vertexDataBuffer.clear();
206+
this.elementCount = 0;
207+
};
208+
209+
ParticleRenderer.prototype.resize = function (width, height)
210+
{};
211+
212+
module.exports = ParticleRenderer;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
var SpriteRenderer = function ()
2+
{};
3+
4+
module.exports = SpriteRenderer;

0 commit comments

Comments
 (0)