2016-10-04 14:39:54 +00:00
|
|
|
/**
|
|
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
|
|
* @copyright 2016 Photon Storm Ltd.
|
|
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2016-10-29 20:29:16 +00:00
|
|
|
* Manages the different WebGL Sprite Batches.
|
2016-10-04 14:39:54 +00:00
|
|
|
*
|
|
|
|
* @class Phaser.Renderer.Canvas
|
|
|
|
* @constructor
|
|
|
|
* @param {Phaser.Game} game - Game reference to the currently running game.
|
|
|
|
*/
|
2016-10-24 16:14:10 +00:00
|
|
|
Phaser.Renderer.WebGL.BatchManager = function (renderer, batchSize)
|
2016-10-04 14:39:54 +00:00
|
|
|
{
|
|
|
|
this.renderer = renderer;
|
|
|
|
|
|
|
|
this.gl = null;
|
|
|
|
|
2016-10-29 20:29:16 +00:00
|
|
|
this.currentBatch = null;
|
|
|
|
|
|
|
|
this.imageBatch = new Phaser.Renderer.WebGL.Batch.Image(this, batchSize);
|
|
|
|
|
|
|
|
// this.multiTextureBatch = new Phaser.Renderer.WebGL.Batch.Image(this, batchSize);
|
|
|
|
// this.pixelBatch = null;
|
|
|
|
// this.fxBatch = null;
|
|
|
|
|
|
|
|
// this.currentBatchSize = 0;
|
|
|
|
// this.dirty = true;
|
|
|
|
// this.list = [];
|
|
|
|
|
2016-10-04 14:39:54 +00:00
|
|
|
};
|
|
|
|
|
2016-10-07 01:09:12 +00:00
|
|
|
Phaser.Renderer.WebGL.BatchManager.prototype.constructor = Phaser.Renderer.WebGL.BatchManager;
|
2016-10-04 14:39:54 +00:00
|
|
|
|
2016-10-07 01:09:12 +00:00
|
|
|
Phaser.Renderer.WebGL.BatchManager.prototype = {
|
2016-10-04 14:39:54 +00:00
|
|
|
|
|
|
|
init: function ()
|
|
|
|
{
|
2016-10-30 14:57:38 +00:00
|
|
|
console.log('BatchManager.init');
|
|
|
|
|
2016-10-04 14:39:54 +00:00
|
|
|
this.gl = this.renderer.gl;
|
|
|
|
|
2016-10-29 20:29:16 +00:00
|
|
|
this.imageBatch.init();
|
2016-10-25 15:44:23 +00:00
|
|
|
|
2016-10-29 20:29:16 +00:00
|
|
|
this.currentBatch = this.imageBatch;
|
2016-10-04 14:39:54 +00:00
|
|
|
},
|
|
|
|
|
2016-10-24 16:14:10 +00:00
|
|
|
start: function ()
|
2016-10-04 14:39:54 +00:00
|
|
|
{
|
2016-10-29 20:29:16 +00:00
|
|
|
this.currentBatch.start();
|
2016-10-04 14:39:54 +00:00
|
|
|
},
|
|
|
|
|
2016-10-18 16:03:25 +00:00
|
|
|
stop: function ()
|
|
|
|
{
|
2016-10-29 20:29:16 +00:00
|
|
|
this.currentBatch.stop();
|
2016-10-04 14:39:54 +00:00
|
|
|
},
|
|
|
|
|
2016-10-29 20:29:16 +00:00
|
|
|
add: function (batch, source)
|
2016-10-19 10:54:00 +00:00
|
|
|
{
|
2016-10-29 20:29:16 +00:00
|
|
|
// Check Batch Size and flush if needed, OR if a different batch then swap
|
2016-10-30 14:57:38 +00:00
|
|
|
// Also what about blend mode or shader swaps?
|
|
|
|
if (this.currentBatch.size >= this.currentBatch.maxSize)
|
2016-10-24 16:14:10 +00:00
|
|
|
{
|
2016-10-30 14:57:38 +00:00
|
|
|
this.currentBatch.flush();
|
2016-10-24 16:14:10 +00:00
|
|
|
}
|
|
|
|
|
2016-10-30 14:57:38 +00:00
|
|
|
if (source)
|
2016-10-25 00:40:16 +00:00
|
|
|
{
|
2016-10-30 14:57:38 +00:00
|
|
|
source.glLastUsed = this.renderer.startTime;
|
|
|
|
|
|
|
|
// Does this TextureSource need updating?
|
|
|
|
if (source.glDirty)
|
|
|
|
{
|
|
|
|
this.renderer.updateTexture(source);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Does the batch need to activate a new texture?
|
|
|
|
if (this.renderer.textureArray[source.glTextureIndex] !== source)
|
|
|
|
{
|
|
|
|
this.setCurrentTexture(source);
|
|
|
|
}
|
2016-10-25 00:40:16 +00:00
|
|
|
}
|
|
|
|
|
2016-10-30 14:57:38 +00:00
|
|
|
// Swap Batch check
|
|
|
|
|
|
|
|
// At this point the game object should call 'add' on the batch it needs (ImageBatch, FXBatch, etc)
|
2016-10-24 16:14:10 +00:00
|
|
|
|
|
|
|
},
|
|
|
|
|
2016-10-30 14:57:38 +00:00
|
|
|
__flush: function ()
|
2016-10-24 16:14:10 +00:00
|
|
|
{
|
2016-10-28 01:42:58 +00:00
|
|
|
var gl = this.gl;
|
|
|
|
|
2016-10-24 16:14:10 +00:00
|
|
|
// Always dirty the first pass through but subsequent calls may be clean
|
|
|
|
if (this.dirty)
|
|
|
|
{
|
2016-10-28 01:42:58 +00:00
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
|
|
|
|
2016-10-24 23:41:45 +00:00
|
|
|
this.initShader();
|
2016-10-04 14:39:54 +00:00
|
|
|
}
|
|
|
|
|
2016-10-25 02:57:34 +00:00
|
|
|
// Upload the vertex data to the GPU - is this cheaper (overall) than creating a new TypedArray view?
|
2016-10-29 12:38:57 +00:00
|
|
|
// The tradeoff is sending 224KB of data to the GPU every frame, even if most of it is empty should the
|
|
|
|
// batch be only slightly populated, vs. the creation of a new TypedArray view and its corresponding gc every frame.
|
|
|
|
|
2016-10-25 02:57:34 +00:00
|
|
|
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices);
|
|
|
|
|
|
|
|
/*
|
2016-10-18 23:23:40 +00:00
|
|
|
if (this.currentBatchSize > this.halfBatchSize)
|
2016-10-04 14:39:54 +00:00
|
|
|
{
|
|
|
|
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
2016-10-18 16:03:25 +00:00
|
|
|
|
2016-10-24 16:14:10 +00:00
|
|
|
// This creates a brand new Typed Array - what's the cost of this vs. just uploading all vert data?
|
2016-10-19 00:56:31 +00:00
|
|
|
var view = this.positions.subarray(0, this.currentBatchSize * this.vertSize);
|
2016-10-18 16:03:25 +00:00
|
|
|
|
2016-10-04 14:39:54 +00:00
|
|
|
gl.bufferSubData(gl.ARRAY_BUFFER, 0, view);
|
|
|
|
}
|
2016-10-25 02:57:34 +00:00
|
|
|
*/
|
2016-10-04 14:39:54 +00:00
|
|
|
|
2016-10-18 16:03:25 +00:00
|
|
|
var sprite;
|
|
|
|
|
2016-10-04 14:39:54 +00:00
|
|
|
var start = 0;
|
2016-10-18 16:03:25 +00:00
|
|
|
var currentSize = 0;
|
2016-10-04 14:39:54 +00:00
|
|
|
|
2016-10-29 12:38:57 +00:00
|
|
|
// Rather than keep the sprites in a list, we can simply flush and switch when
|
|
|
|
// we encounter a new one in the add method, then we don't need to track any offsets?
|
2016-10-18 16:03:25 +00:00
|
|
|
for (var i = 0; i < this.currentBatchSize; i++)
|
2016-10-04 14:39:54 +00:00
|
|
|
{
|
2016-10-24 16:14:10 +00:00
|
|
|
sprite = this.list[i];
|
2016-10-04 14:39:54 +00:00
|
|
|
|
2016-10-24 16:14:10 +00:00
|
|
|
if (sprite.blendMode !== this.renderer.currentBlendMode)
|
2016-10-04 14:39:54 +00:00
|
|
|
{
|
2016-10-25 02:57:34 +00:00
|
|
|
if (currentSize > 0)
|
|
|
|
{
|
|
|
|
gl.drawElements(gl.TRIANGLES, currentSize * 6, gl.UNSIGNED_SHORT, start * 6 * 2);
|
|
|
|
this.renderer.drawCount++;
|
2016-10-27 14:14:22 +00:00
|
|
|
|
|
|
|
// Reset the batch
|
|
|
|
start = i;
|
|
|
|
currentSize = 0;
|
2016-10-25 02:57:34 +00:00
|
|
|
}
|
|
|
|
|
2016-10-24 16:14:10 +00:00
|
|
|
this.renderer.setBlendMode(sprite.blendMode);
|
2016-10-18 16:03:25 +00:00
|
|
|
}
|
2016-10-04 14:39:54 +00:00
|
|
|
|
2016-10-28 01:42:58 +00:00
|
|
|
if (sprite.shader === 2)
|
|
|
|
{
|
|
|
|
gl.drawElements(gl.TRIANGLES, currentSize * 6, gl.UNSIGNED_SHORT, start * 6 * 2);
|
|
|
|
this.renderer.drawCount++;
|
|
|
|
|
|
|
|
// Reset the batch
|
|
|
|
start = i;
|
|
|
|
currentSize = 0;
|
|
|
|
|
|
|
|
this.initAttributes(this.program2);
|
|
|
|
this.initShader();
|
|
|
|
}
|
|
|
|
else if (sprite.shader === 1)
|
|
|
|
{
|
|
|
|
gl.drawElements(gl.TRIANGLES, currentSize * 6, gl.UNSIGNED_SHORT, start * 6 * 2);
|
|
|
|
this.renderer.drawCount++;
|
|
|
|
|
|
|
|
// Reset the batch
|
|
|
|
start = i;
|
|
|
|
currentSize = 0;
|
|
|
|
|
|
|
|
this.initAttributes(this.program);
|
|
|
|
this.initShader();
|
|
|
|
}
|
|
|
|
|
2016-10-25 02:57:34 +00:00
|
|
|
// TODO: Check for shader here
|
|
|
|
|
|
|
|
// If either blend or shader set, we need to drawElements and swap
|
|
|
|
|
2016-10-18 16:03:25 +00:00
|
|
|
currentSize++;
|
2016-10-04 14:39:54 +00:00
|
|
|
}
|
|
|
|
|
2016-10-18 16:03:25 +00:00
|
|
|
if (currentSize > 0)
|
|
|
|
{
|
2016-10-24 16:14:10 +00:00
|
|
|
gl.drawElements(gl.TRIANGLES, currentSize * 6, gl.UNSIGNED_SHORT, start * 6 * 2);
|
|
|
|
this.renderer.drawCount++;
|
2016-10-18 16:03:25 +00:00
|
|
|
}
|
2016-10-04 14:39:54 +00:00
|
|
|
|
2016-10-18 16:03:25 +00:00
|
|
|
// Reset the batch
|
2016-10-04 14:39:54 +00:00
|
|
|
this.currentBatchSize = 0;
|
2016-10-25 00:40:16 +00:00
|
|
|
this._i = 0;
|
2016-10-27 14:14:22 +00:00
|
|
|
|
2016-10-04 14:39:54 +00:00
|
|
|
},
|
|
|
|
|
2016-10-29 20:29:16 +00:00
|
|
|
setCurrentTexture: function (source)
|
2016-10-04 14:39:54 +00:00
|
|
|
{
|
2016-10-29 20:29:16 +00:00
|
|
|
var gl = this.gl;
|
|
|
|
|
|
|
|
this.currentBatch.flush();
|
|
|
|
|
|
|
|
gl.activeTexture(gl.TEXTURE0 + source.glTextureIndex);
|
|
|
|
|
|
|
|
gl.bindTexture(gl.TEXTURE_2D, source.glTexture);
|
|
|
|
|
|
|
|
this.renderer.textureArray[source.glTextureIndex] = source;
|
|
|
|
},
|
2016-10-04 14:39:54 +00:00
|
|
|
|
2016-10-29 20:29:16 +00:00
|
|
|
destroy: function ()
|
|
|
|
{
|
|
|
|
this.imageBatch.destroy();
|
2016-10-04 14:39:54 +00:00
|
|
|
|
|
|
|
this.renderer = null;
|
|
|
|
this.gl = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|