diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 6b95180..eab34bc 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -372,7 +372,7 @@ if(this.currentRenderTarget === this.renderTarget) { this.renderTarget.activate(); - this.gl.viewport(0, 0, this.width, this.height); + //this.gl.viewport(0, 0, this.width, this.height); } }; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 6b95180..eab34bc 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -372,7 +372,7 @@ if(this.currentRenderTarget === this.renderTarget) { this.renderTarget.activate(); - this.gl.viewport(0, 0, this.width, this.height); + //this.gl.viewport(0, 0, this.width, this.height); } }; diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 61cc8ae..58ab2e5 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -1,7 +1,10 @@ var math = require('../../../math'), utils = require('../../../utils'), CONST = require('../../../const'), - //StencilManager = require('../managers/StencilManager'), + + GLTexture = require('pixi-gl-core').GLTexture, + GLFramebuffer = require('pixi-gl-core').GLFramebuffer, + StencilMaskStack = require('./StencilMaskStack'); /** @@ -124,42 +127,31 @@ */ this.root = root; + this.frameBuffer = new GLFramebuffer(gl); + if (!this.root) { - // this.flipY = true; - this.frameBuffer = gl.createFramebuffer(); - /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. */ + + // create a texture to bind attach to the frameBuffer.. + var texture = new GLTexture(gl); - this.texture = gl.createTexture(); + texture.enableLinearScaling() + texture.enableWrapClamp() - gl.bindTexture(gl.TEXTURE_2D, this.texture); + this.frameBuffer.enableTexture(texture); - // set the scale properties of the texture.. - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST); - - // check to see if the texture is a power of two! - var isPowerOfTwo = utils.isPowerOfTwo(width, height); - - //TODO for 99% of use cases if a texture is power of two we should tile the texture... - if (!isPowerOfTwo) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0); + // TODO change! + // this is used by the base texture + this.texture = texture.texture; + } + else + { + // make it a null framebuffer.. + this.frameBuffer.framebuffer = null; } this.resize(width, height); @@ -173,16 +165,9 @@ * * @param [bind=false] {boolean} Should we bind our framebuffer before clearing? */ -RenderTarget.prototype.clear = function(bind) +RenderTarget.prototype.clear = function(r,g,b,a) { - var gl = this.gl; - if(bind) - { - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); - } - - gl.clearColor(0,0,0,0); - gl.clear(gl.COLOR_BUFFER_BIT); + this.frameBuffer.clear(1,1,1,1)//r,g,b,a); }; /** @@ -191,24 +176,14 @@ */ RenderTarget.prototype.attachStencilBuffer = function() { - - if (this.stencilBuffer) - { - return; - } - + //TODO check if stencil is done? /** * The stencil buffer is used for masking in pixi * lets create one and then add attach it to the framebuffer.. */ if (!this.root) { - var gl = this.gl; - - this.stencilBuffer = gl.createRenderbuffer(); - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.size.width * this.resolution , this.size.height * this.resolution ); + this.frameBuffer.enableStencil(); } }; @@ -221,7 +196,8 @@ //TOOD refactor usage of frame.. var gl = this.gl; - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); + this.frameBuffer.bind(); + var projectionFrame = this.frame || this.size; @@ -264,7 +240,6 @@ } }; - /** * Resizes the texture to the specified width and height * @@ -276,29 +251,16 @@ width = width | 0; height = height | 0; - if (this.size.width === width && this.size.height === height) { + if (this.size.width === width && this.size.height === height) + { return; } this.size.width = width; this.size.height = height; - if (!this.root) - { - var gl = this.gl; - - gl.bindTexture(gl.TEXTURE_2D, this.texture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width * this.resolution, height * this.resolution , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - if (this.stencilBuffer ) - { - // update the stencil buffer width and height - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width * this.resolution, height * this.resolution ); - } - } - + this.frameBuffer.resize(width * this.resolution, height * this.resolution); + var projectionFrame = this.frame || this.size; this.calculateProjection( projectionFrame ); @@ -311,9 +273,8 @@ RenderTarget.prototype.destroy = function () { var gl = this.gl; - gl.deleteRenderbuffer( this.stencilBuffer ); - gl.deleteFramebuffer( this.frameBuffer ); - gl.deleteTexture( this.texture ); + + this.frameBuffer.destroy(); this.frameBuffer = null; this.texture = null; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 6b95180..eab34bc 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -372,7 +372,7 @@ if(this.currentRenderTarget === this.renderTarget) { this.renderTarget.activate(); - this.gl.viewport(0, 0, this.width, this.height); + //this.gl.viewport(0, 0, this.width, this.height); } }; diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 61cc8ae..58ab2e5 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -1,7 +1,10 @@ var math = require('../../../math'), utils = require('../../../utils'), CONST = require('../../../const'), - //StencilManager = require('../managers/StencilManager'), + + GLTexture = require('pixi-gl-core').GLTexture, + GLFramebuffer = require('pixi-gl-core').GLFramebuffer, + StencilMaskStack = require('./StencilMaskStack'); /** @@ -124,42 +127,31 @@ */ this.root = root; + this.frameBuffer = new GLFramebuffer(gl); + if (!this.root) { - // this.flipY = true; - this.frameBuffer = gl.createFramebuffer(); - /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. */ + + // create a texture to bind attach to the frameBuffer.. + var texture = new GLTexture(gl); - this.texture = gl.createTexture(); + texture.enableLinearScaling() + texture.enableWrapClamp() - gl.bindTexture(gl.TEXTURE_2D, this.texture); + this.frameBuffer.enableTexture(texture); - // set the scale properties of the texture.. - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST); - - // check to see if the texture is a power of two! - var isPowerOfTwo = utils.isPowerOfTwo(width, height); - - //TODO for 99% of use cases if a texture is power of two we should tile the texture... - if (!isPowerOfTwo) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0); + // TODO change! + // this is used by the base texture + this.texture = texture.texture; + } + else + { + // make it a null framebuffer.. + this.frameBuffer.framebuffer = null; } this.resize(width, height); @@ -173,16 +165,9 @@ * * @param [bind=false] {boolean} Should we bind our framebuffer before clearing? */ -RenderTarget.prototype.clear = function(bind) +RenderTarget.prototype.clear = function(r,g,b,a) { - var gl = this.gl; - if(bind) - { - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); - } - - gl.clearColor(0,0,0,0); - gl.clear(gl.COLOR_BUFFER_BIT); + this.frameBuffer.clear(1,1,1,1)//r,g,b,a); }; /** @@ -191,24 +176,14 @@ */ RenderTarget.prototype.attachStencilBuffer = function() { - - if (this.stencilBuffer) - { - return; - } - + //TODO check if stencil is done? /** * The stencil buffer is used for masking in pixi * lets create one and then add attach it to the framebuffer.. */ if (!this.root) { - var gl = this.gl; - - this.stencilBuffer = gl.createRenderbuffer(); - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.size.width * this.resolution , this.size.height * this.resolution ); + this.frameBuffer.enableStencil(); } }; @@ -221,7 +196,8 @@ //TOOD refactor usage of frame.. var gl = this.gl; - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); + this.frameBuffer.bind(); + var projectionFrame = this.frame || this.size; @@ -264,7 +240,6 @@ } }; - /** * Resizes the texture to the specified width and height * @@ -276,29 +251,16 @@ width = width | 0; height = height | 0; - if (this.size.width === width && this.size.height === height) { + if (this.size.width === width && this.size.height === height) + { return; } this.size.width = width; this.size.height = height; - if (!this.root) - { - var gl = this.gl; - - gl.bindTexture(gl.TEXTURE_2D, this.texture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width * this.resolution, height * this.resolution , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - if (this.stencilBuffer ) - { - // update the stencil buffer width and height - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width * this.resolution, height * this.resolution ); - } - } - + this.frameBuffer.resize(width * this.resolution, height * this.resolution); + var projectionFrame = this.frame || this.size; this.calculateProjection( projectionFrame ); @@ -311,9 +273,8 @@ RenderTarget.prototype.destroy = function () { var gl = this.gl; - gl.deleteRenderbuffer( this.stencilBuffer ); - gl.deleteFramebuffer( this.frameBuffer ); - gl.deleteTexture( this.texture ); + + this.frameBuffer.destroy(); this.frameBuffer = null; this.texture = null; diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 7440a0f..7701fda 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -92,6 +92,9 @@ // call texture setter this.texture = texture || Texture.EMPTY; + + this.vertexDirty = true; + this.vertexData = new Float32Array(8); } // constructor @@ -159,6 +162,8 @@ this._texture = value; this.cachedTint = 0xFFFFFF; + this.textureDirty = true; + if (value) { // wait for the texture to load @@ -194,6 +199,56 @@ } }; +Sprite.prototype.caclulateVertices = function () +{ + + var texture = this._texture, + wt = this.worldTransform, + a = wt.a, b = wt.b, c = wt.c, d = wt.d, tx = wt.tx, ty = wt.ty, + vertexData = this.vertexData, + aX = this.anchor.x, + aY = this.anchor.y, + w0, w1, h0, h1, + trim = texture.trim; + + if (trim) + { + // if the sprite is trimmed and is not a tilingsprite then we need to add the extra space before transforming the sprite coords.. + w1 = trim.x - aX * trim.width; + w0 = w1 + texture.crop.width; + + h1 = trim.y - aY * trim.height; + h0 = h1 + texture.crop.height; + + } + else + { + w0 = (texture._frame.width ) * (1-aX); + w1 = (texture._frame.width ) * -aX; + + h0 = texture._frame.height * (1-aY); + h1 = texture._frame.height * -aY; + } + + // xy + vertexData[0] = a * w1 + c * h1 + tx; + vertexData[1] = d * h1 + b * w1 + ty; + + // xy + vertexData[2] = a * w0 + c * h1 + tx; + vertexData[3] = d * h1 + b * w0 + ty; + + // xy + vertexData[4] = a * w0 + c * h0 + tx; + vertexData[5] = d * h0 + b * w0 + ty; + + // xy + vertexData[6] = a * w1 + c * h0 + tx; + vertexData[7] = d * h0 + b * w1 + ty; + + +} + /** * * Renders the object using the WebGL renderer @@ -203,6 +258,24 @@ */ Sprite.prototype._renderWebGL = function (renderer) { + // if(this.textureDirty) + { + this.textureDirty = false; + + this._onTextureUpdate(); + + this.vertexDirty = true; + } + + //if(this.vertexDirty) + { + this.vertexDirty = false; + + // set the vertex data + this.caclulateVertices(); + + } + renderer.setObjectRenderer(renderer.plugins.sprite); renderer.plugins.sprite.render(this); }; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 6b95180..eab34bc 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -372,7 +372,7 @@ if(this.currentRenderTarget === this.renderTarget) { this.renderTarget.activate(); - this.gl.viewport(0, 0, this.width, this.height); + //this.gl.viewport(0, 0, this.width, this.height); } }; diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 61cc8ae..58ab2e5 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -1,7 +1,10 @@ var math = require('../../../math'), utils = require('../../../utils'), CONST = require('../../../const'), - //StencilManager = require('../managers/StencilManager'), + + GLTexture = require('pixi-gl-core').GLTexture, + GLFramebuffer = require('pixi-gl-core').GLFramebuffer, + StencilMaskStack = require('./StencilMaskStack'); /** @@ -124,42 +127,31 @@ */ this.root = root; + this.frameBuffer = new GLFramebuffer(gl); + if (!this.root) { - // this.flipY = true; - this.frameBuffer = gl.createFramebuffer(); - /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. */ + + // create a texture to bind attach to the frameBuffer.. + var texture = new GLTexture(gl); - this.texture = gl.createTexture(); + texture.enableLinearScaling() + texture.enableWrapClamp() - gl.bindTexture(gl.TEXTURE_2D, this.texture); + this.frameBuffer.enableTexture(texture); - // set the scale properties of the texture.. - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST); - - // check to see if the texture is a power of two! - var isPowerOfTwo = utils.isPowerOfTwo(width, height); - - //TODO for 99% of use cases if a texture is power of two we should tile the texture... - if (!isPowerOfTwo) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0); + // TODO change! + // this is used by the base texture + this.texture = texture.texture; + } + else + { + // make it a null framebuffer.. + this.frameBuffer.framebuffer = null; } this.resize(width, height); @@ -173,16 +165,9 @@ * * @param [bind=false] {boolean} Should we bind our framebuffer before clearing? */ -RenderTarget.prototype.clear = function(bind) +RenderTarget.prototype.clear = function(r,g,b,a) { - var gl = this.gl; - if(bind) - { - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); - } - - gl.clearColor(0,0,0,0); - gl.clear(gl.COLOR_BUFFER_BIT); + this.frameBuffer.clear(1,1,1,1)//r,g,b,a); }; /** @@ -191,24 +176,14 @@ */ RenderTarget.prototype.attachStencilBuffer = function() { - - if (this.stencilBuffer) - { - return; - } - + //TODO check if stencil is done? /** * The stencil buffer is used for masking in pixi * lets create one and then add attach it to the framebuffer.. */ if (!this.root) { - var gl = this.gl; - - this.stencilBuffer = gl.createRenderbuffer(); - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.size.width * this.resolution , this.size.height * this.resolution ); + this.frameBuffer.enableStencil(); } }; @@ -221,7 +196,8 @@ //TOOD refactor usage of frame.. var gl = this.gl; - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); + this.frameBuffer.bind(); + var projectionFrame = this.frame || this.size; @@ -264,7 +240,6 @@ } }; - /** * Resizes the texture to the specified width and height * @@ -276,29 +251,16 @@ width = width | 0; height = height | 0; - if (this.size.width === width && this.size.height === height) { + if (this.size.width === width && this.size.height === height) + { return; } this.size.width = width; this.size.height = height; - if (!this.root) - { - var gl = this.gl; - - gl.bindTexture(gl.TEXTURE_2D, this.texture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width * this.resolution, height * this.resolution , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - if (this.stencilBuffer ) - { - // update the stencil buffer width and height - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width * this.resolution, height * this.resolution ); - } - } - + this.frameBuffer.resize(width * this.resolution, height * this.resolution); + var projectionFrame = this.frame || this.size; this.calculateProjection( projectionFrame ); @@ -311,9 +273,8 @@ RenderTarget.prototype.destroy = function () { var gl = this.gl; - gl.deleteRenderbuffer( this.stencilBuffer ); - gl.deleteFramebuffer( this.frameBuffer ); - gl.deleteTexture( this.texture ); + + this.frameBuffer.destroy(); this.frameBuffer = null; this.texture = null; diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 7440a0f..7701fda 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -92,6 +92,9 @@ // call texture setter this.texture = texture || Texture.EMPTY; + + this.vertexDirty = true; + this.vertexData = new Float32Array(8); } // constructor @@ -159,6 +162,8 @@ this._texture = value; this.cachedTint = 0xFFFFFF; + this.textureDirty = true; + if (value) { // wait for the texture to load @@ -194,6 +199,56 @@ } }; +Sprite.prototype.caclulateVertices = function () +{ + + var texture = this._texture, + wt = this.worldTransform, + a = wt.a, b = wt.b, c = wt.c, d = wt.d, tx = wt.tx, ty = wt.ty, + vertexData = this.vertexData, + aX = this.anchor.x, + aY = this.anchor.y, + w0, w1, h0, h1, + trim = texture.trim; + + if (trim) + { + // if the sprite is trimmed and is not a tilingsprite then we need to add the extra space before transforming the sprite coords.. + w1 = trim.x - aX * trim.width; + w0 = w1 + texture.crop.width; + + h1 = trim.y - aY * trim.height; + h0 = h1 + texture.crop.height; + + } + else + { + w0 = (texture._frame.width ) * (1-aX); + w1 = (texture._frame.width ) * -aX; + + h0 = texture._frame.height * (1-aY); + h1 = texture._frame.height * -aY; + } + + // xy + vertexData[0] = a * w1 + c * h1 + tx; + vertexData[1] = d * h1 + b * w1 + ty; + + // xy + vertexData[2] = a * w0 + c * h1 + tx; + vertexData[3] = d * h1 + b * w0 + ty; + + // xy + vertexData[4] = a * w0 + c * h0 + tx; + vertexData[5] = d * h0 + b * w0 + ty; + + // xy + vertexData[6] = a * w1 + c * h0 + tx; + vertexData[7] = d * h0 + b * w1 + ty; + + +} + /** * * Renders the object using the WebGL renderer @@ -203,6 +258,24 @@ */ Sprite.prototype._renderWebGL = function (renderer) { + // if(this.textureDirty) + { + this.textureDirty = false; + + this._onTextureUpdate(); + + this.vertexDirty = true; + } + + //if(this.vertexDirty) + { + this.vertexDirty = false; + + // set the vertex data + this.caclulateVertices(); + + } + renderer.setObjectRenderer(renderer.plugins.sprite); renderer.plugins.sprite.render(this); }; diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 8795d01..85a766d 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -1,6 +1,7 @@ var ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), TextureShader = require('../../renderers/webgl/shaders/_TextureShader'), + createIndicesForQuads = require('../../utils/createIndicesForQuads'), CONST = require('../../const'), glCore = require('pixi-gl-core'); @@ -71,6 +72,11 @@ */ this.positions = new Float32Array(this.vertices); + /** + * View on the vertices as a Uint32Array for uvs + * + * @member {Float32Array} + */ this.uvs = new Uint32Array(this.vertices); /** @@ -85,18 +91,7 @@ * * @member {Uint16Array} */ - this.indices = new Uint16Array(numIndices); - - // fill the indices with the quads to draw - 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; - } + this.indices = createIndicesForQuads(this.size) /** * The current size of the batch, each render() call adds to this number. @@ -153,8 +148,6 @@ this.vao.addAttribute(this.vertexBuffer, this._shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4); this.vao.addAttribute(this.vertexBuffer, this._shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4); - - this.currentBlendMode = 99999; }; @@ -165,8 +158,6 @@ */ SpriteRenderer.prototype.render = function (sprite) { - var texture = sprite._texture; - //TODO set blend modes.. // check texture.. if (this.currentBatchSize >= this.size) @@ -175,7 +166,7 @@ } // get the uvs for the texture - var uvs = texture._uvs; + var uvs = sprite.texture._uvs; // if the uvs have not updated then no point rendering just yet! if (!uvs) @@ -184,93 +175,28 @@ } // TODO trim?? - var aX = sprite.anchor.x; - var aY = sprite.anchor.y; - - var w0, w1, h0, h1; - - if (texture.trim && sprite.tileScale === undefined) - { - // if the sprite is trimmed and is not a tilingsprite then we need to add the extra space before transforming the sprite coords.. - var trim = texture.trim; - - w1 = trim.x - aX * trim.width; - w0 = w1 + texture.crop.width; - - h1 = trim.y - aY * trim.height; - h0 = h1 + texture.crop.height; - - } - else - { - w0 = (texture._frame.width ) * (1-aX); - w1 = (texture._frame.width ) * -aX; - - h0 = texture._frame.height * (1-aY); - h1 = texture._frame.height * -aY; - } - var index = this.currentBatchSize * this.vertByteSize; - var worldTransform = sprite.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - /* var a = worldTransform[0]; - var b = worldTransform[]; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty;*/ - var colors = this.colors; var positions = this.positions; - if (this.renderer.roundPixels) - { - - var resolution = this.renderer.resolution; - // console.log("<>") - // xy - positions[index] = (((a * w1 + c * h1 + tx) * resolution) | 0) / resolution; - positions[index+1] = (((d * h1 + b * w1 + ty) * resolution) | 0) / resolution; + var vertexData = sprite.vertexData - // xy - positions[index+5] = (((a * w0 + c * h1 + tx) * resolution) | 0) / resolution; - positions[index+6] = (((d * h1 + b * w0 + ty) * resolution) | 0) / resolution; + positions[index] = vertexData[0]; + positions[index+1] = vertexData[1]; - // xy - positions[index+10] = (((a * w0 + c * h0 + tx) * resolution) | 0) / resolution; - positions[index+11] = (((d * h0 + b * w0 + ty) * resolution) | 0) / resolution; + // xy + positions[index+4] = vertexData[2]; + positions[index+5] = vertexData[3]; - // xy - positions[index+15] = (((a * w1 + c * h0 + tx) * resolution) | 0) / resolution; - positions[index+16] = (((d * h0 + b * w1 + ty) * resolution) | 0) / resolution; - - } - else - { - // xy - positions[index] = a * w1 + c * h1 + tx; - positions[index+1] = d * h1 + b * w1 + ty; + // xy + positions[index+8] = vertexData[4]; + positions[index+9] = vertexData[5]; - // xy - positions[index+4] = a * w0 + c * h1 + tx; - positions[index+5] = d * h1 + b * w0 + ty; - - // xy - positions[index+8] = a * w0 + c * h0 + tx; - positions[index+9] = d * h0 + b * w0 + ty; - - // xy - positions[index+12] = a * w1 + c * h0 + tx; - positions[index+13] = d * h0 + b * w1 + ty; - } + // xy + positions[index+12] = vertexData[6]; + positions[index+13] = vertexData[7]; + // upload som uvs! this.uvs[index + 2] = uvs.uvs_uint32[0]; @@ -286,6 +212,14 @@ this.sprites[this.currentBatchSize++] = sprite; }; +SpriteRenderer.prototype.renderSprites = function (sprites) +{ + for (var i = 0; i < sprites.length; i++) + { + sprites[i] + }; +} + /** * Renders the content and empties the current batch. * @@ -355,8 +289,6 @@ { currentShader = nextShader; - - shader = currentShader.shaders ? currentShader.shaders[gl.id] : currentShader; if (!shader) @@ -365,23 +297,7 @@ } - // set shader function??? - // this.renderer.shaderManager.setShader(shader); - this.renderer.bindShader(this._shader); - - //gl.enableVertexAttribArray(1); - //this._shader.uniforms.projectionMatrix = this.renderer.currentRenderTarget.projectionMatrix.toArray(true); - - //TODO - i KNOW this can be optimised! Once v3 is stable il look at this next... - // shader.uniforms.projectionMatrix.value = this.renderer.currentRenderTarget.projectionMatrix.toArray(true); - //Make this a little more dynamic / intelligent! - // shader.syncUniforms(); - - //TODO investigate some kind of texture state managment?? - // need to make sure this texture is the active one for all the batch swaps.. - // gl.activeTexture(gl.TEXTURE0); - } } @@ -411,7 +327,9 @@ var gl = this.renderer.gl; - this.renderer.bindTexture(texture); + // bind the texture.. + this.renderer.bindTexture(texture, gl.TEXTURE0); + // now draw those suckas! gl.drawElements(gl.TRIANGLES, size * 6, gl.UNSIGNED_SHORT, startIndex * 6 * 2); }; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 6b95180..eab34bc 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -372,7 +372,7 @@ if(this.currentRenderTarget === this.renderTarget) { this.renderTarget.activate(); - this.gl.viewport(0, 0, this.width, this.height); + //this.gl.viewport(0, 0, this.width, this.height); } }; diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 61cc8ae..58ab2e5 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -1,7 +1,10 @@ var math = require('../../../math'), utils = require('../../../utils'), CONST = require('../../../const'), - //StencilManager = require('../managers/StencilManager'), + + GLTexture = require('pixi-gl-core').GLTexture, + GLFramebuffer = require('pixi-gl-core').GLFramebuffer, + StencilMaskStack = require('./StencilMaskStack'); /** @@ -124,42 +127,31 @@ */ this.root = root; + this.frameBuffer = new GLFramebuffer(gl); + if (!this.root) { - // this.flipY = true; - this.frameBuffer = gl.createFramebuffer(); - /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. */ + + // create a texture to bind attach to the frameBuffer.. + var texture = new GLTexture(gl); - this.texture = gl.createTexture(); + texture.enableLinearScaling() + texture.enableWrapClamp() - gl.bindTexture(gl.TEXTURE_2D, this.texture); + this.frameBuffer.enableTexture(texture); - // set the scale properties of the texture.. - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, scaleMode === CONST.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST); - - // check to see if the texture is a power of two! - var isPowerOfTwo = utils.isPowerOfTwo(width, height); - - //TODO for 99% of use cases if a texture is power of two we should tile the texture... - if (!isPowerOfTwo) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0); + // TODO change! + // this is used by the base texture + this.texture = texture.texture; + } + else + { + // make it a null framebuffer.. + this.frameBuffer.framebuffer = null; } this.resize(width, height); @@ -173,16 +165,9 @@ * * @param [bind=false] {boolean} Should we bind our framebuffer before clearing? */ -RenderTarget.prototype.clear = function(bind) +RenderTarget.prototype.clear = function(r,g,b,a) { - var gl = this.gl; - if(bind) - { - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); - } - - gl.clearColor(0,0,0,0); - gl.clear(gl.COLOR_BUFFER_BIT); + this.frameBuffer.clear(1,1,1,1)//r,g,b,a); }; /** @@ -191,24 +176,14 @@ */ RenderTarget.prototype.attachStencilBuffer = function() { - - if (this.stencilBuffer) - { - return; - } - + //TODO check if stencil is done? /** * The stencil buffer is used for masking in pixi * lets create one and then add attach it to the framebuffer.. */ if (!this.root) { - var gl = this.gl; - - this.stencilBuffer = gl.createRenderbuffer(); - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.size.width * this.resolution , this.size.height * this.resolution ); + this.frameBuffer.enableStencil(); } }; @@ -221,7 +196,8 @@ //TOOD refactor usage of frame.. var gl = this.gl; - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); + this.frameBuffer.bind(); + var projectionFrame = this.frame || this.size; @@ -264,7 +240,6 @@ } }; - /** * Resizes the texture to the specified width and height * @@ -276,29 +251,16 @@ width = width | 0; height = height | 0; - if (this.size.width === width && this.size.height === height) { + if (this.size.width === width && this.size.height === height) + { return; } this.size.width = width; this.size.height = height; - if (!this.root) - { - var gl = this.gl; - - gl.bindTexture(gl.TEXTURE_2D, this.texture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width * this.resolution, height * this.resolution , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - if (this.stencilBuffer ) - { - // update the stencil buffer width and height - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width * this.resolution, height * this.resolution ); - } - } - + this.frameBuffer.resize(width * this.resolution, height * this.resolution); + var projectionFrame = this.frame || this.size; this.calculateProjection( projectionFrame ); @@ -311,9 +273,8 @@ RenderTarget.prototype.destroy = function () { var gl = this.gl; - gl.deleteRenderbuffer( this.stencilBuffer ); - gl.deleteFramebuffer( this.frameBuffer ); - gl.deleteTexture( this.texture ); + + this.frameBuffer.destroy(); this.frameBuffer = null; this.texture = null; diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 7440a0f..7701fda 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -92,6 +92,9 @@ // call texture setter this.texture = texture || Texture.EMPTY; + + this.vertexDirty = true; + this.vertexData = new Float32Array(8); } // constructor @@ -159,6 +162,8 @@ this._texture = value; this.cachedTint = 0xFFFFFF; + this.textureDirty = true; + if (value) { // wait for the texture to load @@ -194,6 +199,56 @@ } }; +Sprite.prototype.caclulateVertices = function () +{ + + var texture = this._texture, + wt = this.worldTransform, + a = wt.a, b = wt.b, c = wt.c, d = wt.d, tx = wt.tx, ty = wt.ty, + vertexData = this.vertexData, + aX = this.anchor.x, + aY = this.anchor.y, + w0, w1, h0, h1, + trim = texture.trim; + + if (trim) + { + // if the sprite is trimmed and is not a tilingsprite then we need to add the extra space before transforming the sprite coords.. + w1 = trim.x - aX * trim.width; + w0 = w1 + texture.crop.width; + + h1 = trim.y - aY * trim.height; + h0 = h1 + texture.crop.height; + + } + else + { + w0 = (texture._frame.width ) * (1-aX); + w1 = (texture._frame.width ) * -aX; + + h0 = texture._frame.height * (1-aY); + h1 = texture._frame.height * -aY; + } + + // xy + vertexData[0] = a * w1 + c * h1 + tx; + vertexData[1] = d * h1 + b * w1 + ty; + + // xy + vertexData[2] = a * w0 + c * h1 + tx; + vertexData[3] = d * h1 + b * w0 + ty; + + // xy + vertexData[4] = a * w0 + c * h0 + tx; + vertexData[5] = d * h0 + b * w0 + ty; + + // xy + vertexData[6] = a * w1 + c * h0 + tx; + vertexData[7] = d * h0 + b * w1 + ty; + + +} + /** * * Renders the object using the WebGL renderer @@ -203,6 +258,24 @@ */ Sprite.prototype._renderWebGL = function (renderer) { + // if(this.textureDirty) + { + this.textureDirty = false; + + this._onTextureUpdate(); + + this.vertexDirty = true; + } + + //if(this.vertexDirty) + { + this.vertexDirty = false; + + // set the vertex data + this.caclulateVertices(); + + } + renderer.setObjectRenderer(renderer.plugins.sprite); renderer.plugins.sprite.render(this); }; diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 8795d01..85a766d 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -1,6 +1,7 @@ var ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), TextureShader = require('../../renderers/webgl/shaders/_TextureShader'), + createIndicesForQuads = require('../../utils/createIndicesForQuads'), CONST = require('../../const'), glCore = require('pixi-gl-core'); @@ -71,6 +72,11 @@ */ this.positions = new Float32Array(this.vertices); + /** + * View on the vertices as a Uint32Array for uvs + * + * @member {Float32Array} + */ this.uvs = new Uint32Array(this.vertices); /** @@ -85,18 +91,7 @@ * * @member {Uint16Array} */ - this.indices = new Uint16Array(numIndices); - - // fill the indices with the quads to draw - 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; - } + this.indices = createIndicesForQuads(this.size) /** * The current size of the batch, each render() call adds to this number. @@ -153,8 +148,6 @@ this.vao.addAttribute(this.vertexBuffer, this._shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4); this.vao.addAttribute(this.vertexBuffer, this._shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4); - - this.currentBlendMode = 99999; }; @@ -165,8 +158,6 @@ */ SpriteRenderer.prototype.render = function (sprite) { - var texture = sprite._texture; - //TODO set blend modes.. // check texture.. if (this.currentBatchSize >= this.size) @@ -175,7 +166,7 @@ } // get the uvs for the texture - var uvs = texture._uvs; + var uvs = sprite.texture._uvs; // if the uvs have not updated then no point rendering just yet! if (!uvs) @@ -184,93 +175,28 @@ } // TODO trim?? - var aX = sprite.anchor.x; - var aY = sprite.anchor.y; - - var w0, w1, h0, h1; - - if (texture.trim && sprite.tileScale === undefined) - { - // if the sprite is trimmed and is not a tilingsprite then we need to add the extra space before transforming the sprite coords.. - var trim = texture.trim; - - w1 = trim.x - aX * trim.width; - w0 = w1 + texture.crop.width; - - h1 = trim.y - aY * trim.height; - h0 = h1 + texture.crop.height; - - } - else - { - w0 = (texture._frame.width ) * (1-aX); - w1 = (texture._frame.width ) * -aX; - - h0 = texture._frame.height * (1-aY); - h1 = texture._frame.height * -aY; - } - var index = this.currentBatchSize * this.vertByteSize; - var worldTransform = sprite.worldTransform; - - var a = worldTransform.a; - var b = worldTransform.b; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - /* var a = worldTransform[0]; - var b = worldTransform[]; - var c = worldTransform.c; - var d = worldTransform.d; - var tx = worldTransform.tx; - var ty = worldTransform.ty;*/ - var colors = this.colors; var positions = this.positions; - if (this.renderer.roundPixels) - { - - var resolution = this.renderer.resolution; - // console.log("<>") - // xy - positions[index] = (((a * w1 + c * h1 + tx) * resolution) | 0) / resolution; - positions[index+1] = (((d * h1 + b * w1 + ty) * resolution) | 0) / resolution; + var vertexData = sprite.vertexData - // xy - positions[index+5] = (((a * w0 + c * h1 + tx) * resolution) | 0) / resolution; - positions[index+6] = (((d * h1 + b * w0 + ty) * resolution) | 0) / resolution; + positions[index] = vertexData[0]; + positions[index+1] = vertexData[1]; - // xy - positions[index+10] = (((a * w0 + c * h0 + tx) * resolution) | 0) / resolution; - positions[index+11] = (((d * h0 + b * w0 + ty) * resolution) | 0) / resolution; + // xy + positions[index+4] = vertexData[2]; + positions[index+5] = vertexData[3]; - // xy - positions[index+15] = (((a * w1 + c * h0 + tx) * resolution) | 0) / resolution; - positions[index+16] = (((d * h0 + b * w1 + ty) * resolution) | 0) / resolution; - - } - else - { - // xy - positions[index] = a * w1 + c * h1 + tx; - positions[index+1] = d * h1 + b * w1 + ty; + // xy + positions[index+8] = vertexData[4]; + positions[index+9] = vertexData[5]; - // xy - positions[index+4] = a * w0 + c * h1 + tx; - positions[index+5] = d * h1 + b * w0 + ty; - - // xy - positions[index+8] = a * w0 + c * h0 + tx; - positions[index+9] = d * h0 + b * w0 + ty; - - // xy - positions[index+12] = a * w1 + c * h0 + tx; - positions[index+13] = d * h0 + b * w1 + ty; - } + // xy + positions[index+12] = vertexData[6]; + positions[index+13] = vertexData[7]; + // upload som uvs! this.uvs[index + 2] = uvs.uvs_uint32[0]; @@ -286,6 +212,14 @@ this.sprites[this.currentBatchSize++] = sprite; }; +SpriteRenderer.prototype.renderSprites = function (sprites) +{ + for (var i = 0; i < sprites.length; i++) + { + sprites[i] + }; +} + /** * Renders the content and empties the current batch. * @@ -355,8 +289,6 @@ { currentShader = nextShader; - - shader = currentShader.shaders ? currentShader.shaders[gl.id] : currentShader; if (!shader) @@ -365,23 +297,7 @@ } - // set shader function??? - // this.renderer.shaderManager.setShader(shader); - this.renderer.bindShader(this._shader); - - //gl.enableVertexAttribArray(1); - //this._shader.uniforms.projectionMatrix = this.renderer.currentRenderTarget.projectionMatrix.toArray(true); - - //TODO - i KNOW this can be optimised! Once v3 is stable il look at this next... - // shader.uniforms.projectionMatrix.value = this.renderer.currentRenderTarget.projectionMatrix.toArray(true); - //Make this a little more dynamic / intelligent! - // shader.syncUniforms(); - - //TODO investigate some kind of texture state managment?? - // need to make sure this texture is the active one for all the batch swaps.. - // gl.activeTexture(gl.TEXTURE0); - } } @@ -411,7 +327,9 @@ var gl = this.renderer.gl; - this.renderer.bindTexture(texture); + // bind the texture.. + this.renderer.bindTexture(texture, gl.TEXTURE0); + // now draw those suckas! gl.drawElements(gl.TRIANGLES, size * 6, gl.UNSIGNED_SHORT, startIndex * 6 * 2); }; diff --git a/src/core/utils/createIndicesForQuads.js b/src/core/utils/createIndicesForQuads.js new file mode 100644 index 0000000..d5c980b --- /dev/null +++ b/src/core/utils/createIndicesForQuads.js @@ -0,0 +1,32 @@ +/** + * Generic Mask Stack data structure + * @class + * @memberof PIXI + */ + +var GL_MAP = {}; + + +var createIndicesForQuads = function (size) +{ + // the total number of indices in our array, there are 6 points per quad. + + var totalIndices = size * 6; + + var indices = new Uint16Array(totalIndices); + + // fill the indices with the quads to draw + for (var i=0, j=0; i < totalIndices; i += 6, j += 4) + { + indices[i + 0] = j + 0; + indices[i + 1] = j + 1; + indices[i + 2] = j + 2; + indices[i + 3] = j + 0; + indices[i + 4] = j + 2; + indices[i + 5] = j + 3; + } + + return indices; +}; + +module.exports = createIndicesForQuads; \ No newline at end of file