diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..15813be --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +package-lock.json +node_modules/ diff --git a/index.html b/index.html index 3c935e8..d83a010 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - testing + raytracing -
0
+
+ diff --git a/main.js b/main.js index 5d50d70..c7aff68 100644 --- a/main.js +++ b/main.js @@ -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); - diff --git a/red.frag.wgsl b/raytracing.wgsl similarity index 81% rename from red.frag.wgsl rename to raytracing.wgsl index ff1b5cc..83d3c79 100644 --- a/red.frag.wgsl +++ b/raytracing.wgsl @@ -3,9 +3,39 @@ struct VertexOutput { @location(0) pos: vec4f } +@vertex +fn vs_main(@builtin(vertex_index) VertexIndex: u32) -> VertexOutput { + var pos = array( + 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 time: f32; @group(0) @binding(1) var aspect: f32; +@fragment +fn fs_main(input: VertexOutput) -> @location(0) vec4 { + spheres[0].center += time; + + var p = vec3(input.pos.xy, 0.0); + p.x *= aspect; + let camera_pos = vec3(0.0, 0.0, 1.0); + let ray_dir = p - camera_pos; + + let r = Ray(camera_pos, ray_dir); + return vec4(ray_color(r), 1.0); +} + struct Ray { origin: vec3, direction: vec3, @@ -54,11 +84,12 @@ struct HitInfo { index: i32, }; -const sphere_count = 4; +const sphere_count = 5; var spheres = array( Sphere(vec3(0.0, 0.0, -1.0), 0.5), Sphere(vec3(2.0, 0.0, 0.0), 0.25), - Sphere(vec3(1.0, 1.0, -2.0), 0.25), + Sphere(vec3(1.0, 1.0, -1.0), 0.25), + Sphere(vec3(-1.0, 0.5, -0.8), 0.25), Sphere(vec3(0.0, -100.5, -1.0), 100.0) ); @@ -83,7 +114,7 @@ fn hit_spheres(r: Ray) -> HitInfo { fn ray_color(r: Ray) -> vec3 { let info = hit_spheres(r); if info.hit { - let sun_dir = vec3(10.0, 10.0, 10.0) - info.pos; + let sun_dir = vec3(-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 { return (1.0 - a) * vec3(1.0, 1.0, 1.0) + a * vec3(0.5, 0.7, 1.0); } -@fragment -fn main(input: VertexOutput) -> @location(0) vec4 { - spheres[0].center.y = time; - - var p = vec3(input.pos.xy, 0.0); - p.x *= aspect; - let camera_pos = vec3(0.0, 0.0, 1.0); - let ray_dir = p - camera_pos; - - let r = Ray(camera_pos, ray_dir); - return vec4(ray_color(r), 1.0); -} diff --git a/triangle.vert.wgsl b/triangle.vert.wgsl deleted file mode 100644 index 1a9b2be..0000000 --- a/triangle.vert.wgsl +++ /dev/null @@ -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( - 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); -} -