refactored webGL renderer

This commit is contained in:
Mat Groves 2013-12-27 16:21:54 +00:00
parent 530d889b0a
commit d56d6df260
17 changed files with 9388 additions and 7944 deletions

View file

@ -5,6 +5,8 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-yuidoc');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadTasks('tasks');
var srcFiles = [
@ -33,11 +35,13 @@ module.exports = function(grunt) {
'<%= dirs.src %>/renderers/webgl/PixiShader.js',
'<%= dirs.src %>/renderers/webgl/StripShader.js',
'<%= dirs.src %>/renderers/webgl/PrimitiveShader.js',
'<%= dirs.src %>/renderers/webgl/WebGLGraphics.js',
'<%= dirs.src %>/renderers/webgl/utils/WebGLGraphics.js',
'<%= dirs.src %>/renderers/webgl/WebGLRenderer.js',
'<%= dirs.src %>/renderers/webgl/utils/WebGLMaskManager.js',
'<%= dirs.src %>/renderers/webgl/utils/WebGLSpriteBatch.js',
'<%= dirs.src %>/renderers/webgl/WebGLBatch.js',
'<%= dirs.src %>/renderers/webgl/WebGLRenderGroup.js',
'<%= dirs.src %>/renderers/webgl/WebGLFilterManager.js',
'<%= dirs.src %>/renderers/webgl/utils/WebGLFilterManager.js',
'<%= dirs.src %>/renderers/canvas/CanvasRenderer.js',
'<%= dirs.src %>/renderers/canvas/CanvasGraphics.js',
'<%= dirs.src %>/primitives/Graphics.js',
@ -168,6 +172,15 @@ module.exports = function(grunt) {
}
}
},
watch: {
scripts: {
files: ['<%= dirs.src %>/**/*.js'],
tasks: ['concat'],
options: {
spawn: false,
}
}
},
karma: {
unit: {
configFile: 'test/karma.conf.js',
@ -186,4 +199,8 @@ module.exports = function(grunt) {
grunt.registerTask('docs', ['yuidoc']);
grunt.registerTask('travis', ['build', 'test']);
grunt.registerTask('default', ['build', 'test']);
grunt.registerTask('debug-watch', ['concat', 'watch']);
};

File diff suppressed because it is too large Load diff

View file

@ -48,6 +48,7 @@
// just for fun, lets rotate mr rabbit a little
bunny.rotation += 0.1;
// console.log(stage.getBounds().width);
// render the stage
renderer.render(stage);
}

View file

@ -70,9 +70,9 @@
graphics.drawRect(50, 250, 100, 100);
// draw a circle
graphics.lineStyle(0);
graphics.beginFill(0xFFFF0B, 0.5);
graphics.drawCircle(470, 200,100);
/// graphics.lineStyle(0);
// graphics.beginFill(0xFFFF0B, 0.5);
// graphics.drawCircle(470, 200,100);
graphics.lineStyle(20, 0x33FF00);
graphics.moveTo(30,30);
@ -100,7 +100,7 @@
function animate() {
thing.clear();
/* thing.clear();
count += 0.1;
@ -114,7 +114,7 @@
thing.lineTo(-120 + Math.cos(count)* 20, 100 + Math.sin(count)* 20);
thing.lineTo(-120 + Math.sin(count) * 20, -100 + Math.cos(count)* 20);
thing.rotation = count * 0.1;
thing.rotation = count * 0.1;*/
renderer.render(stage);
requestAnimFrame( animate );
}

View file

@ -353,7 +353,8 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', {
passes.push(filterPasses[j]);
}
}
this._filterBlock = value.start;
value.start.filterPasses = passes;
}
else
@ -580,6 +581,17 @@ PIXI.DisplayObject.prototype.getBounds = function()
return PIXI.EmptyRectangle;
}
PIXI.DisplayObject.prototype._renderWebGL = function(renderSession)
{
// OVERWRITE
}
PIXI.DisplayObject.prototype._renderCanvas = function(renderSession)
{
// OVERWRITE
}
PIXI.EmptyRectangle = new PIXI.Rectangle(0,0,0,0);
PIXI.visibleCount = 0;

View file

@ -374,7 +374,7 @@ PIXI.DisplayObjectContainer.prototype.getBounds = function()
maxX = maxX > childMaxX ? maxX : childMaxX;
maxY = maxY > childMaxY ? maxY : childMaxY;
}
var bounds = this._bounds;
bounds.x = minX;
@ -385,3 +385,57 @@ PIXI.DisplayObjectContainer.prototype.getBounds = function()
return bounds;
}
PIXI.DisplayObjectContainer.prototype._renderWebGL = function(renderSession)
{
if(this.visible === false || this.alpha === 0)return;
if(this.mask || this.filters)
{
if(this.mask)
{
renderSession.spriteBatch.stop();
renderSession.maskManager.pushMask(this.mask, renderSession.projection);
renderSession.spriteBatch.start();
}
if(this.filters)
{
renderSession.spriteBatch.flush();
renderSession.filterManager.pushFilter(this._filterBlock);
}
// simple render children!
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child._renderWebGL(renderSession);
}
renderSession.spriteBatch.stop();
if(this.filters)renderSession.filterManager.popFilter();
if(this.mask)renderSession.maskManager.popMask(renderSession.projection);
renderSession.spriteBatch.start();
}
else
{
// simple render children!
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child._renderWebGL(renderSession);
}
}
}
PIXI.DisplayObjectContainer.prototype._renderCanvas = function(renderSession)
{
// OVERWRITE
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child._renderCanvas(renderSession);
}
}

View file

@ -151,8 +151,6 @@ PIXI.Sprite.prototype.setTexture = function(texture)
*/
PIXI.Sprite.prototype.onTextureUpdate = function()
{
//this.texture.removeEventListener( 'update', this.onTextureUpdateBind );
// so if _width is 0 then width was not set..
if(this._width)this.scale.x = this._width / this.texture.frame.width;
if(this._height)this.scale.y = this._height / this.texture.frame.height;
@ -229,6 +227,68 @@ PIXI.Sprite.prototype.getBounds = function()
return bounds;
}
PIXI.Sprite.prototype._renderWebGL = function(renderSession)
{
if(this.visible === false || this.alpha === 0)return;
if(this.mask || this.filters)
{
if(this.mask)
{
renderSession.spriteBatch.stop();
renderSession.maskManager.pushMask(this.mask, renderSession.projection);
renderSession.spriteBatch.start();
}
if(this.filters)
{
renderSession.spriteBatch.flush();
renderSession.filterManager.pushFilter(this._filterBlock);
}
renderSession.spriteBatch.render(this);
// simple render children!
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child._renderWebGL(renderSession);
}
renderSession.spriteBatch.stop();
if(this.filters)renderSession.filterManager.popFilter();
if(this.mask)renderSession.maskManager.popMask(renderSession.projection);
renderSession.spriteBatch.start();
}
else
{
renderSession.spriteBatch.render(this);
// simple render children!
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child._renderWebGL(renderSession);
}
}
//TODO check culling
}
PIXI.Sprite.prototype._renderCanvas = function(renderSession)
{
// OVERWRITE
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child._renderCanvas(renderSession);
}
}
// some helper functions..
/**

View file

@ -102,7 +102,6 @@ PIXI.Stage.prototype.updateTransform = function()
this.interactionManager.dirty = true;
}
if(this.interactive)this.interactionManager.update();
};

View file

@ -14,32 +14,13 @@
*/
PIXI.TilingSprite = function(texture, width, height)
{
PIXI.DisplayObjectContainer.call( this );
PIXI.Sprite.call( this, texture);
/**
* The texture that the sprite is using
*
* @property texture
* @type Texture
*/
this.texture = texture;
/**
* The width of the tiling sprite
*
* @property width
* @type Number
*/
this.width = width;
/**
* The height of the tiling sprite
*
* @property height
* @type Number
*/
this.height = height;
this.width = width || 100;
this.height = height || 100;
texture.baseTexture._powerOf2 = true;
/**
* The scaling of the image that is being tiled
*
@ -62,33 +43,90 @@ PIXI.TilingSprite = function(texture, width, height)
};
// constructor
PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
PIXI.TilingSprite.prototype = Object.create( PIXI.Sprite.prototype );
PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite;
/**
* Sets the texture of the tiling sprite
*
* @method setTexture
* @param texture {Texture} The PIXI texture that is displayed by the sprite
*/
PIXI.TilingSprite.prototype.setTexture = function(texture)
{
//TODO SET THE TEXTURES
//TODO VISIBILITY
// stop current texture
this.texture = texture;
this.updateFrame = true;
};
/**
* When the texture is updated, this event will fire to update the frame
* The width of the sprite, setting this will actually modify the scale to acheive the value set
*
* @method onTextureUpdate
* @param event
* @private
* @property width
* @type Number
*/
PIXI.TilingSprite.prototype.onTextureUpdate = function()
Object.defineProperty(PIXI.TilingSprite.prototype, 'width', {
get: function() {
return this._width
},
set: function(value) {
this._width = value;
}
});
/**
* The height of the TilingSprite, setting this will actually modify the scale to acheive the value set
*
* @property height
* @type Number
*/
Object.defineProperty(PIXI.TilingSprite.prototype, 'height', {
get: function() {
return this._height
},
set: function(value) {
this._height = value;
}
});
PIXI.TilingSprite.prototype._renderWebGL = function(renderSession)
{
this.updateFrame = true;
};
if(this.visible === false || this.alpha === 0)return;
if(this.mask || this.filters)
{
if(this.mask)
{
renderSession.spriteBatch.stop();
renderSession.maskManager.pushMask(this.mask, renderSession.projection);
renderSession.spriteBatch.start();
}
if(this.filters)
{
renderSession.spriteBatch.flush();
renderSession.filterManager.pushFilter(this._filterBlock);
}
renderSession.spriteBatch.renderTilingSprite(this);
// simple render children!
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child._renderWebGL(renderSession);
}
renderSession.spriteBatch.stop();
if(this.filters)renderSession.filterManager.popFilter();
if(this.mask)renderSession.maskManager.popMask(renderSession.projection);
renderSession.spriteBatch.start();
}
else
{
renderSession.spriteBatch.renderTilingSprite(this);
// simple render children!
for(var i=0,j=this.children.length; i<j; i++)
{
var child = this.children[i];
child._renderWebGL(renderSession);
}
}
}
PIXI.TilingSprite.prototype._renderCanvas = function(renderSession)
{
}

View file

@ -130,6 +130,7 @@ PIXI.Graphics.prototype.lineTo = function(x, y)
*/
PIXI.Graphics.prototype.beginFill = function(color, alpha)
{
this.filling = true;
this.fillColor = color || 0;
this.fillAlpha = (arguments.length < 2) ? 1 : alpha;
@ -177,6 +178,7 @@ PIXI.Graphics.prototype.drawRect = function( x, y, width, height )
*/
PIXI.Graphics.prototype.drawCircle = function( x, y, radius)
{
if (!this.currentPath.points.length) this.graphicsData.pop();
this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
@ -198,6 +200,7 @@ PIXI.Graphics.prototype.drawCircle = function( x, y, radius)
*/
PIXI.Graphics.prototype.drawEllipse = function( x, y, width, height)
{
if (!this.currentPath.points.length) this.graphicsData.pop();
this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
@ -226,6 +229,20 @@ PIXI.Graphics.prototype.clear = function()
};
PIXI.Graphics.prototype._renderWebGL = function(renderSession)
{
renderSession.spriteBatch.stop();
PIXI.WebGLGraphics.renderGraphics(this, renderSession.projection);
renderSession.spriteBatch.start();
}
PIXI.DisplayObject.prototype._renderCanvas = function(renderSession)
{
// OVERWRITE
}
PIXI.Graphics.prototype.getBounds = function()
{
if(!this.bounds)this.updateBounds();

View file

@ -8,6 +8,8 @@ PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1);
// only one at the moment :/
PIXI.gl = null;
/**
* the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer
* should be used for browsers support webGL. This Render works by automatically managing webGLBatchs.
@ -96,6 +98,15 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl, this.transparent);
// this.stageRenderGroup. = this.transparent
this.spriteBatch = new PIXI.WebGLSpriteBatch(gl)//this.gl, PIXI.WebGLRenderer.batchSize);
this.maskManager = new PIXI.WebGLMaskManager(gl);
this.filterManager = new PIXI.WebGLFilterManager(this.transparent);
this.renderSession = {};
this.renderSession.maskManager = this.maskManager;
this.renderSession.filterManager = this.filterManager;
this.renderSession.spriteBatch = this.spriteBatch;
};
// constructor
@ -158,6 +169,22 @@ PIXI.WebGLRenderer.prototype.render = function(stage)
// update any textures
PIXI.WebGLRenderer.updateTextures();
// after rendering lets confirm all frames that have been uodated..
if(PIXI.Texture.frameUpdates.length > 0)
{
for (var i=0; i < PIXI.Texture.frameUpdates.length; i++)
{
var texture = PIXI.Texture.frameUpdates[i];
texture.updateFrame = false;
// now set the uvs. Figured that the uv data sits with a texture rather than a sprite.
// so uv data is stored on the texture itself
texture._updateWebGLuvs();
}
PIXI.Texture.frameUpdates = [];
}
// update the scene graph
PIXI.visibleCount++;
stage.updateTransform();
@ -180,7 +207,21 @@ PIXI.WebGLRenderer.prototype.render = function(stage)
PIXI.projection.x = this.width/2;
PIXI.projection.y = -this.height/2;
this.stageRenderGroup.render(PIXI.projection);
// reset the render session data..
this.renderSession.drawCount = 0;
this.renderSession.projection = PIXI.projection;
//console.log(this.renderSession)
// start using the sprite batch
this.spriteBatch.begin(this.renderSession);
this.filterManager.begin(PIXI.projection, null);
stage._renderWebGL(this.renderSession);
this.spriteBatch.end();
// this.stage.render();
// this.stageRenderGroup.render(PIXI.projection);
// interaction
// run interaction!
@ -194,16 +235,7 @@ PIXI.WebGLRenderer.prototype.render = function(stage)
}
}
// after rendering lets confirm all frames that have been uodated..
if(PIXI.Texture.frameUpdates.length > 0)
{
for (var i=0; i < PIXI.Texture.frameUpdates.length; i++)
{
PIXI.Texture.frameUpdates[i].updateFrame = false;
}
PIXI.Texture.frameUpdates = [];
}
};
/**

View file

@ -110,7 +110,7 @@ PIXI.WebGLGraphics.updateGraphics = function(graphics)
{
PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL);
}
else if(data.type === PIXI.Graphics.CIRC || data.type === PIXI.Graphics.ELIP);
else if(data.type === PIXI.Graphics.CIRC || data.type === PIXI.Graphics.ELIP)
{
PIXI.WebGLGraphics.buildCircle(data, graphics._webGL);
}

View file

@ -0,0 +1,58 @@
/**
* @author Matt DesLauriers <mattdesl> https://github.com/mattdesl/
*
* Heavily inspired by LibGDX's WebGLMaskManager:
* https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/WebGLMaskManager.java
*/
PIXI.WebGLMaskManager = function(gl)
{
this.gl = gl;
this.maskStack = [];
this.maskPosition = 0;
}
PIXI.WebGLMaskManager.prototype.pushMask = function(maskData, projection)
{
var gl = this.gl;
if(this.maskStack.length === 0)
{
gl.enable(gl.STENCIL_TEST);
gl.stencilFunc(gl.ALWAYS,1,1);
}
this.maskStack.push(maskData);
gl.colorMask(false, false, false, false);
gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR);
PIXI.WebGLGraphics.renderGraphics(maskData, projection);
gl.colorMask(true, true, true, true);
gl.stencilFunc(gl.NOTEQUAL,0, this.maskStack.length);
gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
}
PIXI.WebGLMaskManager.prototype.popMask = function(projection)
{
var gl = this.gl;
var maskData = this.maskStack.pop();
if(maskData)
{
gl.colorMask(false, false, false, false);
//gl.stencilFunc(gl.ALWAYS,1,1);
gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);
PIXI.WebGLGraphics.renderGraphics(maskData, projection);
gl.colorMask(true, true, true, true);
gl.stencilFunc(gl.NOTEQUAL,0,this.maskStack.length);
gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
}
if(this.maskStack.length === 0)gl.disable(gl.STENCIL_TEST);
}

View file

@ -0,0 +1,261 @@
/**
* @author Matt DesLauriers <mattdesl> https://github.com/mattdesl/
*
* Heavily inspired by LibGDX's WebGLSpriteBatch:
* https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/WebGLSpriteBatch.java
*/
PIXI.WebGLSpriteBatch = function(gl)
{
this.gl = gl;
// create a couple of buffers
this.vertexBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
this.size = 2000;
// 65535 is max index, so 65535 / 6 = 10922.
//the total number of floats in our batch
var numVerts = this.size * 4 * 5;
//the total number of indices in our batch
var numIndices = this.size * 6;
//TODO: use properties here
//current blend mode.. changing it flushes the batch
this.blendMode = PIXI.blendModes.NORMAL;
//vertex data
this.vertices = new Float32Array(numVerts);
//index data
this.indices = new Uint16Array(numIndices);
this.lastIndexCount = 0;
for (var i=0, j=0; i < numIndices; i += 6, j += 4)
{
this.indices[i + 0] = j + 0;
this.indices[i + 1] = j + 1;
this.indices[i + 2] = j + 2;
this.indices[i + 3] = j + 0;
this.indices[i + 4] = j + 2;
this.indices[i + 5] = j + 3;
};
//upload the index data
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW);
this.drawing = false;
this.currentBatchSize = 0;
this.currentBaseTexture;
}
PIXI.WebGLSpriteBatch.prototype.begin = function(renderSession)
{
this.renderSession = renderSession;
var gl = this.gl;
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
var stride = 5 * 4;
var projection = renderSession.projection;
gl.uniform2f(PIXI.defaultShader.projectionVector, projection.x, projection.y);
gl.vertexAttribPointer(PIXI.defaultShader.aVertexPosition, 2, gl.FLOAT, false, stride, 0);
gl.vertexAttribPointer(PIXI.defaultShader.aTextureCoord, 2, gl.FLOAT, false, stride, 2 * 4);
gl.vertexAttribPointer(PIXI.defaultShader.colorAttribute, 1, gl.FLOAT, false, stride, 4 * 4);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
}
PIXI.WebGLSpriteBatch.prototype.end = function()
{
this.flush();
}
PIXI.WebGLSpriteBatch.prototype.render = function(sprite)
{
if(sprite.texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size)
{
this.flush();
this.currentBaseTexture = sprite.texture.baseTexture;
}
// get the uvs for the texture
var uvs = sprite.texture._uvs;
// if the uvs have not updated then no point rendering just yet!
if(!uvs)return;
// get the sprites current alpha
var alpha = sprite.alpha;
var verticies = this.vertices;
width = sprite.texture.frame.width;
height = sprite.texture.frame.height;
// TODO trim??
var aX = sprite.anchor.x; // - sprite.texture.trim.x
var aY = sprite.anchor.y; //- sprite.texture.trim.y
var w0 = width * (1-aX);
var w1 = width * -aX;
var h0 = height * (1-aY);
var h1 = height * -aY;
var index = this.currentBatchSize * 4 * 5;
worldTransform = sprite.worldTransform;
var a = worldTransform[0];
var b = worldTransform[3];
var c = worldTransform[1];
var d = worldTransform[4];
var tx = worldTransform[2];
var ty = worldTransform[5];
// xy
verticies[index++] = a * w1 + c * h1 + tx;
verticies[index++] = d * h1 + b * w1 + ty;
// uv
verticies[index++] = uvs[0];
verticies[index++] = uvs[1];
// color
verticies[index++] = alpha;
// xy
verticies[index++] = a * w0 + c * h1 + tx;
verticies[index++] = d * h1 + b * w0 + ty;
// uv
verticies[index++] = uvs[2];
verticies[index++] = uvs[3];
// color
verticies[index++] = alpha;
// xy
verticies[index++] = a * w0 + c * h0 + tx;
verticies[index++] = d * h0 + b * w0 + ty;
// uv
verticies[index++] = uvs[4];
verticies[index++] = uvs[5];
// color
verticies[index++] = alpha;
// xy
verticies[index++] = a * w1 + c * h0 + tx;
verticies[index++] = d * h0 + b * w1 + ty;
// uv
verticies[index++] = uvs[6];
verticies[index++] = uvs[7];
// color
verticies[index++] = alpha;
// increment the batchs
this.currentBatchSize++;
}
PIXI.WebGLSpriteBatch.prototype.renderTilingSprite = function(tilingSprite)
{
var texture = tilingSprite.texture;
// set the textures uvs temporarily
// TODO create a seperate texture so that we can tile part of a texture
var tempUvs = texture._uvs;
if(!tilingSprite._uvs)tilingSprite._uvs = new Float32Array(8);
var uvs = tilingSprite._uvs;
var offsetX = tilingSprite.tilePosition.x/texture.baseTexture.width;
var offsetY = tilingSprite.tilePosition.y/texture.baseTexture.height;
var scaleX = (tilingSprite.width / texture.baseTexture.width) / tilingSprite.tileScale.x;
var scaleY = (tilingSprite.height / texture.baseTexture.height) / tilingSprite.tileScale.y;
uvs[0] = 0 - offsetX;
uvs[1] = 0 - offsetY;
uvs[2] = (1 * scaleX) - offsetX;
uvs[3] = 0 - offsetY;
uvs[4] = (1 * scaleX) - offsetX;
uvs[5] = (1 * scaleY) - offsetY;
uvs[6] = 0 - offsetX;
uvs[7] = (1 *scaleY) - offsetY;
texture._uvs = uvs;
this.render(tilingSprite);
tilingSprite.texture._uvs = tempUvs;
}
PIXI.WebGLSpriteBatch.prototype.flush = function()
{
// first draw
if (this.currentBatchSize===0)return;
var gl = this.gl;
//setup our vertex attributes & binds textures
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this.currentBaseTexture._glTexture);
// bind the index
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
//bind our vertex buffer
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
// Only update a region of the buffer. On my computer
// this is faster (especially if you are not filling the entire batch)
// but it could do with more testing. In theory it SHOULD be faster
// since bufferData allocates memory, whereas this should not.
var view = this.vertices.subarray(0, this.currentBatchSize * 4 * 5);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, view);
gl.drawElements(gl.TRIANGLES, this.currentBatchSize * 6, gl.UNSIGNED_SHORT, 0);
// then reset!
this.currentBatchSize = 0;
this.renderSession.drawCount++;
}
PIXI.WebGLSpriteBatch.prototype.stop = function()
{
this.flush();
}
PIXI.WebGLSpriteBatch.prototype.start = function()
{
var gl = this.gl;
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
var stride = 5 * 4;
var projection = this.renderSession.projection;
gl.uniform2f(PIXI.defaultShader.projectionVector, projection.x, projection.y);
gl.vertexAttribPointer(PIXI.defaultShader.aVertexPosition, 2, gl.FLOAT, false, stride, 0);
gl.vertexAttribPointer(PIXI.defaultShader.aTextureCoord, 2, gl.FLOAT, false, stride, 2 * 4);
gl.vertexAttribPointer(PIXI.defaultShader.colorAttribute, 1, gl.FLOAT, false, stride, 4 * 4);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
}

View file

@ -93,8 +93,17 @@ PIXI.RenderTexture.prototype.initWebGL = function()
// create a projection matrix..
this.projection = new PIXI.Point(this.width/2 , -this.height/2);
// set the correct render function..
this.render = this.renderWebGL;
this.spriteBatch = new PIXI.WebGLSpriteBatch(gl);
this.renderSession = {};
this.renderSession.spriteBatch = this.spriteBatch;
PIXI.Texture.frameUpdates.push(this);
};
@ -187,25 +196,12 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle
children[i].updateTransform();
}
var renderGroup = displayObject.__renderGroup;
this.renderSession.drawCount = 0;
this.renderSession.projection = this.projection;
if(renderGroup)
{
if(displayObject === renderGroup.root)
{
renderGroup.render(this.projection, this.glFramebuffer);
}
else
{
renderGroup.renderSpecific(displayObject, this.projection, this.glFramebuffer);
}
}
else
{
if(!this.renderGroup)this.renderGroup = new PIXI.WebGLRenderGroup(gl);
this.renderGroup.setRenderable(displayObject);
this.renderGroup.render(this.projection, this.glFramebuffer);
}
this.spriteBatch.begin(this.renderSession);
displayObject._renderWebGL( this.renderSession);
this.spriteBatch.end();
displayObject.worldTransform = originalWorldTransform;
};

View file

@ -83,9 +83,8 @@ PIXI.Texture.prototype.onBaseTextureLoaded = function()
baseTexture.removeEventListener( 'loaded', this.onLoaded );
if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height);
this.noFrame = false;
this.width = this.frame.width;
this.height = this.frame.height;
this.setFrame(this.frame);
this.scope.dispatchEvent( { type: 'update', content: this } );
};
@ -124,6 +123,27 @@ PIXI.Texture.prototype.setFrame = function(frame)
//this.dispatchEvent( { type: 'update', content: this } );
};
PIXI.Texture.prototype._updateWebGLuvs = function()
{
if(!this._uvs)this._uvs = new Float32Array(8)
var frame = this.frame;
var tw = this.baseTexture.width;
var th = this.baseTexture.height;
this._uvs[0] = frame.x / tw;
this._uvs[1] = frame.y / th;
this._uvs[2] = (frame.x + frame.width) / tw;
this._uvs[3] = frame.y / th;
this._uvs[4] = (frame.x + frame.width) / tw;
this._uvs[5] = (frame.y + frame.height) / th;
this._uvs[6] = frame.x / tw;
this._uvs[7] = (frame.y + frame.height) / th;
}
/**
* Helper function that returns a texture based on an image url
* If the image is not in the texture cache it will be created and loaded