UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

151 lines 14 kB
import { TgdDataset } from "./../../dataset/dataset.js"; import { TgdFilterVerbatim } from "./../../filter/index.js"; import { TgdPainter } from "./../painter.js"; import { TgdProgram } from "./../../program/index.js"; import { TgdShaderFragment } from "./../../shader/fragment.js"; import { TgdShaderVertex } from "./../../shader/vertex.js"; import { TgdVertexArray } from "./../../vao/index.js"; import { TgdPainterState } from "../state/index.js"; import { Framebuffers } from "./framebuffers.js"; import { tgdTextureRecordToUniforms } from "./../../utils/index.js"; export class TgdPainterFilter extends TgdPainter { constructor(context, options) { super(); this.context = context; this.z = 0; this.texturesArray = []; this.paintOneFilter = (filterIndex, time, delta, flip = +1) => { const { framebuffers } = this; const textureInput = framebuffers.texture; const filter = this.filters[filterIndex]; const program = this.programs[filterIndex]; const vao = this.vaos[filterIndex]; const { context } = this; const { gl } = context; program.use(); program.uniform1f("uniZ", this.z); program.uniform1f("uniFlipY", flip); const textures = this.texturesArray[filterIndex]; if (textures) { let unit = 1; for (const uniformName of Object.keys(textures)) { const texture = textures[uniformName]; texture.activate(unit++, program, uniformName); } } filter.setUniforms({ context, program, time, delta }); textureInput.activate(0, program, "uniTexture"); vao.bind(); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); vao.unbind(); }; const { texture } = options; if (!texture) { throw new Error(`[TgdPainterFilter] A texture must be given for "${this.name}"!`); } this.framebuffers = new Framebuffers(context, texture); this.z = options.z ?? 0.999999; this.flipY = options.flipY ?? false; const filters = [...(options.filters ?? [])]; if (filters.length === 0) { filters.push(new TgdFilterVerbatim()); } const programs = filters.map((filter) => { const vert = new TgdShaderVertex({ attributes: { attPoint: "vec2", attUV: "vec2", }, varying: { varUV: "vec2", varPixel: "vec2", }, uniforms: { uniZ: "float", uniFlipY: "float", uniTexture: "sampler2D", }, mainCode: [ "varUV = attUV;", "ivec2 size = textureSize(uniTexture, 0);", "varPixel = vec2(1.0 / float(size.x), 1.0 / float(size.y));", "gl_Position = vec4(", ["attPoint * vec2(1.0, uniFlipY),", "uniZ,", "1.0"], ");", ], }).code; const { textures } = filter; this.texturesArray.push(textures); const uniformsForTextures = tgdTextureRecordToUniforms(textures); console.log("🐞 [filter@77] filter =", filter); // @FIXME: Remove this line written on 2026-05-18 at 20:37 const frag = new TgdShaderFragment({ uniforms: { ...uniformsForTextures, uniTexture: "sampler2D", ...filter.uniforms, }, varying: { varUV: "vec2", varPixel: "vec2", }, mainCode: filter.fragmentShaderCode ?? [ "vec4 color = texture(uniTexture, varUV);", "FragColor = color;", ], functions: filter.extraFunctions, }).code; const prg = new TgdProgram(context.gl, { vert, frag }); prg.use(); const samplerNames = Object.keys(textures); for (let unit = 1; unit <= samplerNames.length; unit++) { const uniformName = samplerNames[unit - 1]; const texture = textures[uniformName]; texture.activate(unit, prg, uniformName); } return prg; }); const vaos = programs.map((program) => createVAO(context, program)); this.programs = programs; this.filters = filters; this.vaos = vaos; this.name = options.name ?? `Filter/${this.name}`; } delete() { const { programs, vaos, framebuffers } = this; framebuffers.delete(); for (const prg of programs) prg.delete(); for (const vao of vaos) vao.delete(); } paint(time, delta) { const { framebuffers, filters } = this; TgdPainterState.do(this.context, { depth: "off", blend: "off", cull: "off", action: () => { for (let index = 0; index < filters.length - 1; index++) { framebuffers.paint(() => this.paintOneFilter(index, time, delta)); } }, }); this.paintOneFilter(filters.length - 1, time, delta, (filters.length & 1) === (this.flipY ? 0 : 1) ? +1 : -1); if (filters.length % 2 === 0) framebuffers.swap(); } } function createVAO(context, program) { const dataset = new TgdDataset({ attPoint: "vec2", attUV: "vec2", }); // prettier-ignore dataset.set("attPoint", new Float32Array([-1, +1, +1, +1, -1, -1, +1, -1])); dataset.set("attUV", new Float32Array([0, 0, 1, 0, 0, 1, 1, 1])); const vao = new TgdVertexArray(context.gl, program, [dataset]); if (!vao) throw new Error("Unable to create WebGL VAO!"); return vao; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3BhaW50ZXIvZmlsdGVyL2ZpbHRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUE7QUFDakQsT0FBTyxFQUFrQixpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUMvRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUE7QUFDakQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUN6QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQTtBQUN4RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUE7QUFFcEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUN6QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBQzFDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUM3QyxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFXdkQsTUFBTSxPQUFPLGdCQUFpQixTQUFRLFVBQVU7SUFVNUMsWUFDb0IsT0FBbUIsRUFDbkMsT0FBZ0M7UUFFaEMsS0FBSyxFQUFFLENBQUE7UUFIUyxZQUFPLEdBQVAsT0FBTyxDQUFZO1FBVmhDLE1BQUMsR0FBRyxDQUFDLENBQUE7UUFPSyxrQkFBYSxHQUFvRCxFQUFFLENBQUE7UUF1R25FLG1CQUFjLEdBQUcsQ0FBQyxXQUFtQixFQUFFLElBQVksRUFBRSxLQUFhLEVBQUUsSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDOUYsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLElBQUksQ0FBQTtZQUM3QixNQUFNLFlBQVksR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFBO1lBRXpDLE1BQU0sTUFBTSxHQUFHLElB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