switch to single file shader

This commit is contained in:
sam 2024-05-31 15:06:20 +12:00
parent 923eda6d8f
commit 44c9fdb43a
5 changed files with 64 additions and 56 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
package-lock.json
node_modules/

View file

@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<title>testing</title> <title>raytracing</title>
<script src="main.js" type="module" defer></script> <script src="main.js" type="module" defer></script>
<style> <style>
@ -14,12 +14,17 @@
#frame_time { #frame_time {
position: absolute; position: absolute;
color: black; color: white;
background: rgba(0, 0, 0, 0.5);
user-select: none;
font-family: monospace;
padding: 5px;
} }
</style> </style>
</head> </head>
<body> <body>
<div id="frame_time">0</div> <div id="frame_time"></div>
<canvas id="canvas"> <canvas id="canvas">
</body> </body>
</html> </html>

36
main.js
View file

@ -2,10 +2,8 @@ const canvas = document.querySelector("#canvas");
const context = canvas.getContext("webgpu"); const context = canvas.getContext("webgpu");
const frameTime = document.querySelector("#frame_time"); const frameTime = document.querySelector("#frame_time");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const adapter = await navigator.gpu.requestAdapter(); const adapter = await navigator.gpu.requestAdapter();
const adapterInfo = await adapter.requestAdapterInfo();
const device = await adapter.requestDevice(); const device = await adapter.requestDevice();
const devicePixelRatio = window.devicePixelRatio; const devicePixelRatio = window.devicePixelRatio;
@ -39,17 +37,19 @@ const pipelineLayout = device.createPipelineLayout({
] ]
}); });
const module = device.createShaderModule({
code: await (await fetch("raytracing.wgsl")).text(),
});
const pipeline = device.createRenderPipeline({ const pipeline = device.createRenderPipeline({
layout: pipelineLayout, layout: pipelineLayout,
vertex: { vertex: {
module: device.createShaderModule({ module,
code: await (await fetch("triangle.vert.wgsl")).text(), entry: "vs_main",
}),
}, },
fragment: { fragment: {
module: device.createShaderModule({ module,
code: await (await fetch("red.frag.wgsl")).text(), entry: "fs_main",
}),
targets: [ targets: [
{ {
format: presentationFormat, format: presentationFormat,
@ -82,10 +82,13 @@ const bindGroup = device.createBindGroup({
const timeArray = new Float32Array(1); const timeArray = new Float32Array(1);
const aspectArray = new Float32Array(1); const aspectArray = new Float32Array(1);
let time = Date.now(); let time = 0;
let time_history = []; let time_history = [];
let elapsed_time = 0; let elapsed_time = 0;
function frame() { function frame() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
timeArray.set([Math.sin(elapsed_time)]); timeArray.set([Math.sin(elapsed_time)]);
device.queue.writeBuffer(timeBuffer, 0, timeArray); device.queue.writeBuffer(timeBuffer, 0, timeArray);
@ -114,18 +117,19 @@ function frame() {
device.queue.submit([commandEncoder.finish()]); device.queue.submit([commandEncoder.finish()]);
let end_time = Date.now() / 1000; let end_time = Date.now();
let frame_time = end_time - time; let frame_time = end_time - time;
elapsed_time += frame_time; elapsed_time += frame_time / 1000;
time = end_time; time = end_time;
time_history.push(frame_time); time_history.push(frame_time);
if(time_history.length > 10) time_history.shift(); if(time_history.length > 10) time_history.shift();
frameTime.innerText = let avg_frame_time = time_history.reduce((acc, v) => acc + v) / time_history.length;
(1.0 / (time_history.reduce((acc, v) => acc + v) / time_history.length)).toFixed(2) + " FPS"; frameTime.innerText = `FPS: ${(1 / (avg_frame_time / 1000)).toFixed(2)}
//frameTime.innerText = 1.0 / (frame_time / 1000); Frame time: ${avg_frame_time.toFixed(1)}ms
${adapterInfo.vendor} ${adapterInfo.device} (${adapterInfo.architecture})`;
requestAnimationFrame(frame); requestAnimationFrame(frame);
} }
requestAnimationFrame(frame); requestAnimationFrame(frame);

View file

@ -3,9 +3,39 @@ struct VertexOutput {
@location(0) pos: vec4f @location(0) pos: vec4f
} }
@vertex
fn vs_main(@builtin(vertex_index) VertexIndex: u32) -> VertexOutput {
var pos = array<vec2f, 6>(
vec2(-1.0, 1.0),
vec2(-1.0, -1.0),
vec2(1.0, -1.0),
vec2(1.0, -1.0),
vec2(1.0, 1.0),
vec2(-1.0, 1.0)
);
var p = vec4f(pos[VertexIndex], 0.0, 1.0);
return VertexOutput(p, p);
}
@group(0) @binding(0) var<uniform> time: f32; @group(0) @binding(0) var<uniform> time: f32;
@group(0) @binding(1) var<uniform> aspect: f32; @group(0) @binding(1) var<uniform> aspect: f32;
@fragment
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
spheres[0].center += time;
var p = vec3<f32>(input.pos.xy, 0.0);
p.x *= aspect;
let camera_pos = vec3<f32>(0.0, 0.0, 1.0);
let ray_dir = p - camera_pos;
let r = Ray(camera_pos, ray_dir);
return vec4<f32>(ray_color(r), 1.0);
}
struct Ray { struct Ray {
origin: vec3<f32>, origin: vec3<f32>,
direction: vec3<f32>, direction: vec3<f32>,
@ -54,11 +84,12 @@ struct HitInfo {
index: i32, index: i32,
}; };
const sphere_count = 4; const sphere_count = 5;
var<private> spheres = array<Sphere, sphere_count>( var<private> spheres = array<Sphere, sphere_count>(
Sphere(vec3<f32>(0.0, 0.0, -1.0), 0.5), Sphere(vec3<f32>(0.0, 0.0, -1.0), 0.5),
Sphere(vec3<f32>(2.0, 0.0, 0.0), 0.25), Sphere(vec3<f32>(2.0, 0.0, 0.0), 0.25),
Sphere(vec3<f32>(1.0, 1.0, -2.0), 0.25), Sphere(vec3<f32>(1.0, 1.0, -1.0), 0.25),
Sphere(vec3<f32>(-1.0, 0.5, -0.8), 0.25),
Sphere(vec3<f32>(0.0, -100.5, -1.0), 100.0) Sphere(vec3<f32>(0.0, -100.5, -1.0), 100.0)
); );
@ -83,7 +114,7 @@ fn hit_spheres(r: Ray) -> HitInfo {
fn ray_color(r: Ray) -> vec3<f32> { fn ray_color(r: Ray) -> vec3<f32> {
let info = hit_spheres(r); let info = hit_spheres(r);
if info.hit { if info.hit {
let sun_dir = vec3<f32>(10.0, 10.0, 10.0) - info.pos; let sun_dir = vec3<f32>(-10.0, 10.0, 10.0) - info.pos;
let sun_ray = Ray(info.pos, sun_dir); let sun_ray = Ray(info.pos, sun_dir);
let sun_hit = hit_spheres(sun_ray); let sun_hit = hit_spheres(sun_ray);
@ -97,16 +128,4 @@ fn ray_color(r: Ray) -> vec3<f32> {
return (1.0 - a) * vec3<f32>(1.0, 1.0, 1.0) + a * vec3<f32>(0.5, 0.7, 1.0); return (1.0 - a) * vec3<f32>(1.0, 1.0, 1.0) + a * vec3<f32>(0.5, 0.7, 1.0);
} }
@fragment
fn main(input: VertexOutput) -> @location(0) vec4<f32> {
spheres[0].center.y = time;
var p = vec3<f32>(input.pos.xy, 0.0);
p.x *= aspect;
let camera_pos = vec3<f32>(0.0, 0.0, 1.0);
let ray_dir = p - camera_pos;
let r = Ray(camera_pos, ray_dir);
return vec4<f32>(ray_color(r), 1.0);
}

View file

@ -1,22 +0,0 @@
struct VertexOutput {
@builtin(position) vert_pos: vec4f,
@location(0) pos: vec4f
}
@vertex
fn main(@builtin(vertex_index) VertexIndex: u32) -> VertexOutput {
var pos = array<vec2f, 6>(
vec2(-1.0, 1.0),
vec2(-1.0, -1.0),
vec2(1.0, -1.0),
vec2(1.0, -1.0),
vec2(1.0, 1.0),
vec2(-1.0, 1.0)
);
var p = vec4f(pos[VertexIndex], 0.0, 1.0);
return VertexOutput(p, p);
}