@hello-terrain/three 0.0.0-alpha.4 → 0.0.0-alpha.5

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/dist/index.d.mts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { BufferGeometry } from 'three';
2
2
  import * as three_webgpu from 'three/webgpu';
3
- import { InstancedMesh, NodeMaterial, ConstNode, Node as Node$1, StorageBufferAttribute, StorageBufferNode, UniformNode, Vector3, Vector3Like } from 'three/webgpu';
3
+ import { InstancedMesh, NodeMaterial, Node, WebGPURenderer, StorageBufferAttribute, StorageBufferNode, UniformNode, Vector3, Vector3Like, ConstNode } from 'three/webgpu';
4
4
  import * as three_src_nodes_TSL_js from 'three/src/nodes/TSL.js';
5
5
  import { ShaderCallNodeInternal } from 'three/src/nodes/TSL.js';
6
- import Node from 'three/src/nodes/core/Node.js';
7
6
  import * as _hello_terrain_work from '@hello-terrain/work';
8
7
  import { TaskRef } from '@hello-terrain/work';
8
+ import Node$1 from 'three/src/nodes/core/Node.js';
9
+ import * as three_tsl from 'three/tsl';
9
10
 
10
11
  /**
11
12
  * Custom geometry for terrain tiles with properly handled skirts.
@@ -108,67 +109,47 @@ declare class TerrainMesh extends InstancedMesh {
108
109
  set maxNodes(maxNodes: number);
109
110
  }
110
111
 
111
- /**
112
- * Maps a value or node from texture space [0, 1] to vector space [-1, 1].
113
- *
114
- * @param value - The node or value in the range [0, 1].
115
- * @returns A node mapping the input value to the range [-1, 1].
116
- */
117
- declare const textureSpaceToVectorSpace: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node]>;
118
- /**
119
- * Maps a value or node from vector space [-1, 1] to texture space [0, 1].
120
- *
121
- * @param value - The node or value in the range [-1, 1].
122
- * @returns A node mapping the input value to the range [0, 1].
123
- */
124
- declare const vectorSpaceToTextureSpace: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node]>;
125
- /**
126
- * Blends two normal maps using the Reoriented Normal Mapping technique.
127
- * This is the same algorithm used by Unreal Engine's BlendAngleCorrectedNormals node.
128
- *
129
- * Both inputs should be in vector space [-1, 1].
130
- *
131
- * @see https://blog.selfshadow.com/publications/blending-in-detail/
132
- */
133
- declare const blendAngleCorrectedNormals: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node, number | Node]>;
134
- /**
135
- * Reconstructs the Z component of a normal from the X and Y components.
136
- *
137
- * @param normalXY - A vec2 containing the X and Y components of the normal
138
- * @returns A vec3 with the reconstructed normal (X, Y, derived Z)
139
- */
140
- declare const deriveNormalZ: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node]>;
112
+ type ComputeStageCallback = (nodeIndex: Node, globalVertexIndex: Node, uv: Node, localCoordinates: Node, texelSize: Node) => void;
113
+ type ComputePipeline = ComputeStageCallback[];
141
114
 
115
+ /** Default compile task — uses normalFieldStageTask as the leaf. */
116
+ declare const compileComputeTask: _hello_terrain_work.Task<{
117
+ execute: (renderer: WebGPURenderer, instanceCount: number) => void;
118
+ }, string, unknown>;
119
+ /** Default execute task — dispatches the compiled kernel. */
120
+ declare const executeComputeTask: _hello_terrain_work.Task<any, string, {
121
+ renderer: WebGPURenderer;
122
+ }>;
142
123
  /**
143
- * Input type for segment count: either a JS number or a TSL integer node.
144
- * When a number is provided, it's automatically converted to an int node.
145
- * When a Node is provided, it should resolve to an integer value.
146
- */
147
- type IntNodeInput = number | ConstNode<number> | Node$1;
148
- /**
149
- * Returns a node that is true for skirt vertices in the vertex stage.
124
+ * Factory for user-extensible pipelines.
150
125
  *
151
- * @remarks
152
- * Only valid in the vertex shader. A vertex belongs to the skirt if it is on
153
- * the outermost ring of the tile grid (first/last column or row). The grid
154
- * resolution is derived from `segments`.
126
+ * Users who add custom compute stages create their own stage tasks using
127
+ * the accumulation pattern (`get()` predecessor, spread, append), then pass
128
+ * their leaf stage to this helper to get compile + execute tasks.
155
129
  *
156
- * @param segments - The number of inner segments in the terrain grid.
157
- * @returns A node resolving to a boolean indicating a skirt vertex.
158
- */
159
- declare const isSkirtVertex: three_src_nodes_TSL_js.ShaderNodeFn<[segments: number | Node$1]>;
160
- /**
161
- * Returns a node that is true for skirt UVs.
162
- *
163
- * @remarks
164
- * Uses interpolated UVs and the grid size
165
- * from `segments` to mark fragments outside the inner range
166
- * `(step, 1 - step)` on either axis as skirt, where `step = 1 / (segments + 2)`.
130
+ * @example
131
+ * ```ts
132
+ * const erosionStageTask = task((get, work) => {
133
+ * const upstream = get(elevationFieldStageTask);
134
+ * return work((): ComputePipeline => [
135
+ * ...upstream,
136
+ * (nodeIndex, globalVertexIndex, uv) => {
137
+ * // custom erosion logic
138
+ * },
139
+ * ]);
140
+ * });
167
141
  *
168
- * @param segments - The number of inner segments in the terrain grid.
169
- * @returns A node resolving to a boolean indicating a skirt fragment.
142
+ * const { compile, execute } = createComputePipelineTasks(erosionStageTask);
143
+ * ```
170
144
  */
171
- declare const isSkirtUV: three_src_nodes_TSL_js.ShaderNodeFn<[segments: number | Node$1]>;
145
+ declare function createComputePipelineTasks(leafStageTask: TaskRef<ComputePipeline>): {
146
+ compile: _hello_terrain_work.Task<{
147
+ execute: (renderer: WebGPURenderer, instanceCount: number) => void;
148
+ }, string, unknown>;
149
+ execute: _hello_terrain_work.Task<any, string, {
150
+ renderer: WebGPURenderer;
151
+ }>;
152
+ };
172
153
 
173
154
  declare const Dir: {
174
155
  readonly LEFT: 0;
@@ -182,7 +163,9 @@ type TileId = {
182
163
  /** 0 for flat terrain; 0..5 for cube-sphere faces */
183
164
  space: number;
184
165
  level: number;
166
+ /** tile coordinate at this level (signed to support infinite surfaces) */
185
167
  x: number;
168
+ /** tile coordinate at this level (signed to support infinite surfaces) */
186
169
  y: number;
187
170
  };
188
171
  type TileBounds = {
@@ -195,6 +178,8 @@ type TileBounds = {
195
178
  };
196
179
  type Surface = {
197
180
  spaceCount: number;
181
+ /** maximum number of roots returned by `rootTiles` */
182
+ maxRootCount: number;
198
183
  /**
199
184
  * Compute the same-level neighbor TileId in the requested direction.
200
185
  * Returns false if the neighbor is outside the valid topology.
@@ -211,6 +196,15 @@ type Surface = {
211
196
  y: number;
212
197
  z: number;
213
198
  }, out: TileBounds): void;
199
+ /**
200
+ * Fill root tiles for the current frame and return the count.
201
+ * Implementations should write level-0 tiles into `out[0..count)`.
202
+ */
203
+ rootTiles(cameraOrigin: {
204
+ x: number;
205
+ y: number;
206
+ z: number;
207
+ }, out: TileId[]): number;
214
208
  };
215
209
  type LeafSet = {
216
210
  /** maximum number of leaves that fit in the buffers */
@@ -219,8 +213,8 @@ type LeafSet = {
219
213
  count: number;
220
214
  space: Uint8Array;
221
215
  level: Uint8Array;
222
- x: Uint32Array;
223
- y: Uint32Array;
216
+ x: Int32Array;
217
+ y: Int32Array;
224
218
  };
225
219
  declare function allocLeafSet(capacity: number): LeafSet;
226
220
  declare function resetLeafSet(leaves: LeafSet): void;
@@ -278,8 +272,8 @@ type NodeStore = {
278
272
  gen: Uint16Array;
279
273
  space: Uint8Array;
280
274
  level: Uint8Array;
281
- x: Uint32Array;
282
- y: Uint32Array;
275
+ x: Int32Array;
276
+ y: Int32Array;
283
277
  /** sentinel U32_EMPTY means no children; otherwise children are [firstChild..firstChild+3] */
284
278
  firstChild: Uint32Array;
285
279
  flags: Uint8Array;
@@ -319,6 +313,9 @@ type QuadtreeState = {
319
313
  leafIndex: SpatialIndex;
320
314
  /** traversal scratch */
321
315
  stack: Uint32Array;
316
+ /** root nodes for this frame */
317
+ rootNodeIds: Uint32Array;
318
+ rootCount: number;
322
319
  /** split scheduling scratch (dedupe without allocations) */
323
320
  splitQueue: Uint32Array;
324
321
  splitStamp: Uint16Array;
@@ -327,11 +324,12 @@ type QuadtreeState = {
327
324
  scratchTile: TileId;
328
325
  scratchNeighbor: TileId;
329
326
  scratchBounds: TileBounds;
327
+ scratchRootTiles: TileId[];
330
328
  /** surface space count is fixed for a given state */
331
329
  spaceCount: number;
332
330
  };
333
331
  declare function createState(cfg: QuadtreeConfig, surface: Surface): QuadtreeState;
334
- declare function beginUpdate(state: QuadtreeState, surface: Surface): void;
332
+ declare function beginUpdate(state: QuadtreeState, surface: Surface, params: UpdateParams): void;
335
333
 
336
334
  /**
337
335
  * Update the quadtree for the given surface + camera parameters.
@@ -364,6 +362,20 @@ type FlatSurfaceConfig = {
364
362
  };
365
363
  declare function createFlatSurface(cfg: FlatSurfaceConfig): Surface;
366
364
 
365
+ type InfiniteFlatSurfaceConfig = {
366
+ rootSize: number;
367
+ origin: {
368
+ x: number;
369
+ y: number;
370
+ z: number;
371
+ };
372
+ /** optional conservative vertical extent, included in bounds radius */
373
+ maxHeight?: number;
374
+ /** half-width of root grid in root tiles (1 => 3x3 roots) */
375
+ rootGridRadius?: number;
376
+ };
377
+ declare function createInfiniteFlatSurface(cfg: InfiniteFlatSurfaceConfig): Surface;
378
+
367
379
  type CubeSphereSurfaceConfig = {
368
380
  radius: number;
369
381
  maxHeight?: number;
@@ -376,41 +388,12 @@ type CubeSphereSurfaceConfig = {
376
388
  */
377
389
  declare function createCubeSphereSurface(_cfg: CubeSphereSurfaceConfig): Surface;
378
390
 
379
- interface LeafStorageState {
380
- data: Int32Array<ArrayBuffer>;
381
- attribute: StorageBufferAttribute;
382
- node: StorageBufferNode;
383
- }
384
- declare const quadtreeConfigTask: _hello_terrain_work.Task<{
385
- state: QuadtreeState;
386
- surface: Surface;
387
- }, string, unknown>;
388
- declare const quadtreeUpdateTask: _hello_terrain_work.Task<LeafSet, string, unknown>;
389
- /**
390
- * Creates the GPU storage buffer objects. Recreated when maxNodes changes.
391
- *
392
- * terrainVertextPositionNodeTask depends on this (not leafGpuBufferTask) so
393
- * the shader is only rebuilt when the buffer is resized, not on every
394
- * quadtree update.
395
- */
396
- declare const leafStorageTask: _hello_terrain_work.Task<{
397
- data: Int32Array<ArrayBuffer>;
398
- attribute: StorageBufferAttribute;
399
- node: StorageBufferNode;
400
- }, string, unknown>;
401
- declare const leafGpuBufferTask: _hello_terrain_work.Task<{
402
- count: number;
403
- data: Int32Array<ArrayBuffer>;
404
- attribute: StorageBufferAttribute;
405
- node: StorageBufferNode;
406
- }, string, unknown>;
407
-
408
391
  interface TerrainUniformsParams {
409
392
  rootSize: number;
410
393
  rootOrigin: Vector3Like;
411
394
  innerTileSegments: number;
412
395
  skirtScale: number;
413
- heightmapScale: number;
396
+ elevationScale: number;
414
397
  instanceId: string;
415
398
  }
416
399
  interface TerrainUniformsContext {
@@ -418,56 +401,109 @@ interface TerrainUniformsContext {
418
401
  uRootSize: UniformNode<number>;
419
402
  uInnerTileSegments: UniformNode<number>;
420
403
  uSkirtScale: UniformNode<number>;
421
- uHeightmapScale: UniformNode<number>;
404
+ uElevationScale: UniformNode<number>;
405
+ }
406
+ interface LeafStorageState {
407
+ data: Int32Array<ArrayBuffer>;
408
+ attribute: StorageBufferAttribute;
409
+ node: StorageBufferNode;
422
410
  }
423
- /**
424
- * Factory function for instance-specific uniforms for a TerrainMesh.
425
- * Each TerrainMesh gets its own set of uniforms to avoid global state conflicts.
426
- */
427
- declare function createTerrainUniforms(params: TerrainUniformsParams): TerrainUniformsContext;
428
-
429
- declare function createTileWorldPosition(leafStorage: LeafStorageState, terrainUniforms: TerrainUniformsContext): three_src_nodes_TSL_js.ShaderCallNodeInternal;
430
-
431
- /** Generates a unique instance ID per graph (cached once). */
432
- declare const instanceIdTask: _hello_terrain_work.Task<`${string}-${string}-${string}-${string}-${string}`, string, unknown>;
433
411
 
434
- declare function terrainGraph(): _hello_terrain_work.Graph<string, unknown>;
435
- /** All terrain task refs for direct access. */
436
- declare const terrainTasks: {
437
- readonly instanceId: _hello_terrain_work.Task<`${string}-${string}-${string}-${string}-${string}`, string, unknown>;
438
- readonly quadtreeConfig: _hello_terrain_work.Task<{
439
- state: QuadtreeState;
440
- surface: Surface;
441
- }, string, unknown>;
442
- readonly quadtreeUpdate: _hello_terrain_work.Task<LeafSet, string, unknown>;
443
- readonly leafStorage: _hello_terrain_work.Task<{
444
- data: Int32Array<ArrayBuffer>;
445
- attribute: three_webgpu.StorageBufferAttribute;
446
- node: three_webgpu.StorageBufferNode;
447
- }, string, unknown>;
448
- readonly leafGpuBuffer: _hello_terrain_work.Task<{
449
- count: number;
450
- data: Int32Array<ArrayBuffer>;
451
- attribute: three_webgpu.StorageBufferAttribute;
452
- node: three_webgpu.StorageBufferNode;
453
- }, string, unknown>;
454
- readonly createUniforms: _hello_terrain_work.Task<TerrainUniformsContext, string, unknown>;
455
- readonly updateUniforms: _hello_terrain_work.Task<TerrainUniformsContext, string, unknown>;
456
- readonly positionNode: _hello_terrain_work.Task<three_src_nodes_TSL_js.ShaderCallNodeInternal, string, unknown>;
412
+ declare function createTileCompute(leafStorage: LeafStorageState, uniforms: TerrainUniformsContext): {
413
+ tileLevel: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node]>;
414
+ tileOriginVec2: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node]>;
415
+ tileSize: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node]>;
416
+ rootUVCompute: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node, number | Node, number | Node]>;
417
+ tileVertexWorldPositionCompute: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node, number | Node, number | Node]>;
457
418
  };
458
419
 
420
+ interface QuadtreeConfigState {
421
+ state: QuadtreeState;
422
+ surface: Surface;
423
+ }
424
+ interface LeafGpuBufferState extends LeafStorageState {
425
+ count: number;
426
+ }
427
+ interface ElevationFieldContext {
428
+ data: Float32Array<ArrayBuffer>;
429
+ attribute: StorageBufferAttribute;
430
+ node: StorageBufferNode;
431
+ }
432
+ interface NormalFieldContext {
433
+ data: Uint32Array<ArrayBuffer>;
434
+ attribute: StorageBufferAttribute;
435
+ node: StorageBufferNode;
436
+ }
459
437
  /** Task refs for the standard terrain pipeline. */
460
438
  interface TerrainTasks {
461
439
  instanceId: TaskRef<string>;
462
- quadtreeConfig: TaskRef<any>;
463
- quadtreeUpdate: TaskRef<any>;
440
+ quadtreeConfig: TaskRef<QuadtreeConfigState>;
441
+ quadtreeUpdate: TaskRef<LeafSet>;
442
+ surface: TaskRef<Surface>;
464
443
  leafStorage: TaskRef<LeafStorageState>;
465
- leafGpuBuffer: TaskRef<any>;
444
+ leafGpuBuffer: TaskRef<LeafGpuBufferState>;
466
445
  createUniforms: TaskRef<TerrainUniformsContext>;
467
446
  updateUniforms: TaskRef<TerrainUniformsContext>;
468
447
  positionNode: TaskRef<ShaderCallNodeInternal>;
448
+ createElevationFieldContext: TaskRef<ElevationFieldContext>;
449
+ createTileNodes: TaskRef<ReturnType<typeof createTileCompute>>;
450
+ createNormalFieldContext: TaskRef<NormalFieldContext>;
451
+ elevationFieldStage: TaskRef<ComputePipeline>;
452
+ normalFieldStage: TaskRef<ComputePipeline>;
453
+ compileCompute: TaskRef<{
454
+ execute: (renderer: WebGPURenderer, instanceCount: number) => void;
455
+ }>;
456
+ executeCompute: TaskRef<void | (() => void)>;
469
457
  }
470
458
 
459
+ declare const createElevationFieldContextTask: _hello_terrain_work.Task<{
460
+ data: Float32Array<ArrayBuffer>;
461
+ attribute: StorageBufferAttribute;
462
+ node: three_webgpu.StorageBufferNode;
463
+ }, string, unknown>;
464
+ declare const tileNodesTask: _hello_terrain_work.Task<{
465
+ tileLevel: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
466
+ tileOriginVec2: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
467
+ tileSize: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
468
+ rootUVCompute: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node, number | three_webgpu.Node, number | three_webgpu.Node]>;
469
+ tileVertexWorldPositionCompute: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node, number | three_webgpu.Node, number | three_webgpu.Node]>;
470
+ }, string, unknown>;
471
+ /**
472
+ * Root compute stage — generates elevation data and writes to the
473
+ * elevation field storage buffer. Returns a single-element `ComputePipeline`.
474
+ */
475
+ declare const elevationFieldStageTask: _hello_terrain_work.Task<ComputePipeline, string, unknown>;
476
+
477
+ /** Generates a unique instance ID per graph (cached once). */
478
+ declare const instanceIdTask: _hello_terrain_work.Task<`${string}-${string}-${string}-${string}-${string}`, string, unknown>;
479
+
480
+ declare const createNormalFieldContextTask: _hello_terrain_work.Task<{
481
+ data: Uint32Array<ArrayBuffer>;
482
+ attribute: StorageBufferAttribute;
483
+ node: three_webgpu.StorageBufferNode;
484
+ }, string, unknown>;
485
+ /**
486
+ * Normal field compute stage — reads height neighbors from the elevation field
487
+ * buffer, computes surface normals via central differences, packs XZ
488
+ * components into a u32 via `packHalf2x16`, and writes to the normal field
489
+ * storage buffer.
490
+ *
491
+ * Accumulates the upstream elevation pipeline via `get(elevationFieldStageTask)`.
492
+ */
493
+ declare const normalFieldStageTask: _hello_terrain_work.Task<ComputePipeline, string, unknown>;
494
+
495
+ interface ElevationParams {
496
+ worldPosition: Node$1;
497
+ rootSize: Node$1;
498
+ rootUV: Node$1;
499
+ tileUV: Node$1;
500
+ tileLevel: Node$1;
501
+ tileSize: Node$1;
502
+ tileOriginVec2: Node$1;
503
+ nodeIndex: Node$1;
504
+ }
505
+ type ElevationCallback = (params: ElevationParams) => Node$1;
506
+
471
507
  /** Root tile size in world units. */
472
508
  declare const rootSize: _hello_terrain_work.ParamRef<number>;
473
509
  /** World-space origin of the terrain. */
@@ -476,29 +512,71 @@ declare const origin: _hello_terrain_work.ParamRef<{
476
512
  y: number;
477
513
  z: number;
478
514
  }>;
479
- /** Number of segments per inner tile edge. */
515
+ /**
516
+ * Number of segments per inner tile edge.
517
+ * 13 is the max tiles we can support for 256 workgroups (13 + 3 === 16.. 16x16)
518
+ */
480
519
  declare const innerTileSegments: _hello_terrain_work.ParamRef<number>;
481
520
  /** Skirt scale factor. */
482
521
  declare const skirtScale: _hello_terrain_work.ParamRef<number>;
483
- /** Heightmap vertical scale. */
484
- declare const heightmapScale: _hello_terrain_work.ParamRef<number>;
522
+ /** Elevation vertical scale. */
523
+ declare const elevationScale: _hello_terrain_work.ParamRef<number>;
485
524
  /** Maximum quadtree nodes. */
486
525
  declare const maxNodes: _hello_terrain_work.ParamRef<number>;
487
526
  /** Maximum quadtree subdivision level. */
488
527
  declare const maxLevel: _hello_terrain_work.ParamRef<number>;
489
528
  /** Quadtree update configuration (camera, mode, etc.). */
490
529
  declare const quadtreeUpdate: _hello_terrain_work.ParamRef<UpdateParams>;
530
+ /** Optional custom terrain surface; defaults to bounded flat surface when null. */
531
+ declare const surface: _hello_terrain_work.ParamRef<Surface | null>;
532
+ /** Terrain elevation control function (per vertex, in gpu compute) */
533
+ declare const elevationFn: _hello_terrain_work.ParamRef<ElevationCallback>;
491
534
 
492
535
  /**
493
536
  * Builds the TSL position node for the terrain shader.
494
537
  *
495
- * Depends on leafStorageTask (buffer objects) and createUniformsTask
496
- * (uniform nodes). Both only change when their GPU resources are recreated
538
+ * Depends on leafStorageTask (buffer objects), createUniformsTask
539
+ * (uniform nodes), createElevationFieldContextTask (elevation field storage),
540
+ * and createNormalFieldContextTask (normal field storage).
541
+ *
542
+ * The position node also reads normals from the normal field buffer
543
+ * per-vertex (using vertexIndex) and assigns them to the vNormal
544
+ * varying for use in the fragment shader.
545
+ *
546
+ * These only change when their GPU resources are recreated
497
547
  * (e.g. buffer resize), so this task stays cached during normal quadtree
498
548
  * updates — no unnecessary shader rebuilds.
499
549
  */
500
550
  declare const positionNodeTask: _hello_terrain_work.Task<three_src_nodes_TSL_js.ShaderCallNodeInternal, string, unknown>;
501
551
 
552
+ /**
553
+ * Derives the terrain surface from `rootSize` and `origin`.
554
+ * Automatically recomputes when either param changes, keeping the
555
+ * quadtree refinement in sync with the GPU-side tile positioning.
556
+ */
557
+ declare const surfaceTask: _hello_terrain_work.Task<Surface, string, unknown>;
558
+ declare const quadtreeConfigTask: _hello_terrain_work.Task<{
559
+ state: QuadtreeState;
560
+ surface: Surface;
561
+ }, string, unknown>;
562
+ declare const quadtreeUpdateTask: _hello_terrain_work.Task<LeafSet, string, unknown>;
563
+ /**
564
+ * Creates the GPU storage buffer objects. Recreated when maxNodes changes.
565
+ *
566
+ * positionNodeTask depends on this (not leafGpuBufferTask) so
567
+ * the shader is only rebuilt when the buffer is resized, not on every
568
+ * quadtree update.
569
+ */
570
+ declare const leafStorageTask: _hello_terrain_work.Task<LeafStorageState, string, unknown>;
571
+ declare const leafGpuBufferTask: _hello_terrain_work.Task<{
572
+ count: number;
573
+ data: Int32Array<ArrayBuffer>;
574
+ attribute: three_webgpu.StorageBufferAttribute;
575
+ node: three_webgpu.StorageBufferNode;
576
+ }, string, unknown>;
577
+
578
+ declare function createTerrainUniforms(params: TerrainUniformsParams): TerrainUniformsContext;
579
+
502
580
  /**
503
581
  * Creates the terrain uniform nodes once. Downstream tasks capture
504
582
  * references to these nodes in shader graphs, so the same instances
@@ -511,5 +589,126 @@ declare const createUniformsTask: _hello_terrain_work.Task<TerrainUniformsContex
511
589
  */
512
590
  declare const updateUniformsTask: _hello_terrain_work.Task<TerrainUniformsContext, string, unknown>;
513
591
 
514
- export { Dir, TerrainGeometry, TerrainMesh, U32_EMPTY, allocLeafSet, allocSeamTable, beginUpdate, blendAngleCorrectedNormals, buildLeafIndex, buildSeams2to1, createCubeSphereSurface, createFlatSurface, createSpatialIndex, createState, createTerrainUniforms, createTileWorldPosition, createUniformsTask, deriveNormalZ, heightmapScale, innerTileSegments, instanceIdTask, isSkirtUV, isSkirtVertex, leafGpuBufferTask, leafStorageTask, maxLevel, maxNodes, origin, positionNodeTask, quadtreeConfigTask, quadtreeUpdate, quadtreeUpdateTask, resetLeafSet, resetSeamTable, rootSize, skirtScale, terrainGraph, terrainTasks, textureSpaceToVectorSpace, update, updateUniformsTask, vectorSpaceToTextureSpace };
515
- export type { CubeSphereSurfaceConfig, FlatSurfaceConfig, IntNodeInput, LeafSet, LeafStorageState, LodMode, QuadtreeConfig, QuadtreeState, SeamTable, SpatialIndex, Surface, TerrainTasks, TerrainUniformsContext, TerrainUniformsParams, TileBounds, TileId, UpdateParams };
592
+ declare function terrainGraph(): _hello_terrain_work.Graph<string, {
593
+ renderer: WebGPURenderer;
594
+ }>;
595
+ /** All terrain task refs for direct access. */
596
+ declare const terrainTasks: {
597
+ readonly instanceId: _hello_terrain_work.Task<`${string}-${string}-${string}-${string}-${string}`, string, unknown>;
598
+ readonly quadtreeConfig: _hello_terrain_work.Task<{
599
+ state: QuadtreeState;
600
+ surface: Surface;
601
+ }, string, unknown>;
602
+ readonly quadtreeUpdate: _hello_terrain_work.Task<LeafSet, string, unknown>;
603
+ readonly leafStorage: _hello_terrain_work.Task<LeafStorageState, string, unknown>;
604
+ readonly surface: _hello_terrain_work.Task<Surface, string, unknown>;
605
+ readonly leafGpuBuffer: _hello_terrain_work.Task<{
606
+ count: number;
607
+ data: Int32Array<ArrayBuffer>;
608
+ attribute: three_webgpu.StorageBufferAttribute;
609
+ node: three_webgpu.StorageBufferNode;
610
+ }, string, unknown>;
611
+ readonly createUniforms: _hello_terrain_work.Task<TerrainUniformsContext, string, unknown>;
612
+ readonly updateUniforms: _hello_terrain_work.Task<TerrainUniformsContext, string, unknown>;
613
+ readonly positionNode: _hello_terrain_work.Task<three_src_nodes_TSL_js.ShaderCallNodeInternal, string, unknown>;
614
+ readonly createElevationFieldContext: _hello_terrain_work.Task<{
615
+ data: Float32Array<ArrayBuffer>;
616
+ attribute: three_webgpu.StorageBufferAttribute;
617
+ node: three_webgpu.StorageBufferNode;
618
+ }, string, unknown>;
619
+ readonly createTileNodes: _hello_terrain_work.Task<{
620
+ tileLevel: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
621
+ tileOriginVec2: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
622
+ tileSize: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
623
+ rootUVCompute: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node, number | three_webgpu.Node, number | three_webgpu.Node]>;
624
+ tileVertexWorldPositionCompute: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node, number | three_webgpu.Node, number | three_webgpu.Node]>;
625
+ }, string, unknown>;
626
+ readonly createNormalFieldContext: _hello_terrain_work.Task<{
627
+ data: Uint32Array<ArrayBuffer>;
628
+ attribute: three_webgpu.StorageBufferAttribute;
629
+ node: three_webgpu.StorageBufferNode;
630
+ }, string, unknown>;
631
+ readonly elevationFieldStage: _hello_terrain_work.Task<ComputePipeline, string, unknown>;
632
+ readonly normalFieldStage: _hello_terrain_work.Task<ComputePipeline, string, unknown>;
633
+ readonly compileCompute: _hello_terrain_work.Task<{
634
+ execute: (renderer: WebGPURenderer, instanceCount: number) => void;
635
+ }, string, unknown>;
636
+ readonly executeCompute: _hello_terrain_work.Task<any, string, {
637
+ renderer: WebGPURenderer;
638
+ }>;
639
+ };
640
+
641
+ /**
642
+ * Maps a value or node from texture space [0, 1] to vector space [-1, 1].
643
+ *
644
+ * @param value - The node or value in the range [0, 1].
645
+ * @returns A node mapping the input value to the range [-1, 1].
646
+ */
647
+ declare const textureSpaceToVectorSpace: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node$1]>;
648
+ /**
649
+ * Maps a value or node from vector space [-1, 1] to texture space [0, 1].
650
+ *
651
+ * @param value - The node or value in the range [-1, 1].
652
+ * @returns A node mapping the input value to the range [0, 1].
653
+ */
654
+ declare const vectorSpaceToTextureSpace: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node$1]>;
655
+ /**
656
+ * Blends two normal maps using the Reoriented Normal Mapping technique.
657
+ * This is the same algorithm used by Unreal Engine's BlendAngleCorrectedNormals node.
658
+ *
659
+ * Both inputs should be in vector space [-1, 1].
660
+ *
661
+ * @see https://blog.selfshadow.com/publications/blending-in-detail/
662
+ */
663
+ declare const blendAngleCorrectedNormals: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node$1, number | Node$1]>;
664
+ /**
665
+ * Reconstructs the Z component of a normal from the X and Y components.
666
+ *
667
+ * @param normalXY - A vec2 containing the X and Y components of the normal
668
+ * @returns A vec3 with the reconstructed normal (X, Y, derived Z)
669
+ */
670
+ declare const deriveNormalZ: three_src_nodes_TSL_js.ShaderNodeFn<[number | Node$1]>;
671
+
672
+ /**
673
+ * Input type for segment count: either a JS number or a TSL integer node.
674
+ * When a number is provided, it's automatically converted to an int node.
675
+ * When a Node is provided, it should resolve to an integer value.
676
+ */
677
+ type IntNodeInput = number | ConstNode<number> | Node;
678
+ /**
679
+ * Returns a node that is true for skirt vertices in the vertex stage.
680
+ *
681
+ * @remarks
682
+ * Only valid in the vertex shader. A vertex belongs to the skirt if it is on
683
+ * the outermost ring of the tile grid (first/last column or row). The grid
684
+ * resolution is derived from `segments`.
685
+ *
686
+ * @param segments - The number of inner segments in the terrain grid.
687
+ * @returns A node resolving to a boolean indicating a skirt vertex.
688
+ */
689
+ declare const isSkirtVertex: three_src_nodes_TSL_js.ShaderNodeFn<[segments: number | Node]>;
690
+ /**
691
+ * Returns a node that is true for skirt UVs.
692
+ *
693
+ * @remarks
694
+ * Uses interpolated UVs and the grid size
695
+ * from `segments` to mark fragments outside the inner range
696
+ * `(step, 1 - step)` on either axis as skirt, where `step = 1 / (segments + 2)`.
697
+ *
698
+ * @param segments - The number of inner segments in the terrain grid.
699
+ * @returns A node resolving to a boolean indicating a skirt fragment.
700
+ */
701
+ declare const isSkirtUV: three_src_nodes_TSL_js.ShaderNodeFn<[segments: number | Node]>;
702
+
703
+ declare const vGlobalVertexIndex: three_webgpu.PropertyNode;
704
+ declare const vElevation: three_webgpu.PropertyNode;
705
+
706
+ declare const voronoiCells: three_src_nodes_TSL_js.ShaderNodeFn<[three_tsl.ProxiedObject<{
707
+ scale: number;
708
+ facet: number;
709
+ seed: number;
710
+ uv: Node;
711
+ }>]>;
712
+
713
+ export { Dir, TerrainGeometry, TerrainMesh, U32_EMPTY, allocLeafSet, allocSeamTable, beginUpdate, blendAngleCorrectedNormals, buildLeafIndex, buildSeams2to1, compileComputeTask, createComputePipelineTasks, createCubeSphereSurface, createElevationFieldContextTask, createFlatSurface, createInfiniteFlatSurface, createNormalFieldContextTask, createSpatialIndex, createState, createTerrainUniforms, createUniformsTask, deriveNormalZ, elevationFieldStageTask, elevationFn, elevationScale, executeComputeTask, innerTileSegments, instanceIdTask, isSkirtUV, isSkirtVertex, leafGpuBufferTask, leafStorageTask, maxLevel, maxNodes, normalFieldStageTask, origin, positionNodeTask, quadtreeConfigTask, quadtreeUpdate, quadtreeUpdateTask, resetLeafSet, resetSeamTable, rootSize, skirtScale, surface, surfaceTask, terrainGraph, terrainTasks, textureSpaceToVectorSpace, tileNodesTask, update, updateUniformsTask, vElevation, vGlobalVertexIndex, vectorSpaceToTextureSpace, voronoiCells };
714
+ export type { ComputePipeline, ComputeStageCallback, CubeSphereSurfaceConfig, ElevationCallback, ElevationFieldContext, ElevationParams, FlatSurfaceConfig, InfiniteFlatSurfaceConfig, IntNodeInput, LeafGpuBufferState, LeafSet, LeafStorageState, LodMode, NormalFieldContext, QuadtreeConfig, QuadtreeConfigState, QuadtreeState, SeamTable, SpatialIndex, Surface, TerrainTasks, TerrainUniformsContext, TerrainUniformsParams, TileBounds, TileId, UpdateParams };