@expofp/renderer 3.2.5 → 3.27.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.
Files changed (228) hide show
  1. package/README.md +111 -0
  2. package/dist/Renderer.d.ts +88 -0
  3. package/dist/Renderer.js +53 -0
  4. package/dist/controls/CameraControls.d.ts +102 -0
  5. package/dist/controls/CameraControls.js +239 -0
  6. package/dist/controls/camera-api.d.ts +206 -0
  7. package/dist/controls/camera-api.js +181 -0
  8. package/dist/controls/camera-move.d.ts +13 -0
  9. package/dist/controls/camera-move.js +18 -0
  10. package/dist/controls/camera-state.d.ts +40 -0
  11. package/dist/controls/camera-state.js +65 -0
  12. package/dist/controls/gestures.d.ts +70 -0
  13. package/dist/controls/gestures.js +84 -0
  14. package/dist/controls/handlers/Inertia.d.ts +111 -0
  15. package/dist/controls/handlers/Inertia.js +215 -0
  16. package/dist/controls/handlers/Pan.d.ts +23 -0
  17. package/dist/controls/handlers/Pan.js +32 -0
  18. package/dist/controls/handlers/Pitch.d.ts +94 -0
  19. package/dist/controls/handlers/Pitch.js +191 -0
  20. package/dist/controls/handlers/Roll.d.ts +103 -0
  21. package/dist/controls/handlers/Roll.js +182 -0
  22. package/dist/controls/handlers/Zoom.d.ts +15 -0
  23. package/dist/controls/handlers/Zoom.js +26 -0
  24. package/dist/controls/index.d.ts +56 -0
  25. package/dist/controls/index.js +58 -0
  26. package/dist/controls/zoom-to.d.ts +89 -0
  27. package/dist/controls/zoom-to.js +91 -0
  28. package/dist/core/InstanceUniforms.d.ts +93 -0
  29. package/dist/core/InstanceUniforms.js +266 -0
  30. package/dist/core/SquareDataTexture.d.ts +277 -0
  31. package/dist/core/SquareDataTexture.js +476 -0
  32. package/dist/core/batch/BatchedMesh.d.ts +74 -0
  33. package/dist/core/batch/BatchedMesh.js +149 -0
  34. package/dist/core/instanced/FrustumCulling.d.ts +141 -0
  35. package/dist/core/instanced/FrustumCulling.js +246 -0
  36. package/dist/core/instanced/InstancedMesh.d.ts +302 -0
  37. package/dist/core/instanced/InstancedMesh.js +497 -0
  38. package/dist/core/instanced/Instances.d.ts +119 -0
  39. package/dist/core/instanced/Instances.js +230 -0
  40. package/dist/core/instanced/Raycasting.d.ts +118 -0
  41. package/dist/core/instanced/Raycasting.js +134 -0
  42. package/dist/core/instanced/instanced-material.d.ts +77 -0
  43. package/dist/core/instanced/instanced-material.js +224 -0
  44. package/dist/core/lines/BatchedLines.d.ts +135 -0
  45. package/dist/core/lines/BatchedLines.js +213 -0
  46. package/dist/core/lines/FrustumCulling.d.ts +43 -0
  47. package/dist/core/lines/FrustumCulling.js +85 -0
  48. package/dist/core/lines/Raycasting.d.ts +44 -0
  49. package/dist/core/lines/Raycasting.js +91 -0
  50. package/dist/core/lines/lines-material.d.ts +47 -0
  51. package/dist/core/lines/lines-material.js +115 -0
  52. package/dist/core/shader-source.d.ts +50 -0
  53. package/dist/core/shader-source.js +84 -0
  54. package/dist/core/text/BatchedText.d.ts +227 -0
  55. package/dist/core/text/BatchedText.js +467 -0
  56. package/dist/core/text/MemberTexture.d.ts +90 -0
  57. package/dist/core/text/MemberTexture.js +194 -0
  58. package/dist/core/text/Text.d.ts +73 -0
  59. package/dist/core/text/Text.js +215 -0
  60. package/dist/core/text/batched-text-material.d.ts +56 -0
  61. package/dist/core/text/batched-text-material.js +121 -0
  62. package/dist/core/text/glyph-packing.d.ts +17 -0
  63. package/dist/core/text/glyph-packing.js +61 -0
  64. package/dist/core/typed-array.d.ts +16 -0
  65. package/dist/core/typed-array.js +20 -0
  66. package/dist/debug/components/DebugPanelProvider.d.ts +20 -0
  67. package/dist/debug/components/DebugPanelProvider.js +38 -0
  68. package/dist/debug/components/DebugTools.d.ts +22 -0
  69. package/dist/debug/components/DebugTools.js +28 -0
  70. package/dist/debug/components/Gui.d.ts +20 -0
  71. package/dist/debug/components/Gui.js +32 -0
  72. package/dist/debug/components/MemoryInfo.d.ts +22 -0
  73. package/dist/debug/components/MemoryInfo.js +42 -0
  74. package/dist/debug/components/Panel.d.ts +31 -0
  75. package/dist/debug/components/Panel.js +98 -0
  76. package/dist/debug/components/Stats.d.ts +9 -0
  77. package/dist/debug/components/Stats.js +24 -0
  78. package/dist/debug/debug-context.d.ts +41 -0
  79. package/dist/debug/debug-context.js +59 -0
  80. package/dist/debug/index.d.ts +51 -0
  81. package/dist/debug/index.js +64 -0
  82. package/dist/events/LayoutDriver.d.ts +31 -0
  83. package/dist/events/LayoutDriver.js +88 -0
  84. package/dist/events/PointerMissed.d.ts +23 -0
  85. package/dist/events/PointerMissed.js +58 -0
  86. package/dist/events/def-culling.d.ts +46 -0
  87. package/dist/events/def-culling.js +69 -0
  88. package/dist/events/layout-targets.d.ts +104 -0
  89. package/dist/events/layout-targets.js +245 -0
  90. package/dist/events/pointer.d.ts +118 -0
  91. package/dist/events/pointer.js +168 -0
  92. package/dist/external/ExternalCanvas.d.ts +56 -0
  93. package/dist/external/ExternalCanvas.js +178 -0
  94. package/dist/external/external-camera.d.ts +17 -0
  95. package/dist/external/external-camera.js +82 -0
  96. package/dist/external/external-events.d.ts +14 -0
  97. package/dist/external/external-events.js +33 -0
  98. package/dist/index.d.ts +11 -783
  99. package/dist/index.js +12 -8031
  100. package/dist/objects/Background.d.ts +31 -0
  101. package/dist/objects/Background.js +37 -0
  102. package/dist/objects/Lighting.d.ts +20 -0
  103. package/dist/objects/Lighting.js +85 -0
  104. package/dist/objects/containers/SlotContainer.d.ts +266 -0
  105. package/dist/objects/containers/SlotContainer.js +251 -0
  106. package/dist/objects/containers/hooks.d.ts +46 -0
  107. package/dist/objects/containers/hooks.js +118 -0
  108. package/dist/objects/containers/index.d.ts +6 -0
  109. package/dist/objects/containers/index.js +4 -0
  110. package/dist/objects/containers/keys.d.ts +10 -0
  111. package/dist/objects/containers/keys.js +18 -0
  112. package/dist/objects/containers/mesh-writes.d.ts +106 -0
  113. package/dist/objects/containers/mesh-writes.js +97 -0
  114. package/dist/objects/containers/props.d.ts +23 -0
  115. package/dist/objects/containers/props.js +1 -0
  116. package/dist/objects/images/ImageInstance.d.ts +29 -0
  117. package/dist/objects/images/ImageInstance.js +83 -0
  118. package/dist/objects/images/Images.d.ts +37 -0
  119. package/dist/objects/images/Images.js +204 -0
  120. package/dist/objects/images/atlas-packer.d.ts +128 -0
  121. package/dist/objects/images/atlas-packer.js +315 -0
  122. package/dist/objects/images/image-container.d.ts +51 -0
  123. package/dist/objects/images/image-container.js +70 -0
  124. package/dist/objects/images/index.d.ts +2 -0
  125. package/dist/objects/images/index.js +1 -0
  126. package/dist/objects/images/texture-budget.d.ts +120 -0
  127. package/dist/objects/images/texture-budget.js +215 -0
  128. package/dist/objects/layer/Layer.d.ts +27 -0
  129. package/dist/objects/layer/Layer.js +114 -0
  130. package/dist/objects/layer/index.d.ts +2 -0
  131. package/dist/objects/layer/index.js +1 -0
  132. package/dist/objects/layer/mount-scheduler.d.ts +102 -0
  133. package/dist/objects/layer/mount-scheduler.js +145 -0
  134. package/dist/objects/layer/visibility-gui.d.ts +19 -0
  135. package/dist/objects/layer/visibility-gui.js +93 -0
  136. package/dist/objects/lines/LineInstance.d.ts +21 -0
  137. package/dist/objects/lines/LineInstance.js +73 -0
  138. package/dist/objects/lines/Lines.d.ts +17 -0
  139. package/dist/objects/lines/Lines.js +29 -0
  140. package/dist/objects/lines/index.d.ts +2 -0
  141. package/dist/objects/lines/index.js +1 -0
  142. package/dist/objects/lines/line-container.d.ts +35 -0
  143. package/dist/objects/lines/line-container.js +40 -0
  144. package/dist/objects/materials/ColorMaterial.d.ts +85 -0
  145. package/dist/objects/materials/ColorMaterial.js +89 -0
  146. package/dist/objects/materials/LineMaterial.d.ts +44 -0
  147. package/dist/objects/materials/LineMaterial.js +72 -0
  148. package/dist/objects/materials/ModelMaterial.d.ts +41 -0
  149. package/dist/objects/materials/ModelMaterial.js +84 -0
  150. package/dist/objects/materials/TextureMaterial.d.ts +30 -0
  151. package/dist/objects/materials/TextureMaterial.js +29 -0
  152. package/dist/objects/materials/dim.d.ts +123 -0
  153. package/dist/objects/materials/dim.js +213 -0
  154. package/dist/objects/materials/shared.d.ts +6 -0
  155. package/dist/objects/materials/shared.js +51 -0
  156. package/dist/objects/models/ModelInstance.d.ts +22 -0
  157. package/dist/objects/models/ModelInstance.js +33 -0
  158. package/dist/objects/models/Models.d.ts +22 -0
  159. package/dist/objects/models/Models.js +177 -0
  160. package/dist/objects/models/gltf-cache.d.ts +17 -0
  161. package/dist/objects/models/gltf-cache.js +50 -0
  162. package/dist/objects/models/index.d.ts +2 -0
  163. package/dist/objects/models/index.js +1 -0
  164. package/dist/objects/models/model-asset.d.ts +48 -0
  165. package/dist/objects/models/model-asset.js +77 -0
  166. package/dist/objects/models/model-container.d.ts +139 -0
  167. package/dist/objects/models/model-container.js +227 -0
  168. package/dist/objects/shapes/ShapeInstance.d.ts +26 -0
  169. package/dist/objects/shapes/ShapeInstance.js +40 -0
  170. package/dist/objects/shapes/Shapes.d.ts +21 -0
  171. package/dist/objects/shapes/Shapes.js +120 -0
  172. package/dist/objects/shapes/index.d.ts +2 -0
  173. package/dist/objects/shapes/index.js +1 -0
  174. package/dist/objects/shapes/shape-container.d.ts +165 -0
  175. package/dist/objects/shapes/shape-container.js +272 -0
  176. package/dist/objects/shapes/shape-geometry.d.ts +27 -0
  177. package/dist/objects/shapes/shape-geometry.js +94 -0
  178. package/dist/objects/text/TextInstance.d.ts +22 -0
  179. package/dist/objects/text/TextInstance.js +95 -0
  180. package/dist/objects/text/Texts.d.ts +30 -0
  181. package/dist/objects/text/Texts.js +41 -0
  182. package/dist/objects/text/index.d.ts +2 -0
  183. package/dist/objects/text/index.js +1 -0
  184. package/dist/objects/text/text-container.d.ts +105 -0
  185. package/dist/objects/text/text-container.js +206 -0
  186. package/dist/objects/text/text-layout.d.ts +83 -0
  187. package/dist/objects/text/text-layout.js +154 -0
  188. package/dist/space/Camera.d.ts +103 -0
  189. package/dist/space/Camera.js +321 -0
  190. package/dist/space/Scene.d.ts +44 -0
  191. package/dist/space/Scene.js +112 -0
  192. package/dist/space/Space.d.ts +288 -0
  193. package/dist/space/Space.js +329 -0
  194. package/dist/space/VisibleRect.d.ts +72 -0
  195. package/dist/space/VisibleRect.js +129 -0
  196. package/dist/space/camera-handle.d.ts +67 -0
  197. package/dist/space/camera-handle.js +63 -0
  198. package/dist/space/camera-kind.d.ts +26 -0
  199. package/dist/space/camera-kind.js +30 -0
  200. package/dist/space/canvas-size.d.ts +24 -0
  201. package/dist/space/canvas-size.js +20 -0
  202. package/dist/space/clipping.d.ts +55 -0
  203. package/dist/space/clipping.js +108 -0
  204. package/dist/space/layout-measure.d.ts +65 -0
  205. package/dist/space/layout-measure.js +173 -0
  206. package/dist/space/viewport.d.ts +112 -0
  207. package/dist/space/viewport.js +67 -0
  208. package/dist/types/defs.d.ts +169 -0
  209. package/dist/types/defs.js +1 -0
  210. package/dist/types/events.d.ts +183 -0
  211. package/dist/types/events.js +1 -0
  212. package/dist/types/guards.d.ts +14 -0
  213. package/dist/types/guards.js +42 -0
  214. package/dist/update/index.d.ts +3 -0
  215. package/dist/update/index.js +2 -0
  216. package/dist/update/slot-writers.d.ts +30 -0
  217. package/dist/update/slot-writers.js +72 -0
  218. package/dist/update/store.d.ts +41 -0
  219. package/dist/update/store.js +98 -0
  220. package/dist/utils/arrays.d.ts +13 -0
  221. package/dist/utils/arrays.js +20 -0
  222. package/dist/utils/colors.d.ts +19 -0
  223. package/dist/utils/colors.js +27 -0
  224. package/dist/utils/logging.d.ts +26 -0
  225. package/dist/utils/logging.js +47 -0
  226. package/dist/utils/math.d.ts +24 -0
  227. package/dist/utils/math.js +27 -0
  228. package/package.json +67 -19
@@ -0,0 +1,31 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type ColorInput } from '../types/defs';
3
+ /** Props for {@link Background}. */
4
+ export interface BackgroundProps {
5
+ /** The background color. */
6
+ color: ColorInput;
7
+ }
8
+ /**
9
+ * The scene's background: a screen-space quad drawn below every layer, replacing what a clear
10
+ * color would paint — and unlike one, dimmed with the venue. The root `Layer` renders it inside
11
+ * its own group, under the root layer's dim provider, so the dim reaches this material exactly as
12
+ * it reaches a layer's.
13
+ *
14
+ * **Screen-space in the vertex shader**, as the imperative renderer drew it: projection is
15
+ * replaced with the quad's own xy in clip space at the far plane, so it covers the canvas edge to
16
+ * edge under any camera — fit, zoom, roll, pitch — and no matrix above it is ever read.
17
+ *
18
+ * It draws through the same {@link ColorMaterial} as the layers, with one addition through the
19
+ * material's pre-dim hook: a quad has no batch prologue, so the per-instance dim uniform the
20
+ * unmodified dim patch looks for is declared here as a constant pinned to "inherit" — every
21
+ * fragment defers to the layer amount, which is the point.
22
+ *
23
+ * **Draw order**: `renderOrder` 0 puts it level with the first layer group, and the tie falls to
24
+ * `material.id` — this material is created as the root layer mounts, before the scheduler admits
25
+ * any leaf, so it draws first. That ordering is load-bearing: flat content writes no depth, so
26
+ * anything drawn after the quad simply paints over it.
27
+ * @param props - The color.
28
+ * @returns The quad.
29
+ */
30
+ export declare function Background(props: BackgroundProps): ReactNode;
31
+ //# sourceMappingURL=Background.d.ts.map
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { declareBeforeMain } from '../core/shader-source';
4
+ import { ColorMaterial } from './materials/ColorMaterial';
5
+ import { DIM_INHERIT, DIM_UNIFORM } from './materials/dim';
6
+ /**
7
+ * The scene's background: a screen-space quad drawn below every layer, replacing what a clear
8
+ * color would paint — and unlike one, dimmed with the venue. The root `Layer` renders it inside
9
+ * its own group, under the root layer's dim provider, so the dim reaches this material exactly as
10
+ * it reaches a layer's.
11
+ *
12
+ * **Screen-space in the vertex shader**, as the imperative renderer drew it: projection is
13
+ * replaced with the quad's own xy in clip space at the far plane, so it covers the canvas edge to
14
+ * edge under any camera — fit, zoom, roll, pitch — and no matrix above it is ever read.
15
+ *
16
+ * It draws through the same {@link ColorMaterial} as the layers, with one addition through the
17
+ * material's pre-dim hook: a quad has no batch prologue, so the per-instance dim uniform the
18
+ * unmodified dim patch looks for is declared here as a constant pinned to "inherit" — every
19
+ * fragment defers to the layer amount, which is the point.
20
+ *
21
+ * **Draw order**: `renderOrder` 0 puts it level with the first layer group, and the tie falls to
22
+ * `material.id` — this material is created as the root layer mounts, before the scheduler admits
23
+ * any leaf, so it draws first. That ordering is load-bearing: flat content writes no depth, so
24
+ * anything drawn after the quad simply paints over it.
25
+ * @param props - The color.
26
+ * @returns The quad.
27
+ */
28
+ export function Background(props) {
29
+ // One handler for the material's life, per `ColorMaterial`'s contract for its pre-dim hook.
30
+ const [onBeforeCompile] = useState(() => (parameters) => {
31
+ parameters.vertexShader = parameters.vertexShader.replace('#include <project_vertex>',
32
+ /* glsl */ `gl_Position = vec4(transformed.xy, 1.0, 1.0);`);
33
+ parameters.fragmentShader = declareBeforeMain(parameters.fragmentShader,
34
+ /* glsl */ `const float ${DIM_UNIFORM} = ${DIM_INHERIT}.0;`);
35
+ });
36
+ return (_jsxs("mesh", { name: "background", renderOrder: 0, frustumCulled: false, children: [_jsx("planeGeometry", { args: [2, 2] }), _jsx(ColorMaterial, { color: props.color, onBeforeCompile: onBeforeCompile })] }));
37
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Scene lighting: a hemisphere fill from above the plan plus a directional key that follows the
3
+ * camera, so a surface square-on to the viewer is shaded by exactly its own color (see
4
+ * {@link HALF_ALBEDO}).
5
+ *
6
+ * Only lit materials see any of this — solid shape batches and models. Every 2D primitive draws
7
+ * through a `MeshBasicMaterial`, so lines, text and images are unaffected by a light no matter what
8
+ * the scene holds. That is deliberate: a route line or a booth label has no meaningful surface
9
+ * normal, and shading one would make its color depend on where the camera is.
10
+ *
11
+ * **These sit inside the scene's world matrix**, so every direction below is expressed in the plan's
12
+ * own space and taken there through {@link Space.matrixInverse} — one inverse, shared, rather than
13
+ * one per light. Three reads a light's direction from where it ends up in the *world*, so the two
14
+ * transforms cancel and the light points where it was aimed under any fit. The key light needs a
15
+ * target inside the same space for that to hold: its direction is the difference of two world
16
+ * positions, and only a target under the same matrix cancels the fit's translation.
17
+ * @returns The fill and key lights, and the key's target.
18
+ */
19
+ export declare function Lighting(): import("react").JSX.Element;
20
+ //# sourceMappingURL=Lighting.d.ts.map
@@ -0,0 +1,85 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useFrame } from '@react-three/fiber';
3
+ import { useLayoutEffect, useRef } from 'react';
4
+ import { Color } from 'three';
5
+ import { useSpace } from '../space/Space';
6
+ /**
7
+ * Scene lighting: a hemisphere fill from above the plan plus a directional key that follows the
8
+ * camera, so a surface square-on to the viewer is shaded by exactly its own color (see
9
+ * {@link HALF_ALBEDO}).
10
+ *
11
+ * Only lit materials see any of this — solid shape batches and models. Every 2D primitive draws
12
+ * through a `MeshBasicMaterial`, so lines, text and images are unaffected by a light no matter what
13
+ * the scene holds. That is deliberate: a route line or a booth label has no meaningful surface
14
+ * normal, and shading one would make its color depend on where the camera is.
15
+ *
16
+ * **These sit inside the scene's world matrix**, so every direction below is expressed in the plan's
17
+ * own space and taken there through {@link Space.matrixInverse} — one inverse, shared, rather than
18
+ * one per light. Three reads a light's direction from where it ends up in the *world*, so the two
19
+ * transforms cancel and the light points where it was aimed under any fit. The key light needs a
20
+ * target inside the same space for that to hold: its direction is the difference of two world
21
+ * positions, and only a target under the same matrix cancels the fit's translation.
22
+ * @returns The fill and key lights, and the key's target.
23
+ */
24
+ export function Lighting() {
25
+ const fillRef = useRef(null);
26
+ const keyRef = useRef(null);
27
+ const targetRef = useRef(null);
28
+ const space = useSpace();
29
+ useLayoutEffect(() => {
30
+ keyRef.current.target = targetRef.current;
31
+ }, []);
32
+ // Taken from the camera's own backward axis rather than from the controls' target: only the
33
+ // direction matters for a directional light — the target below pins the other end — so this needs
34
+ // no access to `controls`, and unlike normalizing the camera's *position* it stays correct when
35
+ // the plan's coordinates are far from the origin, which SVG viewboxes routinely are.
36
+ //
37
+ // Column 2 of `matrixWorld` is that backward axis: where the light belongs, shining from the
38
+ // camera toward what it looks at. Read with `setFromMatrixColumn` rather than through
39
+ // `Camera.getWorldDirection`, which negates the axis and, worse, re-runs `updateWorldMatrix` —
40
+ // leaving the camera's `matrixWorldNeedsUpdate` set on every single call, which kept the scene
41
+ // perpetually dirty and no screenshot ever settled.
42
+ //
43
+ // Under the on-demand loop this runs only on frames something already asked for, and camera
44
+ // movement is what asks for them, so a still plan costs nothing.
45
+ useFrame((state) => {
46
+ keyRef.current.position
47
+ .setFromMatrixColumn(state.camera.matrixWorld, 2)
48
+ .transformDirection(space.matrixInverse);
49
+ // The plan's own up axis, as a point whose world position lands back on it — which is what three
50
+ // reads a hemisphere light's sky axis from. Under the viewbox fit that axis is world -z, the
51
+ // side the camera is on; under a caller's own transform it is wherever that transform puts it.
52
+ //
53
+ // Computed here rather than memoized against the space because the space is refitted in place
54
+ // and so never changes identity — and it is four vector operations on a frame that was going to
55
+ // aim the key light anyway.
56
+ fillRef.current.position
57
+ .setFromMatrixColumn(space.matrix, 2)
58
+ .normalize()
59
+ .applyMatrix4(space.matrixInverse);
60
+ });
61
+ return (_jsxs(_Fragment, { children: [_jsx("hemisphereLight", { ref: fillRef, color: LIGHT_COLOR, groundColor: GROUND_COLOR, intensity: HALF_ALBEDO }), _jsx("directionalLight", { ref: keyRef, color: LIGHT_COLOR, intensity: HALF_ALBEDO }), _jsx("object3D", { ref: targetRef })] }));
62
+ }
63
+ /**
64
+ * Each light's intensity, so the two together sum to `π`.
65
+ *
66
+ * three's diffuse BRDF is `albedo / π`, so a light of intensity `I` reaching a surface head-on
67
+ * contributes `I · albedo / π`. At `0.5π` each contributes half the albedo, and the pair sums to
68
+ * exactly the albedo — a surface facing the camera therefore renders at precisely the color the plan
69
+ * author picked, and only faces turning away darken. The key light tracks the camera and the fill's
70
+ * sky axis points at it too, so "facing the camera" is the same set of surfaces for both.
71
+ *
72
+ * Two things elsewhere are load-bearing for that identity rather than cosmetic: the lit material sets
73
+ * `ior = 1` and `specularIntensity = 0`, which drive `F0` to zero so no specular lobe pushes a facing
74
+ * surface *above* its albedo, and `<Canvas flat>` keeps tone mapping off, which would remap the
75
+ * result. Change either and the identity quietly stops holding.
76
+ */
77
+ const HALF_ALBEDO = 0.5 * Math.PI;
78
+ /**
79
+ * Both lights' color — one shared constant, because the {@link HALF_ALBEDO} identity is a property
80
+ * of the pair: two halves sum back to the author's color only when they are halves of the *same*
81
+ * color. Each light copies it on mount, so writing to a light's own color never reaches the other.
82
+ */
83
+ const LIGHT_COLOR = new Color('white');
84
+ /** The fill's ground half: pure black, so the side facing away from the sky axis adds nothing. */
85
+ const GROUND_COLOR = new Color('black');
@@ -0,0 +1,266 @@
1
+ import { type Intersection, type Object3D } from 'three';
2
+ import { type UniformSchemaShader } from '../../core/InstanceUniforms';
3
+ import { type UniformValue } from '../../core/SquareDataTexture';
4
+ import { type RenderableDef } from '../../types/defs';
5
+ /**
6
+ * What a container needs from the mesh it writes into.
7
+ *
8
+ * A capability rather than a union of our mesh classes: `BatchedMeshExt`, `InstancedMeshExt`,
9
+ * `BatchedLinesExt` and `BatchedTextExt` share no base below `Object3D`, yet every one of them
10
+ * declares per-instance uniforms and hides an instance the same way — which is all a container
11
+ * touches generically. Everything else it reaches through its own mesh type, which the subclass
12
+ * names.
13
+ */
14
+ export interface SlotMesh extends Object3D {
15
+ /**
16
+ * Declares per-instance uniforms, merged with whatever is already declared.
17
+ * @param schema - The uniforms to add.
18
+ */
19
+ addUniforms(schema: UniformSchemaShader): void;
20
+ /**
21
+ * Writes one instance's uniform.
22
+ * @param slot - The instance to write.
23
+ * @param name - The uniform's name.
24
+ * @param value - The value to write.
25
+ */
26
+ setUniformAt(slot: number, name: string, value: UniformValue): void;
27
+ /**
28
+ * Shows or hides one instance.
29
+ * @param slot - The instance to show or hide.
30
+ * @param visible - Whether it draws.
31
+ */
32
+ setVisibleAt(slot: number, visible: boolean): void;
33
+ }
34
+ /**
35
+ * An entry in a mesh's render list. Every mesh's sort callback receives a list of these — the
36
+ * published shapes differ in what else they carry, but each entry identifies its instance by
37
+ * `index`, which is all a paint-order sort needs.
38
+ */
39
+ export interface RenderListItem {
40
+ /** The instance id the entry draws. */
41
+ index: number;
42
+ }
43
+ /**
44
+ * One entry in the list `BatchedMesh.customSort` receives. three's published types describe only
45
+ * `start`, `count`, and `z`, but the runtime also passes `index` — the instance id — which is the
46
+ * only way a sort can map an entry back to the instance that produced it.
47
+ */
48
+ export interface BatchedMeshRenderItem extends RenderListItem {
49
+ /** Offset of the instance's geometry in the shared draw range. */
50
+ start: number;
51
+ /** Length of the instance's geometry draw range. */
52
+ count: number;
53
+ /** Instance depth along the camera's view direction. */
54
+ z: number;
55
+ }
56
+ /** How one container differs from the default, passed up by its constructor. */
57
+ export interface SlotContainerOptions {
58
+ /**
59
+ * The per-instance uniforms the mesh declares on {@link SlotContainer.bind}. Defaults to the dim
60
+ * alone, which every def type carries. A container whose mesh needs more (an image's uv region, a
61
+ * model's opacity) passes the merged schema rather than declaring twice: `InstanceUniforms.add`
62
+ * rebuilds the backing texture, so two calls would build it twice per bind.
63
+ */
64
+ schema?: UniformSchemaShader;
65
+ /**
66
+ * Sort the draw list descending, so the *first* instance drawn is the one that paints on top.
67
+ *
68
+ * For a batch whose material keeps the first fragment to reach a pixel and rejects the rest,
69
+ * which is how the line material stops translucent lines darkening where they overlap: there,
70
+ * draw order is the reverse of paint order. Slots are still labeled in paint order either way.
71
+ */
72
+ reverse?: boolean;
73
+ }
74
+ /**
75
+ * One layer's mesh bookkeeping: the bound mesh, which slot each def holds, and the paint order
76
+ * across them.
77
+ *
78
+ * A container is what stands between a layer's defs and one mesh. It is created during render,
79
+ * sized to the membership it first sees, and held in `useState` for as long as its component is
80
+ * mounted; the mesh itself is R3F's, constructed from the subclass's args and handed back through
81
+ * {@link bind}, so R3F owns its lifetime and disposal. Instances claim and release slots from their
82
+ * own effects, and write their type-specific state through the subclass's own methods.
83
+ *
84
+ * What lives here is everything that does not depend on which def type is drawn:
85
+ *
86
+ * - **Slot allocation**, in both directions. `slotOf` is what a paint-order pass over the layer's
87
+ * defs looks each def up with, and {@link defAt} is what turns a pointer hit — which names a slot
88
+ * — back into the def that drew it. Slots come from a mesh's free list, so a released slot may be
89
+ * handed to a different def later; freeing by slot keeps both directions from outliving the claim
90
+ * they describe.
91
+ * - **Paint order**, explicitly. Instance ids come from a mesh's free list, so they do not track
92
+ * sibling order — a container that let slot order stand in for paint order would reorder itself
93
+ * after any claim/release churn, and again under StrictMode's remount, which re-claims in reverse.
94
+ * Explicit order is also what the 2D painter's algorithm needs: 2D content never writes depth, so
95
+ * nothing it draws is in the buffer for the next 2D fragment to test against, and the draw list's
96
+ * order is the only thing that decides overlap.
97
+ * - **The two fields every def type carries**, `hidden` and `dim`, through {@link setVisibleAt} and
98
+ * {@link setDimAt} — which is what lets one hook drive them for every def type.
99
+ *
100
+ * A subclass supplies {@link addInstance} and {@link removeInstance}, names its mesh and def types,
101
+ * and adds whatever its own defs need.
102
+ * @template R - The per-instance resource a claim allocates against (a geometry, a texture region,
103
+ * a line count); compared by identity, so a stable reference means a stable slot. `null` for a
104
+ * container whose members share everything.
105
+ * @template M - The mesh this container writes into.
106
+ * @template T - The def kind the layer holds.
107
+ */
108
+ export declare abstract class SlotContainer<R, M extends SlotMesh = SlotMesh, T extends RenderableDef = RenderableDef> {
109
+ /**
110
+ * Sorts a mesh's render list into paint order. Assigned straight to the mesh's `customSort` JSX
111
+ * prop, whose R3F-generated type leaves the value effectively unchecked — so the entry type here
112
+ * needs no cast against three's published one, which omits `index`.
113
+ *
114
+ * An arrow property rather than a method, because it is handed over as a bare value and a
115
+ * prototype method would arrive unbound.
116
+ * @param list - The render list, sorted in place.
117
+ */
118
+ readonly customSort: (list: RenderListItem[]) => void;
119
+ /**
120
+ * The layer's membership, in authored paint order. Kept so a def whose own dim changes can re-run
121
+ * the order pass without this container having re-rendered — `update(def)` reaches the instance,
122
+ * not here.
123
+ */
124
+ protected layerDefs: readonly T[];
125
+ /**
126
+ * Whether the layer is dimmed, which is what a def without a `dim` of its own inherits.
127
+ *
128
+ * A flag rather than the layer's amount, because the amount is the shader's business and this is
129
+ * only ever asked a yes-or-no question. It is also what makes an eased layer dim cheap: the order
130
+ * pass re-runs when the value crosses zero, not on every frame of the ease.
131
+ */
132
+ protected layerDimmed: boolean;
133
+ /**
134
+ * Whether each slot currently draws dimmed, so a dim write that does not cross the split costs
135
+ * nothing.
136
+ */
137
+ protected readonly dimmedBySlot: (boolean | undefined)[];
138
+ /**
139
+ * Each def's order, durable and weak — collected with the def. It outlives a slot, so a re-claim
140
+ * can seed the new slot's order without waiting for the next order pass.
141
+ */
142
+ private readonly orderByDef;
143
+ /** Each slot's place in the paint order, read by {@link customSort}. */
144
+ private readonly orderBySlot;
145
+ private readonly slotByDef;
146
+ private readonly defBySlot;
147
+ private readonly schema;
148
+ private readonly sortDirection;
149
+ /** Set by {@link bind}, which runs before any effect can claim a slot. */
150
+ private boundMesh;
151
+ /**
152
+ * @param options - How this container differs from the default.
153
+ */
154
+ constructor(options?: SlotContainerOptions);
155
+ /**
156
+ * The mesh every instance writes into. Undefined until {@link bind}; refs attach before passive
157
+ * effects run, so every claim and slot write sees it bound.
158
+ */
159
+ get mesh(): M;
160
+ /**
161
+ * Binds the mesh R3F constructed from this container's args, declaring its per-instance uniforms.
162
+ *
163
+ * Bind-once: the ref-cleanup `null` and any re-bind are ignored, because React StrictMode cycles
164
+ * refs (attach → cleanup → attach) around a passive effect cycle — a container that forgot its
165
+ * mesh there would turn {@link release} into a no-op and leak the slot when the remounted instance
166
+ * re-claims, and one that re-declared its uniforms would strand the values already written into
167
+ * them.
168
+ * @param mesh - The mounted mesh, or the ref-cleanup `null`.
169
+ */
170
+ bind(mesh: M | null): void;
171
+ /**
172
+ * Reserves a slot for one instance, backed by `resource`.
173
+ *
174
+ * Paint order is deliberately not a parameter: it is a property of the whole sibling list, so the
175
+ * component writes it for every def in one pass after each membership change (see
176
+ * {@link setPaintOrder}) — an instance never learns its index, which is what lets a memoized
177
+ * instance ignore structural re-renders entirely.
178
+ * @param def - The def the slot will draw; def-to-slot bookkeeping is keyed by its identity.
179
+ * @param resource - The per-instance resource to allocate against.
180
+ * @returns The slot index.
181
+ */
182
+ claim(def: RenderableDef, resource: R): number;
183
+ /**
184
+ * Frees a slot, and everything recorded about the claim it held.
185
+ * @param slot - The slot to free.
186
+ */
187
+ release(slot: number): void;
188
+ /**
189
+ * The def holding a slot — the reverse of {@link claim}.
190
+ * @param slot - The slot to look up, or `undefined` for a hit that named none.
191
+ * @returns The def, or `undefined` when the slot is free.
192
+ */
193
+ defAt(slot: number | undefined): RenderableDef | undefined;
194
+ /**
195
+ * The def an intersection with this container's mesh hit.
196
+ *
197
+ * Which field of an intersection names a slot is the container's own knowledge — `instanceId` for
198
+ * an instanced mesh, `batchId` for a batched one, the member id for a text batch, whose defs own
199
+ * several — so it is answered here rather than at each registration site.
200
+ * @param hit - The intersection to trace.
201
+ * @returns The def, or `undefined` when the hit cannot be traced to one.
202
+ */
203
+ defFromHit(hit: Intersection): RenderableDef | undefined;
204
+ /**
205
+ * Shows or hides one instance. Every def type carries `hidden`, so `useDefSync` drives this for
206
+ * all of them.
207
+ * @param slot - The slot to show or hide.
208
+ * @param visible - Whether the instance should draw.
209
+ */
210
+ setVisibleAt(slot: number, visible: boolean): void;
211
+ /**
212
+ * Sets one instance's own dim, or clears it back to its layer's.
213
+ *
214
+ * The counterpart to {@link setVisibleAt}, and here for the same reason: `dim` is a `SharedDef`
215
+ * field, so `useDefSync` drives it for every def type. The raw field is passed through rather than
216
+ * an encoded amount, which keeps the sentinel — and the rest of the shader's contract — inside the
217
+ * material module that reads it.
218
+ * @param slot - The slot to dim.
219
+ * @param dim - The def's `dim`; `undefined` defers to the layer's.
220
+ */
221
+ setDimAt(slot: number, dim: number | undefined): void;
222
+ /**
223
+ * Writes an encoded dim into a slot's uniform — the part of {@link setDimAt} that knows how a slot
224
+ * maps onto the mesh, split out so a container whose slot spans several mesh instances overrides
225
+ * only that and keeps the split-crossing check above.
226
+ * @param slot - The slot to write.
227
+ * @param amount - The encoded amount, from `instanceDim`.
228
+ */
229
+ protected writeDim(slot: number, amount: number): void;
230
+ /**
231
+ * Declares the layer's membership and dim, and re-runs the order pass over them.
232
+ *
233
+ * The component calls this from an effect after each structural change — child effects run first,
234
+ * so every mounted instance has claimed by then. Defs that have not claimed yet are recorded
235
+ * anyway: a later claim seeds its slot's order from this assignment, which is what keeps a
236
+ * re-claim correctly ordered without React involvement.
237
+ * @param defs - The current membership, in paint order.
238
+ * @param layerDimmed - Whether the layer is dimmed, inherited by defs without a `dim` of their own.
239
+ */
240
+ setPaintOrder(defs: readonly T[], layerDimmed: boolean): void;
241
+ /**
242
+ * Labels every claimed slot with its place in the layer's draw order, undimmed defs last.
243
+ *
244
+ * Overridden by a container whose mesh has no sortable draw list, where ordering means handing the
245
+ * mesh a rebuilt member list instead.
246
+ */
247
+ protected applyOrder(): void;
248
+ /**
249
+ * The slot a def holds, for an order pass walking the layer's defs.
250
+ * @param def - The def to look up.
251
+ * @returns The slot, or `undefined` when the def has not claimed one.
252
+ */
253
+ protected slotOf(def: RenderableDef): number | undefined;
254
+ /**
255
+ * Allocates one instance in the mesh.
256
+ * @param resource - The per-instance resource to allocate against.
257
+ * @returns The slot the mesh allocated.
258
+ */
259
+ protected abstract addInstance(resource: R): number;
260
+ /**
261
+ * Frees one instance in the mesh.
262
+ * @param slot - The slot to free.
263
+ */
264
+ protected abstract removeInstance(slot: number): void;
265
+ }
266
+ //# sourceMappingURL=SlotContainer.d.ts.map