@genex-ai/cli-demo 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +54 -15
- package/package.json +1 -1
- package/templates/skills/genex-threejs-atmosphere-aerial-perspective/SKILL.md +30 -18
- package/templates/skills/genex-threejs-atmosphere-aerial-perspective/references/atmosphere.md +204 -20
- package/templates/skills/genex-threejs-bloom/SKILL.md +29 -18
- package/templates/skills/genex-threejs-bloom/references/bloom.md +176 -20
- package/templates/skills/genex-threejs-camera-direction/SKILL.md +38 -26
- package/templates/skills/genex-threejs-camera-direction/references/camera-rigs.md +359 -27
- package/templates/skills/genex-threejs-exposure-color-grading/SKILL.md +27 -18
- package/templates/skills/genex-threejs-exposure-color-grading/references/exposure-grading.md +196 -21
- package/templates/skills/genex-threejs-image-pipeline/SKILL.md +38 -17
- package/templates/skills/genex-threejs-image-pipeline/references/image-pipeline.md +185 -29
- package/templates/skills/genex-threejs-procedural-animation/SKILL.md +34 -21
- package/templates/skills/genex-threejs-procedural-animation/references/procedural-motion.md +353 -24
- package/templates/skills/genex-threejs-procedural-architecture/SKILL.md +36 -17
- package/templates/skills/genex-threejs-procedural-architecture/references/architecture-systems.md +500 -22
- package/templates/skills/genex-threejs-procedural-fields/SKILL.md +59 -24
- package/templates/skills/genex-threejs-procedural-fields/references/field-systems.md +222 -25
- package/templates/skills/genex-threejs-procedural-geometry/SKILL.md +34 -20
- package/templates/skills/genex-threejs-procedural-geometry/references/mesh-systems.md +192 -26
- package/templates/skills/genex-threejs-procedural-materials/SKILL.md +55 -18
- package/templates/skills/genex-threejs-procedural-materials/references/material-systems.md +189 -22
- package/templates/skills/genex-threejs-procedural-planets/SKILL.md +36 -18
- package/templates/skills/genex-threejs-procedural-planets/references/planet-systems.md +489 -21
- package/templates/skills/genex-threejs-procedural-vegetation/SKILL.md +35 -25
- package/templates/skills/genex-threejs-procedural-vegetation/references/vegetation-systems.md +304 -27
- package/templates/skills/genex-threejs-procedural-vfx/SKILL.md +26 -18
- package/templates/skills/genex-threejs-procedural-vfx/references/vfx-systems.md +208 -20
- package/templates/skills/genex-threejs-raymarched-space-effects/SKILL.md +25 -18
- package/templates/skills/genex-threejs-raymarched-space-effects/references/space-effects.md +185 -21
- package/templates/skills/genex-threejs-screen-space-ambient-occlusion/SKILL.md +23 -17
- package/templates/skills/genex-threejs-screen-space-ambient-occlusion/references/ambient-occlusion.md +430 -20
- package/templates/skills/genex-threejs-shadow-systems/SKILL.md +29 -18
- package/templates/skills/genex-threejs-shadow-systems/references/shadow-systems.md +420 -21
- package/templates/skills/genex-threejs-skill-router/SKILL.md +21 -21
- package/templates/skills/genex-threejs-spectral-ocean/SKILL.md +30 -20
- package/templates/skills/genex-threejs-spectral-ocean/references/spectral-ocean.md +462 -22
- package/templates/skills/genex-threejs-temporal-surfaces/SKILL.md +26 -17
- package/templates/skills/genex-threejs-temporal-surfaces/references/temporal-surfaces.md +198 -20
- package/templates/skills/genex-threejs-visual-validation/SKILL.md +34 -18
- package/templates/skills/genex-threejs-visual-validation/references/visual-validation.md +396 -32
- package/templates/skills/genex-threejs-volumetric-clouds/SKILL.md +33 -17
- package/templates/skills/genex-threejs-volumetric-clouds/references/volumetric-clouds.md +570 -21
- package/templates/skills/genex-threejs-water-optics/SKILL.md +33 -18
- package/templates/skills/genex-threejs-water-optics/references/water-optics.md +184 -20
package/dist/index.js
CHANGED
|
@@ -788,32 +788,71 @@ async function deployGame(sshUrl, opts, log) {
|
|
|
788
788
|
return false;
|
|
789
789
|
}
|
|
790
790
|
const gitDir = await fs6.mkdtemp(path7.join(os2.tmpdir(), "genex-deploy-"));
|
|
791
|
-
const
|
|
791
|
+
const base = { GIT_DIR: gitDir };
|
|
792
|
+
const ident = {
|
|
793
|
+
GIT_AUTHOR_NAME: "genex",
|
|
794
|
+
GIT_AUTHOR_EMAIL: "agent@genex.local",
|
|
795
|
+
GIT_COMMITTER_NAME: "genex",
|
|
796
|
+
GIT_COMMITTER_EMAIL: "agent@genex.local"
|
|
797
|
+
};
|
|
798
|
+
const EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
792
799
|
try {
|
|
793
|
-
if ((await run("git", ["init", "-q"],
|
|
800
|
+
if ((await run("git", ["init", "-q"], base)).code !== 0) {
|
|
794
801
|
log.warn("git init failed \u2014 the game was not pushed.");
|
|
795
802
|
return false;
|
|
796
803
|
}
|
|
797
|
-
await
|
|
798
|
-
|
|
799
|
-
|
|
804
|
+
await fs6.writeFile(
|
|
805
|
+
path7.join(gitDir, "info", "exclude"),
|
|
806
|
+
["node_modules/", "dist/", ".git/", KEY_NAME, `${KEY_NAME}.pub`, ".genex/", ""].join("\n")
|
|
807
|
+
);
|
|
808
|
+
const stage = async (workTree, indexName) => {
|
|
809
|
+
const env = { ...base, GIT_WORK_TREE: workTree, GIT_INDEX_FILE: path7.join(gitDir, indexName) };
|
|
810
|
+
await run("git", ["add", "-A"], env);
|
|
811
|
+
const tracked = await run("git", ["ls-files"], env);
|
|
812
|
+
if (/(^|\/)genex_key(\.pub)?$/m.test(tracked.out)) throw new Error("KEY_STAGED");
|
|
813
|
+
if (!tracked.out.trim()) return null;
|
|
814
|
+
const tree = (await run("git", ["write-tree"], env)).out.trim();
|
|
815
|
+
return tree || null;
|
|
816
|
+
};
|
|
817
|
+
const commitTree = async (tree, message) => (await run("git", ["commit-tree", tree, "-m", message], { ...base, ...ident })).out.trim();
|
|
818
|
+
let mainTree;
|
|
819
|
+
try {
|
|
820
|
+
mainTree = await stage(siteDir, "index-main");
|
|
821
|
+
} catch {
|
|
800
822
|
log.error(`Refusing to deploy: ${KEY_NAME} is staged. Add it to .gitignore and retry.`);
|
|
801
823
|
return false;
|
|
802
824
|
}
|
|
803
|
-
|
|
804
|
-
"git",
|
|
805
|
-
["-c", "user.email=agent@genex.local", "-c", "user.name=genex", "commit", "-q", "-m", "build"],
|
|
806
|
-
gitEnv
|
|
807
|
-
);
|
|
808
|
-
if (commit.code !== 0 && !/nothing to commit/i.test(commit.out + commit.err)) {
|
|
825
|
+
if (!mainTree || mainTree === EMPTY_TREE) {
|
|
809
826
|
log.warn("Nothing to commit \u2014 the build produced no files.");
|
|
810
827
|
return false;
|
|
811
828
|
}
|
|
829
|
+
await run("git", ["update-ref", "refs/heads/main", await commitTree(mainTree, "build")], base);
|
|
830
|
+
let pushSource = false;
|
|
831
|
+
if (siteDir !== cwd) {
|
|
832
|
+
try {
|
|
833
|
+
const srcTree = await stage(cwd, "index-source");
|
|
834
|
+
if (srcTree && srcTree !== EMPTY_TREE) {
|
|
835
|
+
await run("git", ["update-ref", "refs/heads/source", await commitTree(srcTree, "source")], base);
|
|
836
|
+
pushSource = true;
|
|
837
|
+
}
|
|
838
|
+
} catch {
|
|
839
|
+
log.dim(" (Couldn't publish source for remixing \u2014 the deploy key was in the way.)");
|
|
840
|
+
}
|
|
841
|
+
}
|
|
812
842
|
log.step("Pushing your game over SSH\u2026");
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
843
|
+
const refspecs = ["+refs/heads/main:main"];
|
|
844
|
+
if (pushSource) refspecs.push("+refs/heads/source:source");
|
|
845
|
+
const push = await run(
|
|
846
|
+
"git",
|
|
847
|
+
["push", "-q", ...pushSource ? ["--atomic"] : [], sshUrl, ...refspecs],
|
|
848
|
+
{
|
|
849
|
+
...base,
|
|
850
|
+
// Quote the key path: git splits GIT_SSH_COMMAND with shell-like rules, so a
|
|
851
|
+
// project folder with a space (e.g. "fly drone") otherwise breaks the `-i`
|
|
852
|
+
// argument and ssh fails with "Could not resolve hostname …".
|
|
853
|
+
GIT_SSH_COMMAND: `ssh -i "${keyPath}" -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new`
|
|
854
|
+
}
|
|
855
|
+
);
|
|
817
856
|
if (push.code === 0) {
|
|
818
857
|
log.success("Pushed.");
|
|
819
858
|
if (opts.playUrl) {
|
package/package.json
CHANGED
|
@@ -5,26 +5,38 @@ description: Implement sky and aerial perspective for Genex Three.js games. Use
|
|
|
5
5
|
|
|
6
6
|
# Genex Three.js Atmosphere And Aerial Perspective
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
after the base scene reads.
|
|
8
|
+
Treat sky rendering and aerial perspective as two views of the same scattering model. They must share radii, density profiles, coefficients, sun direction, exposure scale, and coordinate transforms.
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
lighting handoff, and transition checks.
|
|
10
|
+
## Choose the implementation tier
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
- Small scene with no orbital camera: analytic height/distance approximation.
|
|
13
|
+
- Planetary ground-to-space camera: ray integration or precomputed LUTs.
|
|
14
|
+
- Large geospatial world: LUTs plus world-to-planet transform, altitude correction, and depth-aware aerial perspective.
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
3. Add depth-based aerial perspective for terrain, buildings, and distant props.
|
|
20
|
-
4. Connect sun color, ambient color, fog, and material response coherently.
|
|
21
|
-
5. Add planetary shell or LUT paths only when the scale needs them.
|
|
22
|
-
6. Expose debug views for transmittance, inscattering, depth, and no-atmosphere.
|
|
16
|
+
Read [references/atmosphere.md](references/atmosphere.md)
|
|
17
|
+
before implementation. It separates the LUT/ellipsoid architecture from
|
|
18
|
+
dynamic integration and the shell/post handoff.
|
|
23
19
|
|
|
24
|
-
##
|
|
20
|
+
## Required outputs
|
|
25
21
|
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
22
|
+
- sky radiance;
|
|
23
|
+
- sun transmittance/color;
|
|
24
|
+
- segment transmittance from camera to visible surface;
|
|
25
|
+
- segment inscattering;
|
|
26
|
+
- optional sky irradiance for materials;
|
|
27
|
+
- explicit scale conversion between world units and atmosphere units.
|
|
28
|
+
|
|
29
|
+
## Failure conditions
|
|
30
|
+
|
|
31
|
+
- sky and terrain haze use different sun directions or coefficients;
|
|
32
|
+
- the atmosphere is a uniformly transparent sphere;
|
|
33
|
+
- camera altitude is measured in a local flat frame during orbital motion;
|
|
34
|
+
- scene depth is treated as linear when it is not;
|
|
35
|
+
- exposure is used to hide incorrect radiance scale;
|
|
36
|
+
- atmosphere fades abruptly at shell entry.
|
|
37
|
+
|
|
38
|
+
## Routing boundary
|
|
39
|
+
|
|
40
|
+
This skill owns molecular/aerosol sky scattering and surface-segment aerial
|
|
41
|
+
perspective. Use `$genex-threejs-volumetric-clouds` for weather-shaped cloud density,
|
|
42
|
+
temporal cloud reconstruction, and cloud shadows.
|
package/templates/skills/genex-threejs-atmosphere-aerial-perspective/references/atmosphere.md
CHANGED
|
@@ -1,29 +1,213 @@
|
|
|
1
|
-
# Atmosphere
|
|
1
|
+
# Atmosphere system contract
|
|
2
2
|
|
|
3
|
-
Use this
|
|
3
|
+
Use this contract to choose between a precomputed LUT/ellipsoid atmosphere and bounded dynamic integration while keeping sky, aerial perspective, surface lighting, and coordinate transforms coherent.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Contents
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
7
|
+
- Shared parameter model
|
|
8
|
+
- LUT atmosphere implementation LUT contract
|
|
9
|
+
- Ellipsoid and depth ownership
|
|
10
|
+
- planet-space implementation body profiles
|
|
11
|
+
- planet-space implementation integration
|
|
12
|
+
- Shell/post handoff
|
|
13
|
+
- Implementation limits
|
|
14
|
+
- Diagnostics
|
|
11
15
|
|
|
12
|
-
## Aerial perspective
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
- Preserve contrast for interactable objects and traversal edges.
|
|
16
|
-
- Let distant terrain shift color before it loses all form.
|
|
17
|
-
- Provide a debug toggle to remove atmosphere.
|
|
17
|
+
## Shared parameter model
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
`LUT atmosphere implementation` keeps one atmosphere object for sky and aerial perspective.
|
|
20
|
+
Earth-like defaults:
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
```text
|
|
23
|
+
solar irradiance = (1.474, 1.8504, 1.91198)
|
|
24
|
+
sun angular radius = 0.004675 rad
|
|
25
|
+
bottom radius = 6,360,000 m
|
|
26
|
+
top radius = 6,420,000 m
|
|
27
|
+
Rayleigh scattering = (0.005802, 0.013558, 0.0331)
|
|
28
|
+
Mie scattering = (0.003996, 0.003996, 0.003996)
|
|
29
|
+
Mie extinction = (0.00444, 0.00444, 0.00444)
|
|
30
|
+
Mie phase g = 0.8
|
|
31
|
+
absorption extinction = (0.00065, 0.001881, 0.000085)
|
|
32
|
+
ground albedo = 0.1
|
|
33
|
+
```
|
|
24
34
|
|
|
25
|
-
|
|
35
|
+
Density profiles are two-layer functions:
|
|
26
36
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
```text
|
|
38
|
+
density(h) =
|
|
39
|
+
clamp(
|
|
40
|
+
expTerm * exp(expScale * h)
|
|
41
|
+
+ linearTerm * h
|
|
42
|
+
+ constantTerm,
|
|
43
|
+
0,
|
|
44
|
+
1
|
|
45
|
+
)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The default Rayleigh exponential scale is `-0.125`, Mie `-0.833333`.
|
|
49
|
+
Absorption uses two linear layers centered around the ozone region rather than
|
|
50
|
+
another ground-heavy exponential.
|
|
51
|
+
|
|
52
|
+
One explicit meter-to-render-unit conversion is applied when parameters become
|
|
53
|
+
uniforms. Preserve this single conversion boundary.
|
|
54
|
+
|
|
55
|
+
## LUT atmosphere implementation LUT contract
|
|
56
|
+
|
|
57
|
+
The sky material and aerial-perspective effect consume the same:
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
transmittance texture
|
|
61
|
+
scattering 3D texture
|
|
62
|
+
irradiance texture
|
|
63
|
+
optional single-Mie and higher-order scattering textures
|
|
64
|
+
atmosphere parameters
|
|
65
|
+
sun direction
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The sky material reconstructs rays from inverse projection and inverse view
|
|
69
|
+
matrices. It can render sun, moon, ground, and shadow-length integration.
|
|
70
|
+
|
|
71
|
+
The aerial-perspective effect owns:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
camera projection/view and inverses
|
|
75
|
+
camera world position
|
|
76
|
+
depth
|
|
77
|
+
optional normal buffer
|
|
78
|
+
ellipsoid radii
|
|
79
|
+
world-to-ECEF transform
|
|
80
|
+
altitude correction
|
|
81
|
+
geometric-error correction
|
|
82
|
+
overlay/cloud shadow/light-mask inputs
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Default composition enables segment transmittance and inscatter. Direct sun
|
|
86
|
+
light and sky-light relighting are separate switches. Do not collapse these
|
|
87
|
+
signals into one fog color.
|
|
88
|
+
|
|
89
|
+
## Ellipsoid and depth ownership
|
|
90
|
+
|
|
91
|
+
The geospatial path defaults to `Ellipsoid.WGS84` and can correct both
|
|
92
|
+
camera altitude and geometry error. Atmosphere altitude is therefore not
|
|
93
|
+
`worldPosition.y`.
|
|
94
|
+
|
|
95
|
+
Required coordinate contract:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
world position
|
|
99
|
+
-> world-to-ECEF
|
|
100
|
+
-> ellipsoid-relative position
|
|
101
|
+
-> corrected altitude
|
|
102
|
+
-> LUT coordinates / segment scattering
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The aerial effect declares depth ownership through its post-processing effect
|
|
106
|
+
attribute. It also supports octahedral normals or normal reconstruction when
|
|
107
|
+
lighting terms require orientation.
|
|
108
|
+
|
|
109
|
+
## planet-space implementation body profiles
|
|
110
|
+
|
|
111
|
+
planet-space implementation derives profiles by body kind and density. Terrestrial baseline:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
Rayleigh = (0.0058, 0.0135, 0.0331)
|
|
115
|
+
Mie scattering = (0.0022, 0.0022, 0.0022)
|
|
116
|
+
Mie extinction = (0.0032, 0.0032, 0.0032)
|
|
117
|
+
Rayleigh scale height = lerp(7.2, 10.8, normalized density) km
|
|
118
|
+
Mie scale height = lerp(0.9, 1.7, normalized density) km
|
|
119
|
+
Mie g = 0.76
|
|
120
|
+
ozone extinction = (0.00065, 0.001881, 0.000085)
|
|
121
|
+
solar intensity = 13.8
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Rocky bodies reduce scattering and remove ozone. Gas/ice giants use much
|
|
125
|
+
larger scale heights and `g` around `0.80–0.82`.
|
|
126
|
+
|
|
127
|
+
The implementation enforces:
|
|
128
|
+
|
|
129
|
+
```text
|
|
130
|
+
mieExtinction[channel] >= mieScattering[channel] + 0.0001
|
|
131
|
+
g <= 0.92
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
This prevents negative absorption and unstable phase behavior.
|
|
135
|
+
|
|
136
|
+
## planet-space implementation integration
|
|
137
|
+
|
|
138
|
+
For each camera ray, planet-space implementation:
|
|
139
|
+
|
|
140
|
+
1. intersects the top atmosphere sphere;
|
|
141
|
+
2. clamps the segment against the surface sphere;
|
|
142
|
+
3. marches `ATMOSPHERE_VIEW_SAMPLES`;
|
|
143
|
+
4. accumulates Rayleigh, Mie, and triangular ozone depth;
|
|
144
|
+
5. at every view sample, marches a sun segment with
|
|
145
|
+
`ATMOSPHERE_LIGHT_SAMPLES`;
|
|
146
|
+
6. tests planet occlusion of the sun;
|
|
147
|
+
7. evaluates Rayleigh and anisotropic Mie phase;
|
|
148
|
+
8. returns in-scattered radiance and view transmittance.
|
|
149
|
+
|
|
150
|
+
It adds an upper-Rayleigh exponential term and fades density over the final
|
|
151
|
+
`24%` of atmosphere thickness to soften the shell edge.
|
|
152
|
+
|
|
153
|
+
The compact path includes a small multiple-scattering approximation derived
|
|
154
|
+
from `1 - transmittance`; it is not equivalent to the precomputed higher-order
|
|
155
|
+
scattering available in `LUT atmosphere implementation`.
|
|
156
|
+
|
|
157
|
+
## Shell/post handoff
|
|
158
|
+
|
|
159
|
+
planet-space implementation renders a double-sided shell and a depth-aware post path from one
|
|
160
|
+
profile. Runtime face-opacity weights avoid a hard front/back cull switch.
|
|
161
|
+
|
|
162
|
+
The post blend is based on altitude above the atmosphere top:
|
|
163
|
+
|
|
164
|
+
```text
|
|
165
|
+
entry blend near = 140 km
|
|
166
|
+
entry blend far = max(448 km, visual atmosphere height * 0.58)
|
|
167
|
+
post blend = 1 - smoothstep(near, far, altitudeFromTop)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
The post path applies only where scene depth represents a surface. The shell
|
|
171
|
+
continues to own sky pixels and limb appearance.
|
|
172
|
+
|
|
173
|
+
Preserve:
|
|
174
|
+
|
|
175
|
+
```text
|
|
176
|
+
one body center and radius
|
|
177
|
+
one atmosphere profile
|
|
178
|
+
one sun direction
|
|
179
|
+
one unit conversion
|
|
180
|
+
surface-depth classification
|
|
181
|
+
continuous shell/post blend
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Implementation limits
|
|
185
|
+
|
|
186
|
+
- planet-space implementation performs nested dynamic integration and is expensive compared with
|
|
187
|
+
LUT lookup.
|
|
188
|
+
- Its atmosphere uses spheres, while `LUT atmosphere implementation` supports an ellipsoid
|
|
189
|
+
and ECEF correction.
|
|
190
|
+
- planet-space implementation’s multiple-scattering term is an artistic approximation.
|
|
191
|
+
- `LUT atmosphere implementation` is version-sensitive and built around its own
|
|
192
|
+
post-processing/coordinate utilities; adapt the architecture, not imports
|
|
193
|
+
blindly.
|
|
194
|
+
- Do not combine LUT radiance and dynamic integrated radiance at full weight.
|
|
195
|
+
Choose ownership or a validated transition.
|
|
196
|
+
|
|
197
|
+
## Diagnostics
|
|
198
|
+
|
|
199
|
+
Expose:
|
|
200
|
+
|
|
201
|
+
```text
|
|
202
|
+
planet/ECEF coordinates and corrected altitude
|
|
203
|
+
top and bottom intersections
|
|
204
|
+
Rayleigh, Mie, and absorption density
|
|
205
|
+
view and sun optical depth
|
|
206
|
+
sun visibility
|
|
207
|
+
segment transmittance
|
|
208
|
+
single and multiple scattering
|
|
209
|
+
sky versus surface depth classification
|
|
210
|
+
shell front/back opacity
|
|
211
|
+
post blend
|
|
212
|
+
LUT coordinates and texture slices
|
|
213
|
+
```
|
|
@@ -5,26 +5,37 @@ description: Implement controlled HDR bloom for Genex Three.js games. Use for se
|
|
|
5
5
|
|
|
6
6
|
# Genex Three.js Bloom
|
|
7
7
|
|
|
8
|
-
Bloom
|
|
9
|
-
object reads.
|
|
8
|
+
Bloom is a camera/display response to bright HDR signal. Establish scene exposure and emissive luminance before tuning blur.
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
selective contribution, blur hierarchy, and diagnostics.
|
|
10
|
+
## Workflow
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
1. Inspect pre-tone-map luminance.
|
|
13
|
+
2. Choose which scene values should bloom.
|
|
14
|
+
3. Choose a single-node or dual selective-render ownership model.
|
|
15
|
+
4. Calibrate threshold, radius, smooth width, and strength in HDR.
|
|
16
|
+
5. Restore all substituted materials transactionally for selective passes.
|
|
17
|
+
6. Composite before exposure/tone mapping.
|
|
18
|
+
7. Validate base, contribution, and final views.
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
4. Blur at multiple scales.
|
|
20
|
-
5. Composite with exposure-aware strength.
|
|
21
|
-
6. Expose debug views for source, threshold mask, blur levels, final bloom, and
|
|
22
|
-
no-bloom baseline.
|
|
20
|
+
Read [references/bloom.md](references/bloom.md) for the
|
|
21
|
+
HDR ordering, dual selective-bloom transaction, compact emissive hierarchy,
|
|
22
|
+
and the costs and limits of each ownership model.
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Apply the material substitution/restoration ownership pattern in the
|
|
25
|
+
reference before adding selective bloom to a composed scene.
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
27
|
+
## Failure conditions
|
|
28
|
+
|
|
29
|
+
- bloom creates the only visible form of an effect;
|
|
30
|
+
- all bright materials share one arbitrary emission multiplier;
|
|
31
|
+
- threshold is tuned after tone mapping;
|
|
32
|
+
- selective bloom requires mutating scene materials every frame without restoration guarantees;
|
|
33
|
+
- transparent particles disappear from extraction because pass ownership is unclear;
|
|
34
|
+
- bloom radius changes wildly with resolution;
|
|
35
|
+
- highlights become gray because energy is clamped too early.
|
|
36
|
+
|
|
37
|
+
## Routing boundary
|
|
38
|
+
|
|
39
|
+
Use `$genex-threejs-exposure-color-grading` for metering, adaptation, tone mapping,
|
|
40
|
+
and LUTs. Load `$genex-threejs-image-pipeline` only when bloom must be composed with
|
|
41
|
+
several shared image-space systems.
|
|
@@ -1,29 +1,185 @@
|
|
|
1
|
-
#
|
|
1
|
+
# HDR bloom systems
|
|
2
2
|
|
|
3
|
-
Use this reference
|
|
3
|
+
Use this reference to choose bloom ownership, signal order, selective contribution, and scene-relative emissive ranges without making bloom responsible for the underlying form.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Contents
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
7
|
+
- production WebGPU pipeline signal order
|
|
8
|
+
- production WebGPU pipeline bloom controls
|
|
9
|
+
- selective gallery pipeline selective ownership
|
|
10
|
+
- Material substitution invariant
|
|
11
|
+
- atlas-based renderer baseline
|
|
12
|
+
- pooled VFX system HDR hierarchy
|
|
13
|
+
- Implementation limits
|
|
14
|
+
- Diagnostics
|
|
10
15
|
|
|
11
|
-
## Selective bloom
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
- Restore material state after rendering a selected pass.
|
|
15
|
-
- Avoid duplicate contribution from the same object.
|
|
16
|
-
- Keep selected objects documented.
|
|
17
|
+
## production WebGPU pipeline signal order
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
The WebGPU pipeline owns bloom before exposure and render output:
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
```text
|
|
22
|
+
scene pass
|
|
23
|
+
-> optional GTAO composite
|
|
24
|
+
-> optional atmosphere
|
|
25
|
+
-> bloom node
|
|
26
|
+
-> sampled scene + bloom
|
|
27
|
+
-> eye-adaptation exposure
|
|
28
|
+
-> renderOutput / tone map
|
|
29
|
+
-> optional 3D LUT
|
|
30
|
+
-> optional FXAA
|
|
31
|
+
```
|
|
24
32
|
|
|
25
|
-
|
|
33
|
+
The render pipeline disables its automatic output color transform and assigns
|
|
34
|
+
one final output node. Preserve this one-owner rule when adapting to current
|
|
35
|
+
Three.js `RenderPipeline`.
|
|
26
36
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
## production WebGPU pipeline bloom controls
|
|
38
|
+
|
|
39
|
+
Bloom defaults:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
enabled = false
|
|
43
|
+
strength = 0
|
|
44
|
+
radius = 0.35
|
|
45
|
+
threshold = 0.72
|
|
46
|
+
smooth width = 0.08
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The Three.js bloom node reads the HDR texture produced after atmosphere. Its
|
|
50
|
+
strength becomes zero when disabled; radius, threshold, and smooth width remain
|
|
51
|
+
independently updateable.
|
|
52
|
+
|
|
53
|
+
This path does not implement a custom pyramid. Its contract is signal placement
|
|
54
|
+
and parameter ownership around the renderer’s bloom node.
|
|
55
|
+
Verify the installed Three.js node API before using the exact constructor or
|
|
56
|
+
property names.
|
|
57
|
+
|
|
58
|
+
## selective gallery pipeline selective ownership
|
|
59
|
+
|
|
60
|
+
The gallery uses two separate selective bloom pipelines:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
neon layer -> neon UnrealBloomPass
|
|
64
|
+
chandelier layer -> chandelier UnrealBloomPass
|
|
65
|
+
base scene -> final composer
|
|
66
|
+
|
|
67
|
+
final = base + neon bloom + chandelier bloom
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Each bloom composer renders off-screen. A final shader adds both bloom textures
|
|
71
|
+
to the base render, then an `OutputPass` performs display output.
|
|
72
|
+
|
|
73
|
+
Separate ownership lets neon animation change strength/radius without forcing
|
|
74
|
+
the chandelier glow to share the same threshold or spread.
|
|
75
|
+
|
|
76
|
+
Chandelier bulbs, filaments, and glow meshes use unlit materials; bulb and
|
|
77
|
+
filament materials set `toneMapped = false`. The pipeline therefore combines
|
|
78
|
+
explicit layer membership with material-level HDR/display behavior.
|
|
79
|
+
|
|
80
|
+
## Material substitution invariant
|
|
81
|
+
|
|
82
|
+
For each selective pass, selective gallery pipeline traverses visible meshes and replaces every
|
|
83
|
+
non-member material with one shared black material.
|
|
84
|
+
|
|
85
|
+
Required transaction:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
set active bloom layer
|
|
89
|
+
traverse visible meshes
|
|
90
|
+
record { mesh, original material }
|
|
91
|
+
replace non-members with shared black material
|
|
92
|
+
try:
|
|
93
|
+
render bloom composer
|
|
94
|
+
finally:
|
|
95
|
+
restore every recorded material
|
|
96
|
+
clear restoration list
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Support material arrays by storing the complete original `mesh.material`
|
|
100
|
+
value. Also toggle the high-detail and simplified
|
|
101
|
+
chandelier representations so only the intended version contributes.
|
|
102
|
+
|
|
103
|
+
The `finally` block is non-negotiable. Without it, a render error permanently
|
|
104
|
+
blackens scene meshes.
|
|
105
|
+
|
|
106
|
+
## atlas-based renderer baseline
|
|
107
|
+
|
|
108
|
+
atlas-based renderer wraps `UnrealBloomPass` with:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
strength = 0.30
|
|
112
|
+
radius = 0.50
|
|
113
|
+
threshold = 0.05
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Composer order:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
scene -> SSAO -> volumetrics -> bloom -> lens flare -> fog/color
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This is a useful comparison, not the quality target. The threshold is very low
|
|
123
|
+
and can bloom ordinary bright surfaces. The wrapper exposes only enabled,
|
|
124
|
+
strength, and threshold, while radius stays at its constructor value.
|
|
125
|
+
|
|
126
|
+
## pooled VFX system HDR hierarchy
|
|
127
|
+
|
|
128
|
+
pooled VFX system assigns compact effect luminance before bloom:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
spark initial RGB multiplier = 80
|
|
132
|
+
homing projectile = 30
|
|
133
|
+
laser = 10
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
These values establish a material-level contribution hierarchy, but they do
|
|
137
|
+
not define the bloom pass. Validate them against actual renderer exposure
|
|
138
|
+
before reuse.
|
|
139
|
+
|
|
140
|
+
Use the relationship, not the raw numbers:
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
short spark flash
|
|
144
|
+
> projectile core
|
|
145
|
+
> persistent laser
|
|
146
|
+
> ordinary lit surface
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Implementation limits
|
|
150
|
+
|
|
151
|
+
- selective gallery pipeline renders the scene multiple times for selective bloom. This is
|
|
152
|
+
acceptable for its bounded gallery but expensive for large scenes.
|
|
153
|
+
- Temporary material substitution can trigger shader/program changes and must
|
|
154
|
+
account for newly added meshes.
|
|
155
|
+
- The final selective gallery pipeline composite adds bloom textures directly; energy is
|
|
156
|
+
artistic, not physically conserved.
|
|
157
|
+
- atlas-based renderer’s low threshold is not evidence for a general HDR calibration.
|
|
158
|
+
- production WebGPU pipeline depends on version-sensitive Three.js bloom-node behavior.
|
|
159
|
+
- pooled VFX system material multipliers are scene-relative and cannot be treated as
|
|
160
|
+
exposure-independent units.
|
|
161
|
+
|
|
162
|
+
Prefer a dedicated contribution target when MRT/backend architecture supports
|
|
163
|
+
it and the scene cannot afford multiple full renders. Validate that decision
|
|
164
|
+
against the target scene’s measured cost and contribution masks.
|
|
165
|
+
|
|
166
|
+
## Diagnostics
|
|
167
|
+
|
|
168
|
+
Expose:
|
|
169
|
+
|
|
170
|
+
```text
|
|
171
|
+
HDR scene before bloom
|
|
172
|
+
false-color luminance
|
|
173
|
+
neon contribution
|
|
174
|
+
chandelier contribution
|
|
175
|
+
each bloom result
|
|
176
|
+
base without bloom
|
|
177
|
+
final composite
|
|
178
|
+
active layer membership
|
|
179
|
+
material restoration count and leak assertion
|
|
180
|
+
transparent-emitter contribution
|
|
181
|
+
bloom GPU time per render
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Acceptance requires the base frame to retain form and material hierarchy with
|
|
185
|
+
both bloom textures disabled.
|