diff --git a/src/core/particles/webgl/ParticleRenderer.js b/src/core/particles/webgl/ParticleRenderer.js index 009c65d..ea55547 100644 --- a/src/core/particles/webgl/ParticleRenderer.js +++ b/src/core/particles/webgl/ParticleRenderer.js @@ -160,83 +160,20 @@ gl.uniformMatrix3fv(this.shader.uniforms.projectionMatrix._location, false, m.toArray(true)); - this.currentBatchSize = 0; -/* - var rotationDirty = false; - var positionDirty = false; - var vertsDirty = false; - var uvsDirty = false; - var alphaDirty = false;*/ - this.sprites = children; this.vertDirty = 0; - for (var i=0,j= children.length; i b2 * a1); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * The arc method creates an arc/curve (used to create circles, or parts of circles). - * - * @method arc - * @param cx {Number} The x-coordinate of the center of the circle - * @param cy {Number} The y-coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle) - * @param endAngle {Number} The ending angle, in radians - * @param anticlockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise. - * @return {Graphics} - */ -PIXI.Graphics.prototype.arc = function(cx, cy, radius, startAngle, endAngle, anticlockwise) -{ - var startX = cx + Math.cos(startAngle) * radius; - var startY = cy + Math.sin(startAngle) * radius; - var points; - - if( this.currentPath ) - { - points = this.currentPath.shape.points; - - if(points.length === 0) - { - points.push(startX, startY); - } - else if( points[points.length-2] !== startX || points[points.length-1] !== startY) - { - points.push(startX, startY); - } - } - else - { - this.moveTo(startX, startY); - points = this.currentPath.shape.points; - } - - if (startAngle === endAngle)return this; - - if( !anticlockwise && endAngle <= startAngle ) - { - endAngle += Math.PI * 2; - } - else if( anticlockwise && startAngle <= endAngle ) - { - startAngle += Math.PI * 2; - } - - var sweep = anticlockwise ? (startAngle - endAngle) *-1 : (endAngle - startAngle); - var segs = ( Math.abs(sweep)/ (Math.PI * 2) ) * 40; - - if( sweep === 0 ) return this; - - var theta = sweep/(segs*2); - var theta2 = theta*2; - - var cTheta = Math.cos(theta); - var sTheta = Math.sin(theta); - - var segMinus = segs - 1; - - var remainder = ( segMinus % 1 ) / segMinus; - - for(var i=0; i<=segMinus; i++) - { - var real = i + remainder * i; - - - var angle = ((theta) + startAngle + (theta2 * real)); - - var c = Math.cos(angle); - var s = -Math.sin(angle); - - points.push(( (cTheta * c) + (sTheta * s) ) * radius + cx, - ( (cTheta * -s) + (sTheta * c) ) * radius + cy); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {Number} the color of the fill - * @param alpha {Number} the alpha of the fill - * @return {Graphics} - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha === undefined) ? 1 : alpha; - - if(this.currentPath) - { - if(this.currentPath.shape.points.length <= 2) - { - this.currentPath.fill = this.filling; - this.currentPath.fillColor = this.fillColor; - this.currentPath.fillAlpha = this.fillAlpha; - } - } - return this; -}; - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - * @return {Graphics} - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; - - return this; -}; - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - this.drawShape(new PIXI.Rectangle(x,y, width, height)); - - return this; -}; - -/** - * @method drawRoundedRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @param radius {Number} Radius of the rectangle corners - */ -PIXI.Graphics.prototype.drawRoundedRect = function( x, y, width, height, radius ) -{ - this.drawShape(new PIXI.RoundedRectangle(x, y, width, height, radius)); - - return this; -}; - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coordinate of the center of the circle - * @param y {Number} The Y coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawCircle = function(x, y, radius) -{ - this.drawShape(new PIXI.Circle(x,y, radius)); - - return this; -}; - -/** - * Draws an ellipse. - * - * @method drawEllipse - * @param x {Number} The X coordinate of the center of the ellipse - * @param y {Number} The Y coordinate of the center of the ellipse - * @param width {Number} The half width of the ellipse - * @param height {Number} The half height of the ellipse - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawEllipse = function(x, y, width, height) -{ - this.drawShape(new PIXI.Ellipse(x, y, width, height)); - - return this; -}; - -/** - * Draws a polygon using the given path. - * - * @method drawPolygon - * @param path {Array} The path data used to construct the polygon. - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawPolygon = function(path) -{ - if(!(path instanceof Array))path = Array.prototype.slice.call(arguments); - this.drawShape(new PIXI.Polygon(path)); - return this; -}; - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - * @return {Graphics} - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = this.boundsDirty = true; - this.clearDirty = true; - this.graphicsData = []; - - return this; -}; - -/** - * Useful function that returns a texture of the graphics object that can then be used to create sprites - * This can be quite useful if your geometry is complicated and needs to be reused multiple times. - * - * @method generateTexture - * @param resolution {Number} The resolution of the texture being generated - * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts - * @return {Texture} a texture of the graphics object - */ -PIXI.Graphics.prototype.generateTexture = function(resolution, scaleMode) -{ - resolution = resolution || 1; - - var bounds = this.getBounds(); - - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width * resolution, bounds.height * resolution); - - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas, scaleMode); - texture.baseTexture.resolution = resolution; - - canvasBuffer.context.scale(resolution, resolution); - - canvasBuffer.context.translate(-bounds.x,-bounds.y); - - PIXI.CanvasGraphics.renderGraphics(this, canvasBuffer.context); - - return texture; -}; - -/** -* Renders the object using the WebGL renderer -* -* @method _renderWebGL -* @param renderSession {RenderSession} -* @private -*/ -PIXI.Graphics.prototype._renderWebGL = function(renderSession) -{ - // if the sprite is not visible or the alpha is 0 then no need to render this element - if(this.visible === false || this.alpha === 0 || this.isMask === true)return; - - if(this._cacheAsBitmap) - { - - if(this.dirty || this.cachedSpriteDirty) - { - - this._generateCachedSprite(); - - // we will also need to update the texture on the gpu too! - this.updateCachedSpriteTexture(); - - this.cachedSpriteDirty = false; - this.dirty = false; - } - - this._cachedSprite.worldAlpha = this.worldAlpha; - PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession); - - return; - } - else - { - renderSession.spriteBatch.stop(); - renderSession.blendModeManager.setBlendMode(this.blendMode); - - if(this._mask)renderSession.maskManager.pushMask(this._mask, renderSession); - if(this._filters)renderSession.filterManager.pushFilter(this._filterBlock); - - // check blend mode - if(this.blendMode !== renderSession.spriteBatch.currentBlendMode) - { - renderSession.spriteBatch.currentBlendMode = this.blendMode; - var blendModeWebGL = PIXI.blendModesWebGL[renderSession.spriteBatch.currentBlendMode]; - renderSession.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]); - } - - // check if the webgl graphic needs to be updated - if(this.webGLDirty) - { - this.dirty = true; - this.webGLDirty = false; - } - - PIXI.WebGLGraphics.renderGraphics(this, renderSession); - - // only render if it has children! - if(this.children.length) - { - renderSession.spriteBatch.start(); - - // simple render children! - for(var i=0, j=this.children.length; i maxX ? x2 : maxX; - maxX = x3 > maxX ? x3 : maxX; - maxX = x4 > maxX ? x4 : maxX; - - maxY = y2 > maxY ? y2 : maxY; - maxY = y3 > maxY ? y3 : maxY; - maxY = y4 > maxY ? y4 : maxY; - - this._bounds.x = minX; - this._bounds.width = maxX - minX; - - this._bounds.y = minY; - this._bounds.height = maxY - minY; - - return this._bounds; -}; - -/** - * Update the bounds of the object - * - * @method updateLocalBounds - */ -PIXI.Graphics.prototype.updateLocalBounds = function() -{ - var minX = Infinity; - var maxX = -Infinity; - - var minY = Infinity; - var maxY = -Infinity; - - - - if(this.graphicsData.length) - { - var shape, points, x, y, w, h; - - for (var i = 0; i < this.graphicsData.length; i++) { - var data = this.graphicsData[i]; - var type = data.type; - var lineWidth = data.lineWidth; - shape = data.shape; - - - if(type === PIXI.Graphics.RECT || type === PIXI.Graphics.RREC) - { - x = shape.x - lineWidth/2; - y = shape.y - lineWidth/2; - w = shape.width + lineWidth; - h = shape.height + lineWidth; - - minX = x < minX ? x : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y < minY ? y : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.CIRC) - { - x = shape.x; - y = shape.y; - w = shape.radius + lineWidth/2; - h = shape.radius + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.ELIP) - { - x = shape.x; - y = shape.y; - w = shape.width + lineWidth/2; - h = shape.height + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else - { - // POLY - points = shape.points; - - for (var j = 0; j < points.length; j+=2) - { - - x = points[j]; - y = points[j+1]; - minX = x-lineWidth < minX ? x-lineWidth : minX; - maxX = x+lineWidth > maxX ? x+lineWidth : maxX; - - minY = y-lineWidth < minY ? y-lineWidth : minY; - maxY = y+lineWidth > maxY ? y+lineWidth : maxY; - } - } - } - } - else - { - minX = 0; - maxX = 0; - minY = 0; - maxY = 0; - } - - var padding = this.boundsPadding; - - this._localBounds.x = minX - padding; - this._localBounds.width = (maxX - minX) + padding * 2; - - this._localBounds.y = minY - padding; - this._localBounds.height = (maxY - minY) + padding * 2; -}; - -/** - * Generates the cached sprite when the sprite has cacheAsBitmap = true - * - * @method _generateCachedSprite - * @private - */ -PIXI.Graphics.prototype._generateCachedSprite = function() -{ - var bounds = this.getLocalBounds(); - - if(!this._cachedSprite) - { - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height); - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas); - - this._cachedSprite = new PIXI.Sprite(texture); - this._cachedSprite.buffer = canvasBuffer; - - this._cachedSprite.worldTransform = this.worldTransform; - } - else - { - this._cachedSprite.buffer.resize(bounds.width, bounds.height); - } - - // leverage the anchor to account for the offset of the element - this._cachedSprite.anchor.x = -( bounds.x / bounds.width ); - this._cachedSprite.anchor.y = -( bounds.y / bounds.height ); - - // this._cachedSprite.buffer.context.save(); - this._cachedSprite.buffer.context.translate(-bounds.x,-bounds.y); - - // make sure we set the alpha of the graphics to 1 for the render.. - this.worldAlpha = 1; - - // now render the graphic.. - PIXI.CanvasGraphics.renderGraphics(this, this._cachedSprite.buffer.context); - this._cachedSprite.alpha = this.alpha; - -}; - -/** - * Updates texture size based on canvas size - * - * @method updateCachedSpriteTexture - * @private - */ -PIXI.Graphics.prototype.updateCachedSpriteTexture = function() -{ - var cachedSprite = this._cachedSprite; - var texture = cachedSprite.texture; - var canvas = cachedSprite.buffer.canvas; - - texture.baseTexture.width = canvas.width; - texture.baseTexture.height = canvas.height; - texture.crop.width = texture.frame.width = canvas.width; - texture.crop.height = texture.frame.height = canvas.height; - - cachedSprite._width = canvas.width; - cachedSprite._height = canvas.height; - - // update the dirty base textures - texture.baseTexture.dirty(); -}; - -/** - * Destroys a previous cached sprite. - * - * @method destroyCachedSprite - */ -PIXI.Graphics.prototype.destroyCachedSprite = function() -{ - this._cachedSprite.texture.destroy(true); - - // let the gc collect the unused sprite - // TODO could be object pooled! - this._cachedSprite = null; -}; - -/** - * Draws the given shape to this Graphics object. Can be any of Circle, Rectangle, Ellipse, Line or Polygon. - * - * @method drawShape - * @param {Circle|Rectangle|Ellipse|Line|Polygon} shape The Shape object to draw. - * @return {GraphicsData} The generated GraphicsData object. - */ -PIXI.Graphics.prototype.drawShape = function(shape) -{ - if(this.currentPath) - { - // check current path! - if(this.currentPath.shape.points.length <= 2)this.graphicsData.pop(); - } - - this.currentPath = null; - - var data = new PIXI.GraphicsData(this.lineWidth, this.lineColor, this.lineAlpha, this.fillColor, this.fillAlpha, this.filling, shape); - - this.graphicsData.push(data); - - if(data.type === PIXI.Graphics.POLY) - { - data.shape.closed = this.filling; - this.currentPath = data; - } - - this.dirty = this.boundsDirty = true; - - return data; -}; - -/** - * A GraphicsData object. - * - * @class GraphicsData - * @constructor - */ -PIXI.GraphicsData = function(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, shape) -{ - this.lineWidth = lineWidth; - this.lineColor = lineColor; - this.lineAlpha = lineAlpha; - this._lineTint = lineColor; - - this.fillColor = fillColor; - this.fillAlpha = fillAlpha; - this._fillTint = fillColor; - this.fill = fill; - - this.shape = shape; - this.type = shape.type; -}; - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; -PIXI.Graphics.RREC = 4; - -PIXI.Polygon.prototype.type = PIXI.Graphics.POLY; -PIXI.Rectangle.prototype.type = PIXI.Graphics.RECT; -PIXI.Circle.prototype.type = PIXI.Graphics.CIRC; -PIXI.Ellipse.prototype.type = PIXI.Graphics.ELIP; -PIXI.RoundedRectangle.prototype.type = PIXI.Graphics.RREC; - diff --git a/src/core/particles/webgl/ParticleRenderer.js b/src/core/particles/webgl/ParticleRenderer.js index 009c65d..ea55547 100644 --- a/src/core/particles/webgl/ParticleRenderer.js +++ b/src/core/particles/webgl/ParticleRenderer.js @@ -160,83 +160,20 @@ gl.uniformMatrix3fv(this.shader.uniforms.projectionMatrix._location, false, m.toArray(true)); - this.currentBatchSize = 0; -/* - var rotationDirty = false; - var positionDirty = false; - var vertsDirty = false; - var uvsDirty = false; - var alphaDirty = false;*/ - this.sprites = children; this.vertDirty = 0; - for (var i=0,j= children.length; i b2 * a1); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * The arc method creates an arc/curve (used to create circles, or parts of circles). - * - * @method arc - * @param cx {Number} The x-coordinate of the center of the circle - * @param cy {Number} The y-coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle) - * @param endAngle {Number} The ending angle, in radians - * @param anticlockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise. - * @return {Graphics} - */ -PIXI.Graphics.prototype.arc = function(cx, cy, radius, startAngle, endAngle, anticlockwise) -{ - var startX = cx + Math.cos(startAngle) * radius; - var startY = cy + Math.sin(startAngle) * radius; - var points; - - if( this.currentPath ) - { - points = this.currentPath.shape.points; - - if(points.length === 0) - { - points.push(startX, startY); - } - else if( points[points.length-2] !== startX || points[points.length-1] !== startY) - { - points.push(startX, startY); - } - } - else - { - this.moveTo(startX, startY); - points = this.currentPath.shape.points; - } - - if (startAngle === endAngle)return this; - - if( !anticlockwise && endAngle <= startAngle ) - { - endAngle += Math.PI * 2; - } - else if( anticlockwise && startAngle <= endAngle ) - { - startAngle += Math.PI * 2; - } - - var sweep = anticlockwise ? (startAngle - endAngle) *-1 : (endAngle - startAngle); - var segs = ( Math.abs(sweep)/ (Math.PI * 2) ) * 40; - - if( sweep === 0 ) return this; - - var theta = sweep/(segs*2); - var theta2 = theta*2; - - var cTheta = Math.cos(theta); - var sTheta = Math.sin(theta); - - var segMinus = segs - 1; - - var remainder = ( segMinus % 1 ) / segMinus; - - for(var i=0; i<=segMinus; i++) - { - var real = i + remainder * i; - - - var angle = ((theta) + startAngle + (theta2 * real)); - - var c = Math.cos(angle); - var s = -Math.sin(angle); - - points.push(( (cTheta * c) + (sTheta * s) ) * radius + cx, - ( (cTheta * -s) + (sTheta * c) ) * radius + cy); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {Number} the color of the fill - * @param alpha {Number} the alpha of the fill - * @return {Graphics} - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha === undefined) ? 1 : alpha; - - if(this.currentPath) - { - if(this.currentPath.shape.points.length <= 2) - { - this.currentPath.fill = this.filling; - this.currentPath.fillColor = this.fillColor; - this.currentPath.fillAlpha = this.fillAlpha; - } - } - return this; -}; - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - * @return {Graphics} - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; - - return this; -}; - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - this.drawShape(new PIXI.Rectangle(x,y, width, height)); - - return this; -}; - -/** - * @method drawRoundedRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @param radius {Number} Radius of the rectangle corners - */ -PIXI.Graphics.prototype.drawRoundedRect = function( x, y, width, height, radius ) -{ - this.drawShape(new PIXI.RoundedRectangle(x, y, width, height, radius)); - - return this; -}; - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coordinate of the center of the circle - * @param y {Number} The Y coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawCircle = function(x, y, radius) -{ - this.drawShape(new PIXI.Circle(x,y, radius)); - - return this; -}; - -/** - * Draws an ellipse. - * - * @method drawEllipse - * @param x {Number} The X coordinate of the center of the ellipse - * @param y {Number} The Y coordinate of the center of the ellipse - * @param width {Number} The half width of the ellipse - * @param height {Number} The half height of the ellipse - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawEllipse = function(x, y, width, height) -{ - this.drawShape(new PIXI.Ellipse(x, y, width, height)); - - return this; -}; - -/** - * Draws a polygon using the given path. - * - * @method drawPolygon - * @param path {Array} The path data used to construct the polygon. - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawPolygon = function(path) -{ - if(!(path instanceof Array))path = Array.prototype.slice.call(arguments); - this.drawShape(new PIXI.Polygon(path)); - return this; -}; - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - * @return {Graphics} - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = this.boundsDirty = true; - this.clearDirty = true; - this.graphicsData = []; - - return this; -}; - -/** - * Useful function that returns a texture of the graphics object that can then be used to create sprites - * This can be quite useful if your geometry is complicated and needs to be reused multiple times. - * - * @method generateTexture - * @param resolution {Number} The resolution of the texture being generated - * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts - * @return {Texture} a texture of the graphics object - */ -PIXI.Graphics.prototype.generateTexture = function(resolution, scaleMode) -{ - resolution = resolution || 1; - - var bounds = this.getBounds(); - - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width * resolution, bounds.height * resolution); - - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas, scaleMode); - texture.baseTexture.resolution = resolution; - - canvasBuffer.context.scale(resolution, resolution); - - canvasBuffer.context.translate(-bounds.x,-bounds.y); - - PIXI.CanvasGraphics.renderGraphics(this, canvasBuffer.context); - - return texture; -}; - -/** -* Renders the object using the WebGL renderer -* -* @method _renderWebGL -* @param renderSession {RenderSession} -* @private -*/ -PIXI.Graphics.prototype._renderWebGL = function(renderSession) -{ - // if the sprite is not visible or the alpha is 0 then no need to render this element - if(this.visible === false || this.alpha === 0 || this.isMask === true)return; - - if(this._cacheAsBitmap) - { - - if(this.dirty || this.cachedSpriteDirty) - { - - this._generateCachedSprite(); - - // we will also need to update the texture on the gpu too! - this.updateCachedSpriteTexture(); - - this.cachedSpriteDirty = false; - this.dirty = false; - } - - this._cachedSprite.worldAlpha = this.worldAlpha; - PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession); - - return; - } - else - { - renderSession.spriteBatch.stop(); - renderSession.blendModeManager.setBlendMode(this.blendMode); - - if(this._mask)renderSession.maskManager.pushMask(this._mask, renderSession); - if(this._filters)renderSession.filterManager.pushFilter(this._filterBlock); - - // check blend mode - if(this.blendMode !== renderSession.spriteBatch.currentBlendMode) - { - renderSession.spriteBatch.currentBlendMode = this.blendMode; - var blendModeWebGL = PIXI.blendModesWebGL[renderSession.spriteBatch.currentBlendMode]; - renderSession.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]); - } - - // check if the webgl graphic needs to be updated - if(this.webGLDirty) - { - this.dirty = true; - this.webGLDirty = false; - } - - PIXI.WebGLGraphics.renderGraphics(this, renderSession); - - // only render if it has children! - if(this.children.length) - { - renderSession.spriteBatch.start(); - - // simple render children! - for(var i=0, j=this.children.length; i maxX ? x2 : maxX; - maxX = x3 > maxX ? x3 : maxX; - maxX = x4 > maxX ? x4 : maxX; - - maxY = y2 > maxY ? y2 : maxY; - maxY = y3 > maxY ? y3 : maxY; - maxY = y4 > maxY ? y4 : maxY; - - this._bounds.x = minX; - this._bounds.width = maxX - minX; - - this._bounds.y = minY; - this._bounds.height = maxY - minY; - - return this._bounds; -}; - -/** - * Update the bounds of the object - * - * @method updateLocalBounds - */ -PIXI.Graphics.prototype.updateLocalBounds = function() -{ - var minX = Infinity; - var maxX = -Infinity; - - var minY = Infinity; - var maxY = -Infinity; - - - - if(this.graphicsData.length) - { - var shape, points, x, y, w, h; - - for (var i = 0; i < this.graphicsData.length; i++) { - var data = this.graphicsData[i]; - var type = data.type; - var lineWidth = data.lineWidth; - shape = data.shape; - - - if(type === PIXI.Graphics.RECT || type === PIXI.Graphics.RREC) - { - x = shape.x - lineWidth/2; - y = shape.y - lineWidth/2; - w = shape.width + lineWidth; - h = shape.height + lineWidth; - - minX = x < minX ? x : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y < minY ? y : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.CIRC) - { - x = shape.x; - y = shape.y; - w = shape.radius + lineWidth/2; - h = shape.radius + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.ELIP) - { - x = shape.x; - y = shape.y; - w = shape.width + lineWidth/2; - h = shape.height + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else - { - // POLY - points = shape.points; - - for (var j = 0; j < points.length; j+=2) - { - - x = points[j]; - y = points[j+1]; - minX = x-lineWidth < minX ? x-lineWidth : minX; - maxX = x+lineWidth > maxX ? x+lineWidth : maxX; - - minY = y-lineWidth < minY ? y-lineWidth : minY; - maxY = y+lineWidth > maxY ? y+lineWidth : maxY; - } - } - } - } - else - { - minX = 0; - maxX = 0; - minY = 0; - maxY = 0; - } - - var padding = this.boundsPadding; - - this._localBounds.x = minX - padding; - this._localBounds.width = (maxX - minX) + padding * 2; - - this._localBounds.y = minY - padding; - this._localBounds.height = (maxY - minY) + padding * 2; -}; - -/** - * Generates the cached sprite when the sprite has cacheAsBitmap = true - * - * @method _generateCachedSprite - * @private - */ -PIXI.Graphics.prototype._generateCachedSprite = function() -{ - var bounds = this.getLocalBounds(); - - if(!this._cachedSprite) - { - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height); - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas); - - this._cachedSprite = new PIXI.Sprite(texture); - this._cachedSprite.buffer = canvasBuffer; - - this._cachedSprite.worldTransform = this.worldTransform; - } - else - { - this._cachedSprite.buffer.resize(bounds.width, bounds.height); - } - - // leverage the anchor to account for the offset of the element - this._cachedSprite.anchor.x = -( bounds.x / bounds.width ); - this._cachedSprite.anchor.y = -( bounds.y / bounds.height ); - - // this._cachedSprite.buffer.context.save(); - this._cachedSprite.buffer.context.translate(-bounds.x,-bounds.y); - - // make sure we set the alpha of the graphics to 1 for the render.. - this.worldAlpha = 1; - - // now render the graphic.. - PIXI.CanvasGraphics.renderGraphics(this, this._cachedSprite.buffer.context); - this._cachedSprite.alpha = this.alpha; - -}; - -/** - * Updates texture size based on canvas size - * - * @method updateCachedSpriteTexture - * @private - */ -PIXI.Graphics.prototype.updateCachedSpriteTexture = function() -{ - var cachedSprite = this._cachedSprite; - var texture = cachedSprite.texture; - var canvas = cachedSprite.buffer.canvas; - - texture.baseTexture.width = canvas.width; - texture.baseTexture.height = canvas.height; - texture.crop.width = texture.frame.width = canvas.width; - texture.crop.height = texture.frame.height = canvas.height; - - cachedSprite._width = canvas.width; - cachedSprite._height = canvas.height; - - // update the dirty base textures - texture.baseTexture.dirty(); -}; - -/** - * Destroys a previous cached sprite. - * - * @method destroyCachedSprite - */ -PIXI.Graphics.prototype.destroyCachedSprite = function() -{ - this._cachedSprite.texture.destroy(true); - - // let the gc collect the unused sprite - // TODO could be object pooled! - this._cachedSprite = null; -}; - -/** - * Draws the given shape to this Graphics object. Can be any of Circle, Rectangle, Ellipse, Line or Polygon. - * - * @method drawShape - * @param {Circle|Rectangle|Ellipse|Line|Polygon} shape The Shape object to draw. - * @return {GraphicsData} The generated GraphicsData object. - */ -PIXI.Graphics.prototype.drawShape = function(shape) -{ - if(this.currentPath) - { - // check current path! - if(this.currentPath.shape.points.length <= 2)this.graphicsData.pop(); - } - - this.currentPath = null; - - var data = new PIXI.GraphicsData(this.lineWidth, this.lineColor, this.lineAlpha, this.fillColor, this.fillAlpha, this.filling, shape); - - this.graphicsData.push(data); - - if(data.type === PIXI.Graphics.POLY) - { - data.shape.closed = this.filling; - this.currentPath = data; - } - - this.dirty = this.boundsDirty = true; - - return data; -}; - -/** - * A GraphicsData object. - * - * @class GraphicsData - * @constructor - */ -PIXI.GraphicsData = function(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, shape) -{ - this.lineWidth = lineWidth; - this.lineColor = lineColor; - this.lineAlpha = lineAlpha; - this._lineTint = lineColor; - - this.fillColor = fillColor; - this.fillAlpha = fillAlpha; - this._fillTint = fillColor; - this.fill = fill; - - this.shape = shape; - this.type = shape.type; -}; - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; -PIXI.Graphics.RREC = 4; - -PIXI.Polygon.prototype.type = PIXI.Graphics.POLY; -PIXI.Rectangle.prototype.type = PIXI.Graphics.RECT; -PIXI.Circle.prototype.type = PIXI.Graphics.CIRC; -PIXI.Ellipse.prototype.type = PIXI.Graphics.ELIP; -PIXI.RoundedRectangle.prototype.type = PIXI.Graphics.RREC; - diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js deleted file mode 100644 index 82dbc05..0000000 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ /dev/null @@ -1,558 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.glContexts = []; // this is where we store the webGL contexts for easy access. -PIXI.instances = []; - -/** - * The WebGLRenderer draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers that support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batches or Sprite Clouds. - * Don't forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param [width=0] {Number} the width of the canvas view - * @param [height=0] {Number} the height of the canvas view - * @param [options] {Object} The optional renderer parameters - * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional - * @param [options.transparent=false] {Boolean} If the render view is transparent, default false - * @param [options.autoResize=false] {Boolean} If the render view is automatically resized, default false - * @param [options.antialias=false] {Boolean} sets antialias (only applicable in chrome at the moment) - * @param [options.preserveDrawingBuffer=false] {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context - * @param [options.resolution=1] {Number} the resolution of the renderer retina would be 2 - */ -PIXI.WebGLRenderer = function(width, height, options) -{ - if(options) - { - for (var i in PIXI.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') options[i] = PIXI.defaultRenderOptions[i]; - } - } - else - { - options = PIXI.defaultRenderOptions; - } - - if(!PIXI.defaultRenderer) - { - PIXI.sayHello('webGL'); - PIXI.defaultRenderer = this; - } - - /** - * @property type - * @type Number - */ - this.type = PIXI.WEBGL_RENDERER; - - /** - * The resolution of the renderer - * - * @property resolution - * @type Number - * @default 1 - */ - this.resolution = options.resolution; - - // do a catch.. only 1 webGL renderer.. - - /** - * Whether the render view is transparent - * - * @property transparent - * @type Boolean - */ - this.transparent = options.transparent; - - /** - * Whether the render view should be resized automatically - * - * @property autoResize - * @type Boolean - */ - this.autoResize = options.autoResize || false; - - /** - * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. - * - * @property preserveDrawingBuffer - * @type Boolean - */ - this.preserveDrawingBuffer = options.preserveDrawingBuffer; - - /** - * This sets if the WebGLRenderer will clear the context texture or not before the new render pass. If true: - * If the Stage is NOT transparent, Pixi will clear to alpha (0, 0, 0, 0). - * If the Stage is transparent, Pixi will clear to the target Stage's background color. - * Disable this by setting this to false. For example: if your game has a canvas filling background image, you often don't need this set. - * - * @property clearBeforeRender - * @type Boolean - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that everything is drawn to - * - * @property view - * @type HTMLCanvasElement - */ - this.view = options.view || document.createElement( 'canvas' ); - - // deal with losing context.. - - /** - * @property contextLostBound - * @type Function - */ - this.contextLostBound = this.handleContextLost.bind(this); - - /** - * @property contextRestoredBound - * @type Function - */ - this.contextRestoredBound = this.handleContextRestored.bind(this); - - this.view.addEventListener('webglcontextlost', this.contextLostBound, false); - this.view.addEventListener('webglcontextrestored', this.contextRestoredBound, false); - - /** - * @property _contextOptions - * @type Object - * @private - */ - this._contextOptions = { - alpha: this.transparent, - antialias: options.antialias, // SPEED UP?? - premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', - stencil:true, - preserveDrawingBuffer: options.preserveDrawingBuffer - }; - - /** - * @property projection - * @type Point - */ - this.projection = new PIXI.Point(); - - /** - * @property offset - * @type Point - */ - this.offset = new PIXI.Point(0, 0); - - // time to create the render managers! each one focuses on managing a state in webGL - - /** - * Deals with managing the shader programs and their attribs - * @property shaderManager - * @type WebGLShaderManager - */ - this.shaderManager = new PIXI.WebGLShaderManager(); - - /** - * Manages the rendering of sprites - * @property spriteBatch - * @type WebGLSpriteBatch - */ - this.spriteBatch = new PIXI.WebGLSpriteBatch(); - - /** - * Manages the masks using the stencil buffer - * @property maskManager - * @type WebGLMaskManager - */ - this.maskManager = new PIXI.WebGLMaskManager(); - - /** - * Manages the filters - * @property filterManager - * @type WebGLFilterManager - */ - this.filterManager = new PIXI.WebGLFilterManager(); - - /** - * Manages the stencil buffer - * @property stencilManager - * @type WebGLStencilManager - */ - this.stencilManager = new PIXI.WebGLStencilManager(); - - /** - * Manages the blendModes - * @property blendModeManager - * @type WebGLBlendModeManager - */ - this.blendModeManager = new PIXI.WebGLBlendModeManager(); - - /** - * TODO remove - * @property renderSession - * @type Object - */ - this.renderSession = {}; - this.renderSession.gl = this.gl; - this.renderSession.drawCount = 0; - this.renderSession.shaderManager = this.shaderManager; - this.renderSession.maskManager = this.maskManager; - this.renderSession.filterManager = this.filterManager; - this.renderSession.blendModeManager = this.blendModeManager; - this.renderSession.spriteBatch = this.spriteBatch; - this.renderSession.stencilManager = this.stencilManager; - this.renderSession.renderer = this; - this.renderSession.resolution = this.resolution; - this.renderSession.buffer = null; - - // time init the context.. - this.initContext(); - - // map some webGL blend modes.. - this.mapBlendModes(); -}; - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** -* @method initContext -*/ -PIXI.WebGLRenderer.prototype.initContext = function() -{ - var gl = this.view.getContext('webgl', this._contextOptions) || this.view.getContext('experimental-webgl', this._contextOptions); - this.gl = gl; - - if (!gl) { - // fail, not able to get a context - throw new Error('This browser does not support webGL. Try using the canvas renderer'); - } - - this.glContextId = gl.id = PIXI.WebGLRenderer.glContextId ++; - - PIXI.glContexts[this.glContextId] = gl; - - PIXI.instances[this.glContextId] = this; - - // set up the default pixi settings.. - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); - - // need to set the context for all the managers... - this.shaderManager.setContext(gl); - this.spriteBatch.setContext(gl); - this.maskManager.setContext(gl); - this.filterManager.setContext(gl); - this.blendModeManager.setContext(gl); - this.stencilManager.setContext(gl); - - this.renderSession.gl = this.gl; - - // now resize and we are good to go! - this.resize(this.width, this.height); -}; - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - // no point rendering if our context has been blown up! - if(this.contextLost)return; - - // if rendering a new stage clear the batches.. - if(this.__stage !== stage) - { - if(stage.interactive)stage.interactionManager.removeEvents(); - - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - } - - // update the scene graph - stage.updateTransform(); - - var gl = this.gl; - - // interaction - if(stage._interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - else - { - if(stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = false; - stage.interactionManager.setTarget(this); - } - } - - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - - // make sure we are bound to the main frame buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - if (this.clearBeforeRender) - { - if(this.transparent) - { - gl.clearColor(0, 0, 0, 0); - } - else - { - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); - } - - gl.clear (gl.COLOR_BUFFER_BIT); - } - - this.renderDisplayObject( stage, this.projection ); -}; - -/** - * Renders a Display Object. - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The DisplayObject to render - * @param projection {Point} The projection - * @param buffer {Array} a standard WebGL buffer - */ -PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection, buffer) -{ - this.renderSession.blendModeManager.setBlendMode(PIXI.blendModes.NORMAL); - - // reset the render session data.. - this.renderSession.drawCount = 0; - - // set the buffer ref.. - this.renderSession.buffer = buffer; - - // make sure to flip the Y if using a render texture.. - this.renderSession.flipY = buffer ? -1 : 1; - - // set the default projection - this.renderSession.projection = projection; - - //set the default offset - this.renderSession.offset = this.offset; - - // start the sprite batch - this.spriteBatch.begin(this.renderSession); - - // start the filter manager - this.filterManager.begin(this.renderSession, buffer); - - // render the scene! - displayObject._renderWebGL(this.renderSession); - - // finish the sprite batch - this.spriteBatch.end(); -}; - -/** - * Resizes the webGL view to the specified width and height. - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width * this.resolution; - this.height = height * this.resolution; - - this.view.width = this.width; - this.view.height = this.height; - - if (this.autoResize) { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } - - this.gl.viewport(0, 0, this.width, this.height); - - this.projection.x = this.width / 2 / this.resolution; - this.projection.y = -this.height / 2 / this.resolution; -}; - -/** - * Updates and Creates a WebGL texture for the renderers context. - * - * @method updateTexture - * @param texture {Texture} the texture to update - */ -PIXI.WebGLRenderer.prototype.updateTexture = function(texture) -{ - if(!texture.hasLoaded )return; - - var gl = this.gl; - - if(!texture._glTextures[gl.id])texture._glTextures[gl.id] = gl.createTexture(); - - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - - - if(texture.mipmap && PIXI.isPowerOfTwo(texture.width, texture.height)) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); - gl.generateMipmap(gl.TEXTURE_2D); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - } - - // reguler... - if(!texture._powerOf2) - { - 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); - } - - texture._dirty[gl.id] = false; - - return texture._glTextures[gl.id]; -}; - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -}; - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function() -{ - this.initContext(); - - // empty all the ol gl textures as they are useless now - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTextures = []; - } - - this.contextLost = false; -}; - -/** - * Removes everything from the renderer (event listeners, spritebatch, etc...) - * - * @method destroy - */ -PIXI.WebGLRenderer.prototype.destroy = function() -{ - // remove listeners - this.view.removeEventListener('webglcontextlost', this.contextLostBound); - this.view.removeEventListener('webglcontextrestored', this.contextRestoredBound); - - PIXI.glContexts[this.glContextId] = null; - - this.projection = null; - this.offset = null; - - // time to create the render managers! each one focuses on managine a state in webGL - this.shaderManager.destroy(); - this.spriteBatch.destroy(); - this.maskManager.destroy(); - this.filterManager.destroy(); - - this.shaderManager = null; - this.spriteBatch = null; - this.maskManager = null; - this.filterManager = null; - - this.gl = null; - this.renderSession = null; -}; - -/** - * Maps Pixi blend modes to WebGL blend modes. - * - * @method mapBlendModes - */ -PIXI.WebGLRenderer.prototype.mapBlendModes = function() -{ - var gl = this.gl; - - if(!PIXI.blendModesWebGL) - { - PIXI.blendModesWebGL = []; - - PIXI.blendModesWebGL[PIXI.blendModes.NORMAL] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.ADD] = [gl.SRC_ALPHA, gl.DST_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.MULTIPLY] = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SCREEN] = [gl.SRC_ALPHA, gl.ONE]; - PIXI.blendModesWebGL[PIXI.blendModes.OVERLAY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DARKEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LIGHTEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_DODGE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_BURN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HARD_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SOFT_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DIFFERENCE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.EXCLUSION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HUE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - } -}; - -PIXI.WebGLRenderer.glContextId = 0; diff --git a/src/core/particles/webgl/ParticleRenderer.js b/src/core/particles/webgl/ParticleRenderer.js index 009c65d..ea55547 100644 --- a/src/core/particles/webgl/ParticleRenderer.js +++ b/src/core/particles/webgl/ParticleRenderer.js @@ -160,83 +160,20 @@ gl.uniformMatrix3fv(this.shader.uniforms.projectionMatrix._location, false, m.toArray(true)); - this.currentBatchSize = 0; -/* - var rotationDirty = false; - var positionDirty = false; - var vertsDirty = false; - var uvsDirty = false; - var alphaDirty = false;*/ - this.sprites = children; this.vertDirty = 0; - for (var i=0,j= children.length; i b2 * a1); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * The arc method creates an arc/curve (used to create circles, or parts of circles). - * - * @method arc - * @param cx {Number} The x-coordinate of the center of the circle - * @param cy {Number} The y-coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle) - * @param endAngle {Number} The ending angle, in radians - * @param anticlockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise. - * @return {Graphics} - */ -PIXI.Graphics.prototype.arc = function(cx, cy, radius, startAngle, endAngle, anticlockwise) -{ - var startX = cx + Math.cos(startAngle) * radius; - var startY = cy + Math.sin(startAngle) * radius; - var points; - - if( this.currentPath ) - { - points = this.currentPath.shape.points; - - if(points.length === 0) - { - points.push(startX, startY); - } - else if( points[points.length-2] !== startX || points[points.length-1] !== startY) - { - points.push(startX, startY); - } - } - else - { - this.moveTo(startX, startY); - points = this.currentPath.shape.points; - } - - if (startAngle === endAngle)return this; - - if( !anticlockwise && endAngle <= startAngle ) - { - endAngle += Math.PI * 2; - } - else if( anticlockwise && startAngle <= endAngle ) - { - startAngle += Math.PI * 2; - } - - var sweep = anticlockwise ? (startAngle - endAngle) *-1 : (endAngle - startAngle); - var segs = ( Math.abs(sweep)/ (Math.PI * 2) ) * 40; - - if( sweep === 0 ) return this; - - var theta = sweep/(segs*2); - var theta2 = theta*2; - - var cTheta = Math.cos(theta); - var sTheta = Math.sin(theta); - - var segMinus = segs - 1; - - var remainder = ( segMinus % 1 ) / segMinus; - - for(var i=0; i<=segMinus; i++) - { - var real = i + remainder * i; - - - var angle = ((theta) + startAngle + (theta2 * real)); - - var c = Math.cos(angle); - var s = -Math.sin(angle); - - points.push(( (cTheta * c) + (sTheta * s) ) * radius + cx, - ( (cTheta * -s) + (sTheta * c) ) * radius + cy); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {Number} the color of the fill - * @param alpha {Number} the alpha of the fill - * @return {Graphics} - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha === undefined) ? 1 : alpha; - - if(this.currentPath) - { - if(this.currentPath.shape.points.length <= 2) - { - this.currentPath.fill = this.filling; - this.currentPath.fillColor = this.fillColor; - this.currentPath.fillAlpha = this.fillAlpha; - } - } - return this; -}; - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - * @return {Graphics} - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; - - return this; -}; - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - this.drawShape(new PIXI.Rectangle(x,y, width, height)); - - return this; -}; - -/** - * @method drawRoundedRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @param radius {Number} Radius of the rectangle corners - */ -PIXI.Graphics.prototype.drawRoundedRect = function( x, y, width, height, radius ) -{ - this.drawShape(new PIXI.RoundedRectangle(x, y, width, height, radius)); - - return this; -}; - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coordinate of the center of the circle - * @param y {Number} The Y coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawCircle = function(x, y, radius) -{ - this.drawShape(new PIXI.Circle(x,y, radius)); - - return this; -}; - -/** - * Draws an ellipse. - * - * @method drawEllipse - * @param x {Number} The X coordinate of the center of the ellipse - * @param y {Number} The Y coordinate of the center of the ellipse - * @param width {Number} The half width of the ellipse - * @param height {Number} The half height of the ellipse - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawEllipse = function(x, y, width, height) -{ - this.drawShape(new PIXI.Ellipse(x, y, width, height)); - - return this; -}; - -/** - * Draws a polygon using the given path. - * - * @method drawPolygon - * @param path {Array} The path data used to construct the polygon. - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawPolygon = function(path) -{ - if(!(path instanceof Array))path = Array.prototype.slice.call(arguments); - this.drawShape(new PIXI.Polygon(path)); - return this; -}; - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - * @return {Graphics} - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = this.boundsDirty = true; - this.clearDirty = true; - this.graphicsData = []; - - return this; -}; - -/** - * Useful function that returns a texture of the graphics object that can then be used to create sprites - * This can be quite useful if your geometry is complicated and needs to be reused multiple times. - * - * @method generateTexture - * @param resolution {Number} The resolution of the texture being generated - * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts - * @return {Texture} a texture of the graphics object - */ -PIXI.Graphics.prototype.generateTexture = function(resolution, scaleMode) -{ - resolution = resolution || 1; - - var bounds = this.getBounds(); - - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width * resolution, bounds.height * resolution); - - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas, scaleMode); - texture.baseTexture.resolution = resolution; - - canvasBuffer.context.scale(resolution, resolution); - - canvasBuffer.context.translate(-bounds.x,-bounds.y); - - PIXI.CanvasGraphics.renderGraphics(this, canvasBuffer.context); - - return texture; -}; - -/** -* Renders the object using the WebGL renderer -* -* @method _renderWebGL -* @param renderSession {RenderSession} -* @private -*/ -PIXI.Graphics.prototype._renderWebGL = function(renderSession) -{ - // if the sprite is not visible or the alpha is 0 then no need to render this element - if(this.visible === false || this.alpha === 0 || this.isMask === true)return; - - if(this._cacheAsBitmap) - { - - if(this.dirty || this.cachedSpriteDirty) - { - - this._generateCachedSprite(); - - // we will also need to update the texture on the gpu too! - this.updateCachedSpriteTexture(); - - this.cachedSpriteDirty = false; - this.dirty = false; - } - - this._cachedSprite.worldAlpha = this.worldAlpha; - PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession); - - return; - } - else - { - renderSession.spriteBatch.stop(); - renderSession.blendModeManager.setBlendMode(this.blendMode); - - if(this._mask)renderSession.maskManager.pushMask(this._mask, renderSession); - if(this._filters)renderSession.filterManager.pushFilter(this._filterBlock); - - // check blend mode - if(this.blendMode !== renderSession.spriteBatch.currentBlendMode) - { - renderSession.spriteBatch.currentBlendMode = this.blendMode; - var blendModeWebGL = PIXI.blendModesWebGL[renderSession.spriteBatch.currentBlendMode]; - renderSession.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]); - } - - // check if the webgl graphic needs to be updated - if(this.webGLDirty) - { - this.dirty = true; - this.webGLDirty = false; - } - - PIXI.WebGLGraphics.renderGraphics(this, renderSession); - - // only render if it has children! - if(this.children.length) - { - renderSession.spriteBatch.start(); - - // simple render children! - for(var i=0, j=this.children.length; i maxX ? x2 : maxX; - maxX = x3 > maxX ? x3 : maxX; - maxX = x4 > maxX ? x4 : maxX; - - maxY = y2 > maxY ? y2 : maxY; - maxY = y3 > maxY ? y3 : maxY; - maxY = y4 > maxY ? y4 : maxY; - - this._bounds.x = minX; - this._bounds.width = maxX - minX; - - this._bounds.y = minY; - this._bounds.height = maxY - minY; - - return this._bounds; -}; - -/** - * Update the bounds of the object - * - * @method updateLocalBounds - */ -PIXI.Graphics.prototype.updateLocalBounds = function() -{ - var minX = Infinity; - var maxX = -Infinity; - - var minY = Infinity; - var maxY = -Infinity; - - - - if(this.graphicsData.length) - { - var shape, points, x, y, w, h; - - for (var i = 0; i < this.graphicsData.length; i++) { - var data = this.graphicsData[i]; - var type = data.type; - var lineWidth = data.lineWidth; - shape = data.shape; - - - if(type === PIXI.Graphics.RECT || type === PIXI.Graphics.RREC) - { - x = shape.x - lineWidth/2; - y = shape.y - lineWidth/2; - w = shape.width + lineWidth; - h = shape.height + lineWidth; - - minX = x < minX ? x : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y < minY ? y : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.CIRC) - { - x = shape.x; - y = shape.y; - w = shape.radius + lineWidth/2; - h = shape.radius + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.ELIP) - { - x = shape.x; - y = shape.y; - w = shape.width + lineWidth/2; - h = shape.height + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else - { - // POLY - points = shape.points; - - for (var j = 0; j < points.length; j+=2) - { - - x = points[j]; - y = points[j+1]; - minX = x-lineWidth < minX ? x-lineWidth : minX; - maxX = x+lineWidth > maxX ? x+lineWidth : maxX; - - minY = y-lineWidth < minY ? y-lineWidth : minY; - maxY = y+lineWidth > maxY ? y+lineWidth : maxY; - } - } - } - } - else - { - minX = 0; - maxX = 0; - minY = 0; - maxY = 0; - } - - var padding = this.boundsPadding; - - this._localBounds.x = minX - padding; - this._localBounds.width = (maxX - minX) + padding * 2; - - this._localBounds.y = minY - padding; - this._localBounds.height = (maxY - minY) + padding * 2; -}; - -/** - * Generates the cached sprite when the sprite has cacheAsBitmap = true - * - * @method _generateCachedSprite - * @private - */ -PIXI.Graphics.prototype._generateCachedSprite = function() -{ - var bounds = this.getLocalBounds(); - - if(!this._cachedSprite) - { - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height); - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas); - - this._cachedSprite = new PIXI.Sprite(texture); - this._cachedSprite.buffer = canvasBuffer; - - this._cachedSprite.worldTransform = this.worldTransform; - } - else - { - this._cachedSprite.buffer.resize(bounds.width, bounds.height); - } - - // leverage the anchor to account for the offset of the element - this._cachedSprite.anchor.x = -( bounds.x / bounds.width ); - this._cachedSprite.anchor.y = -( bounds.y / bounds.height ); - - // this._cachedSprite.buffer.context.save(); - this._cachedSprite.buffer.context.translate(-bounds.x,-bounds.y); - - // make sure we set the alpha of the graphics to 1 for the render.. - this.worldAlpha = 1; - - // now render the graphic.. - PIXI.CanvasGraphics.renderGraphics(this, this._cachedSprite.buffer.context); - this._cachedSprite.alpha = this.alpha; - -}; - -/** - * Updates texture size based on canvas size - * - * @method updateCachedSpriteTexture - * @private - */ -PIXI.Graphics.prototype.updateCachedSpriteTexture = function() -{ - var cachedSprite = this._cachedSprite; - var texture = cachedSprite.texture; - var canvas = cachedSprite.buffer.canvas; - - texture.baseTexture.width = canvas.width; - texture.baseTexture.height = canvas.height; - texture.crop.width = texture.frame.width = canvas.width; - texture.crop.height = texture.frame.height = canvas.height; - - cachedSprite._width = canvas.width; - cachedSprite._height = canvas.height; - - // update the dirty base textures - texture.baseTexture.dirty(); -}; - -/** - * Destroys a previous cached sprite. - * - * @method destroyCachedSprite - */ -PIXI.Graphics.prototype.destroyCachedSprite = function() -{ - this._cachedSprite.texture.destroy(true); - - // let the gc collect the unused sprite - // TODO could be object pooled! - this._cachedSprite = null; -}; - -/** - * Draws the given shape to this Graphics object. Can be any of Circle, Rectangle, Ellipse, Line or Polygon. - * - * @method drawShape - * @param {Circle|Rectangle|Ellipse|Line|Polygon} shape The Shape object to draw. - * @return {GraphicsData} The generated GraphicsData object. - */ -PIXI.Graphics.prototype.drawShape = function(shape) -{ - if(this.currentPath) - { - // check current path! - if(this.currentPath.shape.points.length <= 2)this.graphicsData.pop(); - } - - this.currentPath = null; - - var data = new PIXI.GraphicsData(this.lineWidth, this.lineColor, this.lineAlpha, this.fillColor, this.fillAlpha, this.filling, shape); - - this.graphicsData.push(data); - - if(data.type === PIXI.Graphics.POLY) - { - data.shape.closed = this.filling; - this.currentPath = data; - } - - this.dirty = this.boundsDirty = true; - - return data; -}; - -/** - * A GraphicsData object. - * - * @class GraphicsData - * @constructor - */ -PIXI.GraphicsData = function(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, shape) -{ - this.lineWidth = lineWidth; - this.lineColor = lineColor; - this.lineAlpha = lineAlpha; - this._lineTint = lineColor; - - this.fillColor = fillColor; - this.fillAlpha = fillAlpha; - this._fillTint = fillColor; - this.fill = fill; - - this.shape = shape; - this.type = shape.type; -}; - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; -PIXI.Graphics.RREC = 4; - -PIXI.Polygon.prototype.type = PIXI.Graphics.POLY; -PIXI.Rectangle.prototype.type = PIXI.Graphics.RECT; -PIXI.Circle.prototype.type = PIXI.Graphics.CIRC; -PIXI.Ellipse.prototype.type = PIXI.Graphics.ELIP; -PIXI.RoundedRectangle.prototype.type = PIXI.Graphics.RREC; - diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js deleted file mode 100644 index 82dbc05..0000000 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ /dev/null @@ -1,558 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.glContexts = []; // this is where we store the webGL contexts for easy access. -PIXI.instances = []; - -/** - * The WebGLRenderer draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers that support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batches or Sprite Clouds. - * Don't forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param [width=0] {Number} the width of the canvas view - * @param [height=0] {Number} the height of the canvas view - * @param [options] {Object} The optional renderer parameters - * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional - * @param [options.transparent=false] {Boolean} If the render view is transparent, default false - * @param [options.autoResize=false] {Boolean} If the render view is automatically resized, default false - * @param [options.antialias=false] {Boolean} sets antialias (only applicable in chrome at the moment) - * @param [options.preserveDrawingBuffer=false] {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context - * @param [options.resolution=1] {Number} the resolution of the renderer retina would be 2 - */ -PIXI.WebGLRenderer = function(width, height, options) -{ - if(options) - { - for (var i in PIXI.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') options[i] = PIXI.defaultRenderOptions[i]; - } - } - else - { - options = PIXI.defaultRenderOptions; - } - - if(!PIXI.defaultRenderer) - { - PIXI.sayHello('webGL'); - PIXI.defaultRenderer = this; - } - - /** - * @property type - * @type Number - */ - this.type = PIXI.WEBGL_RENDERER; - - /** - * The resolution of the renderer - * - * @property resolution - * @type Number - * @default 1 - */ - this.resolution = options.resolution; - - // do a catch.. only 1 webGL renderer.. - - /** - * Whether the render view is transparent - * - * @property transparent - * @type Boolean - */ - this.transparent = options.transparent; - - /** - * Whether the render view should be resized automatically - * - * @property autoResize - * @type Boolean - */ - this.autoResize = options.autoResize || false; - - /** - * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. - * - * @property preserveDrawingBuffer - * @type Boolean - */ - this.preserveDrawingBuffer = options.preserveDrawingBuffer; - - /** - * This sets if the WebGLRenderer will clear the context texture or not before the new render pass. If true: - * If the Stage is NOT transparent, Pixi will clear to alpha (0, 0, 0, 0). - * If the Stage is transparent, Pixi will clear to the target Stage's background color. - * Disable this by setting this to false. For example: if your game has a canvas filling background image, you often don't need this set. - * - * @property clearBeforeRender - * @type Boolean - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that everything is drawn to - * - * @property view - * @type HTMLCanvasElement - */ - this.view = options.view || document.createElement( 'canvas' ); - - // deal with losing context.. - - /** - * @property contextLostBound - * @type Function - */ - this.contextLostBound = this.handleContextLost.bind(this); - - /** - * @property contextRestoredBound - * @type Function - */ - this.contextRestoredBound = this.handleContextRestored.bind(this); - - this.view.addEventListener('webglcontextlost', this.contextLostBound, false); - this.view.addEventListener('webglcontextrestored', this.contextRestoredBound, false); - - /** - * @property _contextOptions - * @type Object - * @private - */ - this._contextOptions = { - alpha: this.transparent, - antialias: options.antialias, // SPEED UP?? - premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', - stencil:true, - preserveDrawingBuffer: options.preserveDrawingBuffer - }; - - /** - * @property projection - * @type Point - */ - this.projection = new PIXI.Point(); - - /** - * @property offset - * @type Point - */ - this.offset = new PIXI.Point(0, 0); - - // time to create the render managers! each one focuses on managing a state in webGL - - /** - * Deals with managing the shader programs and their attribs - * @property shaderManager - * @type WebGLShaderManager - */ - this.shaderManager = new PIXI.WebGLShaderManager(); - - /** - * Manages the rendering of sprites - * @property spriteBatch - * @type WebGLSpriteBatch - */ - this.spriteBatch = new PIXI.WebGLSpriteBatch(); - - /** - * Manages the masks using the stencil buffer - * @property maskManager - * @type WebGLMaskManager - */ - this.maskManager = new PIXI.WebGLMaskManager(); - - /** - * Manages the filters - * @property filterManager - * @type WebGLFilterManager - */ - this.filterManager = new PIXI.WebGLFilterManager(); - - /** - * Manages the stencil buffer - * @property stencilManager - * @type WebGLStencilManager - */ - this.stencilManager = new PIXI.WebGLStencilManager(); - - /** - * Manages the blendModes - * @property blendModeManager - * @type WebGLBlendModeManager - */ - this.blendModeManager = new PIXI.WebGLBlendModeManager(); - - /** - * TODO remove - * @property renderSession - * @type Object - */ - this.renderSession = {}; - this.renderSession.gl = this.gl; - this.renderSession.drawCount = 0; - this.renderSession.shaderManager = this.shaderManager; - this.renderSession.maskManager = this.maskManager; - this.renderSession.filterManager = this.filterManager; - this.renderSession.blendModeManager = this.blendModeManager; - this.renderSession.spriteBatch = this.spriteBatch; - this.renderSession.stencilManager = this.stencilManager; - this.renderSession.renderer = this; - this.renderSession.resolution = this.resolution; - this.renderSession.buffer = null; - - // time init the context.. - this.initContext(); - - // map some webGL blend modes.. - this.mapBlendModes(); -}; - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** -* @method initContext -*/ -PIXI.WebGLRenderer.prototype.initContext = function() -{ - var gl = this.view.getContext('webgl', this._contextOptions) || this.view.getContext('experimental-webgl', this._contextOptions); - this.gl = gl; - - if (!gl) { - // fail, not able to get a context - throw new Error('This browser does not support webGL. Try using the canvas renderer'); - } - - this.glContextId = gl.id = PIXI.WebGLRenderer.glContextId ++; - - PIXI.glContexts[this.glContextId] = gl; - - PIXI.instances[this.glContextId] = this; - - // set up the default pixi settings.. - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); - - // need to set the context for all the managers... - this.shaderManager.setContext(gl); - this.spriteBatch.setContext(gl); - this.maskManager.setContext(gl); - this.filterManager.setContext(gl); - this.blendModeManager.setContext(gl); - this.stencilManager.setContext(gl); - - this.renderSession.gl = this.gl; - - // now resize and we are good to go! - this.resize(this.width, this.height); -}; - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - // no point rendering if our context has been blown up! - if(this.contextLost)return; - - // if rendering a new stage clear the batches.. - if(this.__stage !== stage) - { - if(stage.interactive)stage.interactionManager.removeEvents(); - - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - } - - // update the scene graph - stage.updateTransform(); - - var gl = this.gl; - - // interaction - if(stage._interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - else - { - if(stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = false; - stage.interactionManager.setTarget(this); - } - } - - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - - // make sure we are bound to the main frame buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - if (this.clearBeforeRender) - { - if(this.transparent) - { - gl.clearColor(0, 0, 0, 0); - } - else - { - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); - } - - gl.clear (gl.COLOR_BUFFER_BIT); - } - - this.renderDisplayObject( stage, this.projection ); -}; - -/** - * Renders a Display Object. - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The DisplayObject to render - * @param projection {Point} The projection - * @param buffer {Array} a standard WebGL buffer - */ -PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection, buffer) -{ - this.renderSession.blendModeManager.setBlendMode(PIXI.blendModes.NORMAL); - - // reset the render session data.. - this.renderSession.drawCount = 0; - - // set the buffer ref.. - this.renderSession.buffer = buffer; - - // make sure to flip the Y if using a render texture.. - this.renderSession.flipY = buffer ? -1 : 1; - - // set the default projection - this.renderSession.projection = projection; - - //set the default offset - this.renderSession.offset = this.offset; - - // start the sprite batch - this.spriteBatch.begin(this.renderSession); - - // start the filter manager - this.filterManager.begin(this.renderSession, buffer); - - // render the scene! - displayObject._renderWebGL(this.renderSession); - - // finish the sprite batch - this.spriteBatch.end(); -}; - -/** - * Resizes the webGL view to the specified width and height. - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width * this.resolution; - this.height = height * this.resolution; - - this.view.width = this.width; - this.view.height = this.height; - - if (this.autoResize) { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } - - this.gl.viewport(0, 0, this.width, this.height); - - this.projection.x = this.width / 2 / this.resolution; - this.projection.y = -this.height / 2 / this.resolution; -}; - -/** - * Updates and Creates a WebGL texture for the renderers context. - * - * @method updateTexture - * @param texture {Texture} the texture to update - */ -PIXI.WebGLRenderer.prototype.updateTexture = function(texture) -{ - if(!texture.hasLoaded )return; - - var gl = this.gl; - - if(!texture._glTextures[gl.id])texture._glTextures[gl.id] = gl.createTexture(); - - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - - - if(texture.mipmap && PIXI.isPowerOfTwo(texture.width, texture.height)) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); - gl.generateMipmap(gl.TEXTURE_2D); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - } - - // reguler... - if(!texture._powerOf2) - { - 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); - } - - texture._dirty[gl.id] = false; - - return texture._glTextures[gl.id]; -}; - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -}; - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function() -{ - this.initContext(); - - // empty all the ol gl textures as they are useless now - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTextures = []; - } - - this.contextLost = false; -}; - -/** - * Removes everything from the renderer (event listeners, spritebatch, etc...) - * - * @method destroy - */ -PIXI.WebGLRenderer.prototype.destroy = function() -{ - // remove listeners - this.view.removeEventListener('webglcontextlost', this.contextLostBound); - this.view.removeEventListener('webglcontextrestored', this.contextRestoredBound); - - PIXI.glContexts[this.glContextId] = null; - - this.projection = null; - this.offset = null; - - // time to create the render managers! each one focuses on managine a state in webGL - this.shaderManager.destroy(); - this.spriteBatch.destroy(); - this.maskManager.destroy(); - this.filterManager.destroy(); - - this.shaderManager = null; - this.spriteBatch = null; - this.maskManager = null; - this.filterManager = null; - - this.gl = null; - this.renderSession = null; -}; - -/** - * Maps Pixi blend modes to WebGL blend modes. - * - * @method mapBlendModes - */ -PIXI.WebGLRenderer.prototype.mapBlendModes = function() -{ - var gl = this.gl; - - if(!PIXI.blendModesWebGL) - { - PIXI.blendModesWebGL = []; - - PIXI.blendModesWebGL[PIXI.blendModes.NORMAL] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.ADD] = [gl.SRC_ALPHA, gl.DST_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.MULTIPLY] = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SCREEN] = [gl.SRC_ALPHA, gl.ONE]; - PIXI.blendModesWebGL[PIXI.blendModes.OVERLAY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DARKEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LIGHTEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_DODGE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_BURN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HARD_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SOFT_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DIFFERENCE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.EXCLUSION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HUE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - } -}; - -PIXI.WebGLRenderer.glContextId = 0; diff --git a/src/pixi/renderers/webgl/shaders/PixiShader.js b/src/pixi/renderers/webgl/shaders/PixiShader.js deleted file mode 100644 index bb4a17d..0000000 --- a/src/pixi/renderers/webgl/shaders/PixiShader.js +++ /dev/null @@ -1,397 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * @author Richard Davey http://www.photonstorm.com @photonstorm - */ - -/** -* @class PixiShader -* @constructor -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.PixiShader = function(gl) -{ - /** - * @property _UID - * @type Number - * @private - */ - this._UID = PIXI._UID++; - - /** - * @property gl - * @type WebGLContext - */ - this.gl = gl; - - /** - * The WebGL program. - * @property program - * @type Any - */ - this.program = null; - - /** - * The fragment shader. - * @property fragmentSrc - * @type Array - */ - this.fragmentSrc = [ - 'precision lowp float;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - 'uniform sampler2D uSampler;', - 'void main(void) {', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;', - '}' - ]; - - /** - * A local texture counter for multi-texture shaders. - * @property textureCount - * @type Number - */ - this.textureCount = 0; - - /** - * A local flag - * @property firstRun - * @type Boolean - * @private - */ - this.firstRun = true; - - /** - * A dirty flag - * @property dirty - * @type Boolean - */ - this.dirty = true; - - /** - * Uniform attributes cache. - * @property attributes - * @type Array - * @private - */ - this.attributes = []; - - this.init(); -}; - -PIXI.PixiShader.prototype.constructor = PIXI.PixiShader; - -/** -* Initialises the shader. -* -* @method init -*/ -PIXI.PixiShader.prototype.init = function() -{ - var gl = this.gl; - - var program = PIXI.compileProgram(gl, this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc); - - gl.useProgram(program); - - // get and store the uniforms for the shader - this.uSampler = gl.getUniformLocation(program, 'uSampler'); - this.projectionVector = gl.getUniformLocation(program, 'projectionVector'); - this.offsetVector = gl.getUniformLocation(program, 'offsetVector'); - this.dimensions = gl.getUniformLocation(program, 'dimensions'); - this.flipY = gl.getUniformLocation(program, 'flipY'); - - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition'); - this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord'); - this.colorAttribute = gl.getAttribLocation(program, 'aColor'); - - - // Begin worst hack eva // - - // WHY??? ONLY on my chrome pixel the line above returns -1 when using filters? - // maybe its something to do with the current state of the gl context. - // I'm convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel - // If theres any webGL people that know why could happen please help :) - if(this.colorAttribute === -1) - { - this.colorAttribute = 2; - } - - this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute]; - - // End worst hack eva // - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key); - } - - this.initUniforms(); - - this.program = program; -}; - -/** -* Initialises the shader uniform values. -* -* Uniforms are specified in the GLSL_ES Specification: http://www.khronos.org/registry/webgl/specs/latest/1.0/ -* http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf -* -* @method initUniforms -*/ -PIXI.PixiShader.prototype.initUniforms = function() -{ - this.textureCount = 1; - var gl = this.gl; - var uniform; - - for (var key in this.uniforms) - { - uniform = this.uniforms[key]; - - var type = uniform.type; - - if (type === 'sampler2D') - { - uniform._init = false; - - if (uniform.value !== null) - { - this.initSampler2D(uniform); - } - } - else if (type === 'mat2' || type === 'mat3' || type === 'mat4') - { - // These require special handling - uniform.glMatrix = true; - uniform.glValueLength = 1; - - if (type === 'mat2') - { - uniform.glFunc = gl.uniformMatrix2fv; - } - else if (type === 'mat3') - { - uniform.glFunc = gl.uniformMatrix3fv; - } - else if (type === 'mat4') - { - uniform.glFunc = gl.uniformMatrix4fv; - } - } - else - { - // GL function reference - uniform.glFunc = gl['uniform' + type]; - - if (type === '2f' || type === '2i') - { - uniform.glValueLength = 2; - } - else if (type === '3f' || type === '3i') - { - uniform.glValueLength = 3; - } - else if (type === '4f' || type === '4i') - { - uniform.glValueLength = 4; - } - else - { - uniform.glValueLength = 1; - } - } - } - -}; - -/** -* Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture has loaded) -* -* @method initSampler2D -*/ -PIXI.PixiShader.prototype.initSampler2D = function(uniform) -{ - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) - { - return; - } - - var gl = this.gl; - - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); - - // Extended texture data - if (uniform.textureData) - { - var data = uniform.textureData; - - // GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D); - // GLTextureLinear = mag/min linear, wrap clamp - // GLTextureNearestRepeat = mag/min NEAREST, wrap repeat - // GLTextureNearest = mag/min nearest, wrap clamp - // AudioTexture = whatever + luminance + width 512, height 2, border 0 - // KeyTexture = whatever + luminance + width 256, height 2, border 0 - - // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST - // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; - - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } - - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); - } - - gl.uniform1i(uniform.uniformLocation, this.textureCount); - - uniform._init = true; - - this.textureCount++; - -}; - -/** -* Updates the shader uniform values. -* -* @method syncUniforms -*/ -PIXI.PixiShader.prototype.syncUniforms = function() -{ - this.textureCount = 1; - var uniform; - var gl = this.gl; - - // This would probably be faster in an array and it would guarantee key order - for (var key in this.uniforms) - { - uniform = this.uniforms[key]; - - if (uniform.glValueLength === 1) - { - if (uniform.glMatrix === true) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.transpose, uniform.value); - } - else - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value); - } - } - else if (uniform.glValueLength === 2) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y); - } - else if (uniform.glValueLength === 3) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z); - } - else if (uniform.glValueLength === 4) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z, uniform.value.w); - } - else if (uniform.type === 'sampler2D') - { - if (uniform._init) - { - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - - if(uniform.value.baseTexture._dirty[gl.id]) - { - PIXI.instances[gl.id].updateTexture(uniform.value.baseTexture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); - } - - // gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id] || PIXI.createWebGLTexture( uniform.value.baseTexture, gl)); - gl.uniform1i(uniform.uniformLocation, this.textureCount); - this.textureCount++; - } - else - { - this.initSampler2D(uniform); - } - } - } - -}; - -/** -* Destroys the shader. -* -* @method destroy -*/ -PIXI.PixiShader.prototype.destroy = function() -{ - this.gl.deleteProgram( this.program ); - this.uniforms = null; - this.gl = null; - - this.attributes = null; -}; - -/** -* The Default Vertex shader source. -* -* @property defaultVertexSrc -* @type String -*/ -PIXI.PixiShader.defaultVertexSrc = [ - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - - 'uniform float flipY;', - - 'uniform vec2 projectionVector;', - 'uniform vec2 offsetVector;', - - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'void main(void) {', - - ' vec3 temp = vec3(-1.0, 1.0, flipY);', - - ' gl_Position = vec4( (aVertexPosition + offsetVector) / (projectionVector * temp.yz) + temp.xz , 0.0, 1.0);', - - ' vTextureCoord = aTextureCoord;', - - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - - '}' -]; \ No newline at end of file diff --git a/src/core/particles/webgl/ParticleRenderer.js b/src/core/particles/webgl/ParticleRenderer.js index 009c65d..ea55547 100644 --- a/src/core/particles/webgl/ParticleRenderer.js +++ b/src/core/particles/webgl/ParticleRenderer.js @@ -160,83 +160,20 @@ gl.uniformMatrix3fv(this.shader.uniforms.projectionMatrix._location, false, m.toArray(true)); - this.currentBatchSize = 0; -/* - var rotationDirty = false; - var positionDirty = false; - var vertsDirty = false; - var uvsDirty = false; - var alphaDirty = false;*/ - this.sprites = children; this.vertDirty = 0; - for (var i=0,j= children.length; i b2 * a1); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * The arc method creates an arc/curve (used to create circles, or parts of circles). - * - * @method arc - * @param cx {Number} The x-coordinate of the center of the circle - * @param cy {Number} The y-coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle) - * @param endAngle {Number} The ending angle, in radians - * @param anticlockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise. - * @return {Graphics} - */ -PIXI.Graphics.prototype.arc = function(cx, cy, radius, startAngle, endAngle, anticlockwise) -{ - var startX = cx + Math.cos(startAngle) * radius; - var startY = cy + Math.sin(startAngle) * radius; - var points; - - if( this.currentPath ) - { - points = this.currentPath.shape.points; - - if(points.length === 0) - { - points.push(startX, startY); - } - else if( points[points.length-2] !== startX || points[points.length-1] !== startY) - { - points.push(startX, startY); - } - } - else - { - this.moveTo(startX, startY); - points = this.currentPath.shape.points; - } - - if (startAngle === endAngle)return this; - - if( !anticlockwise && endAngle <= startAngle ) - { - endAngle += Math.PI * 2; - } - else if( anticlockwise && startAngle <= endAngle ) - { - startAngle += Math.PI * 2; - } - - var sweep = anticlockwise ? (startAngle - endAngle) *-1 : (endAngle - startAngle); - var segs = ( Math.abs(sweep)/ (Math.PI * 2) ) * 40; - - if( sweep === 0 ) return this; - - var theta = sweep/(segs*2); - var theta2 = theta*2; - - var cTheta = Math.cos(theta); - var sTheta = Math.sin(theta); - - var segMinus = segs - 1; - - var remainder = ( segMinus % 1 ) / segMinus; - - for(var i=0; i<=segMinus; i++) - { - var real = i + remainder * i; - - - var angle = ((theta) + startAngle + (theta2 * real)); - - var c = Math.cos(angle); - var s = -Math.sin(angle); - - points.push(( (cTheta * c) + (sTheta * s) ) * radius + cx, - ( (cTheta * -s) + (sTheta * c) ) * radius + cy); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {Number} the color of the fill - * @param alpha {Number} the alpha of the fill - * @return {Graphics} - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha === undefined) ? 1 : alpha; - - if(this.currentPath) - { - if(this.currentPath.shape.points.length <= 2) - { - this.currentPath.fill = this.filling; - this.currentPath.fillColor = this.fillColor; - this.currentPath.fillAlpha = this.fillAlpha; - } - } - return this; -}; - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - * @return {Graphics} - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; - - return this; -}; - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - this.drawShape(new PIXI.Rectangle(x,y, width, height)); - - return this; -}; - -/** - * @method drawRoundedRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @param radius {Number} Radius of the rectangle corners - */ -PIXI.Graphics.prototype.drawRoundedRect = function( x, y, width, height, radius ) -{ - this.drawShape(new PIXI.RoundedRectangle(x, y, width, height, radius)); - - return this; -}; - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coordinate of the center of the circle - * @param y {Number} The Y coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawCircle = function(x, y, radius) -{ - this.drawShape(new PIXI.Circle(x,y, radius)); - - return this; -}; - -/** - * Draws an ellipse. - * - * @method drawEllipse - * @param x {Number} The X coordinate of the center of the ellipse - * @param y {Number} The Y coordinate of the center of the ellipse - * @param width {Number} The half width of the ellipse - * @param height {Number} The half height of the ellipse - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawEllipse = function(x, y, width, height) -{ - this.drawShape(new PIXI.Ellipse(x, y, width, height)); - - return this; -}; - -/** - * Draws a polygon using the given path. - * - * @method drawPolygon - * @param path {Array} The path data used to construct the polygon. - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawPolygon = function(path) -{ - if(!(path instanceof Array))path = Array.prototype.slice.call(arguments); - this.drawShape(new PIXI.Polygon(path)); - return this; -}; - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - * @return {Graphics} - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = this.boundsDirty = true; - this.clearDirty = true; - this.graphicsData = []; - - return this; -}; - -/** - * Useful function that returns a texture of the graphics object that can then be used to create sprites - * This can be quite useful if your geometry is complicated and needs to be reused multiple times. - * - * @method generateTexture - * @param resolution {Number} The resolution of the texture being generated - * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts - * @return {Texture} a texture of the graphics object - */ -PIXI.Graphics.prototype.generateTexture = function(resolution, scaleMode) -{ - resolution = resolution || 1; - - var bounds = this.getBounds(); - - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width * resolution, bounds.height * resolution); - - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas, scaleMode); - texture.baseTexture.resolution = resolution; - - canvasBuffer.context.scale(resolution, resolution); - - canvasBuffer.context.translate(-bounds.x,-bounds.y); - - PIXI.CanvasGraphics.renderGraphics(this, canvasBuffer.context); - - return texture; -}; - -/** -* Renders the object using the WebGL renderer -* -* @method _renderWebGL -* @param renderSession {RenderSession} -* @private -*/ -PIXI.Graphics.prototype._renderWebGL = function(renderSession) -{ - // if the sprite is not visible or the alpha is 0 then no need to render this element - if(this.visible === false || this.alpha === 0 || this.isMask === true)return; - - if(this._cacheAsBitmap) - { - - if(this.dirty || this.cachedSpriteDirty) - { - - this._generateCachedSprite(); - - // we will also need to update the texture on the gpu too! - this.updateCachedSpriteTexture(); - - this.cachedSpriteDirty = false; - this.dirty = false; - } - - this._cachedSprite.worldAlpha = this.worldAlpha; - PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession); - - return; - } - else - { - renderSession.spriteBatch.stop(); - renderSession.blendModeManager.setBlendMode(this.blendMode); - - if(this._mask)renderSession.maskManager.pushMask(this._mask, renderSession); - if(this._filters)renderSession.filterManager.pushFilter(this._filterBlock); - - // check blend mode - if(this.blendMode !== renderSession.spriteBatch.currentBlendMode) - { - renderSession.spriteBatch.currentBlendMode = this.blendMode; - var blendModeWebGL = PIXI.blendModesWebGL[renderSession.spriteBatch.currentBlendMode]; - renderSession.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]); - } - - // check if the webgl graphic needs to be updated - if(this.webGLDirty) - { - this.dirty = true; - this.webGLDirty = false; - } - - PIXI.WebGLGraphics.renderGraphics(this, renderSession); - - // only render if it has children! - if(this.children.length) - { - renderSession.spriteBatch.start(); - - // simple render children! - for(var i=0, j=this.children.length; i maxX ? x2 : maxX; - maxX = x3 > maxX ? x3 : maxX; - maxX = x4 > maxX ? x4 : maxX; - - maxY = y2 > maxY ? y2 : maxY; - maxY = y3 > maxY ? y3 : maxY; - maxY = y4 > maxY ? y4 : maxY; - - this._bounds.x = minX; - this._bounds.width = maxX - minX; - - this._bounds.y = minY; - this._bounds.height = maxY - minY; - - return this._bounds; -}; - -/** - * Update the bounds of the object - * - * @method updateLocalBounds - */ -PIXI.Graphics.prototype.updateLocalBounds = function() -{ - var minX = Infinity; - var maxX = -Infinity; - - var minY = Infinity; - var maxY = -Infinity; - - - - if(this.graphicsData.length) - { - var shape, points, x, y, w, h; - - for (var i = 0; i < this.graphicsData.length; i++) { - var data = this.graphicsData[i]; - var type = data.type; - var lineWidth = data.lineWidth; - shape = data.shape; - - - if(type === PIXI.Graphics.RECT || type === PIXI.Graphics.RREC) - { - x = shape.x - lineWidth/2; - y = shape.y - lineWidth/2; - w = shape.width + lineWidth; - h = shape.height + lineWidth; - - minX = x < minX ? x : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y < minY ? y : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.CIRC) - { - x = shape.x; - y = shape.y; - w = shape.radius + lineWidth/2; - h = shape.radius + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.ELIP) - { - x = shape.x; - y = shape.y; - w = shape.width + lineWidth/2; - h = shape.height + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else - { - // POLY - points = shape.points; - - for (var j = 0; j < points.length; j+=2) - { - - x = points[j]; - y = points[j+1]; - minX = x-lineWidth < minX ? x-lineWidth : minX; - maxX = x+lineWidth > maxX ? x+lineWidth : maxX; - - minY = y-lineWidth < minY ? y-lineWidth : minY; - maxY = y+lineWidth > maxY ? y+lineWidth : maxY; - } - } - } - } - else - { - minX = 0; - maxX = 0; - minY = 0; - maxY = 0; - } - - var padding = this.boundsPadding; - - this._localBounds.x = minX - padding; - this._localBounds.width = (maxX - minX) + padding * 2; - - this._localBounds.y = minY - padding; - this._localBounds.height = (maxY - minY) + padding * 2; -}; - -/** - * Generates the cached sprite when the sprite has cacheAsBitmap = true - * - * @method _generateCachedSprite - * @private - */ -PIXI.Graphics.prototype._generateCachedSprite = function() -{ - var bounds = this.getLocalBounds(); - - if(!this._cachedSprite) - { - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height); - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas); - - this._cachedSprite = new PIXI.Sprite(texture); - this._cachedSprite.buffer = canvasBuffer; - - this._cachedSprite.worldTransform = this.worldTransform; - } - else - { - this._cachedSprite.buffer.resize(bounds.width, bounds.height); - } - - // leverage the anchor to account for the offset of the element - this._cachedSprite.anchor.x = -( bounds.x / bounds.width ); - this._cachedSprite.anchor.y = -( bounds.y / bounds.height ); - - // this._cachedSprite.buffer.context.save(); - this._cachedSprite.buffer.context.translate(-bounds.x,-bounds.y); - - // make sure we set the alpha of the graphics to 1 for the render.. - this.worldAlpha = 1; - - // now render the graphic.. - PIXI.CanvasGraphics.renderGraphics(this, this._cachedSprite.buffer.context); - this._cachedSprite.alpha = this.alpha; - -}; - -/** - * Updates texture size based on canvas size - * - * @method updateCachedSpriteTexture - * @private - */ -PIXI.Graphics.prototype.updateCachedSpriteTexture = function() -{ - var cachedSprite = this._cachedSprite; - var texture = cachedSprite.texture; - var canvas = cachedSprite.buffer.canvas; - - texture.baseTexture.width = canvas.width; - texture.baseTexture.height = canvas.height; - texture.crop.width = texture.frame.width = canvas.width; - texture.crop.height = texture.frame.height = canvas.height; - - cachedSprite._width = canvas.width; - cachedSprite._height = canvas.height; - - // update the dirty base textures - texture.baseTexture.dirty(); -}; - -/** - * Destroys a previous cached sprite. - * - * @method destroyCachedSprite - */ -PIXI.Graphics.prototype.destroyCachedSprite = function() -{ - this._cachedSprite.texture.destroy(true); - - // let the gc collect the unused sprite - // TODO could be object pooled! - this._cachedSprite = null; -}; - -/** - * Draws the given shape to this Graphics object. Can be any of Circle, Rectangle, Ellipse, Line or Polygon. - * - * @method drawShape - * @param {Circle|Rectangle|Ellipse|Line|Polygon} shape The Shape object to draw. - * @return {GraphicsData} The generated GraphicsData object. - */ -PIXI.Graphics.prototype.drawShape = function(shape) -{ - if(this.currentPath) - { - // check current path! - if(this.currentPath.shape.points.length <= 2)this.graphicsData.pop(); - } - - this.currentPath = null; - - var data = new PIXI.GraphicsData(this.lineWidth, this.lineColor, this.lineAlpha, this.fillColor, this.fillAlpha, this.filling, shape); - - this.graphicsData.push(data); - - if(data.type === PIXI.Graphics.POLY) - { - data.shape.closed = this.filling; - this.currentPath = data; - } - - this.dirty = this.boundsDirty = true; - - return data; -}; - -/** - * A GraphicsData object. - * - * @class GraphicsData - * @constructor - */ -PIXI.GraphicsData = function(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, shape) -{ - this.lineWidth = lineWidth; - this.lineColor = lineColor; - this.lineAlpha = lineAlpha; - this._lineTint = lineColor; - - this.fillColor = fillColor; - this.fillAlpha = fillAlpha; - this._fillTint = fillColor; - this.fill = fill; - - this.shape = shape; - this.type = shape.type; -}; - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; -PIXI.Graphics.RREC = 4; - -PIXI.Polygon.prototype.type = PIXI.Graphics.POLY; -PIXI.Rectangle.prototype.type = PIXI.Graphics.RECT; -PIXI.Circle.prototype.type = PIXI.Graphics.CIRC; -PIXI.Ellipse.prototype.type = PIXI.Graphics.ELIP; -PIXI.RoundedRectangle.prototype.type = PIXI.Graphics.RREC; - diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js deleted file mode 100644 index 82dbc05..0000000 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ /dev/null @@ -1,558 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.glContexts = []; // this is where we store the webGL contexts for easy access. -PIXI.instances = []; - -/** - * The WebGLRenderer draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers that support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batches or Sprite Clouds. - * Don't forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param [width=0] {Number} the width of the canvas view - * @param [height=0] {Number} the height of the canvas view - * @param [options] {Object} The optional renderer parameters - * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional - * @param [options.transparent=false] {Boolean} If the render view is transparent, default false - * @param [options.autoResize=false] {Boolean} If the render view is automatically resized, default false - * @param [options.antialias=false] {Boolean} sets antialias (only applicable in chrome at the moment) - * @param [options.preserveDrawingBuffer=false] {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context - * @param [options.resolution=1] {Number} the resolution of the renderer retina would be 2 - */ -PIXI.WebGLRenderer = function(width, height, options) -{ - if(options) - { - for (var i in PIXI.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') options[i] = PIXI.defaultRenderOptions[i]; - } - } - else - { - options = PIXI.defaultRenderOptions; - } - - if(!PIXI.defaultRenderer) - { - PIXI.sayHello('webGL'); - PIXI.defaultRenderer = this; - } - - /** - * @property type - * @type Number - */ - this.type = PIXI.WEBGL_RENDERER; - - /** - * The resolution of the renderer - * - * @property resolution - * @type Number - * @default 1 - */ - this.resolution = options.resolution; - - // do a catch.. only 1 webGL renderer.. - - /** - * Whether the render view is transparent - * - * @property transparent - * @type Boolean - */ - this.transparent = options.transparent; - - /** - * Whether the render view should be resized automatically - * - * @property autoResize - * @type Boolean - */ - this.autoResize = options.autoResize || false; - - /** - * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. - * - * @property preserveDrawingBuffer - * @type Boolean - */ - this.preserveDrawingBuffer = options.preserveDrawingBuffer; - - /** - * This sets if the WebGLRenderer will clear the context texture or not before the new render pass. If true: - * If the Stage is NOT transparent, Pixi will clear to alpha (0, 0, 0, 0). - * If the Stage is transparent, Pixi will clear to the target Stage's background color. - * Disable this by setting this to false. For example: if your game has a canvas filling background image, you often don't need this set. - * - * @property clearBeforeRender - * @type Boolean - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that everything is drawn to - * - * @property view - * @type HTMLCanvasElement - */ - this.view = options.view || document.createElement( 'canvas' ); - - // deal with losing context.. - - /** - * @property contextLostBound - * @type Function - */ - this.contextLostBound = this.handleContextLost.bind(this); - - /** - * @property contextRestoredBound - * @type Function - */ - this.contextRestoredBound = this.handleContextRestored.bind(this); - - this.view.addEventListener('webglcontextlost', this.contextLostBound, false); - this.view.addEventListener('webglcontextrestored', this.contextRestoredBound, false); - - /** - * @property _contextOptions - * @type Object - * @private - */ - this._contextOptions = { - alpha: this.transparent, - antialias: options.antialias, // SPEED UP?? - premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', - stencil:true, - preserveDrawingBuffer: options.preserveDrawingBuffer - }; - - /** - * @property projection - * @type Point - */ - this.projection = new PIXI.Point(); - - /** - * @property offset - * @type Point - */ - this.offset = new PIXI.Point(0, 0); - - // time to create the render managers! each one focuses on managing a state in webGL - - /** - * Deals with managing the shader programs and their attribs - * @property shaderManager - * @type WebGLShaderManager - */ - this.shaderManager = new PIXI.WebGLShaderManager(); - - /** - * Manages the rendering of sprites - * @property spriteBatch - * @type WebGLSpriteBatch - */ - this.spriteBatch = new PIXI.WebGLSpriteBatch(); - - /** - * Manages the masks using the stencil buffer - * @property maskManager - * @type WebGLMaskManager - */ - this.maskManager = new PIXI.WebGLMaskManager(); - - /** - * Manages the filters - * @property filterManager - * @type WebGLFilterManager - */ - this.filterManager = new PIXI.WebGLFilterManager(); - - /** - * Manages the stencil buffer - * @property stencilManager - * @type WebGLStencilManager - */ - this.stencilManager = new PIXI.WebGLStencilManager(); - - /** - * Manages the blendModes - * @property blendModeManager - * @type WebGLBlendModeManager - */ - this.blendModeManager = new PIXI.WebGLBlendModeManager(); - - /** - * TODO remove - * @property renderSession - * @type Object - */ - this.renderSession = {}; - this.renderSession.gl = this.gl; - this.renderSession.drawCount = 0; - this.renderSession.shaderManager = this.shaderManager; - this.renderSession.maskManager = this.maskManager; - this.renderSession.filterManager = this.filterManager; - this.renderSession.blendModeManager = this.blendModeManager; - this.renderSession.spriteBatch = this.spriteBatch; - this.renderSession.stencilManager = this.stencilManager; - this.renderSession.renderer = this; - this.renderSession.resolution = this.resolution; - this.renderSession.buffer = null; - - // time init the context.. - this.initContext(); - - // map some webGL blend modes.. - this.mapBlendModes(); -}; - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** -* @method initContext -*/ -PIXI.WebGLRenderer.prototype.initContext = function() -{ - var gl = this.view.getContext('webgl', this._contextOptions) || this.view.getContext('experimental-webgl', this._contextOptions); - this.gl = gl; - - if (!gl) { - // fail, not able to get a context - throw new Error('This browser does not support webGL. Try using the canvas renderer'); - } - - this.glContextId = gl.id = PIXI.WebGLRenderer.glContextId ++; - - PIXI.glContexts[this.glContextId] = gl; - - PIXI.instances[this.glContextId] = this; - - // set up the default pixi settings.. - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); - - // need to set the context for all the managers... - this.shaderManager.setContext(gl); - this.spriteBatch.setContext(gl); - this.maskManager.setContext(gl); - this.filterManager.setContext(gl); - this.blendModeManager.setContext(gl); - this.stencilManager.setContext(gl); - - this.renderSession.gl = this.gl; - - // now resize and we are good to go! - this.resize(this.width, this.height); -}; - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - // no point rendering if our context has been blown up! - if(this.contextLost)return; - - // if rendering a new stage clear the batches.. - if(this.__stage !== stage) - { - if(stage.interactive)stage.interactionManager.removeEvents(); - - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - } - - // update the scene graph - stage.updateTransform(); - - var gl = this.gl; - - // interaction - if(stage._interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - else - { - if(stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = false; - stage.interactionManager.setTarget(this); - } - } - - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - - // make sure we are bound to the main frame buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - if (this.clearBeforeRender) - { - if(this.transparent) - { - gl.clearColor(0, 0, 0, 0); - } - else - { - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); - } - - gl.clear (gl.COLOR_BUFFER_BIT); - } - - this.renderDisplayObject( stage, this.projection ); -}; - -/** - * Renders a Display Object. - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The DisplayObject to render - * @param projection {Point} The projection - * @param buffer {Array} a standard WebGL buffer - */ -PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection, buffer) -{ - this.renderSession.blendModeManager.setBlendMode(PIXI.blendModes.NORMAL); - - // reset the render session data.. - this.renderSession.drawCount = 0; - - // set the buffer ref.. - this.renderSession.buffer = buffer; - - // make sure to flip the Y if using a render texture.. - this.renderSession.flipY = buffer ? -1 : 1; - - // set the default projection - this.renderSession.projection = projection; - - //set the default offset - this.renderSession.offset = this.offset; - - // start the sprite batch - this.spriteBatch.begin(this.renderSession); - - // start the filter manager - this.filterManager.begin(this.renderSession, buffer); - - // render the scene! - displayObject._renderWebGL(this.renderSession); - - // finish the sprite batch - this.spriteBatch.end(); -}; - -/** - * Resizes the webGL view to the specified width and height. - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width * this.resolution; - this.height = height * this.resolution; - - this.view.width = this.width; - this.view.height = this.height; - - if (this.autoResize) { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } - - this.gl.viewport(0, 0, this.width, this.height); - - this.projection.x = this.width / 2 / this.resolution; - this.projection.y = -this.height / 2 / this.resolution; -}; - -/** - * Updates and Creates a WebGL texture for the renderers context. - * - * @method updateTexture - * @param texture {Texture} the texture to update - */ -PIXI.WebGLRenderer.prototype.updateTexture = function(texture) -{ - if(!texture.hasLoaded )return; - - var gl = this.gl; - - if(!texture._glTextures[gl.id])texture._glTextures[gl.id] = gl.createTexture(); - - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - - - if(texture.mipmap && PIXI.isPowerOfTwo(texture.width, texture.height)) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); - gl.generateMipmap(gl.TEXTURE_2D); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - } - - // reguler... - if(!texture._powerOf2) - { - 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); - } - - texture._dirty[gl.id] = false; - - return texture._glTextures[gl.id]; -}; - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -}; - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function() -{ - this.initContext(); - - // empty all the ol gl textures as they are useless now - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTextures = []; - } - - this.contextLost = false; -}; - -/** - * Removes everything from the renderer (event listeners, spritebatch, etc...) - * - * @method destroy - */ -PIXI.WebGLRenderer.prototype.destroy = function() -{ - // remove listeners - this.view.removeEventListener('webglcontextlost', this.contextLostBound); - this.view.removeEventListener('webglcontextrestored', this.contextRestoredBound); - - PIXI.glContexts[this.glContextId] = null; - - this.projection = null; - this.offset = null; - - // time to create the render managers! each one focuses on managine a state in webGL - this.shaderManager.destroy(); - this.spriteBatch.destroy(); - this.maskManager.destroy(); - this.filterManager.destroy(); - - this.shaderManager = null; - this.spriteBatch = null; - this.maskManager = null; - this.filterManager = null; - - this.gl = null; - this.renderSession = null; -}; - -/** - * Maps Pixi blend modes to WebGL blend modes. - * - * @method mapBlendModes - */ -PIXI.WebGLRenderer.prototype.mapBlendModes = function() -{ - var gl = this.gl; - - if(!PIXI.blendModesWebGL) - { - PIXI.blendModesWebGL = []; - - PIXI.blendModesWebGL[PIXI.blendModes.NORMAL] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.ADD] = [gl.SRC_ALPHA, gl.DST_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.MULTIPLY] = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SCREEN] = [gl.SRC_ALPHA, gl.ONE]; - PIXI.blendModesWebGL[PIXI.blendModes.OVERLAY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DARKEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LIGHTEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_DODGE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_BURN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HARD_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SOFT_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DIFFERENCE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.EXCLUSION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HUE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - } -}; - -PIXI.WebGLRenderer.glContextId = 0; diff --git a/src/pixi/renderers/webgl/shaders/PixiShader.js b/src/pixi/renderers/webgl/shaders/PixiShader.js deleted file mode 100644 index bb4a17d..0000000 --- a/src/pixi/renderers/webgl/shaders/PixiShader.js +++ /dev/null @@ -1,397 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * @author Richard Davey http://www.photonstorm.com @photonstorm - */ - -/** -* @class PixiShader -* @constructor -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.PixiShader = function(gl) -{ - /** - * @property _UID - * @type Number - * @private - */ - this._UID = PIXI._UID++; - - /** - * @property gl - * @type WebGLContext - */ - this.gl = gl; - - /** - * The WebGL program. - * @property program - * @type Any - */ - this.program = null; - - /** - * The fragment shader. - * @property fragmentSrc - * @type Array - */ - this.fragmentSrc = [ - 'precision lowp float;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - 'uniform sampler2D uSampler;', - 'void main(void) {', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;', - '}' - ]; - - /** - * A local texture counter for multi-texture shaders. - * @property textureCount - * @type Number - */ - this.textureCount = 0; - - /** - * A local flag - * @property firstRun - * @type Boolean - * @private - */ - this.firstRun = true; - - /** - * A dirty flag - * @property dirty - * @type Boolean - */ - this.dirty = true; - - /** - * Uniform attributes cache. - * @property attributes - * @type Array - * @private - */ - this.attributes = []; - - this.init(); -}; - -PIXI.PixiShader.prototype.constructor = PIXI.PixiShader; - -/** -* Initialises the shader. -* -* @method init -*/ -PIXI.PixiShader.prototype.init = function() -{ - var gl = this.gl; - - var program = PIXI.compileProgram(gl, this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc); - - gl.useProgram(program); - - // get and store the uniforms for the shader - this.uSampler = gl.getUniformLocation(program, 'uSampler'); - this.projectionVector = gl.getUniformLocation(program, 'projectionVector'); - this.offsetVector = gl.getUniformLocation(program, 'offsetVector'); - this.dimensions = gl.getUniformLocation(program, 'dimensions'); - this.flipY = gl.getUniformLocation(program, 'flipY'); - - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition'); - this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord'); - this.colorAttribute = gl.getAttribLocation(program, 'aColor'); - - - // Begin worst hack eva // - - // WHY??? ONLY on my chrome pixel the line above returns -1 when using filters? - // maybe its something to do with the current state of the gl context. - // I'm convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel - // If theres any webGL people that know why could happen please help :) - if(this.colorAttribute === -1) - { - this.colorAttribute = 2; - } - - this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute]; - - // End worst hack eva // - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key); - } - - this.initUniforms(); - - this.program = program; -}; - -/** -* Initialises the shader uniform values. -* -* Uniforms are specified in the GLSL_ES Specification: http://www.khronos.org/registry/webgl/specs/latest/1.0/ -* http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf -* -* @method initUniforms -*/ -PIXI.PixiShader.prototype.initUniforms = function() -{ - this.textureCount = 1; - var gl = this.gl; - var uniform; - - for (var key in this.uniforms) - { - uniform = this.uniforms[key]; - - var type = uniform.type; - - if (type === 'sampler2D') - { - uniform._init = false; - - if (uniform.value !== null) - { - this.initSampler2D(uniform); - } - } - else if (type === 'mat2' || type === 'mat3' || type === 'mat4') - { - // These require special handling - uniform.glMatrix = true; - uniform.glValueLength = 1; - - if (type === 'mat2') - { - uniform.glFunc = gl.uniformMatrix2fv; - } - else if (type === 'mat3') - { - uniform.glFunc = gl.uniformMatrix3fv; - } - else if (type === 'mat4') - { - uniform.glFunc = gl.uniformMatrix4fv; - } - } - else - { - // GL function reference - uniform.glFunc = gl['uniform' + type]; - - if (type === '2f' || type === '2i') - { - uniform.glValueLength = 2; - } - else if (type === '3f' || type === '3i') - { - uniform.glValueLength = 3; - } - else if (type === '4f' || type === '4i') - { - uniform.glValueLength = 4; - } - else - { - uniform.glValueLength = 1; - } - } - } - -}; - -/** -* Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture has loaded) -* -* @method initSampler2D -*/ -PIXI.PixiShader.prototype.initSampler2D = function(uniform) -{ - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) - { - return; - } - - var gl = this.gl; - - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); - - // Extended texture data - if (uniform.textureData) - { - var data = uniform.textureData; - - // GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D); - // GLTextureLinear = mag/min linear, wrap clamp - // GLTextureNearestRepeat = mag/min NEAREST, wrap repeat - // GLTextureNearest = mag/min nearest, wrap clamp - // AudioTexture = whatever + luminance + width 512, height 2, border 0 - // KeyTexture = whatever + luminance + width 256, height 2, border 0 - - // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST - // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; - - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } - - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); - } - - gl.uniform1i(uniform.uniformLocation, this.textureCount); - - uniform._init = true; - - this.textureCount++; - -}; - -/** -* Updates the shader uniform values. -* -* @method syncUniforms -*/ -PIXI.PixiShader.prototype.syncUniforms = function() -{ - this.textureCount = 1; - var uniform; - var gl = this.gl; - - // This would probably be faster in an array and it would guarantee key order - for (var key in this.uniforms) - { - uniform = this.uniforms[key]; - - if (uniform.glValueLength === 1) - { - if (uniform.glMatrix === true) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.transpose, uniform.value); - } - else - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value); - } - } - else if (uniform.glValueLength === 2) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y); - } - else if (uniform.glValueLength === 3) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z); - } - else if (uniform.glValueLength === 4) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z, uniform.value.w); - } - else if (uniform.type === 'sampler2D') - { - if (uniform._init) - { - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - - if(uniform.value.baseTexture._dirty[gl.id]) - { - PIXI.instances[gl.id].updateTexture(uniform.value.baseTexture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); - } - - // gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id] || PIXI.createWebGLTexture( uniform.value.baseTexture, gl)); - gl.uniform1i(uniform.uniformLocation, this.textureCount); - this.textureCount++; - } - else - { - this.initSampler2D(uniform); - } - } - } - -}; - -/** -* Destroys the shader. -* -* @method destroy -*/ -PIXI.PixiShader.prototype.destroy = function() -{ - this.gl.deleteProgram( this.program ); - this.uniforms = null; - this.gl = null; - - this.attributes = null; -}; - -/** -* The Default Vertex shader source. -* -* @property defaultVertexSrc -* @type String -*/ -PIXI.PixiShader.defaultVertexSrc = [ - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - - 'uniform float flipY;', - - 'uniform vec2 projectionVector;', - 'uniform vec2 offsetVector;', - - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'void main(void) {', - - ' vec3 temp = vec3(-1.0, 1.0, flipY);', - - ' gl_Position = vec4( (aVertexPosition + offsetVector) / (projectionVector * temp.yz) + temp.xz , 0.0, 1.0);', - - ' vTextureCoord = aTextureCoord;', - - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - - '}' -]; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/utils/WebGLFilterManager.js b/src/pixi/renderers/webgl/utils/WebGLFilterManager.js deleted file mode 100644 index ba642c3..0000000 --- a/src/pixi/renderers/webgl/utils/WebGLFilterManager.js +++ /dev/null @@ -1,452 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** -* @class WebGLFilterManager -* @constructor -*/ -PIXI.WebGLFilterManager = function() -{ - /** - * @property filterStack - * @type Array - */ - this.filterStack = []; - - /** - * @property offsetX - * @type Number - */ - this.offsetX = 0; - - /** - * @property offsetY - * @type Number - */ - this.offsetY = 0; -}; - -PIXI.WebGLFilterManager.prototype.constructor = PIXI.WebGLFilterManager; - -/** -* Initialises the context and the properties. -* -* @method setContext -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.WebGLFilterManager.prototype.setContext = function(gl) -{ - this.gl = gl; - this.texturePool = []; - - this.initShaderBuffers(); -}; - -/** -* @method begin -* @param renderSession {RenderSession} -* @param buffer {ArrayBuffer} -*/ -PIXI.WebGLFilterManager.prototype.begin = function(renderSession, buffer) -{ - this.renderSession = renderSession; - this.defaultShader = renderSession.shaderManager.defaultShader; - - var projection = this.renderSession.projection; - this.width = projection.x * 2; - this.height = -projection.y * 2; - this.buffer = buffer; -}; - -/** -* Applies the filter and adds it to the current filter stack. -* -* @method pushFilter -* @param filterBlock {Object} the filter that will be pushed to the current filter stack -*/ -PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock) -{ - var gl = this.gl; - - var projection = this.renderSession.projection; - var offset = this.renderSession.offset; - - filterBlock._filterArea = filterBlock.target.filterArea || filterBlock.target.getBounds(); - - // filter program - // OPTIMISATION - the first filter is free if its a simple color change? - this.filterStack.push(filterBlock); - - var filter = filterBlock.filterPasses[0]; - - this.offsetX += filterBlock._filterArea.x; - this.offsetY += filterBlock._filterArea.y; - - var texture = this.texturePool.pop(); - if(!texture) - { - texture = new PIXI.FilterTexture(this.gl, this.width, this.height); - } - else - { - texture.resize(this.width, this.height); - } - - gl.bindTexture(gl.TEXTURE_2D, texture.texture); - - var filterArea = filterBlock._filterArea;// filterBlock.target.getBounds();///filterBlock.target.filterArea; - - var padding = filter.padding; - filterArea.x -= padding; - filterArea.y -= padding; - filterArea.width += padding * 2; - filterArea.height += padding * 2; - - // cap filter to screen size.. - if(filterArea.x < 0)filterArea.x = 0; - if(filterArea.width > this.width)filterArea.width = this.width; - if(filterArea.y < 0)filterArea.y = 0; - if(filterArea.height > this.height)filterArea.height = this.height; - - //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - gl.bindFramebuffer(gl.FRAMEBUFFER, texture.frameBuffer); - - // set view port - gl.viewport(0, 0, filterArea.width, filterArea.height); - - projection.x = filterArea.width/2; - projection.y = -filterArea.height/2; - - offset.x = -filterArea.x; - offset.y = -filterArea.y; - - // update projection - // now restore the regular shader.. - // this.renderSession.shaderManager.setShader(this.defaultShader); - //gl.uniform2f(this.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2); - //gl.uniform2f(this.defaultShader.offsetVector, -filterArea.x, -filterArea.y); - - gl.colorMask(true, true, true, true); - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - - filterBlock._glFilterTexture = texture; - -}; - -/** -* Removes the last filter from the filter stack and doesn't return it. -* -* @method popFilter -*/ -PIXI.WebGLFilterManager.prototype.popFilter = function() -{ - var gl = this.gl; - var filterBlock = this.filterStack.pop(); - var filterArea = filterBlock._filterArea; - var texture = filterBlock._glFilterTexture; - var projection = this.renderSession.projection; - var offset = this.renderSession.offset; - - if(filterBlock.filterPasses.length > 1) - { - gl.viewport(0, 0, filterArea.width, filterArea.height); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - - this.vertexArray[0] = 0; - this.vertexArray[1] = filterArea.height; - - this.vertexArray[2] = filterArea.width; - this.vertexArray[3] = filterArea.height; - - this.vertexArray[4] = 0; - this.vertexArray[5] = 0; - - this.vertexArray[6] = filterArea.width; - this.vertexArray[7] = 0; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - // now set the uvs.. - this.uvArray[2] = filterArea.width/this.width; - this.uvArray[5] = filterArea.height/this.height; - this.uvArray[6] = filterArea.width/this.width; - this.uvArray[7] = filterArea.height/this.height; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); - - var inputTexture = texture; - var outputTexture = this.texturePool.pop(); - if(!outputTexture)outputTexture = new PIXI.FilterTexture(this.gl, this.width, this.height); - outputTexture.resize(this.width, this.height); - - // need to clear this FBO as it may have some left over elements from a previous filter. - gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); - gl.clear(gl.COLOR_BUFFER_BIT); - - gl.disable(gl.BLEND); - - for (var i = 0; i < filterBlock.filterPasses.length-1; i++) - { - var filterPass = filterBlock.filterPasses[i]; - - gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); - - // set texture - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture); - - // draw texture.. - //filterPass.applyFilterPass(filterArea.width, filterArea.height); - this.applyFilterPass(filterPass, filterArea, filterArea.width, filterArea.height); - - // swap the textures.. - var temp = inputTexture; - inputTexture = outputTexture; - outputTexture = temp; - } - - gl.enable(gl.BLEND); - - texture = inputTexture; - this.texturePool.push(outputTexture); - } - - var filter = filterBlock.filterPasses[filterBlock.filterPasses.length-1]; - - this.offsetX -= filterArea.x; - this.offsetY -= filterArea.y; - - var sizeX = this.width; - var sizeY = this.height; - - var offsetX = 0; - var offsetY = 0; - - var buffer = this.buffer; - - // time to render the filters texture to the previous scene - if(this.filterStack.length === 0) - { - gl.colorMask(true, true, true, true);//this.transparent); - } - else - { - var currentFilter = this.filterStack[this.filterStack.length-1]; - filterArea = currentFilter._filterArea; - - sizeX = filterArea.width; - sizeY = filterArea.height; - - offsetX = filterArea.x; - offsetY = filterArea.y; - - buffer = currentFilter._glFilterTexture.frameBuffer; - } - - // TODO need to remove these global elements.. - projection.x = sizeX/2; - projection.y = -sizeY/2; - - offset.x = offsetX; - offset.y = offsetY; - - filterArea = filterBlock._filterArea; - - var x = filterArea.x-offsetX; - var y = filterArea.y-offsetY; - - // update the buffers.. - // make sure to flip the y! - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - - this.vertexArray[0] = x; - this.vertexArray[1] = y + filterArea.height; - - this.vertexArray[2] = x + filterArea.width; - this.vertexArray[3] = y + filterArea.height; - - this.vertexArray[4] = x; - this.vertexArray[5] = y; - - this.vertexArray[6] = x + filterArea.width; - this.vertexArray[7] = y; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - this.uvArray[2] = filterArea.width/this.width; - this.uvArray[5] = filterArea.height/this.height; - this.uvArray[6] = filterArea.width/this.width; - this.uvArray[7] = filterArea.height/this.height; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); - - gl.viewport(0, 0, sizeX, sizeY); - - // bind the buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, buffer ); - - // set the blend mode! - //gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) - - // set texture - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture.texture); - - // apply! - this.applyFilterPass(filter, filterArea, sizeX, sizeY); - - // now restore the regular shader.. should happen automatically now.. - // this.renderSession.shaderManager.setShader(this.defaultShader); - // gl.uniform2f(this.defaultShader.projectionVector, sizeX/2, -sizeY/2); - // gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY); - - // return the texture to the pool - this.texturePool.push(texture); - filterBlock._glFilterTexture = null; -}; - - -/** -* Applies the filter to the specified area. -* -* @method applyFilterPass -* @param filter {AbstractFilter} the filter that needs to be applied -* @param filterArea {Texture} TODO - might need an update -* @param width {Number} the horizontal range of the filter -* @param height {Number} the vertical range of the filter -*/ -PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea, width, height) -{ - // use program - var gl = this.gl; - var shader = filter.shaders[gl.id]; - - if(!shader) - { - shader = new PIXI.PixiShader(gl); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shaders[gl.id] = shader; - } - - // set the shader - this.renderSession.shaderManager.setShader(shader); - -// gl.useProgram(shader.program); - - gl.uniform2f(shader.projectionVector, width/2, -height/2); - gl.uniform2f(shader.offsetVector, 0,0); - - gl.uniform1f(shader.flipY, this.renderSession.flipY); - - if(filter.uniforms.dimensions) - { - filter.uniforms.dimensions.value[0] = this.width;//width; - filter.uniforms.dimensions.value[1] = this.height;//height; - filter.uniforms.dimensions.value[2] = this.vertexArray[0]; - filter.uniforms.dimensions.value[3] = this.vertexArray[5];//filterArea.height; - } - - shader.syncUniforms(); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.vertexAttribPointer(shader.colorAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - // draw the filter... - gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - this.renderSession.drawCount++; -}; - -/** -* Initialises the shader buffers. -* -* @method initShaderBuffers -*/ -PIXI.WebGLFilterManager.prototype.initShaderBuffers = function() -{ - var gl = this.gl; - - // create some buffers - this.vertexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - - // bind and upload the vertexs.. - // keep a reference to the vertexFloatData.. - this.vertexArray = new PIXI.Float32Array([0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.vertexArray, gl.STATIC_DRAW); - - // bind and upload the uv buffer - this.uvArray = new PIXI.Float32Array([0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvArray, gl.STATIC_DRAW); - - this.colorArray = new PIXI.Float32Array([1.0, 0xFFFFFF, - 1.0, 0xFFFFFF, - 1.0, 0xFFFFFF, - 1.0, 0xFFFFFF]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colorArray, gl.STATIC_DRAW); - - // bind and upload the index - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 1, 3, 2]), gl.STATIC_DRAW); - -}; - -/** -* Destroys the filter and removes it from the filter stack. -* -* @method destroy -*/ -PIXI.WebGLFilterManager.prototype.destroy = function() -{ - var gl = this.gl; - - this.filterStack = null; - - this.offsetX = 0; - this.offsetY = 0; - - // destroy textures - for (var i = 0; i < this.texturePool.length; i++) { - this.texturePool[i].destroy(); - } - - this.texturePool = null; - - //destroy buffers.. - gl.deleteBuffer(this.vertexBuffer); - gl.deleteBuffer(this.uvBuffer); - gl.deleteBuffer(this.colorBuffer); - gl.deleteBuffer(this.indexBuffer); -}; diff --git a/src/core/particles/webgl/ParticleRenderer.js b/src/core/particles/webgl/ParticleRenderer.js index 009c65d..ea55547 100644 --- a/src/core/particles/webgl/ParticleRenderer.js +++ b/src/core/particles/webgl/ParticleRenderer.js @@ -160,83 +160,20 @@ gl.uniformMatrix3fv(this.shader.uniforms.projectionMatrix._location, false, m.toArray(true)); - this.currentBatchSize = 0; -/* - var rotationDirty = false; - var positionDirty = false; - var vertsDirty = false; - var uvsDirty = false; - var alphaDirty = false;*/ - this.sprites = children; this.vertDirty = 0; - for (var i=0,j= children.length; i b2 * a1); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * The arc method creates an arc/curve (used to create circles, or parts of circles). - * - * @method arc - * @param cx {Number} The x-coordinate of the center of the circle - * @param cy {Number} The y-coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle) - * @param endAngle {Number} The ending angle, in radians - * @param anticlockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise. - * @return {Graphics} - */ -PIXI.Graphics.prototype.arc = function(cx, cy, radius, startAngle, endAngle, anticlockwise) -{ - var startX = cx + Math.cos(startAngle) * radius; - var startY = cy + Math.sin(startAngle) * radius; - var points; - - if( this.currentPath ) - { - points = this.currentPath.shape.points; - - if(points.length === 0) - { - points.push(startX, startY); - } - else if( points[points.length-2] !== startX || points[points.length-1] !== startY) - { - points.push(startX, startY); - } - } - else - { - this.moveTo(startX, startY); - points = this.currentPath.shape.points; - } - - if (startAngle === endAngle)return this; - - if( !anticlockwise && endAngle <= startAngle ) - { - endAngle += Math.PI * 2; - } - else if( anticlockwise && startAngle <= endAngle ) - { - startAngle += Math.PI * 2; - } - - var sweep = anticlockwise ? (startAngle - endAngle) *-1 : (endAngle - startAngle); - var segs = ( Math.abs(sweep)/ (Math.PI * 2) ) * 40; - - if( sweep === 0 ) return this; - - var theta = sweep/(segs*2); - var theta2 = theta*2; - - var cTheta = Math.cos(theta); - var sTheta = Math.sin(theta); - - var segMinus = segs - 1; - - var remainder = ( segMinus % 1 ) / segMinus; - - for(var i=0; i<=segMinus; i++) - { - var real = i + remainder * i; - - - var angle = ((theta) + startAngle + (theta2 * real)); - - var c = Math.cos(angle); - var s = -Math.sin(angle); - - points.push(( (cTheta * c) + (sTheta * s) ) * radius + cx, - ( (cTheta * -s) + (sTheta * c) ) * radius + cy); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {Number} the color of the fill - * @param alpha {Number} the alpha of the fill - * @return {Graphics} - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha === undefined) ? 1 : alpha; - - if(this.currentPath) - { - if(this.currentPath.shape.points.length <= 2) - { - this.currentPath.fill = this.filling; - this.currentPath.fillColor = this.fillColor; - this.currentPath.fillAlpha = this.fillAlpha; - } - } - return this; -}; - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - * @return {Graphics} - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; - - return this; -}; - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - this.drawShape(new PIXI.Rectangle(x,y, width, height)); - - return this; -}; - -/** - * @method drawRoundedRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @param radius {Number} Radius of the rectangle corners - */ -PIXI.Graphics.prototype.drawRoundedRect = function( x, y, width, height, radius ) -{ - this.drawShape(new PIXI.RoundedRectangle(x, y, width, height, radius)); - - return this; -}; - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coordinate of the center of the circle - * @param y {Number} The Y coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawCircle = function(x, y, radius) -{ - this.drawShape(new PIXI.Circle(x,y, radius)); - - return this; -}; - -/** - * Draws an ellipse. - * - * @method drawEllipse - * @param x {Number} The X coordinate of the center of the ellipse - * @param y {Number} The Y coordinate of the center of the ellipse - * @param width {Number} The half width of the ellipse - * @param height {Number} The half height of the ellipse - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawEllipse = function(x, y, width, height) -{ - this.drawShape(new PIXI.Ellipse(x, y, width, height)); - - return this; -}; - -/** - * Draws a polygon using the given path. - * - * @method drawPolygon - * @param path {Array} The path data used to construct the polygon. - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawPolygon = function(path) -{ - if(!(path instanceof Array))path = Array.prototype.slice.call(arguments); - this.drawShape(new PIXI.Polygon(path)); - return this; -}; - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - * @return {Graphics} - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = this.boundsDirty = true; - this.clearDirty = true; - this.graphicsData = []; - - return this; -}; - -/** - * Useful function that returns a texture of the graphics object that can then be used to create sprites - * This can be quite useful if your geometry is complicated and needs to be reused multiple times. - * - * @method generateTexture - * @param resolution {Number} The resolution of the texture being generated - * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts - * @return {Texture} a texture of the graphics object - */ -PIXI.Graphics.prototype.generateTexture = function(resolution, scaleMode) -{ - resolution = resolution || 1; - - var bounds = this.getBounds(); - - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width * resolution, bounds.height * resolution); - - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas, scaleMode); - texture.baseTexture.resolution = resolution; - - canvasBuffer.context.scale(resolution, resolution); - - canvasBuffer.context.translate(-bounds.x,-bounds.y); - - PIXI.CanvasGraphics.renderGraphics(this, canvasBuffer.context); - - return texture; -}; - -/** -* Renders the object using the WebGL renderer -* -* @method _renderWebGL -* @param renderSession {RenderSession} -* @private -*/ -PIXI.Graphics.prototype._renderWebGL = function(renderSession) -{ - // if the sprite is not visible or the alpha is 0 then no need to render this element - if(this.visible === false || this.alpha === 0 || this.isMask === true)return; - - if(this._cacheAsBitmap) - { - - if(this.dirty || this.cachedSpriteDirty) - { - - this._generateCachedSprite(); - - // we will also need to update the texture on the gpu too! - this.updateCachedSpriteTexture(); - - this.cachedSpriteDirty = false; - this.dirty = false; - } - - this._cachedSprite.worldAlpha = this.worldAlpha; - PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession); - - return; - } - else - { - renderSession.spriteBatch.stop(); - renderSession.blendModeManager.setBlendMode(this.blendMode); - - if(this._mask)renderSession.maskManager.pushMask(this._mask, renderSession); - if(this._filters)renderSession.filterManager.pushFilter(this._filterBlock); - - // check blend mode - if(this.blendMode !== renderSession.spriteBatch.currentBlendMode) - { - renderSession.spriteBatch.currentBlendMode = this.blendMode; - var blendModeWebGL = PIXI.blendModesWebGL[renderSession.spriteBatch.currentBlendMode]; - renderSession.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]); - } - - // check if the webgl graphic needs to be updated - if(this.webGLDirty) - { - this.dirty = true; - this.webGLDirty = false; - } - - PIXI.WebGLGraphics.renderGraphics(this, renderSession); - - // only render if it has children! - if(this.children.length) - { - renderSession.spriteBatch.start(); - - // simple render children! - for(var i=0, j=this.children.length; i maxX ? x2 : maxX; - maxX = x3 > maxX ? x3 : maxX; - maxX = x4 > maxX ? x4 : maxX; - - maxY = y2 > maxY ? y2 : maxY; - maxY = y3 > maxY ? y3 : maxY; - maxY = y4 > maxY ? y4 : maxY; - - this._bounds.x = minX; - this._bounds.width = maxX - minX; - - this._bounds.y = minY; - this._bounds.height = maxY - minY; - - return this._bounds; -}; - -/** - * Update the bounds of the object - * - * @method updateLocalBounds - */ -PIXI.Graphics.prototype.updateLocalBounds = function() -{ - var minX = Infinity; - var maxX = -Infinity; - - var minY = Infinity; - var maxY = -Infinity; - - - - if(this.graphicsData.length) - { - var shape, points, x, y, w, h; - - for (var i = 0; i < this.graphicsData.length; i++) { - var data = this.graphicsData[i]; - var type = data.type; - var lineWidth = data.lineWidth; - shape = data.shape; - - - if(type === PIXI.Graphics.RECT || type === PIXI.Graphics.RREC) - { - x = shape.x - lineWidth/2; - y = shape.y - lineWidth/2; - w = shape.width + lineWidth; - h = shape.height + lineWidth; - - minX = x < minX ? x : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y < minY ? y : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.CIRC) - { - x = shape.x; - y = shape.y; - w = shape.radius + lineWidth/2; - h = shape.radius + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.ELIP) - { - x = shape.x; - y = shape.y; - w = shape.width + lineWidth/2; - h = shape.height + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else - { - // POLY - points = shape.points; - - for (var j = 0; j < points.length; j+=2) - { - - x = points[j]; - y = points[j+1]; - minX = x-lineWidth < minX ? x-lineWidth : minX; - maxX = x+lineWidth > maxX ? x+lineWidth : maxX; - - minY = y-lineWidth < minY ? y-lineWidth : minY; - maxY = y+lineWidth > maxY ? y+lineWidth : maxY; - } - } - } - } - else - { - minX = 0; - maxX = 0; - minY = 0; - maxY = 0; - } - - var padding = this.boundsPadding; - - this._localBounds.x = minX - padding; - this._localBounds.width = (maxX - minX) + padding * 2; - - this._localBounds.y = minY - padding; - this._localBounds.height = (maxY - minY) + padding * 2; -}; - -/** - * Generates the cached sprite when the sprite has cacheAsBitmap = true - * - * @method _generateCachedSprite - * @private - */ -PIXI.Graphics.prototype._generateCachedSprite = function() -{ - var bounds = this.getLocalBounds(); - - if(!this._cachedSprite) - { - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height); - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas); - - this._cachedSprite = new PIXI.Sprite(texture); - this._cachedSprite.buffer = canvasBuffer; - - this._cachedSprite.worldTransform = this.worldTransform; - } - else - { - this._cachedSprite.buffer.resize(bounds.width, bounds.height); - } - - // leverage the anchor to account for the offset of the element - this._cachedSprite.anchor.x = -( bounds.x / bounds.width ); - this._cachedSprite.anchor.y = -( bounds.y / bounds.height ); - - // this._cachedSprite.buffer.context.save(); - this._cachedSprite.buffer.context.translate(-bounds.x,-bounds.y); - - // make sure we set the alpha of the graphics to 1 for the render.. - this.worldAlpha = 1; - - // now render the graphic.. - PIXI.CanvasGraphics.renderGraphics(this, this._cachedSprite.buffer.context); - this._cachedSprite.alpha = this.alpha; - -}; - -/** - * Updates texture size based on canvas size - * - * @method updateCachedSpriteTexture - * @private - */ -PIXI.Graphics.prototype.updateCachedSpriteTexture = function() -{ - var cachedSprite = this._cachedSprite; - var texture = cachedSprite.texture; - var canvas = cachedSprite.buffer.canvas; - - texture.baseTexture.width = canvas.width; - texture.baseTexture.height = canvas.height; - texture.crop.width = texture.frame.width = canvas.width; - texture.crop.height = texture.frame.height = canvas.height; - - cachedSprite._width = canvas.width; - cachedSprite._height = canvas.height; - - // update the dirty base textures - texture.baseTexture.dirty(); -}; - -/** - * Destroys a previous cached sprite. - * - * @method destroyCachedSprite - */ -PIXI.Graphics.prototype.destroyCachedSprite = function() -{ - this._cachedSprite.texture.destroy(true); - - // let the gc collect the unused sprite - // TODO could be object pooled! - this._cachedSprite = null; -}; - -/** - * Draws the given shape to this Graphics object. Can be any of Circle, Rectangle, Ellipse, Line or Polygon. - * - * @method drawShape - * @param {Circle|Rectangle|Ellipse|Line|Polygon} shape The Shape object to draw. - * @return {GraphicsData} The generated GraphicsData object. - */ -PIXI.Graphics.prototype.drawShape = function(shape) -{ - if(this.currentPath) - { - // check current path! - if(this.currentPath.shape.points.length <= 2)this.graphicsData.pop(); - } - - this.currentPath = null; - - var data = new PIXI.GraphicsData(this.lineWidth, this.lineColor, this.lineAlpha, this.fillColor, this.fillAlpha, this.filling, shape); - - this.graphicsData.push(data); - - if(data.type === PIXI.Graphics.POLY) - { - data.shape.closed = this.filling; - this.currentPath = data; - } - - this.dirty = this.boundsDirty = true; - - return data; -}; - -/** - * A GraphicsData object. - * - * @class GraphicsData - * @constructor - */ -PIXI.GraphicsData = function(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, shape) -{ - this.lineWidth = lineWidth; - this.lineColor = lineColor; - this.lineAlpha = lineAlpha; - this._lineTint = lineColor; - - this.fillColor = fillColor; - this.fillAlpha = fillAlpha; - this._fillTint = fillColor; - this.fill = fill; - - this.shape = shape; - this.type = shape.type; -}; - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; -PIXI.Graphics.RREC = 4; - -PIXI.Polygon.prototype.type = PIXI.Graphics.POLY; -PIXI.Rectangle.prototype.type = PIXI.Graphics.RECT; -PIXI.Circle.prototype.type = PIXI.Graphics.CIRC; -PIXI.Ellipse.prototype.type = PIXI.Graphics.ELIP; -PIXI.RoundedRectangle.prototype.type = PIXI.Graphics.RREC; - diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js deleted file mode 100644 index 82dbc05..0000000 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ /dev/null @@ -1,558 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.glContexts = []; // this is where we store the webGL contexts for easy access. -PIXI.instances = []; - -/** - * The WebGLRenderer draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers that support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batches or Sprite Clouds. - * Don't forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param [width=0] {Number} the width of the canvas view - * @param [height=0] {Number} the height of the canvas view - * @param [options] {Object} The optional renderer parameters - * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional - * @param [options.transparent=false] {Boolean} If the render view is transparent, default false - * @param [options.autoResize=false] {Boolean} If the render view is automatically resized, default false - * @param [options.antialias=false] {Boolean} sets antialias (only applicable in chrome at the moment) - * @param [options.preserveDrawingBuffer=false] {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context - * @param [options.resolution=1] {Number} the resolution of the renderer retina would be 2 - */ -PIXI.WebGLRenderer = function(width, height, options) -{ - if(options) - { - for (var i in PIXI.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') options[i] = PIXI.defaultRenderOptions[i]; - } - } - else - { - options = PIXI.defaultRenderOptions; - } - - if(!PIXI.defaultRenderer) - { - PIXI.sayHello('webGL'); - PIXI.defaultRenderer = this; - } - - /** - * @property type - * @type Number - */ - this.type = PIXI.WEBGL_RENDERER; - - /** - * The resolution of the renderer - * - * @property resolution - * @type Number - * @default 1 - */ - this.resolution = options.resolution; - - // do a catch.. only 1 webGL renderer.. - - /** - * Whether the render view is transparent - * - * @property transparent - * @type Boolean - */ - this.transparent = options.transparent; - - /** - * Whether the render view should be resized automatically - * - * @property autoResize - * @type Boolean - */ - this.autoResize = options.autoResize || false; - - /** - * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. - * - * @property preserveDrawingBuffer - * @type Boolean - */ - this.preserveDrawingBuffer = options.preserveDrawingBuffer; - - /** - * This sets if the WebGLRenderer will clear the context texture or not before the new render pass. If true: - * If the Stage is NOT transparent, Pixi will clear to alpha (0, 0, 0, 0). - * If the Stage is transparent, Pixi will clear to the target Stage's background color. - * Disable this by setting this to false. For example: if your game has a canvas filling background image, you often don't need this set. - * - * @property clearBeforeRender - * @type Boolean - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that everything is drawn to - * - * @property view - * @type HTMLCanvasElement - */ - this.view = options.view || document.createElement( 'canvas' ); - - // deal with losing context.. - - /** - * @property contextLostBound - * @type Function - */ - this.contextLostBound = this.handleContextLost.bind(this); - - /** - * @property contextRestoredBound - * @type Function - */ - this.contextRestoredBound = this.handleContextRestored.bind(this); - - this.view.addEventListener('webglcontextlost', this.contextLostBound, false); - this.view.addEventListener('webglcontextrestored', this.contextRestoredBound, false); - - /** - * @property _contextOptions - * @type Object - * @private - */ - this._contextOptions = { - alpha: this.transparent, - antialias: options.antialias, // SPEED UP?? - premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', - stencil:true, - preserveDrawingBuffer: options.preserveDrawingBuffer - }; - - /** - * @property projection - * @type Point - */ - this.projection = new PIXI.Point(); - - /** - * @property offset - * @type Point - */ - this.offset = new PIXI.Point(0, 0); - - // time to create the render managers! each one focuses on managing a state in webGL - - /** - * Deals with managing the shader programs and their attribs - * @property shaderManager - * @type WebGLShaderManager - */ - this.shaderManager = new PIXI.WebGLShaderManager(); - - /** - * Manages the rendering of sprites - * @property spriteBatch - * @type WebGLSpriteBatch - */ - this.spriteBatch = new PIXI.WebGLSpriteBatch(); - - /** - * Manages the masks using the stencil buffer - * @property maskManager - * @type WebGLMaskManager - */ - this.maskManager = new PIXI.WebGLMaskManager(); - - /** - * Manages the filters - * @property filterManager - * @type WebGLFilterManager - */ - this.filterManager = new PIXI.WebGLFilterManager(); - - /** - * Manages the stencil buffer - * @property stencilManager - * @type WebGLStencilManager - */ - this.stencilManager = new PIXI.WebGLStencilManager(); - - /** - * Manages the blendModes - * @property blendModeManager - * @type WebGLBlendModeManager - */ - this.blendModeManager = new PIXI.WebGLBlendModeManager(); - - /** - * TODO remove - * @property renderSession - * @type Object - */ - this.renderSession = {}; - this.renderSession.gl = this.gl; - this.renderSession.drawCount = 0; - this.renderSession.shaderManager = this.shaderManager; - this.renderSession.maskManager = this.maskManager; - this.renderSession.filterManager = this.filterManager; - this.renderSession.blendModeManager = this.blendModeManager; - this.renderSession.spriteBatch = this.spriteBatch; - this.renderSession.stencilManager = this.stencilManager; - this.renderSession.renderer = this; - this.renderSession.resolution = this.resolution; - this.renderSession.buffer = null; - - // time init the context.. - this.initContext(); - - // map some webGL blend modes.. - this.mapBlendModes(); -}; - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** -* @method initContext -*/ -PIXI.WebGLRenderer.prototype.initContext = function() -{ - var gl = this.view.getContext('webgl', this._contextOptions) || this.view.getContext('experimental-webgl', this._contextOptions); - this.gl = gl; - - if (!gl) { - // fail, not able to get a context - throw new Error('This browser does not support webGL. Try using the canvas renderer'); - } - - this.glContextId = gl.id = PIXI.WebGLRenderer.glContextId ++; - - PIXI.glContexts[this.glContextId] = gl; - - PIXI.instances[this.glContextId] = this; - - // set up the default pixi settings.. - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); - - // need to set the context for all the managers... - this.shaderManager.setContext(gl); - this.spriteBatch.setContext(gl); - this.maskManager.setContext(gl); - this.filterManager.setContext(gl); - this.blendModeManager.setContext(gl); - this.stencilManager.setContext(gl); - - this.renderSession.gl = this.gl; - - // now resize and we are good to go! - this.resize(this.width, this.height); -}; - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - // no point rendering if our context has been blown up! - if(this.contextLost)return; - - // if rendering a new stage clear the batches.. - if(this.__stage !== stage) - { - if(stage.interactive)stage.interactionManager.removeEvents(); - - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - } - - // update the scene graph - stage.updateTransform(); - - var gl = this.gl; - - // interaction - if(stage._interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - else - { - if(stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = false; - stage.interactionManager.setTarget(this); - } - } - - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - - // make sure we are bound to the main frame buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - if (this.clearBeforeRender) - { - if(this.transparent) - { - gl.clearColor(0, 0, 0, 0); - } - else - { - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); - } - - gl.clear (gl.COLOR_BUFFER_BIT); - } - - this.renderDisplayObject( stage, this.projection ); -}; - -/** - * Renders a Display Object. - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The DisplayObject to render - * @param projection {Point} The projection - * @param buffer {Array} a standard WebGL buffer - */ -PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection, buffer) -{ - this.renderSession.blendModeManager.setBlendMode(PIXI.blendModes.NORMAL); - - // reset the render session data.. - this.renderSession.drawCount = 0; - - // set the buffer ref.. - this.renderSession.buffer = buffer; - - // make sure to flip the Y if using a render texture.. - this.renderSession.flipY = buffer ? -1 : 1; - - // set the default projection - this.renderSession.projection = projection; - - //set the default offset - this.renderSession.offset = this.offset; - - // start the sprite batch - this.spriteBatch.begin(this.renderSession); - - // start the filter manager - this.filterManager.begin(this.renderSession, buffer); - - // render the scene! - displayObject._renderWebGL(this.renderSession); - - // finish the sprite batch - this.spriteBatch.end(); -}; - -/** - * Resizes the webGL view to the specified width and height. - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width * this.resolution; - this.height = height * this.resolution; - - this.view.width = this.width; - this.view.height = this.height; - - if (this.autoResize) { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } - - this.gl.viewport(0, 0, this.width, this.height); - - this.projection.x = this.width / 2 / this.resolution; - this.projection.y = -this.height / 2 / this.resolution; -}; - -/** - * Updates and Creates a WebGL texture for the renderers context. - * - * @method updateTexture - * @param texture {Texture} the texture to update - */ -PIXI.WebGLRenderer.prototype.updateTexture = function(texture) -{ - if(!texture.hasLoaded )return; - - var gl = this.gl; - - if(!texture._glTextures[gl.id])texture._glTextures[gl.id] = gl.createTexture(); - - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - - - if(texture.mipmap && PIXI.isPowerOfTwo(texture.width, texture.height)) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); - gl.generateMipmap(gl.TEXTURE_2D); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - } - - // reguler... - if(!texture._powerOf2) - { - 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); - } - - texture._dirty[gl.id] = false; - - return texture._glTextures[gl.id]; -}; - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -}; - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function() -{ - this.initContext(); - - // empty all the ol gl textures as they are useless now - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTextures = []; - } - - this.contextLost = false; -}; - -/** - * Removes everything from the renderer (event listeners, spritebatch, etc...) - * - * @method destroy - */ -PIXI.WebGLRenderer.prototype.destroy = function() -{ - // remove listeners - this.view.removeEventListener('webglcontextlost', this.contextLostBound); - this.view.removeEventListener('webglcontextrestored', this.contextRestoredBound); - - PIXI.glContexts[this.glContextId] = null; - - this.projection = null; - this.offset = null; - - // time to create the render managers! each one focuses on managine a state in webGL - this.shaderManager.destroy(); - this.spriteBatch.destroy(); - this.maskManager.destroy(); - this.filterManager.destroy(); - - this.shaderManager = null; - this.spriteBatch = null; - this.maskManager = null; - this.filterManager = null; - - this.gl = null; - this.renderSession = null; -}; - -/** - * Maps Pixi blend modes to WebGL blend modes. - * - * @method mapBlendModes - */ -PIXI.WebGLRenderer.prototype.mapBlendModes = function() -{ - var gl = this.gl; - - if(!PIXI.blendModesWebGL) - { - PIXI.blendModesWebGL = []; - - PIXI.blendModesWebGL[PIXI.blendModes.NORMAL] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.ADD] = [gl.SRC_ALPHA, gl.DST_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.MULTIPLY] = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SCREEN] = [gl.SRC_ALPHA, gl.ONE]; - PIXI.blendModesWebGL[PIXI.blendModes.OVERLAY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DARKEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LIGHTEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_DODGE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_BURN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HARD_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SOFT_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DIFFERENCE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.EXCLUSION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HUE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - } -}; - -PIXI.WebGLRenderer.glContextId = 0; diff --git a/src/pixi/renderers/webgl/shaders/PixiShader.js b/src/pixi/renderers/webgl/shaders/PixiShader.js deleted file mode 100644 index bb4a17d..0000000 --- a/src/pixi/renderers/webgl/shaders/PixiShader.js +++ /dev/null @@ -1,397 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * @author Richard Davey http://www.photonstorm.com @photonstorm - */ - -/** -* @class PixiShader -* @constructor -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.PixiShader = function(gl) -{ - /** - * @property _UID - * @type Number - * @private - */ - this._UID = PIXI._UID++; - - /** - * @property gl - * @type WebGLContext - */ - this.gl = gl; - - /** - * The WebGL program. - * @property program - * @type Any - */ - this.program = null; - - /** - * The fragment shader. - * @property fragmentSrc - * @type Array - */ - this.fragmentSrc = [ - 'precision lowp float;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - 'uniform sampler2D uSampler;', - 'void main(void) {', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;', - '}' - ]; - - /** - * A local texture counter for multi-texture shaders. - * @property textureCount - * @type Number - */ - this.textureCount = 0; - - /** - * A local flag - * @property firstRun - * @type Boolean - * @private - */ - this.firstRun = true; - - /** - * A dirty flag - * @property dirty - * @type Boolean - */ - this.dirty = true; - - /** - * Uniform attributes cache. - * @property attributes - * @type Array - * @private - */ - this.attributes = []; - - this.init(); -}; - -PIXI.PixiShader.prototype.constructor = PIXI.PixiShader; - -/** -* Initialises the shader. -* -* @method init -*/ -PIXI.PixiShader.prototype.init = function() -{ - var gl = this.gl; - - var program = PIXI.compileProgram(gl, this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc); - - gl.useProgram(program); - - // get and store the uniforms for the shader - this.uSampler = gl.getUniformLocation(program, 'uSampler'); - this.projectionVector = gl.getUniformLocation(program, 'projectionVector'); - this.offsetVector = gl.getUniformLocation(program, 'offsetVector'); - this.dimensions = gl.getUniformLocation(program, 'dimensions'); - this.flipY = gl.getUniformLocation(program, 'flipY'); - - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition'); - this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord'); - this.colorAttribute = gl.getAttribLocation(program, 'aColor'); - - - // Begin worst hack eva // - - // WHY??? ONLY on my chrome pixel the line above returns -1 when using filters? - // maybe its something to do with the current state of the gl context. - // I'm convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel - // If theres any webGL people that know why could happen please help :) - if(this.colorAttribute === -1) - { - this.colorAttribute = 2; - } - - this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute]; - - // End worst hack eva // - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key); - } - - this.initUniforms(); - - this.program = program; -}; - -/** -* Initialises the shader uniform values. -* -* Uniforms are specified in the GLSL_ES Specification: http://www.khronos.org/registry/webgl/specs/latest/1.0/ -* http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf -* -* @method initUniforms -*/ -PIXI.PixiShader.prototype.initUniforms = function() -{ - this.textureCount = 1; - var gl = this.gl; - var uniform; - - for (var key in this.uniforms) - { - uniform = this.uniforms[key]; - - var type = uniform.type; - - if (type === 'sampler2D') - { - uniform._init = false; - - if (uniform.value !== null) - { - this.initSampler2D(uniform); - } - } - else if (type === 'mat2' || type === 'mat3' || type === 'mat4') - { - // These require special handling - uniform.glMatrix = true; - uniform.glValueLength = 1; - - if (type === 'mat2') - { - uniform.glFunc = gl.uniformMatrix2fv; - } - else if (type === 'mat3') - { - uniform.glFunc = gl.uniformMatrix3fv; - } - else if (type === 'mat4') - { - uniform.glFunc = gl.uniformMatrix4fv; - } - } - else - { - // GL function reference - uniform.glFunc = gl['uniform' + type]; - - if (type === '2f' || type === '2i') - { - uniform.glValueLength = 2; - } - else if (type === '3f' || type === '3i') - { - uniform.glValueLength = 3; - } - else if (type === '4f' || type === '4i') - { - uniform.glValueLength = 4; - } - else - { - uniform.glValueLength = 1; - } - } - } - -}; - -/** -* Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture has loaded) -* -* @method initSampler2D -*/ -PIXI.PixiShader.prototype.initSampler2D = function(uniform) -{ - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) - { - return; - } - - var gl = this.gl; - - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); - - // Extended texture data - if (uniform.textureData) - { - var data = uniform.textureData; - - // GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D); - // GLTextureLinear = mag/min linear, wrap clamp - // GLTextureNearestRepeat = mag/min NEAREST, wrap repeat - // GLTextureNearest = mag/min nearest, wrap clamp - // AudioTexture = whatever + luminance + width 512, height 2, border 0 - // KeyTexture = whatever + luminance + width 256, height 2, border 0 - - // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST - // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; - - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } - - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); - } - - gl.uniform1i(uniform.uniformLocation, this.textureCount); - - uniform._init = true; - - this.textureCount++; - -}; - -/** -* Updates the shader uniform values. -* -* @method syncUniforms -*/ -PIXI.PixiShader.prototype.syncUniforms = function() -{ - this.textureCount = 1; - var uniform; - var gl = this.gl; - - // This would probably be faster in an array and it would guarantee key order - for (var key in this.uniforms) - { - uniform = this.uniforms[key]; - - if (uniform.glValueLength === 1) - { - if (uniform.glMatrix === true) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.transpose, uniform.value); - } - else - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value); - } - } - else if (uniform.glValueLength === 2) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y); - } - else if (uniform.glValueLength === 3) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z); - } - else if (uniform.glValueLength === 4) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z, uniform.value.w); - } - else if (uniform.type === 'sampler2D') - { - if (uniform._init) - { - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - - if(uniform.value.baseTexture._dirty[gl.id]) - { - PIXI.instances[gl.id].updateTexture(uniform.value.baseTexture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); - } - - // gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id] || PIXI.createWebGLTexture( uniform.value.baseTexture, gl)); - gl.uniform1i(uniform.uniformLocation, this.textureCount); - this.textureCount++; - } - else - { - this.initSampler2D(uniform); - } - } - } - -}; - -/** -* Destroys the shader. -* -* @method destroy -*/ -PIXI.PixiShader.prototype.destroy = function() -{ - this.gl.deleteProgram( this.program ); - this.uniforms = null; - this.gl = null; - - this.attributes = null; -}; - -/** -* The Default Vertex shader source. -* -* @property defaultVertexSrc -* @type String -*/ -PIXI.PixiShader.defaultVertexSrc = [ - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - - 'uniform float flipY;', - - 'uniform vec2 projectionVector;', - 'uniform vec2 offsetVector;', - - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'void main(void) {', - - ' vec3 temp = vec3(-1.0, 1.0, flipY);', - - ' gl_Position = vec4( (aVertexPosition + offsetVector) / (projectionVector * temp.yz) + temp.xz , 0.0, 1.0);', - - ' vTextureCoord = aTextureCoord;', - - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - - '}' -]; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/utils/WebGLFilterManager.js b/src/pixi/renderers/webgl/utils/WebGLFilterManager.js deleted file mode 100644 index ba642c3..0000000 --- a/src/pixi/renderers/webgl/utils/WebGLFilterManager.js +++ /dev/null @@ -1,452 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** -* @class WebGLFilterManager -* @constructor -*/ -PIXI.WebGLFilterManager = function() -{ - /** - * @property filterStack - * @type Array - */ - this.filterStack = []; - - /** - * @property offsetX - * @type Number - */ - this.offsetX = 0; - - /** - * @property offsetY - * @type Number - */ - this.offsetY = 0; -}; - -PIXI.WebGLFilterManager.prototype.constructor = PIXI.WebGLFilterManager; - -/** -* Initialises the context and the properties. -* -* @method setContext -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.WebGLFilterManager.prototype.setContext = function(gl) -{ - this.gl = gl; - this.texturePool = []; - - this.initShaderBuffers(); -}; - -/** -* @method begin -* @param renderSession {RenderSession} -* @param buffer {ArrayBuffer} -*/ -PIXI.WebGLFilterManager.prototype.begin = function(renderSession, buffer) -{ - this.renderSession = renderSession; - this.defaultShader = renderSession.shaderManager.defaultShader; - - var projection = this.renderSession.projection; - this.width = projection.x * 2; - this.height = -projection.y * 2; - this.buffer = buffer; -}; - -/** -* Applies the filter and adds it to the current filter stack. -* -* @method pushFilter -* @param filterBlock {Object} the filter that will be pushed to the current filter stack -*/ -PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock) -{ - var gl = this.gl; - - var projection = this.renderSession.projection; - var offset = this.renderSession.offset; - - filterBlock._filterArea = filterBlock.target.filterArea || filterBlock.target.getBounds(); - - // filter program - // OPTIMISATION - the first filter is free if its a simple color change? - this.filterStack.push(filterBlock); - - var filter = filterBlock.filterPasses[0]; - - this.offsetX += filterBlock._filterArea.x; - this.offsetY += filterBlock._filterArea.y; - - var texture = this.texturePool.pop(); - if(!texture) - { - texture = new PIXI.FilterTexture(this.gl, this.width, this.height); - } - else - { - texture.resize(this.width, this.height); - } - - gl.bindTexture(gl.TEXTURE_2D, texture.texture); - - var filterArea = filterBlock._filterArea;// filterBlock.target.getBounds();///filterBlock.target.filterArea; - - var padding = filter.padding; - filterArea.x -= padding; - filterArea.y -= padding; - filterArea.width += padding * 2; - filterArea.height += padding * 2; - - // cap filter to screen size.. - if(filterArea.x < 0)filterArea.x = 0; - if(filterArea.width > this.width)filterArea.width = this.width; - if(filterArea.y < 0)filterArea.y = 0; - if(filterArea.height > this.height)filterArea.height = this.height; - - //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - gl.bindFramebuffer(gl.FRAMEBUFFER, texture.frameBuffer); - - // set view port - gl.viewport(0, 0, filterArea.width, filterArea.height); - - projection.x = filterArea.width/2; - projection.y = -filterArea.height/2; - - offset.x = -filterArea.x; - offset.y = -filterArea.y; - - // update projection - // now restore the regular shader.. - // this.renderSession.shaderManager.setShader(this.defaultShader); - //gl.uniform2f(this.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2); - //gl.uniform2f(this.defaultShader.offsetVector, -filterArea.x, -filterArea.y); - - gl.colorMask(true, true, true, true); - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - - filterBlock._glFilterTexture = texture; - -}; - -/** -* Removes the last filter from the filter stack and doesn't return it. -* -* @method popFilter -*/ -PIXI.WebGLFilterManager.prototype.popFilter = function() -{ - var gl = this.gl; - var filterBlock = this.filterStack.pop(); - var filterArea = filterBlock._filterArea; - var texture = filterBlock._glFilterTexture; - var projection = this.renderSession.projection; - var offset = this.renderSession.offset; - - if(filterBlock.filterPasses.length > 1) - { - gl.viewport(0, 0, filterArea.width, filterArea.height); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - - this.vertexArray[0] = 0; - this.vertexArray[1] = filterArea.height; - - this.vertexArray[2] = filterArea.width; - this.vertexArray[3] = filterArea.height; - - this.vertexArray[4] = 0; - this.vertexArray[5] = 0; - - this.vertexArray[6] = filterArea.width; - this.vertexArray[7] = 0; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - // now set the uvs.. - this.uvArray[2] = filterArea.width/this.width; - this.uvArray[5] = filterArea.height/this.height; - this.uvArray[6] = filterArea.width/this.width; - this.uvArray[7] = filterArea.height/this.height; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); - - var inputTexture = texture; - var outputTexture = this.texturePool.pop(); - if(!outputTexture)outputTexture = new PIXI.FilterTexture(this.gl, this.width, this.height); - outputTexture.resize(this.width, this.height); - - // need to clear this FBO as it may have some left over elements from a previous filter. - gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); - gl.clear(gl.COLOR_BUFFER_BIT); - - gl.disable(gl.BLEND); - - for (var i = 0; i < filterBlock.filterPasses.length-1; i++) - { - var filterPass = filterBlock.filterPasses[i]; - - gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); - - // set texture - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture); - - // draw texture.. - //filterPass.applyFilterPass(filterArea.width, filterArea.height); - this.applyFilterPass(filterPass, filterArea, filterArea.width, filterArea.height); - - // swap the textures.. - var temp = inputTexture; - inputTexture = outputTexture; - outputTexture = temp; - } - - gl.enable(gl.BLEND); - - texture = inputTexture; - this.texturePool.push(outputTexture); - } - - var filter = filterBlock.filterPasses[filterBlock.filterPasses.length-1]; - - this.offsetX -= filterArea.x; - this.offsetY -= filterArea.y; - - var sizeX = this.width; - var sizeY = this.height; - - var offsetX = 0; - var offsetY = 0; - - var buffer = this.buffer; - - // time to render the filters texture to the previous scene - if(this.filterStack.length === 0) - { - gl.colorMask(true, true, true, true);//this.transparent); - } - else - { - var currentFilter = this.filterStack[this.filterStack.length-1]; - filterArea = currentFilter._filterArea; - - sizeX = filterArea.width; - sizeY = filterArea.height; - - offsetX = filterArea.x; - offsetY = filterArea.y; - - buffer = currentFilter._glFilterTexture.frameBuffer; - } - - // TODO need to remove these global elements.. - projection.x = sizeX/2; - projection.y = -sizeY/2; - - offset.x = offsetX; - offset.y = offsetY; - - filterArea = filterBlock._filterArea; - - var x = filterArea.x-offsetX; - var y = filterArea.y-offsetY; - - // update the buffers.. - // make sure to flip the y! - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - - this.vertexArray[0] = x; - this.vertexArray[1] = y + filterArea.height; - - this.vertexArray[2] = x + filterArea.width; - this.vertexArray[3] = y + filterArea.height; - - this.vertexArray[4] = x; - this.vertexArray[5] = y; - - this.vertexArray[6] = x + filterArea.width; - this.vertexArray[7] = y; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - this.uvArray[2] = filterArea.width/this.width; - this.uvArray[5] = filterArea.height/this.height; - this.uvArray[6] = filterArea.width/this.width; - this.uvArray[7] = filterArea.height/this.height; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); - - gl.viewport(0, 0, sizeX, sizeY); - - // bind the buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, buffer ); - - // set the blend mode! - //gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) - - // set texture - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture.texture); - - // apply! - this.applyFilterPass(filter, filterArea, sizeX, sizeY); - - // now restore the regular shader.. should happen automatically now.. - // this.renderSession.shaderManager.setShader(this.defaultShader); - // gl.uniform2f(this.defaultShader.projectionVector, sizeX/2, -sizeY/2); - // gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY); - - // return the texture to the pool - this.texturePool.push(texture); - filterBlock._glFilterTexture = null; -}; - - -/** -* Applies the filter to the specified area. -* -* @method applyFilterPass -* @param filter {AbstractFilter} the filter that needs to be applied -* @param filterArea {Texture} TODO - might need an update -* @param width {Number} the horizontal range of the filter -* @param height {Number} the vertical range of the filter -*/ -PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea, width, height) -{ - // use program - var gl = this.gl; - var shader = filter.shaders[gl.id]; - - if(!shader) - { - shader = new PIXI.PixiShader(gl); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shaders[gl.id] = shader; - } - - // set the shader - this.renderSession.shaderManager.setShader(shader); - -// gl.useProgram(shader.program); - - gl.uniform2f(shader.projectionVector, width/2, -height/2); - gl.uniform2f(shader.offsetVector, 0,0); - - gl.uniform1f(shader.flipY, this.renderSession.flipY); - - if(filter.uniforms.dimensions) - { - filter.uniforms.dimensions.value[0] = this.width;//width; - filter.uniforms.dimensions.value[1] = this.height;//height; - filter.uniforms.dimensions.value[2] = this.vertexArray[0]; - filter.uniforms.dimensions.value[3] = this.vertexArray[5];//filterArea.height; - } - - shader.syncUniforms(); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.vertexAttribPointer(shader.colorAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - // draw the filter... - gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - this.renderSession.drawCount++; -}; - -/** -* Initialises the shader buffers. -* -* @method initShaderBuffers -*/ -PIXI.WebGLFilterManager.prototype.initShaderBuffers = function() -{ - var gl = this.gl; - - // create some buffers - this.vertexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - - // bind and upload the vertexs.. - // keep a reference to the vertexFloatData.. - this.vertexArray = new PIXI.Float32Array([0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.vertexArray, gl.STATIC_DRAW); - - // bind and upload the uv buffer - this.uvArray = new PIXI.Float32Array([0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvArray, gl.STATIC_DRAW); - - this.colorArray = new PIXI.Float32Array([1.0, 0xFFFFFF, - 1.0, 0xFFFFFF, - 1.0, 0xFFFFFF, - 1.0, 0xFFFFFF]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colorArray, gl.STATIC_DRAW); - - // bind and upload the index - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 1, 3, 2]), gl.STATIC_DRAW); - -}; - -/** -* Destroys the filter and removes it from the filter stack. -* -* @method destroy -*/ -PIXI.WebGLFilterManager.prototype.destroy = function() -{ - var gl = this.gl; - - this.filterStack = null; - - this.offsetX = 0; - this.offsetY = 0; - - // destroy textures - for (var i = 0; i < this.texturePool.length; i++) { - this.texturePool[i].destroy(); - } - - this.texturePool = null; - - //destroy buffers.. - gl.deleteBuffer(this.vertexBuffer); - gl.deleteBuffer(this.uvBuffer); - gl.deleteBuffer(this.colorBuffer); - gl.deleteBuffer(this.indexBuffer); -}; diff --git a/src/pixi/renderers/webgl/utils/WebGLShaderManager.js b/src/pixi/renderers/webgl/utils/WebGLShaderManager.js deleted file mode 100644 index 168e4ac..0000000 --- a/src/pixi/renderers/webgl/utils/WebGLShaderManager.js +++ /dev/null @@ -1,158 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** -* @class WebGLShaderManager -* @constructor -* @private -*/ -PIXI.WebGLShaderManager = function() -{ - /** - * @property maxAttibs - * @type Number - */ - this.maxAttibs = 10; - - /** - * @property attribState - * @type Array - */ - this.attribState = []; - - /** - * @property tempAttribState - * @type Array - */ - this.tempAttribState = []; - - for (var i = 0; i < this.maxAttibs; i++) - { - this.attribState[i] = false; - } - - /** - * @property stack - * @type Array - */ - this.stack = []; - -}; - -PIXI.WebGLShaderManager.prototype.constructor = PIXI.WebGLShaderManager; - -/** -* Initialises the context and the properties. -* -* @method setContext -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.WebGLShaderManager.prototype.setContext = function(gl) -{ - this.gl = gl; - - // the next one is used for rendering primitives - this.primitiveShader = new PIXI.PrimitiveShader(gl); - - // the next one is used for rendering triangle strips - this.complexPrimitiveShader = new PIXI.ComplexPrimitiveShader(gl); - - // this shader is used for the default sprite rendering - this.defaultShader = new PIXI.PixiShader(gl); - - // this shader is used for the fast sprite rendering - this.fastShader = new PIXI.PixiFastShader(gl); - - // the next one is used for rendering triangle strips - this.stripShader = new PIXI.StripShader(gl); - this.setShader(this.defaultShader); -}; - -/** -* Takes the attributes given in parameters. -* -* @method setAttribs -* @param attribs {Array} attribs -*/ -PIXI.WebGLShaderManager.prototype.setAttribs = function(attribs) -{ - // reset temp state - var i; - - for (i = 0; i < this.tempAttribState.length; i++) - { - this.tempAttribState[i] = false; - } - - // set the new attribs - for (i = 0; i < attribs.length; i++) - { - var attribId = attribs[i]; - this.tempAttribState[attribId] = true; - } - - var gl = this.gl; - - for (i = 0; i < this.attribState.length; i++) - { - if(this.attribState[i] !== this.tempAttribState[i]) - { - this.attribState[i] = this.tempAttribState[i]; - - if(this.tempAttribState[i]) - { - gl.enableVertexAttribArray(i); - } - else - { - gl.disableVertexAttribArray(i); - } - } - } -}; - -/** -* Sets the current shader. -* -* @method setShader -* @param shader {Any} -*/ -PIXI.WebGLShaderManager.prototype.setShader = function(shader) -{ - if(this._currentId === shader._UID)return false; - - this._currentId = shader._UID; - - this.currentShader = shader; - - this.gl.useProgram(shader.program); - - this.setAttribs(shader.attributes); - - return true; -}; - -/** -* Destroys this object. -* -* @method destroy -*/ -PIXI.WebGLShaderManager.prototype.destroy = function() -{ - this.attribState = null; - - this.tempAttribState = null; - - this.primitiveShader.destroy(); - - this.complexPrimitiveShader.destroy(); - - this.defaultShader.destroy(); - - this.fastShader.destroy(); - - this.stripShader.destroy(); - - this.gl = null; -}; diff --git a/src/core/particles/webgl/ParticleRenderer.js b/src/core/particles/webgl/ParticleRenderer.js index 009c65d..ea55547 100644 --- a/src/core/particles/webgl/ParticleRenderer.js +++ b/src/core/particles/webgl/ParticleRenderer.js @@ -160,83 +160,20 @@ gl.uniformMatrix3fv(this.shader.uniforms.projectionMatrix._location, false, m.toArray(true)); - this.currentBatchSize = 0; -/* - var rotationDirty = false; - var positionDirty = false; - var vertsDirty = false; - var uvsDirty = false; - var alphaDirty = false;*/ - this.sprites = children; this.vertDirty = 0; - for (var i=0,j= children.length; i b2 * a1); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * The arc method creates an arc/curve (used to create circles, or parts of circles). - * - * @method arc - * @param cx {Number} The x-coordinate of the center of the circle - * @param cy {Number} The y-coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle) - * @param endAngle {Number} The ending angle, in radians - * @param anticlockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise. - * @return {Graphics} - */ -PIXI.Graphics.prototype.arc = function(cx, cy, radius, startAngle, endAngle, anticlockwise) -{ - var startX = cx + Math.cos(startAngle) * radius; - var startY = cy + Math.sin(startAngle) * radius; - var points; - - if( this.currentPath ) - { - points = this.currentPath.shape.points; - - if(points.length === 0) - { - points.push(startX, startY); - } - else if( points[points.length-2] !== startX || points[points.length-1] !== startY) - { - points.push(startX, startY); - } - } - else - { - this.moveTo(startX, startY); - points = this.currentPath.shape.points; - } - - if (startAngle === endAngle)return this; - - if( !anticlockwise && endAngle <= startAngle ) - { - endAngle += Math.PI * 2; - } - else if( anticlockwise && startAngle <= endAngle ) - { - startAngle += Math.PI * 2; - } - - var sweep = anticlockwise ? (startAngle - endAngle) *-1 : (endAngle - startAngle); - var segs = ( Math.abs(sweep)/ (Math.PI * 2) ) * 40; - - if( sweep === 0 ) return this; - - var theta = sweep/(segs*2); - var theta2 = theta*2; - - var cTheta = Math.cos(theta); - var sTheta = Math.sin(theta); - - var segMinus = segs - 1; - - var remainder = ( segMinus % 1 ) / segMinus; - - for(var i=0; i<=segMinus; i++) - { - var real = i + remainder * i; - - - var angle = ((theta) + startAngle + (theta2 * real)); - - var c = Math.cos(angle); - var s = -Math.sin(angle); - - points.push(( (cTheta * c) + (sTheta * s) ) * radius + cx, - ( (cTheta * -s) + (sTheta * c) ) * radius + cy); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {Number} the color of the fill - * @param alpha {Number} the alpha of the fill - * @return {Graphics} - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha === undefined) ? 1 : alpha; - - if(this.currentPath) - { - if(this.currentPath.shape.points.length <= 2) - { - this.currentPath.fill = this.filling; - this.currentPath.fillColor = this.fillColor; - this.currentPath.fillAlpha = this.fillAlpha; - } - } - return this; -}; - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - * @return {Graphics} - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; - - return this; -}; - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - this.drawShape(new PIXI.Rectangle(x,y, width, height)); - - return this; -}; - -/** - * @method drawRoundedRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @param radius {Number} Radius of the rectangle corners - */ -PIXI.Graphics.prototype.drawRoundedRect = function( x, y, width, height, radius ) -{ - this.drawShape(new PIXI.RoundedRectangle(x, y, width, height, radius)); - - return this; -}; - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coordinate of the center of the circle - * @param y {Number} The Y coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawCircle = function(x, y, radius) -{ - this.drawShape(new PIXI.Circle(x,y, radius)); - - return this; -}; - -/** - * Draws an ellipse. - * - * @method drawEllipse - * @param x {Number} The X coordinate of the center of the ellipse - * @param y {Number} The Y coordinate of the center of the ellipse - * @param width {Number} The half width of the ellipse - * @param height {Number} The half height of the ellipse - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawEllipse = function(x, y, width, height) -{ - this.drawShape(new PIXI.Ellipse(x, y, width, height)); - - return this; -}; - -/** - * Draws a polygon using the given path. - * - * @method drawPolygon - * @param path {Array} The path data used to construct the polygon. - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawPolygon = function(path) -{ - if(!(path instanceof Array))path = Array.prototype.slice.call(arguments); - this.drawShape(new PIXI.Polygon(path)); - return this; -}; - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - * @return {Graphics} - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = this.boundsDirty = true; - this.clearDirty = true; - this.graphicsData = []; - - return this; -}; - -/** - * Useful function that returns a texture of the graphics object that can then be used to create sprites - * This can be quite useful if your geometry is complicated and needs to be reused multiple times. - * - * @method generateTexture - * @param resolution {Number} The resolution of the texture being generated - * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts - * @return {Texture} a texture of the graphics object - */ -PIXI.Graphics.prototype.generateTexture = function(resolution, scaleMode) -{ - resolution = resolution || 1; - - var bounds = this.getBounds(); - - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width * resolution, bounds.height * resolution); - - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas, scaleMode); - texture.baseTexture.resolution = resolution; - - canvasBuffer.context.scale(resolution, resolution); - - canvasBuffer.context.translate(-bounds.x,-bounds.y); - - PIXI.CanvasGraphics.renderGraphics(this, canvasBuffer.context); - - return texture; -}; - -/** -* Renders the object using the WebGL renderer -* -* @method _renderWebGL -* @param renderSession {RenderSession} -* @private -*/ -PIXI.Graphics.prototype._renderWebGL = function(renderSession) -{ - // if the sprite is not visible or the alpha is 0 then no need to render this element - if(this.visible === false || this.alpha === 0 || this.isMask === true)return; - - if(this._cacheAsBitmap) - { - - if(this.dirty || this.cachedSpriteDirty) - { - - this._generateCachedSprite(); - - // we will also need to update the texture on the gpu too! - this.updateCachedSpriteTexture(); - - this.cachedSpriteDirty = false; - this.dirty = false; - } - - this._cachedSprite.worldAlpha = this.worldAlpha; - PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession); - - return; - } - else - { - renderSession.spriteBatch.stop(); - renderSession.blendModeManager.setBlendMode(this.blendMode); - - if(this._mask)renderSession.maskManager.pushMask(this._mask, renderSession); - if(this._filters)renderSession.filterManager.pushFilter(this._filterBlock); - - // check blend mode - if(this.blendMode !== renderSession.spriteBatch.currentBlendMode) - { - renderSession.spriteBatch.currentBlendMode = this.blendMode; - var blendModeWebGL = PIXI.blendModesWebGL[renderSession.spriteBatch.currentBlendMode]; - renderSession.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]); - } - - // check if the webgl graphic needs to be updated - if(this.webGLDirty) - { - this.dirty = true; - this.webGLDirty = false; - } - - PIXI.WebGLGraphics.renderGraphics(this, renderSession); - - // only render if it has children! - if(this.children.length) - { - renderSession.spriteBatch.start(); - - // simple render children! - for(var i=0, j=this.children.length; i maxX ? x2 : maxX; - maxX = x3 > maxX ? x3 : maxX; - maxX = x4 > maxX ? x4 : maxX; - - maxY = y2 > maxY ? y2 : maxY; - maxY = y3 > maxY ? y3 : maxY; - maxY = y4 > maxY ? y4 : maxY; - - this._bounds.x = minX; - this._bounds.width = maxX - minX; - - this._bounds.y = minY; - this._bounds.height = maxY - minY; - - return this._bounds; -}; - -/** - * Update the bounds of the object - * - * @method updateLocalBounds - */ -PIXI.Graphics.prototype.updateLocalBounds = function() -{ - var minX = Infinity; - var maxX = -Infinity; - - var minY = Infinity; - var maxY = -Infinity; - - - - if(this.graphicsData.length) - { - var shape, points, x, y, w, h; - - for (var i = 0; i < this.graphicsData.length; i++) { - var data = this.graphicsData[i]; - var type = data.type; - var lineWidth = data.lineWidth; - shape = data.shape; - - - if(type === PIXI.Graphics.RECT || type === PIXI.Graphics.RREC) - { - x = shape.x - lineWidth/2; - y = shape.y - lineWidth/2; - w = shape.width + lineWidth; - h = shape.height + lineWidth; - - minX = x < minX ? x : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y < minY ? y : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.CIRC) - { - x = shape.x; - y = shape.y; - w = shape.radius + lineWidth/2; - h = shape.radius + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.ELIP) - { - x = shape.x; - y = shape.y; - w = shape.width + lineWidth/2; - h = shape.height + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else - { - // POLY - points = shape.points; - - for (var j = 0; j < points.length; j+=2) - { - - x = points[j]; - y = points[j+1]; - minX = x-lineWidth < minX ? x-lineWidth : minX; - maxX = x+lineWidth > maxX ? x+lineWidth : maxX; - - minY = y-lineWidth < minY ? y-lineWidth : minY; - maxY = y+lineWidth > maxY ? y+lineWidth : maxY; - } - } - } - } - else - { - minX = 0; - maxX = 0; - minY = 0; - maxY = 0; - } - - var padding = this.boundsPadding; - - this._localBounds.x = minX - padding; - this._localBounds.width = (maxX - minX) + padding * 2; - - this._localBounds.y = minY - padding; - this._localBounds.height = (maxY - minY) + padding * 2; -}; - -/** - * Generates the cached sprite when the sprite has cacheAsBitmap = true - * - * @method _generateCachedSprite - * @private - */ -PIXI.Graphics.prototype._generateCachedSprite = function() -{ - var bounds = this.getLocalBounds(); - - if(!this._cachedSprite) - { - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height); - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas); - - this._cachedSprite = new PIXI.Sprite(texture); - this._cachedSprite.buffer = canvasBuffer; - - this._cachedSprite.worldTransform = this.worldTransform; - } - else - { - this._cachedSprite.buffer.resize(bounds.width, bounds.height); - } - - // leverage the anchor to account for the offset of the element - this._cachedSprite.anchor.x = -( bounds.x / bounds.width ); - this._cachedSprite.anchor.y = -( bounds.y / bounds.height ); - - // this._cachedSprite.buffer.context.save(); - this._cachedSprite.buffer.context.translate(-bounds.x,-bounds.y); - - // make sure we set the alpha of the graphics to 1 for the render.. - this.worldAlpha = 1; - - // now render the graphic.. - PIXI.CanvasGraphics.renderGraphics(this, this._cachedSprite.buffer.context); - this._cachedSprite.alpha = this.alpha; - -}; - -/** - * Updates texture size based on canvas size - * - * @method updateCachedSpriteTexture - * @private - */ -PIXI.Graphics.prototype.updateCachedSpriteTexture = function() -{ - var cachedSprite = this._cachedSprite; - var texture = cachedSprite.texture; - var canvas = cachedSprite.buffer.canvas; - - texture.baseTexture.width = canvas.width; - texture.baseTexture.height = canvas.height; - texture.crop.width = texture.frame.width = canvas.width; - texture.crop.height = texture.frame.height = canvas.height; - - cachedSprite._width = canvas.width; - cachedSprite._height = canvas.height; - - // update the dirty base textures - texture.baseTexture.dirty(); -}; - -/** - * Destroys a previous cached sprite. - * - * @method destroyCachedSprite - */ -PIXI.Graphics.prototype.destroyCachedSprite = function() -{ - this._cachedSprite.texture.destroy(true); - - // let the gc collect the unused sprite - // TODO could be object pooled! - this._cachedSprite = null; -}; - -/** - * Draws the given shape to this Graphics object. Can be any of Circle, Rectangle, Ellipse, Line or Polygon. - * - * @method drawShape - * @param {Circle|Rectangle|Ellipse|Line|Polygon} shape The Shape object to draw. - * @return {GraphicsData} The generated GraphicsData object. - */ -PIXI.Graphics.prototype.drawShape = function(shape) -{ - if(this.currentPath) - { - // check current path! - if(this.currentPath.shape.points.length <= 2)this.graphicsData.pop(); - } - - this.currentPath = null; - - var data = new PIXI.GraphicsData(this.lineWidth, this.lineColor, this.lineAlpha, this.fillColor, this.fillAlpha, this.filling, shape); - - this.graphicsData.push(data); - - if(data.type === PIXI.Graphics.POLY) - { - data.shape.closed = this.filling; - this.currentPath = data; - } - - this.dirty = this.boundsDirty = true; - - return data; -}; - -/** - * A GraphicsData object. - * - * @class GraphicsData - * @constructor - */ -PIXI.GraphicsData = function(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, shape) -{ - this.lineWidth = lineWidth; - this.lineColor = lineColor; - this.lineAlpha = lineAlpha; - this._lineTint = lineColor; - - this.fillColor = fillColor; - this.fillAlpha = fillAlpha; - this._fillTint = fillColor; - this.fill = fill; - - this.shape = shape; - this.type = shape.type; -}; - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; -PIXI.Graphics.RREC = 4; - -PIXI.Polygon.prototype.type = PIXI.Graphics.POLY; -PIXI.Rectangle.prototype.type = PIXI.Graphics.RECT; -PIXI.Circle.prototype.type = PIXI.Graphics.CIRC; -PIXI.Ellipse.prototype.type = PIXI.Graphics.ELIP; -PIXI.RoundedRectangle.prototype.type = PIXI.Graphics.RREC; - diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js deleted file mode 100644 index 82dbc05..0000000 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ /dev/null @@ -1,558 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.glContexts = []; // this is where we store the webGL contexts for easy access. -PIXI.instances = []; - -/** - * The WebGLRenderer draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers that support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batches or Sprite Clouds. - * Don't forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param [width=0] {Number} the width of the canvas view - * @param [height=0] {Number} the height of the canvas view - * @param [options] {Object} The optional renderer parameters - * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional - * @param [options.transparent=false] {Boolean} If the render view is transparent, default false - * @param [options.autoResize=false] {Boolean} If the render view is automatically resized, default false - * @param [options.antialias=false] {Boolean} sets antialias (only applicable in chrome at the moment) - * @param [options.preserveDrawingBuffer=false] {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context - * @param [options.resolution=1] {Number} the resolution of the renderer retina would be 2 - */ -PIXI.WebGLRenderer = function(width, height, options) -{ - if(options) - { - for (var i in PIXI.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') options[i] = PIXI.defaultRenderOptions[i]; - } - } - else - { - options = PIXI.defaultRenderOptions; - } - - if(!PIXI.defaultRenderer) - { - PIXI.sayHello('webGL'); - PIXI.defaultRenderer = this; - } - - /** - * @property type - * @type Number - */ - this.type = PIXI.WEBGL_RENDERER; - - /** - * The resolution of the renderer - * - * @property resolution - * @type Number - * @default 1 - */ - this.resolution = options.resolution; - - // do a catch.. only 1 webGL renderer.. - - /** - * Whether the render view is transparent - * - * @property transparent - * @type Boolean - */ - this.transparent = options.transparent; - - /** - * Whether the render view should be resized automatically - * - * @property autoResize - * @type Boolean - */ - this.autoResize = options.autoResize || false; - - /** - * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. - * - * @property preserveDrawingBuffer - * @type Boolean - */ - this.preserveDrawingBuffer = options.preserveDrawingBuffer; - - /** - * This sets if the WebGLRenderer will clear the context texture or not before the new render pass. If true: - * If the Stage is NOT transparent, Pixi will clear to alpha (0, 0, 0, 0). - * If the Stage is transparent, Pixi will clear to the target Stage's background color. - * Disable this by setting this to false. For example: if your game has a canvas filling background image, you often don't need this set. - * - * @property clearBeforeRender - * @type Boolean - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that everything is drawn to - * - * @property view - * @type HTMLCanvasElement - */ - this.view = options.view || document.createElement( 'canvas' ); - - // deal with losing context.. - - /** - * @property contextLostBound - * @type Function - */ - this.contextLostBound = this.handleContextLost.bind(this); - - /** - * @property contextRestoredBound - * @type Function - */ - this.contextRestoredBound = this.handleContextRestored.bind(this); - - this.view.addEventListener('webglcontextlost', this.contextLostBound, false); - this.view.addEventListener('webglcontextrestored', this.contextRestoredBound, false); - - /** - * @property _contextOptions - * @type Object - * @private - */ - this._contextOptions = { - alpha: this.transparent, - antialias: options.antialias, // SPEED UP?? - premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', - stencil:true, - preserveDrawingBuffer: options.preserveDrawingBuffer - }; - - /** - * @property projection - * @type Point - */ - this.projection = new PIXI.Point(); - - /** - * @property offset - * @type Point - */ - this.offset = new PIXI.Point(0, 0); - - // time to create the render managers! each one focuses on managing a state in webGL - - /** - * Deals with managing the shader programs and their attribs - * @property shaderManager - * @type WebGLShaderManager - */ - this.shaderManager = new PIXI.WebGLShaderManager(); - - /** - * Manages the rendering of sprites - * @property spriteBatch - * @type WebGLSpriteBatch - */ - this.spriteBatch = new PIXI.WebGLSpriteBatch(); - - /** - * Manages the masks using the stencil buffer - * @property maskManager - * @type WebGLMaskManager - */ - this.maskManager = new PIXI.WebGLMaskManager(); - - /** - * Manages the filters - * @property filterManager - * @type WebGLFilterManager - */ - this.filterManager = new PIXI.WebGLFilterManager(); - - /** - * Manages the stencil buffer - * @property stencilManager - * @type WebGLStencilManager - */ - this.stencilManager = new PIXI.WebGLStencilManager(); - - /** - * Manages the blendModes - * @property blendModeManager - * @type WebGLBlendModeManager - */ - this.blendModeManager = new PIXI.WebGLBlendModeManager(); - - /** - * TODO remove - * @property renderSession - * @type Object - */ - this.renderSession = {}; - this.renderSession.gl = this.gl; - this.renderSession.drawCount = 0; - this.renderSession.shaderManager = this.shaderManager; - this.renderSession.maskManager = this.maskManager; - this.renderSession.filterManager = this.filterManager; - this.renderSession.blendModeManager = this.blendModeManager; - this.renderSession.spriteBatch = this.spriteBatch; - this.renderSession.stencilManager = this.stencilManager; - this.renderSession.renderer = this; - this.renderSession.resolution = this.resolution; - this.renderSession.buffer = null; - - // time init the context.. - this.initContext(); - - // map some webGL blend modes.. - this.mapBlendModes(); -}; - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** -* @method initContext -*/ -PIXI.WebGLRenderer.prototype.initContext = function() -{ - var gl = this.view.getContext('webgl', this._contextOptions) || this.view.getContext('experimental-webgl', this._contextOptions); - this.gl = gl; - - if (!gl) { - // fail, not able to get a context - throw new Error('This browser does not support webGL. Try using the canvas renderer'); - } - - this.glContextId = gl.id = PIXI.WebGLRenderer.glContextId ++; - - PIXI.glContexts[this.glContextId] = gl; - - PIXI.instances[this.glContextId] = this; - - // set up the default pixi settings.. - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); - - // need to set the context for all the managers... - this.shaderManager.setContext(gl); - this.spriteBatch.setContext(gl); - this.maskManager.setContext(gl); - this.filterManager.setContext(gl); - this.blendModeManager.setContext(gl); - this.stencilManager.setContext(gl); - - this.renderSession.gl = this.gl; - - // now resize and we are good to go! - this.resize(this.width, this.height); -}; - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - // no point rendering if our context has been blown up! - if(this.contextLost)return; - - // if rendering a new stage clear the batches.. - if(this.__stage !== stage) - { - if(stage.interactive)stage.interactionManager.removeEvents(); - - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - } - - // update the scene graph - stage.updateTransform(); - - var gl = this.gl; - - // interaction - if(stage._interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - else - { - if(stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = false; - stage.interactionManager.setTarget(this); - } - } - - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - - // make sure we are bound to the main frame buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - if (this.clearBeforeRender) - { - if(this.transparent) - { - gl.clearColor(0, 0, 0, 0); - } - else - { - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); - } - - gl.clear (gl.COLOR_BUFFER_BIT); - } - - this.renderDisplayObject( stage, this.projection ); -}; - -/** - * Renders a Display Object. - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The DisplayObject to render - * @param projection {Point} The projection - * @param buffer {Array} a standard WebGL buffer - */ -PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection, buffer) -{ - this.renderSession.blendModeManager.setBlendMode(PIXI.blendModes.NORMAL); - - // reset the render session data.. - this.renderSession.drawCount = 0; - - // set the buffer ref.. - this.renderSession.buffer = buffer; - - // make sure to flip the Y if using a render texture.. - this.renderSession.flipY = buffer ? -1 : 1; - - // set the default projection - this.renderSession.projection = projection; - - //set the default offset - this.renderSession.offset = this.offset; - - // start the sprite batch - this.spriteBatch.begin(this.renderSession); - - // start the filter manager - this.filterManager.begin(this.renderSession, buffer); - - // render the scene! - displayObject._renderWebGL(this.renderSession); - - // finish the sprite batch - this.spriteBatch.end(); -}; - -/** - * Resizes the webGL view to the specified width and height. - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width * this.resolution; - this.height = height * this.resolution; - - this.view.width = this.width; - this.view.height = this.height; - - if (this.autoResize) { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } - - this.gl.viewport(0, 0, this.width, this.height); - - this.projection.x = this.width / 2 / this.resolution; - this.projection.y = -this.height / 2 / this.resolution; -}; - -/** - * Updates and Creates a WebGL texture for the renderers context. - * - * @method updateTexture - * @param texture {Texture} the texture to update - */ -PIXI.WebGLRenderer.prototype.updateTexture = function(texture) -{ - if(!texture.hasLoaded )return; - - var gl = this.gl; - - if(!texture._glTextures[gl.id])texture._glTextures[gl.id] = gl.createTexture(); - - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - - - if(texture.mipmap && PIXI.isPowerOfTwo(texture.width, texture.height)) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); - gl.generateMipmap(gl.TEXTURE_2D); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - } - - // reguler... - if(!texture._powerOf2) - { - 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); - } - - texture._dirty[gl.id] = false; - - return texture._glTextures[gl.id]; -}; - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -}; - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function() -{ - this.initContext(); - - // empty all the ol gl textures as they are useless now - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTextures = []; - } - - this.contextLost = false; -}; - -/** - * Removes everything from the renderer (event listeners, spritebatch, etc...) - * - * @method destroy - */ -PIXI.WebGLRenderer.prototype.destroy = function() -{ - // remove listeners - this.view.removeEventListener('webglcontextlost', this.contextLostBound); - this.view.removeEventListener('webglcontextrestored', this.contextRestoredBound); - - PIXI.glContexts[this.glContextId] = null; - - this.projection = null; - this.offset = null; - - // time to create the render managers! each one focuses on managine a state in webGL - this.shaderManager.destroy(); - this.spriteBatch.destroy(); - this.maskManager.destroy(); - this.filterManager.destroy(); - - this.shaderManager = null; - this.spriteBatch = null; - this.maskManager = null; - this.filterManager = null; - - this.gl = null; - this.renderSession = null; -}; - -/** - * Maps Pixi blend modes to WebGL blend modes. - * - * @method mapBlendModes - */ -PIXI.WebGLRenderer.prototype.mapBlendModes = function() -{ - var gl = this.gl; - - if(!PIXI.blendModesWebGL) - { - PIXI.blendModesWebGL = []; - - PIXI.blendModesWebGL[PIXI.blendModes.NORMAL] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.ADD] = [gl.SRC_ALPHA, gl.DST_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.MULTIPLY] = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SCREEN] = [gl.SRC_ALPHA, gl.ONE]; - PIXI.blendModesWebGL[PIXI.blendModes.OVERLAY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DARKEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LIGHTEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_DODGE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_BURN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HARD_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SOFT_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DIFFERENCE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.EXCLUSION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HUE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - } -}; - -PIXI.WebGLRenderer.glContextId = 0; diff --git a/src/pixi/renderers/webgl/shaders/PixiShader.js b/src/pixi/renderers/webgl/shaders/PixiShader.js deleted file mode 100644 index bb4a17d..0000000 --- a/src/pixi/renderers/webgl/shaders/PixiShader.js +++ /dev/null @@ -1,397 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * @author Richard Davey http://www.photonstorm.com @photonstorm - */ - -/** -* @class PixiShader -* @constructor -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.PixiShader = function(gl) -{ - /** - * @property _UID - * @type Number - * @private - */ - this._UID = PIXI._UID++; - - /** - * @property gl - * @type WebGLContext - */ - this.gl = gl; - - /** - * The WebGL program. - * @property program - * @type Any - */ - this.program = null; - - /** - * The fragment shader. - * @property fragmentSrc - * @type Array - */ - this.fragmentSrc = [ - 'precision lowp float;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - 'uniform sampler2D uSampler;', - 'void main(void) {', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;', - '}' - ]; - - /** - * A local texture counter for multi-texture shaders. - * @property textureCount - * @type Number - */ - this.textureCount = 0; - - /** - * A local flag - * @property firstRun - * @type Boolean - * @private - */ - this.firstRun = true; - - /** - * A dirty flag - * @property dirty - * @type Boolean - */ - this.dirty = true; - - /** - * Uniform attributes cache. - * @property attributes - * @type Array - * @private - */ - this.attributes = []; - - this.init(); -}; - -PIXI.PixiShader.prototype.constructor = PIXI.PixiShader; - -/** -* Initialises the shader. -* -* @method init -*/ -PIXI.PixiShader.prototype.init = function() -{ - var gl = this.gl; - - var program = PIXI.compileProgram(gl, this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc); - - gl.useProgram(program); - - // get and store the uniforms for the shader - this.uSampler = gl.getUniformLocation(program, 'uSampler'); - this.projectionVector = gl.getUniformLocation(program, 'projectionVector'); - this.offsetVector = gl.getUniformLocation(program, 'offsetVector'); - this.dimensions = gl.getUniformLocation(program, 'dimensions'); - this.flipY = gl.getUniformLocation(program, 'flipY'); - - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition'); - this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord'); - this.colorAttribute = gl.getAttribLocation(program, 'aColor'); - - - // Begin worst hack eva // - - // WHY??? ONLY on my chrome pixel the line above returns -1 when using filters? - // maybe its something to do with the current state of the gl context. - // I'm convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel - // If theres any webGL people that know why could happen please help :) - if(this.colorAttribute === -1) - { - this.colorAttribute = 2; - } - - this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute]; - - // End worst hack eva // - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key); - } - - this.initUniforms(); - - this.program = program; -}; - -/** -* Initialises the shader uniform values. -* -* Uniforms are specified in the GLSL_ES Specification: http://www.khronos.org/registry/webgl/specs/latest/1.0/ -* http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf -* -* @method initUniforms -*/ -PIXI.PixiShader.prototype.initUniforms = function() -{ - this.textureCount = 1; - var gl = this.gl; - var uniform; - - for (var key in this.uniforms) - { - uniform = this.uniforms[key]; - - var type = uniform.type; - - if (type === 'sampler2D') - { - uniform._init = false; - - if (uniform.value !== null) - { - this.initSampler2D(uniform); - } - } - else if (type === 'mat2' || type === 'mat3' || type === 'mat4') - { - // These require special handling - uniform.glMatrix = true; - uniform.glValueLength = 1; - - if (type === 'mat2') - { - uniform.glFunc = gl.uniformMatrix2fv; - } - else if (type === 'mat3') - { - uniform.glFunc = gl.uniformMatrix3fv; - } - else if (type === 'mat4') - { - uniform.glFunc = gl.uniformMatrix4fv; - } - } - else - { - // GL function reference - uniform.glFunc = gl['uniform' + type]; - - if (type === '2f' || type === '2i') - { - uniform.glValueLength = 2; - } - else if (type === '3f' || type === '3i') - { - uniform.glValueLength = 3; - } - else if (type === '4f' || type === '4i') - { - uniform.glValueLength = 4; - } - else - { - uniform.glValueLength = 1; - } - } - } - -}; - -/** -* Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture has loaded) -* -* @method initSampler2D -*/ -PIXI.PixiShader.prototype.initSampler2D = function(uniform) -{ - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) - { - return; - } - - var gl = this.gl; - - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); - - // Extended texture data - if (uniform.textureData) - { - var data = uniform.textureData; - - // GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D); - // GLTextureLinear = mag/min linear, wrap clamp - // GLTextureNearestRepeat = mag/min NEAREST, wrap repeat - // GLTextureNearest = mag/min nearest, wrap clamp - // AudioTexture = whatever + luminance + width 512, height 2, border 0 - // KeyTexture = whatever + luminance + width 256, height 2, border 0 - - // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST - // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; - - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } - - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); - } - - gl.uniform1i(uniform.uniformLocation, this.textureCount); - - uniform._init = true; - - this.textureCount++; - -}; - -/** -* Updates the shader uniform values. -* -* @method syncUniforms -*/ -PIXI.PixiShader.prototype.syncUniforms = function() -{ - this.textureCount = 1; - var uniform; - var gl = this.gl; - - // This would probably be faster in an array and it would guarantee key order - for (var key in this.uniforms) - { - uniform = this.uniforms[key]; - - if (uniform.glValueLength === 1) - { - if (uniform.glMatrix === true) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.transpose, uniform.value); - } - else - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value); - } - } - else if (uniform.glValueLength === 2) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y); - } - else if (uniform.glValueLength === 3) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z); - } - else if (uniform.glValueLength === 4) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z, uniform.value.w); - } - else if (uniform.type === 'sampler2D') - { - if (uniform._init) - { - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - - if(uniform.value.baseTexture._dirty[gl.id]) - { - PIXI.instances[gl.id].updateTexture(uniform.value.baseTexture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); - } - - // gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id] || PIXI.createWebGLTexture( uniform.value.baseTexture, gl)); - gl.uniform1i(uniform.uniformLocation, this.textureCount); - this.textureCount++; - } - else - { - this.initSampler2D(uniform); - } - } - } - -}; - -/** -* Destroys the shader. -* -* @method destroy -*/ -PIXI.PixiShader.prototype.destroy = function() -{ - this.gl.deleteProgram( this.program ); - this.uniforms = null; - this.gl = null; - - this.attributes = null; -}; - -/** -* The Default Vertex shader source. -* -* @property defaultVertexSrc -* @type String -*/ -PIXI.PixiShader.defaultVertexSrc = [ - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - - 'uniform float flipY;', - - 'uniform vec2 projectionVector;', - 'uniform vec2 offsetVector;', - - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'void main(void) {', - - ' vec3 temp = vec3(-1.0, 1.0, flipY);', - - ' gl_Position = vec4( (aVertexPosition + offsetVector) / (projectionVector * temp.yz) + temp.xz , 0.0, 1.0);', - - ' vTextureCoord = aTextureCoord;', - - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - - '}' -]; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/utils/WebGLFilterManager.js b/src/pixi/renderers/webgl/utils/WebGLFilterManager.js deleted file mode 100644 index ba642c3..0000000 --- a/src/pixi/renderers/webgl/utils/WebGLFilterManager.js +++ /dev/null @@ -1,452 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** -* @class WebGLFilterManager -* @constructor -*/ -PIXI.WebGLFilterManager = function() -{ - /** - * @property filterStack - * @type Array - */ - this.filterStack = []; - - /** - * @property offsetX - * @type Number - */ - this.offsetX = 0; - - /** - * @property offsetY - * @type Number - */ - this.offsetY = 0; -}; - -PIXI.WebGLFilterManager.prototype.constructor = PIXI.WebGLFilterManager; - -/** -* Initialises the context and the properties. -* -* @method setContext -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.WebGLFilterManager.prototype.setContext = function(gl) -{ - this.gl = gl; - this.texturePool = []; - - this.initShaderBuffers(); -}; - -/** -* @method begin -* @param renderSession {RenderSession} -* @param buffer {ArrayBuffer} -*/ -PIXI.WebGLFilterManager.prototype.begin = function(renderSession, buffer) -{ - this.renderSession = renderSession; - this.defaultShader = renderSession.shaderManager.defaultShader; - - var projection = this.renderSession.projection; - this.width = projection.x * 2; - this.height = -projection.y * 2; - this.buffer = buffer; -}; - -/** -* Applies the filter and adds it to the current filter stack. -* -* @method pushFilter -* @param filterBlock {Object} the filter that will be pushed to the current filter stack -*/ -PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock) -{ - var gl = this.gl; - - var projection = this.renderSession.projection; - var offset = this.renderSession.offset; - - filterBlock._filterArea = filterBlock.target.filterArea || filterBlock.target.getBounds(); - - // filter program - // OPTIMISATION - the first filter is free if its a simple color change? - this.filterStack.push(filterBlock); - - var filter = filterBlock.filterPasses[0]; - - this.offsetX += filterBlock._filterArea.x; - this.offsetY += filterBlock._filterArea.y; - - var texture = this.texturePool.pop(); - if(!texture) - { - texture = new PIXI.FilterTexture(this.gl, this.width, this.height); - } - else - { - texture.resize(this.width, this.height); - } - - gl.bindTexture(gl.TEXTURE_2D, texture.texture); - - var filterArea = filterBlock._filterArea;// filterBlock.target.getBounds();///filterBlock.target.filterArea; - - var padding = filter.padding; - filterArea.x -= padding; - filterArea.y -= padding; - filterArea.width += padding * 2; - filterArea.height += padding * 2; - - // cap filter to screen size.. - if(filterArea.x < 0)filterArea.x = 0; - if(filterArea.width > this.width)filterArea.width = this.width; - if(filterArea.y < 0)filterArea.y = 0; - if(filterArea.height > this.height)filterArea.height = this.height; - - //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - gl.bindFramebuffer(gl.FRAMEBUFFER, texture.frameBuffer); - - // set view port - gl.viewport(0, 0, filterArea.width, filterArea.height); - - projection.x = filterArea.width/2; - projection.y = -filterArea.height/2; - - offset.x = -filterArea.x; - offset.y = -filterArea.y; - - // update projection - // now restore the regular shader.. - // this.renderSession.shaderManager.setShader(this.defaultShader); - //gl.uniform2f(this.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2); - //gl.uniform2f(this.defaultShader.offsetVector, -filterArea.x, -filterArea.y); - - gl.colorMask(true, true, true, true); - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - - filterBlock._glFilterTexture = texture; - -}; - -/** -* Removes the last filter from the filter stack and doesn't return it. -* -* @method popFilter -*/ -PIXI.WebGLFilterManager.prototype.popFilter = function() -{ - var gl = this.gl; - var filterBlock = this.filterStack.pop(); - var filterArea = filterBlock._filterArea; - var texture = filterBlock._glFilterTexture; - var projection = this.renderSession.projection; - var offset = this.renderSession.offset; - - if(filterBlock.filterPasses.length > 1) - { - gl.viewport(0, 0, filterArea.width, filterArea.height); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - - this.vertexArray[0] = 0; - this.vertexArray[1] = filterArea.height; - - this.vertexArray[2] = filterArea.width; - this.vertexArray[3] = filterArea.height; - - this.vertexArray[4] = 0; - this.vertexArray[5] = 0; - - this.vertexArray[6] = filterArea.width; - this.vertexArray[7] = 0; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - // now set the uvs.. - this.uvArray[2] = filterArea.width/this.width; - this.uvArray[5] = filterArea.height/this.height; - this.uvArray[6] = filterArea.width/this.width; - this.uvArray[7] = filterArea.height/this.height; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); - - var inputTexture = texture; - var outputTexture = this.texturePool.pop(); - if(!outputTexture)outputTexture = new PIXI.FilterTexture(this.gl, this.width, this.height); - outputTexture.resize(this.width, this.height); - - // need to clear this FBO as it may have some left over elements from a previous filter. - gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); - gl.clear(gl.COLOR_BUFFER_BIT); - - gl.disable(gl.BLEND); - - for (var i = 0; i < filterBlock.filterPasses.length-1; i++) - { - var filterPass = filterBlock.filterPasses[i]; - - gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); - - // set texture - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture); - - // draw texture.. - //filterPass.applyFilterPass(filterArea.width, filterArea.height); - this.applyFilterPass(filterPass, filterArea, filterArea.width, filterArea.height); - - // swap the textures.. - var temp = inputTexture; - inputTexture = outputTexture; - outputTexture = temp; - } - - gl.enable(gl.BLEND); - - texture = inputTexture; - this.texturePool.push(outputTexture); - } - - var filter = filterBlock.filterPasses[filterBlock.filterPasses.length-1]; - - this.offsetX -= filterArea.x; - this.offsetY -= filterArea.y; - - var sizeX = this.width; - var sizeY = this.height; - - var offsetX = 0; - var offsetY = 0; - - var buffer = this.buffer; - - // time to render the filters texture to the previous scene - if(this.filterStack.length === 0) - { - gl.colorMask(true, true, true, true);//this.transparent); - } - else - { - var currentFilter = this.filterStack[this.filterStack.length-1]; - filterArea = currentFilter._filterArea; - - sizeX = filterArea.width; - sizeY = filterArea.height; - - offsetX = filterArea.x; - offsetY = filterArea.y; - - buffer = currentFilter._glFilterTexture.frameBuffer; - } - - // TODO need to remove these global elements.. - projection.x = sizeX/2; - projection.y = -sizeY/2; - - offset.x = offsetX; - offset.y = offsetY; - - filterArea = filterBlock._filterArea; - - var x = filterArea.x-offsetX; - var y = filterArea.y-offsetY; - - // update the buffers.. - // make sure to flip the y! - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - - this.vertexArray[0] = x; - this.vertexArray[1] = y + filterArea.height; - - this.vertexArray[2] = x + filterArea.width; - this.vertexArray[3] = y + filterArea.height; - - this.vertexArray[4] = x; - this.vertexArray[5] = y; - - this.vertexArray[6] = x + filterArea.width; - this.vertexArray[7] = y; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - this.uvArray[2] = filterArea.width/this.width; - this.uvArray[5] = filterArea.height/this.height; - this.uvArray[6] = filterArea.width/this.width; - this.uvArray[7] = filterArea.height/this.height; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); - - gl.viewport(0, 0, sizeX, sizeY); - - // bind the buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, buffer ); - - // set the blend mode! - //gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) - - // set texture - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture.texture); - - // apply! - this.applyFilterPass(filter, filterArea, sizeX, sizeY); - - // now restore the regular shader.. should happen automatically now.. - // this.renderSession.shaderManager.setShader(this.defaultShader); - // gl.uniform2f(this.defaultShader.projectionVector, sizeX/2, -sizeY/2); - // gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY); - - // return the texture to the pool - this.texturePool.push(texture); - filterBlock._glFilterTexture = null; -}; - - -/** -* Applies the filter to the specified area. -* -* @method applyFilterPass -* @param filter {AbstractFilter} the filter that needs to be applied -* @param filterArea {Texture} TODO - might need an update -* @param width {Number} the horizontal range of the filter -* @param height {Number} the vertical range of the filter -*/ -PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea, width, height) -{ - // use program - var gl = this.gl; - var shader = filter.shaders[gl.id]; - - if(!shader) - { - shader = new PIXI.PixiShader(gl); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shaders[gl.id] = shader; - } - - // set the shader - this.renderSession.shaderManager.setShader(shader); - -// gl.useProgram(shader.program); - - gl.uniform2f(shader.projectionVector, width/2, -height/2); - gl.uniform2f(shader.offsetVector, 0,0); - - gl.uniform1f(shader.flipY, this.renderSession.flipY); - - if(filter.uniforms.dimensions) - { - filter.uniforms.dimensions.value[0] = this.width;//width; - filter.uniforms.dimensions.value[1] = this.height;//height; - filter.uniforms.dimensions.value[2] = this.vertexArray[0]; - filter.uniforms.dimensions.value[3] = this.vertexArray[5];//filterArea.height; - } - - shader.syncUniforms(); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.vertexAttribPointer(shader.colorAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - // draw the filter... - gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - this.renderSession.drawCount++; -}; - -/** -* Initialises the shader buffers. -* -* @method initShaderBuffers -*/ -PIXI.WebGLFilterManager.prototype.initShaderBuffers = function() -{ - var gl = this.gl; - - // create some buffers - this.vertexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - - // bind and upload the vertexs.. - // keep a reference to the vertexFloatData.. - this.vertexArray = new PIXI.Float32Array([0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.vertexArray, gl.STATIC_DRAW); - - // bind and upload the uv buffer - this.uvArray = new PIXI.Float32Array([0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvArray, gl.STATIC_DRAW); - - this.colorArray = new PIXI.Float32Array([1.0, 0xFFFFFF, - 1.0, 0xFFFFFF, - 1.0, 0xFFFFFF, - 1.0, 0xFFFFFF]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colorArray, gl.STATIC_DRAW); - - // bind and upload the index - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 1, 3, 2]), gl.STATIC_DRAW); - -}; - -/** -* Destroys the filter and removes it from the filter stack. -* -* @method destroy -*/ -PIXI.WebGLFilterManager.prototype.destroy = function() -{ - var gl = this.gl; - - this.filterStack = null; - - this.offsetX = 0; - this.offsetY = 0; - - // destroy textures - for (var i = 0; i < this.texturePool.length; i++) { - this.texturePool[i].destroy(); - } - - this.texturePool = null; - - //destroy buffers.. - gl.deleteBuffer(this.vertexBuffer); - gl.deleteBuffer(this.uvBuffer); - gl.deleteBuffer(this.colorBuffer); - gl.deleteBuffer(this.indexBuffer); -}; diff --git a/src/pixi/renderers/webgl/utils/WebGLShaderManager.js b/src/pixi/renderers/webgl/utils/WebGLShaderManager.js deleted file mode 100644 index 168e4ac..0000000 --- a/src/pixi/renderers/webgl/utils/WebGLShaderManager.js +++ /dev/null @@ -1,158 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** -* @class WebGLShaderManager -* @constructor -* @private -*/ -PIXI.WebGLShaderManager = function() -{ - /** - * @property maxAttibs - * @type Number - */ - this.maxAttibs = 10; - - /** - * @property attribState - * @type Array - */ - this.attribState = []; - - /** - * @property tempAttribState - * @type Array - */ - this.tempAttribState = []; - - for (var i = 0; i < this.maxAttibs; i++) - { - this.attribState[i] = false; - } - - /** - * @property stack - * @type Array - */ - this.stack = []; - -}; - -PIXI.WebGLShaderManager.prototype.constructor = PIXI.WebGLShaderManager; - -/** -* Initialises the context and the properties. -* -* @method setContext -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.WebGLShaderManager.prototype.setContext = function(gl) -{ - this.gl = gl; - - // the next one is used for rendering primitives - this.primitiveShader = new PIXI.PrimitiveShader(gl); - - // the next one is used for rendering triangle strips - this.complexPrimitiveShader = new PIXI.ComplexPrimitiveShader(gl); - - // this shader is used for the default sprite rendering - this.defaultShader = new PIXI.PixiShader(gl); - - // this shader is used for the fast sprite rendering - this.fastShader = new PIXI.PixiFastShader(gl); - - // the next one is used for rendering triangle strips - this.stripShader = new PIXI.StripShader(gl); - this.setShader(this.defaultShader); -}; - -/** -* Takes the attributes given in parameters. -* -* @method setAttribs -* @param attribs {Array} attribs -*/ -PIXI.WebGLShaderManager.prototype.setAttribs = function(attribs) -{ - // reset temp state - var i; - - for (i = 0; i < this.tempAttribState.length; i++) - { - this.tempAttribState[i] = false; - } - - // set the new attribs - for (i = 0; i < attribs.length; i++) - { - var attribId = attribs[i]; - this.tempAttribState[attribId] = true; - } - - var gl = this.gl; - - for (i = 0; i < this.attribState.length; i++) - { - if(this.attribState[i] !== this.tempAttribState[i]) - { - this.attribState[i] = this.tempAttribState[i]; - - if(this.tempAttribState[i]) - { - gl.enableVertexAttribArray(i); - } - else - { - gl.disableVertexAttribArray(i); - } - } - } -}; - -/** -* Sets the current shader. -* -* @method setShader -* @param shader {Any} -*/ -PIXI.WebGLShaderManager.prototype.setShader = function(shader) -{ - if(this._currentId === shader._UID)return false; - - this._currentId = shader._UID; - - this.currentShader = shader; - - this.gl.useProgram(shader.program); - - this.setAttribs(shader.attributes); - - return true; -}; - -/** -* Destroys this object. -* -* @method destroy -*/ -PIXI.WebGLShaderManager.prototype.destroy = function() -{ - this.attribState = null; - - this.tempAttribState = null; - - this.primitiveShader.destroy(); - - this.complexPrimitiveShader.destroy(); - - this.defaultShader.destroy(); - - this.fastShader.destroy(); - - this.stripShader.destroy(); - - this.gl = null; -}; diff --git a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js deleted file mode 100755 index b4d873b..0000000 --- a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js +++ /dev/null @@ -1,639 +0,0 @@ -/** - * @author Mat Groves - * - * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ - * for creating the original pixi version! - * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer - * - * Heavily inspired by LibGDX's WebGLSpriteBatch: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/WebGLSpriteBatch.java - */ - - /** - * - * @class WebGLSpriteBatch - * @private - * @constructor - */ -PIXI.WebGLSpriteBatch = function() -{ - /** - * @property vertSize - * @type Number - */ - this.vertSize = 5; - - /** - * The number of images in the SpriteBatch before it flushes - * @property size - * @type Number - */ - this.size = 2000;//Math.pow(2, 16) / this.vertSize; - - //the total number of bytes in our batch - var numVerts = this.size * 4 * 4 * this.vertSize; - //the total number of indices in our batch - var numIndices = this.size * 6; - - /** - * Holds the vertices - * - * @property vertices - * @type ArrayBuffer - */ - this.vertices = new PIXI.ArrayBuffer(numVerts); - - /** - * View on the vertices as a Float32Array - * - * @property positions - * @type Float32Array - */ - this.positions = new PIXI.Float32Array(this.vertices); - - /** - * View on the vertices as a Uint32Array - * - * @property colors - * @type Uint32Array - */ - this.colors = new PIXI.Uint32Array(this.vertices); - - /** - * Holds the indices - * - * @property indices - * @type Uint16Array - */ - this.indices = new PIXI.Uint16Array(numIndices); - - /** - * @property lastIndexCount - * @type Number - */ - 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; - } - - /** - * @property drawing - * @type Boolean - */ - this.drawing = false; - - /** - * @property currentBatchSize - * @type Number - */ - this.currentBatchSize = 0; - - /** - * @property currentBaseTexture - * @type BaseTexture - */ - this.currentBaseTexture = null; - - /** - * @property dirty - * @type Boolean - */ - this.dirty = true; - - /** - * @property textures - * @type Array - */ - this.textures = []; - - /** - * @property blendModes - * @type Array - */ - this.blendModes = []; - - /** - * @property shaders - * @type Array - */ - this.shaders = []; - - /** - * @property sprites - * @type Array - */ - this.sprites = []; - - /** - * @property defaultShader - * @type AbstractFilter - */ - this.defaultShader = new PIXI.AbstractFilter([ - 'precision lowp float;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - 'uniform sampler2D uSampler;', - 'void main(void) {', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;', - '}' - ]); -}; - -/** -* @method setContext -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.WebGLSpriteBatch.prototype.setContext = function(gl) -{ - this.gl = gl; - - // create a couple of buffers - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - - // 65535 is max index, so 65535 / 6 = 10922. - - //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.currentBlendMode = 99999; - - var shader = new PIXI.PixiShader(gl); - - shader.fragmentSrc = this.defaultShader.fragmentSrc; - shader.uniforms = {}; - shader.init(); - - this.defaultShader.shaders[gl.id] = shader; -}; - -/** -* @method begin -* @param renderSession {Object} The RenderSession object -*/ -PIXI.WebGLSpriteBatch.prototype.begin = function(renderSession) -{ - this.renderSession = renderSession; - this.shader = this.renderSession.shaderManager.defaultShader; - - this.start(); -}; - -/** -* @method end -*/ -PIXI.WebGLSpriteBatch.prototype.end = function() -{ - this.flush(); -}; - -/** -* @method render -* @param sprite {Sprite} the sprite to render when using this spritebatch -*/ -PIXI.WebGLSpriteBatch.prototype.render = function(sprite) -{ - var texture = sprite.texture; - - //TODO set blend modes.. - // check texture.. - if(this.currentBatchSize >= this.size) - { - this.flush(); - this.currentBaseTexture = texture.baseTexture; - } - - // get the uvs for the texture - var uvs = texture._uvs; - // if the uvs have not updated then no point rendering just yet! - if(!uvs)return; - - // TODO trim?? - var aX = sprite.anchor.x; - var aY = sprite.anchor.y; - - var w0, w1, h0, h1; - - if (texture.trim) - { - // if the sprite is trimmed 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 * 4 * this.vertSize; - - var resolution = texture.baseTexture.resolution; - - var worldTransform = sprite.worldTransform; - - var a = worldTransform.a / resolution; - var b = worldTransform.b / resolution; - var c = worldTransform.c / resolution; - var d = worldTransform.d / resolution; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var colors = this.colors; - var positions = this.positions; - - if(this.renderSession.roundPixels) - { - // xy - positions[index] = a * w1 + c * h1 + tx | 0; - positions[index+1] = d * h1 + b * w1 + ty | 0; - - // xy - positions[index+5] = a * w0 + c * h1 + tx | 0; - positions[index+6] = d * h1 + b * w0 + ty | 0; - - // xy - positions[index+10] = a * w0 + c * h0 + tx | 0; - positions[index+11] = d * h0 + b * w0 + ty | 0; - - // xy - positions[index+15] = a * w1 + c * h0 + tx | 0; - positions[index+16] = d * h0 + b * w1 + ty | 0; - } - else - { - // xy - positions[index] = a * w1 + c * h1 + tx; - positions[index+1] = d * h1 + b * w1 + ty; - - // xy - positions[index+5] = a * w0 + c * h1 + tx; - positions[index+6] = d * h1 + b * w0 + ty; - - // xy - positions[index+10] = a * w0 + c * h0 + tx; - positions[index+11] = d * h0 + b * w0 + ty; - - // xy - positions[index+15] = a * w1 + c * h0 + tx; - positions[index+16] = d * h0 + b * w1 + ty; - } - - // uv - positions[index+2] = uvs.x0; - positions[index+3] = uvs.y0; - - // uv - positions[index+7] = uvs.x1; - positions[index+8] = uvs.y1; - - // uv - positions[index+12] = uvs.x2; - positions[index+13] = uvs.y2; - - // uv - positions[index+17] = uvs.x3; - positions[index+18] = uvs.y3; - - // color and alpha - var tint = sprite.tint; - colors[index+4] = colors[index+9] = colors[index+14] = colors[index+19] = (tint >> 16) + (tint & 0xff00) + ((tint & 0xff) << 16) + (sprite.worldAlpha * 255 << 24); - - // increment the batchsize - this.sprites[this.currentBatchSize++] = sprite; - - -}; - -/** -* Renders a TilingSprite using the spriteBatch. -* -* @method renderTilingSprite -* @param sprite {TilingSprite} the tilingSprite to render -*/ -PIXI.WebGLSpriteBatch.prototype.renderTilingSprite = function(tilingSprite) -{ - var texture = tilingSprite.tilingTexture; - - // check texture.. - if(this.currentBatchSize >= this.size) - { - //return; - this.flush(); - this.currentBaseTexture = texture.baseTexture; - } - - // set the textures uvs temporarily - // TODO create a separate texture so that we can tile part of a texture - - if(!tilingSprite._uvs)tilingSprite._uvs = new PIXI.TextureUvs(); - - var uvs = tilingSprite._uvs; - - tilingSprite.tilePosition.x %= texture.baseTexture.width * tilingSprite.tileScaleOffset.x; - tilingSprite.tilePosition.y %= texture.baseTexture.height * tilingSprite.tileScaleOffset.y; - - var offsetX = tilingSprite.tilePosition.x/(texture.baseTexture.width*tilingSprite.tileScaleOffset.x); - var offsetY = tilingSprite.tilePosition.y/(texture.baseTexture.height*tilingSprite.tileScaleOffset.y); - - var scaleX = (tilingSprite.width / texture.baseTexture.width) / (tilingSprite.tileScale.x * tilingSprite.tileScaleOffset.x); - var scaleY = (tilingSprite.height / texture.baseTexture.height) / (tilingSprite.tileScale.y * tilingSprite.tileScaleOffset.y); - - uvs.x0 = 0 - offsetX; - uvs.y0 = 0 - offsetY; - - uvs.x1 = (1 * scaleX) - offsetX; - uvs.y1 = 0 - offsetY; - - uvs.x2 = (1 * scaleX) - offsetX; - uvs.y2 = (1 * scaleY) - offsetY; - - uvs.x3 = 0 - offsetX; - uvs.y3 = (1 * scaleY) - offsetY; - - // get the tilingSprites current alpha and tint and combining them into a single color - var tint = tilingSprite.tint; - var color = (tint >> 16) + (tint & 0xff00) + ((tint & 0xff) << 16) + (tilingSprite.alpha * 255 << 24); - - var positions = this.positions; - var colors = this.colors; - - var width = tilingSprite.width; - var height = tilingSprite.height; - - // TODO trim?? - var aX = tilingSprite.anchor.x; - var aY = tilingSprite.anchor.y; - var w0 = width * (1-aX); - var w1 = width * -aX; - - var h0 = height * (1-aY); - var h1 = height * -aY; - - var index = this.currentBatchSize * 4 * this.vertSize; - - var resolution = texture.baseTexture.resolution; - - var worldTransform = tilingSprite.worldTransform; - - var a = worldTransform.a / resolution;//[0]; - var b = worldTransform.b / resolution;//[3]; - var c = worldTransform.c / resolution;//[1]; - var d = worldTransform.d / resolution;//[4]; - var tx = worldTransform.tx;//[2]; - var ty = worldTransform.ty;//[5]; - - // xy - positions[index++] = a * w1 + c * h1 + tx; - positions[index++] = d * h1 + b * w1 + ty; - // uv - positions[index++] = uvs.x0; - positions[index++] = uvs.y0; - // color - colors[index++] = color; - - // xy - positions[index++] = (a * w0 + c * h1 + tx); - positions[index++] = d * h1 + b * w0 + ty; - // uv - positions[index++] = uvs.x1; - positions[index++] = uvs.y1; - // color - colors[index++] = color; - - // xy - positions[index++] = a * w0 + c * h0 + tx; - positions[index++] = d * h0 + b * w0 + ty; - // uv - positions[index++] = uvs.x2; - positions[index++] = uvs.y2; - // color - colors[index++] = color; - - // xy - positions[index++] = a * w1 + c * h0 + tx; - positions[index++] = d * h0 + b * w1 + ty; - // uv - positions[index++] = uvs.x3; - positions[index++] = uvs.y3; - // color - colors[index++] = color; - - // increment the batchsize - this.sprites[this.currentBatchSize++] = tilingSprite; -}; - -/** -* Renders the content and empties the current batch. -* -* @method flush -*/ -PIXI.WebGLSpriteBatch.prototype.flush = function() -{ - // If the batch is length 0 then return as there is nothing to draw - if (this.currentBatchSize===0)return; - - var gl = this.gl; - var shader; - - if(this.dirty) - { - this.dirty = false; - // bind the main texture - gl.activeTexture(gl.TEXTURE0); - - // bind the buffers - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - shader = this.defaultShader.shaders[gl.id]; - - // this is the same for each shader? - var stride = this.vertSize * 4; - gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, stride, 0); - gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, stride, 2 * 4); - - // color attributes will be interpreted as unsigned bytes and normalized - gl.vertexAttribPointer(shader.colorAttribute, 4, gl.UNSIGNED_BYTE, true, stride, 4 * 4); - } - - // upload the verts to the buffer - if(this.currentBatchSize > ( this.size * 0.5 ) ) - { - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices); - } - else - { - var view = this.positions.subarray(0, this.currentBatchSize * 4 * this.vertSize); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); - } - - var nextTexture, nextBlendMode, nextShader; - var batchSize = 0; - var start = 0; - - var currentBaseTexture = null; - var currentBlendMode = this.renderSession.blendModeManager.currentBlendMode; - var currentShader = null; - - var blendSwap = false; - var shaderSwap = false; - var sprite; - - for (var i = 0, j = this.currentBatchSize; i < j; i++) { - - sprite = this.sprites[i]; - - nextTexture = sprite.texture.baseTexture; - nextBlendMode = sprite.blendMode; - nextShader = sprite.shader || this.defaultShader; - - blendSwap = currentBlendMode !== nextBlendMode; - shaderSwap = currentShader !== nextShader; // should I use _UIDS??? - - if(currentBaseTexture !== nextTexture || blendSwap || shaderSwap) - { - this.renderBatch(currentBaseTexture, batchSize, start); - - start = i; - batchSize = 0; - currentBaseTexture = nextTexture; - - if( blendSwap ) - { - currentBlendMode = nextBlendMode; - this.renderSession.blendModeManager.setBlendMode( currentBlendMode ); - } - - if( shaderSwap ) - { - currentShader = nextShader; - - shader = currentShader.shaders[gl.id]; - - if(!shader) - { - shader = new PIXI.PixiShader(gl); - - shader.fragmentSrc =currentShader.fragmentSrc; - shader.uniforms =currentShader.uniforms; - shader.init(); - - currentShader.shaders[gl.id] = shader; - } - - // set shader function??? - this.renderSession.shaderManager.setShader(shader); - - if(shader.dirty)shader.syncUniforms(); - - // both thease only need to be set if they are changing.. - // set the projection - var projection = this.renderSession.projection; - gl.uniform2f(shader.projectionVector, projection.x, projection.y); - - // TODO - this is temprorary! - var offsetVector = this.renderSession.offset; - gl.uniform2f(shader.offsetVector, offsetVector.x, offsetVector.y); - - // set the correct flip.. - gl.uniform1f(shader.flipY, this.renderSession.flipY); - - - // set the pointers - } - } - - batchSize++; - } - - this.renderBatch(currentBaseTexture, batchSize, start); - - // then reset the batch! - this.currentBatchSize = 0; -}; - -/** -* @method renderBatch -* @param texture {Texture} -* @param size {Number} -* @param startIndex {Number} -*/ -PIXI.WebGLSpriteBatch.prototype.renderBatch = function(texture, size, startIndex) -{ - if(size === 0)return; - - var gl = this.gl; - - // check if a texture is dirty.. - if(texture._dirty[gl.id]) - { - this.renderSession.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - - // now draw those suckas! - gl.drawElements(gl.TRIANGLES, size * 6, gl.UNSIGNED_SHORT, startIndex * 6 * 2); - - // increment the draw count - this.renderSession.drawCount++; -}; - -/** -* @method stop -*/ -PIXI.WebGLSpriteBatch.prototype.stop = function() -{ - this.flush(); - this.dirty = true; -}; - -/** -* @method start -*/ -PIXI.WebGLSpriteBatch.prototype.start = function() -{ - this.dirty = true; -}; - -/** -* Destroys the SpriteBatch. -* -* @method destroy -*/ -PIXI.WebGLSpriteBatch.prototype.destroy = function() -{ - this.vertices = null; - this.indices = null; - - this.gl.deleteBuffer( this.vertexBuffer ); - this.gl.deleteBuffer( this.indexBuffer ); - - this.currentBaseTexture = null; - - this.gl = null; -}; \ No newline at end of file diff --git a/src/core/particles/webgl/ParticleRenderer.js b/src/core/particles/webgl/ParticleRenderer.js index 009c65d..ea55547 100644 --- a/src/core/particles/webgl/ParticleRenderer.js +++ b/src/core/particles/webgl/ParticleRenderer.js @@ -160,83 +160,20 @@ gl.uniformMatrix3fv(this.shader.uniforms.projectionMatrix._location, false, m.toArray(true)); - this.currentBatchSize = 0; -/* - var rotationDirty = false; - var positionDirty = false; - var vertsDirty = false; - var uvsDirty = false; - var alphaDirty = false;*/ - this.sprites = children; this.vertDirty = 0; - for (var i=0,j= children.length; i b2 * a1); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * The arc method creates an arc/curve (used to create circles, or parts of circles). - * - * @method arc - * @param cx {Number} The x-coordinate of the center of the circle - * @param cy {Number} The y-coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle) - * @param endAngle {Number} The ending angle, in radians - * @param anticlockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise. - * @return {Graphics} - */ -PIXI.Graphics.prototype.arc = function(cx, cy, radius, startAngle, endAngle, anticlockwise) -{ - var startX = cx + Math.cos(startAngle) * radius; - var startY = cy + Math.sin(startAngle) * radius; - var points; - - if( this.currentPath ) - { - points = this.currentPath.shape.points; - - if(points.length === 0) - { - points.push(startX, startY); - } - else if( points[points.length-2] !== startX || points[points.length-1] !== startY) - { - points.push(startX, startY); - } - } - else - { - this.moveTo(startX, startY); - points = this.currentPath.shape.points; - } - - if (startAngle === endAngle)return this; - - if( !anticlockwise && endAngle <= startAngle ) - { - endAngle += Math.PI * 2; - } - else if( anticlockwise && startAngle <= endAngle ) - { - startAngle += Math.PI * 2; - } - - var sweep = anticlockwise ? (startAngle - endAngle) *-1 : (endAngle - startAngle); - var segs = ( Math.abs(sweep)/ (Math.PI * 2) ) * 40; - - if( sweep === 0 ) return this; - - var theta = sweep/(segs*2); - var theta2 = theta*2; - - var cTheta = Math.cos(theta); - var sTheta = Math.sin(theta); - - var segMinus = segs - 1; - - var remainder = ( segMinus % 1 ) / segMinus; - - for(var i=0; i<=segMinus; i++) - { - var real = i + remainder * i; - - - var angle = ((theta) + startAngle + (theta2 * real)); - - var c = Math.cos(angle); - var s = -Math.sin(angle); - - points.push(( (cTheta * c) + (sTheta * s) ) * radius + cx, - ( (cTheta * -s) + (sTheta * c) ) * radius + cy); - } - - this.dirty = this.boundsDirty = true; - - return this; -}; - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {Number} the color of the fill - * @param alpha {Number} the alpha of the fill - * @return {Graphics} - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha === undefined) ? 1 : alpha; - - if(this.currentPath) - { - if(this.currentPath.shape.points.length <= 2) - { - this.currentPath.fill = this.filling; - this.currentPath.fillColor = this.fillColor; - this.currentPath.fillAlpha = this.fillAlpha; - } - } - return this; -}; - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - * @return {Graphics} - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; - - return this; -}; - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - this.drawShape(new PIXI.Rectangle(x,y, width, height)); - - return this; -}; - -/** - * @method drawRoundedRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - * @param radius {Number} Radius of the rectangle corners - */ -PIXI.Graphics.prototype.drawRoundedRect = function( x, y, width, height, radius ) -{ - this.drawShape(new PIXI.RoundedRectangle(x, y, width, height, radius)); - - return this; -}; - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coordinate of the center of the circle - * @param y {Number} The Y coordinate of the center of the circle - * @param radius {Number} The radius of the circle - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawCircle = function(x, y, radius) -{ - this.drawShape(new PIXI.Circle(x,y, radius)); - - return this; -}; - -/** - * Draws an ellipse. - * - * @method drawEllipse - * @param x {Number} The X coordinate of the center of the ellipse - * @param y {Number} The Y coordinate of the center of the ellipse - * @param width {Number} The half width of the ellipse - * @param height {Number} The half height of the ellipse - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawEllipse = function(x, y, width, height) -{ - this.drawShape(new PIXI.Ellipse(x, y, width, height)); - - return this; -}; - -/** - * Draws a polygon using the given path. - * - * @method drawPolygon - * @param path {Array} The path data used to construct the polygon. - * @return {Graphics} - */ -PIXI.Graphics.prototype.drawPolygon = function(path) -{ - if(!(path instanceof Array))path = Array.prototype.slice.call(arguments); - this.drawShape(new PIXI.Polygon(path)); - return this; -}; - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - * @return {Graphics} - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = this.boundsDirty = true; - this.clearDirty = true; - this.graphicsData = []; - - return this; -}; - -/** - * Useful function that returns a texture of the graphics object that can then be used to create sprites - * This can be quite useful if your geometry is complicated and needs to be reused multiple times. - * - * @method generateTexture - * @param resolution {Number} The resolution of the texture being generated - * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts - * @return {Texture} a texture of the graphics object - */ -PIXI.Graphics.prototype.generateTexture = function(resolution, scaleMode) -{ - resolution = resolution || 1; - - var bounds = this.getBounds(); - - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width * resolution, bounds.height * resolution); - - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas, scaleMode); - texture.baseTexture.resolution = resolution; - - canvasBuffer.context.scale(resolution, resolution); - - canvasBuffer.context.translate(-bounds.x,-bounds.y); - - PIXI.CanvasGraphics.renderGraphics(this, canvasBuffer.context); - - return texture; -}; - -/** -* Renders the object using the WebGL renderer -* -* @method _renderWebGL -* @param renderSession {RenderSession} -* @private -*/ -PIXI.Graphics.prototype._renderWebGL = function(renderSession) -{ - // if the sprite is not visible or the alpha is 0 then no need to render this element - if(this.visible === false || this.alpha === 0 || this.isMask === true)return; - - if(this._cacheAsBitmap) - { - - if(this.dirty || this.cachedSpriteDirty) - { - - this._generateCachedSprite(); - - // we will also need to update the texture on the gpu too! - this.updateCachedSpriteTexture(); - - this.cachedSpriteDirty = false; - this.dirty = false; - } - - this._cachedSprite.worldAlpha = this.worldAlpha; - PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession); - - return; - } - else - { - renderSession.spriteBatch.stop(); - renderSession.blendModeManager.setBlendMode(this.blendMode); - - if(this._mask)renderSession.maskManager.pushMask(this._mask, renderSession); - if(this._filters)renderSession.filterManager.pushFilter(this._filterBlock); - - // check blend mode - if(this.blendMode !== renderSession.spriteBatch.currentBlendMode) - { - renderSession.spriteBatch.currentBlendMode = this.blendMode; - var blendModeWebGL = PIXI.blendModesWebGL[renderSession.spriteBatch.currentBlendMode]; - renderSession.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]); - } - - // check if the webgl graphic needs to be updated - if(this.webGLDirty) - { - this.dirty = true; - this.webGLDirty = false; - } - - PIXI.WebGLGraphics.renderGraphics(this, renderSession); - - // only render if it has children! - if(this.children.length) - { - renderSession.spriteBatch.start(); - - // simple render children! - for(var i=0, j=this.children.length; i maxX ? x2 : maxX; - maxX = x3 > maxX ? x3 : maxX; - maxX = x4 > maxX ? x4 : maxX; - - maxY = y2 > maxY ? y2 : maxY; - maxY = y3 > maxY ? y3 : maxY; - maxY = y4 > maxY ? y4 : maxY; - - this._bounds.x = minX; - this._bounds.width = maxX - minX; - - this._bounds.y = minY; - this._bounds.height = maxY - minY; - - return this._bounds; -}; - -/** - * Update the bounds of the object - * - * @method updateLocalBounds - */ -PIXI.Graphics.prototype.updateLocalBounds = function() -{ - var minX = Infinity; - var maxX = -Infinity; - - var minY = Infinity; - var maxY = -Infinity; - - - - if(this.graphicsData.length) - { - var shape, points, x, y, w, h; - - for (var i = 0; i < this.graphicsData.length; i++) { - var data = this.graphicsData[i]; - var type = data.type; - var lineWidth = data.lineWidth; - shape = data.shape; - - - if(type === PIXI.Graphics.RECT || type === PIXI.Graphics.RREC) - { - x = shape.x - lineWidth/2; - y = shape.y - lineWidth/2; - w = shape.width + lineWidth; - h = shape.height + lineWidth; - - minX = x < minX ? x : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y < minY ? y : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.CIRC) - { - x = shape.x; - y = shape.y; - w = shape.radius + lineWidth/2; - h = shape.radius + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else if(type === PIXI.Graphics.ELIP) - { - x = shape.x; - y = shape.y; - w = shape.width + lineWidth/2; - h = shape.height + lineWidth/2; - - minX = x - w < minX ? x - w : minX; - maxX = x + w > maxX ? x + w : maxX; - - minY = y - h < minY ? y - h : minY; - maxY = y + h > maxY ? y + h : maxY; - } - else - { - // POLY - points = shape.points; - - for (var j = 0; j < points.length; j+=2) - { - - x = points[j]; - y = points[j+1]; - minX = x-lineWidth < minX ? x-lineWidth : minX; - maxX = x+lineWidth > maxX ? x+lineWidth : maxX; - - minY = y-lineWidth < minY ? y-lineWidth : minY; - maxY = y+lineWidth > maxY ? y+lineWidth : maxY; - } - } - } - } - else - { - minX = 0; - maxX = 0; - minY = 0; - maxY = 0; - } - - var padding = this.boundsPadding; - - this._localBounds.x = minX - padding; - this._localBounds.width = (maxX - minX) + padding * 2; - - this._localBounds.y = minY - padding; - this._localBounds.height = (maxY - minY) + padding * 2; -}; - -/** - * Generates the cached sprite when the sprite has cacheAsBitmap = true - * - * @method _generateCachedSprite - * @private - */ -PIXI.Graphics.prototype._generateCachedSprite = function() -{ - var bounds = this.getLocalBounds(); - - if(!this._cachedSprite) - { - var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height); - var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas); - - this._cachedSprite = new PIXI.Sprite(texture); - this._cachedSprite.buffer = canvasBuffer; - - this._cachedSprite.worldTransform = this.worldTransform; - } - else - { - this._cachedSprite.buffer.resize(bounds.width, bounds.height); - } - - // leverage the anchor to account for the offset of the element - this._cachedSprite.anchor.x = -( bounds.x / bounds.width ); - this._cachedSprite.anchor.y = -( bounds.y / bounds.height ); - - // this._cachedSprite.buffer.context.save(); - this._cachedSprite.buffer.context.translate(-bounds.x,-bounds.y); - - // make sure we set the alpha of the graphics to 1 for the render.. - this.worldAlpha = 1; - - // now render the graphic.. - PIXI.CanvasGraphics.renderGraphics(this, this._cachedSprite.buffer.context); - this._cachedSprite.alpha = this.alpha; - -}; - -/** - * Updates texture size based on canvas size - * - * @method updateCachedSpriteTexture - * @private - */ -PIXI.Graphics.prototype.updateCachedSpriteTexture = function() -{ - var cachedSprite = this._cachedSprite; - var texture = cachedSprite.texture; - var canvas = cachedSprite.buffer.canvas; - - texture.baseTexture.width = canvas.width; - texture.baseTexture.height = canvas.height; - texture.crop.width = texture.frame.width = canvas.width; - texture.crop.height = texture.frame.height = canvas.height; - - cachedSprite._width = canvas.width; - cachedSprite._height = canvas.height; - - // update the dirty base textures - texture.baseTexture.dirty(); -}; - -/** - * Destroys a previous cached sprite. - * - * @method destroyCachedSprite - */ -PIXI.Graphics.prototype.destroyCachedSprite = function() -{ - this._cachedSprite.texture.destroy(true); - - // let the gc collect the unused sprite - // TODO could be object pooled! - this._cachedSprite = null; -}; - -/** - * Draws the given shape to this Graphics object. Can be any of Circle, Rectangle, Ellipse, Line or Polygon. - * - * @method drawShape - * @param {Circle|Rectangle|Ellipse|Line|Polygon} shape The Shape object to draw. - * @return {GraphicsData} The generated GraphicsData object. - */ -PIXI.Graphics.prototype.drawShape = function(shape) -{ - if(this.currentPath) - { - // check current path! - if(this.currentPath.shape.points.length <= 2)this.graphicsData.pop(); - } - - this.currentPath = null; - - var data = new PIXI.GraphicsData(this.lineWidth, this.lineColor, this.lineAlpha, this.fillColor, this.fillAlpha, this.filling, shape); - - this.graphicsData.push(data); - - if(data.type === PIXI.Graphics.POLY) - { - data.shape.closed = this.filling; - this.currentPath = data; - } - - this.dirty = this.boundsDirty = true; - - return data; -}; - -/** - * A GraphicsData object. - * - * @class GraphicsData - * @constructor - */ -PIXI.GraphicsData = function(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, shape) -{ - this.lineWidth = lineWidth; - this.lineColor = lineColor; - this.lineAlpha = lineAlpha; - this._lineTint = lineColor; - - this.fillColor = fillColor; - this.fillAlpha = fillAlpha; - this._fillTint = fillColor; - this.fill = fill; - - this.shape = shape; - this.type = shape.type; -}; - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; -PIXI.Graphics.RREC = 4; - -PIXI.Polygon.prototype.type = PIXI.Graphics.POLY; -PIXI.Rectangle.prototype.type = PIXI.Graphics.RECT; -PIXI.Circle.prototype.type = PIXI.Graphics.CIRC; -PIXI.Ellipse.prototype.type = PIXI.Graphics.ELIP; -PIXI.RoundedRectangle.prototype.type = PIXI.Graphics.RREC; - diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js deleted file mode 100644 index 82dbc05..0000000 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ /dev/null @@ -1,558 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.glContexts = []; // this is where we store the webGL contexts for easy access. -PIXI.instances = []; - -/** - * The WebGLRenderer draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers that support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batches or Sprite Clouds. - * Don't forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param [width=0] {Number} the width of the canvas view - * @param [height=0] {Number} the height of the canvas view - * @param [options] {Object} The optional renderer parameters - * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional - * @param [options.transparent=false] {Boolean} If the render view is transparent, default false - * @param [options.autoResize=false] {Boolean} If the render view is automatically resized, default false - * @param [options.antialias=false] {Boolean} sets antialias (only applicable in chrome at the moment) - * @param [options.preserveDrawingBuffer=false] {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context - * @param [options.resolution=1] {Number} the resolution of the renderer retina would be 2 - */ -PIXI.WebGLRenderer = function(width, height, options) -{ - if(options) - { - for (var i in PIXI.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') options[i] = PIXI.defaultRenderOptions[i]; - } - } - else - { - options = PIXI.defaultRenderOptions; - } - - if(!PIXI.defaultRenderer) - { - PIXI.sayHello('webGL'); - PIXI.defaultRenderer = this; - } - - /** - * @property type - * @type Number - */ - this.type = PIXI.WEBGL_RENDERER; - - /** - * The resolution of the renderer - * - * @property resolution - * @type Number - * @default 1 - */ - this.resolution = options.resolution; - - // do a catch.. only 1 webGL renderer.. - - /** - * Whether the render view is transparent - * - * @property transparent - * @type Boolean - */ - this.transparent = options.transparent; - - /** - * Whether the render view should be resized automatically - * - * @property autoResize - * @type Boolean - */ - this.autoResize = options.autoResize || false; - - /** - * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. - * - * @property preserveDrawingBuffer - * @type Boolean - */ - this.preserveDrawingBuffer = options.preserveDrawingBuffer; - - /** - * This sets if the WebGLRenderer will clear the context texture or not before the new render pass. If true: - * If the Stage is NOT transparent, Pixi will clear to alpha (0, 0, 0, 0). - * If the Stage is transparent, Pixi will clear to the target Stage's background color. - * Disable this by setting this to false. For example: if your game has a canvas filling background image, you often don't need this set. - * - * @property clearBeforeRender - * @type Boolean - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that everything is drawn to - * - * @property view - * @type HTMLCanvasElement - */ - this.view = options.view || document.createElement( 'canvas' ); - - // deal with losing context.. - - /** - * @property contextLostBound - * @type Function - */ - this.contextLostBound = this.handleContextLost.bind(this); - - /** - * @property contextRestoredBound - * @type Function - */ - this.contextRestoredBound = this.handleContextRestored.bind(this); - - this.view.addEventListener('webglcontextlost', this.contextLostBound, false); - this.view.addEventListener('webglcontextrestored', this.contextRestoredBound, false); - - /** - * @property _contextOptions - * @type Object - * @private - */ - this._contextOptions = { - alpha: this.transparent, - antialias: options.antialias, // SPEED UP?? - premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', - stencil:true, - preserveDrawingBuffer: options.preserveDrawingBuffer - }; - - /** - * @property projection - * @type Point - */ - this.projection = new PIXI.Point(); - - /** - * @property offset - * @type Point - */ - this.offset = new PIXI.Point(0, 0); - - // time to create the render managers! each one focuses on managing a state in webGL - - /** - * Deals with managing the shader programs and their attribs - * @property shaderManager - * @type WebGLShaderManager - */ - this.shaderManager = new PIXI.WebGLShaderManager(); - - /** - * Manages the rendering of sprites - * @property spriteBatch - * @type WebGLSpriteBatch - */ - this.spriteBatch = new PIXI.WebGLSpriteBatch(); - - /** - * Manages the masks using the stencil buffer - * @property maskManager - * @type WebGLMaskManager - */ - this.maskManager = new PIXI.WebGLMaskManager(); - - /** - * Manages the filters - * @property filterManager - * @type WebGLFilterManager - */ - this.filterManager = new PIXI.WebGLFilterManager(); - - /** - * Manages the stencil buffer - * @property stencilManager - * @type WebGLStencilManager - */ - this.stencilManager = new PIXI.WebGLStencilManager(); - - /** - * Manages the blendModes - * @property blendModeManager - * @type WebGLBlendModeManager - */ - this.blendModeManager = new PIXI.WebGLBlendModeManager(); - - /** - * TODO remove - * @property renderSession - * @type Object - */ - this.renderSession = {}; - this.renderSession.gl = this.gl; - this.renderSession.drawCount = 0; - this.renderSession.shaderManager = this.shaderManager; - this.renderSession.maskManager = this.maskManager; - this.renderSession.filterManager = this.filterManager; - this.renderSession.blendModeManager = this.blendModeManager; - this.renderSession.spriteBatch = this.spriteBatch; - this.renderSession.stencilManager = this.stencilManager; - this.renderSession.renderer = this; - this.renderSession.resolution = this.resolution; - this.renderSession.buffer = null; - - // time init the context.. - this.initContext(); - - // map some webGL blend modes.. - this.mapBlendModes(); -}; - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** -* @method initContext -*/ -PIXI.WebGLRenderer.prototype.initContext = function() -{ - var gl = this.view.getContext('webgl', this._contextOptions) || this.view.getContext('experimental-webgl', this._contextOptions); - this.gl = gl; - - if (!gl) { - // fail, not able to get a context - throw new Error('This browser does not support webGL. Try using the canvas renderer'); - } - - this.glContextId = gl.id = PIXI.WebGLRenderer.glContextId ++; - - PIXI.glContexts[this.glContextId] = gl; - - PIXI.instances[this.glContextId] = this; - - // set up the default pixi settings.. - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); - - // need to set the context for all the managers... - this.shaderManager.setContext(gl); - this.spriteBatch.setContext(gl); - this.maskManager.setContext(gl); - this.filterManager.setContext(gl); - this.blendModeManager.setContext(gl); - this.stencilManager.setContext(gl); - - this.renderSession.gl = this.gl; - - // now resize and we are good to go! - this.resize(this.width, this.height); -}; - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - // no point rendering if our context has been blown up! - if(this.contextLost)return; - - // if rendering a new stage clear the batches.. - if(this.__stage !== stage) - { - if(stage.interactive)stage.interactionManager.removeEvents(); - - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - } - - // update the scene graph - stage.updateTransform(); - - var gl = this.gl; - - // interaction - if(stage._interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - else - { - if(stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = false; - stage.interactionManager.setTarget(this); - } - } - - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - - // make sure we are bound to the main frame buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - if (this.clearBeforeRender) - { - if(this.transparent) - { - gl.clearColor(0, 0, 0, 0); - } - else - { - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); - } - - gl.clear (gl.COLOR_BUFFER_BIT); - } - - this.renderDisplayObject( stage, this.projection ); -}; - -/** - * Renders a Display Object. - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The DisplayObject to render - * @param projection {Point} The projection - * @param buffer {Array} a standard WebGL buffer - */ -PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection, buffer) -{ - this.renderSession.blendModeManager.setBlendMode(PIXI.blendModes.NORMAL); - - // reset the render session data.. - this.renderSession.drawCount = 0; - - // set the buffer ref.. - this.renderSession.buffer = buffer; - - // make sure to flip the Y if using a render texture.. - this.renderSession.flipY = buffer ? -1 : 1; - - // set the default projection - this.renderSession.projection = projection; - - //set the default offset - this.renderSession.offset = this.offset; - - // start the sprite batch - this.spriteBatch.begin(this.renderSession); - - // start the filter manager - this.filterManager.begin(this.renderSession, buffer); - - // render the scene! - displayObject._renderWebGL(this.renderSession); - - // finish the sprite batch - this.spriteBatch.end(); -}; - -/** - * Resizes the webGL view to the specified width and height. - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width * this.resolution; - this.height = height * this.resolution; - - this.view.width = this.width; - this.view.height = this.height; - - if (this.autoResize) { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } - - this.gl.viewport(0, 0, this.width, this.height); - - this.projection.x = this.width / 2 / this.resolution; - this.projection.y = -this.height / 2 / this.resolution; -}; - -/** - * Updates and Creates a WebGL texture for the renderers context. - * - * @method updateTexture - * @param texture {Texture} the texture to update - */ -PIXI.WebGLRenderer.prototype.updateTexture = function(texture) -{ - if(!texture.hasLoaded )return; - - var gl = this.gl; - - if(!texture._glTextures[gl.id])texture._glTextures[gl.id] = gl.createTexture(); - - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - - - if(texture.mipmap && PIXI.isPowerOfTwo(texture.width, texture.height)) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); - gl.generateMipmap(gl.TEXTURE_2D); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); - } - - // reguler... - if(!texture._powerOf2) - { - 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); - } - - texture._dirty[gl.id] = false; - - return texture._glTextures[gl.id]; -}; - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -}; - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function() -{ - this.initContext(); - - // empty all the ol gl textures as they are useless now - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTextures = []; - } - - this.contextLost = false; -}; - -/** - * Removes everything from the renderer (event listeners, spritebatch, etc...) - * - * @method destroy - */ -PIXI.WebGLRenderer.prototype.destroy = function() -{ - // remove listeners - this.view.removeEventListener('webglcontextlost', this.contextLostBound); - this.view.removeEventListener('webglcontextrestored', this.contextRestoredBound); - - PIXI.glContexts[this.glContextId] = null; - - this.projection = null; - this.offset = null; - - // time to create the render managers! each one focuses on managine a state in webGL - this.shaderManager.destroy(); - this.spriteBatch.destroy(); - this.maskManager.destroy(); - this.filterManager.destroy(); - - this.shaderManager = null; - this.spriteBatch = null; - this.maskManager = null; - this.filterManager = null; - - this.gl = null; - this.renderSession = null; -}; - -/** - * Maps Pixi blend modes to WebGL blend modes. - * - * @method mapBlendModes - */ -PIXI.WebGLRenderer.prototype.mapBlendModes = function() -{ - var gl = this.gl; - - if(!PIXI.blendModesWebGL) - { - PIXI.blendModesWebGL = []; - - PIXI.blendModesWebGL[PIXI.blendModes.NORMAL] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.ADD] = [gl.SRC_ALPHA, gl.DST_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.MULTIPLY] = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SCREEN] = [gl.SRC_ALPHA, gl.ONE]; - PIXI.blendModesWebGL[PIXI.blendModes.OVERLAY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DARKEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LIGHTEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_DODGE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR_BURN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HARD_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SOFT_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.DIFFERENCE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.EXCLUSION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.HUE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; - } -}; - -PIXI.WebGLRenderer.glContextId = 0; diff --git a/src/pixi/renderers/webgl/shaders/PixiShader.js b/src/pixi/renderers/webgl/shaders/PixiShader.js deleted file mode 100644 index bb4a17d..0000000 --- a/src/pixi/renderers/webgl/shaders/PixiShader.js +++ /dev/null @@ -1,397 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * @author Richard Davey http://www.photonstorm.com @photonstorm - */ - -/** -* @class PixiShader -* @constructor -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.PixiShader = function(gl) -{ - /** - * @property _UID - * @type Number - * @private - */ - this._UID = PIXI._UID++; - - /** - * @property gl - * @type WebGLContext - */ - this.gl = gl; - - /** - * The WebGL program. - * @property program - * @type Any - */ - this.program = null; - - /** - * The fragment shader. - * @property fragmentSrc - * @type Array - */ - this.fragmentSrc = [ - 'precision lowp float;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - 'uniform sampler2D uSampler;', - 'void main(void) {', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;', - '}' - ]; - - /** - * A local texture counter for multi-texture shaders. - * @property textureCount - * @type Number - */ - this.textureCount = 0; - - /** - * A local flag - * @property firstRun - * @type Boolean - * @private - */ - this.firstRun = true; - - /** - * A dirty flag - * @property dirty - * @type Boolean - */ - this.dirty = true; - - /** - * Uniform attributes cache. - * @property attributes - * @type Array - * @private - */ - this.attributes = []; - - this.init(); -}; - -PIXI.PixiShader.prototype.constructor = PIXI.PixiShader; - -/** -* Initialises the shader. -* -* @method init -*/ -PIXI.PixiShader.prototype.init = function() -{ - var gl = this.gl; - - var program = PIXI.compileProgram(gl, this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc); - - gl.useProgram(program); - - // get and store the uniforms for the shader - this.uSampler = gl.getUniformLocation(program, 'uSampler'); - this.projectionVector = gl.getUniformLocation(program, 'projectionVector'); - this.offsetVector = gl.getUniformLocation(program, 'offsetVector'); - this.dimensions = gl.getUniformLocation(program, 'dimensions'); - this.flipY = gl.getUniformLocation(program, 'flipY'); - - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition'); - this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord'); - this.colorAttribute = gl.getAttribLocation(program, 'aColor'); - - - // Begin worst hack eva // - - // WHY??? ONLY on my chrome pixel the line above returns -1 when using filters? - // maybe its something to do with the current state of the gl context. - // I'm convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel - // If theres any webGL people that know why could happen please help :) - if(this.colorAttribute === -1) - { - this.colorAttribute = 2; - } - - this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute]; - - // End worst hack eva // - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key); - } - - this.initUniforms(); - - this.program = program; -}; - -/** -* Initialises the shader uniform values. -* -* Uniforms are specified in the GLSL_ES Specification: http://www.khronos.org/registry/webgl/specs/latest/1.0/ -* http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf -* -* @method initUniforms -*/ -PIXI.PixiShader.prototype.initUniforms = function() -{ - this.textureCount = 1; - var gl = this.gl; - var uniform; - - for (var key in this.uniforms) - { - uniform = this.uniforms[key]; - - var type = uniform.type; - - if (type === 'sampler2D') - { - uniform._init = false; - - if (uniform.value !== null) - { - this.initSampler2D(uniform); - } - } - else if (type === 'mat2' || type === 'mat3' || type === 'mat4') - { - // These require special handling - uniform.glMatrix = true; - uniform.glValueLength = 1; - - if (type === 'mat2') - { - uniform.glFunc = gl.uniformMatrix2fv; - } - else if (type === 'mat3') - { - uniform.glFunc = gl.uniformMatrix3fv; - } - else if (type === 'mat4') - { - uniform.glFunc = gl.uniformMatrix4fv; - } - } - else - { - // GL function reference - uniform.glFunc = gl['uniform' + type]; - - if (type === '2f' || type === '2i') - { - uniform.glValueLength = 2; - } - else if (type === '3f' || type === '3i') - { - uniform.glValueLength = 3; - } - else if (type === '4f' || type === '4i') - { - uniform.glValueLength = 4; - } - else - { - uniform.glValueLength = 1; - } - } - } - -}; - -/** -* Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture has loaded) -* -* @method initSampler2D -*/ -PIXI.PixiShader.prototype.initSampler2D = function(uniform) -{ - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) - { - return; - } - - var gl = this.gl; - - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); - - // Extended texture data - if (uniform.textureData) - { - var data = uniform.textureData; - - // GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D); - // GLTextureLinear = mag/min linear, wrap clamp - // GLTextureNearestRepeat = mag/min NEAREST, wrap repeat - // GLTextureNearest = mag/min nearest, wrap clamp - // AudioTexture = whatever + luminance + width 512, height 2, border 0 - // KeyTexture = whatever + luminance + width 256, height 2, border 0 - - // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST - // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; - - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } - - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); - } - - gl.uniform1i(uniform.uniformLocation, this.textureCount); - - uniform._init = true; - - this.textureCount++; - -}; - -/** -* Updates the shader uniform values. -* -* @method syncUniforms -*/ -PIXI.PixiShader.prototype.syncUniforms = function() -{ - this.textureCount = 1; - var uniform; - var gl = this.gl; - - // This would probably be faster in an array and it would guarantee key order - for (var key in this.uniforms) - { - uniform = this.uniforms[key]; - - if (uniform.glValueLength === 1) - { - if (uniform.glMatrix === true) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.transpose, uniform.value); - } - else - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value); - } - } - else if (uniform.glValueLength === 2) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y); - } - else if (uniform.glValueLength === 3) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z); - } - else if (uniform.glValueLength === 4) - { - uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z, uniform.value.w); - } - else if (uniform.type === 'sampler2D') - { - if (uniform._init) - { - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - - if(uniform.value.baseTexture._dirty[gl.id]) - { - PIXI.instances[gl.id].updateTexture(uniform.value.baseTexture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); - } - - // gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id] || PIXI.createWebGLTexture( uniform.value.baseTexture, gl)); - gl.uniform1i(uniform.uniformLocation, this.textureCount); - this.textureCount++; - } - else - { - this.initSampler2D(uniform); - } - } - } - -}; - -/** -* Destroys the shader. -* -* @method destroy -*/ -PIXI.PixiShader.prototype.destroy = function() -{ - this.gl.deleteProgram( this.program ); - this.uniforms = null; - this.gl = null; - - this.attributes = null; -}; - -/** -* The Default Vertex shader source. -* -* @property defaultVertexSrc -* @type String -*/ -PIXI.PixiShader.defaultVertexSrc = [ - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - - 'uniform float flipY;', - - 'uniform vec2 projectionVector;', - 'uniform vec2 offsetVector;', - - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'void main(void) {', - - ' vec3 temp = vec3(-1.0, 1.0, flipY);', - - ' gl_Position = vec4( (aVertexPosition + offsetVector) / (projectionVector * temp.yz) + temp.xz , 0.0, 1.0);', - - ' vTextureCoord = aTextureCoord;', - - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - - '}' -]; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/utils/WebGLFilterManager.js b/src/pixi/renderers/webgl/utils/WebGLFilterManager.js deleted file mode 100644 index ba642c3..0000000 --- a/src/pixi/renderers/webgl/utils/WebGLFilterManager.js +++ /dev/null @@ -1,452 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** -* @class WebGLFilterManager -* @constructor -*/ -PIXI.WebGLFilterManager = function() -{ - /** - * @property filterStack - * @type Array - */ - this.filterStack = []; - - /** - * @property offsetX - * @type Number - */ - this.offsetX = 0; - - /** - * @property offsetY - * @type Number - */ - this.offsetY = 0; -}; - -PIXI.WebGLFilterManager.prototype.constructor = PIXI.WebGLFilterManager; - -/** -* Initialises the context and the properties. -* -* @method setContext -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.WebGLFilterManager.prototype.setContext = function(gl) -{ - this.gl = gl; - this.texturePool = []; - - this.initShaderBuffers(); -}; - -/** -* @method begin -* @param renderSession {RenderSession} -* @param buffer {ArrayBuffer} -*/ -PIXI.WebGLFilterManager.prototype.begin = function(renderSession, buffer) -{ - this.renderSession = renderSession; - this.defaultShader = renderSession.shaderManager.defaultShader; - - var projection = this.renderSession.projection; - this.width = projection.x * 2; - this.height = -projection.y * 2; - this.buffer = buffer; -}; - -/** -* Applies the filter and adds it to the current filter stack. -* -* @method pushFilter -* @param filterBlock {Object} the filter that will be pushed to the current filter stack -*/ -PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock) -{ - var gl = this.gl; - - var projection = this.renderSession.projection; - var offset = this.renderSession.offset; - - filterBlock._filterArea = filterBlock.target.filterArea || filterBlock.target.getBounds(); - - // filter program - // OPTIMISATION - the first filter is free if its a simple color change? - this.filterStack.push(filterBlock); - - var filter = filterBlock.filterPasses[0]; - - this.offsetX += filterBlock._filterArea.x; - this.offsetY += filterBlock._filterArea.y; - - var texture = this.texturePool.pop(); - if(!texture) - { - texture = new PIXI.FilterTexture(this.gl, this.width, this.height); - } - else - { - texture.resize(this.width, this.height); - } - - gl.bindTexture(gl.TEXTURE_2D, texture.texture); - - var filterArea = filterBlock._filterArea;// filterBlock.target.getBounds();///filterBlock.target.filterArea; - - var padding = filter.padding; - filterArea.x -= padding; - filterArea.y -= padding; - filterArea.width += padding * 2; - filterArea.height += padding * 2; - - // cap filter to screen size.. - if(filterArea.x < 0)filterArea.x = 0; - if(filterArea.width > this.width)filterArea.width = this.width; - if(filterArea.y < 0)filterArea.y = 0; - if(filterArea.height > this.height)filterArea.height = this.height; - - //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - gl.bindFramebuffer(gl.FRAMEBUFFER, texture.frameBuffer); - - // set view port - gl.viewport(0, 0, filterArea.width, filterArea.height); - - projection.x = filterArea.width/2; - projection.y = -filterArea.height/2; - - offset.x = -filterArea.x; - offset.y = -filterArea.y; - - // update projection - // now restore the regular shader.. - // this.renderSession.shaderManager.setShader(this.defaultShader); - //gl.uniform2f(this.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2); - //gl.uniform2f(this.defaultShader.offsetVector, -filterArea.x, -filterArea.y); - - gl.colorMask(true, true, true, true); - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - - filterBlock._glFilterTexture = texture; - -}; - -/** -* Removes the last filter from the filter stack and doesn't return it. -* -* @method popFilter -*/ -PIXI.WebGLFilterManager.prototype.popFilter = function() -{ - var gl = this.gl; - var filterBlock = this.filterStack.pop(); - var filterArea = filterBlock._filterArea; - var texture = filterBlock._glFilterTexture; - var projection = this.renderSession.projection; - var offset = this.renderSession.offset; - - if(filterBlock.filterPasses.length > 1) - { - gl.viewport(0, 0, filterArea.width, filterArea.height); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - - this.vertexArray[0] = 0; - this.vertexArray[1] = filterArea.height; - - this.vertexArray[2] = filterArea.width; - this.vertexArray[3] = filterArea.height; - - this.vertexArray[4] = 0; - this.vertexArray[5] = 0; - - this.vertexArray[6] = filterArea.width; - this.vertexArray[7] = 0; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - // now set the uvs.. - this.uvArray[2] = filterArea.width/this.width; - this.uvArray[5] = filterArea.height/this.height; - this.uvArray[6] = filterArea.width/this.width; - this.uvArray[7] = filterArea.height/this.height; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); - - var inputTexture = texture; - var outputTexture = this.texturePool.pop(); - if(!outputTexture)outputTexture = new PIXI.FilterTexture(this.gl, this.width, this.height); - outputTexture.resize(this.width, this.height); - - // need to clear this FBO as it may have some left over elements from a previous filter. - gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); - gl.clear(gl.COLOR_BUFFER_BIT); - - gl.disable(gl.BLEND); - - for (var i = 0; i < filterBlock.filterPasses.length-1; i++) - { - var filterPass = filterBlock.filterPasses[i]; - - gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); - - // set texture - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture); - - // draw texture.. - //filterPass.applyFilterPass(filterArea.width, filterArea.height); - this.applyFilterPass(filterPass, filterArea, filterArea.width, filterArea.height); - - // swap the textures.. - var temp = inputTexture; - inputTexture = outputTexture; - outputTexture = temp; - } - - gl.enable(gl.BLEND); - - texture = inputTexture; - this.texturePool.push(outputTexture); - } - - var filter = filterBlock.filterPasses[filterBlock.filterPasses.length-1]; - - this.offsetX -= filterArea.x; - this.offsetY -= filterArea.y; - - var sizeX = this.width; - var sizeY = this.height; - - var offsetX = 0; - var offsetY = 0; - - var buffer = this.buffer; - - // time to render the filters texture to the previous scene - if(this.filterStack.length === 0) - { - gl.colorMask(true, true, true, true);//this.transparent); - } - else - { - var currentFilter = this.filterStack[this.filterStack.length-1]; - filterArea = currentFilter._filterArea; - - sizeX = filterArea.width; - sizeY = filterArea.height; - - offsetX = filterArea.x; - offsetY = filterArea.y; - - buffer = currentFilter._glFilterTexture.frameBuffer; - } - - // TODO need to remove these global elements.. - projection.x = sizeX/2; - projection.y = -sizeY/2; - - offset.x = offsetX; - offset.y = offsetY; - - filterArea = filterBlock._filterArea; - - var x = filterArea.x-offsetX; - var y = filterArea.y-offsetY; - - // update the buffers.. - // make sure to flip the y! - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - - this.vertexArray[0] = x; - this.vertexArray[1] = y + filterArea.height; - - this.vertexArray[2] = x + filterArea.width; - this.vertexArray[3] = y + filterArea.height; - - this.vertexArray[4] = x; - this.vertexArray[5] = y; - - this.vertexArray[6] = x + filterArea.width; - this.vertexArray[7] = y; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - this.uvArray[2] = filterArea.width/this.width; - this.uvArray[5] = filterArea.height/this.height; - this.uvArray[6] = filterArea.width/this.width; - this.uvArray[7] = filterArea.height/this.height; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); - - gl.viewport(0, 0, sizeX, sizeY); - - // bind the buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, buffer ); - - // set the blend mode! - //gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) - - // set texture - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture.texture); - - // apply! - this.applyFilterPass(filter, filterArea, sizeX, sizeY); - - // now restore the regular shader.. should happen automatically now.. - // this.renderSession.shaderManager.setShader(this.defaultShader); - // gl.uniform2f(this.defaultShader.projectionVector, sizeX/2, -sizeY/2); - // gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY); - - // return the texture to the pool - this.texturePool.push(texture); - filterBlock._glFilterTexture = null; -}; - - -/** -* Applies the filter to the specified area. -* -* @method applyFilterPass -* @param filter {AbstractFilter} the filter that needs to be applied -* @param filterArea {Texture} TODO - might need an update -* @param width {Number} the horizontal range of the filter -* @param height {Number} the vertical range of the filter -*/ -PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea, width, height) -{ - // use program - var gl = this.gl; - var shader = filter.shaders[gl.id]; - - if(!shader) - { - shader = new PIXI.PixiShader(gl); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shaders[gl.id] = shader; - } - - // set the shader - this.renderSession.shaderManager.setShader(shader); - -// gl.useProgram(shader.program); - - gl.uniform2f(shader.projectionVector, width/2, -height/2); - gl.uniform2f(shader.offsetVector, 0,0); - - gl.uniform1f(shader.flipY, this.renderSession.flipY); - - if(filter.uniforms.dimensions) - { - filter.uniforms.dimensions.value[0] = this.width;//width; - filter.uniforms.dimensions.value[1] = this.height;//height; - filter.uniforms.dimensions.value[2] = this.vertexArray[0]; - filter.uniforms.dimensions.value[3] = this.vertexArray[5];//filterArea.height; - } - - shader.syncUniforms(); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.vertexAttribPointer(shader.colorAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - // draw the filter... - gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - this.renderSession.drawCount++; -}; - -/** -* Initialises the shader buffers. -* -* @method initShaderBuffers -*/ -PIXI.WebGLFilterManager.prototype.initShaderBuffers = function() -{ - var gl = this.gl; - - // create some buffers - this.vertexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - - // bind and upload the vertexs.. - // keep a reference to the vertexFloatData.. - this.vertexArray = new PIXI.Float32Array([0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.vertexArray, gl.STATIC_DRAW); - - // bind and upload the uv buffer - this.uvArray = new PIXI.Float32Array([0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvArray, gl.STATIC_DRAW); - - this.colorArray = new PIXI.Float32Array([1.0, 0xFFFFFF, - 1.0, 0xFFFFFF, - 1.0, 0xFFFFFF, - 1.0, 0xFFFFFF]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colorArray, gl.STATIC_DRAW); - - // bind and upload the index - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 1, 3, 2]), gl.STATIC_DRAW); - -}; - -/** -* Destroys the filter and removes it from the filter stack. -* -* @method destroy -*/ -PIXI.WebGLFilterManager.prototype.destroy = function() -{ - var gl = this.gl; - - this.filterStack = null; - - this.offsetX = 0; - this.offsetY = 0; - - // destroy textures - for (var i = 0; i < this.texturePool.length; i++) { - this.texturePool[i].destroy(); - } - - this.texturePool = null; - - //destroy buffers.. - gl.deleteBuffer(this.vertexBuffer); - gl.deleteBuffer(this.uvBuffer); - gl.deleteBuffer(this.colorBuffer); - gl.deleteBuffer(this.indexBuffer); -}; diff --git a/src/pixi/renderers/webgl/utils/WebGLShaderManager.js b/src/pixi/renderers/webgl/utils/WebGLShaderManager.js deleted file mode 100644 index 168e4ac..0000000 --- a/src/pixi/renderers/webgl/utils/WebGLShaderManager.js +++ /dev/null @@ -1,158 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** -* @class WebGLShaderManager -* @constructor -* @private -*/ -PIXI.WebGLShaderManager = function() -{ - /** - * @property maxAttibs - * @type Number - */ - this.maxAttibs = 10; - - /** - * @property attribState - * @type Array - */ - this.attribState = []; - - /** - * @property tempAttribState - * @type Array - */ - this.tempAttribState = []; - - for (var i = 0; i < this.maxAttibs; i++) - { - this.attribState[i] = false; - } - - /** - * @property stack - * @type Array - */ - this.stack = []; - -}; - -PIXI.WebGLShaderManager.prototype.constructor = PIXI.WebGLShaderManager; - -/** -* Initialises the context and the properties. -* -* @method setContext -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.WebGLShaderManager.prototype.setContext = function(gl) -{ - this.gl = gl; - - // the next one is used for rendering primitives - this.primitiveShader = new PIXI.PrimitiveShader(gl); - - // the next one is used for rendering triangle strips - this.complexPrimitiveShader = new PIXI.ComplexPrimitiveShader(gl); - - // this shader is used for the default sprite rendering - this.defaultShader = new PIXI.PixiShader(gl); - - // this shader is used for the fast sprite rendering - this.fastShader = new PIXI.PixiFastShader(gl); - - // the next one is used for rendering triangle strips - this.stripShader = new PIXI.StripShader(gl); - this.setShader(this.defaultShader); -}; - -/** -* Takes the attributes given in parameters. -* -* @method setAttribs -* @param attribs {Array} attribs -*/ -PIXI.WebGLShaderManager.prototype.setAttribs = function(attribs) -{ - // reset temp state - var i; - - for (i = 0; i < this.tempAttribState.length; i++) - { - this.tempAttribState[i] = false; - } - - // set the new attribs - for (i = 0; i < attribs.length; i++) - { - var attribId = attribs[i]; - this.tempAttribState[attribId] = true; - } - - var gl = this.gl; - - for (i = 0; i < this.attribState.length; i++) - { - if(this.attribState[i] !== this.tempAttribState[i]) - { - this.attribState[i] = this.tempAttribState[i]; - - if(this.tempAttribState[i]) - { - gl.enableVertexAttribArray(i); - } - else - { - gl.disableVertexAttribArray(i); - } - } - } -}; - -/** -* Sets the current shader. -* -* @method setShader -* @param shader {Any} -*/ -PIXI.WebGLShaderManager.prototype.setShader = function(shader) -{ - if(this._currentId === shader._UID)return false; - - this._currentId = shader._UID; - - this.currentShader = shader; - - this.gl.useProgram(shader.program); - - this.setAttribs(shader.attributes); - - return true; -}; - -/** -* Destroys this object. -* -* @method destroy -*/ -PIXI.WebGLShaderManager.prototype.destroy = function() -{ - this.attribState = null; - - this.tempAttribState = null; - - this.primitiveShader.destroy(); - - this.complexPrimitiveShader.destroy(); - - this.defaultShader.destroy(); - - this.fastShader.destroy(); - - this.stripShader.destroy(); - - this.gl = null; -}; diff --git a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js deleted file mode 100755 index b4d873b..0000000 --- a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js +++ /dev/null @@ -1,639 +0,0 @@ -/** - * @author Mat Groves - * - * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ - * for creating the original pixi version! - * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer - * - * Heavily inspired by LibGDX's WebGLSpriteBatch: - * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/WebGLSpriteBatch.java - */ - - /** - * - * @class WebGLSpriteBatch - * @private - * @constructor - */ -PIXI.WebGLSpriteBatch = function() -{ - /** - * @property vertSize - * @type Number - */ - this.vertSize = 5; - - /** - * The number of images in the SpriteBatch before it flushes - * @property size - * @type Number - */ - this.size = 2000;//Math.pow(2, 16) / this.vertSize; - - //the total number of bytes in our batch - var numVerts = this.size * 4 * 4 * this.vertSize; - //the total number of indices in our batch - var numIndices = this.size * 6; - - /** - * Holds the vertices - * - * @property vertices - * @type ArrayBuffer - */ - this.vertices = new PIXI.ArrayBuffer(numVerts); - - /** - * View on the vertices as a Float32Array - * - * @property positions - * @type Float32Array - */ - this.positions = new PIXI.Float32Array(this.vertices); - - /** - * View on the vertices as a Uint32Array - * - * @property colors - * @type Uint32Array - */ - this.colors = new PIXI.Uint32Array(this.vertices); - - /** - * Holds the indices - * - * @property indices - * @type Uint16Array - */ - this.indices = new PIXI.Uint16Array(numIndices); - - /** - * @property lastIndexCount - * @type Number - */ - 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; - } - - /** - * @property drawing - * @type Boolean - */ - this.drawing = false; - - /** - * @property currentBatchSize - * @type Number - */ - this.currentBatchSize = 0; - - /** - * @property currentBaseTexture - * @type BaseTexture - */ - this.currentBaseTexture = null; - - /** - * @property dirty - * @type Boolean - */ - this.dirty = true; - - /** - * @property textures - * @type Array - */ - this.textures = []; - - /** - * @property blendModes - * @type Array - */ - this.blendModes = []; - - /** - * @property shaders - * @type Array - */ - this.shaders = []; - - /** - * @property sprites - * @type Array - */ - this.sprites = []; - - /** - * @property defaultShader - * @type AbstractFilter - */ - this.defaultShader = new PIXI.AbstractFilter([ - 'precision lowp float;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - 'uniform sampler2D uSampler;', - 'void main(void) {', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;', - '}' - ]); -}; - -/** -* @method setContext -* @param gl {WebGLContext} the current WebGL drawing context -*/ -PIXI.WebGLSpriteBatch.prototype.setContext = function(gl) -{ - this.gl = gl; - - // create a couple of buffers - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - - // 65535 is max index, so 65535 / 6 = 10922. - - //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.currentBlendMode = 99999; - - var shader = new PIXI.PixiShader(gl); - - shader.fragmentSrc = this.defaultShader.fragmentSrc; - shader.uniforms = {}; - shader.init(); - - this.defaultShader.shaders[gl.id] = shader; -}; - -/** -* @method begin -* @param renderSession {Object} The RenderSession object -*/ -PIXI.WebGLSpriteBatch.prototype.begin = function(renderSession) -{ - this.renderSession = renderSession; - this.shader = this.renderSession.shaderManager.defaultShader; - - this.start(); -}; - -/** -* @method end -*/ -PIXI.WebGLSpriteBatch.prototype.end = function() -{ - this.flush(); -}; - -/** -* @method render -* @param sprite {Sprite} the sprite to render when using this spritebatch -*/ -PIXI.WebGLSpriteBatch.prototype.render = function(sprite) -{ - var texture = sprite.texture; - - //TODO set blend modes.. - // check texture.. - if(this.currentBatchSize >= this.size) - { - this.flush(); - this.currentBaseTexture = texture.baseTexture; - } - - // get the uvs for the texture - var uvs = texture._uvs; - // if the uvs have not updated then no point rendering just yet! - if(!uvs)return; - - // TODO trim?? - var aX = sprite.anchor.x; - var aY = sprite.anchor.y; - - var w0, w1, h0, h1; - - if (texture.trim) - { - // if the sprite is trimmed 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 * 4 * this.vertSize; - - var resolution = texture.baseTexture.resolution; - - var worldTransform = sprite.worldTransform; - - var a = worldTransform.a / resolution; - var b = worldTransform.b / resolution; - var c = worldTransform.c / resolution; - var d = worldTransform.d / resolution; - var tx = worldTransform.tx; - var ty = worldTransform.ty; - - var colors = this.colors; - var positions = this.positions; - - if(this.renderSession.roundPixels) - { - // xy - positions[index] = a * w1 + c * h1 + tx | 0; - positions[index+1] = d * h1 + b * w1 + ty | 0; - - // xy - positions[index+5] = a * w0 + c * h1 + tx | 0; - positions[index+6] = d * h1 + b * w0 + ty | 0; - - // xy - positions[index+10] = a * w0 + c * h0 + tx | 0; - positions[index+11] = d * h0 + b * w0 + ty | 0; - - // xy - positions[index+15] = a * w1 + c * h0 + tx | 0; - positions[index+16] = d * h0 + b * w1 + ty | 0; - } - else - { - // xy - positions[index] = a * w1 + c * h1 + tx; - positions[index+1] = d * h1 + b * w1 + ty; - - // xy - positions[index+5] = a * w0 + c * h1 + tx; - positions[index+6] = d * h1 + b * w0 + ty; - - // xy - positions[index+10] = a * w0 + c * h0 + tx; - positions[index+11] = d * h0 + b * w0 + ty; - - // xy - positions[index+15] = a * w1 + c * h0 + tx; - positions[index+16] = d * h0 + b * w1 + ty; - } - - // uv - positions[index+2] = uvs.x0; - positions[index+3] = uvs.y0; - - // uv - positions[index+7] = uvs.x1; - positions[index+8] = uvs.y1; - - // uv - positions[index+12] = uvs.x2; - positions[index+13] = uvs.y2; - - // uv - positions[index+17] = uvs.x3; - positions[index+18] = uvs.y3; - - // color and alpha - var tint = sprite.tint; - colors[index+4] = colors[index+9] = colors[index+14] = colors[index+19] = (tint >> 16) + (tint & 0xff00) + ((tint & 0xff) << 16) + (sprite.worldAlpha * 255 << 24); - - // increment the batchsize - this.sprites[this.currentBatchSize++] = sprite; - - -}; - -/** -* Renders a TilingSprite using the spriteBatch. -* -* @method renderTilingSprite -* @param sprite {TilingSprite} the tilingSprite to render -*/ -PIXI.WebGLSpriteBatch.prototype.renderTilingSprite = function(tilingSprite) -{ - var texture = tilingSprite.tilingTexture; - - // check texture.. - if(this.currentBatchSize >= this.size) - { - //return; - this.flush(); - this.currentBaseTexture = texture.baseTexture; - } - - // set the textures uvs temporarily - // TODO create a separate texture so that we can tile part of a texture - - if(!tilingSprite._uvs)tilingSprite._uvs = new PIXI.TextureUvs(); - - var uvs = tilingSprite._uvs; - - tilingSprite.tilePosition.x %= texture.baseTexture.width * tilingSprite.tileScaleOffset.x; - tilingSprite.tilePosition.y %= texture.baseTexture.height * tilingSprite.tileScaleOffset.y; - - var offsetX = tilingSprite.tilePosition.x/(texture.baseTexture.width*tilingSprite.tileScaleOffset.x); - var offsetY = tilingSprite.tilePosition.y/(texture.baseTexture.height*tilingSprite.tileScaleOffset.y); - - var scaleX = (tilingSprite.width / texture.baseTexture.width) / (tilingSprite.tileScale.x * tilingSprite.tileScaleOffset.x); - var scaleY = (tilingSprite.height / texture.baseTexture.height) / (tilingSprite.tileScale.y * tilingSprite.tileScaleOffset.y); - - uvs.x0 = 0 - offsetX; - uvs.y0 = 0 - offsetY; - - uvs.x1 = (1 * scaleX) - offsetX; - uvs.y1 = 0 - offsetY; - - uvs.x2 = (1 * scaleX) - offsetX; - uvs.y2 = (1 * scaleY) - offsetY; - - uvs.x3 = 0 - offsetX; - uvs.y3 = (1 * scaleY) - offsetY; - - // get the tilingSprites current alpha and tint and combining them into a single color - var tint = tilingSprite.tint; - var color = (tint >> 16) + (tint & 0xff00) + ((tint & 0xff) << 16) + (tilingSprite.alpha * 255 << 24); - - var positions = this.positions; - var colors = this.colors; - - var width = tilingSprite.width; - var height = tilingSprite.height; - - // TODO trim?? - var aX = tilingSprite.anchor.x; - var aY = tilingSprite.anchor.y; - var w0 = width * (1-aX); - var w1 = width * -aX; - - var h0 = height * (1-aY); - var h1 = height * -aY; - - var index = this.currentBatchSize * 4 * this.vertSize; - - var resolution = texture.baseTexture.resolution; - - var worldTransform = tilingSprite.worldTransform; - - var a = worldTransform.a / resolution;//[0]; - var b = worldTransform.b / resolution;//[3]; - var c = worldTransform.c / resolution;//[1]; - var d = worldTransform.d / resolution;//[4]; - var tx = worldTransform.tx;//[2]; - var ty = worldTransform.ty;//[5]; - - // xy - positions[index++] = a * w1 + c * h1 + tx; - positions[index++] = d * h1 + b * w1 + ty; - // uv - positions[index++] = uvs.x0; - positions[index++] = uvs.y0; - // color - colors[index++] = color; - - // xy - positions[index++] = (a * w0 + c * h1 + tx); - positions[index++] = d * h1 + b * w0 + ty; - // uv - positions[index++] = uvs.x1; - positions[index++] = uvs.y1; - // color - colors[index++] = color; - - // xy - positions[index++] = a * w0 + c * h0 + tx; - positions[index++] = d * h0 + b * w0 + ty; - // uv - positions[index++] = uvs.x2; - positions[index++] = uvs.y2; - // color - colors[index++] = color; - - // xy - positions[index++] = a * w1 + c * h0 + tx; - positions[index++] = d * h0 + b * w1 + ty; - // uv - positions[index++] = uvs.x3; - positions[index++] = uvs.y3; - // color - colors[index++] = color; - - // increment the batchsize - this.sprites[this.currentBatchSize++] = tilingSprite; -}; - -/** -* Renders the content and empties the current batch. -* -* @method flush -*/ -PIXI.WebGLSpriteBatch.prototype.flush = function() -{ - // If the batch is length 0 then return as there is nothing to draw - if (this.currentBatchSize===0)return; - - var gl = this.gl; - var shader; - - if(this.dirty) - { - this.dirty = false; - // bind the main texture - gl.activeTexture(gl.TEXTURE0); - - // bind the buffers - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - shader = this.defaultShader.shaders[gl.id]; - - // this is the same for each shader? - var stride = this.vertSize * 4; - gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, stride, 0); - gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, stride, 2 * 4); - - // color attributes will be interpreted as unsigned bytes and normalized - gl.vertexAttribPointer(shader.colorAttribute, 4, gl.UNSIGNED_BYTE, true, stride, 4 * 4); - } - - // upload the verts to the buffer - if(this.currentBatchSize > ( this.size * 0.5 ) ) - { - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices); - } - else - { - var view = this.positions.subarray(0, this.currentBatchSize * 4 * this.vertSize); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); - } - - var nextTexture, nextBlendMode, nextShader; - var batchSize = 0; - var start = 0; - - var currentBaseTexture = null; - var currentBlendMode = this.renderSession.blendModeManager.currentBlendMode; - var currentShader = null; - - var blendSwap = false; - var shaderSwap = false; - var sprite; - - for (var i = 0, j = this.currentBatchSize; i < j; i++) { - - sprite = this.sprites[i]; - - nextTexture = sprite.texture.baseTexture; - nextBlendMode = sprite.blendMode; - nextShader = sprite.shader || this.defaultShader; - - blendSwap = currentBlendMode !== nextBlendMode; - shaderSwap = currentShader !== nextShader; // should I use _UIDS??? - - if(currentBaseTexture !== nextTexture || blendSwap || shaderSwap) - { - this.renderBatch(currentBaseTexture, batchSize, start); - - start = i; - batchSize = 0; - currentBaseTexture = nextTexture; - - if( blendSwap ) - { - currentBlendMode = nextBlendMode; - this.renderSession.blendModeManager.setBlendMode( currentBlendMode ); - } - - if( shaderSwap ) - { - currentShader = nextShader; - - shader = currentShader.shaders[gl.id]; - - if(!shader) - { - shader = new PIXI.PixiShader(gl); - - shader.fragmentSrc =currentShader.fragmentSrc; - shader.uniforms =currentShader.uniforms; - shader.init(); - - currentShader.shaders[gl.id] = shader; - } - - // set shader function??? - this.renderSession.shaderManager.setShader(shader); - - if(shader.dirty)shader.syncUniforms(); - - // both thease only need to be set if they are changing.. - // set the projection - var projection = this.renderSession.projection; - gl.uniform2f(shader.projectionVector, projection.x, projection.y); - - // TODO - this is temprorary! - var offsetVector = this.renderSession.offset; - gl.uniform2f(shader.offsetVector, offsetVector.x, offsetVector.y); - - // set the correct flip.. - gl.uniform1f(shader.flipY, this.renderSession.flipY); - - - // set the pointers - } - } - - batchSize++; - } - - this.renderBatch(currentBaseTexture, batchSize, start); - - // then reset the batch! - this.currentBatchSize = 0; -}; - -/** -* @method renderBatch -* @param texture {Texture} -* @param size {Number} -* @param startIndex {Number} -*/ -PIXI.WebGLSpriteBatch.prototype.renderBatch = function(texture, size, startIndex) -{ - if(size === 0)return; - - var gl = this.gl; - - // check if a texture is dirty.. - if(texture._dirty[gl.id]) - { - this.renderSession.renderer.updateTexture(texture); - } - else - { - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); - } - - // now draw those suckas! - gl.drawElements(gl.TRIANGLES, size * 6, gl.UNSIGNED_SHORT, startIndex * 6 * 2); - - // increment the draw count - this.renderSession.drawCount++; -}; - -/** -* @method stop -*/ -PIXI.WebGLSpriteBatch.prototype.stop = function() -{ - this.flush(); - this.dirty = true; -}; - -/** -* @method start -*/ -PIXI.WebGLSpriteBatch.prototype.start = function() -{ - this.dirty = true; -}; - -/** -* Destroys the SpriteBatch. -* -* @method destroy -*/ -PIXI.WebGLSpriteBatch.prototype.destroy = function() -{ - this.vertices = null; - this.indices = null; - - this.gl.deleteBuffer( this.vertexBuffer ); - this.gl.deleteBuffer( this.indexBuffer ); - - this.currentBaseTexture = null; - - this.gl = null; -}; \ No newline at end of file diff --git a/src/pixi/textures/RenderTexture.js b/src/pixi/textures/RenderTexture.js deleted file mode 100644 index aad895d..0000000 --- a/src/pixi/textures/RenderTexture.js +++ /dev/null @@ -1,334 +0,0 @@ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A RenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a RenderTexture should be preloaded otherwise black rectangles will be drawn instead. - * - * A RenderTexture takes a snapshot of any Display Object given to its render method. The position and rotation of the given Display Objects is ignored. For example: - * - * var renderTexture = new PIXI.RenderTexture(800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * renderTexture.render(sprite); - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual position a DisplayObjectContainer should be used: - * - * var doc = new PIXI.DisplayObjectContainer(); - * doc.addChild(sprite); - * renderTexture.render(doc); // Renders to center of renderTexture - * - * @class RenderTexture - * @extends Texture - * @constructor - * @param width {Number} The width of the render texture - * @param height {Number} The height of the render texture - * @param renderer {CanvasRenderer|WebGLRenderer} The renderer used for this RenderTexture - * @param scaleMode {Number} See {{#crossLink "PIXI/scaleModes:property"}}PIXI.scaleModes{{/crossLink}} for possible values - * @param resolution {Number} The resolution of the texture being generated - */ -PIXI.RenderTexture = function(width, height, renderer, scaleMode, resolution) -{ - /** - * The with of the render texture - * - * @property width - * @type Number - */ - this.width = width || 100; - - /** - * The height of the render texture - * - * @property height - * @type Number - */ - this.height = height || 100; - - /** - * The Resolution of the texture. - * - * @property resolution - * @type Number - */ - this.resolution = resolution || 1; - - /** - * The framing rectangle of the render texture - * - * @property frame - * @type Rectangle - */ - this.frame = new PIXI.Rectangle(0, 0, this.width * this.resolution, this.height * this.resolution); - - /** - * This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering, - * irrespective of the actual frame size or placement (which can be influenced by trimmed texture atlases) - * - * @property crop - * @type Rectangle - */ - this.crop = new PIXI.Rectangle(0, 0, this.width * this.resolution, this.height * this.resolution); - - /** - * The base texture object that this texture uses - * - * @property baseTexture - * @type BaseTexture - */ - this.baseTexture = new PIXI.BaseTexture(); - this.baseTexture.width = this.width * this.resolution; - this.baseTexture.height = this.height * this.resolution; - this.baseTexture._glTextures = []; - this.baseTexture.resolution = this.resolution; - - this.baseTexture.scaleMode = scaleMode || PIXI.scaleModes.DEFAULT; - - this.baseTexture.hasLoaded = true; - - PIXI.Texture.call(this, - this.baseTexture, - new PIXI.Rectangle(0, 0, this.width, this.height) - ); - - /** - * The renderer this RenderTexture uses. A RenderTexture can only belong to one renderer at the moment if its webGL. - * - * @property renderer - * @type CanvasRenderer|WebGLRenderer - */ - this.renderer = renderer || PIXI.defaultRenderer; - - if(this.renderer.type === PIXI.WEBGL_RENDERER) - { - var gl = this.renderer.gl; - this.baseTexture._dirty[gl.id] = false; - - this.textureBuffer = new PIXI.FilterTexture(gl, this.width * this.resolution, this.height * this.resolution, this.baseTexture.scaleMode); - this.baseTexture._glTextures[gl.id] = this.textureBuffer.texture; - - this.render = this.renderWebGL; - this.projection = new PIXI.Point(this.width*0.5, -this.height*0.5); - } - else - { - this.render = this.renderCanvas; - this.textureBuffer = new PIXI.CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.baseTexture.source = this.textureBuffer.canvas; - } - - /** - * @property valid - * @type Boolean - */ - this.valid = true; - - this._updateUvs(); -}; - -PIXI.RenderTexture.prototype = Object.create(PIXI.Texture.prototype); -PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; - -/** - * Resizes the RenderTexture. - * - * @method resize - * @param width {Number} The width to resize to. - * @param height {Number} The height to resize to. - * @param updateBase {Boolean} Should the baseTexture.width and height values be resized as well? - */ -PIXI.RenderTexture.prototype.resize = function(width, height, updateBase) -{ - if (width === this.width && height === this.height)return; - - this.valid = (width > 0 && height > 0); - - this.width = this.frame.width = this.crop.width = width; - this.height = this.frame.height = this.crop.height = height; - - if (updateBase) - { - this.baseTexture.width = this.width; - this.baseTexture.height = this.height; - } - - if (this.renderer.type === PIXI.WEBGL_RENDERER) - { - this.projection.x = this.width / 2; - this.projection.y = -this.height / 2; - } - - if(!this.valid)return; - - this.textureBuffer.resize(this.width * this.resolution, this.height * this.resolution); -}; - -/** - * Clears the RenderTexture. - * - * @method clear - */ -PIXI.RenderTexture.prototype.clear = function() -{ - if(!this.valid)return; - - if (this.renderer.type === PIXI.WEBGL_RENDERER) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(); -}; - -/** - * This function will draw the display object to the texture. - * - * @method renderWebGL - * @param displayObject {DisplayObject} The display object to render this texture on - * @param [matrix] {Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {Boolean} If true the texture will be cleared before the displayObject is drawn - * @private - */ -PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, matrix, clear) -{ - if(!this.valid)return; - //TOOD replace position with matrix.. - - //Lets create a nice matrix to apply to our display object. Frame buffers come in upside down so we need to flip the matrix - var wt = displayObject.worldTransform; - wt.identity(); - if(matrix)wt.append(matrix); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - - for(var i=0,j=children.length; i