From 0cdb1503578e66f430d484f486bf29faae5d2108 Mon Sep 17 00:00:00 2001 From: Felipe Alfonso Date: Tue, 21 Mar 2017 17:08:43 -0300 Subject: [PATCH] Text rendering via canvas/texture upload --- .../graphics/GraphicsWebGLRenderer.js | 12 +-- v3/src/gameobjects/text/static/Text.js | 43 ++++++++++ .../text/static/TextWebGLRenderer.js | 3 +- .../webgl/batches/sprite/SpriteBatch.js | 85 +++++++++++++++++++ 4 files changed, 135 insertions(+), 8 deletions(-) diff --git a/v3/src/gameobjects/graphics/GraphicsWebGLRenderer.js b/v3/src/gameobjects/graphics/GraphicsWebGLRenderer.js index 0acc01a40..7192aebf5 100644 --- a/v3/src/gameobjects/graphics/GraphicsWebGLRenderer.js +++ b/v3/src/gameobjects/graphics/GraphicsWebGLRenderer.js @@ -119,12 +119,12 @@ var GraphicsWebGLRenderer = function (renderer, src, interpolationPercentage, ca if (iteration === 0) { - lastPath = new Path(tx, ty, lineWidth); + lastPath = new Path(tx, ty, lineWidth, lineColor, lineAlpha); pathArray.push(lastPath); } else { - lastPath.points.push(new Point(tx, ty, lineWidth)); + lastPath.points.push(new Point(tx, ty, lineWidth, lineColor, lineAlpha)); } iteration += iterStep; @@ -155,7 +155,7 @@ var GraphicsWebGLRenderer = function (renderer, src, interpolationPercentage, ca var firstPoint = lastPath.points[0]; var lastPoint = lastPath.points[lastPath.points.length - 1]; lastPath.points.push(firstPoint); - lastPath = new Path(lastPoint.x, lastPoint.y, lineWidth); + lastPath = new Path(lastPoint.x, lastPoint.y, lastPoint.width, lastPoint.rgb, lastPoint.alpha); pathArray.push(lastPath); } break; @@ -261,18 +261,18 @@ var GraphicsWebGLRenderer = function (renderer, src, interpolationPercentage, ca case Commands.LINE_TO: if (lastPath !== null) { - lastPath.points.push(new Point(commandBuffer[cmdIndex + 1], commandBuffer[cmdIndex + 2], lineWidth)); + lastPath.points.push(new Point(commandBuffer[cmdIndex + 1], commandBuffer[cmdIndex + 2], lineWidth, lineColor, lineAlpha)); } else { - lastPath = new Path(commandBuffer[cmdIndex + 1], commandBuffer[cmdIndex + 2], lineWidth); + lastPath = new Path(commandBuffer[cmdIndex + 1], commandBuffer[cmdIndex + 2], lineWidth, lineColor, lineAlpha); pathArray.push(lastPath); } cmdIndex += 2; break; case Commands.MOVE_TO: - lastPath = new Path(commandBuffer[cmdIndex + 1], commandBuffer[cmdIndex + 2], lineWidth); + lastPath = new Path(commandBuffer[cmdIndex + 1], commandBuffer[cmdIndex + 2], lineWidth, lineColor, lineAlpha); pathArray.push(lastPath); cmdIndex += 2; break; diff --git a/v3/src/gameobjects/text/static/Text.js b/v3/src/gameobjects/text/static/Text.js index b21d4e806..047578a46 100644 --- a/v3/src/gameobjects/text/static/Text.js +++ b/v3/src/gameobjects/text/static/Text.js @@ -65,6 +65,10 @@ var Text = new Class({ this.width = 1; this.height = 1; + this.gpuBuffer = null; + this.prevWidth = this.canvas.width; + this.prevHeight = this.canvas.height; + if (text !== '') { this.updateText(); @@ -254,7 +258,46 @@ var Text = new Class({ } } + if (this.state.game.config.renderType === Phaser.WEBGL) + { + this.uploadToGPU(); + } + return this; + }, + + uploadToGPU: function () + { + var gl = this.state.game.renderer.gl; + var currentTexture2D = this.state.game.renderer.currentTexture2D; + var canvas = this.canvas; + + if (this.gpuBuffer === null) + { + this.gpuBuffer = gl.createTexture(); + } + + if (this.prevWidth < canvas.width || this.prevHeight < canvas.height) + { + /* New canvas is too big. We need to reallocate the texture */ + gl.bindTexture(gl.TEXTURE_2D, this.gpuBuffer); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + 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); + this.prevWidth = canvas.width; + this.prevHeight = canvas.height; + } + else + { + /* if the canvas is smaller we just update the resource */ + gl.bindTexture(gl.TEXTURE_2D, this.gpuBuffer); + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvas); + } + + /* we must rebind old texture */ + gl.bindTexture(gl.TEXTURE_2D, currentTexture2D); } }); diff --git a/v3/src/gameobjects/text/static/TextWebGLRenderer.js b/v3/src/gameobjects/text/static/TextWebGLRenderer.js index f3ca9befe..d5aa20022 100644 --- a/v3/src/gameobjects/text/static/TextWebGLRenderer.js +++ b/v3/src/gameobjects/text/static/TextWebGLRenderer.js @@ -5,8 +5,7 @@ var TextWebGLRenderer = function (renderer, src, interpolationPercentage, camera return; } - var cameraScrollX = camera.scrollX; - var cameraScrollY = camera.scrollY; + renderer.spriteBatch.addSpriteTexture(src, camera, src.gpuBuffer, src.prevWidth, src.prevHeight); }; module.exports = TextWebGLRenderer; diff --git a/v3/src/renderer/webgl/batches/sprite/SpriteBatch.js b/v3/src/renderer/webgl/batches/sprite/SpriteBatch.js index e07b13640..ff7ab4940 100644 --- a/v3/src/renderer/webgl/batches/sprite/SpriteBatch.js +++ b/v3/src/renderer/webgl/batches/sprite/SpriteBatch.js @@ -179,6 +179,91 @@ SpriteBatch.prototype = { } }, + addSpriteTexture: function (src, camera, texture, textureWidth, textureHeight) + { + var tempMatrix = this.tempMatrix; + var alpha = 16777216; + var vertexDataBuffer = this.vertexDataBuffer; + var vertexBufferF32 = vertexDataBuffer.floatView; + var vertexBufferU32 = vertexDataBuffer.uintView; + var vertexOffset = 0; + var width = textureWidth * (src.flipX ? -1 : 1); + var height = textureHeight * (src.flipY ? -1 : 1); + var translateX = src.x - camera.scrollX; + var translateY = src.y - camera.scrollY; + var scaleX = src.scaleX; + var scaleY = src.scaleY; + var rotation = -src.rotation; + var tempMatrixMatrix = tempMatrix.matrix; + var x = -src.displayOriginX + ((textureWidth) * (src.flipX ? 1 : 0.0)); + var y = -src.displayOriginY + ((textureHeight) * (src.flipY ? 1 : 0.0)); + var xw = x + width; + var yh = y + height; + var cameraMatrix = camera.matrix.matrix; + var mva, mvb, mvc, mvd, mve, mvf, tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3; + var sra, srb, src, srd, sre, srf, cma, cmb, cmc, cmd, cme, cmf; + + tempMatrix.applyITRS(translateX, translateY, rotation, scaleX, scaleY); + + sra = tempMatrixMatrix[0]; + srb = tempMatrixMatrix[1]; + src = tempMatrixMatrix[2]; + srd = tempMatrixMatrix[3]; + sre = tempMatrixMatrix[4]; + srf = tempMatrixMatrix[5]; + + cma = cameraMatrix[0]; + cmb = cameraMatrix[1]; + cmc = cameraMatrix[2]; + cmd = cameraMatrix[3]; + cme = cameraMatrix[4]; + cmf = cameraMatrix[5]; + + mva = sra * cma + srb * cmc; + mvb = sra * cmb + srb * cmd; + mvc = src * cma + srd * cmc; + mvd = src * cmb + srd * cmd; + mve = sre * cma + srf * cmc + cme; + mvf = sre * cmb + srf * cmd + cmf; + + tx0 = x * mva + y * mvc + mve; + ty0 = x * mvb + y * mvd + mvf; + tx1 = x * mva + yh * mvc + mve; + ty1 = x * mvb + yh * mvd + mvf; + tx2 = xw * mva + yh * mvc + mve; + ty2 = xw * mvb + yh * mvd + mvf; + tx3 = xw * mva + y * mvc + mve; + ty3 = xw * mvb + y * mvd + mvf; + + this.manager.setBatch(this, texture, camera); + vertexOffset = vertexDataBuffer.allocate(20); + this.elementCount += 6; + + vertexBufferF32[vertexOffset++] = tx0; + vertexBufferF32[vertexOffset++] = ty0; + vertexBufferF32[vertexOffset++] = 0; + vertexBufferF32[vertexOffset++] = 0; + vertexBufferU32[vertexOffset++] = 0xFFFFFF; //vertexColor.topLeft; + + vertexBufferF32[vertexOffset++] = tx1; + vertexBufferF32[vertexOffset++] = ty1; + vertexBufferF32[vertexOffset++] = 0; + vertexBufferF32[vertexOffset++] = 1; + vertexBufferU32[vertexOffset++] = 0xFFFFFF; //vertexColor.bottomLeft; + + vertexBufferF32[vertexOffset++] = tx2; + vertexBufferF32[vertexOffset++] = ty2; + vertexBufferF32[vertexOffset++] = 1; + vertexBufferF32[vertexOffset++] = 1; + vertexBufferU32[vertexOffset++] = 0xFFFFFF; //vertexColor.bottomRight; + + vertexBufferF32[vertexOffset++] = tx3; + vertexBufferF32[vertexOffset++] = ty3; + vertexBufferF32[vertexOffset++] = 1; + vertexBufferF32[vertexOffset++] = 0; + vertexBufferU32[vertexOffset++] = 0xFFFFFF; //vertexColor.topRight; + }, + addSprite: function (src, camera) { var tempMatrix = this.tempMatrix;