@aethervtt/shard-render 0.0.1
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 +3 -0
- package/dist/assets.d.ts +104 -0
- package/dist/assets.js +213 -0
- package/dist/atmosphere-model.d.ts +96 -0
- package/dist/atmosphere-model.js +370 -0
- package/dist/atmosphere-nodes.d.ts +55 -0
- package/dist/atmosphere-nodes.js +780 -0
- package/dist/atmosphere-plugin.d.ts +5 -0
- package/dist/atmosphere-plugin.js +42 -0
- package/dist/atmosphere-shaders.d.ts +7 -0
- package/dist/atmosphere-shaders.js +595 -0
- package/dist/atmosphere-state.d.ts +72 -0
- package/dist/atmosphere-state.js +18 -0
- package/dist/atmosphere.d.ts +191 -0
- package/dist/atmosphere.js +950 -0
- package/dist/camera.d.ts +83 -0
- package/dist/camera.js +163 -0
- package/dist/clusters.d.ts +68 -0
- package/dist/clusters.js +288 -0
- package/dist/culling-shaders.d.ts +2 -0
- package/dist/culling-shaders.js +203 -0
- package/dist/culling.d.ts +84 -0
- package/dist/culling.js +498 -0
- package/dist/debug-shaders.d.ts +3 -0
- package/dist/debug-shaders.js +207 -0
- package/dist/debug-views.d.ts +60 -0
- package/dist/debug-views.js +197 -0
- package/dist/deferred-plugin.d.ts +5 -0
- package/dist/deferred-plugin.js +20 -0
- package/dist/deferred-shaders.d.ts +2 -0
- package/dist/deferred-shaders.js +151 -0
- package/dist/deferred.d.ts +22 -0
- package/dist/deferred.js +296 -0
- package/dist/deform.d.ts +80 -0
- package/dist/deform.js +213 -0
- package/dist/describe-plugin.d.ts +5 -0
- package/dist/describe-plugin.js +19 -0
- package/dist/display-nodes.d.ts +5 -0
- package/dist/display-nodes.js +189 -0
- package/dist/dynamic-resolution.d.ts +47 -0
- package/dist/dynamic-resolution.js +191 -0
- package/dist/environment-plugin.d.ts +6 -0
- package/dist/environment-plugin.js +44 -0
- package/dist/environment-shaders.d.ts +2 -0
- package/dist/environment-shaders.js +260 -0
- package/dist/environment-state.d.ts +71 -0
- package/dist/environment-state.js +144 -0
- package/dist/environment.d.ts +70 -0
- package/dist/environment.js +529 -0
- package/dist/forward.d.ts +123 -0
- package/dist/forward.js +1216 -0
- package/dist/fxaa.d.ts +2 -0
- package/dist/fxaa.js +65 -0
- package/dist/gizmo-font.d.ts +21 -0
- package/dist/gizmo-font.js +132 -0
- package/dist/gizmos-plugin.d.ts +5 -0
- package/dist/gizmos-plugin.js +34 -0
- package/dist/gizmos.d.ts +156 -0
- package/dist/gizmos.js +772 -0
- package/dist/gpu-assets.d.ts +114 -0
- package/dist/gpu-assets.js +494 -0
- package/dist/graph.d.ts +204 -0
- package/dist/graph.js +417 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.js +540 -0
- package/dist/instances.d.ts +349 -0
- package/dist/instances.js +1335 -0
- package/dist/large-world.d.ts +13 -0
- package/dist/large-world.js +20 -0
- package/dist/lights.d.ts +160 -0
- package/dist/lights.js +468 -0
- package/dist/material-noise.d.ts +19 -0
- package/dist/material-noise.js +7 -0
- package/dist/material-pipelines.d.ts +46 -0
- package/dist/material-pipelines.js +166 -0
- package/dist/materials.d.ts +108 -0
- package/dist/materials.js +219 -0
- package/dist/noise.d.ts +76 -0
- package/dist/noise.js +286 -0
- package/dist/overlay-registry.d.ts +18 -0
- package/dist/overlay-registry.js +30 -0
- package/dist/overlays.d.ts +35 -0
- package/dist/overlays.js +344 -0
- package/dist/paths.d.ts +20 -0
- package/dist/paths.js +46 -0
- package/dist/picking-plugin.d.ts +2 -0
- package/dist/picking-plugin.js +20 -0
- package/dist/picking.d.ts +94 -0
- package/dist/picking.js +456 -0
- package/dist/pixel-perfect-plugin.d.ts +9 -0
- package/dist/pixel-perfect-plugin.js +135 -0
- package/dist/pixel-perfect.d.ts +27 -0
- package/dist/pixel-perfect.js +70 -0
- package/dist/plugin.d.ts +111 -0
- package/dist/plugin.js +182 -0
- package/dist/pool.d.ts +19 -0
- package/dist/pool.js +43 -0
- package/dist/post-common.d.ts +51 -0
- package/dist/post-common.js +148 -0
- package/dist/post-nodes.d.ts +39 -0
- package/dist/post-nodes.js +849 -0
- package/dist/post-plugin.d.ts +5 -0
- package/dist/post-plugin.js +26 -0
- package/dist/post-shaders.d.ts +8 -0
- package/dist/post-shaders.js +698 -0
- package/dist/post.d.ts +175 -0
- package/dist/post.js +453 -0
- package/dist/readback.d.ts +4 -0
- package/dist/readback.js +95 -0
- package/dist/render-scale.d.ts +53 -0
- package/dist/render-scale.js +63 -0
- package/dist/shaders.d.ts +122 -0
- package/dist/shaders.js +1168 -0
- package/dist/shadows.d.ts +119 -0
- package/dist/shadows.js +562 -0
- package/dist/skin-asset.d.ts +26 -0
- package/dist/skin-asset.js +25 -0
- package/dist/skinning-plugin.d.ts +5 -0
- package/dist/skinning-plugin.js +16 -0
- package/dist/skinning.d.ts +19 -0
- package/dist/skinning.js +343 -0
- package/dist/standard-fields.d.ts +67 -0
- package/dist/standard-fields.js +73 -0
- package/dist/standard.d.ts +7 -0
- package/dist/standard.js +37 -0
- package/dist/stats.d.ts +25 -0
- package/dist/stats.js +18 -0
- package/dist/target.d.ts +55 -0
- package/dist/target.js +70 -0
- package/dist/testing.d.ts +34 -0
- package/dist/testing.js +126 -0
- package/dist/timer.d.ts +28 -0
- package/dist/timer.js +136 -0
- package/dist/view.d.ts +117 -0
- package/dist/view.js +389 -0
- package/dist/visibility.d.ts +10 -0
- package/dist/visibility.js +84 -0
- package/package.json +49 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
function createModel() {
|
|
2
|
+
return {
|
|
3
|
+
bottom: 6360,
|
|
4
|
+
top: 6420,
|
|
5
|
+
ground: 6360,
|
|
6
|
+
rayleigh: new Float64Array(3),
|
|
7
|
+
rayleighInvScale: 1 / 8,
|
|
8
|
+
mieScattering: 0,
|
|
9
|
+
mieAbsorption: 0,
|
|
10
|
+
mieInvScale: 1 / 1.2,
|
|
11
|
+
mieG: new Float64Array(3),
|
|
12
|
+
absorption: new Float64Array(3),
|
|
13
|
+
absorptionCenter: 25,
|
|
14
|
+
absorptionWidth: 30,
|
|
15
|
+
albedo: new Float64Array(3),
|
|
16
|
+
intensity: 1
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const TRANSMITTANCE_W = 256;
|
|
20
|
+
const TRANSMITTANCE_H = 64;
|
|
21
|
+
const MULTISCATTER_SIZE = 32;
|
|
22
|
+
const TRANSMITTANCE_STEPS = 40;
|
|
23
|
+
const MS_STEPS = 20;
|
|
24
|
+
const MS_DIRS = 8;
|
|
25
|
+
function createMedium() {
|
|
26
|
+
return {
|
|
27
|
+
rayleigh: new Float64Array(3),
|
|
28
|
+
mie: 0,
|
|
29
|
+
scattering: new Float64Array(3),
|
|
30
|
+
extinction: new Float64Array(3)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function mediumAt(m, h, out) {
|
|
34
|
+
const hc = Math.max(h, m.ground - m.bottom);
|
|
35
|
+
const dr = Math.exp(-hc * m.rayleighInvScale);
|
|
36
|
+
const dm = Math.exp(-hc * m.mieInvScale);
|
|
37
|
+
const da = Math.max(0, 1 - Math.abs(hc - m.absorptionCenter) / (0.5 * m.absorptionWidth));
|
|
38
|
+
const mieS = m.mieScattering * dm;
|
|
39
|
+
const mieE = mieS + m.mieAbsorption * dm;
|
|
40
|
+
out.mie = mieS;
|
|
41
|
+
for (let c = 0; c < 3; c++) {
|
|
42
|
+
const r = m.rayleigh[c] * dr;
|
|
43
|
+
out.rayleigh[c] = r;
|
|
44
|
+
out.scattering[c] = r + mieS;
|
|
45
|
+
out.extinction[c] = r + mieE + m.absorption[c] * da;
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
function raySphere(ox, oy, oz, dx, dy, dz, r, out) {
|
|
50
|
+
const b = ox * dx + oy * dy + oz * dz;
|
|
51
|
+
const c = ox * ox + oy * oy + oz * oz - r * r;
|
|
52
|
+
const disc = b * b - c;
|
|
53
|
+
if (disc < 0) {
|
|
54
|
+
out[0] = Number.NaN;
|
|
55
|
+
out[1] = Number.NaN;
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const s = Math.sqrt(disc);
|
|
59
|
+
out[0] = -b - s;
|
|
60
|
+
out[1] = -b + s;
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
const hit = new Float64Array(2);
|
|
64
|
+
const med = createMedium();
|
|
65
|
+
function transmittanceToTop(m, px, py, pz, dx, dy, dz, out, steps = TRANSMITTANCE_STEPS) {
|
|
66
|
+
if (raySphere(px, py, pz, dx, dy, dz, m.ground, hit) && hit[0] > 0) {
|
|
67
|
+
out[0] = out[1] = out[2] = 0;
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
if (!raySphere(px, py, pz, dx, dy, dz, m.top, hit) || hit[1] <= 0) {
|
|
71
|
+
out[0] = out[1] = out[2] = 1;
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
const t0 = Math.max(0, hit[0]);
|
|
75
|
+
const dt = (hit[1] - t0) / steps;
|
|
76
|
+
let tr = 0;
|
|
77
|
+
let tg = 0;
|
|
78
|
+
let tb = 0;
|
|
79
|
+
for (let i = 0; i < steps; i++) {
|
|
80
|
+
const t = t0 + (i + 0.5) * dt;
|
|
81
|
+
const x = px + dx * t;
|
|
82
|
+
const y = py + dy * t;
|
|
83
|
+
const z = pz + dz * t;
|
|
84
|
+
mediumAt(m, Math.sqrt(x * x + y * y + z * z) - m.bottom, med);
|
|
85
|
+
tr += med.extinction[0] * dt;
|
|
86
|
+
tg += med.extinction[1] * dt;
|
|
87
|
+
tb += med.extinction[2] * dt;
|
|
88
|
+
}
|
|
89
|
+
out[0] = Math.exp(-tr);
|
|
90
|
+
out[1] = Math.exp(-tg);
|
|
91
|
+
out[2] = Math.exp(-tb);
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
function transmittanceUnit(m, r, mu, out) {
|
|
95
|
+
const rb = m.ground;
|
|
96
|
+
const rt = m.top;
|
|
97
|
+
const H = Math.sqrt(Math.max(0, rt * rt - rb * rb));
|
|
98
|
+
const rho = Math.sqrt(Math.max(0, r * r - rb * rb));
|
|
99
|
+
const disc = r * r * (mu * mu - 1) + rt * rt;
|
|
100
|
+
const d = Math.max(0, -r * mu + Math.sqrt(Math.max(disc, 0)));
|
|
101
|
+
const dMin = rt - r;
|
|
102
|
+
const dMax = rho + H;
|
|
103
|
+
out[0] = dMax > dMin ? (d - dMin) / (dMax - dMin) : 0;
|
|
104
|
+
out[1] = H > 0 ? rho / H : 0;
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
function transmittanceRMu(m, xMu, xR, out) {
|
|
108
|
+
const rb = m.ground;
|
|
109
|
+
const rt = m.top;
|
|
110
|
+
const H = Math.sqrt(Math.max(0, rt * rt - rb * rb));
|
|
111
|
+
const rho = H * xR;
|
|
112
|
+
const r = Math.sqrt(rho * rho + rb * rb);
|
|
113
|
+
const dMin = rt - r;
|
|
114
|
+
const dMax = rho + H;
|
|
115
|
+
const d = dMin + xMu * (dMax - dMin);
|
|
116
|
+
const mu = d === 0 ? 1 : (H * H - rho * rho - d * d) / (2 * r * d);
|
|
117
|
+
out[0] = r;
|
|
118
|
+
out[1] = Math.min(1, Math.max(-1, mu));
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
function sampleLut(lut, x, y, out) {
|
|
122
|
+
const fx = Math.min(1, Math.max(0, x)) * (lut.width - 1);
|
|
123
|
+
const fy = Math.min(1, Math.max(0, y)) * (lut.height - 1);
|
|
124
|
+
const x0 = Math.min(lut.width - 2, Math.floor(fx));
|
|
125
|
+
const y0 = Math.min(lut.height - 2, Math.floor(fy));
|
|
126
|
+
const ax = fx - x0;
|
|
127
|
+
const ay = fy - y0;
|
|
128
|
+
const d = lut.data;
|
|
129
|
+
const w = lut.width;
|
|
130
|
+
for (let c = 0; c < 3; c++) {
|
|
131
|
+
const a = d[(y0 * w + x0) * 3 + c];
|
|
132
|
+
const b = d[(y0 * w + x0 + 1) * 3 + c];
|
|
133
|
+
const e = d[((y0 + 1) * w + x0) * 3 + c];
|
|
134
|
+
const f = d[((y0 + 1) * w + x0 + 1) * 3 + c];
|
|
135
|
+
out[c] = (a * (1 - ax) + b * ax) * (1 - ay) + (e * (1 - ax) + f * ax) * ay;
|
|
136
|
+
}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
const unit = new Float64Array(2);
|
|
140
|
+
const rmu = new Float64Array(2);
|
|
141
|
+
const t3 = new Float64Array(3);
|
|
142
|
+
function transmittanceLut(m) {
|
|
143
|
+
const w = TRANSMITTANCE_W;
|
|
144
|
+
const h = TRANSMITTANCE_H;
|
|
145
|
+
const data = new Float32Array(w * h * 3);
|
|
146
|
+
for (let j = 0; j < h; j++) {
|
|
147
|
+
for (let i = 0; i < w; i++) {
|
|
148
|
+
transmittanceRMu(m, i / (w - 1), j / (h - 1), rmu);
|
|
149
|
+
const r = rmu[0];
|
|
150
|
+
const mu = rmu[1];
|
|
151
|
+
transmittanceToTop(m, 0, r, 0, Math.sqrt(Math.max(0, 1 - mu * mu)), mu, 0, t3);
|
|
152
|
+
data.set(t3, (j * w + i) * 3);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return { width: w, height: h, data };
|
|
156
|
+
}
|
|
157
|
+
function lookupTransmittance(m, lut, r, mu, out) {
|
|
158
|
+
transmittanceUnit(m, r, mu, unit);
|
|
159
|
+
return sampleLut(lut, unit[0], unit[1], out);
|
|
160
|
+
}
|
|
161
|
+
function sunTransmittance(m, lut, x, y, z, sx, sy, sz, out) {
|
|
162
|
+
if (raySphere(x, y, z, sx, sy, sz, m.ground, hit) && hit[0] > 0) {
|
|
163
|
+
out[0] = out[1] = out[2] = 0;
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
const r = Math.sqrt(x * x + y * y + z * z);
|
|
167
|
+
return lookupTransmittance(m, lut, r, (x * sx + y * sy + z * sz) / r, out);
|
|
168
|
+
}
|
|
169
|
+
const sunT = new Float64Array(3);
|
|
170
|
+
const msAcc = new Float64Array(6);
|
|
171
|
+
function multiscatterLut(m, tlut) {
|
|
172
|
+
const n = MULTISCATTER_SIZE;
|
|
173
|
+
const data = new Float32Array(n * n * 3);
|
|
174
|
+
const isotropic = 1 / (4 * Math.PI);
|
|
175
|
+
for (let j = 0; j < n; j++) {
|
|
176
|
+
const r = m.ground + j / (n - 1) * (m.top - m.ground);
|
|
177
|
+
const rr = Math.max(r, m.ground + 1e-3);
|
|
178
|
+
for (let i = 0; i < n; i++) {
|
|
179
|
+
const cs = i / (n - 1) * 2 - 1;
|
|
180
|
+
const sx = 0;
|
|
181
|
+
const sy = cs;
|
|
182
|
+
const sz = Math.sqrt(Math.max(0, 1 - cs * cs));
|
|
183
|
+
msAcc.fill(0);
|
|
184
|
+
for (let a = 0; a < MS_DIRS; a++) {
|
|
185
|
+
for (let b = 0; b < MS_DIRS; b++) {
|
|
186
|
+
const ct = 1 - 2 * (a + 0.5) / MS_DIRS;
|
|
187
|
+
const st = Math.sqrt(Math.max(0, 1 - ct * ct));
|
|
188
|
+
const phi = 2 * Math.PI * (b + 0.5) / MS_DIRS;
|
|
189
|
+
const dx = st * Math.cos(phi);
|
|
190
|
+
const dy = ct;
|
|
191
|
+
const dz = st * Math.sin(phi);
|
|
192
|
+
const hitsGround = raySphere(0, rr, 0, dx, dy, dz, m.ground, hit) && hit[0] > 0;
|
|
193
|
+
const tGround = hit[0];
|
|
194
|
+
raySphere(0, rr, 0, dx, dy, dz, m.top, hit);
|
|
195
|
+
const tMax = hitsGround ? tGround : hit[1];
|
|
196
|
+
const dt = tMax / MS_STEPS;
|
|
197
|
+
let thr = 1;
|
|
198
|
+
let thg = 1;
|
|
199
|
+
let thb = 1;
|
|
200
|
+
for (let k = 0; k < MS_STEPS; k++) {
|
|
201
|
+
const t = (k + 0.5) * dt;
|
|
202
|
+
const x = dx * t;
|
|
203
|
+
const y = rr + dy * t;
|
|
204
|
+
const z = dz * t;
|
|
205
|
+
mediumAt(m, Math.sqrt(x * x + y * y + z * z) - m.bottom, med);
|
|
206
|
+
sunTransmittance(m, tlut, x, y, z, sx, sy, sz, sunT);
|
|
207
|
+
for (let c = 0; c < 3; c++) {
|
|
208
|
+
const ext = Math.max(med.extinction[c], 1e-9);
|
|
209
|
+
const stepT = Math.exp(-ext * dt);
|
|
210
|
+
const sc = med.scattering[c];
|
|
211
|
+
const th = c === 0 ? thr : c === 1 ? thg : thb;
|
|
212
|
+
msAcc[c] = msAcc[c] + th * (sunT[c] * sc * isotropic * (1 - stepT)) / ext;
|
|
213
|
+
msAcc[3 + c] = msAcc[3 + c] + th * (sc * (1 - stepT)) / ext;
|
|
214
|
+
if (c === 0) thr *= stepT;
|
|
215
|
+
else if (c === 1) thg *= stepT;
|
|
216
|
+
else thb *= stepT;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (hitsGround) {
|
|
220
|
+
const x = dx * tMax;
|
|
221
|
+
const y = rr + dy * tMax;
|
|
222
|
+
const z = dz * tMax;
|
|
223
|
+
const len = Math.sqrt(x * x + y * y + z * z);
|
|
224
|
+
const ndl = Math.max(0, (x * sx + y * sy + z * sz) / len);
|
|
225
|
+
sunTransmittance(m, tlut, x * 1.00001, y * 1.00001, z * 1.00001, sx, sy, sz, sunT);
|
|
226
|
+
msAcc[0] = msAcc[0] + thr * sunT[0] * ndl * m.albedo[0] / Math.PI;
|
|
227
|
+
msAcc[1] = msAcc[1] + thg * sunT[1] * ndl * m.albedo[1] / Math.PI;
|
|
228
|
+
msAcc[2] = msAcc[2] + thb * sunT[2] * ndl * m.albedo[2] / Math.PI;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const count = MS_DIRS * MS_DIRS;
|
|
233
|
+
for (let c = 0; c < 3; c++) {
|
|
234
|
+
const l2 = msAcc[c] / count;
|
|
235
|
+
const fms = msAcc[3 + c] / count;
|
|
236
|
+
data[(j * n + i) * 3 + c] = l2 / Math.max(1 - fms, 1e-4);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return { width: n, height: n, data };
|
|
241
|
+
}
|
|
242
|
+
function lookupMultiscatter(m, lut, r, cs, out) {
|
|
243
|
+
return sampleLut(lut, cs * 0.5 + 0.5, (r - m.ground) / (m.top - m.ground), out);
|
|
244
|
+
}
|
|
245
|
+
const rayleighPhase = (mu) => 3 / (16 * Math.PI) * (1 + mu * mu);
|
|
246
|
+
function miePhase(mu, g) {
|
|
247
|
+
const g2 = g * g;
|
|
248
|
+
return 3 / (8 * Math.PI) * ((1 - g2) * (1 + mu * mu)) / ((2 + g2) * (1 + g2 - 2 * g * mu) ** 1.5);
|
|
249
|
+
}
|
|
250
|
+
function createSkySample() {
|
|
251
|
+
return {
|
|
252
|
+
radiance: new Float64Array(3),
|
|
253
|
+
transmittance: new Float64Array(3),
|
|
254
|
+
hitsGround: false,
|
|
255
|
+
length: 0
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
const ms3 = new Float64Array(3);
|
|
259
|
+
function integrateSky(m, tlut, mslut, p, d, suns, out, steps = 32, maxT = Number.POSITIVE_INFINITY) {
|
|
260
|
+
const px = p[0];
|
|
261
|
+
const py = p[1];
|
|
262
|
+
const pz = p[2];
|
|
263
|
+
const dx = d[0];
|
|
264
|
+
const dy = d[1];
|
|
265
|
+
const dz = d[2];
|
|
266
|
+
out.radiance.fill(0);
|
|
267
|
+
out.transmittance.fill(1);
|
|
268
|
+
out.hitsGround = false;
|
|
269
|
+
out.length = 0;
|
|
270
|
+
if (!raySphere(px, py, pz, dx, dy, dz, m.top, hit) || hit[1] <= 0) return out;
|
|
271
|
+
const t0 = Math.max(0, hit[0]);
|
|
272
|
+
let t1 = hit[1];
|
|
273
|
+
let ground = false;
|
|
274
|
+
if (raySphere(px, py, pz, dx, dy, dz, m.ground, hit) && hit[0] > 0 && hit[0] < t1) {
|
|
275
|
+
t1 = hit[0];
|
|
276
|
+
ground = true;
|
|
277
|
+
}
|
|
278
|
+
if (maxT < t1) {
|
|
279
|
+
t1 = maxT;
|
|
280
|
+
ground = false;
|
|
281
|
+
}
|
|
282
|
+
if (t1 <= t0) return out;
|
|
283
|
+
out.length = t1 - t0;
|
|
284
|
+
const T = out.transmittance;
|
|
285
|
+
const L = out.radiance;
|
|
286
|
+
const fromSpace = t0 > 0;
|
|
287
|
+
const bunch = (s) => fromSpace ? 1 - (1 - s) * (1 - s) : s * s;
|
|
288
|
+
for (let k = 0; k < steps; k++) {
|
|
289
|
+
const a = t0 + (t1 - t0) * bunch(k / steps);
|
|
290
|
+
const b = t0 + (t1 - t0) * bunch((k + 1) / steps);
|
|
291
|
+
const t = t0 + (t1 - t0) * bunch((k + 0.5) / steps);
|
|
292
|
+
const dt = b - a;
|
|
293
|
+
const x = px + dx * t;
|
|
294
|
+
const y = py + dy * t;
|
|
295
|
+
const z = pz + dz * t;
|
|
296
|
+
const r = Math.sqrt(x * x + y * y + z * z);
|
|
297
|
+
mediumAt(m, r - m.bottom, med);
|
|
298
|
+
for (let c = 0; c < 3; c++) ms3[c] = 0;
|
|
299
|
+
let sr = 0;
|
|
300
|
+
let sg = 0;
|
|
301
|
+
let sb = 0;
|
|
302
|
+
for (const sun of suns) {
|
|
303
|
+
const sx = sun.direction[0];
|
|
304
|
+
const sy = sun.direction[1];
|
|
305
|
+
const sz = sun.direction[2];
|
|
306
|
+
const mu = dx * sx + dy * sy + dz * sz;
|
|
307
|
+
const pr = rayleighPhase(mu);
|
|
308
|
+
sunTransmittance(m, tlut, x, y, z, sx, sy, sz, sunT);
|
|
309
|
+
lookupMultiscatter(m, mslut, r, (x * sx + y * sy + z * sz) / r, ms3);
|
|
310
|
+
for (let c = 0; c < 3; c++) {
|
|
311
|
+
const e = sun.illuminance[c];
|
|
312
|
+
const single = (med.rayleigh[c] * pr + med.mie * miePhase(mu, m.mieG[c])) * sunT[c] + ms3[c] * med.scattering[c];
|
|
313
|
+
const v = single * e;
|
|
314
|
+
if (c === 0) sr += v;
|
|
315
|
+
else if (c === 1) sg += v;
|
|
316
|
+
else sb += v;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
for (let c = 0; c < 3; c++) {
|
|
320
|
+
const ext = Math.max(med.extinction[c], 1e-9);
|
|
321
|
+
const stepT = Math.exp(-ext * dt);
|
|
322
|
+
const S = c === 0 ? sr : c === 1 ? sg : sb;
|
|
323
|
+
L[c] = L[c] + T[c] * S * (1 - stepT) / ext;
|
|
324
|
+
T[c] = T[c] * stepT;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (ground) {
|
|
328
|
+
out.hitsGround = true;
|
|
329
|
+
const x = px + dx * t1;
|
|
330
|
+
const y = py + dy * t1;
|
|
331
|
+
const z = pz + dz * t1;
|
|
332
|
+
const len = Math.sqrt(x * x + y * y + z * z);
|
|
333
|
+
for (const sun of suns) {
|
|
334
|
+
const sx = sun.direction[0];
|
|
335
|
+
const sy = sun.direction[1];
|
|
336
|
+
const sz = sun.direction[2];
|
|
337
|
+
const ndl = Math.max(0, (x * sx + y * sy + z * sz) / len);
|
|
338
|
+
if (ndl <= 0) continue;
|
|
339
|
+
const k = 1.00001;
|
|
340
|
+
sunTransmittance(m, tlut, x * k, y * k, z * k, sx, sy, sz, sunT);
|
|
341
|
+
for (let c = 0; c < 3; c++) {
|
|
342
|
+
L[c] = L[c] + T[c] * sun.illuminance[c] * sunT[c] * ndl * m.albedo[c] / Math.PI;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
T.fill(0);
|
|
346
|
+
}
|
|
347
|
+
for (let c = 0; c < 3; c++) L[c] = L[c] * m.intensity;
|
|
348
|
+
return out;
|
|
349
|
+
}
|
|
350
|
+
export {
|
|
351
|
+
MULTISCATTER_SIZE,
|
|
352
|
+
TRANSMITTANCE_H,
|
|
353
|
+
TRANSMITTANCE_STEPS,
|
|
354
|
+
TRANSMITTANCE_W,
|
|
355
|
+
createMedium,
|
|
356
|
+
createModel,
|
|
357
|
+
createSkySample,
|
|
358
|
+
integrateSky,
|
|
359
|
+
lookupMultiscatter,
|
|
360
|
+
lookupTransmittance,
|
|
361
|
+
mediumAt,
|
|
362
|
+
miePhase,
|
|
363
|
+
multiscatterLut,
|
|
364
|
+
raySphere,
|
|
365
|
+
rayleighPhase,
|
|
366
|
+
transmittanceLut,
|
|
367
|
+
transmittanceRMu,
|
|
368
|
+
transmittanceToTop,
|
|
369
|
+
transmittanceUnit
|
|
370
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type Entity, type World } from '@aethervtt/shard-core';
|
|
2
|
+
import { GpuBuffer, type GpuContext } from '@aethervtt/shard-gpu';
|
|
3
|
+
import { type AtmosphereRecord } from './atmosphere.js';
|
|
4
|
+
/** Atmospheres whose LUTs stay on the GPU at once (layers of the LUT arrays). */
|
|
5
|
+
export declare const LUT_LAYERS = 8;
|
|
6
|
+
/** Per camera: its uniform, sky-view LUT, and aerial-perspective froxels. */
|
|
7
|
+
interface CameraGpu {
|
|
8
|
+
uniform: GpuBuffer;
|
|
9
|
+
data: Float32Array;
|
|
10
|
+
skyView: GPUTexture | undefined;
|
|
11
|
+
scatter: GPUTexture | undefined;
|
|
12
|
+
transmittance: GPUTexture | undefined;
|
|
13
|
+
/** The frame the sky-view and froxels were last computed. */
|
|
14
|
+
computed: number;
|
|
15
|
+
generation: number;
|
|
16
|
+
seen: number;
|
|
17
|
+
}
|
|
18
|
+
export declare class AtmosphereGpu {
|
|
19
|
+
generation: number;
|
|
20
|
+
transmittance: GPUTexture;
|
|
21
|
+
multiscatter: GPUTexture;
|
|
22
|
+
transmittanceArray: GPUTextureView;
|
|
23
|
+
multiscatterArray: GPUTextureView;
|
|
24
|
+
clamp: GPUSampler;
|
|
25
|
+
repeat: GPUSampler;
|
|
26
|
+
/** The record in each layer, and the frame it was last listed. */
|
|
27
|
+
readonly owners: (AtmosphereRecord | undefined)[];
|
|
28
|
+
readonly used: Int32Array<ArrayBuffer>;
|
|
29
|
+
readonly params: GpuBuffer[];
|
|
30
|
+
readonly cameras: Map<number, CameraGpu>;
|
|
31
|
+
/** LUT recomputations so far (describe, and tests that nothing recomputes per frame). */
|
|
32
|
+
lutComputes: number;
|
|
33
|
+
lutFrame: number;
|
|
34
|
+
frame: number;
|
|
35
|
+
readonly pipelines: Map<string, GPUComputePipeline | GPURenderPipeline>;
|
|
36
|
+
layouts: Record<string, GPUBindGroupLayout> | undefined;
|
|
37
|
+
private readonly groups;
|
|
38
|
+
ensure(gpu: GpuContext): void;
|
|
39
|
+
/** A layer for a record: its own, a free one, or the least recently used. */
|
|
40
|
+
assign(rec: AtmosphereRecord): void;
|
|
41
|
+
camera(gpu: GpuContext, entity: Entity): CameraGpu;
|
|
42
|
+
group(gpu: GpuContext, slot: string, key: string, layout: GPUBindGroupLayout, entries: () => GPUBindGroupEntry[]): GPUBindGroup;
|
|
43
|
+
}
|
|
44
|
+
export declare const AtmosphereGpuResource: import("@aethervtt/shard-core").ResourceDef<AtmosphereGpu>;
|
|
45
|
+
/**
|
|
46
|
+
* Gives every listed atmosphere a LUT layer and uploads each camera's AtmosphereView uniform, and
|
|
47
|
+
* its sky-view and froxel textures at the right sizes.
|
|
48
|
+
*/
|
|
49
|
+
export declare const uploadAtmospheres: import("@aethervtt/shard-core").SystemDef<undefined>;
|
|
50
|
+
/**
|
|
51
|
+
* The LUT pass and per-view sky-view/froxel pass (registered before the environment prefilter,
|
|
52
|
+
* which bakes atmospheres into IBL), the sky pass, and the aerial-perspective composite.
|
|
53
|
+
*/
|
|
54
|
+
export declare function addAtmosphereNodes(world: World): void;
|
|
55
|
+
export {};
|