UNPKG

migalib

Version:

MIGAlib - MInimal GAme LIBrary

259 lines (258 loc) 10.9 kB
"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();