From 8094d8168d89e15ebdf107b82d3b320b02ce1d3c Mon Sep 17 00:00:00 2001 From: Piotrek Date: Wed, 14 Apr 2021 15:42:31 +0200 Subject: [PATCH] added raymarching demo for testing --- build.rs | 9 +++- src/app.rs | 21 ++++---- src/camera.rs | 18 ++++--- src/shaders/bin/shader.frag.spv | Bin 748 -> 8168 bytes src/shaders/bin/shader.vert.spv | Bin 1372 -> 1500 bytes src/shaders/raymarching.cginc | 91 ++++++++++++++++++++++++++++++++ src/shaders/shader.frag | 21 ++++++-- src/shaders/shader.vert | 7 ++- src/shaders/shapes.cginc | 14 +++++ src/uniforms.rs | 23 +++++--- 10 files changed, 174 insertions(+), 30 deletions(-) create mode 100644 src/shaders/raymarching.cginc create mode 100644 src/shaders/shapes.cginc diff --git a/build.rs b/build.rs index 16c85c0..a1c065d 100644 --- a/build.rs +++ b/build.rs @@ -58,9 +58,16 @@ fn main() { let mut compiler = shaderc::Compiler::new().expect("Unable to create shader compiler"); for shader in shaders { println!("cargo:rerun-if-changed={}", shader.src_path.as_os_str().to_str().unwrap()); - let compiled = compiler.compile_into_spirv(&shader.source, shader.kind, &shader.src_path.to_str().unwrap(), "main", Some(&options)).unwrap(); + let compiled = compiler.compile_into_spirv(&shader.source, shader.kind, &shader.src_path.to_str().unwrap(), "main", Some(&options)) + .expect("Shader error:"); write(shader.spv_path, compiled.as_binary_u8()).unwrap(); } + + // Rebuild if any of the cginc change + for path_str in glob("./src/shaders/**/*.cginc").unwrap() { + let path = path_str.unwrap(); + println!("cargo:rerun-if-changed={}", path.as_os_str().to_str().unwrap()); + } } diff --git a/src/app.rs b/src/app.rs index 823e310..56914a4 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,6 +1,6 @@ use std::sync::Arc; use winit::event::Event; -use winit::{window::Window, dpi::PhysicalSize, event::WindowEvent}; +use winit::{window::Window, dpi::PhysicalSize}; use wgpu::util::DeviceExt; use crate::vertex::Vertex; @@ -9,11 +9,14 @@ use crate::camera::Camera; use crate::uniforms::Uniforms; use crate::camera_controller::CameraController; + +// A B +// C D const VERTICES: &[Vertex] = &[ - Vertex { position: [-1.0, 1.0, 0.0], uv: [0.0, 0.0] }, - Vertex { position: [ 1.0, 1.0, 0.0], uv: [1.0, 0.0] }, - Vertex { position: [ 1.0,-1.0, 0.0], uv: [1.0, 1.0] }, - Vertex { position: [-1.0,-1.0, 0.0], uv: [0.0, 1.0] }, + Vertex { position: [-1.0, 1.0, 0.0], uv: [0.0, 0.0] }, // A + Vertex { position: [ 1.0, 1.0, 0.0], uv: [1.0, 0.0] }, // B + Vertex { position: [ 1.0,-1.0, 0.0], uv: [1.0, 1.0] }, // C + Vertex { position: [-1.0,-1.0, 0.0], uv: [0.0, 1.0] }, // D ]; const INDICES: &[u16] = &[ @@ -156,7 +159,7 @@ impl App { entries: &[ wgpu::BindGroupLayoutEntry { binding: 0, - visibility: wgpu::ShaderStage::VERTEX, + visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, @@ -213,9 +216,9 @@ impl App { // Cam let aspect = swapchain_desc.width as f32 / swapchain_desc.height as f32; - let camera = Camera::new((0.0, 0.0, 2.0).into(), (0.0, 0.0, -1.0).into(), aspect); + let camera = Camera::new(aspect, 45.0); let mut uniforms = Uniforms::new(); - uniforms.update_projection_matrix(&camera); + uniforms.update(&camera); let camera_controller = CameraController::new(); // Buffers @@ -260,7 +263,7 @@ impl App { self.camera_controller.update_camera(&mut self.camera, delta_time); // Update projection matrix buffer - self.uniforms.update_projection_matrix(&self.camera); + self.uniforms.update(&self.camera); self.queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[self.uniforms])); } diff --git a/src/camera.rs b/src/camera.rs index 2017855..61b855f 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -20,13 +20,13 @@ pub struct Camera { impl Camera { - pub fn new(position: Point3, forward: Vector3, aspect: f32) -> Self { + pub fn new(aspect: f32, fov: f32) -> Self { Self { - position, - forward, + position: (0.0, 0.0, 0.0).into(), + forward: (0.0, 0.0, 1.0).into(), up: Vector3::unit_y(), aspect, - fovy: 45.0, + fovy: fov, znear: 0.1, zfar: 100.0 } @@ -36,9 +36,11 @@ impl Camera { self.aspect = aspect; } - pub fn projection_matrix(&self) -> Matrix4 { - let view = Matrix4::look_to_rh(self.position, self.forward, self.up); - let proj = cgmath::perspective(Deg(self.fovy), self.aspect, self.znear, self.zfar); - return OPENGL_TO_WGPU_MATRIX * proj * view; + pub fn proj_matrix(&self) -> Matrix4 { + return OPENGL_TO_WGPU_MATRIX * cgmath::perspective(Deg(self.fovy), self.aspect, self.znear, self.zfar); + } + + pub fn view_matrix(&self) -> Matrix4 { + return OPENGL_TO_WGPU_MATRIX * Matrix4::look_to_rh(self.position, self.forward, self.up); } } diff --git a/src/shaders/bin/shader.frag.spv b/src/shaders/bin/shader.frag.spv index bc8ab0fa1d701fcae24b2451002cfffc7e070fe6..97ef2c570f6a138a62458186647db694248fecce 100644 GIT binary patch literal 8168 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 literal 748 zcmYk3PfG$(6vc1qsA+0uX%>XmURqQHQM;Ip;3BByAmbDR{zFHpuh*w)6Lfx0rFn4Y zzH{Dr_uO|Uo4G2O?ODkx*0#;6TSkmo+43&?{g-}knT&cjx7R4DmUTijH7i(7nV1aY zDF^$Crs7aKco}GyRaLWZUCPPL?+5;1;P;<{a6S)~$=5gv#_==?M)4vFlXxAWE2ebu zG#sx+X@Mt2+SfDBdA~1)A3-=9&lV;oYX|a8qEGE}>dEbczv*% z6f7`zFCF^F-4v!?`W(zTv*AAVcl8>Y05j;iX_(tLwa<&|C|c4pD=_cs=v!1~+VBrs zOpkDFbz4$Kk6(K2Fg42C1GLlt^Dfqzx~M9nt2u`MyU~Gp59?fxN6OTo&tqkLc@K9_ zl<|be1I*ju?lft1yop8cKVm%PN3qnbDCh}{e_et1t5olt zu^Y{ox}I>y;@&6r<20M(#Pw(ozvjf-rRG9m7x)Smo z9+d3AoIYH0t&FSkn4_5oChw)h)q?v!k6D^|VDc^{E)VW+UNsl@BJPKTdmT#?$GzAu zn0^lTWplO_MO%!FI z4R-XqA?-;x_iMZrJp)TIx2N5WyQ zU1|Ebd+f<37M^-wz7dyC>@A5gmoMmlB#T^T+ZXQFHuq$1-T=-Cb;%n@vs?W10rO^X zkM%X6sllQCFEM;0&&0Chs}lD6TwdM*jF0*^CCvOz8O(dT=A;(fLCv)q+?|@E_qn=o fC;m6cCmug{f2F$I+moM6ctk zM9pk#cwxA6=A1L<+}-)gyyV$ds|XmB;NfuQ-J0g-ecfF70Pf=GF&Pghq$r>WX*w^_ z;I%&*Cr^Wi=O~Hc!p7!birht$Jc|3HWD+T#{+PE)56*wT%Y2V@e)?gRFBY!c0&7H< zZqlrbJDKwixmk)sa-A++HLdYAv{%iv%5a0BM>vvmD`^3hDsS1!zLUpVT$=K=oU7hv zyv@5n*o5*8-iDB_e#IIu?FddSD-Ia|?`LY*CsVVRuDhM-Ip3@ibwXn+#0jf3Zi|qv zSoQ%S>l^lH1$}{l&{=3L@_;Z)+HS7tN!R>m`V?(~{g+UK3PNH=Vm diff --git a/src/shaders/raymarching.cginc b/src/shaders/raymarching.cginc new file mode 100644 index 0000000..ec311d8 --- /dev/null +++ b/src/shaders/raymarching.cginc @@ -0,0 +1,91 @@ + +// Returns nearest distance to and object id from given point +vec2 map(in vec3 pos) +{ + vec2 d1 = vec2(sdPlane(pos), 1); + vec2 d2 = vec2(sdSphere(pos - vec3(0.0, 2.0, 0.0)), 2); + vec2 d3 = vec2(sdSphere(pos - vec3(2.0, 1.2, 2.0)), 3); + return sdUnion(sdUnion(d1, d2), d3); +} + +// Returns distance to and object id that has been intersected by ray +vec2 intersect(in vec3 ro, in vec3 rd) +{ + float depth = NEAR; + for(int i=0;i 0.0) + { + // Calculate intersection point, normal vector and reflection vector + vec3 pos = ro + rd * result.x; + vec3 nor = estimateNormal(pos); + vec3 ref = reflect(rd, nor); + + // Light + vec3 light = vec3(1); + + float dif = clamp( dot( nor, ld ), 0.0, 1.0 ); + light += 2.20*dif*vec3(1.30,1.00,0.70); + + vec3 hal = normalize( ld-rd ); + float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0); + spe *= dif; + spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,ld),0.0,1.0),5.0); + light += 5.00*spe*vec3(1.30,1.00,0.70); + + //float diffuse = max(dot(norm, -ld), 0); + //color *= diffuse; + + //vec3 ldr = normalize(reflect(-ld, norm)); + //float specular = max(dot(ldr, rd), 0.0); + //specular = pow(specular, 3); + //color += vec3(0.2) * specular; + + //float scatter = pow(1.0-dot(rd, -norm), 2); + + // Calculate color + vec3 color = vec3(0); + if(result.y == 1) color = vec3(0.0, 0.1, 0.01); + else if(result.y == 2) color = vec3(0.5, 0.7, 0.05); + else if(result.y == 3) color = vec3(0.0, 0.2, 0.7); + + // Return + color *= light; + return color; + } + else + { + return vec3(0); + } +} \ No newline at end of file diff --git a/src/shaders/shader.frag b/src/shaders/shader.frag index d971b97..7dc1d5d 100644 --- a/src/shaders/shader.frag +++ b/src/shaders/shader.frag @@ -1,13 +1,28 @@ // shader.frag #version 450 +// Variables layout(location=0) in vec2 vert_uv; -layout(location=0) out vec4 frag_color; - +layout(location=0) out vec4 out_color; layout(set=0, binding=0) uniform texture2D tex; layout(set=0, binding=1) uniform sampler tex_smp; +// Defines +#define PI 3.141592 +#define EPSILON 0.01 +#define NEAR 0.01 +#define MAX_STEPS 200 + +// Include +#include "shapes.cginc" +#include "raymarching.cginc" + void main() { - frag_color = texture(sampler2D(tex, tex_smp), vert_uv); + // Calculate ray + vec3 ro = vec3(0.0, 2, -6.0); // Ray origin + vec3 rd = normalize(vec3(vert_uv - vec2(0.5, 0.5), 1.001)); // Ray direction + + // Render + out_color = vec4(raymarch(ro, rd), 1); } \ No newline at end of file diff --git a/src/shaders/shader.vert b/src/shaders/shader.vert index 9e6efef..d4459e9 100644 --- a/src/shaders/shader.vert +++ b/src/shaders/shader.vert @@ -6,11 +6,14 @@ layout(location=0) out vec2 vert_uv; layout(set=1, binding=0) uniform Uniforms { - mat4 view_projection; + mat4 view; // world to camera + mat4 proj; // camera to screen + mat4 proj_inv; // screen to camera + vec3 cam_pos; // camera position }; void main() { vert_uv = in_uv; - gl_Position = view_projection * vec4(in_position, 1.0); + gl_Position = vec4(in_position, 1.0); } \ No newline at end of file diff --git a/src/shaders/shapes.cginc b/src/shaders/shapes.cginc new file mode 100644 index 0000000..88d60be --- /dev/null +++ b/src/shaders/shapes.cginc @@ -0,0 +1,14 @@ +float sdSphere(in vec3 pos) +{ + return length(pos) - 1.0; +} + +float sdPlane(in vec3 pos) +{ + return pos.y; +} + +vec2 sdUnion(vec2 a, vec2 b) +{ + return (a.x < b.x) ? a : b; +} \ No newline at end of file diff --git a/src/uniforms.rs b/src/uniforms.rs index 6dbd372..c1ffb4e 100644 --- a/src/uniforms.rs +++ b/src/uniforms.rs @@ -4,20 +4,29 @@ use crate::camera::Camera; #[repr(C)] -#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +#[derive(Default, Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] pub struct Uniforms { - view_proj: [[f32; 4]; 4], + view: [[f32; 4]; 4], + proj: [[f32; 4]; 4], + proj_inv: [[f32; 4]; 4], + cam_pos: [f32; 3] } impl Uniforms { pub fn new() -> Self { - Self { - view_proj: cgmath::Matrix4::identity().into(), - } + Self::default() } - pub fn update_projection_matrix(&mut self, camera: &Camera) { - self.view_proj = camera.projection_matrix().into(); + pub fn update(&mut self, camera: &Camera) { + let view = camera.view_matrix(); + let proj = camera.proj_matrix(); + let proj_inv = proj.invert().unwrap(); + let cam_pos = camera.position; + + self.view = view.into(); + self.proj = proj.into(); + self.proj_inv = proj_inv.into(); + self.cam_pos = cam_pos.into(); } }