diff --git a/src/gameobjects/blitter/BlitterWebGLRenderer.js b/src/gameobjects/blitter/BlitterWebGLRenderer.js index 0b2dc1529..7df789fd0 100644 --- a/src/gameobjects/blitter/BlitterWebGLRenderer.js +++ b/src/gameobjects/blitter/BlitterWebGLRenderer.js @@ -7,7 +7,7 @@ var BlitterWebGLRenderer = function (renderer, gameObject, interpolationPercenta return; } - renderer.pipelines.BlitterPipeline.drawBlitter(gameObject, camera); + renderer.pipelines.TextureTintPipeline.drawBlitter(gameObject, camera); }; module.exports = BlitterWebGLRenderer; diff --git a/src/renderer/webgl/Utils.js b/src/renderer/webgl/Utils.js index b97a684b8..6faeae3f5 100644 --- a/src/renderer/webgl/Utils.js +++ b/src/renderer/webgl/Utils.js @@ -18,6 +18,27 @@ module.exports = { var ua = ((a * 255.0)|0) & 0xFF; return ((ua << 24) | (ub << 16) | (ug << 8) | ur) >>> 0; + }, + + getComponentCount: function (attributes) + { + var count = 0; + + for (var index = 0; index < attributes.length; ++index) + { + var element = attributes[index]; + + if (element.type === WebGLRenderingContext.FLOAT) + { + count += element.size; + } + else + { + count += 1; // We'll force any other type to be 32 bit. for now + } + } + + return count; } }; \ No newline at end of file diff --git a/src/renderer/webgl/WebGLPipeline.js b/src/renderer/webgl/WebGLPipeline.js index 9f5e9069b..ffd8c7bc6 100644 --- a/src/renderer/webgl/WebGLPipeline.js +++ b/src/renderer/webgl/WebGLPipeline.js @@ -1,4 +1,5 @@ var Class = require('../../utils/Class'); +var Utils = require('./Utils'); var WebGLPipeline = new Class({ @@ -18,12 +19,14 @@ var WebGLPipeline = new Class({ this.renderer = config.renderer; this.vertexData = new ArrayBuffer(config.vertexCapacity * config.vertexSize); this.vertexBuffer = this.renderer.createVertexBuffer(this.vertexData.byteLength, this.gl.STREAM_DRAW); - this.program = this.renderer.createProgram(config.shader.vert, config.shader.frag); + this.program = this.renderer.createProgram(config.vertShader, config.fragShader); this.attributes = config.attributes; this.vertexSize = config.vertexSize; this.topology = config.topology; this.currentProgram = this.program; this.bytes = new Uint8Array(this.vertexData); + // This will store the amount of components of 32 bit length + this.vertexComponentCount = Utils.getComponentCount(config.attributes.length); }, shouldFlush: function () diff --git a/src/renderer/webgl/WebGLRenderer.js b/src/renderer/webgl/WebGLRenderer.js index 416028241..a13dcd383 100644 --- a/src/renderer/webgl/WebGLRenderer.js +++ b/src/renderer/webgl/WebGLRenderer.js @@ -4,7 +4,8 @@ var WebGLSnapshot = require('../snapshot/WebGLSnapshot'); var IsSizePowerOfTwo = require('../../math/pow2/IsSizePowerOfTwo'); // Default Pipelines -var BlitterPipeline = require('./pipelines/BlitterPipeline'); +var TextureTintPipeline = require('./pipelines/TextureTintPipeline'); +var FlatTintPipeline = require('./pipelines/FlatTintPipeline'); var WebGLRenderer = new Class({ @@ -112,7 +113,8 @@ var WebGLRenderer = new Class({ // Clear previous pipelines and reload default ones this.pipelines = {}; - this.addPipeline('BlitterPipeline', new BlitterPipeline(this.game, gl, this)); + this.addPipeline('TextureTintPipeline', new TextureTintPipeline(this.game, gl, this)); + this.addPipeline('FlatTintPipeline', new FlatTintPipeline(this.game, gl, this)); this.setBlendMode(CONST.BlendModes.NORMAL); this.resize(this.width, this.height, this.game.config.resolution); @@ -486,6 +488,12 @@ var WebGLRenderer = new Class({ { if (this.contextLost) return; + var gl = this.gl; + var color = this.game.config.backgroundColor; + + // Bind custom framebuffer here + gl.clearColor(color.redGL, color.greenGL, color.blueGL, color.alphaGL); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); }, render: function (scene, children, interpolationPercentage, camera) @@ -495,13 +503,9 @@ var WebGLRenderer = new Class({ var gl = this.gl; var list = children.list; var childCount = list.length; - var color = this.game.config.backgroundColor; var scissorEnabled = (camera.x !== 0 || camera.y !== 0 || camera.width !== gl.canvas.width || camera.height !== gl.canvas.height); var pipeline = null; - gl.clearColor(color.redGL, color.greenGL, color.blueGL, color.alphaGL); - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); - this.currentScissorState.enabled = scissorEnabled; if (scissorEnabled) @@ -540,7 +544,7 @@ var WebGLRenderer = new Class({ { child.mask.postRenderWebGL(this, child); } - + pipeline = this.currentPipeline; if (pipeline && pipeline.shouldFlush()) @@ -559,6 +563,8 @@ var WebGLRenderer = new Class({ { if (this.contextLost) return; + // Unbind custom framebuffer here + if (this.snapshotState.callback) { this.snapshotState.callback(WebGLSnapshot(this.canvas, this.snapshotState.type, this.snapshotState.encoder)); diff --git a/src/renderer/webgl/pipelines/FlatTintPipeline.js b/src/renderer/webgl/pipelines/FlatTintPipeline.js new file mode 100644 index 000000000..fd47893f4 --- /dev/null +++ b/src/renderer/webgl/pipelines/FlatTintPipeline.js @@ -0,0 +1,242 @@ +var Class = require('../../../utils/Class'); +var WebGLPipeline = require('../WebGLPipeline'); +var Utils = require('../Utils'); +var Earcut = require('../../../geom/polygon/Earcut'); +var ShaderSource = require('../shaders/FlatTintShader'); + +var FlatTintPipeline = new Class({ + + Extends: WebGLPipeline, + + initialize: + + function FlatTintPipeline(game, gl, renderer) + { + WebGLPipeline.call(this, { + name: 'FlatTintPipeline', + game: game, + gl: gl, + renderer: renderer, + topology: gl.TRIANGLES, + vertShader: ShaderSource.vert, + fragShader: ShaderSource.frag, + vertexCapacity: 12000, + + vertexSize: + Float32Array.BYTES_PER_ELEMENT * 2 + + Uint8Array.BYTES_PER_ELEMENT * 4, + + attributes: [ + { + name: 'inPosition', + size: 2, + type: gl.FLOAT, + normalized: false, + offset: 0 + }, + { + name: 'inTint', + size: 4, + type: gl.UNSIGNED_BYTE, + normalized: true, + offset: Float32Array.BYTES_PER_ELEMENT * 2 + } + ] + }); + + this.orthoViewMatrix = new Float32Array([ + +2.0 / this.width, + +0.0, + +0.0, + +0.0, + + +0.0, + -2.0 / this.height, + +0.0, + +0.0, + + +0.0, + +0.0, + +1.0, + +1.0, + + -1.0, + +1.0, + +0.0, + +0.0 + ]); + + this.vertexViewF32 = new Float32Array(this.vertexData); + this.vertexViewU32 = new Uint32Array(this.vertexData); + this.tempTriangle = [ + {x: 0, y: 0, width: 0, rgb: 0xFFFFFF, alpha: 1.0}, + {x: 0, y: 0, width: 0, rgb: 0xFFFFFF, alpha: 1.0}, + {x: 0, y: 0, width: 0, rgb: 0xFFFFFF, alpha: 1.0}, + {x: 0, y: 0, width: 0, rgb: 0xFFFFFF, alpha: 1.0} + ]; + }, + + resize: function (width, height, resolution) + { + WebGLPipeline.prototype.resize.call(this, width, height, resolution); + + var orthoViewMatrix = this.orthoViewMatrix; + orthoViewMatrix[0] = +2.0 / this.width; + orthoViewMatrix[5] = -2.0 / this.height; + + this.renderer.setMatrix4(this.currentProgram, 'uOrthoMatrix', false, orthoViewMatrix); + + return this; + }, + + batchFillRect: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, x, y, width, height, fillColor, fillAlpha, a1, b1, c1, d1, e1, f1, currentMatrix) + { + if (this.vertexCount + 6 > this.vertexCapacity) + { + this.flush(); + } + + var vertexBufferF32 = this.vertexViewF32; + var vertexBufferU32 = this.vertexViewU32; + var vertexOffset = this.vertexCount * this.vertexComponentCount; + var xw = x + width; + var yh = y + height; + var a0 = currentMatrix.matrix[0]; + var b0 = currentMatrix.matrix[1]; + var c0 = currentMatrix.matrix[2]; + var d0 = currentMatrix.matrix[3]; + var e0 = currentMatrix.matrix[4]; + var f0 = currentMatrix.matrix[5]; + var a = a1 * a0 + b1 * c0; + var b = a1 * b0 + b1 * d0; + var c = c1 * a0 + d1 * c0; + var d = c1 * b0 + d1 * d0; + var e = e1 * a0 + f1 * c0 + e0; + var f = e1 * b0 + f1 * d0 + f0; + var tx0 = x * a + y * c + e; + var ty0 = x * b + y * d + f; + var tx1 = x * a + yh * c + e; + var ty1 = x * b + yh * d + f; + var tx2 = xw * a + yh * c + e; + var ty2 = xw * b + yh * d + f; + var tx3 = xw * a + y * c + e; + var ty3 = xw * b + y * d + f; + var tint = Utils.getTintAppendFloatAlpha(fillColor, fillAlpha); + + vertexBufferF32[vertexOffset + 0] = tx0; + vertexBufferF32[vertexOffset + 1] = ty0; + vertexBufferU32[vertexOffset + 2] = tint; + vertexBufferF32[vertexOffset + 3] = tx1; + vertexBufferF32[vertexOffset + 4] = ty1; + vertexBufferU32[vertexOffset + 5] = tint; + vertexBufferF32[vertexOffset + 6] = tx2; + vertexBufferF32[vertexOffset + 7] = ty2; + vertexBufferU32[vertexOffset + 8] = tint; + vertexBufferF32[vertexOffset + 9] = tx0; + vertexBufferF32[vertexOffset + 10] = ty0; + vertexBufferU32[vertexOffset + 11] = tint; + vertexBufferF32[vertexOffset + 12] = tx2; + vertexBufferF32[vertexOffset + 13] = ty2; + vertexBufferU32[vertexOffset + 14] = tint; + vertexBufferF32[vertexOffset + 15] = tx3; + vertexBufferF32[vertexOffset + 16] = ty3; + vertexBufferU32[vertexOffset + 17] = tint; + + this.vertexCount += 6; + }, + + batchFillTriangle: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, x0, y0, x1, y1, x2, y2, fillColor, fillAlpha, a1, b1, c1, d1, e1, f1, currentMatrix) + { + if (this.vertexCount + 3 > this.vertexCapacity) + { + this.flush(); + } + + var vertexBufferF32 = this.vertexViewF32; + var vertexBufferU32 = this.vertexViewU32; + var vertexOffset = this.vertexCount * this.vertexComponentCount; + var a0 = currentMatrix.matrix[0]; + var b0 = currentMatrix.matrix[1]; + var c0 = currentMatrix.matrix[2]; + var d0 = currentMatrix.matrix[3]; + var e0 = currentMatrix.matrix[4]; + var f0 = currentMatrix.matrix[5]; + var a = a1 * a0 + b1 * c0; + var b = a1 * b0 + b1 * d0; + var c = c1 * a0 + d1 * c0; + var d = c1 * b0 + d1 * d0; + var e = e1 * a0 + f1 * c0 + e0; + var f = e1 * b0 + f1 * d0 + f0; + var tx0 = x0 * a + y0 * c + e; + var ty0 = x0 * b + y0 * d + f; + var tx1 = x1 * a + y1 * c + e; + var ty1 = x1 * b + y1 * d + f; + var tx2 = x2 * a + y2 * c + e; + var ty2 = x2 * b + y2 * d + f; + var tint = Utils.getTintAppendFloatAlpha(fillColor, fillAlpha); + + vertexBufferF32[vertexOffset + 0] = tx0; + vertexBufferF32[vertexOffset + 1] = ty0; + vertexBufferU32[vertexOffset + 2] = tint; + vertexBufferF32[vertexOffset + 3] = tx1; + vertexBufferF32[vertexOffset + 4] = ty1; + vertexBufferU32[vertexOffset + 5] = tint; + vertexBufferF32[vertexOffset + 6] = tx2; + vertexBufferF32[vertexOffset + 7] = ty2; + vertexBufferU32[vertexOffset + 8] = tint; + + this.vertexCount += 3; + }, + + batchStrokeTriangle: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, x0, y0, x1, y1, x2, y2, lineWidth, lineColor, lineAlpha, a, b, c, d, e, f, currentMatrix) + { + var tempTriangle = this.tempTriangle; + + tempTriangle[0].x = x0; + tempTriangle[0].y = y0; + tempTriangle[0].width = lineWidth; + tempTriangle[0].rgb = lineColor; + tempTriangle[0].alpha = lineAlpha; + tempTriangle[1].x = x1; + tempTriangle[1].y = y1; + tempTriangle[1].width = lineWidth; + tempTriangle[1].rgb = lineColor; + tempTriangle[1].alpha = lineAlpha; + tempTriangle[2].x = x2; + tempTriangle[2].y = y2; + tempTriangle[2].width = lineWidth; + tempTriangle[2].rgb = lineColor; + tempTriangle[2].alpha = lineAlpha; + tempTriangle[3].x = x0; + tempTriangle[3].y = y0; + tempTriangle[3].width = lineWidth; + tempTriangle[3].rgb = lineColor; + tempTriangle[3].alpha = lineAlpha; + + this.addStrokePath( + srcX, srcY, srcScaleX, srcScaleY, srcRotation, + tempTriangle, lineWidth, lineColor, lineAlpha, + a, b, c, d, e, f, + false, + currentMatrix + ); + }, + + batchFillPath: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, path, fillColor, fillAlpha, a1, b1, c1, d1, e1, f1, currentMatrix) + { + + }, + + batchStrokePath: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, path, lineWidth, lineColor, lineAlpha, a, b, c, d, e, f, isLastPath, currentMatrix) + { + + }, + + batchLine: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, ax, ay, bx, by, aLineWidth, bLineWidth, aLineColor, bLineColor, lineAlpha, a1, b1, c1, d1, e1, f1, currentMatrix) + { + + } + +}); + +module.exports = FlatTintPipeline; diff --git a/src/renderer/webgl/pipelines/BlitterPipeline.js b/src/renderer/webgl/pipelines/TextureTintPipeline.js similarity index 95% rename from src/renderer/webgl/pipelines/BlitterPipeline.js rename to src/renderer/webgl/pipelines/TextureTintPipeline.js index 3397ae248..b97cd6020 100644 --- a/src/renderer/webgl/pipelines/BlitterPipeline.js +++ b/src/renderer/webgl/pipelines/TextureTintPipeline.js @@ -3,21 +3,22 @@ var ShaderSource = require('../shaders/TextureTintShader'); var WebGLPipeline = require('../WebGLPipeline'); var Utils = require('../Utils'); -var BlitterPipeline = new Class({ +var TextureTintPipeline = new Class({ Extends: WebGLPipeline, initialize: - function BlitterPipeline(game, gl, renderer) + function TextureTintPipeline(game, gl, renderer) { WebGLPipeline.call(this, { - name: 'BlitterPipeline', + name: 'TextureTintPipeline', game: game, gl: gl, renderer: renderer, topology: gl.TRIANGLES, - shader: ShaderSource, + vertShader: ShaderSource.vert, + fragShader: ShaderSource.frag, vertexCapacity: 12000, vertexSize: @@ -91,7 +92,7 @@ var BlitterPipeline = new Class({ drawBlitter: function (blitter, camera) { - this.renderer.setPipeline('BlitterPipeline', blitter.shader); + this.renderer.setPipeline('TextureTintPipeline', blitter.shader); var vertexViewF32 = this.vertexViewF32; var vertexViewU32 = this.vertexViewU32; @@ -192,4 +193,4 @@ var BlitterPipeline = new Class({ } }); -module.exports = BlitterPipeline; +module.exports = TextureTintPipeline; diff --git a/src/renderer/webgl/shaders/FlatTint.frag b/src/renderer/webgl/shaders/FlatTint.frag new file mode 100644 index 000000000..493e0d063 --- /dev/null +++ b/src/renderer/webgl/shaders/FlatTint.frag @@ -0,0 +1,9 @@ +#define SHADER_NAME PHASER_FLAT_TINT_FS + +precision mediump float; + +varying vec4 outTint; + +void main() { + gl_FragColor = vec4(outTint.bgr * outTint.a, outTint.a); +} diff --git a/src/renderer/webgl/shaders/FlatTint.vert b/src/renderer/webgl/shaders/FlatTint.vert new file mode 100644 index 000000000..9322d4840 --- /dev/null +++ b/src/renderer/webgl/shaders/FlatTint.vert @@ -0,0 +1,15 @@ +#define SHADER_NAME PHASER_FLAT_TINT_VS + +precision mediump float; + +uniform mat4 uOrthoMatrix; + +attribute vec2 inPosition; +attribute vec4 inTint; + +varying vec4 outTint; + +void main () { + gl_Position = uOrthoMatrix * vec4(inPosition, 1.0, 1.0); + outTint = inTint; +} diff --git a/src/renderer/webgl/shaders/FlatTintShader.js b/src/renderer/webgl/shaders/FlatTintShader.js new file mode 100644 index 000000000..d47c04a35 --- /dev/null +++ b/src/renderer/webgl/shaders/FlatTintShader.js @@ -0,0 +1,32 @@ +module.exports = { + vert: [ + '#define SHADER_NAME PHASER_FLAT_TINT_VS', + + 'precision mediump float;', + + 'uniform mat4 uOrthoMatrix;', + + 'attribute vec2 inPosition;', + 'attribute vec4 inTint;', + + 'varying vec4 outTint;', + + 'void main () {', + ' gl_Position = uOrthoMatrix * vec4(inPosition, 1.0, 1.0);', + ' outTint = inTint;', + '}' + + ].join('\n'), + frag: [ + '#define SHADER_NAME PHASER_FLAT_TINT_FS', + + 'precision mediump float;', + + 'varying vec4 outTint;', + + 'void main() {', + ' gl_FragColor = vec4(outTint.bgr * outTint.a, outTint.a);', + '}' + + ].join('\n') +};