migalib
Version:
MIGAlib - MInimal GAme LIBrary
259 lines (258 loc) • 10.9 kB
JavaScript
"use strict";
/* HERE BE DRAGONS!
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.RendererFactory = void 0;
var RendererFactorySingleton = /** @class */ (function () {
function RendererFactorySingleton() {
}
RendererFactorySingleton.prototype.compileShader = function (gl, source, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
};
RendererFactorySingleton.prototype.createShaderProgram = function (gl, vsSource, fsSource) {
var program = gl.createProgram();
var vShader = this.compileShader(gl, vsSource, 35633);
var fShader = this.compileShader(gl, fsSource, 35632);
gl.attachShader(program, vShader);
gl.attachShader(program, fShader);
gl.linkProgram(program);
return program;
};
RendererFactorySingleton.prototype.createBuffer = function (gl, bufferType, size, usage) {
var buffer = gl.createBuffer();
gl.bindBuffer(bufferType, buffer);
gl.bufferData(bufferType, size, usage);
return buffer;
};
RendererFactorySingleton.prototype.createTexture = function (gl, image, width, height, scale) {
if (scale === void 0) { scale = 1; }
var texture = gl.createTexture();
gl.bindTexture(3553, texture);
gl.texParameteri(3553, 10242, 33071);
gl.texParameteri(3553, 10243, 33071);
gl.texParameteri(3553, 10240, 9728);
gl.texParameteri(3553, 10241, 9728);
gl.texImage2D(3553, 0, 6408, 6408, 5121, image);
gl.bindTexture(3553, null);
texture.width = width * scale;
texture.height = height * scale;
texture.scale = scale;
return texture;
};
RendererFactorySingleton.prototype.createWebGLRenderer = function (canvas, textureBleedingFix) {
if (textureBleedingFix === void 0) { textureBleedingFix = 0; }
var gl = canvas.getContext("webgl", {
antialias: false,
});
// float + (vec2 * 4) + (char * 4)
var VERTEX_SIZE = 4 + 4 * 2 * 4 + 4;
var MAX_BATCH = 10922; // floor((2 ^ 16) / 6)
var VERTEX_DATA_SIZE = VERTEX_SIZE * MAX_BATCH * 4;
var VERTICES_PER_QUAD = 6;
var INDEX_DATA_SIZE = MAX_BATCH * (2 * VERTICES_PER_QUAD);
var width = canvas.width;
var height = canvas.height;
var shader = this.createShaderProgram(gl, [
"precision lowp float;",
"attribute float a;",
"attribute vec2 b,c,d,e;",
"attribute vec4 f;",
"varying vec2 g;",
"varying vec4 h;",
"uniform mat4 i;",
"void main() {",
"float q=cos(a);",
"float w=sin(a);",
"gl_Position=i*vec4(((vec2((d.x*q-d.y*w), (d.x*w+d.y*q))*c)+b),1.0,1.0);",
"g=e;",
"h=f;",
"}",
].join("\n"), [
"precision lowp float;",
"varying vec2 g;",
"varying vec4 h;",
"uniform sampler2D j;",
"void main(){",
"gl_FragColor=texture2D(j,g)*h;",
"}",
].join("\n"));
var glBufferSubData = gl.bufferSubData.bind(gl);
var glDrawElements = gl.drawElements.bind(gl);
var glBindTexture = gl.bindTexture.bind(gl);
var glClear = gl.clear.bind(gl);
var glClearColor = gl.clearColor.bind(gl);
var vertexData = new ArrayBuffer(VERTEX_DATA_SIZE);
var vPositionData = new Float32Array(vertexData);
var vColorData = new Uint32Array(vertexData);
var vIndexData = new Uint16Array(INDEX_DATA_SIZE);
var IBO = this.createBuffer(gl, 34963, vIndexData.byteLength, 35044);
var VBO = this.createBuffer(gl, 34962, vertexData.byteLength, 35048);
var currentTexture = null;
var count = 0;
var renderer = null;
var indexB;
gl.blendFunc(770, 771);
gl.enable(3042);
gl.useProgram(shader);
gl.bindBuffer(34963, IBO);
for (var indexA = (indexB = 0); indexA < MAX_BATCH * VERTICES_PER_QUAD; indexA += VERTICES_PER_QUAD, indexB += 4) {
(vIndexData[indexA + 0] = indexB),
(vIndexData[indexA + 1] = indexB + 1),
(vIndexData[indexA + 2] = indexB + 2),
(vIndexData[indexA + 3] = indexB + 0),
(vIndexData[indexA + 4] = indexB + 3),
(vIndexData[indexA + 5] = indexB + 1);
}
gl.bufferSubData(34963, 0, vIndexData);
gl.bindBuffer(34962, VBO);
var locRotation = gl.getAttribLocation(shader, "a");
var locTranslation = gl.getAttribLocation(shader, "b");
var locScale = gl.getAttribLocation(shader, "c");
var locPosition = gl.getAttribLocation(shader, "d");
var locUV = gl.getAttribLocation(shader, "e");
var locColor = gl.getAttribLocation(shader, "f");
// Rotation
gl.enableVertexAttribArray(locRotation);
gl.vertexAttribPointer(locRotation, 1, 5126, false, VERTEX_SIZE, 0);
// Translation
gl.enableVertexAttribArray(locTranslation);
gl.vertexAttribPointer(locTranslation, 2, 5126, false, VERTEX_SIZE, 4);
// Scale
gl.enableVertexAttribArray(locScale);
gl.vertexAttribPointer(locScale, 2, 5126, false, VERTEX_SIZE, 12);
// Position
gl.enableVertexAttribArray(locPosition);
gl.vertexAttribPointer(locPosition, 2, 5126, false, VERTEX_SIZE, 20);
// UV
gl.enableVertexAttribArray(locUV);
gl.vertexAttribPointer(locUV, 2, 5126, false, VERTEX_SIZE, 28);
// Color
gl.enableVertexAttribArray(locColor);
gl.vertexAttribPointer(locColor, 4, 5121, true, VERTEX_SIZE, 36);
gl.uniformMatrix4fv(gl.getUniformLocation(shader, "i"), false, new Float32Array([
2 / width,
0,
0,
0,
0,
-2 / height,
0,
0,
0,
0,
1,
1,
-1,
1,
0,
0,
]));
gl.activeTexture(33984);
renderer = {
g: gl,
c: canvas,
col: 0xffffffff,
bkg: function (r, g, b) {
gl.clearColor(r, g, b, 1);
},
cls: function () {
gl.clear(16384);
},
img: function (texture, x, y, w, h, r, tx, ty, sx, sy, u0, v0, u1, v1) {
var x0 = x;
var y0 = y;
var x1 = x + w;
var y1 = y + h;
var x2 = x;
var y2 = y + h;
var x3 = x + w;
var y3 = y;
var offset = 0;
var argb = renderer.col;
if (texture != currentTexture || count + 1 >= MAX_BATCH) {
glBufferSubData(34962, 0, vertexData);
glDrawElements(4, count * VERTICES_PER_QUAD, 5123, 0);
count = 0;
if (texture != currentTexture) {
// textureBleedingFix = (0.0039 * w) / 16 / texture.scale;
// textureBleedingFix = (0.0025 * w) / 16 / texture.scale;
// 8... 0,00125
// textureBleedingFix = 0.00125 * (w / texture.scale / 8);
// 0,00125 * (w / 8)
// 16... 0,0025
// 48 (16*3)... 0,0009
currentTexture = texture;
glBindTexture(3553, currentTexture);
}
}
offset = count * VERTEX_SIZE;
// Vertex Order:
// rotation | translation | scale | position | uv | color
// Vertex 1
vPositionData[offset++] = r;
vPositionData[offset++] = tx - textureBleedingFix;
vPositionData[offset++] = ty - textureBleedingFix;
vPositionData[offset++] = sx;
vPositionData[offset++] = sy;
vPositionData[offset++] = x0;
vPositionData[offset++] = y0;
vPositionData[offset++] = u0 + textureBleedingFix;
vPositionData[offset++] = v0 + textureBleedingFix;
vColorData[offset++] = argb;
// Vertex 2
vPositionData[offset++] = r;
vPositionData[offset++] = tx + textureBleedingFix;
vPositionData[offset++] = ty + textureBleedingFix;
vPositionData[offset++] = sx;
vPositionData[offset++] = sy;
vPositionData[offset++] = x1;
vPositionData[offset++] = y1;
vPositionData[offset++] = u1 - textureBleedingFix;
vPositionData[offset++] = v1 - textureBleedingFix;
vColorData[offset++] = argb;
// Vertex 3
vPositionData[offset++] = r;
vPositionData[offset++] = tx - textureBleedingFix;
vPositionData[offset++] = ty + textureBleedingFix;
vPositionData[offset++] = sx;
vPositionData[offset++] = sy;
vPositionData[offset++] = x2;
vPositionData[offset++] = y2;
vPositionData[offset++] = u0 + textureBleedingFix;
vPositionData[offset++] = v1 - textureBleedingFix;
vColorData[offset++] = argb;
// Vertex 4
vPositionData[offset++] = r;
vPositionData[offset++] = tx + textureBleedingFix;
vPositionData[offset++] = ty - textureBleedingFix;
vPositionData[offset++] = sx;
vPositionData[offset++] = sy;
vPositionData[offset++] = x3;
vPositionData[offset++] = y3;
vPositionData[offset++] = u1 - textureBleedingFix;
vPositionData[offset++] = v0 + textureBleedingFix;
vColorData[offset++] = argb;
if (++count >= MAX_BATCH) {
glBufferSubData(34962, 0, vertexData);
glDrawElements(4, count * VERTICES_PER_QUAD, 5123, 0);
count = 0;
}
},
flush: function () {
if (count == 0) {
return;
}
glBufferSubData(34962, 0, vPositionData.subarray(0, count * VERTEX_SIZE));
glDrawElements(4, count * VERTICES_PER_QUAD, 5123, 0);
count = 0;
},
};
renderer.bkg(0, 0, 0);
return renderer;
};
return RendererFactorySingleton;
}());
exports.RendererFactory = new RendererFactorySingleton();