@threenative/core 0.3.3 → 0.3.4
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/capabilities.json +555 -21
- package/dist/{assets-CYKk2WTu.d.ts → assets-CqvE429w.d.ts} +45 -3
- package/dist/{canvas-layer-C1SnMoJ-.d.ts → canvas-layer-DDmC_VVF.d.ts} +1 -1
- package/dist/{game-D_6r-k4Y.d.ts → game-CljaDv4D.d.ts} +144 -10
- package/dist/{gpu-readback-CMklJs6r.d.ts → gpu-readback-CqJEfWNQ.d.ts} +16 -6
- package/dist/hot.d.ts +4 -4
- package/dist/index.d.ts +467 -35
- package/dist/index.js +3208 -257
- package/dist/playtest.d.ts +11 -5
- package/dist/playtest.js +55 -5
- package/dist/react.d.ts +2 -2
- package/dist/{renderer-Cy4qeBOA.d.ts → renderer-CfsS2hxi.d.ts} +190 -2
- package/dist/ui-layer.d.ts +5 -3
- package/dist/world.d.ts +900 -14
- package/dist/world.js +10876 -126
- package/gpl/fixtures/make_world_fixture.py +184 -0
- package/gpl/recipes/_common.py +11 -0
- package/gpl/recipes/decimate.py +11 -5
- package/gpl/recipes/export_world.py +682 -0
- package/mcp/blender-server.mjs +55 -1
- package/mcp/engine-server.mjs +54 -20
- package/mcp/servers.mjs +3 -3
- package/package.json +6 -6
- package/patches/three@0.185.1.patch +2101 -138
- package/scripts/apply-three-patch.mjs +61 -37
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import * as three from 'three';
|
|
2
|
-
import { Object3D, AnimationClip, AnimationMixer, Camera, Vector3, Group, Matrix4, Mesh, BufferGeometry,
|
|
3
|
-
export { I as IAssetLoader, a as IAssetLoaderOptions, c as createAssetLoader, r as reconcileMirroredClips } from './assets-
|
|
2
|
+
import { Object3D, AnimationClip, AnimationMixer, Camera, Vector3, Group, Matrix4, Mesh, BufferGeometry, InstancedMesh, Material, ColorRepresentation, Box3, Scene, DirectionalLight, HemisphereLight, Color, FogExp2, Sprite, DataTexture, CatmullRomCurve3, Texture } from 'three';
|
|
3
|
+
export { I as IAssetLoader, a as IAssetLoaderOptions, b as ITextureOptions, c as createAssetLoader, r as reconcileMirroredClips } from './assets-CqvE429w.js';
|
|
4
4
|
export { A as AudioBus, I as IAudioBusOptions, b as IAudioPlayOptions, r as resetAudioCueLedger } from './audio-7i3Xl0l3.js';
|
|
5
|
-
export { C as CanvasLayer } from './canvas-layer-
|
|
6
|
-
import { a as IGamePluginRuntime, b as IGamePluginHooks } from './game-
|
|
7
|
-
export { A as AfterPhysicsCallback, C as ContextMenuPolicy, G as GEOMETRY_ASSET_KEY, c as GEOMETRY_CAPTURE_DEFAULT_LIMIT, d as GEOMETRY_CAPTURE_MAX_LIMIT, e as GEOMETRY_CAPTURE_SORTS, f as GEOMETRY_CAPTURE_TIMEOUT_MS, g as GEOMETRY_CAPTURE_WALK_CAP, h as GeometryCaptureSort, i as ICtx, I as IGame, j as IGameObservationContribution, k as IGameObservationSampleRequest, l as IGamePlatformSource, m as IGeometryCaptureAsset, n as IGeometryCaptureMesh, o as IGeometryCapturePass, p as IGeometryCaptureReport, q as IGeometryCaptureRequest, r as IGeometryCaptureRow, s as IInputAction, t as IInputGamepad, u as IPointerDragHandle, v as IPointerEvent3D, w as IPointerEvents3D, x as IPointerEvents3DOptions, y as IPointerEvents3DPicker, z as IPointerState, B as IRandom, D as IRawInputPointer, E as IRawInputPointerEdge, F as IRawInputState, H as IRaycastOptions, J as IScenePickerOptions, K as IThreeNativeAudioConfig, L as IThreeNativeAudioLoop, M as IThreeNativeAudioOverride, N as IThreeNativeAudioSpectrum, O as IThreeNativeBootSplash, P as IThreeNativeConfig, Q as IThreeNativeIconVariants, R as IThreeNativeLodConfig, S as IThreeNativeLodGenerationConfig, T as IThreeNativeLodOverride, U as IThreeNativeLodRuntimeConfig, V as IThreeNativeTexturesConfig, W as ITweenOptions, X as IWarmUpCacheOptions, Y as IWarmUpObservation, Z as IWarmUpOptions, _ as IWarmUpProgress, $ as IWarmUpRenderer, a0 as IWarmUpReport, a1 as InputBindings, a2 as
|
|
5
|
+
export { C as CanvasLayer } from './canvas-layer-DDmC_VVF.js';
|
|
6
|
+
import { a as IGamePluginRuntime, b as IGamePluginHooks } from './game-CljaDv4D.js';
|
|
7
|
+
export { A as AfterPhysicsCallback, C as ContextMenuPolicy, G as GEOMETRY_ASSET_KEY, c as GEOMETRY_CAPTURE_DEFAULT_LIMIT, d as GEOMETRY_CAPTURE_MAX_LIMIT, e as GEOMETRY_CAPTURE_SORTS, f as GEOMETRY_CAPTURE_TIMEOUT_MS, g as GEOMETRY_CAPTURE_WALK_CAP, h as GeometryCaptureSort, i as ICtx, I as IGame, j as IGameObservationContribution, k as IGameObservationSampleRequest, l as IGamePlatformSource, m as IGeometryCaptureAsset, n as IGeometryCaptureMesh, o as IGeometryCapturePass, p as IGeometryCaptureReport, q as IGeometryCaptureRequest, r as IGeometryCaptureRow, s as IInputAction, t as IInputGamepad, u as IPointerDragHandle, v as IPointerEvent3D, w as IPointerEvents3D, x as IPointerEvents3DOptions, y as IPointerEvents3DPicker, z as IPointerState, B as IRandom, D as IRawInputPointer, E as IRawInputPointerEdge, F as IRawInputState, H as IRaycastOptions, J as IScenePickerOptions, K as IThreeNativeAudioConfig, L as IThreeNativeAudioLoop, M as IThreeNativeAudioOverride, N as IThreeNativeAudioSpectrum, O as IThreeNativeBootSplash, P as IThreeNativeConfig, Q as IThreeNativeIconVariants, R as IThreeNativeLodConfig, S as IThreeNativeLodGenerationConfig, T as IThreeNativeLodOverride, U as IThreeNativeLodRuntimeConfig, V as IThreeNativeTexturesConfig, W as ITweenOptions, X as IWarmUpCacheOptions, Y as IWarmUpObservation, Z as IWarmUpOptions, _ as IWarmUpProgress, $ as IWarmUpRenderer, a0 as IWarmUpReport, a1 as InputBindings, a2 as InputMap, a3 as InputPlatformSource, a4 as PointerEvent3DListener, a5 as PointerEvent3DType, a6 as PointerEvents3D, a7 as Scene, a8 as SceneFrame, a9 as ScenePicker, aa as ScheduleHandle, ab as Scheduler, ac as ThreeNativeBackgroundMode, ad as ThreeNativeLodMinTrianglesScope, ae as ThreeNativeLodPreset, af as ThreeNativeOrientation, ag as ThreeNativeUiRenderer, ah as WarmUpCacheStatus, ai as WarmUpObservationStatus, aj as afterPhysics, ak as captureMouse, al as createRandom, am as defineGame, an as warmUpScene } from './game-CljaDv4D.js';
|
|
8
8
|
import * as three_webgpu from 'three/webgpu';
|
|
9
9
|
import { StorageTexture, ComputeNode, UniformNode, Node, TextureNode, NodeMaterial, StorageBufferNode, StructTypeNode, Data3DTexture, ShadowBaseNode, NodeBuilder, NodeFrame, SpriteNodeMaterial, StorageTextureNode } from 'three/webgpu';
|
|
10
|
-
import { I as IRendererLike, F as FramePassKind, a as IFrameBudgetWindow } from './renderer-
|
|
11
|
-
export { D as DEFAULT_PIPELINE_CENSUS_LIMIT, b as
|
|
12
|
-
import { I as IComputeDriven$1, a as IGPUReadbackSample } from './gpu-readback-
|
|
13
|
-
export { C as ComputeDrivenRegistry, G as GPUReadback, b as IGPUReadbackOptions } from './gpu-readback-
|
|
10
|
+
import { I as IRendererLike, F as FramePassKind, a as IFrameBudgetWindow } from './renderer-CfsS2hxi.js';
|
|
11
|
+
export { D as DEFAULT_PIPELINE_CENSUS_LIMIT, b as DEFAULT_TARGET_FPS, c as FRAME_BUDGET_MARKER, d as FRAME_BUDGET_PHASES, e as FRAME_HITCH_MARKER, f as FrameBudget, g as FrameBudgetPhase, h as FrameCounters, i as ICounterDevice, j as IFrameBudgetOptions, k as IFrameBudgetPassSummary, l as IFrameBudgetSummary, m as IFrameCounters, n as IFramePhaseSample, o as IPipelineCensus, p as IPipelineCensusCounts, q as IPipelineCensusEvent, r as IPipelineCensusOptions, s as IPipelineProvenance, t as IPipelineShaderObservation, u as IPlatformInfo, v as IRenderChainApplied, w as IRenderChainBudgetWindow, x as IRenderChainDroppedStage, y as IRenderChainOptions, z as IRenderChainRenderer, A as IRenderChainRequest, B as IRenderChainStage, C as IRenderChainStageContext, E as IRenderChainVelocityMeasurement, G as IRenderChainVelocityReport, H as IRenderChainVelocityRequest, J as IRenderChainVelocityResult, K as IRenderPassSample, L as ITargetFps, M as IVelocityRenderPass, N as MAX_TARGET_FPS, P as PIPELINE_CENSUS_CAPABILITY, O as PIPELINE_CENSUS_VERSION, Q as PipelineCensus, R as PipelineCensusMode, S as PipelineCensusStatus, T as PlatformFormFactor, U as PlatformOS, V as PlatformRuntime, W as RENDER_CHAIN_MARKER, X as RENDER_CHAIN_STAGE_ORDER, Y as RENDER_CHAIN_TIERS, Z as RenderChain, _ as RenderChainSource, $ as RenderChainStageId, a0 as RenderChainStageName, a1 as RenderChainTier, a2 as RenderChainTierRequest, a3 as RenderChainVelocitySource, a4 as TargetFpsSource, a5 as VELOCITY_OUTPUT_NAME, a6 as VELOCITY_PREVIOUS_BONE_MATRICES, a7 as VELOCITY_PREVIOUS_INSTANCE_MATRICES, a8 as VELOCITY_PREVIOUS_WORLD_MATRIX, a9 as VelocityTracker, aa as counterDeviceOf, ab as createPipelineCensus, ac as ensureVelocityOutput, ad as getPlatform, ae as isMobile, af as isNative, ag as isTouchscreenAvailable, ah as isWeb, ai as prewarm, aj as readRenderChainObservation, ak as readRenderChainReport, al as readVelocityPreviousBoneMatrices, am as readVelocityPreviousMatrices, an as readVelocityPreviousWorldMatrix, ao as resolveTargetFps, ap as snapRefreshRate, aq as velocityTexture, ar as withVelocityContext } from './renderer-CfsS2hxi.js';
|
|
12
|
+
import { I as IComputeDriven$1, a as IGPUReadbackSample } from './gpu-readback-CqJEfWNQ.js';
|
|
13
|
+
export { C as ComputeDrivenRegistry, G as GPUReadback, b as IGPUReadbackOptions } from './gpu-readback-CqJEfWNQ.js';
|
|
14
|
+
import { SkyMesh } from 'three/addons/objects/SkyMesh.js';
|
|
14
15
|
import { Node as Node$1 } from 'three/src/nodes/Nodes.js';
|
|
15
16
|
import 'zustand/vanilla';
|
|
16
17
|
|
|
@@ -757,6 +758,15 @@ interface IInstancedBatchBuildOptions {
|
|
|
757
758
|
readonly parent?: Object3D;
|
|
758
759
|
/** Passed straight to the built mesh. Default `false`, as in Three.js. */
|
|
759
760
|
readonly receiveShadow?: boolean;
|
|
761
|
+
/**
|
|
762
|
+
* An existing mesh to refill instead of creating one: used when it draws this batch's geometry
|
|
763
|
+
* and material and holds at least this many instances. Reusing matters on WebGPU, where three
|
|
764
|
+
* keys an instanced mesh's compiled node program by the mesh itself — every new InstancedMesh
|
|
765
|
+
* rebuilds its shader, and a streamed world creating hundreds a cell stalls on it.
|
|
766
|
+
*/
|
|
767
|
+
readonly into?: InstancedMesh;
|
|
768
|
+
/** Instance slots to allocate when a new mesh is created, so later refills fit. Default: count. */
|
|
769
|
+
readonly capacity?: number;
|
|
760
770
|
}
|
|
761
771
|
/**
|
|
762
772
|
* Collapses many copies of one shape into a single draw, without knowing the count up front.
|
|
@@ -777,8 +787,22 @@ declare class InstancedBatch {
|
|
|
777
787
|
constructor(options: IInstancedBatchOptions);
|
|
778
788
|
/** How many instances have been placed so far. */
|
|
779
789
|
get count(): number;
|
|
790
|
+
/**
|
|
791
|
+
* Writes every placed matrix into `target` (a mesh's `instanceMatrix.array`), starting at instance
|
|
792
|
+
* `offset`, and returns how many were written. For a caller that packs several batches into one
|
|
793
|
+
* shared instance buffer instead of building a mesh per batch.
|
|
794
|
+
*/
|
|
795
|
+
writeMatrices(target: Float32Array, offset: number): number;
|
|
780
796
|
/** The built mesh, or `undefined` before {@link build} — never a guess. */
|
|
781
797
|
get mesh(): InstancedMesh | undefined;
|
|
798
|
+
/**
|
|
799
|
+
* True when this batch holds element-for-element the matrices of `other`.
|
|
800
|
+
*
|
|
801
|
+
* A refilter rebuilds a cell's batch from the same run in the same order, so "did the answer
|
|
802
|
+
* change" is exactly this question, and comparing is what lets the swap skip a rebuild that came
|
|
803
|
+
* back identical instead of writing, clearing and compacting records the buffer already holds.
|
|
804
|
+
*/
|
|
805
|
+
equals(other: InstancedBatch | undefined): boolean;
|
|
782
806
|
/**
|
|
783
807
|
* Records one instance from a matrix the game composed itself, and returns its instance index.
|
|
784
808
|
*
|
|
@@ -833,6 +857,33 @@ interface IMergePartsOptions {
|
|
|
833
857
|
*/
|
|
834
858
|
readonly preserve?: readonly ("uv" | "normal")[];
|
|
835
859
|
}
|
|
860
|
+
interface IMergeByMaterialOptions {
|
|
861
|
+
/** Named in the error when a group's merge is refused. Say what was being built. */
|
|
862
|
+
readonly label: string;
|
|
863
|
+
/**
|
|
864
|
+
* Leaves one mesh out of its material's group and out of the result — a piece that moves at run
|
|
865
|
+
* time, or one a capture script addresses by name.
|
|
866
|
+
*/
|
|
867
|
+
readonly skip?: (mesh: Mesh) => boolean;
|
|
868
|
+
/**
|
|
869
|
+
* An `InstancedMesh` is baked into its material's group as one part per instance matrix while that
|
|
870
|
+
* group stays at or below this many triangles. Above it — or absent, which is the old behaviour —
|
|
871
|
+
* it comes back in the result untouched, because one instanced draw is already cheaper than the
|
|
872
|
+
* triangles it expands into.
|
|
873
|
+
*/
|
|
874
|
+
readonly expandInstancedUnderTriangles?: number;
|
|
875
|
+
/**
|
|
876
|
+
* Vertices one merged group may hold before the rest of its material's parts start a second mesh.
|
|
877
|
+
*
|
|
878
|
+
* One merged group is one upload on the frame that first draws it, and that upload is the frame's
|
|
879
|
+
* whole cost: measured in a browser, a streamed world created 826 GPU buffers totalling 228.8 MB
|
|
880
|
+
* out of `createAttribute`, 33 of them over 1 MB, and the first draw of the largest chunk meshes
|
|
881
|
+
* took up to 230 ms. Splitting a material group in traversal order — which keeps the pieces
|
|
882
|
+
* adjacent to the pieces they were placed beside — bounds each of those uploads instead of
|
|
883
|
+
* trading one draw for a single enormous buffer. See `CHUNK_MERGE_MAX_VERTICES`.
|
|
884
|
+
*/
|
|
885
|
+
readonly maxGroupVertices?: number;
|
|
886
|
+
}
|
|
836
887
|
/**
|
|
837
888
|
* Merge game-authored pieces into one buffer, keeping each piece's own colour and, when asked,
|
|
838
889
|
* its uv and authored normals.
|
|
@@ -846,8 +897,69 @@ interface IMergePartsOptions {
|
|
|
846
897
|
* are entirely the game's, one per part, and changing them changes nothing here. By default the
|
|
847
898
|
* merged normals are recomputed from the merged buffer; `preserve` keeps the authored normals and
|
|
848
899
|
* texture coordinates instead so an imported model's shading survives the bake.
|
|
900
|
+
*
|
|
901
|
+
* A group whose parts are all indexed merges indexed — the sum of their vertex counts, not three
|
|
902
|
+
* times their triangles — and only a mixed group falls back to the de-indexed soup. One crossing
|
|
903
|
+
* 65,535 vertices gets a 32-bit index, because a 16-bit one cannot name the vertex.
|
|
849
904
|
*/
|
|
850
905
|
declare function mergeParts(parts: Iterable<IMergePart>, options: IMergePartsOptions): BufferGeometry;
|
|
906
|
+
/**
|
|
907
|
+
* Bake a hierarchy's static meshes into one mesh per material, transforms and all.
|
|
908
|
+
*
|
|
909
|
+
* A building or a ship is dozens of boxes and cylinders that never move relative to each other, and
|
|
910
|
+
* every one of them is a draw call. Grouping by material and merging each group is the ordinary
|
|
911
|
+
* fix, and the ordinary fix is thirty lines an agent rewrites in every game, each time slightly
|
|
912
|
+
* differently: walk the tree, group by material, bake `matrixWorld` into the vertices, hand the
|
|
913
|
+
* group to `mergeParts`, build a mesh on the game's own material. The parts here are the same
|
|
914
|
+
* `IMergePart` list, so a game that already merges by hand gets the same refusals — a group that
|
|
915
|
+
* cannot merge throws naming `label:material`, not silently vanishing.
|
|
916
|
+
*
|
|
917
|
+
* Nothing here decides how anything looks: the material is the game's own instance, the geometry is
|
|
918
|
+
* exactly what was authored, and the group split follows the materials the game already made.
|
|
919
|
+
*
|
|
920
|
+
* `normal` survives when every mesh in a group carries it and is recomputed otherwise. `uv` survives
|
|
921
|
+
* when any mesh carries it, so a group where only some do is the refusal `mergeParts` raises, never
|
|
922
|
+
* a texture silently left unmapped. Skinned meshes are left alone — their vertices are posed per
|
|
923
|
+
* frame — and an instanced one is left alone unless `expandInstancedUnderTriangles` names a cap its
|
|
924
|
+
* group fits under and its own shape is small enough to be worth repeating, which bakes every
|
|
925
|
+
* instance matrix into the merge.
|
|
926
|
+
*
|
|
927
|
+
* `maxGroupVertices` bounds a single group, and a material whose parts cross it is merged into
|
|
928
|
+
* several meshes in traversal order — more draws, none of them carrying a buffer big enough to stall
|
|
929
|
+
* the frame that first submits it.
|
|
930
|
+
*/
|
|
931
|
+
declare function mergeByMaterial(root: Object3D, options: IMergeByMaterialOptions): Mesh[];
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* A debug switch a game reads the same way on every platform it ships to.
|
|
935
|
+
*
|
|
936
|
+
* Two questions an agent answers differently in every game, both of which cost a rewrite: how do I
|
|
937
|
+
* turn this on for one run without changing the code, and how does a capture script reach the object
|
|
938
|
+
* it wants to look at. The answers here are one function each, and neither decides how anything
|
|
939
|
+
* looks.
|
|
940
|
+
*/
|
|
941
|
+
/**
|
|
942
|
+
* A debug switch read from the URL, or from the environment on a native launch.
|
|
943
|
+
*
|
|
944
|
+
* @situation read a debug toggle from the URL or an environment variable
|
|
945
|
+
*
|
|
946
|
+
* A browser asks with the query string — `?freeCam`, or `?freeCam=0` to force it off — and a native
|
|
947
|
+
* launch asks with `TN_DEBUG_FREE_CAM`, because a query string is not something a developer sets on
|
|
948
|
+
* a command line. `0` and `false` are off, so a saved URL that used to enable a switch still says
|
|
949
|
+
* "off" rather than quietly turning it back on.
|
|
950
|
+
*/
|
|
951
|
+
declare function debugFlag(name: string): boolean;
|
|
952
|
+
/**
|
|
953
|
+
* Publish one game object for a capture script or the console, in development builds only.
|
|
954
|
+
*
|
|
955
|
+
* @situation expose a game object to a capture script or the console in dev builds
|
|
956
|
+
*
|
|
957
|
+
* Playtest reads `__THREENATIVE__` in a dev build and is silent in a production one, so a game that
|
|
958
|
+
* publishes its player, its camera or a scene handle under `.debug` is reachable from the same
|
|
959
|
+
* place a production build is not. Other keys on the shared object are left alone; the dev surfaces
|
|
960
|
+
* the engine installs beside them keep working.
|
|
961
|
+
*/
|
|
962
|
+
declare function exposeDebug(name: string, value: unknown): void;
|
|
851
963
|
|
|
852
964
|
/**
|
|
853
965
|
* A mesh that draws only the clusters this camera can resolve.
|
|
@@ -1015,6 +1127,14 @@ declare class ClusteredBatch {
|
|
|
1015
1127
|
update(camera: Camera, viewportHeight: number): number;
|
|
1016
1128
|
}
|
|
1017
1129
|
|
|
1130
|
+
/**
|
|
1131
|
+
* Pixels a one-world-unit error at `depth` covers, for this camera and viewport.
|
|
1132
|
+
*
|
|
1133
|
+
* Perspective divides the projected scale by the depth; orthographic has no depth term and uses the
|
|
1134
|
+
* frustum height instead. A non-positive depth or an unprojectable camera throws rather than
|
|
1135
|
+
* returning a plausible-looking wrong scale.
|
|
1136
|
+
*/
|
|
1137
|
+
declare function lodPixelScale(camera: Camera, viewportHeight: number, depth: number): number;
|
|
1018
1138
|
/** The LOD0 geometry of a mesh under a discrete chain, or the mesh's own geometry otherwise. */
|
|
1019
1139
|
declare function baseGeometryOf(mesh: Mesh): BufferGeometry;
|
|
1020
1140
|
/**
|
|
@@ -1609,6 +1729,8 @@ interface IClipWindow {
|
|
|
1609
1729
|
readonly level: number;
|
|
1610
1730
|
readonly extent: number;
|
|
1611
1731
|
readonly pageWorldSize: number;
|
|
1732
|
+
/** Pages a window trails its followed centre by before it moves and re-renders. */
|
|
1733
|
+
readonly refreshPages: number;
|
|
1612
1734
|
readonly minX: number;
|
|
1613
1735
|
readonly minY: number;
|
|
1614
1736
|
readonly maxX: number;
|
|
@@ -1620,8 +1742,18 @@ interface IDirectionalClipmapOptions {
|
|
|
1620
1742
|
/** Half-width of each level's window in world units, finest first. */
|
|
1621
1743
|
readonly clipExtents: readonly number[];
|
|
1622
1744
|
readonly pagesPerAxis: number;
|
|
1623
|
-
/**
|
|
1624
|
-
|
|
1745
|
+
/**
|
|
1746
|
+
* Fraction of an extent inside which a point selects that level, `(0, 1]`, default 0.9. One value
|
|
1747
|
+
* for every level, or one per level finest first, the last entry standing in for the rest.
|
|
1748
|
+
*/
|
|
1749
|
+
readonly selectionGuard?: number | readonly number[];
|
|
1750
|
+
/**
|
|
1751
|
+
* Fraction of an extent a level's window may trail its followed centre by before it re-renders,
|
|
1752
|
+
* `[0, 1)`, default 0.125. Rounded to a whole number of the level's texels, so `0` keeps the
|
|
1753
|
+
* old one-texel step. Larger steps re-render a level less often as the camera walks. One value
|
|
1754
|
+
* for every level, or one per level finest first, the last entry standing in for the rest.
|
|
1755
|
+
*/
|
|
1756
|
+
readonly refreshStep?: number | readonly number[];
|
|
1625
1757
|
}
|
|
1626
1758
|
/**
|
|
1627
1759
|
* Camera-centred clip windows in a light-space basis, snapped to whole pages.
|
|
@@ -1634,14 +1766,21 @@ declare class DirectionalClipmap {
|
|
|
1634
1766
|
#private;
|
|
1635
1767
|
readonly clipExtents: readonly number[];
|
|
1636
1768
|
readonly pagesPerAxis: number;
|
|
1637
|
-
|
|
1769
|
+
/**
|
|
1770
|
+
* Per level, finest first; the last entry stands in for every level past it. Mutable through
|
|
1771
|
+
* {@link setRefreshStep} so a level whose own render is expensive can be stepped further, which
|
|
1772
|
+
* is fewer grid positions for its window rather than a different grid.
|
|
1773
|
+
*/
|
|
1774
|
+
refreshStep: number[];
|
|
1775
|
+
/** Per level, finest first; the last entry stands in for every level past it. */
|
|
1776
|
+
readonly selectionGuard: readonly number[];
|
|
1638
1777
|
readonly levelCount: number;
|
|
1639
1778
|
basisU: IVector3Like;
|
|
1640
1779
|
basisV: IVector3Like;
|
|
1641
1780
|
basisW: IVector3Like;
|
|
1642
1781
|
centerWorld: IVector3Like;
|
|
1643
1782
|
centerLight: ILightSpacePoint;
|
|
1644
|
-
constructor({ direction, clipExtents, pagesPerAxis, selectionGuard, }: IDirectionalClipmapOptions);
|
|
1783
|
+
constructor({ direction, clipExtents, pagesPerAxis, selectionGuard, refreshStep, }: IDirectionalClipmapOptions);
|
|
1645
1784
|
/** Re-orient the basis; returns true when it changed enough that cached pages are stale. */
|
|
1646
1785
|
setDirection(direction: IVector3Like): boolean;
|
|
1647
1786
|
project(worldPoint: IVector3Like): ILightSpacePoint;
|
|
@@ -1650,6 +1789,8 @@ declare class DirectionalClipmap {
|
|
|
1650
1789
|
v: number;
|
|
1651
1790
|
w?: number;
|
|
1652
1791
|
}): IVector3Like;
|
|
1792
|
+
/** Re-step one level's window: the trail its followed centre may move before it re-renders. */
|
|
1793
|
+
setRefreshStep(level: number, step: number): void;
|
|
1653
1794
|
updateCenter(worldPoint: IVector3Like): readonly IClipWindow[];
|
|
1654
1795
|
getWindow(level: number): IClipWindow;
|
|
1655
1796
|
pageWorldSize(level: number): number;
|
|
@@ -1722,12 +1863,130 @@ interface IVirtualShadowOptions {
|
|
|
1722
1863
|
/**
|
|
1723
1864
|
* Fraction of a level's extent inside which a fragment still selects that level, `(0, 1]`,
|
|
1724
1865
|
* default 0.9 — the outer ring falls through to the next level so the edge is never sampled.
|
|
1866
|
+
* `selectionGuard` minus `refreshStep`, since a window trails its centre by that much. One value
|
|
1867
|
+
* for every level, or one per level finest first, the last entry standing in for the rest.
|
|
1868
|
+
*/
|
|
1869
|
+
readonly selectionGuard?: number | readonly number[];
|
|
1870
|
+
/**
|
|
1871
|
+
* Fraction of a level's extent its window may trail the followed centre by before it re-renders,
|
|
1872
|
+
* `[0, selectionGuard)`, default 0.125 — `refreshStep: 0` keeps the old one-texel step. The step
|
|
1873
|
+
* is rounded to a whole number of that level's texels, so a walking camera re-renders a level
|
|
1874
|
+
* ~`1/refreshStep` times less often while the shadow texels stay on one fixed world grid. Costs
|
|
1875
|
+
* that much of `selectionGuard`, which it is already reduced by, so a window never reaches past
|
|
1876
|
+
* the trailing edge of a map rendered before the centre moved. One value for every level, or one
|
|
1877
|
+
* per level finest first, the last entry standing in for the rest — the fine level is the one a
|
|
1878
|
+
* walking camera re-renders most, so it is the one that wants the larger step.
|
|
1879
|
+
*/
|
|
1880
|
+
readonly refreshStep?: number | readonly number[];
|
|
1881
|
+
/**
|
|
1882
|
+
* Let a level buy itself a wider `refreshStep` out of what its own last render cost, default true.
|
|
1883
|
+
*
|
|
1884
|
+
* A level render is a whole scene draw, so the engine cannot know what one is worth until it has
|
|
1885
|
+
* paid for it: the node measures the draw it just took and smooths that reading, and a level whose
|
|
1886
|
+
* smoothed cost is a large share of the frame period is re-rendered less often. This is automatic
|
|
1887
|
+
* because the value it reacts to is a measurement, not a setting — a game sets nothing, and a
|
|
1888
|
+
* cheap level is never widened and behaves exactly as before. The widened trail is capped by the
|
|
1889
|
+
* window's own margin, so the camera stays inside the region that level serves and everything that
|
|
1890
|
+
* level serves stays inside the map; a level with no such margin is never widened at all.
|
|
1891
|
+
*
|
|
1892
|
+
* `false` puts every level back on the `refreshStep` it was given, which is also what a harness
|
|
1893
|
+
* that wants to count today's renders uses.
|
|
1894
|
+
*/
|
|
1895
|
+
readonly adaptiveRefresh?: boolean;
|
|
1896
|
+
/**
|
|
1897
|
+
* Fraction of the display period a level's smoothed render cost may take before its refresh trail
|
|
1898
|
+
* widens, `(0, 1]`, default 0.4.
|
|
1899
|
+
*
|
|
1900
|
+
* The period is the frame's own `deltaTime`, capped at the 60 fps frame (16.7 ms). The cap is what
|
|
1901
|
+
* keeps the budget honest: the frame that renders an expensive level is itself long because of that
|
|
1902
|
+
* render, so reading the share against its own inflated delta would count the cost twice and let
|
|
1903
|
+
* the very level that needs adapting pass its own test. At 60 Hz the cap is the frame itself; on a
|
|
1904
|
+
* 120 Hz panel the same render is twice the share it is at 60; below 60 the cap holds the budget
|
|
1905
|
+
* at the 60 fps frame rather than growing with the stall. Below the share nothing changes at all,
|
|
1906
|
+
* and above it the trail widens in proportion to the overshoot,
|
|
1907
|
+
* because that is the ratio between what the level costs and what a frame can afford to spend on
|
|
1908
|
+
* it — a level four times over the share refreshs about four times less often, until the cap
|
|
1909
|
+
* below it runs out.
|
|
1910
|
+
*/
|
|
1911
|
+
readonly expensiveRefreshShare?: number;
|
|
1912
|
+
/**
|
|
1913
|
+
* Raise a level's texel size gate while its own render is too expensive for the frame, default
|
|
1914
|
+
* true.
|
|
1915
|
+
*
|
|
1916
|
+
* The same measurement adaptive refresh reads — the smoothed cost of the level's own last render,
|
|
1917
|
+
* against the share of the frame it may take — drives a second, independent adaptation: a level
|
|
1918
|
+
* whose render is over budget sizes its gate up in steps of 1.5 until it is affordable again, up
|
|
1919
|
+
* to 8 times the configured gate, and halves it back toward 1 once the render is comfortably under
|
|
1920
|
+
* half the budget. The gate only ever judges a caster by its size (see `minCasterTexels`), so this
|
|
1921
|
+
* drops the tiniest props first and never a building, and a level that is cheap is never touched:
|
|
1922
|
+
* it stays at scale 1 and submits exactly what it did before.
|
|
1923
|
+
*
|
|
1924
|
+
* `false` pins every level at scale 1, which is also what a harness that wants today's draw
|
|
1925
|
+
* counts uses.
|
|
1926
|
+
*/
|
|
1927
|
+
readonly adaptiveCasterGate?: boolean;
|
|
1928
|
+
/**
|
|
1929
|
+
* How long a level waits after its own last render before an invalidation may re-render it, in
|
|
1930
|
+
* seconds. One value for every level, or one per level finest first, the last entry standing in
|
|
1931
|
+
* for the rest. Default `0.25 * extent / finestExtent` — 0.25 s, 1 s and 3.33 s for extents
|
|
1932
|
+
* 24 / 96 / 320 — and `0` renders on the very next frame, which is what the node did before.
|
|
1933
|
+
*
|
|
1934
|
+
* A streamed world invalidates its shadows on every residency update, and a cell admitted at the
|
|
1935
|
+
* ring edge lands in the coarsest window: the level that redraws for it is the one paying for the
|
|
1936
|
+
* whole ring's wide casters, ten times a second where movement alone asks for two. A level
|
|
1937
|
+
* waiting out its delay keeps the map and window it has, which is already right for every static
|
|
1938
|
+
* caster in it, so only a newly streamed caster is missing — the trade is that a far tree's
|
|
1939
|
+
* shadow can appear up to the delay late (3.33 s at extent 320, invisible on a level whose texel
|
|
1940
|
+
* is wider than the tree). A window that moved is never delayed: that is a different reason, and
|
|
1941
|
+
* it is not this option's.
|
|
1942
|
+
*/
|
|
1943
|
+
readonly invalidationDelay?: number | readonly number[];
|
|
1944
|
+
/**
|
|
1945
|
+
* How far behind the window centre each level camera sits, in world units. Default 200. An
|
|
1946
|
+
* explicit `lightDistance` *and* `depthRange` switch the level's light-space depth off the derived
|
|
1947
|
+
* span below and back onto this pair, so a game that knows its own world sizes can still say so.
|
|
1725
1948
|
*/
|
|
1726
|
-
readonly selectionGuard?: number;
|
|
1727
|
-
/** How far behind the window centre each level camera sits, in world units. Default 200. */
|
|
1728
1949
|
readonly lightDistance?: number;
|
|
1729
|
-
/**
|
|
1950
|
+
/**
|
|
1951
|
+
* Depth range each level camera covers past its centre, in world units. Default 400. Read only
|
|
1952
|
+
* together with `lightDistance`; on its own the span is still derived.
|
|
1953
|
+
*/
|
|
1730
1954
|
readonly depthRange?: number;
|
|
1955
|
+
/**
|
|
1956
|
+
* Texels of a level a caster must cover before it draws into that level, default 1.5. A level's
|
|
1957
|
+
* texel is `2 * extent / mapSize`, so the finest levels keep everything and the coarse ones keep
|
|
1958
|
+
* only what they can resolve: a fern is a whole number of texels in a 48 m window and a fraction
|
|
1959
|
+
* of one in a 640 m window, so it stops being drawn there and the shadow it casts is the ground
|
|
1960
|
+
* cover's own, not its silhouette's. Set 0 to draw every caster into every level.
|
|
1961
|
+
*/
|
|
1962
|
+
readonly minCasterTexels?: number;
|
|
1963
|
+
/**
|
|
1964
|
+
* Draw every level past the finest one with less geometry than the main pass would, default true.
|
|
1965
|
+
*
|
|
1966
|
+
* Two defaults, both Unreal's and both applied in one place — the traverse a level render already
|
|
1967
|
+
* makes over the casters in its window, where each of the two is a change to the object three
|
|
1968
|
+
* draws from and is put back the moment that render is over:
|
|
1969
|
+
*
|
|
1970
|
+
* 1. **Shadow LOD bias.** A mesh whose geometry carries a registered AutoLOD chain
|
|
1971
|
+
* (`lodChainOf`) is submitted with the chain's *coarsest* geometry. A level 2 window cannot
|
|
1972
|
+
* resolve a tree's needles, so drawing LOD0 there is a texel of needles per texel of shadow;
|
|
1973
|
+
* the coarse level's own texel is metres wide. Level 0 draws what the main pass draws.
|
|
1974
|
+
* 2. **Alpha-caster range.** An alpha-tested (`alphaTest > 0`) or transparent mesh casts into the
|
|
1975
|
+
* finest level only. Its cutout is its own texture: a coarse level either drops it — the
|
|
1976
|
+
* level's texel is wider than the card, so the fence is sub-texel — or keeps resolving a
|
|
1977
|
+
* texture it cannot afford. This is a per-primitive shadow cull distance, and the trade is
|
|
1978
|
+
* honest and one-sided: a fence's or a foliage card's shadow ends where the finest level's
|
|
1979
|
+
* window ends, and a wide level shows bare ground where it stood. Opaque casters — a merged
|
|
1980
|
+
* chunk's position-only proxy, a tree's silhouette — are drawn on every level as before.
|
|
1981
|
+
*
|
|
1982
|
+
* Neither is left changed: a hidden caster's `castShadow` and a coarse mesh's `geometry` are put
|
|
1983
|
+
* back before the next level, before the mover maps and before the main pass, which see the world
|
|
1984
|
+
* exactly as the game authored it. Mover maps keep full detail — a 256² map over the level's own
|
|
1985
|
+
* window, drawing only the tracked casters.
|
|
1986
|
+
* `false` puts every level back on stock full-detail draws, which is what the node did before
|
|
1987
|
+
* either default existed.
|
|
1988
|
+
*/
|
|
1989
|
+
readonly shadowLodBias?: boolean;
|
|
1731
1990
|
/** Print the `TN_VIRTUAL_SHADOW` line every `markerEvery` frames; `false` silences it. Default 300. */
|
|
1732
1991
|
readonly marker?: boolean | number;
|
|
1733
1992
|
}
|
|
@@ -1747,8 +2006,76 @@ interface IVirtualShadowStats {
|
|
|
1747
2006
|
readonly cached: number;
|
|
1748
2007
|
/** Levels rendered this frame, for any reason. */
|
|
1749
2008
|
readonly rendered: number;
|
|
2009
|
+
/**
|
|
2010
|
+
* Levels that wanted a render this frame and did not get one, because the node renders at most
|
|
2011
|
+
* one level per frame. They keep the map they already have and come due again next frame.
|
|
2012
|
+
*/
|
|
2013
|
+
readonly deferred: number;
|
|
2014
|
+
/**
|
|
2015
|
+
* Levels holding a redraw for an invalidation that is still inside its own `invalidationDelay`,
|
|
2016
|
+
* so this frame is not the frame they render on. They keep the map they have, which is right for
|
|
2017
|
+
* every static caster in it: only a caster streamed in since is missing, and the cumulative
|
|
2018
|
+
* `coalesced` below is what is being waited out.
|
|
2019
|
+
*/
|
|
2020
|
+
readonly held: number;
|
|
1750
2021
|
/** Fraction of levels served from cache over the node's lifetime. */
|
|
1751
2022
|
readonly reuseRatio: number;
|
|
2023
|
+
/**
|
|
2024
|
+
* Level renders over the node's lifetime, for any reason. `byMove` and `byInvalidation` are the two
|
|
2025
|
+
* the node has — a window that moved, and an invalidation that asked and waited out its delay — and
|
|
2026
|
+
* they add up to this exactly, because a render the single per-frame budget defers is counted
|
|
2027
|
+
* against the reason that queued it and not again when it is finally taken.
|
|
2028
|
+
*/
|
|
2029
|
+
readonly rendersTotal: number;
|
|
2030
|
+
/** Of those, the renders taken because a level's window moved. */
|
|
2031
|
+
readonly byMove: number;
|
|
2032
|
+
/** Of those, the renders taken because an invalidation asked and its level's delay had passed. */
|
|
2033
|
+
readonly byInvalidation: number;
|
|
2034
|
+
/**
|
|
2035
|
+
* Invalidation asks that cost no render of their own, over the node's lifetime: absorbed by a
|
|
2036
|
+
* render the level was taking anyway for its window, or merged into an ask already waiting out
|
|
2037
|
+
* that level's delay. The two of these are the shape of the win — with the default delays a walk
|
|
2038
|
+
* asks once a second and renders about that often, and every ask in between is counted here.
|
|
2039
|
+
*/
|
|
2040
|
+
readonly coalesced: number;
|
|
2041
|
+
/**
|
|
2042
|
+
* The same four counters per level, finest first: which window moved, which invalidation asked
|
|
2043
|
+
* for a redraw, which level took the frame's single render, and which wanted one and did not get
|
|
2044
|
+
* it. One entry per level per frame, so a harness reading this — or the `TN_VIRTUAL_SHADOW`
|
|
2045
|
+
* marker line, which carries it — can see which level a walk keeps re-rendering instead of only
|
|
2046
|
+
* how many.
|
|
2047
|
+
*/
|
|
2048
|
+
readonly perLevel: readonly IVirtualShadowLevelStat[];
|
|
2049
|
+
}
|
|
2050
|
+
/** One level's row of {@link IVirtualShadowStats}: 1 or 0 per counter, per frame. */
|
|
2051
|
+
interface IVirtualShadowLevelStat {
|
|
2052
|
+
/** The level's clip extent, in world units. */
|
|
2053
|
+
readonly extent: number;
|
|
2054
|
+
readonly deferred: number;
|
|
2055
|
+
readonly invalidated: number;
|
|
2056
|
+
readonly moved: number;
|
|
2057
|
+
readonly rendered: number;
|
|
2058
|
+
/** Caster meshes this level's chosen camera layers submit this frame. Zero if it did not render. */
|
|
2059
|
+
readonly draws: number;
|
|
2060
|
+
/** The same bill split by kind; the five parts sum to {@link draws}. */
|
|
2061
|
+
readonly drawsBy: IVirtualShadowDraws;
|
|
2062
|
+
/** The adaptive caster gate's scale on this level, 1 when it is not shedding casters. */
|
|
2063
|
+
readonly gateScale: number;
|
|
2064
|
+
/** Casters the gate hid on the render this level took this frame; zero if it did not render. */
|
|
2065
|
+
readonly gateHidden: number;
|
|
2066
|
+
}
|
|
2067
|
+
/** One level's caster draws, by the kind of mesh that submitted them. */
|
|
2068
|
+
interface IVirtualShadowDraws {
|
|
2069
|
+
/** Caster batch meshes on the cluster layer, when the cluster half is the level's choice. */
|
|
2070
|
+
readonly cluster: number;
|
|
2071
|
+
/** Key-wide caster meshes on the wide layer, when the wide half is the level's choice. */
|
|
2072
|
+
readonly wide: number;
|
|
2073
|
+
/** Small casters, submitted by the finest level and by any level rendering a prewarm. */
|
|
2074
|
+
readonly small: number;
|
|
2075
|
+
/** Merged per-chunk shadow proxies (`<name>-shadow`), drawn with the cluster half. */
|
|
2076
|
+
readonly chunkProxy: number;
|
|
2077
|
+
/** Everything else casting from layer 0 — terrain, props — which every level draws. */
|
|
2078
|
+
readonly layer0: number;
|
|
1752
2079
|
}
|
|
1753
2080
|
declare const VIRTUAL_SHADOW_MARKER = "TN_VIRTUAL_SHADOW";
|
|
1754
2081
|
/**
|
|
@@ -1756,6 +2083,21 @@ declare const VIRTUAL_SHADOW_MARKER = "TN_VIRTUAL_SHADOW";
|
|
|
1756
2083
|
* Keep it free of other uses; the main camera never needs it (tracked objects keep layer 0).
|
|
1757
2084
|
*/
|
|
1758
2085
|
declare const VIRTUAL_SHADOW_MOVER_LAYER = 29;
|
|
2086
|
+
/**
|
|
2087
|
+
* The object layer a shadow-only caster is put on, so each level's own shadow camera renders it and
|
|
2088
|
+
* the main camera never sees it. The level cameras have it enabled already; an object that exists
|
|
2089
|
+
* only as a shadow caster calls `object.layers.set(VIRTUAL_SHADOW_CASTER_LAYER)`.
|
|
2090
|
+
*/
|
|
2091
|
+
declare const VIRTUAL_SHADOW_CASTER_LAYER = 28;
|
|
2092
|
+
/**
|
|
2093
|
+
* The wide counterpart of {@link VIRTUAL_SHADOW_CASTER_LAYER}: one caster mesh per
|
|
2094
|
+
* `asset:level:part` holding every resident cell's records, for the levels whose window covers the
|
|
2095
|
+
* whole resident ring. A level renders exactly one of the two caster layers — whichever submits
|
|
2096
|
+
* fewer draws, counted off the meshes themselves, because a cluster per square is a draw per square
|
|
2097
|
+
* for the same pixels once the window holds the ring. `WorldCells` writes both halves of every key,
|
|
2098
|
+
* so whichever a level picks is there; the main camera renders neither.
|
|
2099
|
+
*/
|
|
2100
|
+
declare const VIRTUAL_SHADOW_WIDE_CASTER_LAYER = 27;
|
|
1759
2101
|
/**
|
|
1760
2102
|
* One directional shadow for a whole open world: camera-centred clip levels, each snapped to its
|
|
1761
2103
|
* own texel grid and re-rendered only when its window moves. Movers never touch that cache: a
|
|
@@ -1770,7 +2112,9 @@ declare const VIRTUAL_SHADOW_MOVER_LAYER = 29;
|
|
|
1770
2112
|
* map type and filter, and those source settings are mirrored into each stock level node before
|
|
1771
2113
|
* rendering. Per-level map sizes, cameras, `autoUpdate` and `needsUpdate` are owned by this node.
|
|
1772
2114
|
* Each level is rendered by the stock {@link ShadowNode} through the renderer's shadow-map type,
|
|
1773
|
-
* so the look is the same code path a plain shadow uses.
|
|
2115
|
+
* so the look is the same code path a plain shadow uses. At most one level renders per frame,
|
|
2116
|
+
* finest first — a level render is a whole scene draw, and a level passed over keeps the map and
|
|
2117
|
+
* window it has, so a fragment only ever samples a map that level drew.
|
|
1774
2118
|
*
|
|
1775
2119
|
* Ported from the virtual-shadow-map prototype's clipmap and invalidation; the sparse page atlas
|
|
1776
2120
|
* is deliberately not the first cut — a page needs the scene rendered once per page, and on a
|
|
@@ -1793,8 +2137,18 @@ declare const VIRTUAL_SHADOW_MOVER_LAYER = 29;
|
|
|
1793
2137
|
declare class VirtualShadowNode extends ShadowBaseNode {
|
|
1794
2138
|
#private;
|
|
1795
2139
|
static get type(): string;
|
|
1796
|
-
readonly options: Required<Omit<IVirtualShadowOptions, "marker">> & {
|
|
2140
|
+
readonly options: Required<Omit<IVirtualShadowOptions, "marker" | "refreshStep" | "selectionGuard" | "invalidationDelay">> & {
|
|
1797
2141
|
readonly markerEvery: number;
|
|
2142
|
+
/** Per level, finest first; the last entry stands in for every level past it. */
|
|
2143
|
+
readonly refreshStep: readonly number[];
|
|
2144
|
+
/** The per-level `selectionGuard` each level's own window is drawn with. */
|
|
2145
|
+
readonly selectionGuard: readonly number[];
|
|
2146
|
+
/**
|
|
2147
|
+
* Per level, finest first: the seconds a dirty level waits after its own last render before an
|
|
2148
|
+
* invalidation may re-render it. Already scaled by that level's extent, so the fine levels
|
|
2149
|
+
* answer a streamed caster promptly and the coarse ones let a burst merge into one render.
|
|
2150
|
+
*/
|
|
2151
|
+
readonly invalidationDelay: readonly number[];
|
|
1798
2152
|
};
|
|
1799
2153
|
readonly clipmap: DirectionalClipmap;
|
|
1800
2154
|
/**
|
|
@@ -1820,6 +2174,18 @@ declare class VirtualShadowNode extends ShadowBaseNode {
|
|
|
1820
2174
|
untrackCaster(objectOrId: Object3D | string): boolean;
|
|
1821
2175
|
/** Force every level to re-render on the next frame — a tree fell, a door opened. */
|
|
1822
2176
|
invalidateAll(): void;
|
|
2177
|
+
/**
|
|
2178
|
+
* Force only the levels whose current window covers `bounds`, on the next frame. A streamed world
|
|
2179
|
+
* that hands its shadow casters over has a moving near set, and a blanket `invalidateAll()` on
|
|
2180
|
+
* every refresh redrew all three levels for a change that lands in one corner of one of them. A
|
|
2181
|
+
* level whose window does not cover the region draws the same thing either way, so skipping it is
|
|
2182
|
+
* the same frame with fewer draws in it.
|
|
2183
|
+
*
|
|
2184
|
+
* `bounds` is `{ min: {x,y,z}, max: {x,y,z} }`, a plain object so a game can hand one over without
|
|
2185
|
+
* importing three. Regions are consumed by the next `updateBefore`; one that arrives before the
|
|
2186
|
+
* levels exist is dropped, because their first frame renders all of them anyway.
|
|
2187
|
+
*/
|
|
2188
|
+
invalidateRegion(bounds: IBoundsLike): void;
|
|
1823
2189
|
setup(builder: NodeBuilder): Node | null | undefined;
|
|
1824
2190
|
updateBefore(frame: NodeFrame): undefined;
|
|
1825
2191
|
dispose(): void;
|
|
@@ -1835,6 +2201,87 @@ declare class VirtualShadowNode extends ShadowBaseNode {
|
|
|
1835
2201
|
*/
|
|
1836
2202
|
declare function readVirtualShadowMarker(line: string): IVirtualShadowStats | undefined;
|
|
1837
2203
|
|
|
2204
|
+
/** Every value is the game's: this rig wires them and chooses none. */
|
|
2205
|
+
interface IDaylightOptions {
|
|
2206
|
+
/** The eye the sky, the sun's shadow windows and the haze centre on; usually the camera. */
|
|
2207
|
+
readonly follow: Object3D;
|
|
2208
|
+
/** Unit vector from the ground towards the sun. */
|
|
2209
|
+
readonly sunDirection: Vector3;
|
|
2210
|
+
readonly sunColor: Color;
|
|
2211
|
+
/** Irradiance in three's physical units; the same number a Blender sun strength carries. */
|
|
2212
|
+
readonly sunIntensity: number;
|
|
2213
|
+
/** Half-widths of the shadow windows in world units, finest first, strictly increasing. */
|
|
2214
|
+
readonly shadowExtents: readonly number[];
|
|
2215
|
+
/**
|
|
2216
|
+
* How far a window may trail the camera before it re-renders, as a fraction of its own extent:
|
|
2217
|
+
* one value for every level, or one per level finest first, the last entry standing in for the
|
|
2218
|
+
* rest. One for all of them spends the hysteresis the fine level can least afford on the coarse
|
|
2219
|
+
* one, which is the level a walking camera re-renders least. Default 0.125.
|
|
2220
|
+
*/
|
|
2221
|
+
readonly refreshStep?: number | readonly number[];
|
|
2222
|
+
/** Preetham sky parameters, as three's `SkyMesh` takes them. */
|
|
2223
|
+
readonly sky: {
|
|
2224
|
+
readonly turbidity: number;
|
|
2225
|
+
readonly rayleigh: number;
|
|
2226
|
+
readonly mieCoefficient: number;
|
|
2227
|
+
readonly mieDirectionalG: number;
|
|
2228
|
+
};
|
|
2229
|
+
/** Sky fill from above and bounce from below, as a hemisphere light. */
|
|
2230
|
+
readonly fill: {
|
|
2231
|
+
readonly sky: Color;
|
|
2232
|
+
readonly ground: Color;
|
|
2233
|
+
readonly intensity: number;
|
|
2234
|
+
};
|
|
2235
|
+
/** Exponential-squared haze in the sky's horizon colour, so distance fades into the sky. */
|
|
2236
|
+
readonly haze: {
|
|
2237
|
+
readonly color: Color;
|
|
2238
|
+
readonly density: number;
|
|
2239
|
+
};
|
|
2240
|
+
/** Linear exposure multiplier for the AgX tone curve (2^EV). */
|
|
2241
|
+
readonly exposure: number;
|
|
2242
|
+
/**
|
|
2243
|
+
* Edge of the sky box in world units. It must sit inside the camera's far plane with its corners
|
|
2244
|
+
* included (a box, so half-diagonal ≈ 0.87 × this).
|
|
2245
|
+
*/
|
|
2246
|
+
readonly skySize: number;
|
|
2247
|
+
}
|
|
2248
|
+
/**
|
|
2249
|
+
* An outdoor daylight rig: a physical sky that stays on the eye, one sun whose open-world shadow
|
|
2250
|
+
* windows follow the eye (`VirtualShadowNode`), a hemisphere fill, sky-coloured distance haze and
|
|
2251
|
+
* the AgX tone curve at the game's exposure. It is plumbing, not a look: every colour, angle,
|
|
2252
|
+
* intensity and density is a required option, and the rig adds nothing a game did not ask for.
|
|
2253
|
+
*
|
|
2254
|
+
* Add it with `ctx.add(daylight)`: `attachRenderer` sets tone mapping, exposure and the shadow map
|
|
2255
|
+
* once, and `process` (render cadence) keeps the sky box, the sun and its target on the eye every
|
|
2256
|
+
* frame, so a 2 km map never walks out of its own sky or shadow.
|
|
2257
|
+
*
|
|
2258
|
+
* @situation daytime sky, sun and shadows for a large outdoor map
|
|
2259
|
+
* @situation distant terrain should fade into the sky instead of a coloured wall
|
|
2260
|
+
* @situation match a Blender look-dev scene's sun, sky and exposure in the game
|
|
2261
|
+
* @constraint every value is required; there is no default sun, sky, haze or exposure
|
|
2262
|
+
* @constraint `skySize` must keep the sky box's corners inside the camera's far plane
|
|
2263
|
+
* @constraint shadowExtents follow `VirtualShadowNode`: half-widths, finest first, strictly increasing
|
|
2264
|
+
* @override sky uniforms stay live on `daylight.sky`; the light and fill are `daylight.sun` and `daylight.fill`
|
|
2265
|
+
* @example
|
|
2266
|
+
* const daylight = new Daylight({ follow: ctx.camera, sunDirection, sunColor, sunIntensity: 4, shadowExtents: [24, 96, 320], sky: { turbidity: 3, rayleigh: 1.4, mieCoefficient: 0.004, mieDirectionalG: 0.8 }, fill: { sky, ground, intensity: 1.1 }, haze: { color: horizon, density: 0.0011 }, exposure: 2 ** -0.6, skySize: 1600 });
|
|
2267
|
+
* ctx.add(daylight);
|
|
2268
|
+
*/
|
|
2269
|
+
declare class Daylight extends Group implements IComputeDriven$1 {
|
|
2270
|
+
#private;
|
|
2271
|
+
readonly warmupNodes: readonly unknown[];
|
|
2272
|
+
readonly processCadence: "render";
|
|
2273
|
+
readonly sky: SkyMesh;
|
|
2274
|
+
readonly sun: DirectionalLight;
|
|
2275
|
+
readonly fill: HemisphereLight;
|
|
2276
|
+
constructor(options: IDaylightOptions);
|
|
2277
|
+
get released(): boolean;
|
|
2278
|
+
/** The haze this rig owns; `attachRenderer` puts it on the scene the rig was added to. */
|
|
2279
|
+
get haze(): FogExp2;
|
|
2280
|
+
attachRenderer(renderer: IRendererLike): void;
|
|
2281
|
+
process(): void;
|
|
2282
|
+
detach(): void;
|
|
2283
|
+
}
|
|
2284
|
+
|
|
1838
2285
|
/**
|
|
1839
2286
|
* Two load-time mechanisms every streaming game writes by hand, and gets wrong in the same places.
|
|
1840
2287
|
*
|
|
@@ -2938,21 +3385,6 @@ declare function measureThreePose(object: Object3D, options?: IMeasureThreePoseO
|
|
|
2938
3385
|
*/
|
|
2939
3386
|
declare function posedBounds(root: Object3D, meshes?: readonly Object3D[]): IThreePoseBounds;
|
|
2940
3387
|
|
|
2941
|
-
type PlatformRuntime = "web" | "native";
|
|
2942
|
-
type PlatformOS = "android" | "ios" | "linux" | "macos" | "windows" | "unknown";
|
|
2943
|
-
type PlatformFormFactor = "mobile" | "desktop" | "unknown";
|
|
2944
|
-
interface IPlatformInfo {
|
|
2945
|
-
readonly runtime: PlatformRuntime;
|
|
2946
|
-
readonly os: PlatformOS;
|
|
2947
|
-
readonly formFactor: PlatformFormFactor;
|
|
2948
|
-
readonly maxTouchPoints: number;
|
|
2949
|
-
}
|
|
2950
|
-
declare function getPlatform(): Readonly<IPlatformInfo>;
|
|
2951
|
-
declare function isWeb(): boolean;
|
|
2952
|
-
declare function isNative(): boolean;
|
|
2953
|
-
declare function isMobile(): boolean;
|
|
2954
|
-
declare function isTouchscreenAvailable(): boolean;
|
|
2955
|
-
|
|
2956
3388
|
type ReplayPointer = readonly [number, number, number, number, number];
|
|
2957
3389
|
interface IReplayRecordingSample {
|
|
2958
3390
|
readonly keys: readonly string[];
|
|
@@ -3210,6 +3642,6 @@ declare function boneLengthDeviations(root: Object3D, bind: IBoneLengthSnapshot,
|
|
|
3210
3642
|
* unavoidable here — core is bundled for browsers and cannot read `package.json` at runtime — so
|
|
3211
3643
|
* the spec now asserts this equals the manifest instead of asserting a number somebody typed.
|
|
3212
3644
|
*/
|
|
3213
|
-
declare const version = "0.3.
|
|
3645
|
+
declare const version = "0.3.4";
|
|
3214
3646
|
|
|
3215
|
-
export { ATLAS_PADDING, ATMOSPHERE_LUT_RESOLUTIONS, AnimationPlayer, Atmosphere, type AtmosphereDirection, AtmosphereLuts, type AtmosphereRgb, Billboard3D, type BillboardLockAxis, CameraShake, type CameraShakeCurve, ClusteredBatch, ClusteredMesh, FlightModel, FluidField2D, FramePassKind, GPUParticles3D, GPUSceneBVH, type GPUSceneBVHTraceFunction, GroundSnap, type IAddInSlicesOptions, type IAddInSlicesProgress, type IAddInSlicesReport, type IAircraftAirframe, type IAnimationPlayOptions, type IAnimationPlayerOptions, type IAtmosphereLutResolution, type IAtmosphereLutResolutions, type IAtmosphereOptions, type IAtmosphereParameterPatch, type IAtmosphereParameters, type IAtmosphereScenePass, type IBillboard3DOptions, type IBoneContactReport, type IBoneLengthDeviation, type IBoneLengthDeviationReport, type IBoneLengthDeviationsOptions, type IBoneLengthSnapshot, type IBonePoseError, type ICameraShakeOffset, type ICameraShakeOptions, type IClipBindingReport, type IClipCoverageReport, type IClipPoseErrorOptions, type IClipPoseErrorReport, type IClipPoseSubject, type IClipTrackBinding, type IClusterTable, type IClusteredBatchBuildOptions, type IClusteredBatchOptions, type IClusteredMeshOptions, type IClusteredPlacement, IComputeDriven$1 as IComputeDriven, type IFlightAxes, type IFlightControls, type IFlightDeck, type IFlightEnvironment, type IFlightForces, type IFlightModelOptions, type IFlightModifiers, type IFlightQuaternion, type IFlightState, type IFlightVector3, type IFluidFieldOptions, type IFluidFieldSampler, type IFluidFieldVector2, IFrameBudgetWindow, IGPUReadbackSample, type IGPUSceneBVHMaterialGroup, type IGPUSceneBVHOptions, IGamePluginHooks, IGamePluginRuntime, type IGroundSnapOptions, type IInstancedBatchBuildOptions, type IInstancedBatchOptions, type IInstancedPlacement, type ILaunchFailure, type ILoadAllOptions, type ILoadAllProgress, type IMatrixWorldReport, type IMeasureThreePoseOptions, type IMergePart, type IMergePartsOptions, type INormaliseToMetresOptions, type IPathFollow3DOptions, type IPathFollow3DProjection, type IPathFollow3DSample, type
|
|
3647
|
+
export { ATLAS_PADDING, ATMOSPHERE_LUT_RESOLUTIONS, AnimationPlayer, Atmosphere, type AtmosphereDirection, AtmosphereLuts, type AtmosphereRgb, Billboard3D, type BillboardLockAxis, CameraShake, type CameraShakeCurve, ClusteredBatch, ClusteredMesh, Daylight, FlightModel, FluidField2D, FramePassKind, GPUParticles3D, GPUSceneBVH, type GPUSceneBVHTraceFunction, GroundSnap, type IAddInSlicesOptions, type IAddInSlicesProgress, type IAddInSlicesReport, type IAircraftAirframe, type IAnimationPlayOptions, type IAnimationPlayerOptions, type IAtmosphereLutResolution, type IAtmosphereLutResolutions, type IAtmosphereOptions, type IAtmosphereParameterPatch, type IAtmosphereParameters, type IAtmosphereScenePass, type IBillboard3DOptions, type IBoneContactReport, type IBoneLengthDeviation, type IBoneLengthDeviationReport, type IBoneLengthDeviationsOptions, type IBoneLengthSnapshot, type IBonePoseError, type ICameraShakeOffset, type ICameraShakeOptions, type IClipBindingReport, type IClipCoverageReport, type IClipPoseErrorOptions, type IClipPoseErrorReport, type IClipPoseSubject, type IClipTrackBinding, type IClusterTable, type IClusteredBatchBuildOptions, type IClusteredBatchOptions, type IClusteredMeshOptions, type IClusteredPlacement, IComputeDriven$1 as IComputeDriven, type IDaylightOptions, type IFlightAxes, type IFlightControls, type IFlightDeck, type IFlightEnvironment, type IFlightForces, type IFlightModelOptions, type IFlightModifiers, type IFlightQuaternion, type IFlightState, type IFlightVector3, type IFluidFieldOptions, type IFluidFieldSampler, type IFluidFieldVector2, IFrameBudgetWindow, IGPUReadbackSample, type IGPUSceneBVHMaterialGroup, type IGPUSceneBVHOptions, IGamePluginHooks, IGamePluginRuntime, type IGroundSnapOptions, type IInstancedBatchBuildOptions, type IInstancedBatchOptions, type IInstancedPlacement, type ILaunchFailure, type ILoadAllOptions, type ILoadAllProgress, type IMatrixWorldReport, type IMeasureThreePoseOptions, type IMergeByMaterialOptions, type IMergePart, type IMergePartsOptions, type INormaliseToMetresOptions, type IPathFollow3DOptions, type IPathFollow3DProjection, type IPathFollow3DSample, type IProbeVolumeBakeProgress, type IProbeVolumeCoefficient, type IProbeVolumeObservation, type IProbeVolumeOptions, type IReplayOptions, type IReplayRecording, type IReplayRecordingSample, type IResolvedAtmosphereParameters, type IRippleFieldFlow, type IRippleFieldOptions, type ISceneShape, type ISceneWarning, type ISkeletalMesh3DOptions, type ISoftBody3DOptions, type ISoftBodyCollision, type ISolarPosition, type ISolarPositionInput, type ISpanProbeTarget, type ISpanSummary, type ISpanWindow, type ISpectralOceanCascade, type ISpectralOceanHeight, type ISpectralOceanOptions, type ISpriteAnimator3DOptions, type ISpriteFrame3D, type IStaticTransformCensus, type IStrideReport, type IThreePoseBounds, type IThreePoseMeasurement, type ITracerPool3DOptions, type ITracerSpawnOptions, type IValidationReport, type IVirtualShadowOptions, type IVirtualShadowStats, type IWaterReflectionOptions, type IWaterSurfaceOptions, type IWaveFieldDomainWarp, type IWaveFieldGraphOptions, type IWaveFieldOptions, type IWaveFieldSample, type IWaveFieldWave, InstancedBatch, LUT_RESOLUTIONS, type LaunchFailureKind, type MatrixWorldMode, MatrixWorldPass, NEUTRAL_FLIGHT_MODIFIERS, type NormaliseAxis, PROBE_VOLUME_MARKER, PathFollow3D, ProbeVolume, type ProbeVolumeDensity, RENDERLIST_VALIDATE_FLAG, RENDERLIST_VALIDATE_MARKER, type Recording, RenderListValidator, type ReplayPointer, RippleField, SCENE_WARNING_MARKER, SPANS, SPANS_FLAG, SPANS_MARKER, SPAN_COUNT, SPAN_NAMES, STATIC_TRANSFORM_MARKER, SkeletalMesh3D, SoftBody3D, type SpanId, SpanRecorder, SpectralOcean, SpriteAnimator3D, type SpritePlaybackMode, type ThreePoseQuaternion, type ThreePoseVector, TracerPool3D, VIRTUAL_SHADOW_CASTER_LAYER, VIRTUAL_SHADOW_MARKER, VIRTUAL_SHADOW_MOVER_LAYER, VIRTUAL_SHADOW_WIDE_CASTER_LAYER, VirtualShadowNode, WaterSurface3D, type WaveDirection, WaveField, addInSlices, addSpan, aerodynamicCoefficients, airDensity, aircraftMass, alwaysRender, attachToBone, attitudeAxes, baseGeometryOf, beginSpan, boneContact, boneLengthDeviations, boneLengths, bvhIntersectFirstHit, clipBoneCoverage, clipPoseError, clipTrackBindings, createReplayDriver, debugFlag, describeSceneShape, describeSceneWarning, directionFromSolarPosition, directionalTransmittance, displayPeriodMs, endSpan, exposeDebug, formatSceneWarning, formatSpansWindow, formatValidationReport, gearClearance, installSpanProbes, invalidateStatic, isStatic, loadAll, lodPixelScale, markStatic, measureThreePose, mergeByMaterial, mergeParts, normaliseToMetres, onLaunchFailure, parseReplayRecording, posedBounds, rayStruct, readProbeVolumeObservation, readVirtualShadowMarker, refreshStaticTransforms, renderListValidationRequested, replay, resetStaticTransforms, resolveAtmosphereLutResolutions, resolveAtmosphereParameters, sceneWarning, setAttitude, setSpanRecorder, skeletonBones, softCircleDataTexture, solarPosition, solarPositionAt, spanNow, spanRecorder, spansRequested, staticTransformCensus, unmarkStatic, updateAtmosphereParameters, updateClusteredMeshes, updateModelLods, validateWorldMatrices, version, zenithTransmittance };
|