@tinypoly/gpu-renderer 0.0.0-stage → 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/ARCHITECTURE.md +339 -0
- package/LICENSE +21 -0
- package/README.md +284 -2
- package/dist/accumulator.d.ts +27 -0
- package/dist/accumulator.d.ts.map +1 -0
- package/dist/accumulator.js +57 -0
- package/dist/accumulator.js.map +1 -0
- package/dist/bvh.d.ts +26 -0
- package/dist/bvh.d.ts.map +1 -0
- package/dist/bvh.js +296 -0
- package/dist/bvh.js.map +1 -0
- package/dist/bvhBuilder.d.ts +72 -0
- package/dist/bvhBuilder.d.ts.map +1 -0
- package/dist/bvhBuilder.js +126 -0
- package/dist/bvhBuilder.js.map +1 -0
- package/dist/bvhWorker.d.ts +2 -0
- package/dist/bvhWorker.d.ts.map +1 -0
- package/dist/bvhWorker.js +8 -0
- package/dist/bvhWorker.js.map +1 -0
- package/dist/camera.d.ts +29 -0
- package/dist/camera.d.ts.map +1 -0
- package/dist/camera.js +48 -0
- package/dist/camera.js.map +1 -0
- package/dist/canvas.d.ts +9 -0
- package/dist/canvas.d.ts.map +1 -0
- package/dist/canvas.js +11 -0
- package/dist/canvas.js.map +1 -0
- package/dist/denoise.d.ts +69 -0
- package/dist/denoise.d.ts.map +1 -0
- package/dist/denoise.js +455 -0
- package/dist/denoise.js.map +1 -0
- package/dist/device.d.ts +37 -0
- package/dist/device.d.ts.map +1 -0
- package/dist/device.js +52 -0
- package/dist/device.js.map +1 -0
- package/dist/dispatchScheduler.d.ts +43 -0
- package/dist/dispatchScheduler.d.ts.map +1 -0
- package/dist/dispatchScheduler.js +49 -0
- package/dist/dispatchScheduler.js.map +1 -0
- package/dist/environment.d.ts +39 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +168 -0
- package/dist/environment.js.map +1 -0
- package/dist/frameLayout.d.ts +4 -0
- package/dist/frameLayout.d.ts.map +1 -0
- package/dist/frameLayout.js +58 -0
- package/dist/frameLayout.js.map +1 -0
- package/dist/geometry.d.ts +75 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +799 -0
- package/dist/geometry.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/lights.d.ts +64 -0
- package/dist/lights.d.ts.map +1 -0
- package/dist/lights.js +264 -0
- package/dist/lights.js.map +1 -0
- package/dist/materialLayout.d.ts +143 -0
- package/dist/materialLayout.d.ts.map +1 -0
- package/dist/materialLayout.js +297 -0
- package/dist/materialLayout.js.map +1 -0
- package/dist/math.d.ts +10 -0
- package/dist/math.d.ts.map +1 -0
- package/dist/math.js +40 -0
- package/dist/math.js.map +1 -0
- package/dist/pathTracePass.d.ts +27 -0
- package/dist/pathTracePass.d.ts.map +1 -0
- package/dist/pathTracePass.js +83 -0
- package/dist/pathTracePass.js.map +1 -0
- package/dist/planarCapture.d.ts +38 -0
- package/dist/planarCapture.d.ts.map +1 -0
- package/dist/planarCapture.js +163 -0
- package/dist/planarCapture.js.map +1 -0
- package/dist/presentPass.d.ts +31 -0
- package/dist/presentPass.d.ts.map +1 -0
- package/dist/presentPass.js +78 -0
- package/dist/presentPass.js.map +1 -0
- package/dist/renderer.d.ts +209 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +847 -0
- package/dist/renderer.js.map +1 -0
- package/dist/sceneAssets.d.ts +24 -0
- package/dist/sceneAssets.d.ts.map +1 -0
- package/dist/sceneAssets.js +77 -0
- package/dist/sceneAssets.js.map +1 -0
- package/dist/sceneUpload.d.ts +61 -0
- package/dist/sceneUpload.d.ts.map +1 -0
- package/dist/sceneUpload.js +98 -0
- package/dist/sceneUpload.js.map +1 -0
- package/dist/shaderModule.d.ts +7 -0
- package/dist/shaderModule.d.ts.map +1 -0
- package/dist/shaderModule.js +19 -0
- package/dist/shaderModule.js.map +1 -0
- package/dist/shaderProgram.d.ts +124 -0
- package/dist/shaderProgram.d.ts.map +1 -0
- package/dist/shaderProgram.js +1030 -0
- package/dist/shaderProgram.js.map +1 -0
- package/dist/structLayout.d.ts +28 -0
- package/dist/structLayout.d.ts.map +1 -0
- package/dist/structLayout.js +58 -0
- package/dist/structLayout.js.map +1 -0
- package/dist/texturePack.d.ts +54 -0
- package/dist/texturePack.d.ts.map +1 -0
- package/dist/texturePack.js +86 -0
- package/dist/texturePack.js.map +1 -0
- package/dist/upstream.d.ts +7 -0
- package/dist/upstream.d.ts.map +1 -0
- package/dist/upstream.js +11 -0
- package/dist/upstream.js.map +1 -0
- package/dist/volumetric.d.ts +10 -0
- package/dist/volumetric.d.ts.map +1 -0
- package/dist/volumetric.js +34 -0
- package/dist/volumetric.js.map +1 -0
- package/dist/wgsl/bsdf.wgsl.d.ts +13 -0
- package/dist/wgsl/bsdf.wgsl.d.ts.map +1 -0
- package/dist/wgsl/bsdf.wgsl.js +619 -0
- package/dist/wgsl/bsdf.wgsl.js.map +1 -0
- package/dist/wgsl/bvh.wgsl.d.ts +3 -0
- package/dist/wgsl/bvh.wgsl.d.ts.map +1 -0
- package/dist/wgsl/bvh.wgsl.js +218 -0
- package/dist/wgsl/bvh.wgsl.js.map +1 -0
- package/dist/wgsl/common.wgsl.d.ts +3 -0
- package/dist/wgsl/common.wgsl.d.ts.map +1 -0
- package/dist/wgsl/common.wgsl.js +193 -0
- package/dist/wgsl/common.wgsl.js.map +1 -0
- package/dist/wgsl/environment.wgsl.d.ts +10 -0
- package/dist/wgsl/environment.wgsl.d.ts.map +1 -0
- package/dist/wgsl/environment.wgsl.js +145 -0
- package/dist/wgsl/environment.wgsl.js.map +1 -0
- package/dist/wgsl/lights.wgsl.d.ts +10 -0
- package/dist/wgsl/lights.wgsl.d.ts.map +1 -0
- package/dist/wgsl/lights.wgsl.js +434 -0
- package/dist/wgsl/lights.wgsl.js.map +1 -0
- package/dist/wgsl/pathTrace.wgsl.d.ts +14 -0
- package/dist/wgsl/pathTrace.wgsl.d.ts.map +1 -0
- package/dist/wgsl/pathTrace.wgsl.js +1020 -0
- package/dist/wgsl/pathTrace.wgsl.js.map +1 -0
- package/dist/wgsl/present.wgsl.d.ts +7 -0
- package/dist/wgsl/present.wgsl.d.ts.map +1 -0
- package/dist/wgsl/present.wgsl.js +154 -0
- package/dist/wgsl/present.wgsl.js.map +1 -0
- package/dist/wgsl/random.wgsl.d.ts +9 -0
- package/dist/wgsl/random.wgsl.d.ts.map +1 -0
- package/dist/wgsl/random.wgsl.js +91 -0
- package/dist/wgsl/random.wgsl.js.map +1 -0
- package/dist/wgsl/sampling.wgsl.d.ts +3 -0
- package/dist/wgsl/sampling.wgsl.d.ts.map +1 -0
- package/dist/wgsl/sampling.wgsl.js +31 -0
- package/dist/wgsl/sampling.wgsl.js.map +1 -0
- package/dist/wgsl/shaderSupport.wgsl.d.ts +6 -0
- package/dist/wgsl/shaderSupport.wgsl.d.ts.map +1 -0
- package/dist/wgsl/shaderSupport.wgsl.js +120 -0
- package/dist/wgsl/shaderSupport.wgsl.js.map +1 -0
- package/dist/wgsl/surface.wgsl.d.ts +10 -0
- package/dist/wgsl/surface.wgsl.d.ts.map +1 -0
- package/dist/wgsl/surface.wgsl.js +794 -0
- package/dist/wgsl/surface.wgsl.js.map +1 -0
- package/dist/wgsl/texture.wgsl.d.ts +11 -0
- package/dist/wgsl/texture.wgsl.d.ts.map +1 -0
- package/dist/wgsl/texture.wgsl.js +132 -0
- package/dist/wgsl/texture.wgsl.js.map +1 -0
- package/package.json +77 -3
- package/src/accumulator.ts +64 -0
- package/src/bvh.ts +336 -0
- package/src/bvhBuilder.ts +178 -0
- package/src/bvhWorker.ts +13 -0
- package/src/camera.ts +77 -0
- package/src/canvas.ts +13 -0
- package/src/denoise.ts +514 -0
- package/src/device.ts +81 -0
- package/src/dispatchScheduler.ts +71 -0
- package/src/environment.ts +233 -0
- package/src/frameLayout.ts +59 -0
- package/src/geometry.ts +1067 -0
- package/src/index.ts +64 -0
- package/src/lights.ts +365 -0
- package/src/materialLayout.ts +408 -0
- package/src/math.ts +48 -0
- package/src/pathTracePass.ts +97 -0
- package/src/planarCapture.ts +225 -0
- package/src/presentPass.ts +99 -0
- package/src/renderer.ts +1145 -0
- package/src/sceneAssets.ts +118 -0
- package/src/sceneUpload.ts +185 -0
- package/src/shaderModule.ts +19 -0
- package/src/shaderProgram.ts +1370 -0
- package/src/structLayout.ts +93 -0
- package/src/texturePack.ts +152 -0
- package/src/upstream.ts +56 -0
- package/src/volumetric.ts +42 -0
- package/src/wgsl/bsdf.wgsl.ts +618 -0
- package/src/wgsl/bvh.wgsl.ts +217 -0
- package/src/wgsl/common.wgsl.ts +193 -0
- package/src/wgsl/environment.wgsl.ts +144 -0
- package/src/wgsl/lights.wgsl.ts +433 -0
- package/src/wgsl/pathTrace.wgsl.ts +1019 -0
- package/src/wgsl/present.wgsl.ts +153 -0
- package/src/wgsl/random.wgsl.ts +90 -0
- package/src/wgsl/sampling.wgsl.ts +30 -0
- package/src/wgsl/shaderSupport.wgsl.ts +119 -0
- package/src/wgsl/surface.wgsl.ts +793 -0
- package/src/wgsl/texture.wgsl.ts +131 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { HDRLoader } from "three/examples/jsm/loaders/HDRLoader.js";
|
|
2
|
+
import type { RenderEnvironment, SerializedTexture } from "./upstream.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The light that surrounds the scene. A gradient is three numbers the shader evaluates directly; an equirectangular
|
|
6
|
+
* image is a texture plus the tables that let a shadow ray aim at its bright parts.
|
|
7
|
+
*
|
|
8
|
+
* Without those tables a sun in an image is exactly the problem direct light sampling exists to solve: a tiny, very
|
|
9
|
+
* bright region that a cosine weighted bounce almost never finds. The construction is the one in `environment.js` of
|
|
10
|
+
* the CPU renderer: a cumulative distribution over rows weighted by luminance and the sine of the colatitude, then one
|
|
11
|
+
* over the columns of each row.
|
|
12
|
+
*/
|
|
13
|
+
export interface PackedEnvironment {
|
|
14
|
+
/** The image itself, ready to join the scene's own textures. */
|
|
15
|
+
texture: SerializedTexture;
|
|
16
|
+
/** Rows, then each row's columns, then the luminance of every texel: `2 * width * height + height` floats. */
|
|
17
|
+
distribution: Float32Array;
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
/** The sum of luminance times the sine of the colatitude, which turns a texel's share into a density. */
|
|
21
|
+
total: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The grid the distribution is built on, as in the CPU renderer. Finer than this buys nothing but memory. */
|
|
25
|
+
const GRID_WIDTH = 256;
|
|
26
|
+
const GRID_HEIGHT = 128;
|
|
27
|
+
|
|
28
|
+
/** How large an image is kept for the sharp lookup. A full resolution sky costs more memory than it adds detail here. */
|
|
29
|
+
const MAX_WIDTH = 1024;
|
|
30
|
+
|
|
31
|
+
const luminance = (r: number, g: number, b: number) => 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
32
|
+
|
|
33
|
+
/** An area averaged reduction to `width` by `height`, which is what the distribution is built from. */
|
|
34
|
+
function reduce(source: Float32Array, sourceWidth: number, sourceHeight: number, width: number, height: number) {
|
|
35
|
+
const target = new Float32Array(width * height * 3);
|
|
36
|
+
const scaleX = sourceWidth / width, scaleY = sourceHeight / height;
|
|
37
|
+
|
|
38
|
+
for (let y = 0; y < height; y++) {
|
|
39
|
+
for (let x = 0; x < width; x++) {
|
|
40
|
+
const x0 = Math.floor(x * scaleX), x1 = Math.max(x0 + 1, Math.ceil((x + 1) * scaleX));
|
|
41
|
+
const y0 = Math.floor(y * scaleY), y1 = Math.max(y0 + 1, Math.ceil((y + 1) * scaleY));
|
|
42
|
+
let r = 0, g = 0, b = 0, n = 0;
|
|
43
|
+
|
|
44
|
+
for (let sy = y0; sy < Math.min(sourceHeight, y1); sy++) {
|
|
45
|
+
for (let sx = x0; sx < Math.min(sourceWidth, x1); sx++) {
|
|
46
|
+
const at = (sy * sourceWidth + sx) * 4;
|
|
47
|
+
|
|
48
|
+
r += source[at];
|
|
49
|
+
g += source[at + 1];
|
|
50
|
+
b += source[at + 2];
|
|
51
|
+
n++;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const at = (y * width + x) * 3;
|
|
56
|
+
const weight = n || 1;
|
|
57
|
+
|
|
58
|
+
target[at] = r / weight;
|
|
59
|
+
target[at + 1] = g / weight;
|
|
60
|
+
target[at + 2] = b / weight;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return target;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Never picked less often than this share of the average, so no direction is left without a density. */
|
|
68
|
+
const FLOOR = 0.02;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The luminance a direction is picked by. It is the neighbourhood's brightest rather than the texel's own, because the
|
|
72
|
+
* image is read back with a bilinear filter: that filter spreads a sun into the texels around it, and a direction the
|
|
73
|
+
* distribution gave no chance of being picked would arrive through the bounce alone, as a firefly. Taking the maximum
|
|
74
|
+
* over the neighbours keeps the density above what the filter can produce there.
|
|
75
|
+
*/
|
|
76
|
+
function weights(grid: Float32Array, width: number, height: number): Float32Array {
|
|
77
|
+
const raw = new Float32Array(width * height);
|
|
78
|
+
const spread = new Float32Array(width * height);
|
|
79
|
+
let sum = 0;
|
|
80
|
+
|
|
81
|
+
for (let index = 0; index < width * height; index++) {
|
|
82
|
+
raw[index] = luminance(grid[index * 3], grid[index * 3 + 1], grid[index * 3 + 2]);
|
|
83
|
+
sum += raw[index];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const floor = sum / (width * height) * FLOOR;
|
|
87
|
+
|
|
88
|
+
for (let y = 0; y < height; y++) {
|
|
89
|
+
for (let x = 0; x < width; x++) {
|
|
90
|
+
let peak = 0;
|
|
91
|
+
|
|
92
|
+
for (let dy = -1; dy <= 1; dy++) {
|
|
93
|
+
const row = Math.min(Math.max(y + dy, 0), height - 1);
|
|
94
|
+
|
|
95
|
+
for (let dx = -1; dx <= 1; dx++) {
|
|
96
|
+
// Longitude wraps around, so the texel left of the first column is the last one.
|
|
97
|
+
peak = Math.max(peak, raw[row * width + (x + dx + width) % width]);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
spread[y * width + x] = peak + floor;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return spread;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Cumulative distributions over the reduced image. A row is weighted by the sine of its colatitude, because a row near
|
|
110
|
+
* a pole covers far less of the sphere than one at the equator.
|
|
111
|
+
*/
|
|
112
|
+
export function environmentDistribution(grid: Float32Array, width: number, height: number) {
|
|
113
|
+
const rows = new Float32Array(height);
|
|
114
|
+
const columns = new Float32Array(width * height);
|
|
115
|
+
const values = weights(grid, width, height);
|
|
116
|
+
let total = 0;
|
|
117
|
+
|
|
118
|
+
for (let y = 0; y < height; y++) {
|
|
119
|
+
const sine = Math.sin((y + 0.5) / height * Math.PI);
|
|
120
|
+
let row = 0;
|
|
121
|
+
|
|
122
|
+
for (let x = 0; x < width; x++) {
|
|
123
|
+
const index = y * width + x;
|
|
124
|
+
|
|
125
|
+
row += values[index] * sine;
|
|
126
|
+
columns[index] = row;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
for (let x = 0; x < width; x++) {
|
|
130
|
+
const index = y * width + x;
|
|
131
|
+
|
|
132
|
+
// A row with nothing in it is still chosen uniformly, so a search over it always terminates somewhere.
|
|
133
|
+
columns[index] = row > 0 ? columns[index] / row : (x + 1) / width;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
total += row;
|
|
137
|
+
rows[y] = total;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!(total > 0)) return null;
|
|
141
|
+
|
|
142
|
+
for (let y = 0; y < height; y++) rows[y] /= total;
|
|
143
|
+
|
|
144
|
+
const distribution = new Float32Array(height + width * height * 2);
|
|
145
|
+
|
|
146
|
+
distribution.set(rows, 0);
|
|
147
|
+
distribution.set(columns, height);
|
|
148
|
+
distribution.set(values, height + width * height);
|
|
149
|
+
|
|
150
|
+
return { distribution, total };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Loads an equirectangular image and builds everything the shader needs from it. Returns null for an environment that
|
|
155
|
+
* is not an image, or one whose file could not be read, which leaves the renderer on its gradient.
|
|
156
|
+
*/
|
|
157
|
+
export async function loadEnvironment(environment: RenderEnvironment): Promise<PackedEnvironment | null> {
|
|
158
|
+
if (environment.kind !== "hdri" || !environment.url) return null;
|
|
159
|
+
|
|
160
|
+
const loaded = await new Promise<{ data: Float32Array; width: number; height: number } | null>(resolve => {
|
|
161
|
+
new HDRLoader()
|
|
162
|
+
.setDataType(1015 as never)
|
|
163
|
+
.load(
|
|
164
|
+
environment.url,
|
|
165
|
+
texture => {
|
|
166
|
+
const image = texture.image as { data: Float32Array; width: number; height: number } | undefined;
|
|
167
|
+
|
|
168
|
+
resolve(image?.data instanceof Float32Array ? image : null);
|
|
169
|
+
texture.dispose();
|
|
170
|
+
},
|
|
171
|
+
undefined,
|
|
172
|
+
() => resolve(null));
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
if (!loaded || loaded.width < 1 || loaded.height < 1) return null;
|
|
176
|
+
|
|
177
|
+
return environmentFromImage(loaded.data, loaded.width, loaded.height);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* An equirectangular image already in memory, linear RGBA floats with the zenith in the first row, made into an
|
|
182
|
+
* environment: a procedural sky baked by the CPU renderer's interpreter arrives this way.
|
|
183
|
+
*/
|
|
184
|
+
export function environmentFromImage(
|
|
185
|
+
data: Float32Array, sourceWidth: number, sourceHeight: number, id = "environment"): PackedEnvironment | null {
|
|
186
|
+
const loaded = { data, width: sourceWidth, height: sourceHeight };
|
|
187
|
+
|
|
188
|
+
if (loaded.width < 1 || loaded.height < 1 || data.length < loaded.width * loaded.height * 4) return null;
|
|
189
|
+
|
|
190
|
+
// The sharp lookup keeps at most MAX_WIDTH across; the distribution is built on a much coarser grid either way.
|
|
191
|
+
const width = Math.min(loaded.width, MAX_WIDTH);
|
|
192
|
+
const height = Math.max(1, Math.round(loaded.height * (width / loaded.width)));
|
|
193
|
+
|
|
194
|
+
const scaled = width === loaded.width
|
|
195
|
+
? loaded.data
|
|
196
|
+
: (() => {
|
|
197
|
+
const reduced = reduce(loaded.data, loaded.width, loaded.height, width, height);
|
|
198
|
+
const rgba = new Float32Array(width * height * 4);
|
|
199
|
+
|
|
200
|
+
for (let texel = 0; texel < width * height; texel++) {
|
|
201
|
+
rgba[texel * 4] = reduced[texel * 3];
|
|
202
|
+
rgba[texel * 4 + 1] = reduced[texel * 3 + 1];
|
|
203
|
+
rgba[texel * 4 + 2] = reduced[texel * 3 + 2];
|
|
204
|
+
rgba[texel * 4 + 3] = 1;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return rgba;
|
|
208
|
+
})();
|
|
209
|
+
|
|
210
|
+
const gridWidth = Math.min(GRID_WIDTH, width);
|
|
211
|
+
const gridHeight = Math.min(GRID_HEIGHT, height);
|
|
212
|
+
const built = environmentDistribution(reduce(scaled, width, height, gridWidth, gridHeight), gridWidth, gridHeight);
|
|
213
|
+
|
|
214
|
+
if (!built) return null;
|
|
215
|
+
|
|
216
|
+
const texture: SerializedTexture = {
|
|
217
|
+
id,
|
|
218
|
+
width,
|
|
219
|
+
height,
|
|
220
|
+
data: scaled,
|
|
221
|
+
// An HDR file is linear already, and the loader hands back floats.
|
|
222
|
+
colorSpace: "srgb-linear",
|
|
223
|
+
// Longitude wraps around; latitude stops at the poles.
|
|
224
|
+
wrapS: 1000,
|
|
225
|
+
wrapT: 1001,
|
|
226
|
+
matrix: [1, 0, 0, 0, 1, 0, 0, 0, 1],
|
|
227
|
+
flipY: false,
|
|
228
|
+
channel: 0,
|
|
229
|
+
nearest: false,
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
return { texture, distribution: built.distribution, width: gridWidth, height: gridHeight, total: built.total };
|
|
233
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { layoutStruct } from "./structLayout.js";
|
|
2
|
+
|
|
3
|
+
/** The kernel's per dispatch uniform, as both sides of the device see it. */
|
|
4
|
+
export const FRAME_LAYOUT = layoutStruct("Frame", [
|
|
5
|
+
{ name: "cameraToWorld", type: "mat4f" },
|
|
6
|
+
{ name: "worldToCamera", type: "mat4f" },
|
|
7
|
+
{ name: "projection", type: "mat4f" },
|
|
8
|
+
{ name: "inverseProjection", type: "mat4f", doc: "Clip space to view space: every camera ray goes through it." },
|
|
9
|
+
{ name: "environmentTop", type: "vec4f", doc: "rgb is the colour at the top of the gradient, w its exponent." },
|
|
10
|
+
{ name: "environmentBottom", type: "vec4f", doc: "rgb is the colour at the bottom, w the environment's strength." },
|
|
11
|
+
{ name: "ambientSky", type: "vec4f", doc: "An ambient or hemisphere light, as radiance along the axis and against it." },
|
|
12
|
+
{ name: "ambientGround", type: "vec4f" },
|
|
13
|
+
{ name: "ambientAxis", type: "vec4f" },
|
|
14
|
+
...Array.from({ length: 9 }, (_, k) => ({
|
|
15
|
+
name: `probe${k}`,
|
|
16
|
+
type: "vec4f" as const,
|
|
17
|
+
doc: k === 0 ? "Light probes: Three's nine spherical harmonic coefficients of radiance, summed." : undefined,
|
|
18
|
+
})),
|
|
19
|
+
{ name: "fogColor", type: "vec4f", doc: "rgb is the fog colour, w its kind: 0 none, 1 linear, 2 exponential squared." },
|
|
20
|
+
{ name: "fogParams", type: "vec4f", doc: "near, far, density, and 1 when the fog covers every surface." },
|
|
21
|
+
{ name: "background", type: "vec4f", doc: "rgb is the colour, w the mode: 0 environment, 1 colour, 2 transparent." },
|
|
22
|
+
{ name: "lens", type: "vec4f", doc: "Lens radius, focus distance, blade count; a radius of zero is a pinhole." },
|
|
23
|
+
{ name: "resolution", type: "vec2u" },
|
|
24
|
+
{ name: "bandOrigin", type: "vec2u" },
|
|
25
|
+
{ name: "bandSize", type: "vec2u" },
|
|
26
|
+
{ name: "sampleIndex", type: "u32" },
|
|
27
|
+
{ name: "sampleCount", type: "u32" },
|
|
28
|
+
{ name: "cameraKind", type: "u32", doc: "0 perspective, 1 orthographic." },
|
|
29
|
+
{ name: "bounces", type: "u32" },
|
|
30
|
+
{ name: "triangleCount", type: "u32" },
|
|
31
|
+
{ name: "lightCount", type: "u32" },
|
|
32
|
+
{ name: "areaLightCount", type: "u32", doc: "How many leading lights are emissive triangles." },
|
|
33
|
+
{ name: "clampIndirect", type: "f32", doc: "Maximum luminance one indirect contribution may add; zero leaves it." },
|
|
34
|
+
{ name: "shadowSpread", type: "f32", doc: "Tangent of half the angular diameter shadow rays spread over." },
|
|
35
|
+
{ name: "shadowsEnabled", type: "u32" },
|
|
36
|
+
{ name: "uvOffset", type: "u32", doc: "Where the UV sets start inside the attribute buffer." },
|
|
37
|
+
{ name: "orderOffset", type: "u32", doc: "Where the hierarchy's triangle order starts inside the index buffer." },
|
|
38
|
+
{ name: "colorOffset", type: "u32", doc: "Where vertex colours start inside the attribute buffer." },
|
|
39
|
+
{ name: "hasColors", type: "u32" },
|
|
40
|
+
{ name: "varyingOffset", type: "u32", doc: "Where shader varyings start inside the attribute buffer." },
|
|
41
|
+
{ name: "environmentTexture", type: "u32", doc: "The surrounding image, or NO_TEXTURE for the gradient." },
|
|
42
|
+
{ name: "environmentCdf", type: "u32" },
|
|
43
|
+
{ name: "environmentCdfSize", type: "vec2u" },
|
|
44
|
+
{ name: "environmentTotal", type: "f32" },
|
|
45
|
+
{ name: "environmentRotation", type: "f32" },
|
|
46
|
+
{ name: "environmentPick", type: "f32", doc: "How often direct sampling picks the environment over a light." },
|
|
47
|
+
{ name: "skyProgram", type: "u32", doc: "A procedural sky's foreground program, or NO_PROGRAM." },
|
|
48
|
+
{ name: "skyData", type: "u32" },
|
|
49
|
+
{ name: "skyBackground", type: "u32", doc: "Whether a procedural sky paints the background (1) or leaves it black (0)." },
|
|
50
|
+
{ name: "skyIntensity", type: "f32", doc: "The strength a procedural sky lights with, which its background ignores." },
|
|
51
|
+
{ name: "pixelCount", type: "u32", doc: "Where the alpha half of the accumulation buffer starts." },
|
|
52
|
+
{ name: "volumetricCount", type: "u32", doc: "Lights that scatter in the air, and where their records start." },
|
|
53
|
+
{ name: "volumetricData", type: "u32" },
|
|
54
|
+
{ name: "adaptiveMin", type: "u32", doc: "Samples a pixel takes before it may stop as converged; 0 never stops." },
|
|
55
|
+
{ name: "adaptiveThreshold", type: "f32", doc: "The error under which a pixel and its neighbours count as converged." },
|
|
56
|
+
{ name: "clipPlane", type: "vec4f", doc: "A plane the camera ray drops surfaces behind, for planar captures; w = 0 and xyz = 0 is none." },
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
export const FRAME_WORDS = FRAME_LAYOUT.words;
|