@expofp/renderer 0.0.0-experimental.cf063fc
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 +145 -0
- package/dist/Renderer.d.ts +102 -0
- package/dist/Renderer.js +96 -0
- package/dist/controls/CameraControls.d.ts +108 -0
- package/dist/controls/CameraControls.js +203 -0
- package/dist/controls/Controls.d.ts +53 -0
- package/dist/controls/Controls.js +54 -0
- package/dist/controls/camera-api.d.ts +226 -0
- package/dist/controls/camera-api.js +179 -0
- package/dist/controls/gestures.d.ts +71 -0
- package/dist/controls/gestures.js +98 -0
- package/dist/controls/handlers/DoubleTapZoom.d.ts +23 -0
- package/dist/controls/handlers/DoubleTapZoom.js +82 -0
- package/dist/controls/handlers/Inertia.d.ts +60 -0
- package/dist/controls/handlers/Inertia.js +222 -0
- package/dist/controls/handlers/Pan.d.ts +23 -0
- package/dist/controls/handlers/Pan.js +212 -0
- package/dist/controls/handlers/Pitch.d.ts +19 -0
- package/dist/controls/handlers/Pitch.js +200 -0
- package/dist/controls/handlers/Roll.d.ts +30 -0
- package/dist/controls/handlers/Roll.js +196 -0
- package/dist/controls/handlers/Zoom.d.ts +28 -0
- package/dist/controls/handlers/Zoom.js +34 -0
- package/dist/controls/hooks.d.ts +136 -0
- package/dist/controls/hooks.js +200 -0
- package/dist/controls/index.d.ts +9 -0
- package/dist/controls/index.js +7 -0
- package/dist/controls/zoom-to.d.ts +89 -0
- package/dist/controls/zoom-to.js +91 -0
- package/dist/core/InstanceUniforms.d.ts +108 -0
- package/dist/core/InstanceUniforms.js +298 -0
- package/dist/core/SquareDataTexture.d.ts +277 -0
- package/dist/core/SquareDataTexture.js +476 -0
- package/dist/core/batch/BatchedMesh.d.ts +74 -0
- package/dist/core/batch/BatchedMesh.js +155 -0
- package/dist/core/instanced/FrustumCulling.d.ts +141 -0
- package/dist/core/instanced/FrustumCulling.js +246 -0
- package/dist/core/instanced/InstancedMesh.d.ts +302 -0
- package/dist/core/instanced/InstancedMesh.js +497 -0
- package/dist/core/instanced/Instances.d.ts +119 -0
- package/dist/core/instanced/Instances.js +230 -0
- package/dist/core/instanced/Raycasting.d.ts +118 -0
- package/dist/core/instanced/Raycasting.js +134 -0
- package/dist/core/instanced/instanced-material.d.ts +77 -0
- package/dist/core/instanced/instanced-material.js +228 -0
- package/dist/core/lines/BatchedLines.d.ts +137 -0
- package/dist/core/lines/BatchedLines.js +215 -0
- package/dist/core/lines/FrustumCullingLines.d.ts +44 -0
- package/dist/core/lines/FrustumCullingLines.js +85 -0
- package/dist/core/lines/RaycastingLines.d.ts +45 -0
- package/dist/core/lines/RaycastingLines.js +91 -0
- package/dist/core/lines/lines-material.d.ts +47 -0
- package/dist/core/lines/lines-material.js +124 -0
- package/dist/core/shader-source.d.ts +70 -0
- package/dist/core/shader-source.js +110 -0
- package/dist/core/sprites/BatchedSprites.d.ts +115 -0
- package/dist/core/sprites/BatchedSprites.js +173 -0
- package/dist/core/sprites/RaycastingSprites.d.ts +41 -0
- package/dist/core/sprites/RaycastingSprites.js +71 -0
- package/dist/core/sprites/sprite-material.d.ts +59 -0
- package/dist/core/sprites/sprite-material.js +192 -0
- package/dist/core/text/BatchedText.d.ts +233 -0
- package/dist/core/text/BatchedText.js +473 -0
- package/dist/core/text/MemberTexture.d.ts +90 -0
- package/dist/core/text/MemberTexture.js +289 -0
- package/dist/core/text/Text.d.ts +88 -0
- package/dist/core/text/Text.js +230 -0
- package/dist/core/text/batched-text-material.d.ts +56 -0
- package/dist/core/text/batched-text-material.js +123 -0
- package/dist/core/text/glyph-packing.d.ts +17 -0
- package/dist/core/text/glyph-packing.js +61 -0
- package/dist/core/typed-array.d.ts +16 -0
- package/dist/core/typed-array.js +20 -0
- package/dist/debug/components/DebugPanelProvider.d.ts +20 -0
- package/dist/debug/components/DebugPanelProvider.js +50 -0
- package/dist/debug/components/DebugTools.d.ts +22 -0
- package/dist/debug/components/DebugTools.js +28 -0
- package/dist/debug/components/Gui.d.ts +22 -0
- package/dist/debug/components/Gui.js +42 -0
- package/dist/debug/components/MemoryInfo.d.ts +22 -0
- package/dist/debug/components/MemoryInfo.js +42 -0
- package/dist/debug/components/Panel.d.ts +31 -0
- package/dist/debug/components/Panel.js +104 -0
- package/dist/debug/components/Stats.d.ts +9 -0
- package/dist/debug/components/Stats.js +24 -0
- package/dist/debug/debug-chunk.d.ts +26 -0
- package/dist/debug/debug-chunk.js +32 -0
- package/dist/debug/debug-context.d.ts +41 -0
- package/dist/debug/debug-context.js +59 -0
- package/dist/debug/index.d.ts +41 -0
- package/dist/debug/index.js +43 -0
- package/dist/events/LayoutDriver.d.ts +36 -0
- package/dist/events/LayoutDriver.js +192 -0
- package/dist/events/PointerMissed.d.ts +23 -0
- package/dist/events/PointerMissed.js +58 -0
- package/dist/events/def-culling.d.ts +46 -0
- package/dist/events/def-culling.js +69 -0
- package/dist/events/layout-targets.d.ts +151 -0
- package/dist/events/layout-targets.js +397 -0
- package/dist/events/placement/box.d.ts +59 -0
- package/dist/events/placement/box.js +96 -0
- package/dist/events/placement/grid.d.ts +161 -0
- package/dist/events/placement/grid.js +235 -0
- package/dist/events/placement/index.d.ts +2 -0
- package/dist/events/placement/index.js +1 -0
- package/dist/events/placement/pass.d.ts +70 -0
- package/dist/events/placement/pass.js +617 -0
- package/dist/events/pointer.d.ts +194 -0
- package/dist/events/pointer.js +356 -0
- package/dist/external/ExternalCanvas.d.ts +56 -0
- package/dist/external/ExternalCanvas.js +177 -0
- package/dist/external/external-camera.d.ts +18 -0
- package/dist/external/external-camera.js +103 -0
- package/dist/external/external-events.d.ts +14 -0
- package/dist/external/external-events.js +33 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +14 -0
- package/dist/objects/Background.d.ts +31 -0
- package/dist/objects/Background.js +37 -0
- package/dist/objects/containers/SlotContainer.d.ts +312 -0
- package/dist/objects/containers/SlotContainer.js +311 -0
- package/dist/objects/containers/hooks.d.ts +61 -0
- package/dist/objects/containers/hooks.js +196 -0
- package/dist/objects/containers/index.d.ts +6 -0
- package/dist/objects/containers/index.js +4 -0
- package/dist/objects/containers/keys.d.ts +10 -0
- package/dist/objects/containers/keys.js +18 -0
- package/dist/objects/containers/mesh-writes.d.ts +106 -0
- package/dist/objects/containers/mesh-writes.js +97 -0
- package/dist/objects/containers/props.d.ts +33 -0
- package/dist/objects/containers/props.js +1 -0
- package/dist/objects/images/ImageInstance.d.ts +29 -0
- package/dist/objects/images/ImageInstance.js +152 -0
- package/dist/objects/images/Images.d.ts +49 -0
- package/dist/objects/images/Images.js +394 -0
- package/dist/objects/images/atlas-packer.d.ts +129 -0
- package/dist/objects/images/atlas-packer.js +287 -0
- package/dist/objects/images/image-container.d.ts +74 -0
- package/dist/objects/images/image-container.js +100 -0
- package/dist/objects/images/index.d.ts +2 -0
- package/dist/objects/images/index.js +1 -0
- package/dist/objects/images/pack-sources.d.ts +190 -0
- package/dist/objects/images/pack-sources.js +272 -0
- package/dist/objects/images/texture-budget.d.ts +120 -0
- package/dist/objects/images/texture-budget.js +215 -0
- package/dist/objects/images/worker/atlas-worker.d.ts +56 -0
- package/dist/objects/images/worker/atlas-worker.js +123 -0
- package/dist/objects/images/worker/client.d.ts +62 -0
- package/dist/objects/images/worker/client.js +249 -0
- package/dist/objects/images/worker/index.d.ts +10 -0
- package/dist/objects/images/worker/index.js +1 -0
- package/dist/objects/layer/Layer.d.ts +28 -0
- package/dist/objects/layer/Layer.js +134 -0
- package/dist/objects/layer/index.d.ts +2 -0
- package/dist/objects/layer/index.js +1 -0
- package/dist/objects/layer/layer-context.d.ts +74 -0
- package/dist/objects/layer/layer-context.js +82 -0
- package/dist/objects/layer/mount-scheduler.d.ts +131 -0
- package/dist/objects/layer/mount-scheduler.js +289 -0
- package/dist/objects/layer/visibility-gui.d.ts +19 -0
- package/dist/objects/layer/visibility-gui.js +93 -0
- package/dist/objects/lighting/Lighting.d.ts +92 -0
- package/dist/objects/lighting/Lighting.js +384 -0
- package/dist/objects/lighting/OcclusionPasses.d.ts +23 -0
- package/dist/objects/lighting/OcclusionPasses.js +271 -0
- package/dist/objects/lighting/index.d.ts +11 -0
- package/dist/objects/lighting/index.js +10 -0
- package/dist/objects/lighting/lighting-gui.d.ts +24 -0
- package/dist/objects/lighting/lighting-gui.js +114 -0
- package/dist/objects/lighting/occluder.d.ts +34 -0
- package/dist/objects/lighting/occluder.js +62 -0
- package/dist/objects/lighting/occlusion-targets.d.ts +143 -0
- package/dist/objects/lighting/occlusion-targets.js +276 -0
- package/dist/objects/lines/LineInstance.d.ts +21 -0
- package/dist/objects/lines/LineInstance.js +73 -0
- package/dist/objects/lines/Lines.d.ts +17 -0
- package/dist/objects/lines/Lines.js +31 -0
- package/dist/objects/lines/index.d.ts +2 -0
- package/dist/objects/lines/index.js +1 -0
- package/dist/objects/lines/line-container.d.ts +35 -0
- package/dist/objects/lines/line-container.js +40 -0
- package/dist/objects/materials/ColorMaterial.d.ts +92 -0
- package/dist/objects/materials/ColorMaterial.js +124 -0
- package/dist/objects/materials/LineMaterial.d.ts +44 -0
- package/dist/objects/materials/LineMaterial.js +74 -0
- package/dist/objects/materials/ModelMaterial.d.ts +53 -0
- package/dist/objects/materials/ModelMaterial.js +111 -0
- package/dist/objects/materials/TextureMaterial.d.ts +33 -0
- package/dist/objects/materials/TextureMaterial.js +48 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-pass.d.ts +77 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-pass.js +296 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-patch.d.ts +29 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-patch.js +115 -0
- package/dist/objects/materials/effects/ao/blur-pass.d.ts +61 -0
- package/dist/objects/materials/effects/ao/blur-pass.js +101 -0
- package/dist/objects/materials/effects/ao/index.d.ts +129 -0
- package/dist/objects/materials/effects/ao/index.js +72 -0
- package/dist/objects/materials/effects/color-dim.d.ts +115 -0
- package/dist/objects/materials/effects/color-dim.js +206 -0
- package/dist/objects/materials/effects/contact-shadow.d.ts +100 -0
- package/dist/objects/materials/effects/contact-shadow.js +167 -0
- package/dist/objects/materials/effects/effects-context.d.ts +53 -0
- package/dist/objects/materials/effects/effects-context.js +24 -0
- package/dist/objects/materials/shared.d.ts +24 -0
- package/dist/objects/materials/shared.js +72 -0
- package/dist/objects/models/ModelInstance.d.ts +22 -0
- package/dist/objects/models/ModelInstance.js +33 -0
- package/dist/objects/models/Models.d.ts +22 -0
- package/dist/objects/models/Models.js +186 -0
- package/dist/objects/models/gltf-cache.d.ts +17 -0
- package/dist/objects/models/gltf-cache.js +50 -0
- package/dist/objects/models/index.d.ts +2 -0
- package/dist/objects/models/index.js +1 -0
- package/dist/objects/models/model-asset.d.ts +48 -0
- package/dist/objects/models/model-asset.js +77 -0
- package/dist/objects/models/model-container.d.ts +123 -0
- package/dist/objects/models/model-container.js +207 -0
- package/dist/objects/shapes/ShapeInstance.d.ts +26 -0
- package/dist/objects/shapes/ShapeInstance.js +39 -0
- package/dist/objects/shapes/Shapes.d.ts +21 -0
- package/dist/objects/shapes/Shapes.js +131 -0
- package/dist/objects/shapes/index.d.ts +2 -0
- package/dist/objects/shapes/index.js +1 -0
- package/dist/objects/shapes/shape-container.d.ts +141 -0
- package/dist/objects/shapes/shape-container.js +242 -0
- package/dist/objects/shapes/shape-geometry.d.ts +27 -0
- package/dist/objects/shapes/shape-geometry.js +94 -0
- package/dist/objects/text/TextInstance.d.ts +22 -0
- package/dist/objects/text/TextInstance.js +95 -0
- package/dist/objects/text/Texts.d.ts +30 -0
- package/dist/objects/text/Texts.js +43 -0
- package/dist/objects/text/index.d.ts +2 -0
- package/dist/objects/text/index.js +1 -0
- package/dist/objects/text/text-container.d.ts +121 -0
- package/dist/objects/text/text-container.js +229 -0
- package/dist/objects/text/text-layout.d.ts +92 -0
- package/dist/objects/text/text-layout.js +180 -0
- package/dist/space/Camera.d.ts +103 -0
- package/dist/space/Camera.js +321 -0
- package/dist/space/Scene.d.ts +47 -0
- package/dist/space/Scene.js +127 -0
- package/dist/space/Space.d.ts +325 -0
- package/dist/space/Space.js +359 -0
- package/dist/space/VisibleRect.d.ts +45 -0
- package/dist/space/VisibleRect.js +129 -0
- package/dist/space/camera-handle.d.ts +67 -0
- package/dist/space/camera-handle.js +63 -0
- package/dist/space/camera-kind.d.ts +26 -0
- package/dist/space/camera-kind.js +30 -0
- package/dist/space/canvas-size.d.ts +24 -0
- package/dist/space/canvas-size.js +20 -0
- package/dist/space/clipping.d.ts +69 -0
- package/dist/space/clipping.js +130 -0
- package/dist/space/layout-measure.d.ts +67 -0
- package/dist/space/layout-measure.js +175 -0
- package/dist/space/viewport.d.ts +112 -0
- package/dist/space/viewport.js +67 -0
- package/dist/types/defs.d.ts +234 -0
- package/dist/types/defs.js +1 -0
- package/dist/types/events.d.ts +198 -0
- package/dist/types/events.js +1 -0
- package/dist/types/guards.d.ts +21 -0
- package/dist/types/guards.js +52 -0
- package/dist/update/index.d.ts +3 -0
- package/dist/update/index.js +2 -0
- package/dist/update/slot-writers.d.ts +30 -0
- package/dist/update/slot-writers.js +76 -0
- package/dist/update/store.d.ts +41 -0
- package/dist/update/store.js +104 -0
- package/dist/utils/arrays.d.ts +13 -0
- package/dist/utils/arrays.js +20 -0
- package/dist/utils/colors.d.ts +19 -0
- package/dist/utils/colors.js +27 -0
- package/dist/utils/hot-state.d.ts +41 -0
- package/dist/utils/hot-state.js +37 -0
- package/dist/utils/logging.d.ts +29 -0
- package/dist/utils/logging.js +55 -0
- package/dist/utils/math.d.ts +52 -0
- package/dist/utils/math.js +76 -0
- package/package.json +79 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { ShaderChunk, } from 'three';
|
|
2
|
+
import { declareBeforeMain, openMain } from '../shader-source';
|
|
3
|
+
/**
|
|
4
|
+
* Vertex declarations: the index and matrices samplers, and the fetches that read them.
|
|
5
|
+
*
|
|
6
|
+
* Unguarded, unlike upstream's `#ifdef USE_INSTANCING_INDIRECT`. The guard is what made it safe to
|
|
7
|
+
* append to a chunk every material compiles; injected into one shader at a time, it would only ever
|
|
8
|
+
* test a define this same call sets.
|
|
9
|
+
*/
|
|
10
|
+
const INSTANCED_DECLARATIONS = /* glsl */ `
|
|
11
|
+
uniform highp sampler2D indexTexture;
|
|
12
|
+
|
|
13
|
+
// The id this draw’s instance holds. A mutable global rather than a local of main, so the
|
|
14
|
+
// fetches below can read it; main assigns it before anything else runs.
|
|
15
|
+
float instanceIndex;
|
|
16
|
+
|
|
17
|
+
// Resolves a draw to the instance it should read. The culling pass writes the surviving ids into
|
|
18
|
+
// indexTexture in draw order, so gl_InstanceID addresses it directly.
|
|
19
|
+
float getIndirectIndex( int id ) {
|
|
20
|
+
int size = textureSize( indexTexture, 0 ).x;
|
|
21
|
+
return texelFetch( indexTexture, ivec2( id % size, id / size ), 0 ).r;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#ifdef USE_INSTANCING_MATRIX_INDIRECT
|
|
25
|
+
|
|
26
|
+
uniform highp sampler2D matricesTexture;
|
|
27
|
+
|
|
28
|
+
mat4 getInstancedMatrix() {
|
|
29
|
+
int size = textureSize( matricesTexture, 0 ).x;
|
|
30
|
+
int j = int( instanceIndex ) * 4;
|
|
31
|
+
int x = j % size;
|
|
32
|
+
int y = j / size;
|
|
33
|
+
vec4 v1 = texelFetch( matricesTexture, ivec2( x, y ), 0 );
|
|
34
|
+
vec4 v2 = texelFetch( matricesTexture, ivec2( x + 1, y ), 0 );
|
|
35
|
+
vec4 v3 = texelFetch( matricesTexture, ivec2( x + 2, y ), 0 );
|
|
36
|
+
vec4 v4 = texelFetch( matricesTexture, ivec2( x + 3, y ), 0 );
|
|
37
|
+
return mat4( v1, v2, v3, v4 );
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#else
|
|
41
|
+
|
|
42
|
+
// No transforms written, so nothing to sample: a mesh placing its instances some other way — a
|
|
43
|
+
// line batch, by two endpoints — allocates no matrices texture at all, and the transform chunks
|
|
44
|
+
// that read this go on compiling.
|
|
45
|
+
mat4 getInstancedMatrix() {
|
|
46
|
+
return mat4( 1.0 );
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#endif
|
|
50
|
+
`;
|
|
51
|
+
/**
|
|
52
|
+
* What every instanced draw resolves before anything reads it: the instance this draw stands for,
|
|
53
|
+
* and its transform.
|
|
54
|
+
*
|
|
55
|
+
* The matrix is declared here rather than where the transform chunks use it, so it lands in `main`
|
|
56
|
+
* whether or not the material includes those chunks. It shadows the `attribute mat4 instanceMatrix`
|
|
57
|
+
* three declares for any `isInstancedMesh` object — which is what the placeholder attribute on
|
|
58
|
+
* `InstancedMeshImpl` exists to satisfy — and a material doing its own transform simply never reads
|
|
59
|
+
* it.
|
|
60
|
+
*/
|
|
61
|
+
const INSTANCED_RESOLVE = /* glsl */ `
|
|
62
|
+
instanceIndex = getIndirectIndex( gl_InstanceID );
|
|
63
|
+
mat4 instanceMatrix = getInstancedMatrix();
|
|
64
|
+
`;
|
|
65
|
+
/** Vertex color declarations: the colors sampler and its fetch. */
|
|
66
|
+
const INSTANCED_COLOR_DECLARATIONS = /* glsl */ `
|
|
67
|
+
uniform highp sampler2D colorsTexture;
|
|
68
|
+
|
|
69
|
+
vec4 getColorTexture() {
|
|
70
|
+
int size = textureSize( colorsTexture, 0 ).x;
|
|
71
|
+
int j = int( instanceIndex );
|
|
72
|
+
int x = j % size;
|
|
73
|
+
int y = j / size;
|
|
74
|
+
return texelFetch( colorsTexture, ivec2( x, y ), 0 );
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
/**
|
|
78
|
+
* Seeds `vColor`, folds in the geometry's vertex color and then the instance's — the chunk
|
|
79
|
+
* substituted for `<color_vertex>`, whose composition it keeps.
|
|
80
|
+
*
|
|
81
|
+
* Every stage here, where upstream splits them across `<color_vertex>` and `batching_vertex`. They
|
|
82
|
+
* cannot move apart: three seeds `vColor` at `<color_vertex>` and every multiply has to follow it, so
|
|
83
|
+
* with the rest of the instancing injected at the top of `main` — ahead of both — the only place the
|
|
84
|
+
* instance color still reads right is beside the seed.
|
|
85
|
+
*
|
|
86
|
+
* `USE_COLOR` is the define three sets for `material.vertexColors`; upstream tests a
|
|
87
|
+
* `USE_VERTEX_COLOR` that three never defines, so a geometry's vertex colors were dropped rather than
|
|
88
|
+
* multiplied in. `color` is a `vec4` under it because the substitution defines `USE_COLOR_ALPHA` as
|
|
89
|
+
* well, which is what three's attribute declaration keys on — a geometry carrying only rgb has the
|
|
90
|
+
* alpha filled in by GL.
|
|
91
|
+
*/
|
|
92
|
+
const INSTANCED_COLOR_VERTEX = /* glsl */ `
|
|
93
|
+
vColor = vec4( 1.0 );
|
|
94
|
+
|
|
95
|
+
#ifdef USE_COLOR
|
|
96
|
+
vColor *= color;
|
|
97
|
+
#endif
|
|
98
|
+
|
|
99
|
+
vColor *= getColorTexture();
|
|
100
|
+
`;
|
|
101
|
+
let patched = false;
|
|
102
|
+
/**
|
|
103
|
+
* Prepares three's global `ShaderChunk` for indirect instancing, once per process.
|
|
104
|
+
*
|
|
105
|
+
* Only what a *stock* material needs, because only a stock material has these chunks to begin with:
|
|
106
|
+
* the transform chunks that apply the instance matrix, widened to fire under the indirect define as
|
|
107
|
+
* well, and the color chunk substituted for `<color_vertex>`. Everything else an instanced draw
|
|
108
|
+
* needs is injected into the one shader being compiled — see the module docs. Nothing here changes
|
|
109
|
+
* another material's output: the widened branches are inert without `USE_INSTANCING_INDIRECT`, which
|
|
110
|
+
* only an instanced mesh sets on the material it is drawing with, and the added chunk is reached only
|
|
111
|
+
* through the substitution below.
|
|
112
|
+
*/
|
|
113
|
+
export function patchInstancedShaderChunks() {
|
|
114
|
+
if (patched)
|
|
115
|
+
return;
|
|
116
|
+
patched = true;
|
|
117
|
+
// three types `ShaderChunk` as a fixed record, so the custom `instanced_*` key is reached through
|
|
118
|
+
// an index view.
|
|
119
|
+
const chunks = ShaderChunk;
|
|
120
|
+
chunks.instanced_color_vertex = INSTANCED_COLOR_VERTEX;
|
|
121
|
+
// Let the stock transform chunks honor the indirect define alongside three's own `USE_INSTANCING`.
|
|
122
|
+
chunks.project_vertex = withIndirectInstancing(chunks.project_vertex);
|
|
123
|
+
chunks.worldpos_vertex = withIndirectInstancing(chunks.worldpos_vertex);
|
|
124
|
+
chunks.defaultnormal_vertex = withIndirectInstancing(chunks.defaultnormal_vertex);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Wraps a material so the program it compiles reads one mesh's instancing textures.
|
|
128
|
+
*
|
|
129
|
+
* Wraps the material three handed the mesh rather than the mesh's own, because those differ: a scene
|
|
130
|
+
* with an `overrideMaterial` draws every object with that one instead, and an override that skipped
|
|
131
|
+
* the wrap would stack every instance on a single transform. Undoing it afterward is what makes
|
|
132
|
+
* wrapping a material the mesh does not own safe — three tracks whether the program it cached was
|
|
133
|
+
* built for an instanced draw and rebuilds when the next object disagrees, so the plain meshes
|
|
134
|
+
* sharing that override compile their own way.
|
|
135
|
+
*
|
|
136
|
+
* The one case this does not cover is two instanced meshes sharing a material: both are
|
|
137
|
+
* `isInstancedMesh`, so three sees nothing to disagree with and the second draws against the
|
|
138
|
+
* first's textures. Give each mesh its own material.
|
|
139
|
+
* @param material - The material about to draw.
|
|
140
|
+
* @param textures - The textures its program should fetch from, read at compile time so a texture
|
|
141
|
+
* added later is still picked up.
|
|
142
|
+
* @returns Restores the material exactly as it arrived. Call it once, after the draw.
|
|
143
|
+
*/
|
|
144
|
+
export function patchInstancedMaterial(material, textures) {
|
|
145
|
+
// Saved raw rather than bound, which is what the rule below would have us do: restoring a bound
|
|
146
|
+
// copy would put a *different* function back on the material, and the next draw would bind that
|
|
147
|
+
// one in turn — a fresh layer every frame, each wrapping the last. The receiver is supplied at
|
|
148
|
+
// the two call sites instead.
|
|
149
|
+
/* eslint-disable @typescript-eslint/unbound-method -- restored verbatim; called with `.call`. */
|
|
150
|
+
const baseOnBeforeCompile = material.onBeforeCompile;
|
|
151
|
+
const baseCacheKey = material.customProgramCacheKey;
|
|
152
|
+
/* eslint-enable @typescript-eslint/unbound-method */
|
|
153
|
+
// Distinguishes the program from the material's unwrapped one, and from a wrapped one compiled
|
|
154
|
+
// before a texture was added, since each changes the generated GLSL. Every texture that can arrive
|
|
155
|
+
// late is named: the matrices are allocated by the first transform written, and a program built
|
|
156
|
+
// before that reads identity.
|
|
157
|
+
//
|
|
158
|
+
// The uniforms contribute their whole schema and not just their presence. Two meshes that declare
|
|
159
|
+
// different uniforms generate different GLSL, so a key that recorded only "has uniforms" would let
|
|
160
|
+
// the second draw against the first's layout.
|
|
161
|
+
const key = () => `${!!textures.matricesTexture}_${!!textures.colorsTexture}_${textures.uniforms.shaderKey}`;
|
|
162
|
+
material.customProgramCacheKey = () => `efp_${key()}_${baseCacheKey.call(material)}`;
|
|
163
|
+
material.onBeforeCompile = (shader, renderer) => {
|
|
164
|
+
// Instancing first, the material's own handler after — the same order the batched meshes use,
|
|
165
|
+
// and an invariant materials rely on: a patch that reads a per-instance uniform can only find
|
|
166
|
+
// it once the prologue below has declared it. Nothing here depends on the reverse; the
|
|
167
|
+
// material patches that exist anchor on `#include` chunks this leaves untouched.
|
|
168
|
+
injectInstancing(shader, textures);
|
|
169
|
+
baseOnBeforeCompile.call(material, shader, renderer);
|
|
170
|
+
};
|
|
171
|
+
return () => {
|
|
172
|
+
material.onBeforeCompile = baseOnBeforeCompile;
|
|
173
|
+
material.customProgramCacheKey = baseCacheKey;
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Injects the index, matrix, uniform and color instancing into a compiling shader.
|
|
178
|
+
* @param shader - The program parameters to edit.
|
|
179
|
+
* @param textures - The textures to bind.
|
|
180
|
+
* @throws {Error} If the vertex shader has no `main` to inject into.
|
|
181
|
+
*/
|
|
182
|
+
function injectInstancing(shader, textures) {
|
|
183
|
+
// Cloned so a shared material (e.g. `scene.overrideMaterial`) does not accumulate our defines.
|
|
184
|
+
shader.defines = { ...shader.defines, USE_INSTANCING_INDIRECT: '' };
|
|
185
|
+
shader.uniforms.indexTexture = { value: textures.indexTexture };
|
|
186
|
+
if (textures.matricesTexture) {
|
|
187
|
+
shader.defines.USE_INSTANCING_MATRIX_INDIRECT = '';
|
|
188
|
+
shader.uniforms.matricesTexture = { value: textures.matricesTexture };
|
|
189
|
+
}
|
|
190
|
+
textures.uniforms.patchShader(shader, 'instanceIndex');
|
|
191
|
+
shader.vertexShader = declareBeforeMain(shader.vertexShader, INSTANCED_DECLARATIONS);
|
|
192
|
+
// Written after the uniform prologue precisely so it runs before it: `openMain` inserts at the top
|
|
193
|
+
// of `main`, and the prologue's fetch addresses the texture by the index resolved here.
|
|
194
|
+
shader.vertexShader = openMain(shader.vertexShader, INSTANCED_RESOLVE);
|
|
195
|
+
injectInstancedColor(shader, textures.colorsTexture);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Points a compiling shader at the per-instance colors, when it is a shader that can read them.
|
|
199
|
+
*
|
|
200
|
+
* Per-instance color is the one part of instancing that stays on three's chunks, because it has to
|
|
201
|
+
* meet `vColor` where three seeds it — `<color_vertex>` in the vertex stage, declared for the stage
|
|
202
|
+
* that reads it by `<color_pars_fragment>`. **Both**, not either: a material carrying the fragment
|
|
203
|
+
* half alone would take the defines and then interpolate a varying nothing ever assigned. A shader
|
|
204
|
+
* keeping neither is doing its own color, which is what three's line material does — so this is a
|
|
205
|
+
* skip rather than a failure.
|
|
206
|
+
* @param shader - The program parameters to edit.
|
|
207
|
+
* @param colorsTexture - The per-instance colors, or `null` while none have been written.
|
|
208
|
+
*/
|
|
209
|
+
function injectInstancedColor(shader, colorsTexture) {
|
|
210
|
+
const readsColorChunks = shader.vertexShader.includes('<color_vertex>') &&
|
|
211
|
+
shader.fragmentShader.includes('<color_pars_fragment>');
|
|
212
|
+
if (!colorsTexture || !readsColorChunks)
|
|
213
|
+
return;
|
|
214
|
+
const defines = (shader.defines ??= {});
|
|
215
|
+
defines.USE_INSTANCING_COLOR_INDIRECT = '';
|
|
216
|
+
defines.USE_COLOR_ALPHA = '';
|
|
217
|
+
shader.uniforms.colorsTexture = { value: colorsTexture };
|
|
218
|
+
shader.vertexShader = declareBeforeMain(shader.vertexShader, INSTANCED_COLOR_DECLARATIONS);
|
|
219
|
+
shader.vertexShader = shader.vertexShader.replace('<color_vertex>', '<instanced_color_vertex>');
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Widens a chunk's `USE_INSTANCING` guard to also fire under indirect instancing.
|
|
223
|
+
* @param chunk - The stock chunk source.
|
|
224
|
+
* @returns The widened chunk.
|
|
225
|
+
*/
|
|
226
|
+
function withIndirectInstancing(chunk) {
|
|
227
|
+
return chunk.replace('#ifdef USE_INSTANCING', '#if defined USE_INSTANCING || defined USE_INSTANCING_INDIRECT');
|
|
228
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { type Box3, type BufferGeometry, type Camera, type Group, type Material, type Scene, type Sphere, Vector3, type Vector3Like, type WebGLRenderer } from 'three';
|
|
2
|
+
import { LineMaterial } from 'three/addons/lines/LineMaterial.js';
|
|
3
|
+
import { LineSegmentsGeometry } from 'three/addons/lines/LineSegmentsGeometry.js';
|
|
4
|
+
import { InstancedMeshImpl, type InstancedMeshImplParams } from '../instanced/InstancedMesh';
|
|
5
|
+
import { FrustumCullingLines } from './FrustumCullingLines';
|
|
6
|
+
import { RaycastingLines } from './RaycastingLines';
|
|
7
|
+
/**
|
|
8
|
+
* An instanced mesh whose instances are placed by two endpoints instead of a matrix.
|
|
9
|
+
*
|
|
10
|
+
* That sentence is the whole of it. A wide line is a quad expanded *after* projection — three's line
|
|
11
|
+
* shader takes a segment's two ends into clip space and offsets the corners by a width measured in
|
|
12
|
+
* screen pixels — so no matrix maps the template onto the segment, and the placement cannot be a
|
|
13
|
+
* transform. Everything else an instanced mesh does applies unchanged: slots, visibility, growth,
|
|
14
|
+
* per-instance uniforms, the draw list that is also the paint order, and the material wiring.
|
|
15
|
+
*
|
|
16
|
+
* What this class holds is what "placed by endpoints" changes:
|
|
17
|
+
*
|
|
18
|
+
* - **The endpoints**, as two per-instance uniforms rather than the instanced attributes
|
|
19
|
+
* `LineSegmentsGeometry` would carry. They are named for those attributes deliberately: the
|
|
20
|
+
* uniform prologue declares them as locals of `main`, so three's own shader goes on reading its own
|
|
21
|
+
* names and needs no rewriting beyond dropping the declarations — see `objects/materials/LineMaterial`.
|
|
22
|
+
* - **The bounds**, swept from the endpoints, because the template geometry's own are in the
|
|
23
|
+
* parametric space the shader expands from and mean nothing in the plan.
|
|
24
|
+
* - **Picking**, which has to run in screen space at each member's own width — see {@link RaycastingLines}.
|
|
25
|
+
*
|
|
26
|
+
* And what it stops needing by being one: the endpoints are addressed by id, so paint order is a
|
|
27
|
+
* `customSort` over the draw list like every other batch's rather than a packing of the buffer;
|
|
28
|
+
* hiding a member drops it from that list instead of collapsing it in the shader; and the geometry
|
|
29
|
+
* carries no instanced attributes, so nothing has to work around the instance ceiling three caches
|
|
30
|
+
* the first time it binds one.
|
|
31
|
+
*
|
|
32
|
+
* Render it with {@link BatchedLines}.
|
|
33
|
+
*/
|
|
34
|
+
export declare class BatchedLinesImpl extends InstancedMeshImpl {
|
|
35
|
+
/** Marks this as a line batch. three's brand pattern, so a holder can tell the batch kinds apart. */
|
|
36
|
+
readonly isBatchedLines = true;
|
|
37
|
+
/**
|
|
38
|
+
* The segment template every member is drawn from, and the whole of what the geometry carries: the
|
|
39
|
+
* per-instance data three would put in instanced attributes is in the uniforms instead.
|
|
40
|
+
*
|
|
41
|
+
* Built here rather than mounted as a child element, because it is not a choice the way an atlas's
|
|
42
|
+
* quad is — three's own class is the definition of the template.
|
|
43
|
+
*/
|
|
44
|
+
geometry: LineSegmentsGeometry;
|
|
45
|
+
/**
|
|
46
|
+
* The material three's line shader compiles from, narrowed because both the fallback width and the
|
|
47
|
+
* resolution screen-space widths are measured against are read off it.
|
|
48
|
+
*
|
|
49
|
+
* Seeded with a throwaway the `<LineMaterial>` child replaces on mount, as the base seeds one for
|
|
50
|
+
* R3F's `<TextureMaterial>` to replace — but a *line* material, because those two are read before
|
|
51
|
+
* anything has been drawn.
|
|
52
|
+
*/
|
|
53
|
+
material: LineMaterial;
|
|
54
|
+
/** Draw order is paint order, which a container decides through `customSort` rather than depth. */
|
|
55
|
+
sortObjects: boolean;
|
|
56
|
+
/** Screen space, at each member's own width — see {@link RaycastingLines}. */
|
|
57
|
+
protected raycasting: RaycastingLines;
|
|
58
|
+
/** By the ribbon each member draws rather than the segment it runs — see {@link FrustumCullingLines}. */
|
|
59
|
+
protected culling: FrustumCullingLines;
|
|
60
|
+
/**
|
|
61
|
+
* @param params - Instance capacity; the buffers grow past it on demand.
|
|
62
|
+
*/
|
|
63
|
+
constructor(params?: InstancedMeshImplParams);
|
|
64
|
+
/**
|
|
65
|
+
* Reads a member's endpoints.
|
|
66
|
+
* @param id - The member to read.
|
|
67
|
+
* @param start - Receives the segment start.
|
|
68
|
+
* @param end - Receives the segment end.
|
|
69
|
+
*/
|
|
70
|
+
getPointsAt(id: number, start: Vector3, end: Vector3): void;
|
|
71
|
+
/**
|
|
72
|
+
* Writes a member's endpoints, invalidating the bounds they define.
|
|
73
|
+
*
|
|
74
|
+
* Writes what it is given, like every other setter here. Skipping an unchanged segment is the
|
|
75
|
+
* caller's to do — `LineInstance` compares first, exactly as the write helpers do for the meshes
|
|
76
|
+
* that carry transforms and colors — so a member is never read back on a path that means to write.
|
|
77
|
+
* @param id - The member to write.
|
|
78
|
+
* @param start - The segment start.
|
|
79
|
+
* @param end - The segment end.
|
|
80
|
+
*/
|
|
81
|
+
setPointsAt(id: number, start: Vector3Like, end: Vector3Like): void;
|
|
82
|
+
/**
|
|
83
|
+
* A member's own width, or a negative value while it has none and draws at the material's.
|
|
84
|
+
* @param id - The member to read.
|
|
85
|
+
* @returns The width.
|
|
86
|
+
*/
|
|
87
|
+
getWidthAt(id: number): number;
|
|
88
|
+
/**
|
|
89
|
+
* Sets a member's width, in the units the material's `worldUnits` selects.
|
|
90
|
+
*
|
|
91
|
+
* Optional, and the batch cannot make it otherwise — a member nobody set a width for keeps the
|
|
92
|
+
* material's, which every `LineMaterial` has. That fallback is marked by a *negative* width
|
|
93
|
+
* rather than by zero, because zero expands the segment quad to no area: it draws nothing, which
|
|
94
|
+
* is a thing a caller can ask for and not the same request. Callers that treat a width as user
|
|
95
|
+
* input should clamp it at zero, so a nonsensical negative reads as invisible rather than as "use
|
|
96
|
+
* the material's".
|
|
97
|
+
* @param id - The member to write.
|
|
98
|
+
* @param width - The width; negative to fall back to the material's, zero to draw nothing.
|
|
99
|
+
*/
|
|
100
|
+
setWidthAt(id: number, width: number): void;
|
|
101
|
+
/**
|
|
102
|
+
* Encloses one member: the sphere through its two endpoints.
|
|
103
|
+
*
|
|
104
|
+
* Takes no account of the width, as three's own line bounds do not either — the ends are where a
|
|
105
|
+
* segment runs, and the ribbon drawn around them is a screen-space skin whose size in the plan
|
|
106
|
+
* depends on the camera.
|
|
107
|
+
* @param id - The member.
|
|
108
|
+
* @param target - Receives the result.
|
|
109
|
+
* @returns The bounds.
|
|
110
|
+
*/
|
|
111
|
+
getBoundingSphereAt(id: number, target: Sphere): Sphere;
|
|
112
|
+
/**
|
|
113
|
+
* Encloses one member in a box: the two endpoints, and nothing between them to measure.
|
|
114
|
+
* @param id - The member.
|
|
115
|
+
* @param target - Receives the result.
|
|
116
|
+
* @returns The bounds.
|
|
117
|
+
*/
|
|
118
|
+
getBoundingBoxAt(id: number, target: Box3): Box3;
|
|
119
|
+
/** Frees the segment template, which this batch built rather than three or R3F. */
|
|
120
|
+
dispose(): void;
|
|
121
|
+
/**
|
|
122
|
+
* Clears a member as it is handed out, so a reused slot keeps nothing of the one that held it.
|
|
123
|
+
*
|
|
124
|
+
* Everything it could inherit, not only what a caller usually sets: a container that writes a
|
|
125
|
+
* color and a width but no endpoints would otherwise draw the removed member's line.
|
|
126
|
+
* @param id - The member being handed out.
|
|
127
|
+
*/
|
|
128
|
+
protected resetInstance(id: number): void;
|
|
129
|
+
onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, material: Material, group: Group): void;
|
|
130
|
+
protected patchMaterial(material: Material): () => void;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Registers the class as an R3F element, by value so the generated key cannot collide with anything
|
|
134
|
+
* three puts in the catalog when the canvas mounts.
|
|
135
|
+
*/
|
|
136
|
+
export declare const BatchedLines: import("react").ExoticComponent<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<BatchedLinesImpl, import("@react-three/fiber").MathProps<BatchedLinesImpl> & import("@react-three/fiber").ReactProps<BatchedLinesImpl> & Partial<import("@react-three/fiber").EventHandlers>>>, Omit<import("@react-three/fiber").InstanceProps<BatchedLinesImpl, typeof BatchedLinesImpl>, "object">>>>;
|
|
137
|
+
//# sourceMappingURL=BatchedLines.d.ts.map
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { extend } from '@react-three/fiber';
|
|
2
|
+
import { Vector3, Vector4, } from 'three';
|
|
3
|
+
import { LineMaterial } from 'three/addons/lines/LineMaterial.js';
|
|
4
|
+
import { LineSegmentsGeometry } from 'three/addons/lines/LineSegmentsGeometry.js';
|
|
5
|
+
import { InstancedMeshImpl } from '../instanced/InstancedMesh';
|
|
6
|
+
import { FrustumCullingLines } from './FrustumCullingLines';
|
|
7
|
+
import { END_UNIFORM, patchLineMaterial, START_UNIFORM, WIDTH_UNIFORM } from './lines-material';
|
|
8
|
+
import { RaycastingLines } from './RaycastingLines';
|
|
9
|
+
/**
|
|
10
|
+
* An instanced mesh whose instances are placed by two endpoints instead of a matrix.
|
|
11
|
+
*
|
|
12
|
+
* That sentence is the whole of it. A wide line is a quad expanded *after* projection — three's line
|
|
13
|
+
* shader takes a segment's two ends into clip space and offsets the corners by a width measured in
|
|
14
|
+
* screen pixels — so no matrix maps the template onto the segment, and the placement cannot be a
|
|
15
|
+
* transform. Everything else an instanced mesh does applies unchanged: slots, visibility, growth,
|
|
16
|
+
* per-instance uniforms, the draw list that is also the paint order, and the material wiring.
|
|
17
|
+
*
|
|
18
|
+
* What this class holds is what "placed by endpoints" changes:
|
|
19
|
+
*
|
|
20
|
+
* - **The endpoints**, as two per-instance uniforms rather than the instanced attributes
|
|
21
|
+
* `LineSegmentsGeometry` would carry. They are named for those attributes deliberately: the
|
|
22
|
+
* uniform prologue declares them as locals of `main`, so three's own shader goes on reading its own
|
|
23
|
+
* names and needs no rewriting beyond dropping the declarations — see `objects/materials/LineMaterial`.
|
|
24
|
+
* - **The bounds**, swept from the endpoints, because the template geometry's own are in the
|
|
25
|
+
* parametric space the shader expands from and mean nothing in the plan.
|
|
26
|
+
* - **Picking**, which has to run in screen space at each member's own width — see {@link RaycastingLines}.
|
|
27
|
+
*
|
|
28
|
+
* And what it stops needing by being one: the endpoints are addressed by id, so paint order is a
|
|
29
|
+
* `customSort` over the draw list like every other batch's rather than a packing of the buffer;
|
|
30
|
+
* hiding a member drops it from that list instead of collapsing it in the shader; and the geometry
|
|
31
|
+
* carries no instanced attributes, so nothing has to work around the instance ceiling three caches
|
|
32
|
+
* the first time it binds one.
|
|
33
|
+
*
|
|
34
|
+
* Render it with {@link BatchedLines}.
|
|
35
|
+
*/
|
|
36
|
+
export class BatchedLinesImpl extends InstancedMeshImpl {
|
|
37
|
+
/** Marks this as a line batch. three's brand pattern, so a holder can tell the batch kinds apart. */
|
|
38
|
+
isBatchedLines = true;
|
|
39
|
+
/**
|
|
40
|
+
* The segment template every member is drawn from, and the whole of what the geometry carries: the
|
|
41
|
+
* per-instance data three would put in instanced attributes is in the uniforms instead.
|
|
42
|
+
*
|
|
43
|
+
* Built here rather than mounted as a child element, because it is not a choice the way an atlas's
|
|
44
|
+
* quad is — three's own class is the definition of the template.
|
|
45
|
+
*/
|
|
46
|
+
geometry = new LineSegmentsGeometry();
|
|
47
|
+
/**
|
|
48
|
+
* The material three's line shader compiles from, narrowed because both the fallback width and the
|
|
49
|
+
* resolution screen-space widths are measured against are read off it.
|
|
50
|
+
*
|
|
51
|
+
* Seeded with a throwaway the `<LineMaterial>` child replaces on mount, as the base seeds one for
|
|
52
|
+
* R3F's `<TextureMaterial>` to replace — but a *line* material, because those two are read before
|
|
53
|
+
* anything has been drawn.
|
|
54
|
+
*/
|
|
55
|
+
material = new LineMaterial();
|
|
56
|
+
/** Draw order is paint order, which a container decides through `customSort` rather than depth. */
|
|
57
|
+
sortObjects = true;
|
|
58
|
+
/** Screen space, at each member's own width — see {@link RaycastingLines}. */
|
|
59
|
+
raycasting = new RaycastingLines();
|
|
60
|
+
/** By the ribbon each member draws rather than the segment it runs — see {@link FrustumCullingLines}. */
|
|
61
|
+
culling = new FrustumCullingLines();
|
|
62
|
+
/**
|
|
63
|
+
* @param params - Instance capacity; the buffers grow past it on demand.
|
|
64
|
+
*/
|
|
65
|
+
constructor(params = {}) {
|
|
66
|
+
super(params);
|
|
67
|
+
// Declared by the class rather than by a caller, because the shader reading them is the one three
|
|
68
|
+
// ships and two of the names are its own.
|
|
69
|
+
this.addUniforms({
|
|
70
|
+
vertex: { [START_UNIFORM]: 'vec3', [END_UNIFORM]: 'vec3', [WIDTH_UNIFORM]: 'float' },
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Reads a member's endpoints.
|
|
75
|
+
* @param id - The member to read.
|
|
76
|
+
* @param start - Receives the segment start.
|
|
77
|
+
* @param end - Receives the segment end.
|
|
78
|
+
*/
|
|
79
|
+
getPointsAt(id, start, end) {
|
|
80
|
+
this.getUniformAt(id, START_UNIFORM, start);
|
|
81
|
+
this.getUniformAt(id, END_UNIFORM, end);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Writes a member's endpoints, invalidating the bounds they define.
|
|
85
|
+
*
|
|
86
|
+
* Writes what it is given, like every other setter here. Skipping an unchanged segment is the
|
|
87
|
+
* caller's to do — `LineInstance` compares first, exactly as the write helpers do for the meshes
|
|
88
|
+
* that carry transforms and colors — so a member is never read back on a path that means to write.
|
|
89
|
+
* @param id - The member to write.
|
|
90
|
+
* @param start - The segment start.
|
|
91
|
+
* @param end - The segment end.
|
|
92
|
+
*/
|
|
93
|
+
setPointsAt(id, start, end) {
|
|
94
|
+
this.setUniformAt(id, START_UNIFORM, _start.set(start.x, start.y, start.z));
|
|
95
|
+
this.setUniformAt(id, END_UNIFORM, _end.set(end.x, end.y, end.z));
|
|
96
|
+
this.invalidateBounds();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* A member's own width, or a negative value while it has none and draws at the material's.
|
|
100
|
+
* @param id - The member to read.
|
|
101
|
+
* @returns The width.
|
|
102
|
+
*/
|
|
103
|
+
getWidthAt(id) {
|
|
104
|
+
return this.getUniformAt(id, WIDTH_UNIFORM);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Sets a member's width, in the units the material's `worldUnits` selects.
|
|
108
|
+
*
|
|
109
|
+
* Optional, and the batch cannot make it otherwise — a member nobody set a width for keeps the
|
|
110
|
+
* material's, which every `LineMaterial` has. That fallback is marked by a *negative* width
|
|
111
|
+
* rather than by zero, because zero expands the segment quad to no area: it draws nothing, which
|
|
112
|
+
* is a thing a caller can ask for and not the same request. Callers that treat a width as user
|
|
113
|
+
* input should clamp it at zero, so a nonsensical negative reads as invisible rather than as "use
|
|
114
|
+
* the material's".
|
|
115
|
+
* @param id - The member to write.
|
|
116
|
+
* @param width - The width; negative to fall back to the material's, zero to draw nothing.
|
|
117
|
+
*/
|
|
118
|
+
setWidthAt(id, width) {
|
|
119
|
+
this.setUniformAt(id, WIDTH_UNIFORM, width);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Encloses one member: the sphere through its two endpoints.
|
|
123
|
+
*
|
|
124
|
+
* Takes no account of the width, as three's own line bounds do not either — the ends are where a
|
|
125
|
+
* segment runs, and the ribbon drawn around them is a screen-space skin whose size in the plan
|
|
126
|
+
* depends on the camera.
|
|
127
|
+
* @param id - The member.
|
|
128
|
+
* @param target - Receives the result.
|
|
129
|
+
* @returns The bounds.
|
|
130
|
+
*/
|
|
131
|
+
getBoundingSphereAt(id, target) {
|
|
132
|
+
this.getPointsAt(id, _start, _end);
|
|
133
|
+
target.center.addVectors(_start, _end).multiplyScalar(0.5);
|
|
134
|
+
target.radius = _start.distanceTo(_end) / 2;
|
|
135
|
+
return target;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Encloses one member in a box: the two endpoints, and nothing between them to measure.
|
|
139
|
+
* @param id - The member.
|
|
140
|
+
* @param target - Receives the result.
|
|
141
|
+
* @returns The bounds.
|
|
142
|
+
*/
|
|
143
|
+
getBoundingBoxAt(id, target) {
|
|
144
|
+
this.getPointsAt(id, _start, _end);
|
|
145
|
+
return target.makeEmpty().expandByPoint(_start).expandByPoint(_end);
|
|
146
|
+
}
|
|
147
|
+
/** Frees the segment template, which this batch built rather than three or R3F. */
|
|
148
|
+
dispose() {
|
|
149
|
+
super.dispose();
|
|
150
|
+
this.geometry.dispose();
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Clears a member as it is handed out, so a reused slot keeps nothing of the one that held it.
|
|
154
|
+
*
|
|
155
|
+
* Everything it could inherit, not only what a caller usually sets: a container that writes a
|
|
156
|
+
* color and a width but no endpoints would otherwise draw the removed member's line.
|
|
157
|
+
* @param id - The member being handed out.
|
|
158
|
+
*/
|
|
159
|
+
resetInstance(id) {
|
|
160
|
+
super.resetInstance(id);
|
|
161
|
+
this.setPointsAt(id, ORIGIN, ORIGIN);
|
|
162
|
+
this.setWidthAt(id, MATERIAL_WIDTH);
|
|
163
|
+
this.setColorAt(id, UNTINTED);
|
|
164
|
+
}
|
|
165
|
+
onBeforeRender(renderer, scene, camera, geometry, material, group) {
|
|
166
|
+
// What screen-space widths are measured against, and only the renderer knows it. Set from the
|
|
167
|
+
// mesh rather than the material's own hook, which three calls after this one — picking reads it
|
|
168
|
+
// between frames, and would otherwise read one that is a frame stale.
|
|
169
|
+
renderer.getViewport(_viewport);
|
|
170
|
+
this.material.resolution.set(_viewport.z, _viewport.w);
|
|
171
|
+
super.onBeforeRender(renderer, scene, camera, geometry, material, group);
|
|
172
|
+
}
|
|
173
|
+
patchMaterial(material) {
|
|
174
|
+
// Only a line material can draw a segment at all, so anything else three hands over — a scene's
|
|
175
|
+
// `overrideMaterial`, a shadow pass's depth material — takes the instancing patch alone and
|
|
176
|
+
// simply does not draw them.
|
|
177
|
+
if (!isLineMaterial(material))
|
|
178
|
+
return super.patchMaterial(material);
|
|
179
|
+
// First, so the instancing patch wraps *around* it: at compile time the prologue the line patch
|
|
180
|
+
// reads has to be injected before it runs.
|
|
181
|
+
const unpatchLine = patchLineMaterial(material);
|
|
182
|
+
const unpatchInstancing = super.patchMaterial(material);
|
|
183
|
+
return () => {
|
|
184
|
+
unpatchInstancing();
|
|
185
|
+
unpatchLine();
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Registers the class as an R3F element, by value so the generated key cannot collide with anything
|
|
191
|
+
* three puts in the catalog when the canvas mounts.
|
|
192
|
+
*/
|
|
193
|
+
export const BatchedLines = extend(BatchedLinesImpl);
|
|
194
|
+
/**
|
|
195
|
+
* Whether a material is one three's line shader compiles from.
|
|
196
|
+
* @param material - The material three is about to draw with.
|
|
197
|
+
* @returns Whether it can draw segments.
|
|
198
|
+
*/
|
|
199
|
+
function isLineMaterial(material) {
|
|
200
|
+
return material.isLineMaterial === true;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* The width a member starts at: negative, which is how "none of its own" is marked, so it draws at
|
|
204
|
+
* the material's. See {@link BatchedLinesImpl.setWidthAt} for why the marker is a negative value and
|
|
205
|
+
* not zero.
|
|
206
|
+
*/
|
|
207
|
+
const MATERIAL_WIDTH = -1;
|
|
208
|
+
/** The tint a member starts at: untinted and opaque, so it draws in the material's own color. */
|
|
209
|
+
const UNTINTED = new Vector4(1, 1, 1, 1);
|
|
210
|
+
/** What a member's endpoints are cleared to: a segment with no length, and so no area. */
|
|
211
|
+
const ORIGIN = new Vector3();
|
|
212
|
+
// Scratch, each filled and consumed within one synchronous call.
|
|
213
|
+
const _start = new Vector3();
|
|
214
|
+
const _end = new Vector3();
|
|
215
|
+
const _viewport = new Vector4();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Camera, type Sphere } from 'three';
|
|
2
|
+
import { type LineMaterial } from 'three/addons/lines/LineMaterial.js';
|
|
3
|
+
import { type CullingHost, FrustumCulling } from '../instanced/FrustumCulling';
|
|
4
|
+
/** What {@link FrustumCullingLines} reads off the batch it culls, beyond what every instanced mesh offers. */
|
|
5
|
+
interface CullingHostLines extends CullingHost {
|
|
6
|
+
/** The material, whose width a member with none of its own draws at, and whose units they are in. */
|
|
7
|
+
material: LineMaterial;
|
|
8
|
+
/**
|
|
9
|
+
* A member's own width, or a negative value while it has none.
|
|
10
|
+
* @param id - The member.
|
|
11
|
+
* @returns The width.
|
|
12
|
+
*/
|
|
13
|
+
getWidthAt(id: number): number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Culling for a line batch: each member tested by where it is *drawn*, not where it runs.
|
|
17
|
+
*
|
|
18
|
+
* A member's bounds are its two endpoints, which is the segment. What covers pixels is the ribbon the
|
|
19
|
+
* shader expands around it — after projection, by a width counted in screen pixels — so a member with
|
|
20
|
+
* both ends off screen still shows if that ribbon crosses the edge, and culling on the ends alone
|
|
21
|
+
* pops it there.
|
|
22
|
+
*
|
|
23
|
+
* The margin is added here rather than to the bounds themselves because it is not a property of the
|
|
24
|
+
* member: it depends on the camera, and on how far *this* member is from it. Which is also why it is
|
|
25
|
+
* per member rather than one figure for the batch — a member already knows its own width, and a batch
|
|
26
|
+
* of hairlines beside one wide route would otherwise be padded by the widest of them.
|
|
27
|
+
*/
|
|
28
|
+
export declare class FrustumCullingLines extends FrustumCulling {
|
|
29
|
+
protected instanceSphere(host: CullingHostLines, id: number, camera: Camera, target: Sphere): Sphere;
|
|
30
|
+
/**
|
|
31
|
+
* How far past its endpoints one member draws, in the units its bounds are measured in.
|
|
32
|
+
*
|
|
33
|
+
* Measured at the far side of the member, since a screen-space width covers more of the plan the
|
|
34
|
+
* further away it is — the near side would under-pad the end that is further off.
|
|
35
|
+
* @param host - The batch being culled.
|
|
36
|
+
* @param id - The member.
|
|
37
|
+
* @param camera - The camera the width is measured from.
|
|
38
|
+
* @param sphere - What encloses it, in the batch's own space.
|
|
39
|
+
* @returns The margin.
|
|
40
|
+
*/
|
|
41
|
+
private drawnMargin;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=FrustumCullingLines.d.ts.map
|