Graphics WebGL Rendering

This commit is contained in:
Felipe Alfonso 2018-01-24 00:03:43 -03:00
parent ca465c8139
commit 5170784338
6 changed files with 644 additions and 418 deletions

View file

@ -745,9 +745,9 @@ var Graphics = new Class({
{ {
this.renderCanvas(sys.game.renderer, this, 0, Graphics.TargetCamera, ctx); this.renderCanvas(sys.game.renderer, this, 0, Graphics.TargetCamera, ctx);
if (this.gl && texture) if (sys.game.renderer.gl && texture)
{ {
sys.game.renderer.uploadCanvasToGPU(ctx.canvas, texture.source[0].glTexture, true); texture.source[0].glTexture = sys.game.renderer.canvasToTexture(ctx.canvas, texture.source[0].glTexture, true, 0);
} }
} }

View file

@ -1,373 +1,13 @@
var Commands = require('./Commands');
var GameObject = require('../GameObject'); var GameObject = require('../GameObject');
var TransformMatrix = require('../components/TransformMatrix');
var cos = Math.cos; var GraphicsWebGLRenderer = function (renderer, graphics, interpolationPercentage, camera, forceRenderTarget)
var sin = Math.sin;
var currentMatrix = new TransformMatrix();
var matrixStack = new Float32Array(6 * 1000);
var matrixStackLength = 0;
var pathArray = [];
var tempMatrix = new TransformMatrix();
var Point = function (x, y, width, rgb, alpha)
{ {
this.x = x; if (GameObject.RENDER_MASK !== graphics.renderFlags || (graphics.cameraFilter > 0 && (graphics.cameraFilter & camera._id)))
this.y = y;
this.width = width;
this.rgb = rgb;
this.alpha = alpha;
};
var Path = function (x, y, width, rgb, alpha)
{
this.points = [];
this.pointsLength = 1;
this.points[0] = new Point(x, y, width, rgb, alpha);
};
var GraphicsWebGLRenderer = function (renderer, gameObject, interpolationPercentage, camera, forceRenderTarget)
{
if (GameObject.RENDER_MASK !== gameObject.renderFlags || (gameObject.cameraFilter > 0 && (gameObject.cameraFilter & camera._id)))
{ {
return; return;
} }
var renderTarget = forceRenderTarget || gameObject.renderTarget; renderer.pipelines.FlatTintPipeline.batchGraphics(this, camera);
var shapeBatch = renderer.shapeBatch;
var cameraScrollX = camera.scrollX * gameObject.scrollFactorX;
var cameraScrollY = camera.scrollY * gameObject.scrollFactorY;
var srcX = gameObject.x - cameraScrollX;
var srcY = gameObject.y - cameraScrollY;
var srcScaleX = gameObject.scaleX;
var srcScaleY = gameObject.scaleY;
var srcRotation = -gameObject.rotation;
var commandBuffer = gameObject.commandBuffer;
var lineAlpha = 1.0;
var fillAlpha = 1.0;
var lineColor = 0;
var fillColor = 0;
var lineWidth = 1.0;
var cameraMatrix = camera.matrix.matrix;
var lastPath = null;
var iteration = 0;
var iterStep = 0.01;
var tx = 0;
var ty = 0;
var ta = 0;
var x, y, radius, startAngle, endAngle, anticlockwise;
var path;
var tempMatrixMatrix = tempMatrix.matrix;
var sra, srb, src, srd, sre, srf, cma, cmb, cmc, cmd, cme, cmf;
var mva, mvb, mvc, mvd, mve, mvf;
tempMatrix.applyITRS(srcX, srcY, srcRotation, srcScaleX, srcScaleY);
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;
renderer.setRenderer(shapeBatch, null, renderTarget);
for (var cmdIndex = 0, cmdLength = commandBuffer.length; cmdIndex < cmdLength; ++cmdIndex)
{
cmd = commandBuffer[cmdIndex];
switch (cmd)
{
case Commands.ARC:
iteration = 0;
x = commandBuffer[cmdIndex + 1];
y = commandBuffer[cmdIndex + 2];
radius = commandBuffer[cmdIndex + 3];
startAngle = commandBuffer[cmdIndex + 4];
endAngle = commandBuffer[cmdIndex + 5];
anticlockwise = commandBuffer[cmdIndex + 6];
if (anticlockwise)
{
ta = endAngle;
endAngle = startAngle;
startAngle = -ta;
}
while (iteration < 1)
{
ta = (endAngle - startAngle) * iteration + startAngle;
tx = x + cos(ta) * radius;
ty = y + sin(ta) * radius;
if (iteration === 0)
{
lastPath = new Path(tx, ty, lineWidth, lineColor, lineAlpha);
pathArray.push(lastPath);
}
else
{
lastPath.points.push(new Point(tx, ty, lineWidth, lineColor, lineAlpha));
}
iteration += iterStep;
}
cmdIndex += 6;
break;
case Commands.LINE_STYLE:
lineWidth = commandBuffer[cmdIndex + 1];
lineColor = commandBuffer[cmdIndex + 2];
lineAlpha = commandBuffer[cmdIndex + 3];
cmdIndex += 3;
break;
case Commands.FILL_STYLE:
fillColor = commandBuffer[cmdIndex + 1];
fillAlpha = commandBuffer[cmdIndex + 2];
cmdIndex += 2;
break;
case Commands.BEGIN_PATH:
pathArray.length = 0;
break;
case Commands.CLOSE_PATH:
if (lastPath !== null && lastPath.points.length > 0)
{
var firstPoint = lastPath.points[0];
var lastPoint = lastPath.points[lastPath.points.length - 1];
lastPath.points.push(firstPoint);
lastPath = new Path(lastPoint.x, lastPoint.y, lastPoint.width, lastPoint.rgb, lastPoint.alpha);
pathArray.push(lastPath);
}
break;
case Commands.FILL_PATH:
for (var pathArrayIndex = 0, pathArrayLength = pathArray.length;
pathArrayIndex < pathArrayLength;
++pathArrayIndex)
{
shapeBatch.addFillPath(
/* Graphics Game Object Properties */
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
/* Rectangle properties */
pathArray[pathArrayIndex].points,
fillColor,
fillAlpha,
/* Transform */
mva, mvb, mvc, mvd, mve, mvf,
currentMatrix
);
}
break;
case Commands.STROKE_PATH:
for (var pathArrayIndex = 0, pathArrayLength = pathArray.length;
pathArrayIndex < pathArrayLength;
++pathArrayIndex)
{
path = pathArray[pathArrayIndex];
shapeBatch.addStrokePath(
/* Graphics Game Object Properties */
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
/* Rectangle properties */
path.points,
lineWidth,
lineColor,
lineAlpha,
/* Transform */
mva, mvb, mvc, mvd, mve, mvf,
path === this._lastPath,
currentMatrix
);
}
break;
case Commands.FILL_RECT:
shapeBatch.addFillRect(
/* Graphics Game Object Properties */
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
/* Rectangle properties */
commandBuffer[cmdIndex + 1],
commandBuffer[cmdIndex + 2],
commandBuffer[cmdIndex + 3],
commandBuffer[cmdIndex + 4],
fillColor,
fillAlpha,
/* Transform */
mva, mvb, mvc, mvd, mve, mvf,
currentMatrix
);
cmdIndex += 4;
break;
case Commands.FILL_TRIANGLE:
shapeBatch.addFillTriangle(
/* Graphics Game Object Properties */
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
/* Triangle properties */
commandBuffer[cmdIndex + 1],
commandBuffer[cmdIndex + 2],
commandBuffer[cmdIndex + 3],
commandBuffer[cmdIndex + 4],
commandBuffer[cmdIndex + 5],
commandBuffer[cmdIndex + 6],
fillColor,
fillAlpha,
/* Transform */
mva, mvb, mvc, mvd, mve, mvf,
currentMatrix
);
cmdIndex += 6;
break;
case Commands.STROKE_TRIANGLE:
shapeBatch.addStrokeTriangle(
/* Graphics Game Object Properties */
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
/* Triangle properties */
commandBuffer[cmdIndex + 1],
commandBuffer[cmdIndex + 2],
commandBuffer[cmdIndex + 3],
commandBuffer[cmdIndex + 4],
commandBuffer[cmdIndex + 5],
commandBuffer[cmdIndex + 6],
lineWidth,
lineColor,
lineAlpha,
/* Transform */
mva, mvb, mvc, mvd, mve, mvf,
currentMatrix
);
cmdIndex += 6;
break;
case Commands.LINE_TO:
if (lastPath !== null)
{
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, lineColor, lineAlpha);
pathArray.push(lastPath);
}
cmdIndex += 2;
break;
case Commands.MOVE_TO:
lastPath = new Path(commandBuffer[cmdIndex + 1], commandBuffer[cmdIndex + 2], lineWidth, lineColor, lineAlpha);
pathArray.push(lastPath);
cmdIndex += 2;
break;
case Commands.LINE_FX_TO:
if (lastPath !== null)
{
lastPath.points.push(new Point(
commandBuffer[cmdIndex + 1],
commandBuffer[cmdIndex + 2],
commandBuffer[cmdIndex + 3],
commandBuffer[cmdIndex + 4],
commandBuffer[cmdIndex + 5]
));
}
else
{
lastPath = new Path(
commandBuffer[cmdIndex + 1],
commandBuffer[cmdIndex + 2],
commandBuffer[cmdIndex + 3],
commandBuffer[cmdIndex + 4],
commandBuffer[cmdIndex + 5]
);
pathArray.push(lastPath);
}
cmdIndex += 5;
break;
case Commands.MOVE_FX_TO:
lastPath = new Path(
commandBuffer[cmdIndex + 1],
commandBuffer[cmdIndex + 2],
commandBuffer[cmdIndex + 3],
commandBuffer[cmdIndex + 4],
commandBuffer[cmdIndex + 5]
);
pathArray.push(lastPath);
cmdIndex += 5;
break;
case Commands.SAVE:
matrixStack[matrixStackLength + 0] = currentMatrix.matrix[0];
matrixStack[matrixStackLength + 1] = currentMatrix.matrix[1];
matrixStack[matrixStackLength + 2] = currentMatrix.matrix[2];
matrixStack[matrixStackLength + 3] = currentMatrix.matrix[3];
matrixStack[matrixStackLength + 4] = currentMatrix.matrix[4];
matrixStack[matrixStackLength + 5] = currentMatrix.matrix[5];
matrixStackLength += 6;
break;
case Commands.RESTORE:
matrixStackLength -= 6;
currentMatrix.matrix[0] = matrixStack[matrixStackLength + 0];
currentMatrix.matrix[1] = matrixStack[matrixStackLength + 1];
currentMatrix.matrix[2] = matrixStack[matrixStackLength + 2];
currentMatrix.matrix[3] = matrixStack[matrixStackLength + 3];
currentMatrix.matrix[4] = matrixStack[matrixStackLength + 4];
currentMatrix.matrix[5] = matrixStack[matrixStackLength + 5];
break;
case Commands.TRANSLATE:
currentMatrix.translate(
commandBuffer[cmdIndex + 1],
commandBuffer[cmdIndex + 2]
);
cmdIndex += 2;
break;
case Commands.SCALE:
currentMatrix.scale(
commandBuffer[cmdIndex + 1],
commandBuffer[cmdIndex + 2]
);
cmdIndex += 2;
break;
case Commands.ROTATE:
currentMatrix.rotate(
-commandBuffer[cmdIndex + 1]
);
cmdIndex += 1;
break;
default:
console.error('Phaser: Invalid Graphics Command ID ' + cmd);
break;
}
}
currentMatrix.loadIdentity();
pathArray.length = 0;
}; };
module.exports = GraphicsWebGLRenderer; module.exports = GraphicsWebGLRenderer;

View file

@ -16,7 +16,7 @@ var GameObjects = {
//Container: require('./container/Container'), //Container: require('./container/Container'),
//DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapText'), //DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapText'),
//DynamicTilemapLayer: require('./tilemap/dynamiclayer/DynamicTilemapLayer'), //DynamicTilemapLayer: require('./tilemap/dynamiclayer/DynamicTilemapLayer'),
//Graphics: require('./graphics/Graphics.js'), Graphics: require('./graphics/Graphics.js'),
//Group: require('./group/Group'), //Group: require('./group/Group'),
Image: require('./image/Image'), Image: require('./image/Image'),
//Particles: require('./particles/ParticleEmitterManager'), //Particles: require('./particles/ParticleEmitterManager'),
@ -37,7 +37,7 @@ var GameObjects = {
Blitter: require('./blitter/BlitterFactory'), Blitter: require('./blitter/BlitterFactory'),
//Container: require('./container/ContainerFactory'), //Container: require('./container/ContainerFactory'),
//DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapTextFactory'), //DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapTextFactory'),
//Graphics: require('./graphics/GraphicsFactory'), Graphics: require('./graphics/GraphicsFactory'),
//Group: require('./group/GroupFactory'), //Group: require('./group/GroupFactory'),
Image: require('./image/ImageFactory'), Image: require('./image/ImageFactory'),
//Particles: require('./particles/ParticleManagerFactory'), //Particles: require('./particles/ParticleManagerFactory'),
@ -55,7 +55,7 @@ var GameObjects = {
Blitter: require('./blitter/BlitterCreator'), Blitter: require('./blitter/BlitterCreator'),
//Container: require('./container/ContainerCreator'), //Container: require('./container/ContainerCreator'),
//DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapTextCreator'), //DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapTextCreator'),
//Graphics: require('./graphics/GraphicsCreator'), Graphics: require('./graphics/GraphicsCreator'),
//Group: require('./group/GroupCreator'), //Group: require('./group/GroupCreator'),
Image: require('./image/ImageCreator'), Image: require('./image/ImageCreator'),
//Particles: require('./particles/ParticleManagerCreator'), //Particles: require('./particles/ParticleManagerCreator'),
@ -77,12 +77,10 @@ if (WEBGL_RENDERER)
GameObjects.Mesh = require('./mesh/Mesh'); GameObjects.Mesh = require('./mesh/Mesh');
GameObjects.Quad = require('./quad/Quad'); GameObjects.Quad = require('./quad/Quad');
//GameObjects.Factories.EffectLayer = require('./effectlayer/EffectLayerFactory');
//GameObjects.Factories.LightLayer = require('./lightlayer/LightLayerFactory'); //GameObjects.Factories.LightLayer = require('./lightlayer/LightLayerFactory');
GameObjects.Factories.Mesh = require('./mesh/MeshFactory'); GameObjects.Factories.Mesh = require('./mesh/MeshFactory');
GameObjects.Factories.Quad = require('./quad/QuadFactory'); GameObjects.Factories.Quad = require('./quad/QuadFactory');
//GameObjects.Creators.EffectLayer = require('./effectlayer/EffectLayerCreator');
//GameObjects.Creators.LightLayer = require('./lightlayer/LightLayerCreator'); //GameObjects.Creators.LightLayer = require('./lightlayer/LightLayerCreator');
GameObjects.Creators.Mesh = require('./mesh/MeshCreator'); GameObjects.Creators.Mesh = require('./mesh/MeshCreator');
GameObjects.Creators.Quad = require('./quad/QuadCreator'); GameObjects.Creators.Quad = require('./quad/QuadCreator');

View file

@ -632,7 +632,7 @@ var WebGLRenderer = new Class({
} }
else else
{ {
this.setTexture2D(dstTexture); this.setTexture2D(dstTexture, 0);
if (!shouldReallocate) if (!shouldReallocate)
{ {
@ -645,7 +645,7 @@ var WebGLRenderer = new Class({
dstTexture.height = srcCanvas.height; dstTexture.height = srcCanvas.height;
} }
this.setTexture2D(null); this.setTexture2D(null, 0);
} }
return dstTexture; return dstTexture;

View file

@ -4,6 +4,28 @@ var Utils = require('../Utils');
var Earcut = require('../../../geom/polygon/Earcut'); var Earcut = require('../../../geom/polygon/Earcut');
var ShaderSourceVS = require('../shaders/FlatTint.vert'); var ShaderSourceVS = require('../shaders/FlatTint.vert');
var ShaderSourceFS = require('../shaders/FlatTint.frag'); var ShaderSourceFS = require('../shaders/FlatTint.frag');
var Commands = require('../../../gameobjects/graphics/Commands');
var Point = function (x, y, width, rgb, alpha)
{
this.x = x;
this.y = y;
this.width = width;
this.rgb = rgb;
this.alpha = alpha;
};
var Path = function (x, y, width, rgb, alpha)
{
this.points = [];
this.pointsLength = 1;
this.points[0] = new Point(x, y, width, rgb, alpha);
};
var currentMatrix = new Float32Array([1, 0, 0, 1, 0, 0]);
var matrixStack = new Float32Array(6 * 1000);
var matrixStackLength = 0;
var pathArray = [];
var FlatTintPipeline = new Class({ var FlatTintPipeline = new Class({
@ -75,6 +97,7 @@ var FlatTintPipeline = new Class({
{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}
]; ];
this.polygonCache = [];
}, },
resize: function (width, height, resolution) resize: function (width, height, resolution)
@ -91,23 +114,25 @@ var FlatTintPipeline = new Class({
}, },
batchFillRect: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, x, y, width, height, fillColor, fillAlpha, a1, b1, c1, d1, e1, f1, currentMatrix) batchFillRect: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, x, y, width, height, fillColor, fillAlpha, a1, b1, c1, d1, e1, f1, currentMatrix)
{ {
this.renderer.setPipeline(this);
if (this.vertexCount + 6 > this.vertexCapacity) if (this.vertexCount + 6 > this.vertexCapacity)
{ {
this.flush(); this.flush();
} }
var vertexBufferF32 = this.vertexViewF32; var vertexViewF32 = this.vertexViewF32;
var vertexBufferU32 = this.vertexViewU32; var vertexViewU32 = this.vertexViewU32;
var vertexOffset = this.vertexCount * this.vertexComponentCount; var vertexOffset = this.vertexCount * this.vertexComponentCount;
var xw = x + width; var xw = x + width;
var yh = y + height; var yh = y + height;
var a0 = currentMatrix.matrix[0]; var a0 = currentMatrix[0];
var b0 = currentMatrix.matrix[1]; var b0 = currentMatrix[1];
var c0 = currentMatrix.matrix[2]; var c0 = currentMatrix[2];
var d0 = currentMatrix.matrix[3]; var d0 = currentMatrix[3];
var e0 = currentMatrix.matrix[4]; var e0 = currentMatrix[4];
var f0 = currentMatrix.matrix[5]; var f0 = currentMatrix[5];
var a = a1 * a0 + b1 * c0; var a = a1 * a0 + b1 * c0;
var b = a1 * b0 + b1 * d0; var b = a1 * b0 + b1 * d0;
var c = c1 * a0 + d1 * c0; var c = c1 * a0 + d1 * c0;
@ -124,44 +149,46 @@ var FlatTintPipeline = new Class({
var ty3 = xw * b + y * d + f; var ty3 = xw * b + y * d + f;
var tint = Utils.getTintAppendFloatAlpha(fillColor, fillAlpha); var tint = Utils.getTintAppendFloatAlpha(fillColor, fillAlpha);
vertexBufferF32[vertexOffset + 0] = tx0; vertexViewF32[vertexOffset + 0] = tx0;
vertexBufferF32[vertexOffset + 1] = ty0; vertexViewF32[vertexOffset + 1] = ty0;
vertexBufferU32[vertexOffset + 2] = tint; vertexViewU32[vertexOffset + 2] = tint;
vertexBufferF32[vertexOffset + 3] = tx1; vertexViewF32[vertexOffset + 3] = tx1;
vertexBufferF32[vertexOffset + 4] = ty1; vertexViewF32[vertexOffset + 4] = ty1;
vertexBufferU32[vertexOffset + 5] = tint; vertexViewU32[vertexOffset + 5] = tint;
vertexBufferF32[vertexOffset + 6] = tx2; vertexViewF32[vertexOffset + 6] = tx2;
vertexBufferF32[vertexOffset + 7] = ty2; vertexViewF32[vertexOffset + 7] = ty2;
vertexBufferU32[vertexOffset + 8] = tint; vertexViewU32[vertexOffset + 8] = tint;
vertexBufferF32[vertexOffset + 9] = tx0; vertexViewF32[vertexOffset + 9] = tx0;
vertexBufferF32[vertexOffset + 10] = ty0; vertexViewF32[vertexOffset + 10] = ty0;
vertexBufferU32[vertexOffset + 11] = tint; vertexViewU32[vertexOffset + 11] = tint;
vertexBufferF32[vertexOffset + 12] = tx2; vertexViewF32[vertexOffset + 12] = tx2;
vertexBufferF32[vertexOffset + 13] = ty2; vertexViewF32[vertexOffset + 13] = ty2;
vertexBufferU32[vertexOffset + 14] = tint; vertexViewU32[vertexOffset + 14] = tint;
vertexBufferF32[vertexOffset + 15] = tx3; vertexViewF32[vertexOffset + 15] = tx3;
vertexBufferF32[vertexOffset + 16] = ty3; vertexViewF32[vertexOffset + 16] = ty3;
vertexBufferU32[vertexOffset + 17] = tint; vertexViewU32[vertexOffset + 17] = tint;
this.vertexCount += 6; 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) batchFillTriangle: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, x0, y0, x1, y1, x2, y2, fillColor, fillAlpha, a1, b1, c1, d1, e1, f1, currentMatrix)
{ {
this.renderer.setPipeline(this);
if (this.vertexCount + 3 > this.vertexCapacity) if (this.vertexCount + 3 > this.vertexCapacity)
{ {
this.flush(); this.flush();
} }
var vertexBufferF32 = this.vertexViewF32; var vertexViewF32 = this.vertexViewF32;
var vertexBufferU32 = this.vertexViewU32; var vertexViewU32 = this.vertexViewU32;
var vertexOffset = this.vertexCount * this.vertexComponentCount; var vertexOffset = this.vertexCount * this.vertexComponentCount;
var a0 = currentMatrix.matrix[0]; var a0 = currentMatrix[0];
var b0 = currentMatrix.matrix[1]; var b0 = currentMatrix[1];
var c0 = currentMatrix.matrix[2]; var c0 = currentMatrix[2];
var d0 = currentMatrix.matrix[3]; var d0 = currentMatrix[3];
var e0 = currentMatrix.matrix[4]; var e0 = currentMatrix[4];
var f0 = currentMatrix.matrix[5]; var f0 = currentMatrix[5];
var a = a1 * a0 + b1 * c0; var a = a1 * a0 + b1 * c0;
var b = a1 * b0 + b1 * d0; var b = a1 * b0 + b1 * d0;
var c = c1 * a0 + d1 * c0; var c = c1 * a0 + d1 * c0;
@ -176,21 +203,22 @@ var FlatTintPipeline = new Class({
var ty2 = x2 * b + y2 * d + f; var ty2 = x2 * b + y2 * d + f;
var tint = Utils.getTintAppendFloatAlpha(fillColor, fillAlpha); var tint = Utils.getTintAppendFloatAlpha(fillColor, fillAlpha);
vertexBufferF32[vertexOffset + 0] = tx0; vertexViewF32[vertexOffset + 0] = tx0;
vertexBufferF32[vertexOffset + 1] = ty0; vertexViewF32[vertexOffset + 1] = ty0;
vertexBufferU32[vertexOffset + 2] = tint; vertexViewU32[vertexOffset + 2] = tint;
vertexBufferF32[vertexOffset + 3] = tx1; vertexViewF32[vertexOffset + 3] = tx1;
vertexBufferF32[vertexOffset + 4] = ty1; vertexViewF32[vertexOffset + 4] = ty1;
vertexBufferU32[vertexOffset + 5] = tint; vertexViewU32[vertexOffset + 5] = tint;
vertexBufferF32[vertexOffset + 6] = tx2; vertexViewF32[vertexOffset + 6] = tx2;
vertexBufferF32[vertexOffset + 7] = ty2; vertexViewF32[vertexOffset + 7] = ty2;
vertexBufferU32[vertexOffset + 8] = tint; vertexViewU32[vertexOffset + 8] = tint;
this.vertexCount += 3; 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) 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; var tempTriangle = this.tempTriangle;
tempTriangle[0].x = x0; tempTriangle[0].x = x0;
@ -214,7 +242,7 @@ var FlatTintPipeline = new Class({
tempTriangle[3].rgb = lineColor; tempTriangle[3].rgb = lineColor;
tempTriangle[3].alpha = lineAlpha; tempTriangle[3].alpha = lineAlpha;
this.addStrokePath( this.batchStrokePath(
srcX, srcY, srcScaleX, srcScaleY, srcRotation, srcX, srcY, srcScaleX, srcScaleY, srcRotation,
tempTriangle, lineWidth, lineColor, lineAlpha, tempTriangle, lineWidth, lineColor, lineAlpha,
a, b, c, d, e, f, a, b, c, d, e, f,
@ -225,16 +253,576 @@ var FlatTintPipeline = new Class({
batchFillPath: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, path, fillColor, fillAlpha, a1, b1, c1, d1, e1, f1, currentMatrix) batchFillPath: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, path, fillColor, fillAlpha, a1, b1, c1, d1, e1, f1, currentMatrix)
{ {
this.renderer.setPipeline(this);
var length = path.length;
var polygonCache = this.polygonCache;
var polygonIndexArray;
var point;
var v0, v1, v2;
var vertexViewF32 = this.vertexViewF32;
var vertexViewU32 = this.vertexViewU32;
var vertexOffset = 0;
var x0, y0, x1, y1, x2, y2;
var tx0, ty0, tx1, ty1, tx2, ty2;
var a0 = currentMatrix[0];
var b0 = currentMatrix[1];
var c0 = currentMatrix[2];
var d0 = currentMatrix[3];
var e0 = currentMatrix[4];
var f0 = currentMatrix[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 tint = Utils.getTintAppendFloatAlpha(fillColor, fillAlpha);
for (var pathIndex = 0; pathIndex < length; ++pathIndex)
{
point = path[pathIndex];
polygonCache.push(point.x, point.y);
}
polygonIndexArray = Earcut(polygonCache);
length = polygonIndexArray.length;
for (var index = 0; index < length; index += 3)
{
v0 = polygonIndexArray[index + 0] * 2;
v1 = polygonIndexArray[index + 1] * 2;
v2 = polygonIndexArray[index + 2] * 2;
if (this.vertexCount + 3 > this.vertexCapacity)
{
this.flush();
}
vertexOffset = this.vertexCount * this.vertexComponentCount;
x0 = polygonCache[v0 + 0];
y0 = polygonCache[v0 + 1];
x1 = polygonCache[v1 + 0];
y1 = polygonCache[v1 + 1];
x2 = polygonCache[v2 + 0];
y2 = polygonCache[v2 + 1];
tx0 = x0 * a + y0 * c + e;
ty0 = x0 * b + y0 * d + f;
tx1 = x1 * a + y1 * c + e;
ty1 = x1 * b + y1 * d + f;
tx2 = x2 * a + y2 * c + e;
ty2 = x2 * b + y2 * d + f;
vertexViewF32[vertexOffset + 0] = tx0;
vertexViewF32[vertexOffset + 1] = ty0;
vertexViewU32[vertexOffset + 2] = tint;
vertexViewF32[vertexOffset + 3] = tx1;
vertexViewF32[vertexOffset + 4] = ty1;
vertexViewU32[vertexOffset + 5] = tint;
vertexViewF32[vertexOffset + 6] = tx2;
vertexViewF32[vertexOffset + 7] = ty2;
vertexViewU32[vertexOffset + 8] = tint;
this.vertexCount += 3;
}
polygonCache.length = 0;
}, },
batchStrokePath: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, path, lineWidth, lineColor, lineAlpha, a, b, c, d, e, f, isLastPath, currentMatrix) batchStrokePath: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, path, lineWidth, lineColor, lineAlpha, a, b, c, d, e, f, isLastPath, currentMatrix)
{ {
this.renderer.setPipeline(this);
var point0, point1;
var pathLength = path.length;
var polylines = this.polygonCache;
var last, curr;
var vertexViewF32 = this.vertexViewF32;
var vertexViewU32 = this.vertexViewU32;
var vertexOffset;
var line;
var getTint = Utils.getTintAppendFloatAlpha;
for (var pathIndex = 0; pathIndex + 1 < pathLength; pathIndex += 1)
{
point0 = path[pathIndex];
point1 = path[pathIndex + 1];
line = this.batchLine(
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
point0.x, point0.y,
point1.x, point1.y,
point0.width / 2, point1.width / 2,
point0.rgb, point1.rgb, lineAlpha,
a, b, c, d, e, f,
currentMatrix
);
polylines.push(line);
}
/* Render joints */
for (var index = 1, polylinesLength = polylines.length; index < polylinesLength; ++index)
{
if (this.vertexCount + 6 > this.vertexCapacity)
{
this.flush();
}
last = polylines[index - 1] || polylines[polylinesLength - 1];
curr = polylines[index];
vertexOffset = this.vertexCount * this.vertexComponentCount;
vertexViewF32[vertexOffset + 0] = last[3 * 2 + 0];
vertexViewF32[vertexOffset + 1] = last[3 * 2 + 1];
vertexViewU32[vertexOffset + 2] = getTint(last[3 * 2 + 2], lineAlpha);
vertexViewF32[vertexOffset + 3] = last[3 * 0 + 0];
vertexViewF32[vertexOffset + 4] = last[3 * 0 + 1];
vertexViewU32[vertexOffset + 5] = getTint(last[3 * 0 + 2], lineAlpha);
vertexViewF32[vertexOffset + 6] = curr[3 * 3 + 0];
vertexViewF32[vertexOffset + 7] = curr[3 * 3 + 1];
vertexViewU32[vertexOffset + 8] = getTint(curr[3 * 3 + 2], lineAlpha);
vertexViewF32[vertexOffset + 9] = last[3 * 0 + 0];
vertexViewF32[vertexOffset + 10] = last[3 * 0 + 1];
vertexViewU32[vertexOffset + 11] = getTint(last[3 * 0 + 2], lineAlpha);
vertexViewF32[vertexOffset + 12] = last[3 * 2 + 0];
vertexViewF32[vertexOffset + 13] = last[3 * 2 + 1];
vertexViewU32[vertexOffset + 14] = getTint(last[3 * 2 + 2], lineAlpha);
vertexViewF32[vertexOffset + 15] = curr[3 * 1 + 0];
vertexViewF32[vertexOffset + 16] = curr[3 * 1 + 1];
vertexViewU32[vertexOffset + 17] = getTint(curr[3 * 1 + 2], lineAlpha);
this.vertexCount += 6;
}
polylines.length = 0;
}, },
batchLine: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, ax, ay, bx, by, aLineWidth, bLineWidth, aLineColor, bLineColor, lineAlpha, a1, b1, c1, d1, e1, f1, currentMatrix) batchLine: function (srcX, srcY, srcScaleX, srcScaleY, srcRotation, ax, ay, bx, by, aLineWidth, bLineWidth, aLineColor, bLineColor, lineAlpha, a1, b1, c1, d1, e1, f1, currentMatrix)
{ {
this.renderer.setPipeline(this);
if (this.vertexCount + 6 > this.vertexCapacity)
{
this.flush();
}
var a0 = currentMatrix[0];
var b0 = currentMatrix[1];
var c0 = currentMatrix[2];
var d0 = currentMatrix[3];
var e0 = currentMatrix[4];
var f0 = currentMatrix[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 vertexViewF32 = this.vertexViewF32;
var vertexViewU32 = this.vertexViewU32;
var dx = bx - ax;
var dy = by - ay;
var len = Math.sqrt(dx * dx + dy * dy);
var al0 = aLineWidth * (by - ay) / len;
var al1 = aLineWidth * (ax - bx) / len;
var bl0 = bLineWidth * (by - ay) / len;
var bl1 = bLineWidth * (ax - bx) / len;
var lx0 = bx - bl0;
var ly0 = by - bl1;
var lx1 = ax - al0;
var ly1 = ay - al1;
var lx2 = bx + bl0;
var ly2 = by + bl1;
var lx3 = ax + al0;
var ly3 = ay + al1;
var x0 = lx0 * a + ly0 * c + e;
var y0 = lx0 * b + ly0 * d + f;
var x1 = lx1 * a + ly1 * c + e;
var y1 = lx1 * b + ly1 * d + f;
var x2 = lx2 * a + ly2 * c + e;
var y2 = lx2 * b + ly2 * d + f;
var x3 = lx3 * a + ly3 * c + e;
var y3 = lx3 * b + ly3 * d + f;
var getTint = Utils.getTintAppendFloatAlpha;
var aTint = getTint(aLineColor, lineAlpha);
var bTint = getTint(bLineColor, lineAlpha);
var vertexOffset = this.vertexCount * this.vertexComponentCount;
vertexViewF32[vertexOffset + 0] = x0;
vertexViewF32[vertexOffset + 1] = y0;
vertexViewU32[vertexOffset + 2] = bTint;
vertexViewF32[vertexOffset + 3] = x1;
vertexViewF32[vertexOffset + 4] = y1;
vertexViewU32[vertexOffset + 5] = aTint;
vertexViewF32[vertexOffset + 6] = x2;
vertexViewF32[vertexOffset + 7] = y2;
vertexViewU32[vertexOffset + 8] = bTint
vertexViewF32[vertexOffset + 9] = x1;
vertexViewF32[vertexOffset + 10] = y1;
vertexViewU32[vertexOffset + 11] = aTint;
vertexViewF32[vertexOffset + 12] = x3;
vertexViewF32[vertexOffset + 13] = y3;
vertexViewU32[vertexOffset + 14] = aTint;
vertexViewF32[vertexOffset + 15] = x2;
vertexViewF32[vertexOffset + 16] = y2;
vertexViewU32[vertexOffset + 17] = bTint;
this.vertexCount += 6;
return [
x0, y0, bLineColor,
x1, y1, aLineColor,
x2, y2, bLineColor,
x3, y3, aLineColor
];
},
batchGraphics: function (graphics, camera)
{
this.renderer.setPipeline(this);
var cameraScrollX = camera.scrollX * graphics.scrollFactorX;
var cameraScrollY = camera.scrollY * graphics.scrollFactorY;
var srcX = graphics.x - cameraScrollX;
var srcY = graphics.y - cameraScrollY;
var srcScaleX = graphics.scaleX;
var srcScaleY = graphics.scaleY;
var srcRotation = -graphics.rotation;
var commands = graphics.commandBuffer;
var lineAlpha = 1.0;
var fillAlpha = 1.0;
var lineColor = 0;
var fillColor = 0;
var lineWidth = 1.0;
var cameraMatrix = camera.matrix.matrix;
var lastPath = null;
var iteration = 0;
var iterStep = 0.01;
var tx = 0;
var ty = 0;
var ta = 0;
var x = 0;
var y = 0;
var radius = 0;
var startAngle = 0;
var endAngle = 0;
var anticlockwise = 0;
var path = null;
var sin = Math.sin;
var cos = Math.cos;
var sr = sin(srcRotation);
var cr = cos(srcRotation);
var sra = cr * srcScaleX;
var srb = -sr * srcScaleX;
var src = sr * srcScaleY;
var srd = cr * srcScaleY;
var sre = srcX;
var srf = srcY;
var cma = cameraMatrix[0];
var cmb = cameraMatrix[1];
var cmc = cameraMatrix[2];
var cmd = cameraMatrix[3];
var cme = cameraMatrix[4];
var cmf = cameraMatrix[5];
var mva = sra * cma + srb * cmc;
var mvb = sra * cmb + srb * cmd;
var mvc = src * cma + srd * cmc;
var mvd = src * cmb + srd * cmd;
var mve = sre * cma + srf * cmc + cme;
var mvf = sre * cmb + srf * cmd + cmf;
for (var cmdIndex = 0, cmdLength = commands.length; cmdIndex < cmdLength; ++cmdIndex)
{
cmd = commands[cmdIndex];
switch (cmd)
{
case Commands.ARC:
iteration = 0;
x = commands[cmdIndex + 1];
y = commands[cmdIndex + 2];
radius = commands[cmdIndex + 3];
startAngle = commands[cmdIndex + 4];
endAngle = commands[cmdIndex + 5];
anticlockwise = commands[cmdIndex + 6];
if (anticlockwise)
{
ta = endAngle;
endAngle = startAngle;
startAngle = -ta;
}
while (iteration < 1)
{
ta = (endAngle - startAngle) * iteration + startAngle;
tx = x + cos(ta) * radius;
ty = y + sin(ta) * radius;
if (iteration === 0)
{
lastPath = new Path(tx, ty, lineWidth, lineColor, lineAlpha);
pathArray.push(lastPath);
}
else
{
lastPath.points.push(new Point(tx, ty, lineWidth, lineColor, lineAlpha));
}
iteration += iterStep;
}
cmdIndex += 6;
break;
case Commands.LINE_STYLE:
lineWidth = commands[cmdIndex + 1];
lineColor = commands[cmdIndex + 2];
lineAlpha = commands[cmdIndex + 3];
cmdIndex += 3;
break;
case Commands.FILL_STYLE:
fillColor = commands[cmdIndex + 1];
fillAlpha = commands[cmdIndex + 2];
cmdIndex += 2;
break;
case Commands.BEGIN_PATH:
pathArray.length = 0;
break;
case Commands.CLOSE_PATH:
if (lastPath !== null && lastPath.points.length > 0)
{
var firstPoint = lastPath.points[0];
var lastPoint = lastPath.points[lastPath.points.length - 1];
lastPath.points.push(firstPoint);
lastPath = new Path(lastPoint.x, lastPoint.y, lastPoint.width, lastPoint.rgb, lastPoint.alpha);
pathArray.push(lastPath);
}
break;
case Commands.FILL_PATH:
for (var pathArrayIndex = 0, pathArrayLength = pathArray.length;
pathArrayIndex < pathArrayLength;
++pathArrayIndex)
{
this.batchFillPath(
/* Graphics Game Object Properties */
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
/* Rectangle properties */
pathArray[pathArrayIndex].points,
fillColor,
fillAlpha,
/* Transform */
mva, mvb, mvc, mvd, mve, mvf,
currentMatrix
);
}
break;
case Commands.STROKE_PATH:
for (var pathArrayIndex = 0, pathArrayLength = pathArray.length;
pathArrayIndex < pathArrayLength;
++pathArrayIndex)
{
path = pathArray[pathArrayIndex];
this.batchStrokePath(
/* Graphics Game Object Properties */
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
/* Rectangle properties */
path.points,
lineWidth,
lineColor,
lineAlpha,
/* Transform */
mva, mvb, mvc, mvd, mve, mvf,
path === this._lastPath,
currentMatrix
);
}
break;
case Commands.FILL_RECT:
this.batchFillRect(
/* Graphics Game Object Properties */
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
/* Rectangle properties */
commands[cmdIndex + 1],
commands[cmdIndex + 2],
commands[cmdIndex + 3],
commands[cmdIndex + 4],
fillColor,
fillAlpha,
/* Transform */
mva, mvb, mvc, mvd, mve, mvf,
currentMatrix
);
cmdIndex += 4;
break;
case Commands.FILL_TRIANGLE:
this.batchFillTriangle(
/* Graphics Game Object Properties */
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
/* Triangle properties */
commands[cmdIndex + 1],
commands[cmdIndex + 2],
commands[cmdIndex + 3],
commands[cmdIndex + 4],
commands[cmdIndex + 5],
commands[cmdIndex + 6],
fillColor,
fillAlpha,
/* Transform */
mva, mvb, mvc, mvd, mve, mvf,
currentMatrix
);
cmdIndex += 6;
break;
case Commands.STROKE_TRIANGLE:
this.batchStrokeTriangle(
/* Graphics Game Object Properties */
srcX, srcY, srcScaleX, srcScaleY, srcRotation,
/* Triangle properties */
commands[cmdIndex + 1],
commands[cmdIndex + 2],
commands[cmdIndex + 3],
commands[cmdIndex + 4],
commands[cmdIndex + 5],
commands[cmdIndex + 6],
lineWidth,
lineColor,
lineAlpha,
/* Transform */
mva, mvb, mvc, mvd, mve, mvf,
currentMatrix
);
cmdIndex += 6;
break;
case Commands.LINE_TO:
if (lastPath !== null)
{
lastPath.points.push(new Point(commands[cmdIndex + 1], commands[cmdIndex + 2], lineWidth, lineColor, lineAlpha));
}
else
{
lastPath = new Path(commands[cmdIndex + 1], commands[cmdIndex + 2], lineWidth, lineColor, lineAlpha);
pathArray.push(lastPath);
}
cmdIndex += 2;
break;
case Commands.MOVE_TO:
lastPath = new Path(commands[cmdIndex + 1], commands[cmdIndex + 2], lineWidth, lineColor, lineAlpha);
pathArray.push(lastPath);
cmdIndex += 2;
break;
case Commands.LINE_FX_TO:
if (lastPath !== null)
{
lastPath.points.push(new Point(
commands[cmdIndex + 1],
commands[cmdIndex + 2],
commands[cmdIndex + 3],
commands[cmdIndex + 4],
commands[cmdIndex + 5]
));
}
else
{
lastPath = new Path(
commands[cmdIndex + 1],
commands[cmdIndex + 2],
commands[cmdIndex + 3],
commands[cmdIndex + 4],
commands[cmdIndex + 5]
);
pathArray.push(lastPath);
}
cmdIndex += 5;
break;
case Commands.MOVE_FX_TO:
lastPath = new Path(
commands[cmdIndex + 1],
commands[cmdIndex + 2],
commands[cmdIndex + 3],
commands[cmdIndex + 4],
commands[cmdIndex + 5]
);
pathArray.push(lastPath);
cmdIndex += 5;
break;
case Commands.SAVE:
matrixStack[matrixStackLength + 0] = currentMatrix[0];
matrixStack[matrixStackLength + 1] = currentMatrix[1];
matrixStack[matrixStackLength + 2] = currentMatrix[2];
matrixStack[matrixStackLength + 3] = currentMatrix[3];
matrixStack[matrixStackLength + 4] = currentMatrix[4];
matrixStack[matrixStackLength + 5] = currentMatrix[5];
matrixStackLength += 6;
break;
case Commands.RESTORE:
matrixStackLength -= 6;
currentMatrix[0] = matrixStack[matrixStackLength + 0];
currentMatrix[1] = matrixStack[matrixStackLength + 1];
currentMatrix[2] = matrixStack[matrixStackLength + 2];
currentMatrix[3] = matrixStack[matrixStackLength + 3];
currentMatrix[4] = matrixStack[matrixStackLength + 4];
currentMatrix[5] = matrixStack[matrixStackLength + 5];
break;
case Commands.TRANSLATE:
x = commands[cmdIndex + 1];
y = commands[cmdIndex + 2];
currentMatrix[4] = currentMatrix[0] * x + currentMatrix[2] * y + currentMatrix[4];
currentMatrix[5] = currentMatrix[1] * x + currentMatrix[3] * y + currentMatrix[5];
cmdIndex += 2;
break;
case Commands.SCALE:
x = commands[cmdIndex + 1];
y = commands[cmdIndex + 2];
currentMatrix[0] *= x;
currentMatrix[1] *= x;
currentMatrix[2] *= y;
currentMatrix[3] *= y;
cmdIndex += 2;
break;
case Commands.ROTATE:
y = commands[cmdIndex + 1];
x = sin(y);
y = cos(y);
sra = currentMatrix[0];
srb = currentMatrix[1];
src = currentMatrix[2];
srd = currentMatrix[3];
currentMatrix[0] = y * sra + x * src;
currentMatrix[1] = y * srb + x * srd;
currentMatrix[2] = -x * sra + y * src;
currentMatrix[3] = -x * srb + y * srd;
cmdIndex += 1;
break;
default:
console.error('Phaser: Invalid Graphics Command ID ' + cmd);
break;
}
}
} }

View file

@ -5,5 +5,5 @@ precision mediump float;
varying vec4 outTint; varying vec4 outTint;
void main() { void main() {
gl_FragColor = vec4(outTint.bgr * outTint.a, outTint.a); gl_FragColor = vec4(outTint.rgb * outTint.a, outTint.a);
} }