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

36
main.js
View file

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

View file

@ -3,9 +3,39 @@ struct VertexOutput {
@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(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 {
origin: vec3<f32>,
direction: vec3<f32>,
@ -54,11 +84,12 @@ struct HitInfo {
index: i32,
};
const sphere_count = 4;
const sphere_count = 5;
var<private> spheres = array<Sphere, sphere_count>(
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>(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)
);
@ -83,7 +114,7 @@ fn hit_spheres(r: Ray) -> HitInfo {
fn ray_color(r: Ray) -> vec3<f32> {
let info = hit_spheres(r);
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_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);
}
@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);
}