UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

275 lines 22.3 kB
import { TgdDataset } from "./../../dataset/index.js"; import { TgdMaterialFaceOrientation } from "./../../material/index.js"; import { TgdTransfo } from "./../../math/index.js"; import { TgdPainter } from "./../painter.js"; import { TgdProgram } from "./../../program/index.js"; import { TgdShaderFragment, TgdShaderVertex } from "./../../shader/index.js"; import { TgdVertexArray } from "./../../vao/index.js"; import { makeCapsule } from "./capsule.js"; /** * @example * ``` * const factory = new TgdPainterSegmentsData() * factory.add( * [0, 0, 0, .2], * [1, 0, 0, .1], * ) * factory.add( * [0, 0, 0, .2], * [0, 1, 0, .1], * ) * factory.add( * [0, 0, 0, .2], * [0, 0, 1, .1], * ) * const segments = new TgdPainterSegments( * segment, factory * ) * ``` */ export class TgdPainterSegments extends TgdPainter { static createDataset({ attXYZR0 = "attXYZR0", attUV0 = "attUV0", attInfluence0 = "attInfluence0", attXYZR1 = "attXYZR1", attUV1 = "attUV1", attInfluence1 = "attInfluence1", buffer, usage, target, } = {}) { const dataset = new TgdDataset({ [attXYZR0]: "vec4", [attUV0]: "vec2", [attInfluence0]: "float", [attXYZR1]: "vec4", [attUV1]: "vec2", [attInfluence1]: "float", }, { divisor: 1, buffer, usage, target, }); return dataset; } constructor(context, options) { super(); this.context = context; this.transfo = new TgdTransfo(); this.minRadius = 1; this.radiusMultiplier = 1; this.radiusConstant = 1; this.radiusSwitch = 0; this.instanceCount = 0; this.name = `TgdPainterSegments#${this.id}`; this.radiusMultiplier = options.radiusMultiplier ?? 1; const { roundness = 3, minRadius = 1, dataset } = options; const geometry = makeCapsule(roundness); const material = options.material ?? new TgdMaterialFaceOrientation(); this.material = material; material.attPosition = geometry.attPosition; material.attNormal = "normal"; // geometry.attNormal material.attUV = "((attUV0 + attUV1) * .5)"; this.minRadius = minRadius; if (roundness > 127) { throw new Error("[TgdPainterSegments] Max roundness is 127!"); } if (roundness < 0) { throw new Error("[TgdPainterSegments] Min roundness is 0!"); } const vert = new TgdShaderVertex({ uniforms: { uniTransfoMatrix: "mat4", uniModelViewMatrix: "mat4", uniProjectionMatrix: "mat4", uniPixelPerScreenUnit: "float", uniMinRadiusInPixel: "float", uniRadiusMultiplier: "float", ...material.uniforms, }, attributes: { [geometry.attPosition]: "vec4", [geometry.attNormal]: "vec3", attTip: "float", attXYZR0: "vec4", attXYZR1: "vec4", attUV0: "vec2", attUV1: "vec2", }, varying: { ...material.varyings, }, functions: { ...material.extraVertexShaderFunctions, getPosition: [ "vec4 getPosition(vec4 pos) {", [material.vertexShaderCodeForGetPosition ?? "return pos;"], "}", ], applyMaterial: [ "void applyMaterial(vec3 position, vec3 normal, vec2 uv) {", [material.vertexShaderCode], "}", ], }, mainCode: [ `vec3 normal = ${geometry.attNormal};`, `vec3 pos = getPosition(${geometry.attPosition}).xyz;`, "vec4 xyzr = mix(attXYZR0, attXYZR1, attTip);", "vec3 center = xyzr.xyz;", "vec4 centerInCameraSpace = uniModelViewMatrix * uniTransfoMatrix * vec4(center, 1);", "vec4 centerInScreenSpace = uniProjectionMatrix * centerInCameraSpace;", "float screenUnitPerCameraUnit = (uniProjectionMatrix * vec4(0, 1, centerInCameraSpace.z, 1)).y / centerInScreenSpace.w;", "float minRadiusInCameraUnit = uniMinRadiusInPixel / (uniPixelPerScreenUnit * screenUnitPerCameraUnit);", "float radius = max(", ["xyzr.w * uniRadiusMultiplier,", "minRadiusInCameraUnit"], ");", "vec3 dir = attXYZR1.xyz - attXYZR0.xyz;", "float len = length(dir);", "if (len == 0.0) {", ["// Just a sphere", "pos *= radius;", "pos += center.xyz;"], "} else {", [ "// Full capsule", "vec3 Z = dir / len;", "bool yUp = abs(Z.y) < 0.9;", "vec3 fakeY = yUp ? vec3(0,1,0) : vec3(0,0,1);", "vec3 X = cross(fakeY, Z);", "vec3 Y = cross(Z, X);", "mat3 mat = mat3(X, Y, Z);", "pos *= radius;", "pos = mat * pos + center.xyz;", "normal = mat * normal;", ], "}", "gl_Position = uniProjectionMatrix * uniModelViewMatrix * uniTransfoMatrix * vec4(pos, 1);", `applyMaterial(pos, normal, ${material.attUV}.xy);`, ], }).code; const frag = new TgdShaderFragment({ header: material.fragmentShaderHeader, uniforms: material.uniforms, outputs: { FragColor: "vec4" }, varying: { ...material.varyings }, functions: { ...material.extraFragmentShaderFunctions, applyMaterial: ["vec4 applyMaterial() {", [material.fragmentShaderCode], "}"], }, mainCode: ["FragColor = applyMaterial();"], }).code; const prg = new TgdProgram(context.gl, { name: `TgdPainterSegments/TgdProgram#${this.id}`, vert, frag, }); this.prg = prg; if (dataset instanceof TgdPainterSegments) { if (dataset.vao.gl !== context.gl) { throw new Error("[TgdPainterSegments] You cannot share a VAO accross different contexts!"); } this.vao = dataset.vao; this.vao.share(); this.instanceCount = dataset.instanceCount; } else if (dataset) { const instance = extract(dataset); instance.addAttributes({ attXYZR0: "vec4", attUV0: "vec2", attInfluence0: "float", attXYZR1: "vec4", attUV1: "vec2", attInfluence1: "float", }); this.vao = new TgdVertexArray(context.gl, prg, [geometry.dataset, instance], geometry.elements); this.instanceCount = instance.count; } else { context.console.error("[TgdPainterSegments] options =", options); throw new Error("option `dataset` of TgdPainterSegments is undefined!"); } this.vertexCount = geometry.elements?.length ?? 0; } debug(caption) { this.prg.debug(caption ?? this.name); } getBuffer() { return this.vao.getBuffer(1); } delete() { this.vao.delete(); this.prg.delete(); } paint(time, delta) { const { context, prg, vao, vertexCount, instanceCount, material } = this; const { gl, camera } = context; gl.disable(gl.DITHER); prg.use(); this.material.setUniforms?.({ program: prg, context, time, delta }); prg.uniform1f("uniPixelPerScreenUnit", gl.drawingBufferHeight); prg.uniform1f("uniMinRadiusInPixel", this.minRadius); prg.uniform1f("uniRadiusMultiplier", this.radiusMultiplier); prg.uniformMatrix4fv("uniTransfoMatrix", this.transfo.matrix); prg.uniformMatrix4fv("uniModelViewMatrix", camera.matrixModelView); prg.uniformMatrix4fv("uniProjectionMatrix", camera.matrixProjection); material.applyState(this.context, () => { vao.bind(); gl.drawElementsInstanced(gl.TRIANGLES, vertexCount, gl.UNSIGNED_SHORT, 0, instanceCount); vao.unbind(); }); } } export class TgdPainterSegmentsData { constructor() { this._count = 0; this.attXYZR0 = []; this.attUV0 = []; this.attInfluence0 = []; this.attXYZR1 = []; this.attUV1 = []; this.attInfluence1 = []; /** * You can rename the attributes if you need to use * them in another Painter. */ this.makeDataset = (args = {}) => { const dataset = TgdPainterSegments.createDataset(args); const { attXYZR0 = "attXYZR0", attUV0 = "attUV0", attInfluence0 = "attInfluence0", attXYZR1 = "attXYZR1", attUV1 = "attUV1", attInfluence1 = "attInfluence1", } = args; dataset.set(attXYZR0, new Float32Array(this.attXYZR0)); dataset.set(attUV0, new Float32Array(this.attUV0)); dataset.set(attInfluence0, new Float32Array(this.attInfluence0)); dataset.set(attXYZR1, new Float32Array(this.attXYZR1)); dataset.set(attUV1, new Float32Array(this.attUV1)); dataset.set(attInfluence1, new Float32Array(this.attInfluence1)); return dataset; }; } get count() { return this._count; } getXYZR0(index) { const arr = this.attXYZR0; const offset = index * 4; return [arr[offset + 0] ?? 0, arr[offset + 1] ?? 0, arr[offset + 2] ?? 0, arr[offset + 3] ?? 0]; } getXYZR1(index) { const arr = this.attXYZR1; const offset = index * 4; return [arr[offset + 0] ?? 0, arr[offset + 1] ?? 0, arr[offset + 2] ?? 0, arr[offset + 3] ?? 0]; } /** * @param XYZR0 (x,y,z) and radius of point A. * @param XYZR1 (x,y,z) and radius of point B. * @param UV0 Texture coordinates for point A. * @param UV1 Texture coordinates for point B. * @param radiusMultiplierInfluence0 If you put 0, the radius won't change regardless to the currently applied radius multiplicator. * @param radiusMultiplierInfluence1 */ add(XYZR0, XYZR1, UV0 = [0, 0], UV1 = [0, 0], radiusMultiplierInfluence0 = 1, radiusMultiplierInfluence1 = 1) { this.attXYZR0.push(...XYZR0); this.attUV0.push(...UV0); this.attInfluence0.push(radiusMultiplierInfluence0); this.attXYZR1.push(...XYZR1); this.attUV1.push(...UV1); this.attInfluence1.push(radiusMultiplierInfluence1); this._count++; } } function extract(arg) { if (typeof arg === "function") return arg(); return arg; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VnbWVudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcGFpbnRlci9zZWdtZW50cy9zZWdtZW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFJQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBQ3pDLE9BQU8sRUFBb0IsMEJBQTBCLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDNUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUN0QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUE7QUFDakQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUN6QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsZUFBZSxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBRWhFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFDekMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQWlDdkM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsTUFBTSxPQUFPLGtCQUFtQixTQUFRLFVBQVU7SUFDOUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxFQUNqQixRQUFRLEdBQUcsVUFBVSxFQUNyQixNQUFNLEdBQUcsUUFBUSxFQUNqQixhQUFhLEdBQUcsZUFBZSxFQUMvQixRQUFRLEdBQUcsVUFBVSxFQUNyQixNQUFNLEdBQUcsUUFBUSxFQUNqQixhQUFhLEdBQUcsZUFBZSxFQUMvQixNQUFNLEVBQ04sS0FBSyxFQUNMLE1BQU0sTUFXTCxFQUFFO1FBQ0gsTUFBTSxPQUFPLEdBQUcsSUFBSSxVQUFVLENBQzFCO1lBQ0ksQ0FBQyxRQUFRLENBQUMsRUFBRSxNQUFNO1lBQ2xCLENBQUMsTUFBTSxDQUFDLEVBQUUsTUFBTTtZQUNoQixDQUFDLGFBQWEsQ0FBQyxFQUFFLE9BQU87WUFDeEIsQ0FBQyxRQUFRLENBQUMsRUFBRSxNQUFNO1lBQ2xCLENBQUMs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