@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
295 lines • 27.7 kB
JavaScript
import { TgdDataset } from "./../dataset/index.js";
import { TgdConsole } from "./../debug/index.js";
import { TgdProgram } from "./../program/index.js";
import { TgdShaderFragment, TgdShaderVertex, tgdCodeStringify, } from "./../shader/index.js";
import { ensureArray, tgdTextureRecordToUniforms, webglElementTypeFromTypedArray, webglLookup } from "./../utils/index.js";
import { TgdPainterLogic, TgdVertexArray } from "./../index.js";
import { TgdUniformBufferObject } from "./../uniform/uniform-buffer-object.js";
import { TgdPainter } from "./painter.js";
import { TgdPainterState } from "./state/index.js";
export class TgdPainterProgram extends TgdPainter {
constructor(context, { onEnter, onDelete, uniforms = {}, textures = {}, varying, vert, frag, dataset, elements, drawMode, state, elementsCount, elementsOffset, instancesCount, }) {
super();
this.context = context;
this.elementsCount = 0;
this.elementsOffset = 0;
this.instancesCount = 0;
this.uniformBlocks = [];
this.uniformBlocksToDelete = [];
this.internalPaint = (time, delta) => {
const { context, onEnter, textures, uniformBlocks, prg, vao, elementsType, elementsCount, elementsOffset, instancesCount, drawMode: mode, } = this;
const { gl } = context;
prg.use();
let unit = 0;
for (const name of Object.keys(textures)) {
const texture = textures[name];
texture.activate(unit++, prg, name);
}
onEnter?.(time, delta);
for (const block of uniformBlocks) {
block.updateData();
}
vao.bind();
if (this.hasElements) {
if (instancesCount > 0) {
gl.drawElementsInstanced(mode, elementsCount, elementsType, elementsOffset, instancesCount);
}
else {
gl.drawElements(mode, elementsCount, elementsType, elementsOffset);
}
}
else {
if (instancesCount > 0) {
gl.drawArraysInstanced(mode, elementsOffset, elementsCount, instancesCount);
}
else {
gl.drawArrays(mode, elementsOffset, elementsCount);
}
}
vao.unbind();
};
this.textures = textures;
this.onEnter = onEnter;
this.onDelete = onDelete;
const datasets = ensureArray(dataset).map((item) => {
if (item instanceof TgdDataset)
return item;
const attributesDefinition = {};
for (const attribName of Object.keys(item.attribs)) {
attributesDefinition[attribName] = item.attribs[attribName].type;
}
const ds = new TgdDataset(attributesDefinition, item);
for (const attribName of Object.keys(item.attribs)) {
ds.set(attribName, item.attribs[attribName].data);
}
return ds;
});
this.drawMode = typeof drawMode === "number" ? drawMode : context.gl[drawMode];
const uniformsHeader = ensureArray(this.uniformsToCode(uniforms));
const uniformsForTextures = tgdTextureRecordToUniforms(textures);
const vertexShader = new TgdShaderVertex({
...vert,
uniforms: uniformsForTextures,
attributes: resolveAttributesFromDataset(datasets),
header: [...uniformsHeader, ...ensureArray(vert.header)],
varying,
});
const fragmentShader = new TgdShaderFragment({
...frag,
uniforms: uniformsForTextures,
header: [...uniformsHeader, ...ensureArray(vert.header)],
varying,
});
const program = new TgdProgram(context.gl, {
vert: vertexShader,
frag: fragmentShader,
});
this.prg = program;
program.use();
const samplerNames = Object.keys(textures);
for (let unit = 0; unit < samplerNames.length; unit++) {
const uniformName = samplerNames[unit];
const texture = textures[uniformName];
texture.activate(unit, program, uniformName);
}
const vao = new TgdVertexArray(context.gl, program, datasets, elements);
this.vao = vao;
this.painterState = new TgdPainterState(context, {
...state,
children: [new TgdPainterLogic(this.internalPaint)],
});
this.elementsCount = elementsCount ?? resolveElementsCount(datasets, elements);
this.elementsOffset = elementsOffset ?? 0;
this.instancesCount = instancesCount ?? resolveInstancesCount(datasets);
this.hasElements = !!elements;
this.elementsType = elements ? webglElementTypeFromTypedArray(elements) : 0;
const setBindingPoints = new Set();
Object.keys(uniforms).forEach((blockName, index) => {
const block = this.uniformBlocks[index];
if (setBindingPoints.has(block.bindingPoint)) {
const code = Object.keys(uniforms).map((blockName, index) => this.uniformBlocks[index].toShaderCode(blockName));
throw new Error(`[TgdPainterProgram] Uniform blocks must have distincts binding points!\n${tgdCodeStringify(code)}`);
}
setBindingPoints.add(block.bindingPoint);
block.bindToProgram(program, blockName);
});
}
setElements(elements) {
this.vao.updateElements(elements);
this.elementsCount = elements.length;
}
/**
* Update the values of an attribute of a dataset and resolve the counts.
*/
setAttributeValues(dataset, attribName, values) {
try {
dataset.set(attribName, values);
this.vao.updateDataset(dataset);
if (dataset.divisor > 0) {
this.instancesCount = values.length;
}
else {
const { gl } = this.context;
switch (this.drawMode) {
case gl.POINTS:
return values.length;
case gl.LINES:
return Math.floor(values.length / 2);
case gl.LINE_LOOP:
return values.length;
case gl.LINE_STRIP:
return values.length - 1;
case gl.TRIANGLES:
return Math.floor(values.length / 3);
case gl.TRIANGLE_FAN:
case gl.TRIANGLE_STRIP:
return values.length - 2;
default:
throw new Error(`Unknown drawMode: ${webglLookup(this.drawMode)}!`);
}
}
}
catch (error) {
const message = error instanceof Error ? error.message : JSON.stringify(error);
throw new Error(`[TgdPainterProgram] Unable to set attribute values of dataset "${dataset.name}" for "${this.name}"!\n${message}`);
}
}
delete() {
this.onDelete?.();
for (const block of this.uniformBlocksToDelete) {
block.delete();
}
this.prg.delete();
this.vao.delete();
}
paint(time, delta) {
this.painterState.paint(time, delta);
}
debug(caption) {
console.debug(caption ?? this.name);
console.debug({
drawMode: webglLookup(this.drawMode),
elementsCount: this.elementsCount,
elementsOffset: this.elementsOffset,
instancesCount: this.instancesCount,
});
this.vao.debug();
}
uniformsToCode(uniforms) {
const code = [];
const setNames = new Set();
const setDuplicated = new Set();
const names = {};
for (const blockName of Object.keys(uniforms)) {
const block = this.resolveUniformBlock(uniforms[blockName]);
this.uniformBlocks.push(block);
names[blockName] = block.names;
code.push(...ensureArray(block.toShaderCode(blockName)));
for (const name of block.names) {
if (setNames.has(name))
setDuplicated.add(name);
else
setNames.add(name);
}
}
if (setDuplicated.size > 0) {
// There is a duplicate!
const out = new TgdConsole({
text: "[TgdPainterProgram] You have duplicated names in your uniform blocks:\n",
color: "#f33",
});
for (const blockName of Object.keys(names)) {
out.add(` ${blockName}`, { bold: true }).add(": ");
names[blockName].forEach((name, index) => {
if (index > 0)
out.add(", ");
out.add(name, setDuplicated.has(name)
? {
bold: true,
color: "#f33",
}
: undefined);
});
out.nl();
}
out.error();
}
return code;
}
resolveUniformBlock(obj) {
if (obj instanceof TgdUniformBufferObject)
return obj;
return new TgdUniformBufferObject(this.context, obj);
}
}
function resolveAttributesFromDataset(datasets) {
const attributes = {};
const setNames = new Set();
const setDuplicated = new Set();
for (const dataset of datasets) {
for (const name of dataset.attributesNames) {
if (setNames.has(name))
setDuplicated.add(name);
else
setNames.add(name);
attributes[name] = dataset.getType(name);
}
}
if (setDuplicated.size > 0) {
// There is a duplicate!
const out = new TgdConsole({
text: "[TgdPainterProgram] You have duplicated names in your datasets:\n",
color: "#f33",
});
for (const dataset of datasets) {
out.add(` ${dataset.name}`, { bold: true }).add(": ");
dataset.attributesNames.forEach((name, index) => {
if (index > 0)
out.add(", ");
out.add(name, setDuplicated.has(name)
? {
bold: true,
color: "#f33",
}
: undefined);
});
out.nl();
}
out.error();
}
return attributes;
}
function resolveElementsCount(datasets, elements) {
if (elements)
return elements.length;
const counts = datasets.filter((ds) => ds.divisor === 0).map((ds) => ds.count);
if (counts.length === 0) {
throw new Error("[TgdPainterProgram] You must give at least one Dataset with divisor 0 in the constructor!\nOr you can specify elementsCount.");
}
if (counts.length === 1)
return counts[0];
counts.sort();
const [first] = counts;
const last = counts[counts.length - 1];
if (first === last)
return first;
throw new Error(`[TgdPainterPogram] I cannot resolve elementsCount because your datasets have different counts!\n${datasets
.filter((ds) => ds.divisor === 0)
.map((ds) => ` ${ds.name}: count == ${ds.count}`)}`);
}
function resolveInstancesCount(datasets) {
const counts = datasets.filter((ds) => ds.divisor > 0).map((ds) => ds.count / ds.divisor);
if (counts.length === 0)
return 0;
if (counts.length === 1)
return counts[0];
counts.sort();
const [first] = counts;
const last = counts[counts.length - 1];
if (first === last)
return first;
throw new Error(`[TgdPainterPogram] I cannot resolve elementsCount because your instance datasets have different counts!\n${datasets
.filter((ds) => ds.divisor > 0)
.map((ds) => ` ${ds.name}: count == ${ds.count} / ${ds.divisor} == ${ds.count / ds.divisor}`)}`);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZ3JhbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYWludGVyL3Byb2dyYW0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFVBQVUsRUFBMEUsTUFBTSxjQUFjLENBQUE7QUFDakgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUN2QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBQ3pDLE9BQU8sRUFJSCxpQkFBaUIsRUFDakIsZUFBZSxFQUNmLGdCQUFnQixHQUNuQixNQUFNLGFBQWEsQ0FBQTtBQUdwQixPQUFPLEVBQUUsV0FBVyxFQUFFLDBCQUEwQixFQUFFLDhCQUE4QixFQUFFLFdBQVcsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUNqSCxPQUFPLEVBQUUsZUFBZSxFQUFnQyxjQUFjLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUM5RixPQUFPLEVBQUUsc0JBQXNCLEVBQXNDLE1BQU0sb0NBQW9DLENBQUE7QUFDL0csT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUN0QyxPQUFPLEVBQUUsZUFBZSxFQUErQixNQUFNLFNBQVMsQ0FBQTtBQThEdEUsTUFBTSxPQUFPLGlCQUFrQixTQUFRLFVBQVU7SUFpQjdDLFlBQ29CLE9BQW1CLEVBQ25DLEVBQ0ksT0FBTyxFQUNQLFFBQVEsRUFDUixRQUFRLEdBQUcsRUFBRSxFQUNiLFFBQVEsR0FBRyxFQUFFLEVBQ2IsT0FBTyxFQUNQLElBQUksRUFDSixJQUFJLEVBQ0osT0FBTyxFQUNQLFFBQVEsRUFDUixRQUFRLEVBQ1IsS0FBSyxFQUNMLGFBQWEsRUFDYixjQUFjLEVBQ2QsY0FBYyxHQUNTO1FBRTNCLEtBQUssRUFBRSxDQUFBO1FBbEJTLFlBQU8sR0FBUCxPQUFPLENBQVk7UUFqQmhDLGtCQUFhLEdBQUcsQ0FBQyxDQUFBO1FBQ2pCLG1CQUFjLEdBQUcsQ0FBQyxDQUFBO1FBQ2xCLG1CQUFj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