Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6fddd17
docs(spec): add WGSL→WESL conversion + shared shader library design
rulkens May 7, 2026
ab66322
docs(plan): add WESL conversion 15-task implementation plan
rulkens May 7, 2026
94117e3
chore(shaders): bootstrap wesl-plugin tooling and convert toneMap
rulkens May 7, 2026
ab938e9
chore(shaders): rename remaining 6 shaders .wgsl → .wesl
rulkens May 7, 2026
e62a59c
refactor(shaders): extract lib/math.wesl — saturate, rot2, sabs, pola…
rulkens May 7, 2026
bc4c86d
refactor(shaders): create lib/camera.wesl with shared CameraUniforms …
rulkens May 7, 2026
07a87a8
refactor(shaders): adopt CameraUniforms in filaments shader
rulkens May 7, 2026
603c5ec
refactor(shaders): adopt CameraUniforms in quads shader
rulkens May 7, 2026
fde1ef5
refactor(shaders): adopt CameraUniforms in disks shader
rulkens May 7, 2026
3637f76
refactor(shaders): adopt CameraUniforms in proceduralDisks shader
rulkens May 7, 2026
637236b
refactor(shaders): adopt CameraUniforms in milkyWayImpostor shader
rulkens May 7, 2026
d78195a
refactor(shaders): adopt CameraUniforms in points + pick shaders
rulkens May 7, 2026
96951fc
test(postProcess): mock getCompilationInfo on createShaderModule
rulkens May 7, 2026
2e2ad21
fix(shaders): hoist milkyWay math imports to top of file
rulkens May 7, 2026
15e213f
chore(gpu): label every WebGPU resource for debuggability
rulkens May 7, 2026
1b084f2
refactor(shaders): create lib/billboard.wesl with billboard expansion…
rulkens May 7, 2026
f1cc3e3
refactor(shaders): adopt billboard lib in quads.wesl
rulkens May 7, 2026
a20a18d
refactor(shaders): adopt billboard lib in disks.wesl
rulkens May 7, 2026
2c9fcbc
refactor(shaders): adopt billboard lib in proceduralDisks.wesl
rulkens May 7, 2026
93d7880
refactor(shaders): adopt billboard lib in points.wesl
rulkens May 7, 2026
3dbedca
refactor(shaders): create lib/orientation.wesl with PA+inclination ax…
rulkens May 7, 2026
ff6141b
refactor(shaders): adopt orientation lib in disks.wesl
rulkens May 7, 2026
f6c201c
refactor(shaders): tighten pole-degeneracy guard in lib/orientation.wesl
rulkens May 7, 2026
e5da67d
refactor(shaders): adopt orientation lib in proceduralDisks.wesl
rulkens May 7, 2026
71bce18
refactor(shaders): extract lib/colorIndex.wesl
rulkens May 7, 2026
2466164
refactor(shaders): extract lib/cloudFade.wesl
rulkens May 7, 2026
2113add
refactor(shaders): unify CloudUniforms in lib/cloudFade.wesl
rulkens May 7, 2026
ad086b2
refactor(shaders): extract lib/masks.wesl
rulkens May 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,600 changes: 1,600 additions & 0 deletions docs/superpowers/plans/2026-05-07-wesl-conversion.md

Large diffs are not rendered by default.

149 changes: 149 additions & 0 deletions docs/superpowers/specs/2026-05-07-wesl-conversion-design.md

Large diffs are not rendered by default.

115 changes: 115 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
"typescript": "6.0.3",
"vite": "8.0.10",
"vitest": "4.1.5",
"wesl": "0.7.26",
"wesl-plugin": "0.6.74",
"wrangler": "4.87.0"
},
"dependencies": {
Expand Down
9 changes: 9 additions & 0 deletions src/@types/wesl.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Activate wesl-plugin's ambient declarations for `?static` etc.
//
// We import these via tsconfig.json `types: ["wesl-plugin/suffixes"]`, but
// that subpath form isn't reliably resolved by every TypeScript version
// when the compilerOptions are picked up by the editor / build separately.
// A triple-slash reference here is the belt-and-braces fallback that
// guarantees resolution from any compiler entry point.
/// <reference types="wesl-plugin/suffixes" />
export {};
2 changes: 2 additions & 0 deletions src/services/gpu/cloudFade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export class CloudFade {
startNowMs: number = performance.now(),
) {
this.buffer = device.createBuffer({
label: 'cloudFade-uniform-buffer',
// 16 bytes is WebGPU's minimum uniform-buffer alignment — even though
// we only need 4 bytes for the f32 opacity, allocating less is a
// validation error. The shader's `_pad0/1/2` fields consume the
Expand All @@ -140,6 +141,7 @@ export class CloudFade {
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
});
this.bindGroup = device.createBindGroup({
label: 'cloudFade-bg',
layout: bindGroupLayout,
entries: [{ binding: 0, resource: { buffer: this.buffer } }],
});
Expand Down
41 changes: 26 additions & 15 deletions src/services/gpu/diskRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@

import type { mat4 } from 'gl-matrix';
import type { GpuContext } from '../../@types';
import diskWgsl from './shaders/disks.wgsl?raw';
import diskWgsl from './shaders/disks.wesl?static';
import { createShaderModuleWithDevLog } from './shaderCompileLogger';

export type DiskInstance = {
x: number;
Expand All @@ -53,20 +54,27 @@ const FLOATS_PER_INSTANCE = 12;
const BYTES_PER_INSTANCE = FLOATS_PER_INSTANCE * 4;

/**
* 96-byte uniform layout (matches the WGSL `Uniforms` struct in disks.wgsl):
* 96-byte uniform layout (matches the WESL `Uniforms` struct in
* disks.wesl, which now extends the shared `CameraUniforms` prefix from
* `lib/camera.wesl`):
*
* bytes 0..63 : viewProj mat4x4<f32> (16 floats = 64 B)
* bytes 64..71 : viewport vec2<f32> (2 floats = 8 B)
* bytes 72..79 : _pad0/_pad1 f32 × 2 (8 B; pads next vec3 to 16-B boundary)
* bytes 80..91 : camPos vec3<f32> (3 floats = 12 B; vec3 needs 16-B alignment)
* bytes 92..95 : _pad2 f32 (4 B; trailing pad in camPos's vec4 quantum)
* bytes 0..63 : cam.viewProj mat4x4<f32> (16 floats = 64 B)
* bytes 64..71 : cam.viewportPx vec2<f32> (2 floats = 8 B)
* bytes 72..79 : cam._pad0 / _pad1 f32 × 2 (8 B; pads next vec3 to 16-B boundary)
* bytes 80..91 : camPos vec3<f32> (3 floats = 12 B; vec3 needs 16-B alignment)
* bytes 92..95 : _pad2 f32 (4 B; trailing pad in camPos's vec4 quantum)
*
* Total: 96 bytes — multiple of 16 ✓. This mirrors the QuadRenderer's
* revised layout (after the orbit-warp fix) so the two passes can share
* the same conceptual binding even though their consumers differ:
* QuadRenderer uses the trailing slot for `pxPerRad`, while DiskRenderer
* doesn't need pixel-radius math (the disk geometry sizes itself in
* world space) and leaves it as padding.
* Total: 96 bytes — multiple of 16 ✓. Byte-for-byte identical to the
* pre-CameraUniforms layout: the WESL refactor only renamed the prefix
* fields ('viewProj' → 'cam.viewProj', 'viewport' → 'cam.viewportPx',
* '_pad0/_pad1' → 'cam._pad0/_pad1') without moving any of the
* trailing renderer-specific bytes, so this CPU uploader didn't need to
* shift any offsets. This mirrors the QuadRenderer's revised layout
* (after the orbit-warp fix) so the two passes can share the same
* conceptual binding even though their consumers differ: QuadRenderer
* uses the trailing slot for `pxPerRad`, while DiskRenderer doesn't
* need pixel-radius math (the disk geometry sizes itself in world
* space) and leaves it as padding.
*/
const UNIFORM_BYTES = 96;

Expand Down Expand Up @@ -95,11 +103,14 @@ export class DiskRenderer {
],
});

const module = this.device.createShaderModule({ label: 'disks-wgsl', code: diskWgsl });
const module = createShaderModuleWithDevLog(this.device, diskWgsl, 'disks');

this.pipeline = this.device.createRenderPipeline({
label: 'disk-pipeline',
layout: this.device.createPipelineLayout({ bindGroupLayouts: [this.bindGroupLayout] }),
layout: this.device.createPipelineLayout({
label: 'disks-pipeline-layout',
bindGroupLayouts: [this.bindGroupLayout],
}),
vertex: {
module,
entryPoint: 'vs',
Expand Down
Loading
Loading