BlitterBatch pipeline working

This commit is contained in:
Felipe Alfonso 2018-01-10 17:03:01 -03:00
parent 15c45bda0e
commit 54274b782a
22 changed files with 238 additions and 435 deletions

View file

@ -1,82 +1,13 @@
var GameObject = require('../GameObject');
var BlitterWebGLRenderer = function (renderer, src, interpolationPercentage, camera)
var BlitterWebGLRenderer = function (renderer, gameObject, interpolationPercentage, camera)
{
if (GameObject.RENDER_MASK !== src.renderFlags || (src.cameraFilter > 0 && (src.cameraFilter & camera._id)))
if (GameObject.RENDER_MASK !== gameObject.renderFlags || (gameObject.cameraFilter > 0 && (gameObject.cameraFilter & camera._id)))
{
return;
}
var list = src.getRenderList();
var blitterBatch = renderer.blitterBatch;
var cameraMatrix = camera.matrix.matrix;
var a = cameraMatrix[0];
var b = cameraMatrix[1];
var c = cameraMatrix[2];
var d = cameraMatrix[3];
var e = cameraMatrix[4];
var f = cameraMatrix[5];
var cameraScrollX = camera.scrollX * src.scrollFactorX;
var cameraScrollY = camera.scrollY * src.scrollFactorY;
var renderTarget = src.renderTarget;
// Render bobs
for (var i = 0, l = list.length; i < l; i++)
{
var bob = list[i];
var frame = bob.frame;
var alpha = bob.alpha;
var vertexDataBuffer = blitterBatch.vertexDataBuffer;
var vertexBuffer = vertexDataBuffer.floatView;
var vertexOffset = 0;
var uvs = frame.uvs;
var width = frame.width * (bob.flipX ? -1 : 1);
var height = frame.height * (bob.flipY ? -1 : 1);
var x = bob.x + frame.x - cameraScrollX + ((frame.width) * (bob.flipX ? 1 : 0.0));
var y = bob.y + frame.y - cameraScrollY + ((frame.height) * (bob.flipY ? 1 : 0.0));
var xw = x + width;
var yh = y + height;
var tx = x * a + y * c + e;
var ty = x * b + y * d + f;
var txw = xw * a + yh * c + e;
var tyh = xw * b + yh * d + f;
if (blitterBatch.elementCount >= blitterBatch.maxParticles)
{
blitterBatch.flush();
}
renderer.setRenderer(blitterBatch, frame.texture.source[frame.sourceIndex].glTexture, camera, renderTarget);
vertexOffset = vertexDataBuffer.allocate(20);
blitterBatch.elementCount += 6;
x += frame.x;
y += frame.y;
vertexBuffer[vertexOffset++] = tx;
vertexBuffer[vertexOffset++] = ty;
vertexBuffer[vertexOffset++] = uvs.x0;
vertexBuffer[vertexOffset++] = uvs.y0;
vertexBuffer[vertexOffset++] = alpha;
vertexBuffer[vertexOffset++] = tx;
vertexBuffer[vertexOffset++] = tyh;
vertexBuffer[vertexOffset++] = uvs.x1;
vertexBuffer[vertexOffset++] = uvs.y1;
vertexBuffer[vertexOffset++] = alpha;
vertexBuffer[vertexOffset++] = txw;
vertexBuffer[vertexOffset++] = tyh;
vertexBuffer[vertexOffset++] = uvs.x2;
vertexBuffer[vertexOffset++] = uvs.y2;
vertexBuffer[vertexOffset++] = alpha;
vertexBuffer[vertexOffset++] = txw;
vertexBuffer[vertexOffset++] = ty;
vertexBuffer[vertexOffset++] = uvs.x3;
vertexBuffer[vertexOffset++] = uvs.y3;
vertexBuffer[vertexOffset++] = alpha;
}
renderer.blitterBatch.drawBlitter(gameObject, camera)
};
module.exports = BlitterWebGLRenderer;

View file

@ -1,7 +1,7 @@
var Class = require('../../../utils/Class');
var GameObject = require('../../GameObject');
var Components = require('../../components');
var CONST = require('../../../renderer/webgl/renderers/tilemaprenderer/const');
var CONST = require('../../../renderer/webgl/pipelines/tilemaprenderer/const');
var StaticTilemapLayerRender = require('./StaticTilemapLayerRender');
var TilemapComponents = require('../components');

View file

@ -1,124 +1,163 @@
var Class = require('../../../utils/Class');
var Class = require('../../utils/Class');
var Pipeline = new Class({
initialize:
initialize:
function Pipeline(config)
{
function Pipeline(config)
{
this.name = config.name;
this.game = config.game;
this.view = config.game.canvas;
this.resolution = config.game.config.resolution;
this.width = config.game.config.width * this.resolution;
this.height = config.game.config.height * this.resolution;
this.gl = config.gl;
this.vertexCount = 0;
this.vertexCapacity = config.vertexCapacity;
this.manager = config.manager;
this.resources = config.manager.resourceManager;
this.vertexData = new ArrayBuffer(config.vertexCapacity * config.vertexSize);
this.vertexBuffer = null;
this.program = null;
this.vertexLayout = config.vertexLayout;
this.vertexSize = config.vertexSize;
this.currentRenderTarget = null;
this.currentProgram = null;
this.topology = config.topology;
this.onBeginPassTarget = config.onBeginPassTarget || null;
this.onEndPassTarget = config.onBeginPassTarget || null;
this.onFlushTarget = config.onFlushTarget || null;
this.onBindTarget = config.onBindTarget || null;
this.onResizeTarget = config.onResizeTarget || null;
this.onBeginPass = config.onBeginPass || function onBeginPassStub(pipeline) {};
this.onEndPass = config.onEndPass || function onEndPassStub(pipeline) {};
this.onFlush = config.onFlush || function onFlushStub(pipeline) {};
this.onBind = config.onBind || function onBindStub(pipeline) {};
this.onResize = config.onResize || function onResize(width, height, resolution) {};
// Initialize Shaders and Buffers
{
var gl = this.gl;
var resources = this.resources;
var vertexSize = this.vertexSize;
var vertexLayout = this.vertexLayout;
var program = resources.createShader(this.name, config.shader);
var vertexBuffer = resources.createBuffer(gl.ARRAY_BUFFER, this.vertexData.byteLength, gl.STREAM_DRAW);
this.name = config.name;
this.game = config.game;
this.view = config.game.canvas;
this.resolution = config.game.config.resolution;
this.width = config.game.config.width * this.resolution;
this.height = config.game.config.height * this.resolution;
this.glContext = config.gl;
this.vertexCount = 0;
this.vertexCapacity = config.vertexCapacity;
this.manager = config.manager;
this.resources = config.manager.resourceManager;
this.vertexData = new ArrayBuffer(config.vertexCapacity * config.vertexSize);
this.vertexBuffer = null;
this.program = null;
this.vertexLayout = config.vertexLayout;
this.vertexSize = config.vertexSize;
this.currentRenderTarget = null;
this.currentProgram = null;
this.topology = config.topology;
// Initialize Shaders and Buffers
{
var gl = this.glContext;
var resources = this.resources;
var vertexSize = this.vertexSize;
var vertexLayout = this.vertexLayout;
var program = resources.createShader(this.name, config.shader);
var vertexBuffer = resources.createBuffer(gl.ARRAY_BUFFER, this.vertexCapacity, gl.STREAM_DRAW);
for (var key in vertexLayout)
{
var element = vertexLayout[key];
for (var key in vertexLayout)
{
var element = vertexLayout[key];
vertexBuffer.addAttribute(
program.getAttribLocation(key),
element.size,
element.type,
element.normalize,
vertexSize,
element.offset
);
}
vertexBuffer.addAttribute(
program.getAttribLocation(key),
element.size,
element.type,
element.normalize,
vertexSize,
element.offset
);
}
this.vertexBuffer = vertexBuffer;
this.program = program;
}
},
this.vertexBuffer = vertexBuffer;
this.program = program;
}
},
shouldFlush: function ()
{
return this.vertexCount >= this.vertexCapacity;
},
beginDraw: function (renderTarget, program)
{
if (this.currentRenderTarget !== null ||
this.currentProgram !== null)
{
this.draw();
this.endDraw();
}
bind: function ()
{
this.onBind.call(this.onBindTarget, this);
return this;
},
this.currentRenderTarget = (renderTarget || null);
this.currentProgram = (program || this.program);
this.currentProgram.bind();
this.vertexBuffer.bind();
resize: function (width, height, resolution)
{
this.onResize.call(this.onResizeTarget, width, height, resolution);
return this;
},
gl.bindFramebuffer(gl.FRAMEBUFFER, this.currentRenderTarget.framebufferObject);
beginPass: function (renderTarget, program)
{
if (this.currentRenderTarget !== null ||
this.currentProgram !== null)
{
this.flush();
this.endPass();
}
return this;
},
this.currentRenderTarget = (renderTarget || null);
this.currentProgram = (program || this.program);
this.currentProgram.bind();
this.vertexBuffer.bind();
draw: function ()
{
var gl = this.glContext;
var vertexCount = this.vertexCount;
var vertexBuffer = this.vertexBuffer;
var vertexData = this.vertexData;
var topology = this.topology;
if (this.currentRenderTarget !== null)
{
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.currentRenderTarget.framebufferObject);
}
else
{
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
}
if (vertexCount === 0) return;
this.onBeginPass.call(this.onBeginPassTarget, this);
vertexBuffer.updateResource(vertexData, 0);
gl.drawArrays(topology, 0, vertexCount);
return this;
},
this.vertexCount = 0;
flush: function ()
{
var gl = this.gl;
var vertexCount = this.vertexCount;
var vertexBuffer = this.vertexBuffer;
var vertexData = this.vertexData;
var topology = this.topology;
return this;
},
if (vertexCount === 0) return;
endDraw: function ()
{
var renderTarget = this.currentRenderTarget;
var program = this.currentProgram;
vertexBuffer.updateResource(vertexData, 0);
gl.drawArrays(topology, 0, vertexCount);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
this.vertexCount = 0;
this.currentRenderTarget = null;
this.program = null;
this.vertexCount = 0;
this.onFlush.call(this.onFlushTarget, this);
return this;
},
return this;
},
destroy: function ()
{
var resources = this.resources;
endPass: function ()
{
var renderTarget = this.currentRenderTarget;
var program = this.currentProgram;
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
this.currentRenderTarget = null;
this.currentProgram = null;
this.vertexCount = 0;
this.onEndPass.call(this.onEndPassTarget, this);
return this;
},
destroy: function ()
{
var resources = this.resources;
resources.deleteShader(this.program);
resources.deleteBuffer(this.vertexBuffer);
resources.deleteBuffer(this.vertexBuffer);
this.program = null;
this.vertexBuffer = null;
this.program = null;
this.vertexBuffer = null;
return this;
}
return this;
}
});
module.exports = BaseRenderer;
module.exports = Pipeline;

View file

@ -6,28 +6,28 @@
*/
var BlendModes = require('../BlendModes');
var BlitterBatch = require('./renderers/blitterbatch/BlitterBatch');
var BlitterBatch = require('./pipelines/blitterbatch/BlitterBatch');
var Class = require('../../utils/Class');
var CONST = require('../../const');
var EffectRenderer = require('./renderers/effectrenderer/EffectRenderer');
var EffectRenderer = require('./pipelines/effectrenderer/EffectRenderer');
var IsSizePowerOfTwo = require('../../math/pow2/IsSizePowerOfTwo');
var MaskRenderer = require('./renderers/maskrenderer/MaskRenderer');
var QuadBatch = require('./renderers/quadbatch/QuadBatch');
var ParticleRenderer = require('./renderers/particlerenderer/ParticleRenderer');
var MaskRenderer = require('./pipelines/maskrenderer/MaskRenderer');
var QuadBatch = require('./pipelines/quadbatch/QuadBatch');
var ParticleRenderer = require('./pipelines/particlerenderer/ParticleRenderer');
var ResourceManager = require('./ResourceManager');
var Resources = require('./resources');
var ScaleModes = require('../ScaleModes');
var ShapeBatch = require('./renderers/shapebatch/ShapeBatch');
var SpriteBatch = require('./renderers/spritebatch/SpriteBatch');
var TileBatch = require('./renderers/tilebatch/TileBatch');
var TilemapRenderer = require('./renderers/tilemaprenderer/TilemapRenderer');
var ShapeBatch = require('./pipelines/shapebatch/ShapeBatch');
var SpriteBatch = require('./pipelines/spritebatch/SpriteBatch');
var TileBatch = require('./pipelines/tilebatch/TileBatch');
var TilemapRenderer = require('./pipelines/tilemaprenderer/TilemapRenderer');
var WebGLSnapshot = require('../snapshot/WebGLSnapshot');
var WebGLRenderer = new Class({
var WebGLpipeline = new Class({
initialize:
function WebGLRenderer (game)
function WebGLpipeline (game)
{
var _this = this;
this.game = game;
@ -40,10 +40,10 @@ var WebGLRenderer = new Class({
this.view = game.canvas;
this.view.addEventListener('webglcontextlost', function (evt) {
var callbacks = _this.onContextLostCallbacks;
var renderers = _this.rendererArray;
for (var index = 0; index < renderers.length; ++index)
var pipelines = _this.pipelines;
for (var index = 0; index < pipelines.length; ++index)
{
renderers[index].destroy();
pipelines[index].destroy();
}
_this.contextLost = true;
for (var index = 0; index < callbacks.length; ++index)
@ -55,7 +55,7 @@ var WebGLRenderer = new Class({
this.view.addEventListener('webglcontextrestored', function (evt) {
var callbacks = _this.onContextRestoredCallbacks;
_this.rendererArray.length = 0;
_this.pipelines.length = 0;
_this.resourceManager.shaderCache = {};
_this.resourceManager.shaderCount = 0;
_this.contextLost = false;
@ -95,14 +95,14 @@ var WebGLRenderer = new Class({
this.gl = null;
this.extensions = null;
this.extensionList = {};
this.rendererArray = [];
this.pipelines = [];
this.blitterBatch = null;
this.aaQuadBatch = null;
this.spriteBatch = null;
this.shapeBatch = null;
this.effectRenderer = null;
this.maskRenderer = null;
this.currentRenderer = null;
this.EffectRenderer = null;
this.MaskRenderer = null;
this.currentPipeline = null;
this.currentTexture = [];
this.shaderCache = {};
this.currentShader = null;
@ -130,7 +130,7 @@ var WebGLRenderer = new Class({
if (!this.gl)
{
this.contextLost = true;
throw new Error('This browser does not support WebGL. Try using the Canvas renderer.');
throw new Error('This browser does not support WebGL. Try using the Canvas pipeline.');
}
var gl = this.gl;
@ -164,16 +164,16 @@ var WebGLRenderer = new Class({
this.blendMode = -1;
this.extensions = gl.getSupportedExtensions();
this.blitterBatch = this.addRenderer(new BlitterBatch(this.game, gl, this));
this.quadBatch = this.addRenderer(new QuadBatch(this.game, gl, this));
this.spriteBatch = this.addRenderer(new SpriteBatch(this.game, gl, this));
this.shapeBatch = this.addRenderer(new ShapeBatch(this.game, gl, this));
this.effectRenderer = this.addRenderer(new EffectRenderer(this.game, gl, this));
this.tileBatch = this.addRenderer(new TileBatch(this.game, gl, this));
this.tilemapRenderer = this.addRenderer(new TilemapRenderer(this.game, gl, this));
this.particleRenderer = this.addRenderer(new ParticleRenderer(this.game, gl, this));
this.maskRenderer = this.addRenderer(new MaskRenderer(this.game, gl, this));
this.currentRenderer = this.spriteBatch;
this.blitterBatch = this.addPipeline(new BlitterBatch(this.game, gl, this));
//this.quadBatch = this.addPipeline(new QuadBatch(this.game, gl, this));
//this.spriteBatch = this.addPipeline(new SpriteBatch(this.game, gl, this));
//this.shapeBatch = this.addPipeline(new ShapeBatch(this.game, gl, this));
//this.EffectRenderer = this.addPipeline(new EffectRenderer(this.game, gl, this));
//this.tileBatch = this.addPipeline(new TileBatch(this.game, gl, this));
//this.TilemapRenderer = this.addPipeline(new TilemapRenderer(this.game, gl, this));
//this.ParticleRenderer = this.addPipeline(new ParticleRenderer(this.game, gl, this));
//this.MaskRenderer = this.addPipeline(new MaskRenderer(this.game, gl, this));
this.currentPipeline = this.blitterBatch;
this.currentVertexBuffer = null;
this.setBlendMode(0);
this.resize(this.width, this.height);
@ -298,7 +298,8 @@ var WebGLRenderer = new Class({
{
var gl = this.gl;
this.currentRenderer.flush();
this.currentPipeline.flush();
this.currentPipeline.endPass();
gl.activeTexture(gl.TEXTURE0 + unit);
@ -315,15 +316,14 @@ var WebGLRenderer = new Class({
}
},
setRenderer: function (renderer, texture, renderTarget)
setPipeline: function (pipeline)
{
this.setTexture(texture);
this.setRenderTarget(renderTarget);
if (this.currentRenderer !== renderer || this.currentRenderer.shouldFlush())
if (this.currentPipeline !== pipeline ||
this.currentPipeline.shouldFlush())
{
this.currentRenderer.flush();
this.currentRenderer = renderer;
this.currentPipeline.flush();
this.currentPipeline.endPass();
this.currentPipeline = pipeline;
}
},
@ -333,7 +333,7 @@ var WebGLRenderer = new Class({
if (this.currentRenderTarget !== renderTarget)
{
this.currentRenderer.flush();
this.currentPipeline.flush();
if (renderTarget !== null)
{
@ -374,13 +374,13 @@ var WebGLRenderer = new Class({
this.gl.viewport(0, 0, this.width, this.height);
for (var i = 0, l = this.rendererArray.length; i < l; ++i)
for (var i = 0, l = this.pipelines.length; i < l; ++i)
{
this.rendererArray[i].bind();
this.rendererArray[i].resize(width, height, resolution);
//this.pipelines[i].bind();
//this.pipelines[i].resize(width, height, resolution);
}
this.currentRenderer.bind();
//this.currentPipeline.bind();
},
// Call at the start of the render loop
@ -442,21 +442,18 @@ var WebGLRenderer = new Class({
{
var color = camera.backgroundColor;
quadBatch.bind();
quadBatch.add(
camera.x, camera.y, camera.width, camera.height,
color.redGL, color.greenGL, color.blueGL, color.alphaGL
);
quadBatch.flush();
this.currentRenderer.bind();
//quadBatch.bind();
//quadBatch.add(
// camera.x, camera.y, camera.width, camera.height,
// color.redGL, color.greenGL, color.blueGL, color.alphaGL
//);
//quadBatch.flush();
//this.currentPipeline.bind();
}
var list = children.list;
var length = list.length;
var renderer;
var pipeline;
for (var index = 0; index < length; ++index)
{
@ -485,42 +482,39 @@ var WebGLRenderer = new Class({
child.mask.postRenderWebGL(this, child);
}
renderer = this.currentRenderer;
pipeline = this.currentPipeline;
if (renderer.isFull() || renderer.shouldFlush())
if (pipeline.shouldFlush())
{
renderer.flush();
pipeline.flush();
}
}
this.currentRenderer.flush();
this.currentPipeline.flush();
if (camera._fadeAlpha > 0 || camera._flashAlpha > 0)
{
this.setRenderTarget(null);
this.setBlendMode(BlendModes.NORMAL);
// fade rendering
quadBatch.add(
camera.x, camera.y, camera.width, camera.height,
camera._fadeRed,
camera._fadeGreen,
camera._fadeBlue,
camera._fadeAlpha
);
// flash rendering
quadBatch.add(
camera.x, camera.y, camera.width, camera.height,
camera._flashRed,
camera._flashGreen,
camera._flashBlue,
camera._flashAlpha
);
quadBatch.flush();
this.currentRenderer.bind();
// // fade rendering
// quadBatch.add(
// camera.x, camera.y, camera.width, camera.height,
// camera._fadeRed,
// camera._fadeGreen,
// camera._fadeBlue,
// camera._fadeAlpha
// );
// // flash rendering
// quadBatch.add(
// camera.x, camera.y, camera.width, camera.height,
// camera._flashRed,
// camera._flashGreen,
// camera._flashBlue,
// camera._flashAlpha
// );
// quadBatch.flush();
// this.currentPipeline.bind();
}
if (this.scissor.enabled)
@ -534,7 +528,7 @@ var WebGLRenderer = new Class({
{
if (this.contextLost) return;
this.currentRenderer.flush();
this.currentPipeline.flush();
if (this.snapshotCallback)
{
@ -565,13 +559,13 @@ var WebGLRenderer = new Class({
return;
}
var renderer = this.currentRenderer;
var pipeline = this.currentPipeline;
if (this.blendMode !== newBlendMode)
{
if (renderer)
if (pipeline)
{
renderer.flush();
pipeline.flush();
}
var blend = this.blendModes[newBlendMode].func;
@ -592,14 +586,14 @@ var WebGLRenderer = new Class({
}
},
addRenderer: function (rendererInstance)
addPipeline: function (pipelineInstance)
{
var index = this.rendererArray.indexOf(rendererInstance);
var index = this.pipelines.indexOf(pipelineInstance);
if (index < 0)
{
this.rendererArray.push(rendererInstance);
return rendererInstance;
this.pipelines.push(pipelineInstance);
return pipelineInstance;
}
return null;
@ -640,7 +634,7 @@ var WebGLRenderer = new Class({
if (dstTexture != this.currentTexture[0])
{
this.currentRenderer.flush();
this.currentPipeline.flush();
}
gl.activeTexture(gl.TEXTURE0);
@ -684,4 +678,4 @@ var WebGLRenderer = new Class({
});
module.exports = WebGLRenderer;
module.exports = WebGLpipeline;

View file

@ -11,7 +11,7 @@ var BlitterBatch = new Class({
function BlitterBatch(game, gl, manager)
{
Pipeline.call(this, game, {
Pipeline.call(this, {
name: 'BlitterBatch',
game: game,
gl: gl,
@ -19,7 +19,7 @@ var BlitterBatch = new Class({
topology: gl.TRIANGLES,
shader: ShaderSource,
vertexCapacity: 12000,
vertexSize:
Float32Array.BYTES_PER_ELEMENT * 2 +
Float32Array.BYTES_PER_ELEMENT * 2 +
@ -37,7 +37,7 @@ var BlitterBatch = new Class({
type: gl.FLOAT,
normalize: false,
offset: Float32Array.BYTES_PER_ELEMENT * 2
}
},
'inTint': {
size: 4,
type: gl.UNSIGNED_BYTE,
@ -75,11 +75,15 @@ var BlitterBatch = new Class({
drawBlitter: function (blitter, camera)
{
this.beginDraw(blitter.shader, blitter.renderTarget);
this.manager.setPipeline(this);
this.beginPass(blitter.shader, blitter.renderTarget);
var vertexViewF32 = this.vertexViewF32;
var vertexViewU32 = this.vertexViewU32;
var orthoViewMatrix = this.orthoViewMatrix;
var manager = this.manager;
var gl = this.gl;
var shader = this.currentProgram;
var list = blitter.getRenderList();
var length = list.length;
var cameraMatrix = camera.matrix.matrix;
@ -94,6 +98,11 @@ var BlitterBatch = new Class({
var batchCount = Math.ceil(length / 2000);
var batchOffset = 0;
orthoViewMatrix[0] = +2.0 / this.width;
orthoViewMatrix[5] = -2.0 / this.height;
shader.setConstantMatrix4x4(shader.getUniformLocation('uOrthoMatrix'), orthoViewMatrix);
for (var batchIndex = 0; batchIndex < batchCount; ++batchIndex)
{
var batchSize = Math.min(length, 2000);
@ -122,8 +131,7 @@ var BlitterBatch = new Class({
// Bind Texture if texture wasn't bound.
// This needs to be here because of multiple
// texture atlas.
// manager.setTexture(frame.texture.source[frame.sourceIndex].glTexture, 0);
manager.setTexture(frame.texture.source[frame.sourceIndex].glTexture, 0);
vertexViewF32[vertexOffset + 0] = tx;
vertexViewF32[vertexOffset + 1] = ty;
@ -168,10 +176,10 @@ var BlitterBatch = new Class({
length -= batchSize;
this.vertexCount = (batchSize * 6);
this.draw();
this.flush();
}
this.endDraw();
this.endPass();
}
});

View file

@ -1,169 +0,0 @@
var Class = require('../../../../utils/Class');
var CONST = require('./const');
var DataBuffer16 = require('../../utils/DataBuffer16');
var DataBuffer32 = require('../../utils/DataBuffer32');
var PHASER_CONST = require('../../../../const');
var TexturedAndAlphaShader = require('../../shaders/TexturedAndAlphaShader');
var BlitterBatch = new Class({
initialize:
function BlitterBatch (game, gl, manager)
{
this.game = game;
this.type = PHASER_CONST.WEBGL;
this.view = game.canvas;
this.resolution = game.config.resolution;
this.width = game.config.width * game.config.resolution;
this.height = game.config.height * game.config.resolution;
this.glContext = gl;
this.maxParticles = null;
this.shader = null;
this.vertexBufferObject = null;
this.indexBufferObject = null;
this.vertexDataBuffer = null;
this.indexDataBuffer = null;
this.elementCount = 0;
this.currentTexture2D = null;
this.viewMatrixLocation = null;
// All of these settings will be able to be controlled via the Game Config
this.config = {
clearBeforeRender: true,
transparent: false,
autoResize: false,
preserveDrawingBuffer: false,
WebGLContextOptions: {
alpha: true,
antialias: true,
premultipliedAlpha: true,
stencil: true,
preserveDrawingBuffer: false
}
};
this.manager = manager;
this.dirty = false;
this.init(this.glContext);
},
init: function (gl)
{
var vertexDataBuffer = new DataBuffer32(CONST.VERTEX_SIZE * CONST.PARTICLE_VERTEX_COUNT * CONST.MAX_PARTICLES);
var indexDataBuffer = new DataBuffer16(CONST.INDEX_SIZE * CONST.PARTICLE_INDEX_COUNT * CONST.MAX_PARTICLES);
var shader = this.manager.resourceManager.createShader('TexturedAndAlphaShader', TexturedAndAlphaShader);
var indexBufferObject = this.manager.resourceManager.createBuffer(gl.ELEMENT_ARRAY_BUFFER, indexDataBuffer.getByteCapacity(), gl.STATIC_DRAW);
var vertexBufferObject = this.manager.resourceManager.createBuffer(gl.ARRAY_BUFFER, vertexDataBuffer.getByteCapacity(), gl.STREAM_DRAW);
var viewMatrixLocation = shader.getUniformLocation('u_view_matrix');
var indexBuffer = indexDataBuffer.uintView;
var max = CONST.MAX_PARTICLES * CONST.PARTICLE_INDEX_COUNT;
vertexBufferObject.addAttribute(shader.getAttribLocation('a_position'), 2, gl.FLOAT, false, CONST.VERTEX_SIZE, 0);
vertexBufferObject.addAttribute(shader.getAttribLocation('a_tex_coord'), 2, gl.FLOAT, false, CONST.VERTEX_SIZE, 8);
vertexBufferObject.addAttribute(shader.getAttribLocation('a_alpha'), 1, gl.FLOAT, false, CONST.VERTEX_SIZE, 16);
this.vertexDataBuffer = vertexDataBuffer;
this.indexDataBuffer = indexDataBuffer;
this.shader = shader;
this.indexBufferObject = indexBufferObject;
this.vertexBufferObject = vertexBufferObject;
this.viewMatrixLocation = viewMatrixLocation;
this.maxParticles = max;
// Populate the index buffer only once
for (var indexA = 0, indexB = 0; indexA < max; indexA += CONST.PARTICLE_INDEX_COUNT, indexB += CONST.PARTICLE_VERTEX_COUNT)
{
indexBuffer[indexA + 0] = indexB + 0;
indexBuffer[indexA + 1] = indexB + 1;
indexBuffer[indexA + 2] = indexB + 2;
indexBuffer[indexA + 3] = indexB + 0;
indexBuffer[indexA + 4] = indexB + 2;
indexBuffer[indexA + 5] = indexB + 3;
}
indexBufferObject.updateResource(indexBuffer, 0);
this.resize(this.width, this.height, this.game.config.resolution);
},
shouldFlush: function ()
{
return false;
},
isFull: function ()
{
return (this.vertexDataBuffer.getByteLength() >= this.vertexDataBuffer.getByteCapacity());
},
bind: function (shader)
{
if (!shader)
{
this.shader.bind();
}
else
{
shader.bind();
this.resize(this.width, this.height, this.game.config.resolution, shader);
}
this.indexBufferObject.bind();
this.vertexBufferObject.bind();
},
flush: function (shader)
{
var gl = this.glContext;
var vertexDataBuffer = this.vertexDataBuffer;
if (this.elementCount === 0)
{
return;
}
this.bind(shader);
this.vertexBufferObject.updateResource(vertexDataBuffer.getUsedBufferAsFloat(), 0);
gl.drawElements(gl.TRIANGLES, this.elementCount, gl.UNSIGNED_SHORT, 0);
vertexDataBuffer.clear();
this.elementCount = 0;
},
resize: function (width, height, resolution, shader)
{
var activeShader = shader ? shader : this.shader;
this.width = width * resolution;
this.height = height * resolution;
activeShader.setConstantMatrix4x4(
this.viewMatrixLocation,
new Float32Array([
2 / this.width, 0, 0, 0,
0, -2 / this.height, 0, 0,
0, 0, 1, 1,
-1, 1, 0, 0
])
);
},
destroy: function ()
{
this.manager.resourceManager.deleteShader(this.shader);
this.manager.resourceManager.deleteBuffer(this.indexBufferObject);
this.manager.resourceManager.deleteBuffer(this.vertexBufferObject);
this.shader = null;
this.indexBufferObject = null;
this.vertexBufferObject = null;
}
});
module.exports = BlitterBatch;