@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
242 lines • 22.4 kB
JavaScript
import { tgdCodeStringify } from "./../shader/code.js";
/**
* This class helps to manage a WebGLProgram.
* It will report meaninfull errors and help you with
* the uniforms.
*/
export class TgdProgram {
constructor(gl, code) {
var _a;
this.gl = gl;
this.code = code;
const prg = gl.createProgram();
if (!prg)
throw new Error("Unable to create WebGLProgram!");
const vert = tgdCodeStringify(code.vert);
const vertShader = this.createShader("VERTEX_SHADER", vert);
gl.attachShader(prg, vertShader);
const frag = tgdCodeStringify(code.frag);
const fragShader = this.createShader("FRAGMENT_SHADER", frag);
gl.attachShader(prg, fragShader);
gl.linkProgram(prg);
if (!gl.getProgramParameter(prg, gl.LINK_STATUS)) {
const info = (_a = gl.getProgramInfoLog(prg)) !== null && _a !== void 0 ? _a : "";
console.warn(info);
const errorLines = getErrorLines(info);
const cause = [
logCode("Vertex Shader", vert, errorLines),
logCode("Fragment Shader", frag, errorLines),
].join("\n");
throw new Error(cause);
}
this.program = prg;
this.shaders = [vertShader, fragShader];
this.uniformsLocations = this.getUniformsLocations();
gl.detachShader(prg, vertShader);
gl.deleteShader(vertShader);
gl.detachShader(prg, fragShader);
gl.deleteShader(fragShader);
}
toCode({ indent = "" } = {}) {
const lines = [
`function createProgram(gl: WebGL2RenderingContext) {`,
` const prg = gl.createProgram()`,
` const vertexShader = gl.createShader(gl.VERTEX_SHADER)`,
` gl.shaderSource(vertexShader, \`${tgdCodeStringify(this.code.vert)}\`)`,
` gl.compileShader(vertexShader)`,
` const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)`,
` gl.shaderSource(fragmentShader, \`${tgdCodeStringify(this.code.frag)}\`)`,
` gl.compileShader(fragmentShader)`,
` gl.attachShader(prg, vertexShader)`,
` gl.attachShader(prg, fragmentShader)`,
` gl.linkProgram(prg)`,
` return prg`,
`}`,
];
return lines.map(line => `${indent}${line}`).join("\n");
}
hasAttribute(name) {
const { gl, program } = this;
const loc = gl.getAttribLocation(program, name);
return loc >= 0;
}
getAttribLocation(name) {
const { gl, program } = this;
const loc = gl.getAttribLocation(program, name);
if (loc < 0) {
throw new Error(`Attribute "${name}" not found!`);
}
return loc;
}
getUniformLocation(name) {
const { uniformsLocations } = this;
const names = Object.keys(uniformsLocations);
if (name.length === 0) {
console.warn(`Uniform "${name}" has not been found: there is no active uniform in this program!`);
return 0;
}
const location = uniformsLocations[name];
if (!location) {
console.warn(`No active uniform found with name "${name}"!\nAvailable names are: ${names.join(", ")}.`);
}
return location;
}
uniform1f(name, value) {
const { gl } = this;
gl.uniform1f(this.getUniformLocation(name), value);
}
uniform2f(name, x, y) {
const { gl } = this;
gl.uniform2f(this.getUniformLocation(name), x, y);
}
uniform3f(name, x, y, z) {
const { gl } = this;
gl.uniform3f(this.getUniformLocation(name), x, y, z);
}
uniform3fv(name, vec3) {
const { gl } = this;
gl.uniform3fv(this.getUniformLocation(name), vec3);
}
uniform4f(name, x, y, z, w) {
const { gl } = this;
gl.uniform4f(this.getUniformLocation(name), x, y, z, w);
}
uniform4fv(name, vec4) {
const { gl } = this;
gl.uniform4fv(this.getUniformLocation(name), vec4);
}
uniform1i(name, value) {
const { gl } = this;
gl.uniform1i(this.getUniformLocation(name), value);
}
uniform2i(name, x, y) {
const { gl } = this;
gl.uniform2i(this.getUniformLocation(name), x, y);
}
uniform3i(name, x, y, z) {
const { gl } = this;
gl.uniform3i(this.getUniformLocation(name), x, y, z);
}
uniform4i(name, x, y, z, w) {
const { gl } = this;
gl.uniform4i(this.getUniformLocation(name), x, y, z, w);
}
uniform1ui(name, value) {
const { gl } = this;
gl.uniform1ui(this.getUniformLocation(name), value);
}
uniform2ui(name, x, y) {
const { gl } = this;
gl.uniform2ui(this.getUniformLocation(name), x, y);
}
uniform3ui(name, x, y, z) {
const { gl } = this;
gl.uniform3ui(this.getUniformLocation(name), x, y, z);
}
uniform4ui(name, x, y, z, w) {
const { gl } = this;
gl.uniform4ui(this.getUniformLocation(name), x, y, z, w);
}
uniformMatrix3fv(name, mat3) {
const { gl } = this;
gl.uniformMatrix3fv(this.getUniformLocation(name), false, mat3);
}
uniformMatrix4fv(name, mat4) {
const { gl } = this;
gl.uniformMatrix4fv(this.getUniformLocation(name), false, mat4);
}
/**
* Use the current program.
* This is equivalent to `gl.useProgram(program)`.
*/
use() {
const { gl, program } = this;
gl.useProgram(program);
}
delete() {
const { gl } = this;
for (const shader of this.shaders)
gl.deleteShader(shader);
gl.deleteProgram(this.program);
}
debug(caption = "TgdProgram") {
console.log(caption);
const { code } = this;
logCode("Vertex Shader", tgdCodeStringify(code.vert));
logCode("Fragment Shader", tgdCodeStringify(code.frag));
}
createShader(type, code) {
const { gl } = this;
const shader = gl.createShader(gl[type]);
if (!shader)
throw new Error(`Unable to create a WebGLShader of type "${type}"!`);
gl.shaderSource(shader, code);
gl.compileShader(shader);
const info = gl.getShaderInfoLog(shader);
if (info) {
console.error(`Error in ${type} code:`, info);
const errorLines = getErrorLines(info);
throw new Error(logCode(type, code, errorLines));
}
return shader;
}
getUniformsLocations() {
const { gl, program } = this;
const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
if (typeof count !== "number")
throw new Error("Unable to get the number of uniforms in a WebGLProgram!");
const uniforms = {};
for (let index = 0; index < count; index++) {
const uniform = gl.getActiveUniform(program, index);
if (!uniform)
continue;
const location = gl.getUniformLocation(program, uniform.name);
if (location === null)
throw new Error(`Unable to get location for uniform "${uniform.name}"!`);
uniforms[uniform.name] = location;
}
return uniforms;
}
}
const RX_ERROR_LINE = /^ERROR:[ \t]+([0-9]+):([0-9]+):/g;
function getErrorLines(message) {
const lines = [];
const messages = [];
for (const line of message.split("\n")) {
RX_ERROR_LINE.lastIndex = -1;
const match = RX_ERROR_LINE.exec(line);
if (match) {
lines.push(Number.parseInt(match[2], 10));
messages.push(line.slice(match[0].length).trim());
}
}
return { lines, messages };
}
function style(background, bold = false) {
return `color:#fff;background:${background};font-family:monospace;font-size:80%;font-weight:${bold ? "bolder" : "100"};margin:0;color:${bold ? "#777" : "#fff"}`;
}
function logCode(title, code, options) {
const { lines = [], messages = [] } = options !== null && options !== void 0 ? options : {};
const output = [title];
const codeLines = [`%c${title}`];
const styles = ["font-weight:bolder;font-size:120%"];
let hasError = false;
for (const [index, line] of code.split("\n").entries()) {
const lineNumber = index + 1;
const prefix = `${lineNumber}`.padStart(5, " ");
const background = lines.includes(lineNumber) ? "#f00" : "#000";
codeLines.push(`%c${prefix} %c${line}`);
output.push(`${prefix} ${line}`);
styles.push(style(background, true), style(background, false));
if (lines.includes(lineNumber)) {
hasError = true;
codeLines.push(`%c${messages[lines.indexOf(lineNumber)]}`);
output.push(`##### ${messages[lines.indexOf(lineNumber)]}`);
styles.push("color:#f33;background:#333;font-weight:bold");
console.error();
}
}
console.log(codeLines.join("\n"), ...styles);
return hasError ? output.join("\n") : "";
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZ3JhbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm9ncmFtL3Byb2dyYW0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFHbkQ7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBT25CLFlBQ29CLEVBQTBCLEVBQ3pCLElBQXVCOztRQUR4QixPQUFFLEdBQUYsRUFBRSxDQUF3QjtRQUN6QixTQUFJLEdBQUosSUFBSSxDQUFtQjtRQUV4QyxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDOUIsSUFBSSxDQUFDLEdBQUc7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUE7UUFFM0QsTUFBTSxJQUFJLEdBQUcsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3hDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxDQUFBO1FBQzNELEVBQUUsQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxDQUFBO1FBQ2hDLE1BQU0sSUFBSSxHQUFHLGdCQUFnQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUN4QyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxDQUFBO1FBQzdELEVBQUUsQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxDQUFBO1FBQ2hDLEVBQUUsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDbkIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUM7WUFDL0MsTUFBTSxJQUFJLEdBQUcsTUFBQSxFQUFFLENBQUMsaUJBQWlC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