@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
335 lines (331 loc) • 30.5 kB
JavaScript
import { TgdConsole } from "./../debug/index.js";
import { TgdShaderFragment, TgdShaderVertex } from "./../shader/index.js";
import { tgdCodeStringify } from "./../shader/index.js";
/**
* This class helps to manage a WebGLProgram.
* It will report meaninfull errors and help you with
* the uniforms.
*/
export class TgdProgram {
constructor(gl, options) {
this.gl = gl;
this.options = options;
const prg = gl.createProgram();
if (!prg)
throw new Error("Unable to create WebGLProgram!");
this.name = options.name ?? `TgdProgram#${TgdProgram.id++}`;
const { vert, frag } = checkCompatibilityBetweenShaders(options);
this.vert = vert;
this.frag = frag;
const vertShader = this.createShader("VERTEX_SHADER", vert);
gl.attachShader(prg, vertShader);
const fragShader = this.createShader("FRAGMENT_SHADER", frag);
gl.attachShader(prg, fragShader);
const { transformFeedback } = options;
if (transformFeedback) {
const bufferMode = Array.isArray(transformFeedback)
? gl.INTERLEAVED_ATTRIBS
: gl[transformFeedback.bufferMode];
const varyings = Array.isArray(transformFeedback) ? transformFeedback : transformFeedback.varyings;
gl.transformFeedbackVaryings(prg, varyings, bufferMode);
}
gl.linkProgram(prg);
gl.validateProgram(prg);
if (!gl.getProgramParameter(prg, gl.LINK_STATUS) && !gl.isContextLost()) {
const info = gl.getProgramInfoLog(prg) ?? "";
console.error(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.vert)}\`)`,
` gl.compileShader(vertexShader)`,
` const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)`,
` gl.shaderSource(fragmentShader, \`${tgdCodeStringify(this.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.sort().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);
}
uniform2fv(name, vec2) {
const { gl } = this;
gl.uniform2fv(this.getUniformLocation(name), vec2);
}
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);
}
uniformMatrix2fv(name, mat2) {
const { gl } = this;
gl.uniformMatrix2fv(this.getUniformLocation(name), false, mat2);
}
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) {
const { gl, program } = this;
console.debug(caption ?? this.name);
const contextLost = gl.isContextLost();
const items = [
{ text: "Context lost: " },
{
text: contextLost ? "TRUE" : "FALSE",
color: contextLost ? "#0F0" : "#f00",
},
"\n",
];
const params = [
[gl.DELETE_STATUS, "Flagged for deletion"],
[gl.LINK_STATUS, "Last link operation was successful"],
[gl.VALIDATE_STATUS, "Last validation operation was successful"],
[gl.ATTACHED_SHADERS, "Number of attached shaders"],
[gl.ACTIVE_ATTRIBUTES, "Number of active attribute variables"],
[gl.ACTIVE_UNIFORMS, "Number of active uniforms"],
];
for (const [id, label] of params) {
items.push(`${label}: `);
const param = gl.getProgramParameter(program, id);
if (param === true)
items.push({ text: "TRUE", color: "#0f0" });
else if (param === false)
items.push({ text: "FALSE", color: "#f00" });
else
items.push({ text: JSON.stringify(param), color: "#09f" });
items.push("\n");
}
TgdConsole.debug(...items);
logCode("Vertex Shader", tgdCodeStringify(this.vert));
logCode("Fragment Shader", tgdCodeStringify(this.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") {
if (gl.isContextLost())
return {};
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) {
// this.debug()
// console.warn(
// `Unable to get location for uniform "${uniform.name}" (size: ${uniform.size}, type: ${uniform.type})!`
// )
}
else {
uniforms[uniform.name] = location;
}
}
return uniforms;
}
}
TgdProgram.id = 1;
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 ?? {};
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.debug(codeLines.join("\n"), ...styles);
return hasError ? output.join("\n") : "No error.";
}
function checkCompatibilityBetweenShaders({ vert, frag, }) {
if (vert instanceof TgdShaderVertex && frag instanceof TgdShaderFragment) {
if (!frag.varying || Object.keys(frag.varying).length === 0) {
frag.varying = vert.varying;
}
else {
const vertVarying = Object.keys(vert.varying)
.sort()
.map((key) => ` ${key}:${vert.varying[key]} `)
.join("\n");
const fragVarying = Object.keys(frag.varying)
.sort()
.map((key) => ` ${key}:${frag.varying[key]} `)
.join("\n");
if (vertVarying !== fragVarying) {
throw new Error(`[TgdProgram] Different varying for vertex and fragments shaders!
Vertex shader:
${vertVarying}
Fragment shader:
${fragVarying}
To avoid such mistake, just don't specify the varyings for the fragment shader,
and we will use the same as the vertex shader.
`);
}
}
}
const vertCode = vert instanceof TgdShaderVertex ? vert.code : tgdCodeStringify(vert);
const fragCode = frag instanceof TgdShaderFragment ? frag.code : tgdCodeStringify(frag);
return { vert: vertCode, frag: fragCode };
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZ3JhbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm9ncmFtL3Byb2dyYW0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBa0IsTUFBTSxZQUFZLENBQUE7QUFFdkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGVBQWUsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUNoRSxPQUFPLEVBQWUsZ0JBQWdCLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFHM0Q7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBWW5CLFlBQ29CLEVBQTBCLEVBQ3pCLE9BQTBCO1FBRDNCLE9BQUUsR0FBRixFQUFFLENBQXdCO1FBQ3pCLFlBQU8sR0FBUCxPQUFPLENBQW1CO1FBRTNDLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxhQUFhLEVBQUUsQ0FBQTtRQUM5QixJQUFJLENBQUMsR0FBRztZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQTtRQUUzRCxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLElBQUksY0FBYyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQTtRQUMzRCxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxHQUFHLGdDQUFnQyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQ2hFLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFBO1FBQ2hCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFBO1FBQ2hCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxDQUFBO1FBQzNELEVBQUUsQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxDQUFBO1FBQ2hDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFDN0QsRUFBRSxDQUFD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