Update ImageCompositor.ts
This commit is contained in:
parent
4d51ed7faf
commit
30f5387b3b
|
|
@ -5,15 +5,14 @@
|
||||||
|
|
||||||
import { createTexture, initShaderProgram } from '../webgl.js';
|
import { createTexture, initShaderProgram } from '../webgl.js';
|
||||||
|
|
||||||
export type ImageCompositorFxParamDefs = Record<string, any>;
|
export type ImageCompositorProgramParamDefs = Record<string, any>;
|
||||||
|
|
||||||
export function defineImageCompositorFx<ID extends string, PS extends ImageCompositorFxParamDefs, US extends string[]>(fx: ImageCompositorFx<ID, PS, US>) {
|
export function defineImageCompositorFx<PS extends ImageCompositorProgramParamDefs, US extends string[]>(program: ImageCompositorProgram<PS, US>) {
|
||||||
return fx;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ImageCompositorFx<ID extends string = string, PS extends ImageCompositorFxParamDefs = ImageCompositorFxParamDefs, US extends string[] = string[]> = {
|
export type ImageCompositorProgram<PS extends ImageCompositorProgramParamDefs = ImageCompositorProgramParamDefs, US extends string[] = string[]> = {
|
||||||
id: ID;
|
id: string;
|
||||||
name: string;
|
|
||||||
shader: string;
|
shader: string;
|
||||||
uniforms: US;
|
uniforms: US;
|
||||||
params: PS,
|
params: PS,
|
||||||
|
|
@ -30,10 +29,12 @@ export type ImageCompositorFx<ID extends string = string, PS extends ImageCompos
|
||||||
|
|
||||||
export type ImageCompositorNode = {
|
export type ImageCompositorNode = {
|
||||||
id: string;
|
id: string;
|
||||||
fxId: string;
|
programId: string;
|
||||||
params: Record<string, any>;
|
params: Record<string, any>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: per node cache
|
||||||
|
|
||||||
export class ImageCompositor {
|
export class ImageCompositor {
|
||||||
private gl: WebGL2RenderingContext;
|
private gl: WebGL2RenderingContext;
|
||||||
private canvas: HTMLCanvasElement | null = null;
|
private canvas: HTMLCanvasElement | null = null;
|
||||||
|
|
@ -45,6 +46,7 @@ export class ImageCompositor {
|
||||||
private perLayerResultFrameBuffers: Map<string, WebGLFramebuffer> = new Map();
|
private perLayerResultFrameBuffers: Map<string, WebGLFramebuffer> = new Map();
|
||||||
private nopProgram: WebGLProgram;
|
private nopProgram: WebGLProgram;
|
||||||
private registeredTextures: Map<string, { texture: WebGLTexture; width: number; height: number; }> = new Map();
|
private registeredTextures: Map<string, { texture: WebGLTexture; width: number; height: number; }> = new Map();
|
||||||
|
private programs: ImageCompositorProgram[] = [];
|
||||||
|
|
||||||
constructor(options: {
|
constructor(options: {
|
||||||
canvas: HTMLCanvasElement;
|
canvas: HTMLCanvasElement;
|
||||||
|
|
@ -117,10 +119,10 @@ export class ImageCompositor {
|
||||||
private renderNode(node: ImageCompositorNode, preTexture: WebGLTexture, invert = false) {
|
private renderNode(node: ImageCompositorNode, preTexture: WebGLTexture, invert = false) {
|
||||||
const gl = this.gl;
|
const gl = this.gl;
|
||||||
|
|
||||||
const fx = this.fxs.find(fx => fx.id === node.fxId);
|
const program = this.programs.find(p => p.id === node.programId);
|
||||||
if (fx == null) return;
|
if (program == null) return;
|
||||||
|
|
||||||
const cachedShader = this.shaderCache.get(fx.id);
|
const cachedShader = this.shaderCache.get(program.id);
|
||||||
const shaderProgram = cachedShader ?? initShaderProgram(this.gl, `#version 300 es
|
const shaderProgram = cachedShader ?? initShaderProgram(this.gl, `#version 300 es
|
||||||
in vec2 position;
|
in vec2 position;
|
||||||
uniform bool u_invert;
|
uniform bool u_invert;
|
||||||
|
|
@ -130,9 +132,9 @@ export class ImageCompositor {
|
||||||
in_uv = (position + 1.0) / 2.0;
|
in_uv = (position + 1.0) / 2.0;
|
||||||
gl_Position = u_invert ? vec4(position * vec2(1.0, -1.0), 0.0, 1.0) : vec4(position, 0.0, 1.0);
|
gl_Position = u_invert ? vec4(position * vec2(1.0, -1.0), 0.0, 1.0) : vec4(position, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
`, fx.shader);
|
`, program.shader);
|
||||||
if (cachedShader == null) {
|
if (cachedShader == null) {
|
||||||
this.shaderCache.set(fx.id, shaderProgram);
|
this.shaderCache.set(program.id, shaderProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.useProgram(shaderProgram);
|
gl.useProgram(shaderProgram);
|
||||||
|
|
@ -148,11 +150,11 @@ export class ImageCompositor {
|
||||||
const in_texture = gl.getUniformLocation(shaderProgram, 'in_texture');
|
const in_texture = gl.getUniformLocation(shaderProgram, 'in_texture');
|
||||||
gl.uniform1i(in_texture, 0);
|
gl.uniform1i(in_texture, 0);
|
||||||
|
|
||||||
fx.main({
|
program.main({
|
||||||
gl: gl,
|
gl: gl,
|
||||||
program: shaderProgram,
|
program: shaderProgram,
|
||||||
params: node.params,
|
params: node.params,
|
||||||
u: Object.fromEntries(fx.uniforms.map(u => [u, gl.getUniformLocation(shaderProgram, 'u_' + u)!])),
|
u: Object.fromEntries(program.uniforms.map(u => [u, gl.getUniformLocation(shaderProgram, 'u_' + u)!])),
|
||||||
width: this.renderWidth,
|
width: this.renderWidth,
|
||||||
height: this.renderHeight,
|
height: this.renderHeight,
|
||||||
textures: this.registeredTextures,
|
textures: this.registeredTextures,
|
||||||
|
|
@ -194,7 +196,7 @@ export class ImageCompositor {
|
||||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||||
} else {
|
} else {
|
||||||
const cachedResultFrameBuffer = this.perLayerResultFrameBuffers.get(layer.id);
|
const cachedResultFrameBuffer = this.perLayerResultFrameBuffers.get(layer.id);
|
||||||
const resultFrameBuffer = cachedResultFrameBuffer ?? gl.createFramebuffer()!;
|
const resultFrameBuffer = cachedResultFrameBuffer ?? gl.createFramebuffer();
|
||||||
if (cachedResultFrameBuffer == null) {
|
if (cachedResultFrameBuffer == null) {
|
||||||
this.perLayerResultFrameBuffers.set(layer.id, resultFrameBuffer);
|
this.perLayerResultFrameBuffers.set(layer.id, resultFrameBuffer);
|
||||||
}
|
}
|
||||||
|
|
@ -208,15 +210,15 @@ export class ImageCompositor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public registerFx(fx: ImageCompositorFx) {
|
public registerProgram(program: ImageCompositorProgram) {
|
||||||
this.fxs.push(fx);
|
this.programs.push(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public registerTexture(key: string, image: ImageData | ImageBitmap | HTMLImageElement | HTMLCanvasElement) {
|
public registerTexture(key: string, image: ImageData | ImageBitmap | HTMLImageElement | HTMLCanvasElement) {
|
||||||
const gl = this.gl;
|
const gl = this.gl;
|
||||||
|
|
||||||
if (this.registeredTextures.has(key)) {
|
const existing = this.registeredTextures.get(key);
|
||||||
const existing = this.registeredTextures.get(key)!;
|
if (existing != null) {
|
||||||
gl.deleteTexture(existing.texture);
|
gl.deleteTexture(existing.texture);
|
||||||
this.registeredTextures.delete(key);
|
this.registeredTextures.delete(key);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue