@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
275 lines • 22.3 kB
JavaScript
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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