@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
604 lines • 47.5 kB
JavaScript
import { TgdCameraPerspective } from "./../camera/index.js";
import { TgdConsole } from "./../debug/index.js";
import { TgdInputs } from "./../input/index.js";
import { TgdTime } from "./../time/index.js";
import { TgdEvent } from "../event/index.js";
import { TgdPainterGroup } from "../painter/group.js";
import { webglLookup } from "../utils/index.js";
import { TgdManagerAnimation } from "./animation/animation-manager.js";
import { Console } from "./console.js";
import { UniformBufferObjectsManager } from "./ubo-manager.js";
import { WebglParams } from "./webgl-params.js";
import { TgdExtensions } from "./extensions.js";
/**
* This class gives you a [WebGL2RenderingContext](https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext) for a given canvas,
* through its public readonly attribute `gl`.
*
* It also takes care of the canvas resizing and the animation frames.
*
* @example
* ```
* import { TgdContext, TgdPainterClear } from "@tgd"
*
* export function paint(canvas: HTMLCanvasElement) {
* const ctx = new TgdContext(canvas)
* const clear = new TgdPainterClear(ctx, { color: [1, 0.667, 0, 1] })
* ctx.add(clear)
* ctx.paint()
* }
* ```
*/
export class TgdContext extends TgdPainterGroup {
/**
* Ratio of the resolution in physical pixels to the resolution in CSS pixels
* for the current display device.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio
*/
static get devicePixelRatio() {
return globalThis.devicePixelRatio ?? 1;
}
/**
* @param canvas The canvas to which attach a WebGL2 context.
* @see {@link TgdContextOptions}
*/
constructor(canvas, options = {}) {
super();
this.canvas = canvas;
this.options = options;
/**
* TGD will write error and warning messages to the console
* in case of problems and if `verbose` is set to `true`.
*/
this.verbose = true;
this.console = new Console(this);
this.eventResize = new TgdEvent();
/**
* Dispatched when everything has been painted.
*/
this.eventPaint = new TgdEvent();
/**
* Dispatched before anything is painted.
*/
this.eventPaintEnter = new TgdEvent();
/**
* Dispathed everytime we play or pause the main animation loop (`TgdContext.play()`, `TgdContext.pause()`).
*/
this.eventPlayingChange = new TgdEvent();
/**
* When the browser decides to destroy the context.
* @see https://wikis.khronos.org/webgl/HandlingContextLost
*/
this.eventWebGLContextLost = new TgdEvent();
/**
* At the point that setupWebGLStateAndResources is called the browser
* has reset all state to the default WebGL state and all previously
* allocated resources are invalid. So, you need to re-create textures,
* buffers, framebuffers, renderbuffers, shaders, programs,
* and setup your state (clearColor, blendFunc, depthFunc, etc...)
* @see https://wikis.khronos.org/webgl/HandlingContextLost
*/
this.eventWebGLContextRestored = new TgdEvent();
this.resolution = 1;
this.uniformBufferObjects = new UniformBufferObjectsManager();
this._gl = null;
/**
* If this function is set, it will be called once at the end of the next repaint.
* This is useful for snapshots.
*/
this.doSnapshot = null;
this._camera = new TgdCameraPerspective({
transfo: { distance: 10 },
far: 100,
near: 0.1,
fovy: Math.PI / 8,
zoom: 1,
});
this._width = 0;
this._height = 0;
this._fps = 0;
this._aspectRatio = 1;
this._aspectRatioInverse = 1;
this.paintingIsOngoing = false;
// We need to start another paiting after the current one is finished
this.paintingIsQueued = false;
this.isPlaying = false;
this.requestAnimationFrame = -1;
// Last time the context has been painted.
this.lastTimeInSec = -1;
this.animationManager = new TgdManagerAnimation(this);
// Used to store result of gl.readPixels() for one pixel.
this.readPixelColor = new Uint8Array(4);
this.oneTimePainters = new Set();
/**
* When you need a painter to be painted only one time.
*
* These painters will be painted before all the recurrent ones during next repaint.
* The main purpose of this function is to use it with framebuffers that will
* update textures that could be used in normal paintings.
*/
this.paintOneTime = (...painters) => {
for (const painter of painters) {
this.oneTimePainters.add(painter);
}
this.paint();
};
/**
* Trigger the painters to render the scene.
*/
this.paint = () => {
if (this.paintingIsOngoing) {
this.paintingIsQueued = true;
}
else {
this.paintingIsQueued = false;
this.paintingIsOngoing = true;
globalThis.cancelAnimationFrame(this.requestAnimationFrame);
this.requestAnimationFrame = globalThis.requestAnimationFrame(this.actualPaint);
}
};
this.actualPaint = (time) => {
const timeInSec = time * 1e-3;
if (this.lastTimeInSec < 0) {
this.lastTimeInSec = timeInSec;
this.paintingIsOngoing = false;
this.paintingIsQueued = false;
// First frame, let's skip it to get better timing.
this.paint();
return;
}
try {
const { gl } = this;
this.virtualTime.update(this);
this.setCurrentSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
this.eventPaintEnter.dispatch(this);
const delayInSec = timeInSec - this.lastTimeInSec;
this._fps = Math.round(1 / delayInSec);
this.lastTimeInSec = timeInSec;
for (const oneTimePainter of this.oneTimePainters) {
oneTimePainter.paint(timeInSec, delayInSec);
}
this.oneTimePainters.clear();
super.paint(timeInSec, delayInSec);
if (this.animationManager.paint(timeInSec) || this.paintingIsQueued || this.isPlaying) {
this.paintingIsOngoing = false;
this.paint();
}
this.eventPaint.dispatch(this);
}
catch (error) {
this.console.error(error);
this.pause();
}
finally {
this.paintingIsOngoing = false;
this.doSnapshot?.();
}
};
this.createWebGLContext = () => {
const { canvas, options } = this;
const gl = canvas.getContext("webgl2", options);
if (!gl)
throw new Error("Unable to create a WebGL2 context!");
this._gl = gl;
gl.canvas.addEventListener("webglcontextlost", (evt) => {
// @see https://wikis.khronos.org/webgl/HandlingContextLost
evt.preventDefault();
this.console.error("[TgdContext] WebGL context has been lost!", evt instanceof WebGLContextEvent ? evt.statusMessage : evt);
this.pause();
super.delete();
this.eventWebGLContextLost.dispatch(this);
}, false);
gl.canvas.addEventListener("webglcontextrestored", () => {
this.console.info("[TgdContext] WebGL context has been restored.");
this.initialize?.(this);
this.eventWebGLContextRestored.dispatch(this);
}, false);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
this.resolution = options.resolution ?? 1;
if (this.resolution <= 0) {
this.resolution = TgdContext.devicePixelRatio ?? 1;
}
this.stateReset();
return gl;
};
this.verbose = options.verbose ?? true;
const gl = this.createWebGLContext();
this.extensions = new TgdExtensions(gl);
this.initialize = options.initialize;
canvas.addEventListener("webglcontextlost", (evt) => {
TgdConsole.debug({
text: "[TgdContext]",
color: "#fffe",
background: "#a00",
}, ` WebGL context has been lost! ${evt instanceof WebGLContextEvent ? evt.statusMessage : evt}`);
// @see https://wikis.khronos.org/webgl/HandlingContextLost
evt.preventDefault();
this.delete({ preserveContextLostEvents: true });
this.eventWebGLContextLost.dispatch(this);
}, false);
canvas.addEventListener("webglcontextrestored", () => {
TgdConsole.debug({
text: "[TgdContext]",
color: "#000e",
background: "#0f0",
}, " WebGL context has been restored");
const { initialize } = this;
if (initialize) {
this.createWebGLContext();
initialize(this);
}
this.eventWebGLContextRestored.dispatch(this);
}, false);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
this.resolution = options.resolution ?? 1;
if (this.resolution <= 0) {
this.resolution = TgdContext.devicePixelRatio ?? 1;
}
this.implementationColorReadFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
this.implementationColorReadType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
this._gl = gl;
this.observer = new ResizeObserver(() => {
const width = isOffscreen(canvas) ? canvas.width : canvas.clientWidth * this.resolution;
const height = isOffscreen(canvas) ? canvas.width : canvas.clientHeight * this.resolution;
const { onResize } = options;
if (onResize) {
if (!isOffscreen(canvas)) {
onResize(this, canvas.clientWidth, canvas.clientHeight);
}
}
else {
canvas.width = width;
canvas.height = height;
}
this.eventResize.dispatch({ width, height });
this.paint();
});
if (isOffscreen(canvas)) {
this.inputs = new TgdInputs();
}
else {
this.observer.observe(canvas);
this.inputs = new TgdInputs(canvas);
// Prevent system gestures.
canvas.style.touchAction = "none";
}
if (options.camera)
this._camera = options.camera;
this.name = options.name ?? `Context#${TgdContext.incrementalId++}`;
this.stateReset();
this.webglParams = new WebglParams(gl);
this.virtualTime = new TgdTime();
this.console.debug(`[TgdContext/${this.name}] New:`, options);
}
viewportExec(action, viewport) {
const { webglParams, camera } = this;
const savedWidth = this.width;
const savedHeight = this.height;
const savedViewport = webglParams.viewport;
const savedScissor = webglParams.scissor;
const savedScissorTest = webglParams.scissorTest;
const savedAspectRatio = this.width / this.height;
const savedAspectRatioInverse = 1 / savedAspectRatio;
const { x = 0, y = 0, width = savedWidth, height = savedHeight } = viewport;
this.width = width;
this.height = height;
this._aspectRatio = width / height;
this._aspectRatioInverse = 1 / this._aspectRatio;
webglParams.setViewport(x, y, width, height);
webglParams.scissorTest = true;
webglParams.scissor = [x, y, width, height];
if (camera) {
camera.screenWidth = width;
camera.screenHeight = height;
}
action();
if (camera) {
camera.screenWidth = savedWidth;
camera.screenHeight = savedHeight;
}
webglParams.scissorTest = savedScissorTest;
webglParams.scissor = savedScissor;
webglParams.viewport = savedViewport;
this._aspectRatio = savedAspectRatio;
this._aspectRatioInverse = savedAspectRatioInverse;
this.width = savedWidth;
this.height = savedHeight;
}
get gl() {
if (!this._gl) {
throw new Error(`[TgdContext] This context has been deleted: ${this.name}!`);
}
return this._gl;
}
get fps() {
return this._fps;
}
get time() {
return this.lastTimeInSec;
}
get camera() {
return this._camera;
}
set camera(camera) {
if (camera === this._camera)
return;
this._camera = camera;
camera.screenWidth = this.width;
camera.screenHeight = this.height;
}
/**
* Check if the last WebGL command has returned an error.
* If an error has been found, output `caption` to the console (if verbose is true)
* and execute `action()`.
* Do not use this function in a loop because it is slow.
* @returns `true` is an error has been detected.
*/
checkError(caption, action) {
const { gl } = this;
const error = gl.getError();
if (error !== gl.NO_ERROR && error !== gl.CONTEXT_LOST_WEBGL) {
this.console.error(`WebGL Error in ${caption}:`, webglLookup(error));
action?.();
return true;
}
return false;
}
animSchedule(...animations) {
const result = [];
let delay = 0;
for (const animation of animations) {
const duration = animation.duration + (animation.delay ?? 0);
animation.delay = delay + (animation.delay ?? 0);
delay += duration;
result.push(this.animationManager.schedule(animation));
}
this.paint();
return result;
}
animCancel(animation) {
this.animationManager.cancel(animation);
}
animCancelArray(animations) {
for (const animation of animations)
this.animationManager.cancel(animation);
}
animDebug(caption) {
this.animationManager.debug(caption);
}
get width() {
return this._width;
}
set width(width) {
this._width = width;
}
get height() {
return this._height;
}
set height(height) {
this._height = height;
}
get aspectRatio() {
return this._aspectRatio;
}
get aspectRatioInverse() {
return this._aspectRatioInverse;
}
set aspectRatio(aspectRatio) {
this._aspectRatio = aspectRatio;
this._aspectRatioInverse = 1 / aspectRatio;
}
/**
* Is the animation playing?
*/
get playing() {
return this.isPlaying;
}
/**
* If `playing` is true, the method `paint()` will be called
* for every animation frame.
* @see paint()
*/
set playing(value) {
if (value === this.isPlaying)
return;
if (!value) {
this.paintingIsOngoing = false;
this.paintingIsQueued = false;
globalThis.cancelAnimationFrame(this.requestAnimationFrame);
this.requestAnimationFrame = -1;
}
this.isPlaying = value;
this.eventPlayingChange.dispatch(value);
/**
* Even when pausing, we want to paint a last time.
* This will be helpful for TgdTime, for instance.
*/
this.paint();
}
/**
* Start the animation.
* You can achieve the same result with `context.playing = true`.
*
* @see playing
*/
play() {
this.playing = true;
}
/**
* Pause the animation.
* You can achieve the same result with `context.playing = false`.
*
* @see playing
*/
pause() {
this.playing = false;
}
takeSnapshot() {
const { canvas } = this;
const img = new Image();
return new Promise((resolve) => {
const blobToImage = (blob) => {
if (!blob) {
resolve(img);
return;
}
const url = URL.createObjectURL(blob);
img.src = url;
// eslint-disable-next-line unicorn/prefer-add-event-listener
img.onload = () => resolve(img);
};
this.doSnapshot = () => {
if (isOffscreen(canvas)) {
canvas
.convertToBlob()
.then(blobToImage)
.catch(() => resolve(img));
}
else {
canvas.toBlob(blobToImage);
}
};
});
}
lookupWebglConstant(value) {
const { gl } = this;
for (const key in gl) {
if (gl[key] === value)
return key;
}
return `Unknown gl[${value}]`;
}
/**
* Helper to test a context lost situation.
* @param restorationDelayInMilliseconds Time, in milliseconds, before the context is restored.
*/
loseContext(restorationDelayInMilliseconds = 1000) {
const ext = this.extensions.WEBGL_lose_context;
if (ext) {
ext.loseContext();
globalThis.setTimeout(() => {
ext.restoreContext();
}, restorationDelayInMilliseconds);
}
}
/**
* Most of the painters rely on the current viewport which is based on the canvas size.
* But if you want to paint in a framebuffer, you may want to use the texture widt/height
* instead.
*/
paintInCustomSize(width, height, paint) {
const { width: savedWidth, height: savedHeight } = this;
this.setCurrentSize(width, height);
paint();
this.setCurrentSize(savedWidth, savedHeight);
}
setCurrentSize(width, height) {
this.width = width;
this.height = height;
this.camera.screenWidth = this.width;
this.camera.screenHeight = this.height;
this.aspectRatio = this.width / this.height;
this.webglParams.setViewport(0, 0, this.width, this.height);
}
now() {
return Date.now() * 1e-3;
}
/**
* Read the color of a pixel as a Uint8Array of size 4.
*
* Don't forget to use `preserveDrawingBuffer: true` in the creation options
* of the WebGL context.
*
* @param xScreen From -1 (left) to +1 (right)
* @param yScreen From -1 (bottom) to +1 (top)
* @returns The color of a pixel
*/
readPixel(xScreen, yScreen) {
const { gl } = this;
const pixelX = Math.round(0.5 * (xScreen + 1) * gl.drawingBufferWidth);
const pixelY = Math.round(0.5 * (yScreen + 1) * gl.drawingBufferHeight);
gl.readPixels(pixelX, pixelY, 1, // width
1, // height
gl.RGBA, // format
gl.UNSIGNED_BYTE, // type
this.readPixelColor);
return this.readPixelColor;
}
delete({ preserveContextLostEvents = false, } = {}) {
this.eventPaint.removeAllListeners();
if (!preserveContextLostEvents) {
this.eventWebGLContextLost.removeAllListeners();
this.eventWebGLContextRestored.removeAllListeners();
}
this.inputs.keyboard.detach();
this.inputs.pointer.detach();
this.pause();
if (!isOffscreen(this.canvas)) {
this.observer.unobserve(this.canvas);
}
super.delete();
this._gl = null;
this.console.debug(`[TgdContext/${this.name}] Delete`);
}
stateReset() {
const { gl } = this;
const numberAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
const temporary = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, temporary);
for (let ii = 0; ii < numberAttribs; ++ii) {
gl.disableVertexAttribArray(ii);
gl.vertexAttribPointer(ii, 4, gl.FLOAT, false, 0, 0);
gl.vertexAttrib1f(ii, 0);
}
gl.deleteBuffer(temporary);
const numberTextureUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
for (let ii = 0; ii < numberTextureUnits; ++ii) {
gl.activeTexture(gl.TEXTURE0 + ii);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
gl.bindTexture(gl.TEXTURE_2D, null);
}
gl.activeTexture(gl.TEXTURE0);
gl.useProgram(null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.disable(gl.BLEND);
gl.disable(gl.CULL_FACE);
gl.disable(gl.DEPTH_TEST);
gl.disable(gl.DITHER);
gl.disable(gl.SCISSOR_TEST);
gl.blendColor(0, 0, 0, 0);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.ONE, gl.ZERO);
gl.clearColor(0, 0, 0, 0);
gl.clearDepth(1);
gl.clearStencil(-1);
gl.colorMask(true, true, true, true);
gl.cullFace(gl.BACK);
gl.depthFunc(gl.LESS);
gl.depthMask(true);
gl.depthRange(0, 1);
gl.frontFace(gl.CCW);
gl.hint(gl.GENERATE_MIPMAP_HINT, gl.DONT_CARE);
gl.lineWidth(1);
gl.pixelStorei(gl.PACK_ALIGNMENT, 4);
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
gl.polygonOffset(0, 0);
gl.sampleCoverage(1, false);
gl.scissor(0, 0, gl.canvas.width, gl.canvas.height);
gl.stencilFunc(gl.ALWAYS, 0, 0xffffffff);
gl.stencilMask(0xffffffff);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
return gl;
}
}
TgdContext.incrementalId = 1;
function isOffscreen(canvas) {
return canvas instanceof OffscreenCanvas;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb250ZXh0L2NvbnRleHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFrQixvQkFBb0IsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUNsRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBQ3ZDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDdEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUVuQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBQ25DLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUVsRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBQ3RDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLCtCQUErQixDQUFBO0FBQ25FLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDbkMsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQzNELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBaUQ1Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxNQUFNLE9BQU8sVUFBVyxTQUFRLGVBQWU7SUFFM0M7Ozs7T0FJRztJQUNJLE1BQU0sS0FBSyxnQkFBZ0I7UUFDOUIsT0FBTyxVQUFVLENBQUMsZ0JBQWdCLElBQUksQ0FBQyxDQUFBO0lBQzNDLENBQUM7SUE4RUQ7OztPQUdHO0lBQ0gsWUFDb0IsTUFBMkMsRUFDM0MsVUFBdUMsRUFBRTtRQUV6RCxLQUFLLEVBQUUsQ0FBQTtRQUhTLFdBQU0sR0FBTixNQUFNLENBQXFDO1FBQzNDLFlBQU8sR0FBUCxPQUFPLENBQWtDO1FBaEY3RDs7O1dB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