wgsl-play 0.0.2 → 0.0.4
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/README.md +115 -3
- package/package.json +8 -5
- package/playwright-report/index.html +1 -1
- package/src/Config.ts +26 -0
- package/src/FetchingResolver.ts +146 -0
- package/src/HttpPackageLoader.ts +239 -0
- package/src/PackageLoader.ts +140 -29
- package/src/Renderer.ts +32 -13
- package/src/WgslPlay.css +2 -0
- package/src/WgslPlay.ts +144 -64
- package/src/index.ts +2 -0
- package/src/test/BundleHydrator.test.ts +1 -1
- package/src/test/WgslPlay.e2e.ts +181 -13
- package/src/test/WgslPlay.e2e.ts-snapshots/basic-shader-chromium-darwin.png +0 -0
- package/src/test/WgslPlay.e2e.ts-snapshots/conditions-after-red-chromium-darwin.png +0 -0
- package/src/test/WgslPlay.e2e.ts-snapshots/conditions-initial-green-chromium-darwin.png +0 -0
- package/src/test/WgslPlay.e2e.ts-snapshots/link-import-chromium-darwin.png +0 -0
- package/src/test/WgslPlay.e2e.ts-snapshots/npm-cdn-chromium-darwin.png +0 -0
- package/src/test/WgslPlay.e2e.ts-snapshots/shader-root-internal-chromium-darwin.png +0 -0
- package/src/test/WgslPlay.e2e.ts-snapshots/shader-root-src-chromium-darwin.png +0 -0
- package/src/test/WgslPlay.e2e.ts-snapshots/static-import-chromium-darwin.png +0 -0
- package/test-page/index.html +94 -11
- package/test-page/main.ts +87 -8
- package/test-page/shaders/effects/common.wesl +5 -0
- package/test-page/shaders/effects/main.wesl +10 -0
- package/test-page/shaders/utils.wesl +5 -0
- package/test-page/wesl.toml +3 -0
- package/tsconfig.json +1 -1
- package/vite.config.ts +19 -0
package/src/test/WgslPlay.e2e.ts
CHANGED
|
@@ -1,23 +1,191 @@
|
|
|
1
1
|
/** E2E tests for wgsl-play component using Playwright. */
|
|
2
|
-
import { expect, test } from "@playwright/test";
|
|
2
|
+
import { expect, type Page, test } from "@playwright/test";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/** Wait for wgsl-play custom element to be defined and upgraded. */
|
|
5
|
+
async function waitForWgslPlay(page: Page) {
|
|
6
|
+
await page.waitForFunction(() => customElements.get("wgsl-play"));
|
|
7
|
+
}
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
/** Wait for a wgsl-play element to render at least one frame. */
|
|
10
|
+
async function waitForFrame(page: Page, selector: string) {
|
|
11
|
+
await page.waitForFunction(
|
|
12
|
+
sel =>
|
|
13
|
+
(document.querySelector(sel) as HTMLElement & { frameCount: number })
|
|
14
|
+
?.frameCount > 0,
|
|
15
|
+
selector,
|
|
16
|
+
);
|
|
17
|
+
}
|
|
9
18
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
19
|
+
/** Get current frameCount for a wgsl-play element. */
|
|
20
|
+
async function getFrameCount(page: Page, selector: string): Promise<number> {
|
|
21
|
+
return page.evaluate(
|
|
22
|
+
sel =>
|
|
23
|
+
(document.querySelector(sel) as HTMLElement & { frameCount: number })
|
|
24
|
+
?.frameCount ?? 0,
|
|
25
|
+
selector,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
13
28
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
29
|
+
/** Wait for frameCount to increase from current value (for re-renders after changes). */
|
|
30
|
+
async function waitForNewFrame(page: Page, selector: string) {
|
|
31
|
+
const before = await getFrameCount(page, selector);
|
|
32
|
+
await page.waitForFunction(
|
|
33
|
+
([sel, prev]) =>
|
|
34
|
+
((document.querySelector(sel) as HTMLElement & { frameCount: number })
|
|
35
|
+
?.frameCount ?? 0) > prev,
|
|
36
|
+
[selector, before] as const,
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Get canvas bounding box from inside shadow DOM. */
|
|
41
|
+
async function getCanvasBox(page: Page, playerId: string) {
|
|
42
|
+
return page.evaluate(id => {
|
|
43
|
+
const el = document.querySelector(id) as HTMLElement | null;
|
|
44
|
+
const canvas = el?.shadowRoot?.querySelector("canvas");
|
|
45
|
+
if (!canvas) return null;
|
|
46
|
+
const rect = canvas.getBoundingClientRect();
|
|
47
|
+
return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
|
|
48
|
+
}, playerId);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Scroll player into view and snapshot its shadow DOM canvas. */
|
|
52
|
+
async function expectCanvasSnapshot(
|
|
53
|
+
page: Page,
|
|
54
|
+
playerId: string,
|
|
55
|
+
name: string,
|
|
56
|
+
) {
|
|
57
|
+
await page.locator(playerId).scrollIntoViewIfNeeded();
|
|
58
|
+
const box = await getCanvasBox(page, playerId);
|
|
59
|
+
if (!box) {
|
|
60
|
+
const debug = await page.evaluate(id => {
|
|
61
|
+
const el = document.querySelector(id);
|
|
62
|
+
return { found: !!el, hasShadow: !!el?.shadowRoot };
|
|
63
|
+
}, playerId);
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Canvas not found for ${playerId}: ${JSON.stringify(debug)}`,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
await expect(page).toHaveScreenshot(name, {
|
|
69
|
+
clip: { x: box.x, y: box.y, width: box.width, height: box.height },
|
|
17
70
|
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
test("wgsl-play component loads", async ({ page }, testInfo) => {
|
|
74
|
+
testInfo.setTimeout(10000); // Fast fail - 10s instead of 30s
|
|
75
|
+
|
|
76
|
+
const errors: string[] = [];
|
|
77
|
+
page.on("pageerror", err => errors.push(err.message));
|
|
78
|
+
|
|
79
|
+
await page.goto("/");
|
|
80
|
+
|
|
81
|
+
// Fails fast if module has syntax errors or component fails to register
|
|
82
|
+
const defined = await page
|
|
83
|
+
.waitForFunction(() => customElements.get("wgsl-play"), { timeout: 5000 })
|
|
84
|
+
.then(() => true)
|
|
85
|
+
.catch(() => false);
|
|
86
|
+
|
|
87
|
+
if (!defined) {
|
|
88
|
+
const msg = errors.length
|
|
89
|
+
? `JS errors: ${errors.join("; ")}`
|
|
90
|
+
: "No JS errors captured - check if module loaded";
|
|
91
|
+
throw new Error(`wgsl-play custom element not defined. ${msg}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Verify shadow DOM is created
|
|
95
|
+
const hasShadow = await page.evaluate(
|
|
96
|
+
() => !!document.querySelector("#player1")?.shadowRoot,
|
|
97
|
+
);
|
|
98
|
+
expect(hasShadow).toBe(true);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("basic shader renders", async ({ page }) => {
|
|
102
|
+
await page.goto("/");
|
|
103
|
+
await waitForWgslPlay(page);
|
|
104
|
+
|
|
105
|
+
const player1 = page.locator("#player1");
|
|
106
|
+
await expect(player1).toBeVisible();
|
|
107
|
+
|
|
108
|
+
// Check no error overlay
|
|
109
|
+
const errorOverlay = player1.locator("text=Error");
|
|
110
|
+
await expect(errorOverlay).not.toBeVisible();
|
|
111
|
+
|
|
112
|
+
await expectCanvasSnapshot(page, "#player1", "basic-shader.png");
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("npm CDN - external imports work", async ({ page }) => {
|
|
116
|
+
await page.goto("/");
|
|
117
|
+
await waitForWgslPlay(page);
|
|
118
|
+
|
|
119
|
+
await page.click("#load-npm");
|
|
120
|
+
await page.waitForLoadState("networkidle");
|
|
121
|
+
await waitForFrame(page, "#player2");
|
|
122
|
+
|
|
123
|
+
// Rewind to time=0 for deterministic snapshot
|
|
124
|
+
await page.click("#rewind2");
|
|
125
|
+
await waitForNewFrame(page, "#player2");
|
|
126
|
+
await expectCanvasSnapshot(page, "#player2", "npm-cdn.png");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("shaderRoot - package:: imports resolve", async ({ page }) => {
|
|
130
|
+
await page.goto("/");
|
|
131
|
+
await waitForWgslPlay(page);
|
|
132
|
+
|
|
133
|
+
await page.click("#load-internal");
|
|
134
|
+
await waitForFrame(page, "#player3");
|
|
135
|
+
|
|
136
|
+
await expectCanvasSnapshot(page, "#player3", "shader-root-internal.png");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("shaderRoot - src attribute with super:: and package:: imports", async ({
|
|
140
|
+
page,
|
|
141
|
+
}) => {
|
|
142
|
+
await page.goto("/");
|
|
143
|
+
await waitForWgslPlay(page);
|
|
144
|
+
|
|
145
|
+
await page.click("#load-src");
|
|
146
|
+
await waitForFrame(page, "#player4");
|
|
147
|
+
|
|
148
|
+
await expectCanvasSnapshot(page, "#player4", "shader-root-src.png");
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test("?static import - wesl-plugin build-time linking", async ({ page }) => {
|
|
152
|
+
await page.goto("/");
|
|
153
|
+
await waitForWgslPlay(page);
|
|
154
|
+
|
|
155
|
+
await page.click("#load-static");
|
|
156
|
+
await waitForFrame(page, "#player5");
|
|
157
|
+
|
|
158
|
+
await expectCanvasSnapshot(page, "#player5", "static-import.png");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("?link import - wesl-plugin runtime linking", async ({ page }) => {
|
|
162
|
+
await page.goto("/");
|
|
163
|
+
await waitForWgslPlay(page);
|
|
164
|
+
|
|
165
|
+
await page.click("#load-link");
|
|
166
|
+
await waitForFrame(page, "#player6");
|
|
167
|
+
|
|
168
|
+
await expectCanvasSnapshot(page, "#player6", "link-import.png");
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test("project.conditions - shows green initially, red after setting RED", async ({
|
|
172
|
+
page,
|
|
173
|
+
}) => {
|
|
174
|
+
await page.goto("/");
|
|
175
|
+
await waitForFrame(page, "#player7");
|
|
176
|
+
|
|
177
|
+
// Initial state: no conditions, should show green (@else branch)
|
|
178
|
+
await expectCanvasSnapshot(page, "#player7", "conditions-initial-green.png");
|
|
179
|
+
|
|
180
|
+
// Click to set RED condition
|
|
181
|
+
await page.click("#load-conditions");
|
|
182
|
+
await waitForNewFrame(page, "#player7");
|
|
183
|
+
|
|
184
|
+
// After setting RED: should show red (@if branch)
|
|
185
|
+
await expectCanvasSnapshot(page, "#player7", "conditions-after-red.png");
|
|
18
186
|
});
|
|
19
187
|
|
|
20
|
-
test("no critical console errors", async ({ page }) => {
|
|
188
|
+
test("no critical console errors on basic load", async ({ page }) => {
|
|
21
189
|
const errors: string[] = [];
|
|
22
190
|
page.on("console", msg => {
|
|
23
191
|
if (msg.type() === "error") {
|
|
@@ -29,7 +197,7 @@ test("no critical console errors", async ({ page }) => {
|
|
|
29
197
|
});
|
|
30
198
|
|
|
31
199
|
await page.goto("/");
|
|
32
|
-
await page
|
|
200
|
+
await waitForFrame(page, "#player1");
|
|
33
201
|
|
|
34
202
|
const criticalErrors = errors.filter(
|
|
35
203
|
e => !e.includes("favicon") && !e.includes("404"),
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/test-page/index.html
CHANGED
|
@@ -6,23 +6,106 @@
|
|
|
6
6
|
<title>wgsl-play test</title>
|
|
7
7
|
<style>
|
|
8
8
|
body { margin: 20px; background: #1a1a1a; color: #e0e0e0; font-family: sans-serif; }
|
|
9
|
-
wgsl-play { width:
|
|
9
|
+
wgsl-play { width: 128px; height: 128px; display: block; margin-bottom: 20px; }
|
|
10
10
|
.controls { margin-bottom: 10px; }
|
|
11
11
|
button { padding: 6px 12px; margin-right: 8px; }
|
|
12
|
+
.section { margin-bottom: 30px; padding: 15px; background: #2a2a2a; border-radius: 8px; }
|
|
13
|
+
h3 { margin-top: 0; }
|
|
14
|
+
pre { background: #333; padding: 10px; overflow-x: auto; font-size: 12px; }
|
|
12
15
|
</style>
|
|
13
16
|
</head>
|
|
14
17
|
<body>
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
<h2>wgsl-play Test Page</h2>
|
|
19
|
+
|
|
20
|
+
<!-- Basic test (with uniforms import) -->
|
|
21
|
+
<div class="section">
|
|
22
|
+
<h3>1. Basic (test::Uniforms)</h3>
|
|
23
|
+
<wgsl-play id="player1">
|
|
24
|
+
<script type="text/wesl">
|
|
25
|
+
import test::Uniforms;
|
|
26
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
27
|
+
|
|
28
|
+
@fragment fn fs_main(@builtin(position) pos: vec4f) -> @location(0) vec4f {
|
|
29
|
+
let uv = pos.xy / u.resolution;
|
|
30
|
+
return vec4f(uv, 0.5, 1.0);
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
</wgsl-play>
|
|
19
34
|
</div>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
|
|
36
|
+
<!-- npm CDN test (external imports) -->
|
|
37
|
+
<div class="section">
|
|
38
|
+
<h3>2. npm CDN (animated)</h3>
|
|
39
|
+
<div class="controls">
|
|
40
|
+
<button id="load-npm">Load from npm</button>
|
|
41
|
+
<button id="play2">Play</button>
|
|
42
|
+
<button id="pause2">Pause</button>
|
|
43
|
+
<button id="rewind2">Rewind</button>
|
|
44
|
+
</div>
|
|
45
|
+
<wgsl-play id="player2"></wgsl-play>
|
|
46
|
+
<pre id="npm-status">Status: Ready</pre>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<!-- shaderRoot test (internal imports) -->
|
|
50
|
+
<div class="section">
|
|
51
|
+
<h3>3. shaderRoot (internal imports)</h3>
|
|
52
|
+
<p>Tests <code>package::</code> and <code>super::</code> imports from /shaders</p>
|
|
53
|
+
<div class="controls">
|
|
54
|
+
<button id="load-internal">Load from shaderRoot</button>
|
|
55
|
+
</div>
|
|
56
|
+
<wgsl-play id="player3" shader-root="/shaders"></wgsl-play>
|
|
57
|
+
<pre id="internal-status">Status: Ready</pre>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<!-- src attribute with shaderRoot -->
|
|
61
|
+
<div class="section">
|
|
62
|
+
<h3>4. src attribute with shaderRoot</h3>
|
|
63
|
+
<p>Loads shader file with <code>super::</code> and <code>package::</code> imports</p>
|
|
64
|
+
<div class="controls">
|
|
65
|
+
<button id="load-src">Load from src</button>
|
|
66
|
+
</div>
|
|
67
|
+
<wgsl-play id="player4" shader-root="/shaders"></wgsl-play>
|
|
68
|
+
<pre id="src-status">Status: Ready</pre>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<!-- ?static import test (wesl-plugin) -->
|
|
72
|
+
<div class="section">
|
|
73
|
+
<h3>5. ?static import (wesl-plugin)</h3>
|
|
74
|
+
<p>Tests build-time linking via <code>import wgsl from "./shader.wesl?static"</code></p>
|
|
75
|
+
<div class="controls">
|
|
76
|
+
<button id="load-static">Load ?static shader</button>
|
|
77
|
+
</div>
|
|
78
|
+
<wgsl-play id="player5"></wgsl-play>
|
|
79
|
+
<pre id="static-status">Status: Ready</pre>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<!-- ?link import test (wesl-plugin) -->
|
|
83
|
+
<div class="section">
|
|
84
|
+
<h3>6. ?link import (wesl-plugin)</h3>
|
|
85
|
+
<p>Tests runtime linking via <code>import config from "./shader.wesl?link"</code></p>
|
|
86
|
+
<div class="controls">
|
|
87
|
+
<button id="load-link">Load ?link shader</button>
|
|
88
|
+
</div>
|
|
89
|
+
<wgsl-play id="player6"></wgsl-play>
|
|
90
|
+
<pre id="link-status">Status: Ready</pre>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<!-- conditions test (project.conditions with inline shader) -->
|
|
94
|
+
<div class="section">
|
|
95
|
+
<h3>7. Conditions (project.conditions)</h3>
|
|
96
|
+
<p>Tests <code>project = { conditions: { RED: true } }</code> with inline shader</p>
|
|
97
|
+
<div class="controls">
|
|
98
|
+
<button id="load-conditions">Load with RED condition</button>
|
|
99
|
+
</div>
|
|
100
|
+
<wgsl-play id="player7">
|
|
101
|
+
@fragment fn fs_main() -> @location(0) vec4f {
|
|
102
|
+
@if(RED) { return vec4f(1.0, 0.0, 0.0, 1.0); }
|
|
103
|
+
@else { return vec4f(0.0, 1.0, 0.0, 1.0); }
|
|
104
|
+
}
|
|
105
|
+
</wgsl-play>
|
|
106
|
+
<pre id="conditions-status">Status: Ready</pre>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
26
109
|
<script type="module" src="./main.ts"></script>
|
|
27
110
|
</body>
|
|
28
111
|
</html>
|
package/test-page/main.ts
CHANGED
|
@@ -1,12 +1,91 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
1
|
+
/// <reference types="wesl-plugin/suffixes" />
|
|
2
|
+
import "../src/index.ts"; // Register the custom element
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import type { WgslPlay } from "../src/index.ts";
|
|
5
|
+
import linkConfig from "./shaders/effects/main.wesl?link";
|
|
6
|
+
import staticWgsl from "./shaders/effects/main.wesl?static";
|
|
5
7
|
|
|
6
|
-
document.querySelector("#
|
|
8
|
+
const player1 = document.querySelector<WgslPlay>("#player1")!;
|
|
9
|
+
|
|
10
|
+
// npm CDN test (external imports) with animation
|
|
11
|
+
const player2 = document.querySelector<WgslPlay>("#player2")!;
|
|
12
|
+
const npmShader = `
|
|
13
|
+
import random_wgsl::pcg_2u_3f;
|
|
14
|
+
import test::Uniforms;
|
|
15
|
+
|
|
16
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
17
|
+
|
|
18
|
+
@fragment fn fs_main(@builtin(position) pos: vec4f) -> @location(0) vec4f {
|
|
19
|
+
let uv = pos.xy;
|
|
20
|
+
let seed = vec2u(u32(uv.x) + u32(u.time * 10.0), u32(uv.y));
|
|
21
|
+
let color = pcg_2u_3f(seed);
|
|
22
|
+
return vec4f(color, 1.0);
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
document.querySelector("#load-npm")!.addEventListener("click", () => {
|
|
26
|
+
player2.source = npmShader;
|
|
27
|
+
});
|
|
7
28
|
document
|
|
8
|
-
.querySelector("#
|
|
9
|
-
.addEventListener("click", () =>
|
|
29
|
+
.querySelector("#play2")!
|
|
30
|
+
.addEventListener("click", () => player2.play());
|
|
10
31
|
document
|
|
11
|
-
.querySelector("#
|
|
12
|
-
.addEventListener("click", () =>
|
|
32
|
+
.querySelector("#pause2")!
|
|
33
|
+
.addEventListener("click", () => player2.pause());
|
|
34
|
+
document
|
|
35
|
+
.querySelector("#rewind2")!
|
|
36
|
+
.addEventListener("click", () => player2.rewind());
|
|
37
|
+
|
|
38
|
+
// shaderRoot test (internal imports)
|
|
39
|
+
const player3 = document.querySelector<WgslPlay>("#player3")!;
|
|
40
|
+
const internalShader = `
|
|
41
|
+
import package::utils::gradient;
|
|
42
|
+
import test::Uniforms;
|
|
43
|
+
|
|
44
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
45
|
+
|
|
46
|
+
@fragment fn fs_main(@builtin(position) pos: vec4f) -> @location(0) vec4f {
|
|
47
|
+
let uv = pos.xy / u.resolution;
|
|
48
|
+
let color = gradient(uv);
|
|
49
|
+
return vec4f(color, 1.0);
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
document.querySelector("#load-internal")!.addEventListener("click", () => {
|
|
53
|
+
player3.source = internalShader;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// src attribute with shaderRoot test
|
|
57
|
+
const player4 = document.querySelector<WgslPlay>("#player4")!;
|
|
58
|
+
document.querySelector("#load-src")!.addEventListener("click", () => {
|
|
59
|
+
player4.setAttribute("src", "/shaders/effects/main.wesl");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// ?static import test (wesl-plugin build-time linking)
|
|
63
|
+
const player5 = document.querySelector<WgslPlay>("#player5")!;
|
|
64
|
+
document.querySelector("#load-static")!.addEventListener("click", () => {
|
|
65
|
+
player5.source = staticWgsl;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// ?link import test (wesl-plugin runtime linking)
|
|
69
|
+
const player6 = document.querySelector<WgslPlay>("#player6")!;
|
|
70
|
+
document.querySelector("#load-link")!.addEventListener("click", () => {
|
|
71
|
+
player6.project = linkConfig;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// conditions test (project.conditions with inline shader)
|
|
75
|
+
const player7 = document.querySelector<WgslPlay>("#player7")!;
|
|
76
|
+
document.querySelector("#load-conditions")!.addEventListener("click", () => {
|
|
77
|
+
player7.project = { conditions: { RED: true } };
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Expose for console debugging
|
|
81
|
+
Object.assign(window, {
|
|
82
|
+
player1,
|
|
83
|
+
player2,
|
|
84
|
+
player3,
|
|
85
|
+
player4,
|
|
86
|
+
player5,
|
|
87
|
+
player6,
|
|
88
|
+
player7,
|
|
89
|
+
staticWgsl,
|
|
90
|
+
linkConfig,
|
|
91
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Main shader testing super:: imports
|
|
2
|
+
import super::common::tint;
|
|
3
|
+
import package::utils::gradient;
|
|
4
|
+
|
|
5
|
+
@fragment fn fs_main(@builtin(position) pos: vec4f) -> @location(0) vec4f {
|
|
6
|
+
let uv = pos.xy / 128.0;
|
|
7
|
+
let color = gradient(uv);
|
|
8
|
+
let tinted = tint(color, 0.8);
|
|
9
|
+
return vec4f(tinted, 1.0);
|
|
10
|
+
}
|
package/tsconfig.json
CHANGED
package/vite.config.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import { linkBuildExtension, staticBuildExtension } from "wesl-plugin";
|
|
3
|
+
import viteWesl from "wesl-plugin/vite";
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [
|
|
7
|
+
viteWesl({
|
|
8
|
+
extensions: [staticBuildExtension, linkBuildExtension],
|
|
9
|
+
// debug: true,
|
|
10
|
+
weslToml: "./test-page/wesl.toml",
|
|
11
|
+
}),
|
|
12
|
+
],
|
|
13
|
+
server: {
|
|
14
|
+
fs: {
|
|
15
|
+
// Allow serving files from sibling packages for dev mode testing
|
|
16
|
+
allow: [".."],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
});
|