Dynamic Bitmap Text webgl rendering

This commit is contained in:
Felipe Alfonso 2018-01-24 15:55:23 -03:00
parent 69c56fc920
commit 06fa0afcc8
4 changed files with 381 additions and 328 deletions

View file

@ -4,285 +4,17 @@ var Utils = require('../../../renderer/webgl/Utils');
var tempMatrix = new TransformMatrix();
var tempMatrixChar = new TransformMatrix();
var DynamicBitmapTextWebGLRenderer = function (renderer, gameObject, interpolationPercentage, camera)
var DynamicBitmapTextWebGLRenderer = function (renderer, bitmapText, interpolationPercentage, camera)
{
var text = gameObject.text;
var text = bitmapText.text;
var textLength = text.length;
if (GameObject.RENDER_MASK !== gameObject.renderFlags || textLength === 0 || (gameObject.cameraFilter > 0 && (gameObject.cameraFilter & camera._id)))
if (GameObject.RENDER_MASK !== bitmapText.renderFlags || textLength === 0 || (bitmapText.cameraFilter > 0 && (bitmapText.cameraFilter & camera._id)))
{
return;
}
var spriteRenderer = renderer.spriteRenderer;
var displayCallback = gameObject.displayCallback;
var textureFrame = gameObject.frame;
var cameraScrollX = camera.scrollX * gameObject.scrollFactorX;
var cameraScrollY = camera.scrollY * gameObject.scrollFactorY;
var chars = gameObject.fontData.chars;
var lineHeight = gameObject.fontData.lineHeight;
var getTint = Utils.getTintAppendFloatAlpha;
var alpha = gameObject.alpha;
var tintTL = getTint(gameObject._tintTL, alpha);
var tintTR = getTint(gameObject._tintTR, alpha);
var tintBL = getTint(gameObject._tintBL, alpha);
var tintBR = getTint(gameObject._tintBR, alpha);
var vertexViewF32 = spriteRenderer.vertexViewF32;
var vertexViewU32 = spriteRenderer.vertexViewU32;
var vertexOffset = 0;
var textureData = gameObject.texture.source[textureFrame.sourceIndex];
var textureX = textureFrame.cutX;
var textureY = textureFrame.cutY;
var textureWidth = textureData.width;
var textureHeight = textureData.height;
var texture = textureData.glTexture;
var xAdvance = 0;
var yAdvance = 0;
var indexCount = 0;
var charCode = 0;
var glyph = null;
var glyphX = 0;
var glyphY = 0;
var glyphW = 0;
var glyphH = 0;
var x = 0;
var y = 0;
var rotation = 0;
var xw = 0;
var yh = 0;
var umin = 0;
var umax = 0;
var vmin = 0;
var vmax = 0;
var lastGlyph = null;
var lastCharCode = 0;
var tempMatrixMatrix = tempMatrix.matrix;
var cameraMatrix = camera.matrix.matrix;
var scale = (gameObject.fontSize / gameObject.fontData.size);
var uta, utb, utc, utd, ute, utf;
var tempMatrixCharMatrix = tempMatrixChar.matrix;
var renderTarget = gameObject.renderTarget;
var sr = Math.sin(-gameObject.rotation);
var cr = Math.cos(-gameObject.rotation);
var sra = cr * gameObject.scaleX;
var srb = -sr * gameObject.scaleX;
var src = sr * gameObject.scaleY;
var srd = cr * gameObject.scaleY;
var sre = gameObject.x - cameraScrollX;
var srf = gameObject.y - cameraScrollY;
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;
var gl = renderer.gl;
var shader = null;
renderer.setPipeline(spriteRenderer);
spriteRenderer.beginPass(gameObject.shader, gameObject.renderTarget);
renderer.setTexture(texture, 0);
shader = spriteRenderer.currentProgram;
spriteRenderer.orthoViewMatrix[0] = +2.0 / spriteRenderer.width;
spriteRenderer.orthoViewMatrix[5] = -2.0 / spriteRenderer.height;
shader.setConstantMatrix4x4(shader.getUniformLocation('uOrthoMatrix'), spriteRenderer.orthoViewMatrix);
if (gameObject.cropWidth > 0 && gameObject.cropHeight > 0)
{
spriteRenderer.flush();
if (!renderer.scissor.enabled)
{
gl.enable(gl.SCISSOR_TEST);
}
var sw = gameObject.cropWidth * gameObject.scaleX;
var sh = gameObject.cropHeight * gameObject.scaleY;
gl.scissor(gameObject.x, gl.drawingBufferHeight - gameObject.y - sh, sw, sh);
}
for (var index = 0; index < textLength; ++index)
{
charCode = text.charCodeAt(index);
if (charCode === 10)
{
xAdvance = 0;
indexCount = 0;
yAdvance += lineHeight;
lastGlyph = null;
continue;
}
glyph = chars[charCode];
if (!glyph)
{
continue;
}
glyphX = textureX + glyph.x;
glyphY = textureY + glyph.y;
glyphW = glyph.width;
glyphH = glyph.height;
x = (indexCount + glyph.xOffset + xAdvance) * scale;
y = (glyph.yOffset + yAdvance) * scale;
rotation = 0;
if (lastGlyph !== null)
{
var kerningOffset = glyph.kerning[lastCharCode];
x += (kerningOffset !== undefined) ? kerningOffset : 0;
}
if (displayCallback)
{
var output = displayCallback({ color: 0, tint: { topLeft: tintTL, topRight: tintTR, bottomLeft: tintBL, bottomRight: tintBR }, index: index, charCode: charCode, x: x, y: y, scale: scale, rotation: 0, data: glyph.data });
x = output.x;
y = output.y;
scale = output.scale;
rotation = output.rotation;
if (output.color)
{
tintTL = output.color;
tintTR = output.color;
tintBL = output.color;
tintBR = output.color;
}
else
{
tintTL = output.tint.topLeft;
tintTR = output.tint.topRight;
tintBL = output.tint.bottomLeft;
tintBR = output.tint.bottomRight;
}
tintTL = getTint(tintTL, alpha);
tintTR = getTint(tintTR, alpha);
tintBL = getTint(tintBL, alpha);
tintBR = getTint(tintBR, alpha);
}
x -= gameObject.scrollX | 0;
y -= gameObject.scrollY | 0;
tempMatrixChar.applyITRS(
x, y,
-rotation,
scale, scale
);
uta = tempMatrixCharMatrix[0];
utb = tempMatrixCharMatrix[1];
utc = tempMatrixCharMatrix[2];
utd = tempMatrixCharMatrix[3];
ute = tempMatrixCharMatrix[4];
utf = tempMatrixCharMatrix[5];
sra = uta * mva + utb * mvc;
srb = uta * mvb + utb * mvd;
src = utc * mva + utd * mvc;
srd = utc * mvb + utd * mvd;
sre = ute * mva + utf * mvc + mve;
srf = ute * mvb + utf * mvd + mvf;
xw = glyphW;
yh = glyphH;
tx0 = sre;
ty0 = srf;
tx1 = yh * src + sre;
ty1 = yh * srd + srf;
tx2 = xw * sra + yh * src + sre;
ty2 = xw * srb + yh * srd + srf;
tx3 = xw * sra + sre;
ty3 = xw * srb + srf;
umin = glyphX / textureWidth;
umax = (glyphX + glyphW) / textureWidth;
vmin = glyphY / textureHeight;
vmax = (glyphY + glyphH) / textureHeight;
if (spriteRenderer.vertexCount >= spriteRenderer.vertexCapacity)
{
spriteRenderer.flush();
vertexOffset = 0;
}
spriteRenderer.vertexCount += 6;
vertexViewF32[vertexOffset++] = tx0;
vertexViewF32[vertexOffset++] = ty0;
vertexViewF32[vertexOffset++] = umin;
vertexViewF32[vertexOffset++] = vmin;
vertexViewU32[vertexOffset++] = tintTL;
vertexViewF32[vertexOffset++] = tx1;
vertexViewF32[vertexOffset++] = ty1;
vertexViewF32[vertexOffset++] = umin;
vertexViewF32[vertexOffset++] = vmax;
vertexViewU32[vertexOffset++] = tintBL;
vertexViewF32[vertexOffset++] = tx2;
vertexViewF32[vertexOffset++] = ty2;
vertexViewF32[vertexOffset++] = umax;
vertexViewF32[vertexOffset++] = vmax;
vertexViewU32[vertexOffset++] = tintBR;
vertexViewF32[vertexOffset++] = tx0;
vertexViewF32[vertexOffset++] = ty0;
vertexViewF32[vertexOffset++] = umin;
vertexViewF32[vertexOffset++] = vmin;
vertexViewU32[vertexOffset++] = tintTL;
vertexViewF32[vertexOffset++] = tx2;
vertexViewF32[vertexOffset++] = ty2;
vertexViewF32[vertexOffset++] = umax;
vertexViewF32[vertexOffset++] = vmax;
vertexViewU32[vertexOffset++] = tintBR;
vertexViewF32[vertexOffset++] = tx3;
vertexViewF32[vertexOffset++] = ty3;
vertexViewF32[vertexOffset++] = umax;
vertexViewF32[vertexOffset++] = vmin;
vertexViewU32[vertexOffset++] = tintTR;
xAdvance += glyph.xAdvance;
indexCount += 1;
lastGlyph = glyph;
lastCharCode = charCode;
}
if (gameObject.cropWidth > 0 && gameObject.cropHeight > 0)
{
spriteRenderer.flush();
if (renderer.scissor.enabled)
{
gl.scissor(renderer.scissor.x, renderer.scissor.y, renderer.scissor.width, renderer.scissor.height);
}
else
{
gl.scissor(camera.x, gl.drawingBufferHeight - camera.y - camera.height, camera.width, camera.height);
gl.disable(gl.SCISSOR_TEST);
}
}
spriteRenderer.flush();
spriteRenderer.endPass();
renderer.pipelines.TextureTintPipeline.batchDynamicBitmapText(bitmapText, camera);
};
module.exports = DynamicBitmapTextWebGLRenderer;

View file

@ -14,7 +14,7 @@ var GameObjects = {
BitmapText: require('./bitmaptext/static/BitmapText'),
Blitter: require('./blitter/Blitter'),
//Container: require('./container/Container'),
//DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapText'),
DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapText'),
//DynamicTilemapLayer: require('./tilemap/dynamiclayer/DynamicTilemapLayer'),
Graphics: require('./graphics/Graphics.js'),
//Group: require('./group/Group'),
@ -36,7 +36,7 @@ var GameObjects = {
Factories: {
Blitter: require('./blitter/BlitterFactory'),
//Container: require('./container/ContainerFactory'),
//DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapTextFactory'),
DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapTextFactory'),
Graphics: require('./graphics/GraphicsFactory'),
//Group: require('./group/GroupFactory'),
Image: require('./image/ImageFactory'),
@ -54,7 +54,7 @@ var GameObjects = {
Creators: {
Blitter: require('./blitter/BlitterCreator'),
//Container: require('./container/ContainerCreator'),
//DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapTextCreator'),
DynamicBitmapText: require('./bitmaptext/dynamic/DynamicBitmapTextCreator'),
Graphics: require('./graphics/GraphicsCreator'),
//Group: require('./group/GroupCreator'),
Image: require('./image/ImageCreator'),

View file

@ -62,7 +62,10 @@ var WebGLRenderer = new Class({
this.currentVertexBuffer = null;
this.currentIndexBuffer = null;
this.currentBlendMode = Infinity;
this.currentScissorState = { enabled: false, x: 0, y: 0, w: 0, h: 0 };
this.currentScissorEnabled = false;
this.currentScissor = new Uint32Array([0, 0, this.width, this.height]);
this.currentScissorIdx = 0;
this.scissorStack = new Uint32Array(4 * 1000);
// Setup context lost and restore event listeners
this.canvas.addEventListener('webglcontextlost', function (event) {
@ -229,45 +232,70 @@ var WebGLRenderer = new Class({
return this;
},
beginScissor: function (x, y, width, height)
setScissor: function (x, y, w, h)
{
var gl = this.gl;
var scissorState = this.currentScissorState;
var currentScissor = this.currentScissor;
var enabled = (x == 0 && y == 0 && w == gl.canvas.width && h == gl.canvas.height && w >= 0 && h >= 0);
if (x == 0 &&
y == 0 &&
width == gl.canvas.width &&
height == gl.canvas.height &&
width > 0 &&
height > 0)
{
return;
}
if (!scissorState.enabled)
if (currentScissor[0] !== x ||
currentScissor[1] !== y ||
currentScissor[2] !== w ||
currentScissor[3] !== h)
{
this.flush();
gl.enable(gl.SCISSOR_TEST);
scissorState.enabled = true;
}
scissorState.x = x;
scissorState.y = gl.drawingBufferHeight - y - height;
scissorState.width = width;
scissorState.height = height;
gl.scissor(scissorState.x, scissorState.y, scissorState.width, scissorState.height);
},
currentScissor[0] = x;
currentScissor[1] = y;
currentScissor[2] = w;
currentScissor[3] = h;
endScissor: function ()
{
var gl = this.gl;
var scissorState = this.currentScissorState;
this.currentScissorEnabled = enabled;
if (scissorState.enabled)
if (enabled)
{
gl.disable(gl.SCISSOR_TEST);
scissorState.enabled = false;
return;
}
gl.enable(gl.SCISSOR_TEST);
gl.scissor(x, (gl.drawingBufferHeight - y - h), w, h);
return this;
},
pushScissor: function (x, y, w, h)
{
var scissorStack = this.scissorStack;
var stackIndex = this.currentScissorIdx;
var currentScissor = this.currentScissor;
scissorStack[stackIndex + 0] = currentScissor[0];
scissorStack[stackIndex + 1] = currentScissor[1];
scissorStack[stackIndex + 2] = currentScissor[2];
scissorStack[stackIndex + 3] = currentScissor[3];
this.currentScissorIdx += 4;
this.setScissor(x, y, w, h);
return this;
},
popScissor: function ()
{
var scissorStack = this.scissorStack;
var stackIndex = this.currentScissorIdx - 4;
var x = scissorStack[stackIndex + 0];
var y = scissorStack[stackIndex + 1];
var w = scissorStack[stackIndex + 2];
var h = scissorStack[stackIndex + 3];
this.currentScissorIdx = stackIndex;
this.setScissor(x, y, w, h);
return this;
},
setPipeline: function (pipelineInstance, overrideProgram)
@ -559,7 +587,7 @@ var WebGLRenderer = new Class({
/* Rendering Functions */
preRenderCamera: function (camera)
{
this.beginScissor(camera.x, camera.y, camera.width, camera.height);
this.pushScissor(camera.x, camera.y, camera.width, camera.height);
if (camera.backgroundColor.alphaGL > 0)
{
@ -608,7 +636,7 @@ var WebGLRenderer = new Class({
FlatTintPipeline.flush();
}
this.endScissor();
this.popScissor();
},
preRender: function ()

View file

@ -531,7 +531,7 @@ var TextureTintPipeline = new Class({
var cameraScrollY = camera.scrollY * bitmapText.scrollFactorY;
var fontData = bitmapText.fontData;
var lineHeight = fontData.lineHeight;
var scale = (bitmapText.fontSize / fontData.size);
var scale = (bitmapText.fontSize / bitmapText.fontData.size);
var chars = fontData.chars;
var alpha = bitmapText.alpha;
var tint0 = getTint(bitmapText._tintTL, alpha);
@ -589,6 +589,8 @@ var TextureTintPipeline = new Class({
var mvd = src * cmb + srd * cmd;
var mve = sre * cma + srf * cmc + cme;
var mvf = sre * cmb + srf * cmd + cmf;
var crop = (bitmapText.cropWidth > 0 || bitmapText.cropHeight > 0);
var uta, utb, utc, utd, ute, utf;
var vertexOffset = 0;
renderer.setTexture2D(texture, 0);
@ -615,38 +617,44 @@ var TextureTintPipeline = new Class({
glyphX = textureX + glyph.x;
glyphY = textureY + glyph.y;
glyphW = glyph.width;
glyphH = glyph.height;
x = (indexCount + glyph.xOffset + xAdvance) * scale;
y = (glyph.yOffset + yAdvance) * scale;
x = (indexCount + glyph.xOffset + xAdvance) - scrollX;
y = (glyph.yOffset + yAdvance) - scrollY;
if (lastGlyph !== null)
{
var kerningOffset = glyph.kerning[lastCharCode];
x += (kerningOffset !== undefined) ? kerningOffset : 0;
}
}
xAdvance += glyph.xAdvance;
indexCount += 1;
lastGlyph = glyph;
lastCharCode = charCode;
uta = scale;
utb = 0;
utc = 0;
utd = scale;
ute = x * scale;
utf = y * scale;
// Nothing to render or a space? Then skip to the next glyph
if (glyphW === 0 || glyphH === 0 || charCode === 32)
{
continue;
}
sra = uta * mva + utb * mvc;
srb = uta * mvb + utb * mvd;
src = utc * mva + utd * mvc;
srd = utc * mvb + utd * mvd;
sre = ute * mva + utf * mvc + mve;
srf = ute * mvb + utf * mvd + mvf;
xw = glyphW;
yh = glyphH;
tx0 = sre;
ty0 = srf;
tx1 = yh * src + sre;
ty1 = yh * srd + srf;
tx2 = xw * sra + yh * src + sre;
ty2 = xw * srb + yh * srd + srf;
tx3 = xw * sra + sre;
ty3 = xw * srb + srf;
xw = x + glyphW * scale;
yh = y + glyphH * scale;
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;
umin = glyphX / textureWidth;
umax = (glyphX + glyphW) / textureWidth;
vmin = glyphY / textureHeight;
@ -689,9 +697,294 @@ var TextureTintPipeline = new Class({
vertexViewF32[vertexOffset + 27] = umax;
vertexViewF32[vertexOffset + 28] = vmin;
vertexViewU32[vertexOffset + 29] = tint3;
xAdvance += glyph.xAdvance;
indexCount += 1;
lastGlyph = glyph;
lastCharCode = charCode;
this.vertexCount += 6;
}
if (crop)
{
renderer.popScissor();
}
},
batchDynamicBitmapText: function (bitmapText, camera)
{
this.renderer.setPipeline(this);
if (this.vertexCount + 6 > this.vertexCapacity)
{
this.flush();
}
var displayCallback = bitmapText.displayCallback;
var text = bitmapText.text;
var textLength = text.length;
var getTint = Utils.getTintAppendFloatAlpha;
var vertexViewF32 = this.vertexViewF32;
var vertexViewU32 = this.vertexViewU32;
var renderer = this.renderer;
var cameraMatrix = camera.matrix.matrix;
var cameraWidth = camera.width + 50;
var cameraHeight = camera.height + 50;
var cameraX = -50;
var cameraY = -50;
var frame = bitmapText.frame;
var textureSource = bitmapText.texture.source[frame.sourceIndex];
var cameraScrollX = camera.scrollX * bitmapText.scrollFactorX;
var cameraScrollY = camera.scrollY * bitmapText.scrollFactorY;
var scrollX = bitmapText.scrollX;
var scrollY = bitmapText.scrollY;
var fontData = bitmapText.fontData;
var lineHeight = fontData.lineHeight;
var scale = (bitmapText.fontSize / fontData.size);
var chars = fontData.chars;
var alpha = bitmapText.alpha;
var tint0 = getTint(bitmapText._tintTL, alpha);
var tint1 = getTint(bitmapText._tintTR, alpha);
var tint2 = getTint(bitmapText._tintBL, alpha);
var tint3 = getTint(bitmapText._tintBR, alpha);
var srcX = bitmapText.x;
var srcY = bitmapText.y;
var textureX = frame.cutX;
var textureY = frame.cutY;
var textureWidth = textureSource.width;
var textureHeight = textureSource.height;
var texture = textureSource.glTexture;
var xAdvance = 0;
var yAdvance = 0;
var indexCount = 0;
var charCode = 0;
var glyph = null;
var glyphX = 0;
var glyphY = 0;
var glyphW = 0;
var glyphH = 0;
var x = 0;
var y = 0;
var xw = 0;
var yh = 0;
var umin = 0;
var umax = 0;
var vmin = 0;
var vmax = 0;
var lastGlyph = null;
var lastCharCode = 0;
var translateX = srcX + frame.x;
var translateY = srcY + frame.y;
var rotation = -bitmapText.rotation;
var scaleX = bitmapText.scaleX;
var scaleY = bitmapText.scaleY;
var sr = Math.sin(rotation);
var cr = Math.cos(rotation);
var sra = cr * scaleX;
var srb = -sr * scaleX;
var src = sr * scaleY;
var srd = cr * scaleY;
var sre = translateX;
var srf = translateY;
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;
var crop = (bitmapText.cropWidth > 0 || bitmapText.cropHeight > 0);
var uta, utb, utc, utd, ute, utf;
var vertexOffset = 0;
renderer.setTexture2D(texture, 0);
if (crop)
{
renderer.pushScissor(
bitmapText.x,
bitmapText.y,
bitmapText.cropWidth * bitmapText.scaleX,
bitmapText.cropHeight * bitmapText.scaleY
);
}
for (var index = 0; index < textLength; ++index)
{
scale = (bitmapText.fontSize / bitmapText.fontData.size);
rotation = 0;
charCode = text.charCodeAt(index);
if (charCode === 10)
{
xAdvance = 0;
indexCount = 0;
yAdvance += lineHeight;
lastGlyph = null;
continue;
}
glyph = chars[charCode];
if (!glyph)
{
continue;
}
glyphX = textureX + glyph.x;
glyphY = textureY + glyph.y;
glyphW = glyph.width;
glyphH = glyph.height;
x = (indexCount + glyph.xOffset + xAdvance) - scrollX;
y = (glyph.yOffset + yAdvance) - scrollY;
if (lastGlyph !== null)
{
var kerningOffset = glyph.kerning[lastCharCode];
x += (kerningOffset !== undefined) ? kerningOffset : 0;
}
if (displayCallback)
{
var output = displayCallback({
color: 0,
tint: {
topLeft: tint0,
topRight: tint1,
bottomLeft: tint2,
bottomRight: tint3
},
index: index,
charCode: charCode,
x: x,
y: y,
scale: scale,
rotation: 0,
data: glyph.data
});
x = output.x;
y = output.y;
scale = output.scale;
rotation = output.rotation;
if (output.color)
{
tint0 = output.color;
tint1 = output.color;
tint2 = output.color;
tint3 = output.color;
}
else
{
tint0 = output.tint.topLeft;
tint1 = output.tint.topRight;
tint2 = output.tint.bottomLeft;
tint3 = output.tint.bottomRight;
}
tint0 = getTint(tint0, alpha);
tint1 = getTint(tint1, alpha);
tint2 = getTint(tint2, alpha);
tint3 = getTint(tint3, alpha);
}
x *= scale;
y *= scale;
x -= cameraScrollX;
y -= cameraScrollY;
sr = Math.sin(-rotation);
cr = Math.cos(-rotation);
uta = cr * scale;
utb = -sr * scale;
utc = sr * scale;
utd = cr * scale;
ute = x;
utf = y;
sra = uta * mva + utb * mvc;
srb = uta * mvb + utb * mvd;
src = utc * mva + utd * mvc;
srd = utc * mvb + utd * mvd;
sre = ute * mva + utf * mvc + mve;
srf = ute * mvb + utf * mvd + mvf;
xw = glyphW;
yh = glyphH;
tx0 = sre;
ty0 = srf;
tx1 = yh * src + sre;
ty1 = yh * srd + srf;
tx2 = xw * sra + yh * src + sre;
ty2 = xw * srb + yh * srd + srf;
tx3 = xw * sra + sre;
ty3 = xw * srb + srf;
umin = glyphX / textureWidth;
umax = (glyphX + glyphW) / textureWidth;
vmin = glyphY / textureHeight;
vmax = (glyphY + glyphH) / textureHeight;
if (this.vertexCount + 6 > this.vertexCapacity)
{
this.flush();
}
vertexOffset = this.vertexCount * this.vertexComponentCount;
vertexViewF32[vertexOffset + 0] = tx0;
vertexViewF32[vertexOffset + 1] = ty0;
vertexViewF32[vertexOffset + 2] = umin;
vertexViewF32[vertexOffset + 3] = vmin;
vertexViewU32[vertexOffset + 4] = tint0;
vertexViewF32[vertexOffset + 5] = tx1;
vertexViewF32[vertexOffset + 6] = ty1;
vertexViewF32[vertexOffset + 7] = umin;
vertexViewF32[vertexOffset + 8] = vmax;
vertexViewU32[vertexOffset + 9] = tint1;
vertexViewF32[vertexOffset + 10] = tx2;
vertexViewF32[vertexOffset + 11] = ty2;
vertexViewF32[vertexOffset + 12] = umax;
vertexViewF32[vertexOffset + 13] = vmax;
vertexViewU32[vertexOffset + 14] = tint2;
vertexViewF32[vertexOffset + 15] = tx0;
vertexViewF32[vertexOffset + 16] = ty0;
vertexViewF32[vertexOffset + 17] = umin;
vertexViewF32[vertexOffset + 18] = vmin;
vertexViewU32[vertexOffset + 19] = tint0;
vertexViewF32[vertexOffset + 20] = tx2;
vertexViewF32[vertexOffset + 21] = ty2;
vertexViewF32[vertexOffset + 22] = umax;
vertexViewF32[vertexOffset + 23] = vmax;
vertexViewU32[vertexOffset + 24] = tint2;
vertexViewF32[vertexOffset + 25] = tx3;
vertexViewF32[vertexOffset + 26] = ty3;
vertexViewF32[vertexOffset + 27] = umax;
vertexViewF32[vertexOffset + 28] = vmin;
vertexViewU32[vertexOffset + 29] = tint3;
xAdvance += glyph.xAdvance;
indexCount += 1;
lastGlyph = glyph;
lastCharCode = charCode;
this.vertexCount += 6;
}
if (crop)
{
renderer.popScissor();
}
}
});