Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>WebGPU Rainbow Spiral</title>
- <style>
- body { background:#111; color:white; font-family:monospace; }
- #log { white-space:pre; margin-top:10px; }
- </style>
- </head>
- <body>
- <canvas id="c" width="1280" height="1280"></canvas>
- <div id="log"></div>
- <script>
- const W = 1280, H = 1280;
- const log = document.getElementById("log");
- function out(m){ log.textContent += m + "\n"; }
- const SHADER = `
- const palette = array<vec3f, 19>(
- vec3f(255.0, 0.0, 0.0), vec3f(255.0, 64.0, 0.0), vec3f(255.0, 128.0, 0.0),
- vec3f(255.0, 192.0, 0.0), vec3f(255.0, 255.0, 0.0), vec3f(192.0, 255.0, 0.0),
- vec3f(128.0, 255.0, 0.0), vec3f(0.0, 255.0, 0.0), vec3f(0.0, 255.0, 128.0),
- vec3f(0.0, 255.0, 192.0), vec3f(0.0, 255.0, 255.0), vec3f(0.0, 192.0, 255.0),
- vec3f(0.0, 128.0, 255.0), vec3f(0.0, 64.0, 255.0), vec3f(64.0, 0.0, 255.0),
- vec3f(128.0, 0.0, 255.0), vec3f(192.0, 0.0, 255.0), vec3f(255.0, 0.0, 255.0),
- vec3f(255.0, 0.0, 128.0)
- );
- @vertex fn vs_main(@builtin(vertex_index) idx : u32) -> @builtin(position) vec4f {
- var pos = array<vec2f, 3>(
- vec2f(-1.0, -1.0),
- vec2f(3.0, -1.0),
- vec2f(-1.0, 3.0)
- );
- return vec4f(pos[idx], 0.0, 1.0);
- }
- @fragment fn fs_main(@builtin(position) coord: vec4f) -> @location(0) vec4f {
- let cx = 640.0;
- let cy = 640.0;
- let dx = coord.x - cx;
- let dy = coord.y - cy;
- let r = sqrt(dx*dx + dy*dy);
- if (r > 1000.0 || r < 1.0) {
- return vec4f(0.0, 0.0, 0.0, 0.0);
- }
- let angle_deg = 2000.0 - (2.0 * r);
- let angle_rad = angle_deg * 3.1415926535 / 180.0;
- var local_angle = atan2(dy, dx);
- if (local_angle < 0.0) {
- local_angle += 2.0 * 3.1415926535;
- }
- var source_angle = (local_angle - angle_rad) % (2.0 * 3.1415926535);
- if (source_angle < 0.0) {
- source_angle += 2.0 * 3.1415926535;
- }
- let idx = i32(floor(source_angle / ((2.0 * 3.1415926535) / 19.0))) % 19;
- return vec4f(palette[idx] / 255.0, 1.0);
- }
- `;
- async function main() {
- out("navigator.gpu = " + !!navigator.gpu);
- if (!navigator.gpu) { out("WebGPU not available in this browser"); return; }
- const adapter = await navigator.gpu.requestAdapter();
- if (!adapter){ out("adapter null"); return; }
- out("adapter OK");
- const device = await adapter.requestDevice();
- out("device OK");
- const module = device.createShaderModule({ code: SHADER });
- const ci = await module.getCompilationInfo();
- for (const m of ci.messages) out("[WGSL " + m.type + "] L" + m.lineNum + ": " + m.message);
- if (ci.messages.length === 0) out("WGSL compilation clean");
- const canvas = document.getElementById("c");
- const ctx = canvas.getContext("webgpu");
- const format = navigator.gpu.getPreferredCanvasFormat();
- out("canvas format: " + format);
- const pipeline = device.createRenderPipeline({
- layout: "auto",
- vertex: { module, entryPoint: "vs_main" },
- fragment: { module, entryPoint: "fs_main", targets: [{ format: format }] },
- primitive: { topology:"triangle-list" }
- });
- ctx.configure({
- device,
- format: format,
- alphaMode: "premultiplied"
- });
- device.pushErrorScope("validation");
- const enc = device.createCommandEncoder();
- const pass = enc.beginRenderPass({
- colorAttachments: [{
- view: ctx.getCurrentTexture().createView(),
- clearValue: {r:0,g:0,b:0,a:0},
- loadOp:"clear",
- storeOp:"store"
- }]
- });
- pass.setPipeline(pipeline);
- pass.draw(3);
- pass.end();
- device.queue.submit([enc.finish()]);
- const err = await device.popErrorScope();
- if (err) out("[VALIDATION ERROR] " + err.message);
- await device.queue.onSubmittedWorkDone();
- out("draw submitted and complete - spiral should be visible above");
- }
- main().catch(e => out("ERROR: " + (e && e.message)));
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment