@genex-ai/cli-demo 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/index.js +5 -0
  2. package/package.json +1 -1
  3. package/templates/skills/genex-threejs-atmosphere-aerial-perspective/SKILL.md +30 -18
  4. package/templates/skills/genex-threejs-atmosphere-aerial-perspective/references/atmosphere.md +204 -20
  5. package/templates/skills/genex-threejs-bloom/SKILL.md +29 -18
  6. package/templates/skills/genex-threejs-bloom/references/bloom.md +176 -20
  7. package/templates/skills/genex-threejs-camera-direction/SKILL.md +38 -26
  8. package/templates/skills/genex-threejs-camera-direction/references/camera-rigs.md +359 -27
  9. package/templates/skills/genex-threejs-exposure-color-grading/SKILL.md +27 -18
  10. package/templates/skills/genex-threejs-exposure-color-grading/references/exposure-grading.md +196 -21
  11. package/templates/skills/genex-threejs-image-pipeline/SKILL.md +38 -17
  12. package/templates/skills/genex-threejs-image-pipeline/references/image-pipeline.md +185 -29
  13. package/templates/skills/genex-threejs-procedural-animation/SKILL.md +34 -21
  14. package/templates/skills/genex-threejs-procedural-animation/references/procedural-motion.md +353 -24
  15. package/templates/skills/genex-threejs-procedural-architecture/SKILL.md +36 -17
  16. package/templates/skills/genex-threejs-procedural-architecture/references/architecture-systems.md +500 -22
  17. package/templates/skills/genex-threejs-procedural-fields/SKILL.md +59 -24
  18. package/templates/skills/genex-threejs-procedural-fields/references/field-systems.md +222 -25
  19. package/templates/skills/genex-threejs-procedural-geometry/SKILL.md +34 -20
  20. package/templates/skills/genex-threejs-procedural-geometry/references/mesh-systems.md +192 -26
  21. package/templates/skills/genex-threejs-procedural-materials/SKILL.md +55 -18
  22. package/templates/skills/genex-threejs-procedural-materials/references/material-systems.md +189 -22
  23. package/templates/skills/genex-threejs-procedural-planets/SKILL.md +36 -18
  24. package/templates/skills/genex-threejs-procedural-planets/references/planet-systems.md +489 -21
  25. package/templates/skills/genex-threejs-procedural-vegetation/SKILL.md +35 -25
  26. package/templates/skills/genex-threejs-procedural-vegetation/references/vegetation-systems.md +304 -27
  27. package/templates/skills/genex-threejs-procedural-vfx/SKILL.md +26 -18
  28. package/templates/skills/genex-threejs-procedural-vfx/references/vfx-systems.md +208 -20
  29. package/templates/skills/genex-threejs-raymarched-space-effects/SKILL.md +25 -18
  30. package/templates/skills/genex-threejs-raymarched-space-effects/references/space-effects.md +185 -21
  31. package/templates/skills/genex-threejs-screen-space-ambient-occlusion/SKILL.md +23 -17
  32. package/templates/skills/genex-threejs-screen-space-ambient-occlusion/references/ambient-occlusion.md +430 -20
  33. package/templates/skills/genex-threejs-shadow-systems/SKILL.md +29 -18
  34. package/templates/skills/genex-threejs-shadow-systems/references/shadow-systems.md +420 -21
  35. package/templates/skills/genex-threejs-skill-router/SKILL.md +21 -21
  36. package/templates/skills/genex-threejs-spectral-ocean/SKILL.md +30 -20
  37. package/templates/skills/genex-threejs-spectral-ocean/references/spectral-ocean.md +462 -22
  38. package/templates/skills/genex-threejs-temporal-surfaces/SKILL.md +26 -17
  39. package/templates/skills/genex-threejs-temporal-surfaces/references/temporal-surfaces.md +198 -20
  40. package/templates/skills/genex-threejs-visual-validation/SKILL.md +34 -18
  41. package/templates/skills/genex-threejs-visual-validation/references/visual-validation.md +396 -32
  42. package/templates/skills/genex-threejs-volumetric-clouds/SKILL.md +33 -17
  43. package/templates/skills/genex-threejs-volumetric-clouds/references/volumetric-clouds.md +570 -21
  44. package/templates/skills/genex-threejs-water-optics/SKILL.md +33 -18
  45. package/templates/skills/genex-threejs-water-optics/references/water-optics.md +184 -20
@@ -1,29 +1,439 @@
1
- # Ambient Occlusion
1
+ # GTAO and bent-normal pipeline
2
2
 
3
- Use this reference for screen-space contact grounding.
3
+ Use this reference for a bounded-cost WebGPU/TSL ambient-visibility pass with half-resolution horizon integration, bent normals, bilateral reconstruction, and directional ambient tint.
4
4
 
5
- ## Inputs
5
+ ## Contents
6
6
 
7
- - Depth with known projection convention.
8
- - Normals in a documented space.
9
- - Camera near/far and projection matrix.
10
- - Optional velocity or history for temporal filtering.
7
+ 1. Gather budget and depth convention
8
+ 2. World-radius projection and horizon integration
9
+ 3. Bent-normal encoding
10
+ 4. Bilateral reconstruction
11
+ 5. Indirect-light composite
12
+ 6. Implementation defects, adaptation, and diagnostics
11
13
 
12
- ## Sampling
14
+ ## 1. Preserve the actual budget
13
15
 
14
- - Use a stable noise pattern or rotated kernel.
15
- - Tie radius to world or view-space units.
16
- - Reduce samples for low quality tiers.
17
- - Keep thin geometry and silhouette cases visible in debug.
16
+ The gather uses:
18
17
 
19
- ## Filtering
18
+ ```text
19
+ resolution scale 0.5 × 0.5
20
+ slices 2
21
+ steps per side 4
22
+ sides per slice 2
23
+ depth taps 16 per half-resolution pixel
24
+ target RGBA16F
25
+ RGB bent direction encoded to [0, 1]
26
+ A scalar visibility, 1 = open
27
+ ```
20
28
 
21
- - Use bilateral filtering against depth and normal discontinuities.
22
- - Upsample from half resolution carefully.
23
- - Avoid bleeding occlusion across foreground/background edges.
29
+ Half linear resolution means one quarter of full-resolution fragments.
24
30
 
25
- ## Applying AO
31
+ The implementation targets an approximately `2 ms` budget by combining:
26
32
 
27
- - Apply to indirect or ambient contribution, not direct sunlight.
28
- - Keep strength subtle enough that materials still read.
29
- - Provide a no-AO baseline for comparison.
33
+ - half-resolution gather;
34
+ - few slices;
35
+ - interleaved-gradient-noise rotation;
36
+ - direct UV marching;
37
+ - one view-position reconstruction per tap;
38
+ - sky early-outs in gather and composite.
39
+
40
+ Do not increase slices first. Validate whether the bilateral pass and stable
41
+ rotation already remove directional structure.
42
+
43
+ ## 2. Preserve the depth convention
44
+
45
+ The implementation uses reversed depth:
46
+
47
+ ```text
48
+ sky threshold 0.000001
49
+ maximum reconstruction 0.999999
50
+ ```
51
+
52
+ Sky is cleared to zero. Far terrain remains above the sky threshold.
53
+
54
+ Gather:
55
+
56
+ ```text
57
+ if rawDepth <= 1e-6:
58
+ output visibility = 1
59
+ output encoded bent = encoded view normal
60
+ skip all 16 taps
61
+ ```
62
+
63
+ Composite clamps depth to `[0, 0.999999]` before linearization so sky
64
+ neighbours do not create extreme view-Z values.
65
+
66
+ Do not port these thresholds to a forward-depth target unchanged.
67
+
68
+ ## 3. Preserve world-radius projection
69
+
70
+ Default controls:
71
+
72
+ ```text
73
+ radius 0.5 m
74
+ intensity 1.0
75
+ power 1.6
76
+ thickness 0.35 m in view Z
77
+ bentNormalStrength 0.6
78
+ ```
79
+
80
+ The horizontal projection scale is cached from:
81
+
82
+ ```text
83
+ camera.projectionMatrix.elements[0]
84
+ ```
85
+
86
+ and refreshed every frame.
87
+
88
+ World radius becomes UV reach:
89
+
90
+ ```text
91
+ radiusUv =
92
+ radius
93
+ * projectionScaleX
94
+ / max(-viewPosition.z, 0.0001)
95
+ * 0.5
96
+
97
+ radiusUv = clamp(radiusUv, 0.004, 0.08)
98
+ ```
99
+
100
+ This clamp prevents near surfaces searching half the screen and stops far
101
+ surfaces collapsing to a useless footprint.
102
+
103
+ Observed adaptation issue: only the X projection term is used, then one scalar
104
+ radius is applied to both UV axes. At unusual aspect ratios or asymmetric
105
+ projections, derive a `vec2` reach from both projection axes.
106
+
107
+ ## 4. Rotate two horizon slices per pixel
108
+
109
+ For slice `i`:
110
+
111
+ ```text
112
+ noise = interleavedGradientNoise(screenCoordinate)
113
+ angle = (i / 2 + noise) * PI
114
+ sliceDirection = (cos(angle), sin(angle))
115
+ ```
116
+
117
+ The axis covers both positive and negative directions, so angles only span
118
+ `PI`, not `2 * PI`.
119
+
120
+ Step spacing:
121
+
122
+ ```text
123
+ t = (stepIndex + noise + 0.5) / 4
124
+ stepUv = sliceDirection * radiusUv * t
125
+ ```
126
+
127
+ The shared noise rotates slices and jitters their radial positions.
128
+
129
+ The pass has no temporal accumulation. Its stability depends on the
130
+ noise being screen-stable and the full-resolution spatial composite.
131
+
132
+ ## 5. Keep horizon angle and distance falloff separate
133
+
134
+ For each positive and negative sample:
135
+
136
+ ```text
137
+ delta = sampleViewPosition - centerViewPosition
138
+ distance = max(length(delta), 0.0001)
139
+ falloff = saturate(1 - distance / max(radius, 0.0001))
140
+ ```
141
+
142
+ Accept the sample only when:
143
+
144
+ ```text
145
+ abs(delta.z) < thickness
146
+ ```
147
+
148
+ Raw horizon cosine:
149
+
150
+ ```text
151
+ cosine = dot(delta, viewDirection) / distance
152
+ ```
153
+
154
+ Apply distance falloff by mixing toward fully open:
155
+
156
+ ```text
157
+ horizon = mix(-1, cosine, falloff)
158
+ maxHorizon = max(maxHorizon, horizon)
159
+ ```
160
+
161
+ Do not multiply the cosine directly by falloff. Mixing toward `-1` weakens a
162
+ distant occluder without changing the angle of a nearby one.
163
+
164
+ Per slice:
165
+
166
+ ```text
167
+ positiveAngle = acos(clamp(positiveHorizon, -1, 1))
168
+ negativeAngle = acos(clamp(negativeHorizon, -1, 1))
169
+ visibility += saturate((positiveAngle + negativeAngle) / PI)
170
+ ```
171
+
172
+ Final scalar:
173
+
174
+ ```text
175
+ visibility = visibility / 2
176
+ visibility = visibility ^ power
177
+ visibility = saturate(mix(1, visibility, intensity))
178
+ ```
179
+
180
+ Disabling the pass sets intensity to zero; the gather still runs unless the
181
+ owner removes or bypasses the node. If disabled cost matters, bypass the pass
182
+ at pipeline construction or add an update/render gate.
183
+
184
+ ## 6. Treat the bent direction as an observed heuristic
185
+
186
+ For accepted samples, the gather accumulates:
187
+
188
+ ```text
189
+ bentDirection +=
190
+ normalize(delta)
191
+ * saturate(cosine * falloff)
192
+ ```
193
+
194
+ Then:
195
+
196
+ ```text
197
+ bent = normalize(
198
+ mix(
199
+ viewNormal,
200
+ normalize(viewDirection + bentDirection),
201
+ bentNormalStrength
202
+ )
203
+ )
204
+ ```
205
+
206
+ The output stores `bent * 0.5 + 0.5`.
207
+
208
+ Important objective finding: the accumulated vectors point toward accepted
209
+ sample positions. A physically derived bent normal normally points toward
210
+ unoccluded directions, so do not assume this sign convention is correct in an
211
+ adaptation.
212
+
213
+ Required validation:
214
+
215
+ ```text
216
+ place a flat receiver beside one vertical wall
217
+ show geometric normal
218
+ show decoded bent direction
219
+ show environment sample direction
220
+ verify the direction turns away from the blocked hemisphere
221
+ ```
222
+
223
+ If it turns toward the wall, negate/rederive the directional accumulator
224
+ before using it for environment lighting.
225
+
226
+ ## 7. Own gather rendering state
227
+
228
+ `GtaoNode.updateBefore()`:
229
+
230
+ 1. saves/reset renderer state through `RendererUtils`;
231
+ 2. reads drawing-buffer dimensions;
232
+ 3. resizes the half-resolution target;
233
+ 4. refreshes projection scale;
234
+ 5. renders one fullscreen `QuadMesh`;
235
+ 6. restores renderer state.
236
+
237
+ Dispose both the target and node material.
238
+
239
+ Do not let a post node leak render target, viewport, or material state into the
240
+ main pipeline.
241
+
242
+ ## 8. Upsample with the exact kernel
243
+
244
+ The full-resolution composite gathers eight neighbours:
245
+
246
+ ```text
247
+ left, right, up, down
248
+ four diagonals
249
+ center omitted
250
+ ```
251
+
252
+ Each weight is depth-only:
253
+
254
+ ```text
255
+ weight = exp(-abs(sampleViewZ - centerViewZ) / 0.5)
256
+ ```
257
+
258
+ If total weight is above `0.01`, normalize the eight-sample sum. Otherwise use
259
+ the center AO texel.
260
+
261
+ This is an eight-neighbour `3×3` ring with the center skipped, not a cross.
262
+
263
+ The rationale is to cover the four-pixel interleaved-gradient-noise repeat
264
+ while sampling across half-resolution AO texels.
265
+
266
+ Observed limitation: `screenTexelHint()` returns only:
267
+
268
+ ```text
269
+ 1 / screenWidth
270
+ ```
271
+
272
+ and uses that scalar for both X and Y offsets. At non-square viewports the
273
+ vertical step is wrong. Adapt as:
274
+
275
+ ```text
276
+ texel = vec2(1 / width, 1 / height)
277
+ ```
278
+
279
+ Observed limitation: the filter has no normal-similarity weight despite having
280
+ the normal buffer available later in the composite. Thin foreground/background
281
+ contacts may need:
282
+
283
+ ```text
284
+ weight *= pow(saturate(dot(centerNormal, sampleNormal)), normalPower)
285
+ ```
286
+
287
+ Add this only after confirming the depth-only kernel causes cross-edge leakage;
288
+ normal buffers can be noisy at hard edges.
289
+
290
+ ## 9. Apply AO only to reconstructed indirect light
291
+
292
+ Do not multiply final scene color by AO.
293
+
294
+ It approximates indirect light:
295
+
296
+ ```text
297
+ irradiance =
298
+ PMREM sampled along bent direction at texture level 1
299
+ or fallback cavity color (0.55, 0.62, 0.78)
300
+
301
+ indirectEstimate =
302
+ albedo
303
+ * environmentIntensity
304
+ * irradiance
305
+
306
+ indirect = min(indirectEstimate, sceneColor)
307
+ direct = sceneColor - indirect
308
+ ```
309
+
310
+ The clamp ensures direct light never becomes negative.
311
+
312
+ Then:
313
+
314
+ ```text
315
+ occludedIndirect = indirect * visibility
316
+
317
+ deviation =
318
+ saturate(1 - dot(decodedBentView, geometricViewNormal))
319
+
320
+ tintAmount =
321
+ deviation
322
+ * (1 - visibility)
323
+ * bentTintStrength
324
+
325
+ bentTintStrength default = 0.35
326
+
327
+ tintedIndirect =
328
+ mix(
329
+ occludedIndirect,
330
+ occludedIndirect * irradiance,
331
+ saturate(tintAmount)
332
+ )
333
+
334
+ output = direct + tintedIndirect
335
+ ```
336
+
337
+ This keeps direct sun and most specular response out of the AO multiply.
338
+
339
+ The indirect reconstruction is still approximate because it works from a
340
+ forward-shaded scene color and an albedo MRT. Specular energy can leak into
341
+ the `direct` residual. Prefer a renderer-provided indirect-diffuse signal when
342
+ available.
343
+
344
+ ## 10. Verify view/world transform semantics
345
+
346
+ The composite decodes the bent direction in view space and calls:
347
+
348
+ ```text
349
+ transformDirection(bentView, cameraViewMatrix)
350
+ ```
351
+
352
+ while describing the result as view-to-world.
353
+
354
+ Matrix-direction semantics in TSL are version-sensitive. Verify the installed
355
+ Three.js behavior with axis probes:
356
+
357
+ ```text
358
+ camera facing -Z:
359
+ view (0, 0, 1) maps to expected world direction
360
+
361
+ camera rotated 90 degrees:
362
+ decoded bent direction rotates with the camera exactly once
363
+ ```
364
+
365
+ Do not copy the matrix expression solely from the comment.
366
+
367
+ ## 11. Temporal behavior
368
+
369
+ This pipeline has no motion vectors, history target, reprojection,
370
+ neighborhood clamp, or disocclusion rejection.
371
+
372
+ Do not describe it as temporally accumulated GTAO.
373
+
374
+ If adding temporal accumulation:
375
+
376
+ 1. preserve raw half-resolution visibility and bent direction;
377
+ 2. add representative depth/normal validity;
378
+ 3. reproject with velocity;
379
+ 4. clamp scalar visibility to the current neighborhood;
380
+ 5. constrain bent history by angular deviation;
381
+ 6. reset on camera cuts and resolution changes.
382
+
383
+ First verify whether the current stable-noise plus bilateral pass already meets
384
+ the target. Temporal history adds ghosting risk to moving procedural geometry.
385
+
386
+ ## 12. Required diagnostics
387
+
388
+ Expose:
389
+
390
+ ```text
391
+ raw reversed depth and linear view Z
392
+ sky classification
393
+ view normal
394
+ projected radius UV/pixels
395
+ slice angle and jitter
396
+ positive/negative horizon cosine
397
+ thickness acceptance
398
+ distance falloff
399
+ visibility before power/intensity
400
+ raw encoded and decoded bent direction
401
+ one-sided-wall bent-direction test
402
+ eight bilateral sample depths and weights
403
+ X/Y texel offsets
404
+ upsampled visibility
405
+ albedo and environment irradiance
406
+ indirect estimate before/after scene-color clamp
407
+ direct residual
408
+ tint deviation and amount
409
+ final direct versus indirect contribution
410
+ GPU time for gather and composite
411
+ ```
412
+
413
+ Failure diagnosis:
414
+
415
+ ```text
416
+ AO radius changes with distance incorrectly:
417
+ world radius was replaced by a fixed pixel radius
418
+
419
+ far surfaces lose all contact:
420
+ projected radius was not clamped to a minimum
421
+
422
+ thick silhouette halos:
423
+ thickness or depth-only bilateral weights cross discontinuities
424
+
425
+ vertical blur differs from horizontal blur:
426
+ width-derived scalar texel size was used for Y
427
+
428
+ bent tint points into walls:
429
+ the observed accumulator sign was accepted without a one-sided-wall test
430
+
431
+ sunlit surfaces become gray:
432
+ visibility multiplied final scene color instead of reconstructed indirect
433
+
434
+ disabled AO still costs the full pass:
435
+ intensity was set to zero without bypassing gather rendering
436
+
437
+ camera rotation changes tint incorrectly:
438
+ view-to-world direction transform semantics were not verified
439
+ ```
@@ -5,26 +5,37 @@ description: Implement stable shadow systems for Genex Three.js games. Use for l
5
5
 
6
6
  # Genex Three.js Shadow Systems
7
7
 
8
- Shadows ground gameplay and explain scale. They need stability more than maximum
9
- resolution everywhere.
8
+ Use a single shadow map only when its receiver region is genuinely bounded. For large moving views, make shadow coverage an explicit spatial hierarchy.
10
9
 
11
- Read [references/shadow-systems.md](references/shadow-systems.md) for cascades,
12
- clipmaps, invalidation, and diagnostic captures.
10
+ ## Cached clipmap workflow
13
11
 
14
- ## Build order
12
+ 1. Define concentric light-space square levels.
13
+ 2. Snap each level center to its own texel grid.
14
+ 3. Cross-fade adjacent levels in shader space.
15
+ 4. Refresh near levels continuously.
16
+ 5. Cache coarse levels and update them under a frame budget.
17
+ 6. Invalidate intersecting levels when important casters or streamed terrain change.
18
+ 7. Scale normal bias by world-space texel width.
15
19
 
16
- 1. Define light direction, camera envelope, world scale, dynamic objects, and
17
- target shadow budget.
18
- 2. Choose basic maps, cascades, cached clipmaps, or contact-only shadows.
19
- 3. Stabilize shadow texels for moving cameras.
20
- 4. Separate static, dynamic, and invalidated casters.
21
- 5. Add filtering and bias after acne/peter-panning diagnostics.
22
- 6. Expose debug views for cascades, texel density, casters, receivers, and bias.
20
+ Read [references/shadow-systems.md](references/shadow-systems.md) before implementing a large-world directional light.
23
21
 
24
- ## Rules
22
+ Read the
23
+ [cached shadow clipmaps](../threejs-procedural-architecture/examples/authored-financial-tower/shadow-clipmaps.js)
24
+ for three light-space square levels, per-level texel snapping, containment
25
+ cross-fades, cached coarse updates, scaled bias, and unshadowed outside weight.
25
26
 
26
- - Do not chase every artifact by raising resolution.
27
- - Keep shadow distance tied to camera and gameplay scale.
28
- - Cache static shadows when the world allows it.
29
- - Validate sun angle extremes and fast camera motion.
30
- - Provide lower-cost tiers for weaker GPUs.
27
+ ## Failure conditions
28
+
29
+ - projection centers move by fractions of a texel;
30
+ - shader containment does not match the map's committed center;
31
+ - all cascades refresh every frame without evidence;
32
+ - coarse levels freeze moving casters indefinitely;
33
+ - depth texture samples occur in divergent fragment control flow;
34
+ - the same normal bias is used across radically different texel sizes;
35
+ - level boundaries become visible under camera motion.
36
+
37
+ ## Routing boundary
38
+
39
+ Use this skill for light-space directional shadow maps. Use
40
+ `$genex-threejs-screen-space-ambient-occlusion` for view-dependent ambient
41
+ visibility; AO is not a replacement for cast shadows.