@multiplekex/shallot 0.2.4 → 0.3.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/package.json +1 -1
- package/src/core/component.ts +1 -1
- package/src/core/index.ts +1 -13
- package/src/core/math.ts +186 -0
- package/src/core/state.ts +1 -1
- package/src/core/xml.ts +56 -41
- package/src/extras/arrows/index.ts +3 -3
- package/src/extras/caustic.ts +37 -0
- package/src/extras/gradient/index.ts +63 -69
- package/src/extras/index.ts +3 -0
- package/src/extras/lines/index.ts +3 -3
- package/src/extras/orbit/index.ts +1 -1
- package/src/extras/skylab/index.ts +314 -0
- package/src/extras/text/font.ts +69 -14
- package/src/extras/text/index.ts +17 -69
- package/src/extras/text/sdf.ts +13 -2
- package/src/extras/water/index.ts +119 -0
- package/src/standard/defaults.ts +2 -0
- package/src/standard/index.ts +2 -0
- package/src/standard/raster/batch.ts +149 -0
- package/src/standard/raster/forward.ts +832 -0
- package/src/standard/raster/index.ts +191 -0
- package/src/standard/raster/shadow.ts +408 -0
- package/src/standard/{render → raytracing}/bvh/blas.ts +336 -88
- package/src/standard/raytracing/bvh/radix.ts +473 -0
- package/src/standard/raytracing/bvh/refit.ts +711 -0
- package/src/standard/{render → raytracing}/bvh/structs.ts +0 -55
- package/src/standard/{render → raytracing}/bvh/tlas.ts +155 -140
- package/src/standard/{render → raytracing}/bvh/traverse.ts +72 -64
- package/src/standard/{render → raytracing}/depth.ts +9 -9
- package/src/standard/raytracing/index.ts +409 -0
- package/src/standard/{render → raytracing}/instance.ts +31 -16
- package/src/standard/{render → raytracing}/ray.ts +1 -1
- package/src/standard/raytracing/shaders.ts +798 -0
- package/src/standard/{render → raytracing}/triangle.ts +1 -1
- package/src/standard/render/camera.ts +96 -106
- package/src/standard/render/data.ts +1 -1
- package/src/standard/render/index.ts +136 -220
- package/src/standard/render/indirect.ts +9 -10
- package/src/standard/render/light.ts +2 -2
- package/src/standard/render/mesh.ts +404 -0
- package/src/standard/render/overlay.ts +8 -5
- package/src/standard/render/pass.ts +1 -1
- package/src/standard/render/postprocess.ts +263 -242
- package/src/standard/render/scene.ts +28 -16
- package/src/standard/render/surface/index.ts +81 -12
- package/src/standard/render/surface/shaders.ts +511 -0
- package/src/standard/render/surface/structs.ts +23 -6
- package/src/standard/tween/tween.ts +44 -115
- package/src/standard/render/bvh/radix.ts +0 -476
- package/src/standard/render/forward/index.ts +0 -259
- package/src/standard/render/forward/raster.ts +0 -228
- package/src/standard/render/mesh/box.ts +0 -20
- package/src/standard/render/mesh/index.ts +0 -446
- package/src/standard/render/mesh/plane.ts +0 -11
- package/src/standard/render/mesh/sphere.ts +0 -40
- package/src/standard/render/mesh/unified.ts +0 -96
- package/src/standard/render/shaders.ts +0 -484
- package/src/standard/render/surface/compile.ts +0 -67
- package/src/standard/render/surface/noise.ts +0 -45
- package/src/standard/render/surface/wgsl.ts +0 -573
- /package/src/standard/{render → raytracing}/intersection.ts +0 -0
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import type { ComputeNode, ExecutionContext } from "../../compute";
|
|
2
|
-
import type { SurfaceData } from "../surface";
|
|
3
|
-
import type { Batch } from "../mesh";
|
|
4
|
-
import { COLOR_FORMAT } from "../scene";
|
|
5
|
-
import { compileUberShader } from "../shaders";
|
|
6
|
-
import { createRasterPipeline, createSkyPipeline } from "./raster";
|
|
7
|
-
|
|
8
|
-
export interface ForwardConfig {
|
|
9
|
-
scene: GPUBuffer;
|
|
10
|
-
matrices: GPUBuffer;
|
|
11
|
-
colors: GPUBuffer;
|
|
12
|
-
sizes: GPUBuffer;
|
|
13
|
-
pbr: GPUBuffer;
|
|
14
|
-
emission: GPUBuffer;
|
|
15
|
-
shapes: GPUBuffer;
|
|
16
|
-
surfaces: GPUBuffer;
|
|
17
|
-
data: GPUBuffer;
|
|
18
|
-
getSurfaces: () => SurfaceData[];
|
|
19
|
-
getRaytracing: () => boolean;
|
|
20
|
-
getClearColor: () => { r: number; g: number; b: number };
|
|
21
|
-
getSky: () => boolean;
|
|
22
|
-
acquire?: (message?: string) => (() => void) | undefined;
|
|
23
|
-
batches: () => (Batch | null)[];
|
|
24
|
-
tlasNodes: GPUBuffer;
|
|
25
|
-
tlasInstanceIds: GPUBuffer;
|
|
26
|
-
blasNodes: GPUBuffer;
|
|
27
|
-
blasTriIds: GPUBuffer;
|
|
28
|
-
blasTriangles: GPUBuffer;
|
|
29
|
-
blasMeta: GPUBuffer;
|
|
30
|
-
instanceInverses: GPUBuffer;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export type ForwardNode = ComputeNode;
|
|
34
|
-
|
|
35
|
-
export function createForwardNode(config: ForwardConfig): ForwardNode {
|
|
36
|
-
let rasterPipeline: GPURenderPipeline | null = null;
|
|
37
|
-
let rtPipeline: GPUComputePipeline | null = null;
|
|
38
|
-
let rtCompiling = false;
|
|
39
|
-
let skyPipeline: GPURenderPipeline | null = null;
|
|
40
|
-
|
|
41
|
-
function executeRT(ctx: ExecutionContext): void {
|
|
42
|
-
const { device, encoder } = ctx;
|
|
43
|
-
|
|
44
|
-
const colorView = ctx.getTextureView("color");
|
|
45
|
-
const linearDepthView = ctx.getTextureView("linear-depth");
|
|
46
|
-
const eidView = ctx.getTextureView("eid");
|
|
47
|
-
|
|
48
|
-
if (!colorView || !linearDepthView || !eidView || !rtPipeline) {
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const bindGroup0 = device.createBindGroup({
|
|
53
|
-
layout: rtPipeline.getBindGroupLayout(0),
|
|
54
|
-
entries: [
|
|
55
|
-
{ binding: 0, resource: { buffer: config.scene } },
|
|
56
|
-
{ binding: 1, resource: { buffer: config.data } },
|
|
57
|
-
{ binding: 2, resource: colorView },
|
|
58
|
-
{ binding: 3, resource: linearDepthView },
|
|
59
|
-
{ binding: 4, resource: eidView },
|
|
60
|
-
],
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const bindGroup1 = device.createBindGroup({
|
|
64
|
-
layout: rtPipeline.getBindGroupLayout(1),
|
|
65
|
-
entries: [
|
|
66
|
-
{ binding: 0, resource: { buffer: config.tlasNodes } },
|
|
67
|
-
{ binding: 1, resource: { buffer: config.tlasInstanceIds } },
|
|
68
|
-
{ binding: 2, resource: { buffer: config.blasNodes } },
|
|
69
|
-
{ binding: 3, resource: { buffer: config.blasTriIds } },
|
|
70
|
-
{ binding: 4, resource: { buffer: config.blasTriangles } },
|
|
71
|
-
{ binding: 5, resource: { buffer: config.blasMeta } },
|
|
72
|
-
{ binding: 6, resource: { buffer: config.instanceInverses } },
|
|
73
|
-
],
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const colorTexture = ctx.getTexture("color");
|
|
77
|
-
if (!colorTexture) return;
|
|
78
|
-
|
|
79
|
-
const width = colorTexture.width;
|
|
80
|
-
const height = colorTexture.height;
|
|
81
|
-
|
|
82
|
-
const pass = encoder.beginComputePass();
|
|
83
|
-
pass.setPipeline(rtPipeline);
|
|
84
|
-
pass.setBindGroup(0, bindGroup0);
|
|
85
|
-
pass.setBindGroup(1, bindGroup1);
|
|
86
|
-
pass.dispatchWorkgroups(Math.ceil(width / 8), Math.ceil(height / 8));
|
|
87
|
-
pass.end();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function executeRaster(ctx: ExecutionContext): void {
|
|
91
|
-
const { device, encoder } = ctx;
|
|
92
|
-
|
|
93
|
-
const colorView = ctx.getTextureView("color");
|
|
94
|
-
const eidView = ctx.getTextureView("eid");
|
|
95
|
-
const depthView = ctx.getTextureView("depth");
|
|
96
|
-
|
|
97
|
-
if (!colorView || !eidView || !depthView || !rasterPipeline) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const batches = config.batches();
|
|
102
|
-
const colorTexture = ctx.getTexture("color");
|
|
103
|
-
if (!colorTexture) return;
|
|
104
|
-
|
|
105
|
-
const clearColor = config.getClearColor();
|
|
106
|
-
const hasSky = config.getSky() && skyPipeline;
|
|
107
|
-
|
|
108
|
-
if (hasSky) {
|
|
109
|
-
const skyPass = encoder.beginRenderPass({
|
|
110
|
-
colorAttachments: [
|
|
111
|
-
{
|
|
112
|
-
view: colorView as GPUTextureView,
|
|
113
|
-
clearValue: { r: clearColor.r, g: clearColor.g, b: clearColor.b, a: 1 },
|
|
114
|
-
loadOp: "clear" as const,
|
|
115
|
-
storeOp: "store" as const,
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
depthStencilAttachment: {
|
|
119
|
-
view: depthView as GPUTextureView,
|
|
120
|
-
depthClearValue: 1.0,
|
|
121
|
-
depthLoadOp: "clear" as const,
|
|
122
|
-
depthStoreOp: "store" as const,
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
const skyBindGroup = device.createBindGroup({
|
|
127
|
-
layout: skyPipeline!.getBindGroupLayout(0),
|
|
128
|
-
entries: [{ binding: 0, resource: { buffer: config.scene } }],
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
skyPass.setPipeline(skyPipeline!);
|
|
132
|
-
skyPass.setBindGroup(0, skyBindGroup);
|
|
133
|
-
skyPass.draw(3);
|
|
134
|
-
skyPass.end();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const pass = encoder.beginRenderPass({
|
|
138
|
-
colorAttachments: [
|
|
139
|
-
{
|
|
140
|
-
view: colorView as GPUTextureView,
|
|
141
|
-
clearValue: { r: clearColor.r, g: clearColor.g, b: clearColor.b, a: 1 },
|
|
142
|
-
loadOp: hasSky ? ("load" as const) : ("clear" as const),
|
|
143
|
-
storeOp: "store" as const,
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
view: eidView as GPUTextureView,
|
|
147
|
-
clearValue: { r: 0, g: 0, b: 0, a: 0 },
|
|
148
|
-
loadOp: "clear" as const,
|
|
149
|
-
storeOp: "store" as const,
|
|
150
|
-
},
|
|
151
|
-
],
|
|
152
|
-
depthStencilAttachment: {
|
|
153
|
-
view: depthView as GPUTextureView,
|
|
154
|
-
depthClearValue: 1.0,
|
|
155
|
-
depthLoadOp: hasSky ? ("load" as const) : ("clear" as const),
|
|
156
|
-
depthStoreOp: "store" as const,
|
|
157
|
-
},
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
pass.setPipeline(rasterPipeline);
|
|
161
|
-
|
|
162
|
-
for (const batch of batches) {
|
|
163
|
-
if (!batch || batch.count === 0) continue;
|
|
164
|
-
|
|
165
|
-
const batchBindGroup = device.createBindGroup({
|
|
166
|
-
layout: rasterPipeline.getBindGroupLayout(0),
|
|
167
|
-
entries: [
|
|
168
|
-
{ binding: 0, resource: { buffer: config.scene } },
|
|
169
|
-
{ binding: 1, resource: { buffer: batch.entityIds } },
|
|
170
|
-
{ binding: 2, resource: { buffer: config.matrices } },
|
|
171
|
-
{ binding: 3, resource: { buffer: config.colors } },
|
|
172
|
-
{ binding: 4, resource: { buffer: config.sizes } },
|
|
173
|
-
{ binding: 5, resource: { buffer: config.pbr } },
|
|
174
|
-
{ binding: 6, resource: { buffer: config.emission } },
|
|
175
|
-
{ binding: 7, resource: { buffer: config.shapes } },
|
|
176
|
-
{ binding: 8, resource: { buffer: config.surfaces } },
|
|
177
|
-
],
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
pass.setBindGroup(0, batchBindGroup);
|
|
181
|
-
pass.setVertexBuffer(0, batch.buffers.vertex);
|
|
182
|
-
pass.setIndexBuffer(batch.buffers.index, "uint16");
|
|
183
|
-
pass.drawIndexed(batch.buffers.indexCount, batch.count);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
pass.end();
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return {
|
|
190
|
-
id: "forward",
|
|
191
|
-
inputs: [{ id: "tlas-bvh-nodes", access: "read" as const }],
|
|
192
|
-
outputs: [
|
|
193
|
-
{ id: "color", access: "write" },
|
|
194
|
-
{ id: "linear-depth", access: "write" },
|
|
195
|
-
{ id: "eid", access: "write" },
|
|
196
|
-
],
|
|
197
|
-
|
|
198
|
-
async prepare(device: GPUDevice) {
|
|
199
|
-
const surfaces = config.getSurfaces();
|
|
200
|
-
rasterPipeline = await createRasterPipeline(device, surfaces, COLOR_FORMAT);
|
|
201
|
-
skyPipeline = await createSkyPipeline(device, COLOR_FORMAT);
|
|
202
|
-
|
|
203
|
-
if (config.getRaytracing()) {
|
|
204
|
-
rtCompiling = true;
|
|
205
|
-
const release = config.acquire?.("compiling shaders");
|
|
206
|
-
createRTPipeline(device, surfaces)
|
|
207
|
-
.then((p) => {
|
|
208
|
-
rtPipeline = p;
|
|
209
|
-
})
|
|
210
|
-
.finally(() => {
|
|
211
|
-
rtCompiling = false;
|
|
212
|
-
release?.();
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
},
|
|
216
|
-
|
|
217
|
-
execute(ctx: ExecutionContext) {
|
|
218
|
-
const wantRT = config.getRaytracing();
|
|
219
|
-
|
|
220
|
-
if (wantRT && !rtPipeline && !rtCompiling) {
|
|
221
|
-
rtCompiling = true;
|
|
222
|
-
const release = config.acquire?.("compiling shaders");
|
|
223
|
-
const surfaces = config.getSurfaces();
|
|
224
|
-
createRTPipeline(ctx.device, surfaces)
|
|
225
|
-
.then((p) => {
|
|
226
|
-
rtPipeline = p;
|
|
227
|
-
})
|
|
228
|
-
.finally(() => {
|
|
229
|
-
rtCompiling = false;
|
|
230
|
-
release?.();
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (wantRT && rtPipeline) {
|
|
235
|
-
executeRT(ctx);
|
|
236
|
-
} else {
|
|
237
|
-
executeRaster(ctx);
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export function compileRTShader(surfaces: SurfaceData[]): string {
|
|
244
|
-
return compileUberShader(surfaces);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
export async function createRTPipeline(
|
|
248
|
-
device: GPUDevice,
|
|
249
|
-
surfaces: SurfaceData[]
|
|
250
|
-
): Promise<GPUComputePipeline> {
|
|
251
|
-
const code = compileRTShader(surfaces);
|
|
252
|
-
const module = device.createShaderModule({ code });
|
|
253
|
-
return device.createComputePipelineAsync({
|
|
254
|
-
layout: "auto",
|
|
255
|
-
compute: { module, entryPoint: "main" },
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
export { createRasterPipeline, compileRasterShader } from "./raster";
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import type { SurfaceData } from "../surface";
|
|
2
|
-
import { SCENE_STRUCT_WGSL, WGSL_STRUCTS } from "../surface/structs";
|
|
3
|
-
import { compileVertexBody, WGSL_LIGHTING_CALC, SKY_WGSL, SKY_DIR_WGSL } from "../surface/wgsl";
|
|
4
|
-
|
|
5
|
-
function compileSurfaceVariant(id: number, data: SurfaceData): string {
|
|
6
|
-
const vertexBody = compileVertexBody(data.vertex);
|
|
7
|
-
const fragmentBody = data.fragment ?? "";
|
|
8
|
-
const lit = data.lit !== false;
|
|
9
|
-
|
|
10
|
-
return `
|
|
11
|
-
fn userVertexTransform_${id}(worldPos: vec3<f32>, normal: vec3<f32>, eid: u32) -> vec3<f32> {
|
|
12
|
-
${vertexBody}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
fn userFragment_${id}(surface: ptr<function, SurfaceData>, position: vec4<f32>) {
|
|
16
|
-
${fragmentBody}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
fn applyLighting_${id}(surface: SurfaceData) -> vec3<f32> {
|
|
20
|
-
${
|
|
21
|
-
lit
|
|
22
|
-
? `${WGSL_LIGHTING_CALC}
|
|
23
|
-
return surface.baseColor * lighting + surface.emission;`
|
|
24
|
-
: "return surface.baseColor;"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
`;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function compileDispatchFunctions(surfaceCount: number): string {
|
|
31
|
-
const vertexCases = Array.from(
|
|
32
|
-
{ length: surfaceCount },
|
|
33
|
-
(_, i) => ` case ${i}u: { return userVertexTransform_${i}(worldPos, normal, eid); }`
|
|
34
|
-
).join("\n");
|
|
35
|
-
|
|
36
|
-
const fragmentCases = Array.from(
|
|
37
|
-
{ length: surfaceCount },
|
|
38
|
-
(_, i) => ` case ${i}u: { userFragment_${i}(surface, position); }`
|
|
39
|
-
).join("\n");
|
|
40
|
-
|
|
41
|
-
const lightingCases = Array.from(
|
|
42
|
-
{ length: surfaceCount },
|
|
43
|
-
(_, i) => ` case ${i}u: { return applyLighting_${i}(surface); }`
|
|
44
|
-
).join("\n");
|
|
45
|
-
|
|
46
|
-
return `
|
|
47
|
-
fn dispatchVertexTransform(surfaceId: u32, worldPos: vec3<f32>, normal: vec3<f32>, eid: u32) -> vec3<f32> {
|
|
48
|
-
switch surfaceId {
|
|
49
|
-
${vertexCases}
|
|
50
|
-
default: { return userVertexTransform_0(worldPos, normal, eid); }
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
fn dispatchFragment(surfaceId: u32, surface: ptr<function, SurfaceData>, position: vec4<f32>) {
|
|
55
|
-
switch surfaceId {
|
|
56
|
-
${fragmentCases}
|
|
57
|
-
default: { userFragment_0(surface, position); }
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
fn dispatchLighting(surfaceId: u32, surface: SurfaceData) -> vec3<f32> {
|
|
62
|
-
switch surfaceId {
|
|
63
|
-
${lightingCases}
|
|
64
|
-
default: { return applyLighting_0(surface); }
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
`;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function compileRasterShader(surfaces: SurfaceData[]): string {
|
|
71
|
-
const surfaceVariants = surfaces.map((s, i) => compileSurfaceVariant(i, s)).join("\n");
|
|
72
|
-
const dispatchFunctions = compileDispatchFunctions(surfaces.length);
|
|
73
|
-
|
|
74
|
-
return /* wgsl */ `
|
|
75
|
-
${WGSL_STRUCTS}
|
|
76
|
-
|
|
77
|
-
@group(0) @binding(8) var<storage, read> surfaceIds: array<u32>;
|
|
78
|
-
|
|
79
|
-
${surfaceVariants}
|
|
80
|
-
${dispatchFunctions}
|
|
81
|
-
|
|
82
|
-
@vertex
|
|
83
|
-
fn vs(input: VertexInput) -> VertexOutput {
|
|
84
|
-
let eid = entityIds[input.instance];
|
|
85
|
-
let world = matrices[eid];
|
|
86
|
-
let scaledPos = input.position * sizes[eid].xyz;
|
|
87
|
-
let baseWorldPos = (world * vec4<f32>(scaledPos, 1.0)).xyz;
|
|
88
|
-
let worldNormal = normalize((world * vec4<f32>(input.normal, 0.0)).xyz);
|
|
89
|
-
let surfaceId = surfaceIds[eid] & 0xFFu;
|
|
90
|
-
let finalWorldPos = dispatchVertexTransform(surfaceId, baseWorldPos, worldNormal, eid);
|
|
91
|
-
_ = shapes[eid];
|
|
92
|
-
|
|
93
|
-
var output: VertexOutput;
|
|
94
|
-
output.position = scene.viewProj * vec4<f32>(finalWorldPos, 1.0);
|
|
95
|
-
output.color = colors[eid];
|
|
96
|
-
output.worldNormal = worldNormal;
|
|
97
|
-
output.entityId = eid;
|
|
98
|
-
output.worldPos = finalWorldPos;
|
|
99
|
-
return output;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
@fragment
|
|
103
|
-
fn fs(input: VertexOutput) -> FragmentOutput {
|
|
104
|
-
let eid = input.entityId;
|
|
105
|
-
let pbrData = pbr[eid];
|
|
106
|
-
let emissionData = emission[eid];
|
|
107
|
-
let surfaceId = surfaceIds[eid] & 0xFFu;
|
|
108
|
-
|
|
109
|
-
var surface: SurfaceData;
|
|
110
|
-
surface.baseColor = input.color.rgb;
|
|
111
|
-
surface.roughness = pbrData.x;
|
|
112
|
-
surface.metallic = pbrData.y;
|
|
113
|
-
surface.emission = emissionData.rgb * emissionData.a;
|
|
114
|
-
surface.normal = normalize(input.worldNormal);
|
|
115
|
-
surface.worldPos = input.worldPos;
|
|
116
|
-
|
|
117
|
-
dispatchFragment(surfaceId, &surface, input.position);
|
|
118
|
-
|
|
119
|
-
let litColor = dispatchLighting(surfaceId, surface);
|
|
120
|
-
|
|
121
|
-
var output: FragmentOutput;
|
|
122
|
-
output.color = vec4<f32>(litColor, input.color.a);
|
|
123
|
-
output.entityId = input.entityId;
|
|
124
|
-
return output;
|
|
125
|
-
}
|
|
126
|
-
`;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export async function createRasterPipeline(
|
|
130
|
-
device: GPUDevice,
|
|
131
|
-
surfaces: SurfaceData[],
|
|
132
|
-
colorFormat: GPUTextureFormat
|
|
133
|
-
): Promise<GPURenderPipeline> {
|
|
134
|
-
const code = compileRasterShader(surfaces);
|
|
135
|
-
const module = device.createShaderModule({ code });
|
|
136
|
-
|
|
137
|
-
return device.createRenderPipelineAsync({
|
|
138
|
-
layout: "auto",
|
|
139
|
-
vertex: {
|
|
140
|
-
module,
|
|
141
|
-
entryPoint: "vs",
|
|
142
|
-
buffers: [
|
|
143
|
-
{
|
|
144
|
-
arrayStride: 24,
|
|
145
|
-
attributes: [
|
|
146
|
-
{ shaderLocation: 0, offset: 0, format: "float32x3" },
|
|
147
|
-
{ shaderLocation: 1, offset: 12, format: "float32x3" },
|
|
148
|
-
],
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
},
|
|
152
|
-
fragment: {
|
|
153
|
-
module,
|
|
154
|
-
entryPoint: "fs",
|
|
155
|
-
targets: [{ format: colorFormat }, { format: "r32uint" }],
|
|
156
|
-
},
|
|
157
|
-
depthStencil: {
|
|
158
|
-
format: "depth24plus",
|
|
159
|
-
depthWriteEnabled: true,
|
|
160
|
-
depthCompare: "less",
|
|
161
|
-
},
|
|
162
|
-
primitive: {
|
|
163
|
-
topology: "triangle-list",
|
|
164
|
-
cullMode: "back",
|
|
165
|
-
},
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export function compileSkyShader(): string {
|
|
170
|
-
return /* wgsl */ `
|
|
171
|
-
${SCENE_STRUCT_WGSL}
|
|
172
|
-
|
|
173
|
-
@group(0) @binding(0) var<uniform> scene: Scene;
|
|
174
|
-
|
|
175
|
-
${SKY_DIR_WGSL}
|
|
176
|
-
${SKY_WGSL}
|
|
177
|
-
|
|
178
|
-
struct VertexOutput {
|
|
179
|
-
@builtin(position) position: vec4<f32>,
|
|
180
|
-
@location(0) uv: vec2<f32>,
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
@vertex
|
|
184
|
-
fn vs(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
|
|
185
|
-
var positions = array<vec2<f32>, 3>(
|
|
186
|
-
vec2(-1.0, -1.0),
|
|
187
|
-
vec2(3.0, -1.0),
|
|
188
|
-
vec2(-1.0, 3.0)
|
|
189
|
-
);
|
|
190
|
-
var output: VertexOutput;
|
|
191
|
-
output.position = vec4(positions[vertexIndex], 0.0, 1.0);
|
|
192
|
-
output.uv = (positions[vertexIndex] + 1.0) * 0.5;
|
|
193
|
-
output.uv.y = 1.0 - output.uv.y;
|
|
194
|
-
return output;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
@fragment
|
|
198
|
-
fn fs(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
199
|
-
let dir = computeSkyDir(input.uv.x, input.uv.y);
|
|
200
|
-
let color = sampleSky(dir);
|
|
201
|
-
return vec4(color, 1.0);
|
|
202
|
-
}
|
|
203
|
-
`;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export async function createSkyPipeline(
|
|
207
|
-
device: GPUDevice,
|
|
208
|
-
colorFormat: GPUTextureFormat
|
|
209
|
-
): Promise<GPURenderPipeline> {
|
|
210
|
-
const code = compileSkyShader();
|
|
211
|
-
const module = device.createShaderModule({ code });
|
|
212
|
-
|
|
213
|
-
return device.createRenderPipelineAsync({
|
|
214
|
-
layout: "auto",
|
|
215
|
-
vertex: { module, entryPoint: "vs" },
|
|
216
|
-
fragment: {
|
|
217
|
-
module,
|
|
218
|
-
entryPoint: "fs",
|
|
219
|
-
targets: [{ format: colorFormat }],
|
|
220
|
-
},
|
|
221
|
-
depthStencil: {
|
|
222
|
-
format: "depth24plus",
|
|
223
|
-
depthWriteEnabled: false,
|
|
224
|
-
depthCompare: "always",
|
|
225
|
-
},
|
|
226
|
-
primitive: { topology: "triangle-list" },
|
|
227
|
-
});
|
|
228
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { MeshData } from "./index";
|
|
2
|
-
|
|
3
|
-
export function createBox(): MeshData {
|
|
4
|
-
const vertices = new Float32Array([
|
|
5
|
-
-0.5, -0.5, 0.5, 0, 0, 1, 0.5, -0.5, 0.5, 0, 0, 1, 0.5, 0.5, 0.5, 0, 0, 1, -0.5, 0.5, 0.5,
|
|
6
|
-
0, 0, 1, 0.5, -0.5, -0.5, 0, 0, -1, -0.5, -0.5, -0.5, 0, 0, -1, -0.5, 0.5, -0.5, 0, 0, -1,
|
|
7
|
-
0.5, 0.5, -0.5, 0, 0, -1, -0.5, 0.5, 0.5, 0, 1, 0, 0.5, 0.5, 0.5, 0, 1, 0, 0.5, 0.5, -0.5,
|
|
8
|
-
0, 1, 0, -0.5, 0.5, -0.5, 0, 1, 0, -0.5, -0.5, -0.5, 0, -1, 0, 0.5, -0.5, -0.5, 0, -1, 0,
|
|
9
|
-
0.5, -0.5, 0.5, 0, -1, 0, -0.5, -0.5, 0.5, 0, -1, 0, 0.5, -0.5, 0.5, 1, 0, 0, 0.5, -0.5,
|
|
10
|
-
-0.5, 1, 0, 0, 0.5, 0.5, -0.5, 1, 0, 0, 0.5, 0.5, 0.5, 1, 0, 0, -0.5, -0.5, -0.5, -1, 0, 0,
|
|
11
|
-
-0.5, -0.5, 0.5, -1, 0, 0, -0.5, 0.5, 0.5, -1, 0, 0, -0.5, 0.5, -0.5, -1, 0, 0,
|
|
12
|
-
]);
|
|
13
|
-
|
|
14
|
-
const indices = new Uint16Array([
|
|
15
|
-
0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18,
|
|
16
|
-
16, 18, 19, 20, 21, 22, 20, 22, 23,
|
|
17
|
-
]);
|
|
18
|
-
|
|
19
|
-
return { vertices, indices, vertexCount: 24, indexCount: 36 };
|
|
20
|
-
}
|