@adatechnology/game-weather-three 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +48 -2
- package/dist/index.d.ts +331 -0
- package/dist/index.global.js +2394 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +537 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anderson Fernandes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,49 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @adatechnology/game-weather-three
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The three.js picture of [`@adatechnology/game-weather`](../game-weather): the rain, fog, sky, lightning, headlights and heat of the weather that a
|
|
4
|
+
`createWeather` world samples. It reads `weather.sample()` once a frame and draws it; it never advances the weather.
|
|
5
|
+
|
|
6
|
+
| Part | What it draws | Where it comes from |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| **Rain curtain** (`createRainCurtain`) | 14 000 GPU points in a 70 m x 25 m box that follows the camera, falling 13 m/s; shader texts character for character; sized by the weather's `drops` (the whole curtain at 4 000, the storm) and by the profile (`low` 0.35, `medium` 0.7, `high` 1) | game `jogo.js`, `const RAIN = 14000` |
|
|
9
|
+
| **Near rain** (`createNearRain`) | the Workshop's streaks (`engine.rain`, up to 4 000, slanted by the wind), the splashes on the `normal` sprite pool and the rings (only where `puddleAt` says there is a puddle, within `12 / (1 + quality)` m); `game-vfx-three` draws them | Workshop W313-331 |
|
|
10
|
+
| **Mist and ash** (`emitAirborne`) | `mistPerSecond` puffs of low mist and `ashPerSecond` flakes of falling ash a second around the camera, into the same pool | Workshop `neblina`, W1085-1086 |
|
|
11
|
+
| **Fog** (`createFog`, `fogOf`) | linear fog (near 25 m, far from the weather: 220 clear, 140 rain) or exponential-squared fog where the weather has a density (`fog` 0.075), and the zone fog (colour, far, weight; near 4 m at full weight) | game `skyUpdate` and `ZONA_NEBLINA` |
|
|
12
|
+
| **Sky** (`createSky`) | night colour `0x0b0f18` to day `0x8796a6` by `sample.sun`, times `sample.skyScale` (the page's 0.8 in rain), pulled to the zone colour; it also gives the fog its colour | game `skyUpdate` |
|
|
13
|
+
| **Lightning** (`createLightning`) | the double flash of `sample.flash`: hemisphere light `+ 3.2 I`, background `+ I * (.25, .27, .32)`, screen white `I * .12` | Workshop `chuva`, W1068-1072 |
|
|
14
|
+
| **Headlights** (`createHeadlights`) | two spot lights and two additive beam cones on any `Object3D`, lit at night, in rain or in fog, real light only within 40 m of the camera, and rain that glows inside the beam (up to 600 lit drops a second) | Workshop `farol`, W101-103 and W1161-1170 |
|
|
15
|
+
| **Heat haze** (`createHeatHaze`) | warm bands that rise over the lower half of the view, by `sample.haze` | SDK-made: no team delivered it |
|
|
16
|
+
|
|
17
|
+
`createWeatherRenderer(THREE, { scene, camera, weather, vfx, profile, zone, puddles, puddleAt, headlights, layers })` puts them together:
|
|
18
|
+
`update(dt)` each frame, `setLayer(id, on)` for `far_rain`, `near_rain`, `mist`, `fog`, `sky`, `lightning`, `headlights` and `haze`, `setZoneFog`,
|
|
19
|
+
`setProfile`, `headlights.attach(car, lensMaterial)`. Without `vfx` only the curtain, fog, sky, lightning light, headlights and haze are drawn.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import * as THREE from 'three'
|
|
23
|
+
import { createWeather } from '@adatechnology/game-weather'
|
|
24
|
+
import { createWeatherRenderer } from '@adatechnology/game-weather-three'
|
|
25
|
+
|
|
26
|
+
const weather = createWeather({ seed: 1, start: 'storm' })
|
|
27
|
+
const picture = createWeatherRenderer(THREE, { scene, camera, weather, vfx })
|
|
28
|
+
// every frame
|
|
29
|
+
weather.advance(dt)
|
|
30
|
+
picture.update(dt)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Bench
|
|
34
|
+
|
|
35
|
+
`createWeatherTestModule({ visual: createWeatherVisual({ vfx: room.vfx }) })` (the module of `game-weather`) adds the picture to the weather bench: seven layers
|
|
36
|
+
(rain curtain, near rain and splashes, mist and ash, sky, lightning, headlights, heat haze; names in pt-BR and en), and a lamp rig (two lamps on a block, the
|
|
37
|
+
Workshop's `hlMat` lenses) in front of the camera to show the headlights. `layers: { sky: false }` keeps a room's own sky; the bench's own `fog` layer reaches the
|
|
38
|
+
renderer too. The fog layer gives back the fog the host had when it is switched off.
|
|
39
|
+
|
|
40
|
+
## Proof
|
|
41
|
+
|
|
42
|
+
- `tools/golden/bin/record-weather-visual.mjs` cuts the rain block of `jogo.js` (`const RAIN = 14000` to `skyUpdate`) and runs it in a vm with three.js stubs under a
|
|
43
|
+
seeded `Math.random`; the fixture `tools/golden/fixtures/weather/game-rain-curtain.json` keeps the SHA-256 of the 42 000 floats, the shader texts and the sky, zone and
|
|
44
|
+
fog lines of the page. `tests/rain-curtain-golden.test.ts` compares the points bit for bit, the shaders character for character and the numbers of sky, fog, lightning,
|
|
45
|
+
headlights, mist and ash against the page text.
|
|
46
|
+
- The Workshop's `chuva` (three intensities), `neblina` and `farol` run in `game-vfx` as effects (`rain_and_puddles`, `fog_and_ash`, `headlights_in_rain`), with their own
|
|
47
|
+
golden of the events and the pools (`vfx-workshop-weather.json`).
|
|
48
|
+
|
|
49
|
+
No game content here: no names of a city or a faction. Peer dependency: `three` ^0.160.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import * as THREE_NS from 'three';
|
|
2
|
+
import { WorkshopEngine, VfxWorld, Puddle } from '@adatechnology/game-vfx';
|
|
3
|
+
import { WeatherSample, WeatherVisualFactory } from '@adatechnology/game-weather';
|
|
4
|
+
|
|
5
|
+
/** The only three.js members the renderer needs at runtime. Pass your own `THREE` instance (the whole namespace works). */
|
|
6
|
+
type ThreeLib = Pick<typeof THREE_NS, 'AdditiveBlending' | 'BoxGeometry' | 'BufferAttribute' | 'BufferGeometry' | 'Color' | 'ConeGeometry' | 'DoubleSide' | 'Fog' | 'FogExp2' | 'Group' | 'HemisphereLight' | 'Mesh' | 'MeshBasicMaterial' | 'Object3D' | 'PlaneGeometry' | 'Points' | 'ShaderMaterial' | 'SpotLight' | 'Vector3'>;
|
|
7
|
+
/** What the renderer reads of a weather world: its sample. A `createWeather` world fits. */
|
|
8
|
+
type WeatherSource = {
|
|
9
|
+
sample(): WeatherSample;
|
|
10
|
+
};
|
|
11
|
+
/** The quality names of game-vfx; they size the rain curtain. */
|
|
12
|
+
type WeatherProfileName = 'low' | 'medium' | 'high';
|
|
13
|
+
/** Zone fog (the game's `ZONA_NEBLINA`): colour, far distance in metres and weight 0..1. */
|
|
14
|
+
type ZoneFog = {
|
|
15
|
+
readonly color?: number;
|
|
16
|
+
readonly far?: number;
|
|
17
|
+
readonly weight: number;
|
|
18
|
+
};
|
|
19
|
+
type Vec3 = readonly [number, number, number];
|
|
20
|
+
|
|
21
|
+
/** The page's linear fog starts at 25 m and, in the zone, at 4 m (`scene.fog.near = lerp(25, 4, weight)`). */
|
|
22
|
+
declare const FOG_NEAR = 25;
|
|
23
|
+
declare const FOG_ZONE_NEAR = 4;
|
|
24
|
+
/** Below this exponential-squared density the weather uses the linear fog (the clear weathers have 0). */
|
|
25
|
+
declare const FOG_EXP_FROM = 0.0005;
|
|
26
|
+
/** exp2 density that sees as far as a linear fog of `far` metres (2 % left): used to blend the zone fog in the exponential case. */
|
|
27
|
+
declare const densityForFar: (far: number) => number;
|
|
28
|
+
type FogValues = {
|
|
29
|
+
readonly mode: 'linear';
|
|
30
|
+
readonly near: number;
|
|
31
|
+
readonly far: number;
|
|
32
|
+
} | {
|
|
33
|
+
readonly mode: 'exp2';
|
|
34
|
+
readonly density: number;
|
|
35
|
+
};
|
|
36
|
+
/** The fog the weather and the zone ask for. Pure. */
|
|
37
|
+
declare function fogOf(sample: WeatherSample, zone?: ZoneFog, expFrom?: number): FogValues;
|
|
38
|
+
type Fog = {
|
|
39
|
+
/** Puts the weather's fog on the scene (the page's `fog.far` and `fog.near`, or the exponential-squared one) with the sky's colour. */
|
|
40
|
+
update(sample: WeatherSample, sky: THREE_NS.Color, zone?: ZoneFog): void;
|
|
41
|
+
/** Takes the fog off the scene (a layer switched off). */
|
|
42
|
+
clear(): void;
|
|
43
|
+
};
|
|
44
|
+
declare function createFog(THREE: ThreeLib, scene: {
|
|
45
|
+
fog: unknown;
|
|
46
|
+
}, options?: {
|
|
47
|
+
readonly expFrom?: number;
|
|
48
|
+
}): Fog;
|
|
49
|
+
/** The Workshop's mist (W1073: low, slow, 3 to 5 m wide) and ash (fine, falling in a spiral), in a box that follows the camera. */
|
|
50
|
+
declare const MIST: {
|
|
51
|
+
readonly box: {
|
|
52
|
+
readonly x: readonly [-14, 10];
|
|
53
|
+
readonly y: readonly [0.2, 1.1];
|
|
54
|
+
readonly z: readonly [-3, 8];
|
|
55
|
+
};
|
|
56
|
+
readonly drift: readonly [0.15, 0.35];
|
|
57
|
+
readonly life: readonly [9, 13];
|
|
58
|
+
readonly size: readonly [3, 5];
|
|
59
|
+
readonly grow: 1.4;
|
|
60
|
+
readonly color: 8227488;
|
|
61
|
+
readonly alpha: 0.13;
|
|
62
|
+
readonly fadeIn: 0.35;
|
|
63
|
+
};
|
|
64
|
+
declare const ASH: {
|
|
65
|
+
readonly box: {
|
|
66
|
+
readonly x: readonly [-10, 8];
|
|
67
|
+
readonly y: readonly [4, 6];
|
|
68
|
+
readonly z: readonly [-3, 7];
|
|
69
|
+
};
|
|
70
|
+
readonly fall: -0.35;
|
|
71
|
+
readonly life: readonly [8, 12];
|
|
72
|
+
readonly size: readonly [0.025, 0.04];
|
|
73
|
+
readonly color: 10525328;
|
|
74
|
+
readonly alpha: 0.75;
|
|
75
|
+
readonly fadeIn: 0.1;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Feeds the `normal` sprite pool of the Workshop with `mistPerSecond` puffs of mist and `ashPerSecond` flakes of ash a second (the page's `emit('fog', ...)`
|
|
79
|
+
* and `emit('ash', ...)`, at the weather's rate instead of 5 and 14), around `camera`. The renderer of game-vfx-three draws them.
|
|
80
|
+
*/
|
|
81
|
+
declare function emitAirborne(engine: WorkshopEngine, sample: WeatherSample, dt: number, camera: Vec3): void;
|
|
82
|
+
|
|
83
|
+
/** The Workshop's car lamps (W101-103) and the rain that glows inside their beam (W1161-1170). */
|
|
84
|
+
declare const HEADLIGHTS: {
|
|
85
|
+
readonly spot: {
|
|
86
|
+
readonly color: 16773584;
|
|
87
|
+
readonly intensity: 2.4;
|
|
88
|
+
readonly distance: 26;
|
|
89
|
+
readonly angle: 0.33;
|
|
90
|
+
readonly penumbra: 0.5;
|
|
91
|
+
readonly decay: 1.6;
|
|
92
|
+
};
|
|
93
|
+
/** Lamp position on the car (x is mirrored), where the spot points, and the cone drawn in the air. */
|
|
94
|
+
readonly lamp: readonly [0.65, 0.74, 2.15];
|
|
95
|
+
readonly aim: readonly [0.65, 0.2, 12];
|
|
96
|
+
readonly cone: {
|
|
97
|
+
readonly radius: 2.4;
|
|
98
|
+
readonly length: 9;
|
|
99
|
+
readonly segments: 18;
|
|
100
|
+
readonly color: 16773584;
|
|
101
|
+
readonly opacity: 0.06;
|
|
102
|
+
};
|
|
103
|
+
readonly lens: {
|
|
104
|
+
readonly on: 16773584;
|
|
105
|
+
readonly off: 3815988;
|
|
106
|
+
};
|
|
107
|
+
/** Lit drops a second, thrown into the beam 1 to 13 m ahead (W1176). */
|
|
108
|
+
readonly lit: {
|
|
109
|
+
readonly rate: 600;
|
|
110
|
+
readonly depth: readonly [1, 13];
|
|
111
|
+
readonly spread: 0.33;
|
|
112
|
+
readonly color: 13622512;
|
|
113
|
+
readonly alpha: 0.9;
|
|
114
|
+
readonly life: 0.06;
|
|
115
|
+
readonly len: 0.035;
|
|
116
|
+
readonly velocity: readonly [0.8, -14, 0];
|
|
117
|
+
};
|
|
118
|
+
/** Beyond this many metres a car keeps only the cone: no real light (W-b text of `farol`). */
|
|
119
|
+
readonly lightRange: 40;
|
|
120
|
+
};
|
|
121
|
+
type HeadlightRules = {
|
|
122
|
+
/** Whether the lamps are lit in this weather and light (default: night, rain or fog). */
|
|
123
|
+
readonly lit?: (sample: WeatherSample) => boolean;
|
|
124
|
+
readonly lightRange?: number;
|
|
125
|
+
};
|
|
126
|
+
/** Night (the sun below the page's 0.3 night factor), rain or fog make a driver turn the lamps on. */
|
|
127
|
+
declare const defaultHeadlightRule: (sample: WeatherSample) => boolean;
|
|
128
|
+
type Headlights = {
|
|
129
|
+
/** Gives `car` its two spot lights and two beam cones (`lens`, when given, is the material of the lamp glass, lit with them). Returns the function that takes them off. */
|
|
130
|
+
attach(car: THREE_NS.Object3D, lens?: THREE_NS.MeshBasicMaterial): () => void;
|
|
131
|
+
/** Lights the lamps of the cars attached, the real light only within range of `camera`; throws the lit drops of the beams into the Workshop's streak pool. */
|
|
132
|
+
update(sample: WeatherSample, dt: number, camera: Vec3, engine?: WorkshopEngine, enabled?: boolean): void;
|
|
133
|
+
count(): number;
|
|
134
|
+
dispose(): void;
|
|
135
|
+
};
|
|
136
|
+
declare function createHeadlights(THREE: ThreeLib, rules?: HeadlightRules): Headlights;
|
|
137
|
+
|
|
138
|
+
/** Peak opacity of the shimmer at full haze, and how fast the bands rise (SDK-made: no team delivered heat haze, see the open question). */
|
|
139
|
+
declare const HEAT_HAZE: {
|
|
140
|
+
readonly opacity: 0.09;
|
|
141
|
+
readonly bands: 38;
|
|
142
|
+
readonly rise: 1.4;
|
|
143
|
+
readonly color: readonly [1, 0.93, 0.82];
|
|
144
|
+
};
|
|
145
|
+
declare const HEAT_HAZE_VERTEX = "varying vec2 vUv; void main(){ vUv = uv; gl_Position = vec4(position.xy, 0., 1.); }";
|
|
146
|
+
declare const HEAT_HAZE_FRAGMENT = "uniform float uTime; uniform float uHaze; uniform vec3 uColor; varying vec2 vUv; void main(){ float low = 1. - smoothstep(0.15, 0.7, vUv.y); float wave = sin(vUv.y*38. - uTime*1.4 + sin(vUv.x*11. + uTime*.7)*2.2) * .5 + .5; gl_FragColor = vec4(uColor, uHaze*low*wave*.09); }";
|
|
147
|
+
type HeatHaze = {
|
|
148
|
+
readonly object: THREE_NS.Mesh;
|
|
149
|
+
update(sample: WeatherSample, time: number): void;
|
|
150
|
+
dispose(): void;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* The heat shimmer of `extreme_heat` (`WeatherSample.haze`, 0..1): a screen-space layer of warm bands that rise over the lower half of the view. It is a layer, not a
|
|
154
|
+
* distortion of the picture, because bending the picture needs a render target that only the host owns.
|
|
155
|
+
*/
|
|
156
|
+
declare function createHeatHaze(THREE: ThreeLib): HeatHaze;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* What the Workshop's double flash does to the scene (W1072): the hemisphere light gains `I * 3.2`, the background gains `I * (.25, .27, .32)` and the screen goes
|
|
160
|
+
* white by `I * .12`, where `I` is the flash the weather samples (1, then .2, then .8 for 0.26 s).
|
|
161
|
+
*/
|
|
162
|
+
declare const LIGHTNING: {
|
|
163
|
+
readonly light: 3.2;
|
|
164
|
+
readonly background: readonly [0.25, 0.27, 0.32];
|
|
165
|
+
readonly white: 0.12;
|
|
166
|
+
readonly skyColor: 3820650;
|
|
167
|
+
readonly groundColor: 723724;
|
|
168
|
+
};
|
|
169
|
+
type Lightning = {
|
|
170
|
+
readonly light: THREE_NS.HemisphereLight;
|
|
171
|
+
/**
|
|
172
|
+
* Lights the scene with the flash of `sample`. `background`, when given, is the sky just written for this frame (the renderer passes it only when it owns the sky),
|
|
173
|
+
* and gains the flash; a background the host keeps for itself is left alone.
|
|
174
|
+
*/
|
|
175
|
+
update(sample: WeatherSample, background?: THREE_NS.Color): void;
|
|
176
|
+
dispose(): void;
|
|
177
|
+
};
|
|
178
|
+
declare function createLightning(THREE: ThreeLib, scene: {
|
|
179
|
+
add(object: THREE_NS.Object3D): unknown;
|
|
180
|
+
remove(object: THREE_NS.Object3D): unknown;
|
|
181
|
+
}, vfx?: VfxWorld): Lightning;
|
|
182
|
+
|
|
183
|
+
/** The rain (mm/h) from which a drop that lands splashes (the Workshop's garoa, 2.5, does not; its chuva, 15, does). */
|
|
184
|
+
declare const SPLASH_FROM_MM = 5;
|
|
185
|
+
type NearRainOptions = {
|
|
186
|
+
/** Ground ellipses where a drop leaves a ring (the Workshop's four dark puddles; a game has its own). None by default. */
|
|
187
|
+
readonly puddles?: readonly Puddle[];
|
|
188
|
+
/** Replaces the puddle test. */
|
|
189
|
+
readonly puddleAt?: (x: number, z: number) => boolean;
|
|
190
|
+
readonly splashFrom?: number;
|
|
191
|
+
};
|
|
192
|
+
type NearRain = {
|
|
193
|
+
update(sample: WeatherSample, dt: number, camera: Vec3): void;
|
|
194
|
+
/** Streaks alive. */
|
|
195
|
+
count(): number;
|
|
196
|
+
clear(): void;
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* The Workshop's near rain (W313-331) driven by the weather: the streaks live in the world's Workshop engine (`engine.rain`), game-vfx-three draws them, and the
|
|
200
|
+
* splashes and rings they leave go to the `normal` sprite pool and the rings. `drops` (900 garoa, 2 200 chuva, 4 000 temporal) and the wind along x are the Workshop's own
|
|
201
|
+
* numbers for its three intensities.
|
|
202
|
+
*/
|
|
203
|
+
declare function createNearRain(vfx: VfxWorld | undefined, options?: NearRainOptions): NearRain;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* The game's rain curtain (jogo.js `const RAIN = 14000`): a box of points that follows the camera, 70 m wide and 25 m high, falling 13 m/s. The shader texts and the
|
|
207
|
+
* numbers are the page's, character for character (a golden cuts them from the page and compares).
|
|
208
|
+
*/
|
|
209
|
+
declare const RAIN_CURTAIN: {
|
|
210
|
+
readonly count: 14000;
|
|
211
|
+
readonly width: 70;
|
|
212
|
+
readonly height: 25;
|
|
213
|
+
readonly speed: 13;
|
|
214
|
+
readonly pointSize: 1.6;
|
|
215
|
+
};
|
|
216
|
+
declare const RAIN_CURTAIN_VERTEX = "uniform float uTime; uniform vec3 uCam; void main(){ vec3 p = position; p.y = mod(p.y - uTime*13., 25.); p.xz = uCam.xz + mod(p.xz - uCam.xz + 35., 70.) - 35.; gl_Position = projectionMatrix*viewMatrix*vec4(p,1.); gl_PointSize = 1.6; }";
|
|
217
|
+
declare const RAIN_CURTAIN_FRAGMENT = "uniform float uDay; void main(){ gl_FragColor = vec4(vec3(.68,.72,.78)*(0.25+0.75*uDay), .22+.1*uDay); }";
|
|
218
|
+
/** The share of the 14 000 points each quality draws. */
|
|
219
|
+
declare const RAIN_CURTAIN_PROFILES: Readonly<Record<WeatherProfileName, number>>;
|
|
220
|
+
/** The weather's `drops` at which the whole curtain is drawn (the storm's 4 000). */
|
|
221
|
+
declare const RAIN_CURTAIN_FULL_AT = 4000;
|
|
222
|
+
/** The page's loop: x and z in -35..35, y in 0..25, three draws a point in that order, stored as Float32. */
|
|
223
|
+
declare function rainCurtainPositions(random?: () => number, count?: number): Float32Array;
|
|
224
|
+
type RainCurtainOptions = {
|
|
225
|
+
readonly random?: () => number;
|
|
226
|
+
readonly profile?: WeatherProfileName;
|
|
227
|
+
/** Drops (`WeatherSample.drops`) that draw the whole curtain. */
|
|
228
|
+
readonly fullAt?: number;
|
|
229
|
+
readonly count?: number;
|
|
230
|
+
};
|
|
231
|
+
type RainCurtain = {
|
|
232
|
+
readonly object: THREE_NS.Points;
|
|
233
|
+
/** Draws `sample.drops` of the curtain around `camera`; `daylight` is the game's `s` (0 night, 1 day). */
|
|
234
|
+
update(sample: WeatherSample, camera: {
|
|
235
|
+
readonly x: number;
|
|
236
|
+
readonly y: number;
|
|
237
|
+
readonly z: number;
|
|
238
|
+
}, time: number, daylight: number): void;
|
|
239
|
+
setProfile(profile: WeatherProfileName): void;
|
|
240
|
+
/** How many points are drawn now. */
|
|
241
|
+
drawn(): number;
|
|
242
|
+
dispose(): void;
|
|
243
|
+
};
|
|
244
|
+
declare function createRainCurtain(THREE: ThreeLib, options?: RainCurtainOptions): RainCurtain;
|
|
245
|
+
|
|
246
|
+
/** The colours of the game's `skyUpdate` (jogo.js `_skyN` and `_skyD`): the sky goes from the night one to the day one with the sun height. */
|
|
247
|
+
declare const SKY_NIGHT = 724760;
|
|
248
|
+
declare const SKY_DAY = 8885926;
|
|
249
|
+
/** The zone fog colour is lit by `0.35 + 0.65 s` (the page's `ZONA_NEBLINA` blend). */
|
|
250
|
+
declare const ZONE_LIGHT: {
|
|
251
|
+
readonly base: 0.35;
|
|
252
|
+
readonly sun: 0.65;
|
|
253
|
+
};
|
|
254
|
+
/** The page's zone fog (`ZONA_NEBLINA`): colour and far distance; its weight is the game's to set. */
|
|
255
|
+
declare const ZONE_FOG_DEFAULTS: {
|
|
256
|
+
readonly color: 3820090;
|
|
257
|
+
readonly far: 60;
|
|
258
|
+
};
|
|
259
|
+
type Sky = {
|
|
260
|
+
/** The sky colour for this weather: night to day by `sample.sun`, dimmed by `sample.skyScale` (the page's 0.8 in rain), pulled to the zone colour by its weight. */
|
|
261
|
+
update(sample: WeatherSample, zone?: ZoneFog): THREE_NS.Color;
|
|
262
|
+
readonly color: THREE_NS.Color;
|
|
263
|
+
};
|
|
264
|
+
/** Writes the sky into `scene.background` (a `Color`; made when the scene has none) and hands the colour to the fog. */
|
|
265
|
+
declare function createSky(THREE: ThreeLib, scene: {
|
|
266
|
+
background: unknown;
|
|
267
|
+
}): Sky;
|
|
268
|
+
|
|
269
|
+
/** The parts the renderer draws, each of which a layer switches. */
|
|
270
|
+
declare const WEATHER_LAYERS: readonly ["far_rain", "near_rain", "mist", "fog", "sky", "lightning", "headlights", "haze"];
|
|
271
|
+
type WeatherLayerId = (typeof WEATHER_LAYERS)[number];
|
|
272
|
+
type WeatherRendererOptions = {
|
|
273
|
+
readonly scene: THREE_NS.Scene;
|
|
274
|
+
readonly camera: THREE_NS.Camera;
|
|
275
|
+
readonly weather: WeatherSource;
|
|
276
|
+
/** The effects world: near rain, splashes, mist, ash, the white of lightning and the lit drops of headlights live in its Workshop pools (game-vfx-three draws them). */
|
|
277
|
+
readonly vfx?: VfxWorld;
|
|
278
|
+
readonly profile?: WeatherProfileName;
|
|
279
|
+
/** Seeds the rain curtain (default `Math.random`). */
|
|
280
|
+
readonly random?: () => number;
|
|
281
|
+
readonly zone?: ZoneFog;
|
|
282
|
+
readonly puddles?: readonly Puddle[];
|
|
283
|
+
readonly puddleAt?: (x: number, z: number) => boolean;
|
|
284
|
+
readonly headlights?: HeadlightRules;
|
|
285
|
+
readonly layers?: Partial<Record<WeatherLayerId, boolean>>;
|
|
286
|
+
};
|
|
287
|
+
type WeatherRenderer = {
|
|
288
|
+
readonly curtain: RainCurtain;
|
|
289
|
+
readonly nearRain: NearRain;
|
|
290
|
+
readonly fog: Fog;
|
|
291
|
+
readonly sky: Sky;
|
|
292
|
+
readonly lightning: Lightning;
|
|
293
|
+
readonly headlights: Headlights;
|
|
294
|
+
readonly haze: HeatHaze;
|
|
295
|
+
/** Draws the weather of the source for a frame of `dt` seconds. Call once per frame, after the weather advanced. */
|
|
296
|
+
update(dt: number): void;
|
|
297
|
+
setLayer(id: WeatherLayerId, on: boolean): void;
|
|
298
|
+
layer(id: WeatherLayerId): boolean;
|
|
299
|
+
setZoneFog(zone: ZoneFog | undefined): void;
|
|
300
|
+
setProfile(profile: WeatherProfileName): void;
|
|
301
|
+
stats(): {
|
|
302
|
+
readonly rainCurtain: number;
|
|
303
|
+
readonly rainNear: number;
|
|
304
|
+
readonly cars: number;
|
|
305
|
+
};
|
|
306
|
+
dispose(): void;
|
|
307
|
+
};
|
|
308
|
+
/** The whole weather picture: rain curtain, near rain with splashes, mist and ash, fog, sky, lightning, headlights and heat haze, from one `WeatherSource`. */
|
|
309
|
+
declare function createWeatherRenderer(THREE: ThreeLib, options: WeatherRendererOptions): WeatherRenderer;
|
|
310
|
+
|
|
311
|
+
type WeatherVisualOptions = Pick<WeatherRendererOptions, 'profile' | 'random' | 'zone' | 'puddles' | 'puddleAt' | 'headlights'> & {
|
|
312
|
+
/** The effects world of the room (`room.vfx`); without it the near rain, mist, ash, white flash and lit drops are left out. */
|
|
313
|
+
readonly vfx?: VfxWorld;
|
|
314
|
+
/** Where the lamp rig stands (the two headlights of the Workshop's car, to see the beams); `false` leaves it out. Default 2.5 m ahead of the test room camera, lamps toward it. */
|
|
315
|
+
readonly rig?: readonly [x: number, z: number, turn: number] | false;
|
|
316
|
+
/** Which layers start on (all do by default); the room that is not about weather starts the sky and the fog off to keep its own look. */
|
|
317
|
+
readonly layers?: Partial<Record<WeatherLayerId, boolean>>;
|
|
318
|
+
};
|
|
319
|
+
/**
|
|
320
|
+
* The picture of the weather for the weather bench: `createWeatherTestModule({ visual: createWeatherVisual({ vfx: room.vfx }) })`. It draws the weather the bench shows with
|
|
321
|
+
* `createWeatherRenderer` on the room's scene and camera, switches each part with the bench layers and puts a lamp rig in front of the camera for the headlights.
|
|
322
|
+
*/
|
|
323
|
+
declare function createWeatherVisual(options?: WeatherVisualOptions): WeatherVisualFactory;
|
|
324
|
+
|
|
325
|
+
/** The names of the visual layers in the bench; any other locale falls back to English. */
|
|
326
|
+
type WeatherVisualText = {
|
|
327
|
+
readonly layers: Readonly<Record<Exclude<WeatherLayerId, 'fog'>, string>>;
|
|
328
|
+
};
|
|
329
|
+
declare const weatherVisualTextOf: (locale: string) => WeatherVisualText;
|
|
330
|
+
|
|
331
|
+
export { ASH, FOG_EXP_FROM, FOG_NEAR, FOG_ZONE_NEAR, type Fog, type FogValues, HEADLIGHTS, HEAT_HAZE, HEAT_HAZE_FRAGMENT, HEAT_HAZE_VERTEX, type HeadlightRules, type Headlights, type HeatHaze, LIGHTNING, type Lightning, MIST, type NearRain, type NearRainOptions, RAIN_CURTAIN, RAIN_CURTAIN_FRAGMENT, RAIN_CURTAIN_FULL_AT, RAIN_CURTAIN_PROFILES, RAIN_CURTAIN_VERTEX, type RainCurtain, type RainCurtainOptions, SKY_DAY, SKY_NIGHT, SPLASH_FROM_MM, type Sky, type ThreeLib, type Vec3, WEATHER_LAYERS, type WeatherLayerId, type WeatherProfileName, type WeatherRenderer, type WeatherRendererOptions, type WeatherSource, type WeatherVisualOptions, type WeatherVisualText, ZONE_FOG_DEFAULTS, ZONE_LIGHT, type ZoneFog, createFog, createHeadlights, createHeatHaze, createLightning, createNearRain, createRainCurtain, createSky, createWeatherRenderer, createWeatherVisual, defaultHeadlightRule, densityForFar, emitAirborne, fogOf, rainCurtainPositions, weatherVisualTextOf };
|