/**
* @author Mat Groves
*
* Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
* for creating the original pixi version!
* Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer
*
* Heavily inspired by LibGDX's ParticleBuffer:
* https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleBuffer.java
*/
/**
* The particle buffer manages the static and dynamic buffers for a particle container.
*
* @class
* @private
* @memberof PIXI
*/
function ParticleBuffer(gl, properties, dynamicPropertyFlags, size)
{
/**
* The current WebGL drawing context.
*
* @member {WebGLRenderingContext}
*/
this.gl = gl;
/**
* Size of a single vertex.
*
* @member {number}
*/
this.vertSize = 2;
/**
* Size of a single vertex in bytes.
*
* @member {number}
*/
this.vertByteSize = this.vertSize * 4;
/**
* The number of particles the buffer can hold
*
* @member {number}
*/
this.size = size;
/**
* A list of the properties that are dynamic.
*
* @member {object[]}
*/
this.dynamicProperties = [];
/**
* A list of the properties that are static.
*
* @member {object[]}
*/
this.staticProperties = [];
for (var i = 0; i < properties.length; i++)
{
var property = properties[i];
if(dynamicPropertyFlags[i])
{
this.dynamicProperties.push(property);
}
else
{
this.staticProperties.push(property);
}
}
this.staticStride = 0;
this.staticBuffer = null;
this.staticData = null;
this.dynamicStride = 0;
this.dynamicBuffer = null;
this.dynamicData = null;
this.initBuffers();
}
ParticleBuffer.prototype.constructor = ParticleBuffer;
module.exports = ParticleBuffer;
/**
* Sets up the renderer context and necessary buffers.
*
* @private
*/
ParticleBuffer.prototype.initBuffers = function ()
{
var gl = this.gl;
var i;
var property;
var dynamicOffset = 0;
this.dynamicStride = 0;
for (i = 0; i < this.dynamicProperties.length; i++)
{
property = this.dynamicProperties[i];
property.offset = dynamicOffset;
dynamicOffset += property.size;
this.dynamicStride += property.size;
}
this.dynamicData = new Float32Array( this.size * this.dynamicStride * 4);
this.dynamicBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.dynamicBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.dynamicData, gl.DYNAMIC_DRAW);
// static //
var staticOffset = 0;
this.staticStride = 0;
for (i = 0; i < this.staticProperties.length; i++)
{
property = this.staticProperties[i];
property.offset = staticOffset;
staticOffset += property.size;
this.staticStride += property.size;
}
this.staticData = new Float32Array( this.size * this.staticStride * 4);
this.staticBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.staticBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.staticData, gl.DYNAMIC_DRAW);
};
/**
* Uploads the dynamic properties.
*
*/
ParticleBuffer.prototype.uploadDynamic = function(children, startIndex, amount)
{
var gl = this.gl;
for (var i = 0; i < this.dynamicProperties.length; i++)
{
var property = this.dynamicProperties[i];
property.uploadFunction(children, startIndex, amount, this.dynamicData, this.dynamicStride, property.offset);
}
gl.bindBuffer(gl.ARRAY_BUFFER, this.dynamicBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.dynamicData);
};
/**
* Uploads the static properties.
*
*/
ParticleBuffer.prototype.uploadStatic = function(children, startIndex, amount)
{
var gl = this.gl;
for (var i = 0; i < this.staticProperties.length; i++)
{
var property = this.staticProperties[i];
property.uploadFunction(children, startIndex, amount, this.staticData, this.staticStride, property.offset);
}
gl.bindBuffer(gl.ARRAY_BUFFER, this.staticBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.staticData);
};
/**
* Binds the buffers to the GPU
*
*/
ParticleBuffer.prototype.bind = function ()
{
var gl = this.gl;
var i, property;
gl.bindBuffer(gl.ARRAY_BUFFER, this.dynamicBuffer);
for (i = 0; i < this.dynamicProperties.length; i++)
{
property = this.dynamicProperties[i];
gl.vertexAttribPointer(property.attribute, property.size, gl.FLOAT, false, this.dynamicStride * 4, property.offset * 4);
}
gl.bindBuffer(gl.ARRAY_BUFFER, this.staticBuffer);
for (i = 0; i < this.staticProperties.length; i++)
{
property = this.staticProperties[i];
gl.vertexAttribPointer(property.attribute, property.size, gl.FLOAT, false, this.staticStride * 4, property.offset * 4);
}
};
/**
* Destroys the ParticleBuffer.
*
*/
ParticleBuffer.prototype.destroy = function ()
{
this.dynamicProperties = null;
this.dynamicData = null;
this.gl.deleteBuffer(this.dynamicBuffer);
this.staticProperties = null;
this.staticData = null;
this.gl.deleteBuffer(this.staticBuffer);
};