phoria2 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/dist/bloom.js +4 -4
- package/dist/bloom.js.map +1 -1
- package/dist/charts.js +436 -436
- package/dist/charts.js.map +1 -1
- package/dist/core.js +1223 -862
- package/dist/core.js.map +1 -1
- package/dist/debug.js +297 -0
- package/dist/debug.js.map +1 -0
- package/dist/edit.js +40 -40
- package/dist/edit.js.map +1 -1
- package/dist/explain.js +32 -13
- package/dist/explain.js.map +1 -1
- package/dist/gltf.js +128 -128
- package/dist/gltf.js.map +1 -1
- package/dist/keyboard.js +19 -19
- package/dist/keyboard.js.map +1 -1
- package/dist/motion.js +35 -35
- package/dist/motion.js.map +1 -1
- package/dist/particles.js +36 -36
- package/dist/particles.js.map +1 -1
- package/dist/passes.js +116 -104
- package/dist/passes.js.map +1 -1
- package/dist/phoria2.js +1 -1
- package/dist/picking.js +88 -71
- package/dist/picking.js.map +1 -1
- package/dist/snapshot.js +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/types/View.d.ts +16 -0
- package/dist/types/debug.d.ts +74 -0
- package/dist/types/explain.d.ts +4 -0
- package/dist/types/frame.d.ts +5 -0
- package/dist/types/material/Material.d.ts +52 -0
- package/dist/types/watch.d.ts +8 -1
- package/dist/types/webgl/hooks.d.ts +48 -0
- package/dist/types/webgl/passes.d.ts +4 -0
- package/dist/types/webgl/programs.d.ts +15 -5
- package/dist/types/webgl/shaders.d.ts +36 -5
- package/llms-full.txt +227 -0
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/schema/scene.schema.json +27 -0
- package/src/View.js +105 -7
- package/src/debug.js +283 -0
- package/src/explain.js +19 -0
- package/src/frame.js +7 -2
- package/src/material/Material.js +121 -2
- package/src/scene/drawables.js +21 -4
- package/src/watch.js +18 -2
- package/src/webgl/WebGLRenderer.js +19 -2
- package/src/webgl/hooks.js +121 -0
- package/src/webgl/passes.js +17 -2
- package/src/webgl/picking.js +23 -2
- package/src/webgl/programs.js +20 -9
- package/src/webgl/resources.js +1 -1
- package/src/webgl/shaders.js +443 -35
package/dist/picking.js
CHANGED
|
@@ -1,22 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as e, C as t, D as n, M as r, S as i, T as a, Vt as o, j as s, w as c, zt as l } from "./core.js";
|
|
2
2
|
// src/webgl/picking.js
|
|
3
|
-
var
|
|
3
|
+
var u = 33, d = 4, f = `precision highp float;
|
|
4
4
|
precision highp int;
|
|
5
5
|
flat in uint vPickElement;
|
|
6
6
|
#ifdef SPRITES
|
|
7
7
|
in vec2 vUv;
|
|
8
8
|
#endif
|
|
9
|
-
#
|
|
9
|
+
#if defined(CLIP) || defined(HOOK_FRAGMENT)
|
|
10
10
|
in vec3 vWorldPosition;
|
|
11
11
|
#endif
|
|
12
|
+
#ifdef HOOK_FRAGMENT
|
|
13
|
+
in vec3 vNormal;
|
|
14
|
+
in vec2 vUv;
|
|
15
|
+
in vec3 vColor;
|
|
16
|
+
#endif
|
|
12
17
|
uniform uint uPickId;
|
|
13
18
|
layout(location = 0) out uvec4 pickOut;
|
|
14
|
-
${
|
|
15
|
-
${
|
|
19
|
+
${n}
|
|
20
|
+
${a}
|
|
16
21
|
void main() {
|
|
17
22
|
#ifdef CLIP
|
|
18
23
|
clipAway(vWorldPosition);
|
|
19
24
|
#endif
|
|
25
|
+
#ifdef HOOK_FRAGMENT
|
|
26
|
+
{
|
|
27
|
+
vec4 base = vec4(vColor, 1.0);
|
|
28
|
+
vec3 emissive = vec3(0.0);
|
|
29
|
+
vec3 normal = normalize(vNormal);
|
|
30
|
+
if (base.a <= 0.0) discard;
|
|
31
|
+
}
|
|
32
|
+
#endif
|
|
20
33
|
#ifdef ROUND
|
|
21
34
|
#ifdef SPRITES
|
|
22
35
|
vec2 p = vUv * 2.0 - 1.0;
|
|
@@ -27,11 +40,11 @@ if (dot(p, p) > 1.0) discard;
|
|
|
27
40
|
#endif
|
|
28
41
|
pickOut = uvec4(uPickId, vPickElement, floatBitsToUint(gl_FragCoord.z), 1u);
|
|
29
42
|
}
|
|
30
|
-
`,
|
|
31
|
-
mesh: [
|
|
32
|
-
points: [
|
|
33
|
-
lines: [e,
|
|
34
|
-
},
|
|
43
|
+
`, p = {
|
|
44
|
+
mesh: [s, f],
|
|
45
|
+
points: [r, f],
|
|
46
|
+
lines: [e, f]
|
|
47
|
+
}, m = class {
|
|
35
48
|
#e = null;
|
|
36
49
|
#t = /* @__PURE__ */ new Uint32Array(4356);
|
|
37
50
|
#n = /* @__PURE__ */ new Float32Array(16);
|
|
@@ -46,79 +59,79 @@ pickOut = uvec4(uPickId, vPickElement, floatBitsToUint(gl_FragCoord.z), 1u);
|
|
|
46
59
|
this.#e = null, this.#a = null, this.#o = !1;
|
|
47
60
|
}
|
|
48
61
|
pick(e, t, n, r, i, a) {
|
|
49
|
-
let o = this.gl,
|
|
50
|
-
return
|
|
62
|
+
let o = this.gl, s = this.#s(e, t, n, r, i, a);
|
|
63
|
+
return s ? (o.readPixels(0, 0, u, u, o.RGBA_INTEGER, o.UNSIGNED_INT, this.#t), o.bindFramebuffer(o.FRAMEBUFFER, null), this.#c(s)) : null;
|
|
51
64
|
}
|
|
52
65
|
pickAsync(e, t, n, r, i, a) {
|
|
53
66
|
if (this.#o) return null;
|
|
54
|
-
let o = this.gl,
|
|
55
|
-
if (!
|
|
56
|
-
let
|
|
57
|
-
o.bindBuffer(o.PIXEL_PACK_BUFFER,
|
|
58
|
-
let
|
|
67
|
+
let o = this.gl, s = this.#s(e, t, n, r, i, a);
|
|
68
|
+
if (!s) return Promise.resolve(null);
|
|
69
|
+
let c = this.#l();
|
|
70
|
+
o.bindBuffer(o.PIXEL_PACK_BUFFER, c), o.readPixels(0, 0, u, u, o.RGBA_INTEGER, o.UNSIGNED_INT, 0), o.bindBuffer(o.PIXEL_PACK_BUFFER, null), o.bindFramebuffer(o.FRAMEBUFFER, null);
|
|
71
|
+
let l = o.fenceSync(o.SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
59
72
|
return o.flush(), this.#o = !0, new Promise((e) => {
|
|
60
73
|
let t = () => {
|
|
61
|
-
o.isContextLost() ? (this.#o = !1, e(null)) : o.clientWaitSync(
|
|
74
|
+
o.isContextLost() ? (this.#o = !1, e(null)) : o.clientWaitSync(l, 0, 0) === o.TIMEOUT_EXPIRED ? setTimeout(t, 1) : (o.deleteSync(l), o.bindBuffer(o.PIXEL_PACK_BUFFER, c), o.getBufferSubData(o.PIXEL_PACK_BUFFER, 0, this.#t), o.bindBuffer(o.PIXEL_PACK_BUFFER, null), this.#o = !1, e(this.#c(s)));
|
|
62
75
|
};
|
|
63
76
|
setTimeout(t, 0);
|
|
64
77
|
});
|
|
65
78
|
}
|
|
66
|
-
#s(e, t, r, i, a
|
|
67
|
-
let
|
|
68
|
-
if (!
|
|
69
|
-
let
|
|
70
|
-
|
|
79
|
+
#s(e, t, n, r, i, a) {
|
|
80
|
+
let s = this.gl, c = h(e);
|
|
81
|
+
if (!c.length) return null;
|
|
82
|
+
let l = this.#d();
|
|
83
|
+
s.bindFramebuffer(s.FRAMEBUFFER, l.framebuffer), s.viewport(0, 0, u, u), s.disable(s.BLEND), s.disable(s.SCISSOR_TEST), s.enable(s.DEPTH_TEST), s.depthFunc(s.LEQUAL), s.depthMask(!0), s.clearBufferuiv(s.COLOR, 0, [
|
|
71
84
|
0,
|
|
72
85
|
0,
|
|
73
86
|
0,
|
|
74
87
|
0
|
|
75
|
-
]),
|
|
76
|
-
let d =
|
|
77
|
-
|
|
88
|
+
]), s.clearBufferfv(s.DEPTH, 0, [1]);
|
|
89
|
+
let d = u, f = t / r * 2 - 1, p = 1 - n / i * 2, m = new Float32Array([
|
|
90
|
+
r / d,
|
|
78
91
|
0,
|
|
79
92
|
0,
|
|
80
93
|
0,
|
|
81
94
|
0,
|
|
82
|
-
|
|
95
|
+
i / d,
|
|
83
96
|
0,
|
|
84
97
|
0,
|
|
85
98
|
0,
|
|
86
99
|
0,
|
|
87
100
|
1,
|
|
88
101
|
0,
|
|
102
|
+
-f * r / d,
|
|
89
103
|
-p * i / d,
|
|
90
|
-
-m * a / d,
|
|
91
104
|
0,
|
|
92
105
|
1
|
|
93
106
|
]);
|
|
94
|
-
return
|
|
95
|
-
items:
|
|
96
|
-
cx:
|
|
97
|
-
cy:
|
|
98
|
-
width:
|
|
99
|
-
height:
|
|
107
|
+
return o(this.#n, m, e.camera.projection), o(this.#r, this.#n, e.camera.view), c.forEach((t, n) => this.#u(t, n + 1, e, i, a)), s.bindVertexArray(null), {
|
|
108
|
+
items: c,
|
|
109
|
+
cx: f,
|
|
110
|
+
cy: p,
|
|
111
|
+
width: r,
|
|
112
|
+
height: i
|
|
100
113
|
};
|
|
101
114
|
}
|
|
102
115
|
#c({ items: e, cx: t, cy: n, width: r, height: i }) {
|
|
103
|
-
let a = this.#t, o = (e, t) => (t *
|
|
104
|
-
if (
|
|
116
|
+
let a = this.#t, o = (e, t) => (t * u + e) * 4, s = a[o(16, 16)] ? o(16, 16) : -1, c = 0, l = 0;
|
|
117
|
+
if (s < 0) {
|
|
105
118
|
let t = Infinity;
|
|
106
|
-
for (let n = -4; n <=
|
|
119
|
+
for (let n = -4; n <= d; n++) for (let r = -4; r <= d; r++) {
|
|
107
120
|
let i = r * r + n * n;
|
|
108
121
|
if (i > 16 || i >= t) continue;
|
|
109
|
-
let
|
|
110
|
-
|
|
122
|
+
let u = o(16 + r, 16 + n), d = a[u];
|
|
123
|
+
d && e[d - 1].node.drawMode !== "triangles" && (s = u, t = i, c = r, l = n);
|
|
111
124
|
}
|
|
112
125
|
}
|
|
113
|
-
if (
|
|
114
|
-
let f = new Float32Array(new Uint32Array([a[
|
|
115
|
-
t +
|
|
116
|
-
n +
|
|
126
|
+
if (s < 0) return null;
|
|
127
|
+
let f = new Float32Array(new Uint32Array([a[s + 2]]).buffer)[0], p = [
|
|
128
|
+
t + c * 2 / r,
|
|
129
|
+
n + l * 2 / i,
|
|
117
130
|
f * 2 - 1
|
|
118
131
|
];
|
|
119
132
|
return {
|
|
120
|
-
item: e[a[
|
|
121
|
-
element: a[
|
|
133
|
+
item: e[a[s] - 1],
|
|
134
|
+
element: a[s + 1],
|
|
122
135
|
ndc: p
|
|
123
136
|
};
|
|
124
137
|
}
|
|
@@ -127,35 +140,39 @@ pickOut = uvec4(uPickId, vPickElement, floatBitsToUint(gl_FragCoord.z), 1u);
|
|
|
127
140
|
let e = this.gl;
|
|
128
141
|
return this.#a = e.createBuffer(), e.bindBuffer(e.PIXEL_PACK_BUFFER, this.#a), e.bufferData(e.PIXEL_PACK_BUFFER, this.#t.byteLength, e.STREAM_READ), e.bindBuffer(e.PIXEL_PACK_BUFFER, null), this.#a;
|
|
129
142
|
}
|
|
130
|
-
#u(e, n, r,
|
|
131
|
-
let
|
|
132
|
-
|
|
133
|
-
let
|
|
134
|
-
|
|
135
|
-
let
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
143
|
+
#u(e, n, r, a, o) {
|
|
144
|
+
let s = this.gl, { node: d, geometry: f, material: m, worldMatrix: h, instances: g } = e, _ = d.drawMode, v = _ === "points" ? "points" : _ === "lines" ? "lines" : "mesh", y = ["PICK"];
|
|
145
|
+
g && y.push("INSTANCED");
|
|
146
|
+
let b = v === "points" && d.drawsSprites;
|
|
147
|
+
v === "points" && (m.sizeAttenuation && y.push("SIZE_ATTENUATION"), m.map || y.push("ROUND"), b && y.push("SPRITES")), v === "mesh" && e.clip && y.push("CLIP");
|
|
148
|
+
let x = i(m);
|
|
149
|
+
x && y.push(...t(x, v === "mesh"));
|
|
150
|
+
let S = this.programs.ready(`pick-${v}`, y, p[v], x?.source);
|
|
151
|
+
if (!S.failed) {
|
|
152
|
+
if (s.useProgram(S.program), S.set("uView", r.camera.view), S.set("uProjection", this.#n), S.set("uViewProjection", this.#r), S.set("uModel", h), S.set("uPickId", n), S.set("uHighlightIndex", -2), e.clip && S.set("uClipPlane", e.clip.plane), x && c(S, m, r.time ?? 0, r.camera.position, (e) => this.resources.texture(e)), v === "lines") {
|
|
153
|
+
s.disable(s.CULL_FACE), S.set("uResolution", [u, u]), S.set("uWidth", m.width * o), S.set("uNear", r.camera.near);
|
|
154
|
+
let e = d.arrowBits ?? 0;
|
|
155
|
+
S.set("uArrows", e), S.set("uArrowSize", d.arrowPixels?.(m.width) * o || 0);
|
|
156
|
+
let t = this.resources.lines(f);
|
|
157
|
+
s.bindVertexArray(t.vao), s.drawArraysInstanced(s.TRIANGLES, 0, e ? 12 : 6, Math.min(t.count, Math.floor(f.drawnCount / 2)));
|
|
158
|
+
} else if (v === "points") {
|
|
159
|
+
if (s.disable(s.CULL_FACE), S.set("uSize", m.sizeAttenuation ? m.size : m.size * o), S.set("uScale", r.camera.projection[5] * a / 2), b) {
|
|
160
|
+
S.set("uResolution", [u, u]);
|
|
161
|
+
let e = this.resources.sprites(f);
|
|
162
|
+
s.bindVertexArray(e.vao), s.drawArraysInstanced(s.TRIANGLE_STRIP, 0, 4, e.count);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
let e = this.resources.mesh(f, null, !1);
|
|
166
|
+
s.bindVertexArray(e.vao), s.drawArrays(s.POINTS, 0, f.drawnVertices);
|
|
167
|
+
} else S.set("uNormalMatrix", this.#i), m.depthTest ? s.enable(s.DEPTH_TEST) : s.disable(s.DEPTH_TEST), m.doubleSided || e.clip?.cap ? s.disable(s.CULL_FACE) : (s.enable(s.CULL_FACE), s.cullFace(s.BACK), s.frontFace(l(h) < 0 ? s.CW : s.CCW)), this.resources.drawTriangles(f, g);
|
|
168
|
+
}
|
|
152
169
|
}
|
|
153
170
|
#d() {
|
|
154
171
|
if (this.#e) return this.#e;
|
|
155
172
|
let e = this.gl, t = e.createTexture();
|
|
156
|
-
e.activeTexture(e.TEXTURE15), e.bindTexture(e.TEXTURE_2D, t), e.texStorage2D(e.TEXTURE_2D, 1, e.RGBA32UI,
|
|
173
|
+
e.activeTexture(e.TEXTURE15), e.bindTexture(e.TEXTURE_2D, t), e.texStorage2D(e.TEXTURE_2D, 1, e.RGBA32UI, u, u);
|
|
157
174
|
let n = e.createRenderbuffer();
|
|
158
|
-
e.bindRenderbuffer(e.RENDERBUFFER, n), e.renderbufferStorage(e.RENDERBUFFER, e.DEPTH_COMPONENT24,
|
|
175
|
+
e.bindRenderbuffer(e.RENDERBUFFER, n), e.renderbufferStorage(e.RENDERBUFFER, e.DEPTH_COMPONENT24, u, u);
|
|
159
176
|
let r = e.createFramebuffer();
|
|
160
177
|
return e.bindFramebuffer(e.FRAMEBUFFER, r), e.framebufferTexture2D(e.FRAMEBUFFER, e.COLOR_ATTACHMENT0, e.TEXTURE_2D, t, 0), e.framebufferRenderbuffer(e.FRAMEBUFFER, e.DEPTH_ATTACHMENT, e.RENDERBUFFER, n), e.bindFramebuffer(e.FRAMEBUFFER, null), this.#e = {
|
|
161
178
|
framebuffer: r,
|
|
@@ -164,7 +181,7 @@ pickOut = uvec4(uPickId, vPickElement, floatBitsToUint(gl_FragCoord.z), 1u);
|
|
|
164
181
|
}, this.#e;
|
|
165
182
|
}
|
|
166
183
|
};
|
|
167
|
-
function
|
|
184
|
+
function h(e) {
|
|
168
185
|
let t = /* @__PURE__ */ new Map(), n = (e) => {
|
|
169
186
|
if (!e) return !0;
|
|
170
187
|
let r = t.get(e);
|
|
@@ -172,6 +189,6 @@ function f(e) {
|
|
|
172
189
|
}, r = [...e.opaque, ...e.transparent].filter((e) => n(e.node));
|
|
173
190
|
return [...r.filter((e) => e.material.depthTest), ...r.filter((e) => !e.material.depthTest)];
|
|
174
191
|
}
|
|
175
|
-
export {
|
|
192
|
+
export { m as Picker };
|
|
176
193
|
|
|
177
194
|
//# sourceMappingURL=picking.js.map
|
package/dist/picking.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"picking.js","names":["mat4.determinant","LINES_VERTEX","
|
|
1
|
+
{"version":3,"file":"picking.js","names":["mat4.determinant","LINES_VERTEX","passDefines","COMMON","POINTS_VERTEX","hookFor","CLIP","multiply","MESH_VERTEX","setHookUniforms","determinant","REGION","TOLERANCE","PICK_FRAGMENT","SOURCES","Picker","gl","programs","resources","#target","#pack","#waiting","region","#drawRegion","frame","x","y","width","height","pixelRatio","#pixels","#decode","buffer","#readBuffer","fence","poll","resolve","items","pickable","target","#ensureTarget","s","cx","cy","zoom","#projection","#viewProjection","#draw","item","i","p","at","py","px","best","bestX","bestY","bestD","dy","dx","d","o","id","depth","ndc","mode","node","kind","defines","instances","sprites","material","hook","program","worldMatrix","t","arrows","buffers","geometry","#normal","color","framebuffer","seen","ok","n","v"],"sources":[],"mappings":""}
|
package/dist/snapshot.js
CHANGED
package/dist/tooltip.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ft as e, Nt as t } from "./core.js";
|
|
2
2
|
// src/tooltip.js
|
|
3
3
|
var n = "\n:where(.phoria-tooltip) { position: fixed; left: 0; top: 0; z-index: 1000; pointer-events: none; max-width: 320px;\n padding: 6px 10px; border-radius: 6px; background: rgba(20, 20, 24, 0.92); color: #fff;\n font: 12px/1.45 system-ui, sans-serif; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); white-space: pre-line; }\n:where(.phoria-tooltip-title) { font-weight: 600; }\n:where(.phoria-tooltip-rows) { display: grid; grid-template-columns: auto auto; column-gap: 12px; }\n:where(.phoria-tooltip-rows > :nth-child(odd)) { opacity: 0.7; }\n:where(.phoria-tooltip-rows > :nth-child(even)) { text-align: right; font-variant-numeric: tabular-nums; }\n", r = 14, i = class {
|
|
4
4
|
el;
|
package/dist/types/View.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ import type { CameraOptions } from './scene/cameras.js';
|
|
|
17
17
|
import type { ColorInput, Vec3Input } from './types.js';
|
|
18
18
|
import type { Node } from './scene/Node.js';
|
|
19
19
|
import type { KeyboardOptions } from './keyboard.js';
|
|
20
|
+
import type { DebugOptions } from './debug.js';
|
|
20
21
|
export type RenderMode = 'auto' | 'always' | 'manual';
|
|
21
22
|
export type ViewOptions = {
|
|
22
23
|
/**
|
|
@@ -125,6 +126,11 @@ export type ViewOptions = {
|
|
|
125
126
|
* on and no description, one is made from the scene (charts describe themselves)
|
|
126
127
|
*/
|
|
127
128
|
description?: string | null;
|
|
129
|
+
/**
|
|
130
|
+
* pictures for checking a scene: lights, shadow cameras, bounds,
|
|
131
|
+
* normals, axes, the orbit target and a stats readout. true shows all but normals. Default false
|
|
132
|
+
*/
|
|
133
|
+
debug?: boolean | DebugOptions;
|
|
128
134
|
};
|
|
129
135
|
export type ViewEvent = 'click' | 'hover';
|
|
130
136
|
export type ViewHandler = (hit: Hit | null, event: PointerEvent | MouseEvent | null) => void;
|
|
@@ -195,6 +201,16 @@ export declare class View {
|
|
|
195
201
|
get reducedMotion(): boolean;
|
|
196
202
|
/** @param {'auto' | boolean} v */
|
|
197
203
|
set reducedMotion(v: 'auto' | boolean);
|
|
204
|
+
/**
|
|
205
|
+
* Debug drawing, or false: what it shows, as DebugOptions. Assign true for everything but normals,
|
|
206
|
+
* options for some, or false. Its code loads the first time it's turned on.
|
|
207
|
+
*
|
|
208
|
+
* view.debug = { lights: true, shadows: true, bounds: 'hovered', stats: 'bottom-right' }
|
|
209
|
+
* @returns {boolean | DebugOptions} the options in force, every one given, or false
|
|
210
|
+
*/
|
|
211
|
+
get debug(): boolean | DebugOptions;
|
|
212
|
+
/** @param {boolean | DebugOptions} v */
|
|
213
|
+
set debug(v: boolean | DebugOptions);
|
|
198
214
|
/**
|
|
199
215
|
* What the view shows, for screen readers - the canvas's label - or null. With keyboard on and no
|
|
200
216
|
* description, one is made from the scene.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Box3 } from './value/Box3.js';
|
|
2
|
+
import type { FrameDescription } from './frame.js';
|
|
3
|
+
import type { Hit } from './Raycaster.js';
|
|
4
|
+
import type { Camera } from './scene/cameras.js';
|
|
5
|
+
export type DebugOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* each light: an arrow for directional ones, a small sphere and its range
|
|
8
|
+
* for point lights, a cone for spot lights - in the light's colour
|
|
9
|
+
*/
|
|
10
|
+
lights?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* the box or cone each shadow is drawn from - the usual reason a shadow
|
|
13
|
+
* is cut off or soft
|
|
14
|
+
*/
|
|
15
|
+
shadows?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* world bounding boxes - what culling and view.frame() see
|
|
18
|
+
*/
|
|
19
|
+
bounds?: boolean | 'hovered';
|
|
20
|
+
/**
|
|
21
|
+
* short lines along vertex normals (meshes up to 5,000
|
|
22
|
+
* vertices each when all are shown)
|
|
23
|
+
*/
|
|
24
|
+
normals?: boolean | 'hovered';
|
|
25
|
+
/**
|
|
26
|
+
* x, y and z at the origin, red, green and blue
|
|
27
|
+
*/
|
|
28
|
+
axes?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* the point the camera orbits round
|
|
31
|
+
*/
|
|
32
|
+
camera?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* a readout of
|
|
35
|
+
* frame time, draw calls, triangles, programs, textures and geometries, in a corner of the canvas
|
|
36
|
+
*/
|
|
37
|
+
stats?: boolean | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
38
|
+
};
|
|
39
|
+
export declare class DebugDraw {
|
|
40
|
+
#private;
|
|
41
|
+
overlay: HTMLElement;
|
|
42
|
+
/** @param {HTMLElement | null} overlay where the stats readout goes - the layer over the canvas */
|
|
43
|
+
constructor(overlay: HTMLElement | null);
|
|
44
|
+
/**
|
|
45
|
+
* Add the helpers to a frame about to be drawn, after everything in it. Returns how many items were
|
|
46
|
+
* added to each list, to take out again once it is drawn.
|
|
47
|
+
* @param {FrameDescription} frame @param {DebugOptions} o
|
|
48
|
+
* @param {{ camera: Camera, hovered: Hit | null, bounds: Box3 }} at
|
|
49
|
+
* @returns {{ opaque: number, transparent: number }}
|
|
50
|
+
*/
|
|
51
|
+
add(frame: FrameDescription, o: DebugOptions, at: {
|
|
52
|
+
camera: Camera;
|
|
53
|
+
hovered: Hit | null;
|
|
54
|
+
bounds: Box3;
|
|
55
|
+
}): {
|
|
56
|
+
opaque: number;
|
|
57
|
+
transparent: number;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* The corner readout, refreshed a few times a second.
|
|
61
|
+
* @param {DebugOptions['stats']} where
|
|
62
|
+
* @param {{ drawCalls: number, triangles: number, programs: number, textures: number, geometries: number, compiling: number }} info
|
|
63
|
+
* @param {number} frameMs time between drawn frames @param {number} cpuMs time the last frame took to draw
|
|
64
|
+
*/
|
|
65
|
+
stats(where: DebugOptions['stats'], info: {
|
|
66
|
+
drawCalls: number;
|
|
67
|
+
triangles: number;
|
|
68
|
+
programs: number;
|
|
69
|
+
textures: number;
|
|
70
|
+
geometries: number;
|
|
71
|
+
compiling: number;
|
|
72
|
+
}, frameMs: number, cpuMs: number): void;
|
|
73
|
+
dispose(): void;
|
|
74
|
+
}
|
package/dist/types/explain.d.ts
CHANGED
|
@@ -44,6 +44,10 @@ export type ExplainInfo = {
|
|
|
44
44
|
* lines from nodes that describe themselves, such as charts
|
|
45
45
|
*/
|
|
46
46
|
notes?: string[];
|
|
47
|
+
/**
|
|
48
|
+
* what debug drawing shows, when it is on
|
|
49
|
+
*/
|
|
50
|
+
debug?: Record<string, unknown> | null;
|
|
47
51
|
};
|
|
48
52
|
/** @param {ExplainInfo} info @returns {string} */
|
|
49
53
|
export declare function explain(info: ExplainInfo): string;
|
package/dist/types/frame.d.ts
CHANGED
|
@@ -272,6 +272,10 @@ export type FrameDescription = {
|
|
|
272
272
|
drawn: number;
|
|
273
273
|
culled: number;
|
|
274
274
|
};
|
|
275
|
+
/**
|
|
276
|
+
* the View's clock in seconds, for shader hooks that read uTime
|
|
277
|
+
*/
|
|
278
|
+
time?: number;
|
|
275
279
|
/**
|
|
276
280
|
* set by the View for hover highlighting
|
|
277
281
|
*/
|
|
@@ -414,6 +418,7 @@ export type FrameDescription = {
|
|
|
414
418
|
* @property {PointShadowFrame | null} pointShadow a point light's shadow, all round it
|
|
415
419
|
* @property {FrameCap[]} caps section planes' caps to fill, after the opaque pass
|
|
416
420
|
* @property {{ drawn: number, culled: number }} stats
|
|
421
|
+
* @property {number} [time] the View's clock in seconds, for shader hooks that read uTime
|
|
417
422
|
* @property {FrameHighlight | null} highlight set by the View for hover highlighting
|
|
418
423
|
* @property {any[]} overlays HTML elements carried by the nodes drawn (node.overlay)
|
|
419
424
|
* @property {boolean} interactive some node has a tooltip, highlight or pointer handler
|
|
@@ -3,6 +3,39 @@ import { Texture } from './Texture.js';
|
|
|
3
3
|
import type { ColorInput } from '../types.js';
|
|
4
4
|
import type { TextureOptions } from './Texture.js';
|
|
5
5
|
export type MapInput = Texture | TextureOptions | string;
|
|
6
|
+
export type ShaderUniform = number | number[] | ColorInput | Texture;
|
|
7
|
+
export type ShaderHooks = {
|
|
8
|
+
/**
|
|
9
|
+
* runs on each vertex before it is placed: change `local` (vec3, the
|
|
10
|
+
* geometry's own space) - and for meshes `n`, its normal; reads `uv` (meshes), `index` (the
|
|
11
|
+
* instance, point or segment), `size` (points: change it too) and `along` (lines: 0 at a
|
|
12
|
+
* segment's start, 1 at its end)
|
|
13
|
+
*/
|
|
14
|
+
vertex?: string;
|
|
15
|
+
/**
|
|
16
|
+
* runs on each pixel before lighting: change `base` (vec4: linear
|
|
17
|
+
* colour and alpha) and, on meshes, `emissive` and `normal` (the shading normal, world space - bend it for
|
|
18
|
+
* relief lit per pixel); `discard` cuts the pixel away - shadows and
|
|
19
|
+
* picking too. Reads `vUv`, `vWorldPosition`, `vNormal` (meshes), `pointUv` and `index`
|
|
20
|
+
* (points), `distance` along the line and `index` the segment (lines)
|
|
21
|
+
*/
|
|
22
|
+
fragment?: string;
|
|
23
|
+
/**
|
|
24
|
+
* runs after lighting: change `color` (vec3, linear) and `base.a` - glows,
|
|
25
|
+
* scanlines and fades the light doesn't touch
|
|
26
|
+
*/
|
|
27
|
+
lit?: string;
|
|
28
|
+
/**
|
|
29
|
+
* values the hooks read, by name; change them on
|
|
30
|
+
* `material.shader.uniforms` and the View redraws
|
|
31
|
+
*/
|
|
32
|
+
uniforms?: Record<string, ShaderUniform>;
|
|
33
|
+
/**
|
|
34
|
+
* how far, in world units, the vertex hook can move a vertex: bounds are
|
|
35
|
+
* padded by it for culling, framing and shadows. Without it a vertex hook turns frustum culling off
|
|
36
|
+
*/
|
|
37
|
+
bounds?: number;
|
|
38
|
+
};
|
|
6
39
|
export type MaterialOptions = {
|
|
7
40
|
name?: string;
|
|
8
41
|
/**
|
|
@@ -207,6 +240,11 @@ export type MaterialOptions = {
|
|
|
207
240
|
* Points: sized in the world, so smaller with distance (default true)
|
|
208
241
|
*/
|
|
209
242
|
sizeAttenuation?: boolean;
|
|
243
|
+
/**
|
|
244
|
+
* GLSL of your own, run at fixed points in the shader - waves,
|
|
245
|
+
* dissolves, glows (default none)
|
|
246
|
+
*/
|
|
247
|
+
shader?: ShaderHooks | null;
|
|
210
248
|
/**
|
|
211
249
|
* Lines: width in pixels (default 1)
|
|
212
250
|
*/
|
|
@@ -252,6 +290,10 @@ export declare class Material {
|
|
|
252
290
|
colour: string;
|
|
253
291
|
emissiveColor: string;
|
|
254
292
|
alpha: string;
|
|
293
|
+
onBeforeCompile: string;
|
|
294
|
+
vertexShader: string;
|
|
295
|
+
fragmentShader: string;
|
|
296
|
+
uniforms: string;
|
|
255
297
|
};
|
|
256
298
|
/** @type {string} */ name: string;
|
|
257
299
|
/** @type {number} */ opacity: number;
|
|
@@ -292,6 +334,16 @@ export declare class Material {
|
|
|
292
334
|
/** Lines: how far the dashes have moved along. @type {number} */ dashOffset: number;
|
|
293
335
|
/** @param {MaterialOptions} [options] */
|
|
294
336
|
constructor(options?: MaterialOptions);
|
|
337
|
+
/**
|
|
338
|
+
* GLSL hooks run inside the shader, or null. Change its uniforms in place
|
|
339
|
+
* (`material.shader.uniforms.uAmount = 2`); assign a new object to change the code.
|
|
340
|
+
* @returns {Required<Omit<ShaderHooks, 'bounds'>> & { bounds: number | null } | null}
|
|
341
|
+
*/
|
|
342
|
+
get shader(): (Required<Omit<ShaderHooks, 'bounds'>> & {
|
|
343
|
+
bounds: number | null;
|
|
344
|
+
}) | null;
|
|
345
|
+
/** @param {ShaderHooks | null} v */
|
|
346
|
+
set shader(v: ShaderHooks | null);
|
|
295
347
|
/** Base colour; assign any colour input. @returns {Color} */
|
|
296
348
|
get color(): Color;
|
|
297
349
|
/** @param {ColorInput} v */
|
package/dist/types/watch.d.ts
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import type { Scene } from './scene/Scene.js';
|
|
2
2
|
import type { Camera } from './scene/cameras.js';
|
|
3
|
+
/** Does a material's shader hook read the clock? @param {{ vertex: string, fragment: string, lit: string }} h */
|
|
4
|
+
export declare const usesTime: (h: {
|
|
5
|
+
vertex: string;
|
|
6
|
+
fragment: string;
|
|
7
|
+
lit: string;
|
|
8
|
+
}) => boolean;
|
|
3
9
|
export declare class ChangeWatch {
|
|
4
10
|
#private;
|
|
5
11
|
/**
|
|
6
12
|
* Has anything that affects the picture changed since the last call? The first call says yes.
|
|
7
13
|
* @param {Scene} scene
|
|
8
14
|
* @param {Camera} camera
|
|
15
|
+
* @param {number} [time] the View's clock, which shader hooks reading uTime follow
|
|
9
16
|
* @returns {boolean}
|
|
10
17
|
*/
|
|
11
|
-
changed(scene: Scene, camera: Camera): boolean;
|
|
18
|
+
changed(scene: Scene, camera: Camera, time?: number): boolean;
|
|
12
19
|
/** Forget the last signature, so the next check reports a change. */
|
|
13
20
|
reset(): void;
|
|
14
21
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Texture } from '../material/Texture.js';
|
|
2
|
+
import type { Material } from '../material/Material.js';
|
|
3
|
+
import type { HookSource } from './shaders.js';
|
|
4
|
+
import type { Program } from './programs.js';
|
|
5
|
+
export type Hook = {
|
|
6
|
+
/**
|
|
7
|
+
* its code and uniform types - one program per signature
|
|
8
|
+
*/
|
|
9
|
+
signature: string;
|
|
10
|
+
/**
|
|
11
|
+
* HOOK_VERTEX, HOOK_FRAGMENT, HOOK_LIT for the parts it has, and its id
|
|
12
|
+
*/
|
|
13
|
+
defines: string[];
|
|
14
|
+
/**
|
|
15
|
+
* what the shaders splice in
|
|
16
|
+
*/
|
|
17
|
+
source: HookSource;
|
|
18
|
+
/**
|
|
19
|
+
* it has a vertex hook
|
|
20
|
+
*/
|
|
21
|
+
moves: boolean;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* The hooks a material draws with, or null: none, or ones that failed to compile.
|
|
25
|
+
* @param {Material} material
|
|
26
|
+
* @returns {Hook | null}
|
|
27
|
+
*/
|
|
28
|
+
export declare function hookFor(material: Material): Hook | null;
|
|
29
|
+
/**
|
|
30
|
+
* Defines for a pass that isn't the colour pass: the vertex hook always - so a shadow, an outline or
|
|
31
|
+
* a pick is of the moved shape - and the fragment hook only where its discards should cut (meshes'
|
|
32
|
+
* shadows and picks); never the lit hook.
|
|
33
|
+
* @param {Hook} hook @param {boolean} cuts
|
|
34
|
+
*/
|
|
35
|
+
export declare function passDefines(hook: Hook, cuts: boolean): string[];
|
|
36
|
+
/**
|
|
37
|
+
* Set the hook's uniforms: the clock, where the camera is, and the material's own values.
|
|
38
|
+
* @param {Program} program @param {Material} material @param {number} time
|
|
39
|
+
* @param {ArrayLike<number>} camera the camera's world position
|
|
40
|
+
* @param {(t: Texture) => WebGLTexture} texture
|
|
41
|
+
*/
|
|
42
|
+
export declare function setHookUniforms(program: Program, material: Material, time: number, camera: ArrayLike<number>, texture: (t: Texture) => WebGLTexture): void;
|
|
43
|
+
/**
|
|
44
|
+
* A program built with a material's hooks failed: say why, once, in the hook's own terms, and draw
|
|
45
|
+
* the material without them from now on.
|
|
46
|
+
* @param {Material} material @param {Hook} hook @param {string} log the compiler's
|
|
47
|
+
*/
|
|
48
|
+
export declare function hookFailed(material: Material, hook: Hook, log: string): void;
|
|
@@ -73,6 +73,10 @@ export declare class Passes {
|
|
|
73
73
|
gl: WebGL2RenderingContext;
|
|
74
74
|
programs: Programs;
|
|
75
75
|
resources: Resources;
|
|
76
|
+
/** The View's clock, for shader hooks that read uTime - set by the renderer each frame. */
|
|
77
|
+
time: number;
|
|
78
|
+
/** The camera's world position, for shader hooks' fresnel and cameraPosition - set each frame too. @type {ArrayLike<number>} */
|
|
79
|
+
cameraPosition: ArrayLike<number>;
|
|
76
80
|
/** Rendering to float textures, which environments need. */
|
|
77
81
|
floatTargets: boolean;
|
|
78
82
|
/** @param {WebGL2RenderingContext} gl @param {Programs} programs @param {Resources} resources */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ShaderKind } from './shaders.js';
|
|
1
|
+
import type { HookSource, ShaderKind } from './shaders.js';
|
|
2
2
|
export type Program = {
|
|
3
3
|
program: WebGLProgram;
|
|
4
4
|
key: string;
|
|
@@ -14,12 +14,18 @@ export type Program = {
|
|
|
14
14
|
* compiled, linked and its uniforms found
|
|
15
15
|
*/
|
|
16
16
|
ready: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* the compiler's log, for a program with a material's shader hooks that
|
|
19
|
+
* failed - those are reported and drawn without, rather than thrown
|
|
20
|
+
*/
|
|
21
|
+
failed?: string;
|
|
17
22
|
};
|
|
18
23
|
export type Building = Program & {
|
|
19
24
|
shaders: [WebGLShader, WebGLShader];
|
|
20
25
|
sources: [string, string];
|
|
26
|
+
hooked: boolean;
|
|
21
27
|
};
|
|
22
|
-
/** @import { ShaderKind } from './shaders.js' */
|
|
28
|
+
/** @import { HookSource, ShaderKind } from './shaders.js' */
|
|
23
29
|
/**
|
|
24
30
|
* @typedef {object} Program
|
|
25
31
|
* @property {WebGLProgram} program
|
|
@@ -27,9 +33,11 @@ export type Building = Program & {
|
|
|
27
33
|
* @property {(name: string, value: any) => void} set set a uniform by name (ignored if the shader doesn't use it)
|
|
28
34
|
* @property {number} frame the frame its per-frame uniforms were last set for
|
|
29
35
|
* @property {boolean} ready compiled, linked and its uniforms found
|
|
36
|
+
* @property {string} [failed] the compiler's log, for a program with a material's shader hooks that
|
|
37
|
+
* failed - those are reported and drawn without, rather than thrown
|
|
30
38
|
*/
|
|
31
39
|
/**
|
|
32
|
-
* @typedef {Program & { shaders: [WebGLShader, WebGLShader], sources: [string, string] }} Building
|
|
40
|
+
* @typedef {Program & { shaders: [WebGLShader, WebGLShader], sources: [string, string], hooked: boolean }} Building
|
|
33
41
|
*/
|
|
34
42
|
export declare class Programs {
|
|
35
43
|
#private;
|
|
@@ -45,16 +53,18 @@ export declare class Programs {
|
|
|
45
53
|
* @param {ShaderKind | string} kind a drawable kind, or a pass's name when it brings its sources
|
|
46
54
|
* @param {string[]} defines
|
|
47
55
|
* @param {[string, string]} [sources] a pass's vertex and fragment shaders
|
|
56
|
+
* @param {HookSource | null} [hooks] a material's shader hooks, spliced in (its id is in the defines)
|
|
48
57
|
* @returns {Program}
|
|
49
58
|
*/
|
|
50
|
-
get(kind: ShaderKind | string, defines: string[], sources?: [string, string]): Program;
|
|
59
|
+
get(kind: ShaderKind | string, defines: string[], sources?: [string, string], hooks?: HookSource | null): Program;
|
|
51
60
|
/**
|
|
52
61
|
* A program, waiting for it to finish compiling if it hasn't - for passes and picking, which
|
|
53
62
|
* need their programs now.
|
|
54
63
|
* @param {ShaderKind | string} kind @param {string[]} defines @param {[string, string]} [sources]
|
|
64
|
+
* @param {HookSource | null} [hooks]
|
|
55
65
|
* @returns {Program}
|
|
56
66
|
*/
|
|
57
|
-
ready(kind: ShaderKind | string, defines: string[], sources?: [string, string]): Program;
|
|
67
|
+
ready(kind: ShaderKind | string, defines: string[], sources?: [string, string], hooks?: HookSource | null): Program;
|
|
58
68
|
/**
|
|
59
69
|
* Has it finished compiling? Asks without waiting, and finishes it (finding its uniforms) once
|
|
60
70
|
* it has.
|