소스 검색

Add camera and camera controller modules, camera controller doesnt work

Ghastrod 1 년 전
부모
커밋
4941e76f3d
8개의 변경된 파일381개의 추가작업 그리고 29개의 파일을 삭제
  1. 29 0
      src/camera.rs
  2. 109 0
      src/camera_controller.rs
  3. 102 0
      src/camera_controller2.rs
  4. 23 0
      src/camera_uniform.rs
  5. 4 0
      src/main.rs
  6. 18 13
      src/shader.wgsl
  7. 93 14
      src/state.rs
  8. 3 2
      src/vertex_buffer.rs

+ 29 - 0
src/camera.rs

@@ -0,0 +1,29 @@
+use glam::{Mat4, Vec4};
+
+pub struct Camera{
+    pub eye: glam::Vec3,
+    pub target: glam::Vec3,
+    pub up: glam::Vec3,
+    pub aspect: f32,
+    pub fovy: f32,
+    pub znear: f32,
+    pub zfar: f32,
+}
+
+
+#[rustfmt::skip]
+pub const OPENGL_TO_WGPU_MATRIX2 : Mat4 = glam::Mat4::from_cols(
+    Vec4::new(1.0, 0.0, 0.0, 0.0),
+    Vec4::new(0.0, 1.0, 0.0, 0.0),
+    Vec4::new(0.0, 0.0, 0.5, 0.0),
+    Vec4::new(0.0, 0.0, 0.5, 1.0),
+);
+
+
+impl Camera{
+    pub fn build_view_projection_matrix(&self) -> glam::Mat4{
+        let view = glam::Mat4::look_at_rh(self.eye, self.target, self.up);
+        let proj = glam::Mat4::perspective_rh_gl(self.fovy, self.aspect, self.znear, self.zfar);
+        OPENGL_TO_WGPU_MATRIX2 * proj * view
+    }
+}

+ 109 - 0
src/camera_controller.rs

@@ -0,0 +1,109 @@
+use winit::{event::WindowEvent, keyboard::KeyCode};
+
+use crate::camera::Camera;
+
+pub struct CameraController{
+    pub speed: f32,
+    pub is_forward_pressed: bool,
+    pub is_backward_pressed: bool,
+    pub is_left_pressed: bool,
+    pub is_right_pressed: bool,
+}
+
+impl CameraController{
+    pub fn new(speed:f32)->Self{
+        Self{
+            speed,
+            is_forward_pressed: false,
+            is_backward_pressed: false,
+            is_left_pressed: false,
+            is_right_pressed: false,
+        }
+    }
+
+
+    pub fn process_events(&mut self, event: &WindowEvent) -> bool {
+        match event {
+            WindowEvent::KeyboardInput { event, .. } => {
+                let is_pressed = event.state == winit::event::ElementState::Pressed;
+                if is_pressed {
+                    match event.physical_key {
+                        winit::keyboard::PhysicalKey::Code(key_code) => {
+                            match key_code {
+                                KeyCode::KeyW => {
+                                    println!("W pressed!");
+                                    self.is_forward_pressed = is_pressed;
+                                    // Add logic for handling W press
+                                    return true;
+                                }
+                                KeyCode::KeyA => {
+                                    //println!("A pressed!");
+                                    self.is_left_pressed = is_pressed;
+                                    // Add logic for handling A press
+                                    return true;
+                                }
+                                KeyCode::KeyS => {
+                                    //println!("S pressed!");
+                                    self.is_backward_pressed = is_pressed;
+                                    // Add logic for handling S press
+                                    return true;
+                                }
+                                KeyCode::KeyD => {
+                                    //println!("D pressed!");
+                                    self.is_right_pressed = is_pressed;
+                                    // Add logic for handling D press
+                                    return true;
+                                }
+                                _ => false, // Ignore other key codes
+                            };
+                        }
+                        winit::keyboard::PhysicalKey::Unidentified(native_code) => {
+                            // Handle unidentified keys (optional)
+                            // You can potentially store and compare raw codes for custom keybinds
+                            println!("Unidentified key pressed: {:?}", native_code);
+                        }
+                    }
+                }
+                return false // Indicate event not handled
+            }
+            _ => (), // Ignore other events
+        }
+    
+        false // Default return value
+    }
+    
+
+    pub fn update_camera(&self, camera: &mut Camera) {
+
+        let forward = camera.target - camera.eye;
+        let forward_norm = forward.normalize();
+        let forward_mag = forward.length();  // Use glam's length method
+    
+        // Prevents glitching when camera gets too close to the
+        // center of the scene.
+        if self.is_forward_pressed && forward_mag > self.speed {
+            camera.eye += forward_norm * self.speed;
+        }
+        if self.is_backward_pressed {
+            camera.eye -= forward_norm * self.speed;
+        }
+    
+        let right = forward_norm.cross(camera.up);
+    
+        // Redo radius calc in case the up/ down is pressed.
+        let forward = camera.target - camera.eye;
+        let forward_mag = forward.length();
+    
+        if self.is_right_pressed {
+            // Rescale the distance between the target and eye so
+            // that it doesn't change. The eye therefore still
+            // lies on the circle made by the target and eye.
+            let new_forward = (forward + right * self.speed).normalize();
+            camera.eye = camera.target - new_forward * forward_mag;
+        }
+        if self.is_left_pressed {
+            camera.eye = camera.target - (forward - right * self.speed).normalize() * forward_mag;
+        }
+    }
+    
+}

+ 102 - 0
src/camera_controller2.rs

@@ -0,0 +1,102 @@
+use winit::{event::{ElementState, KeyEvent, WindowEvent}, keyboard::{KeyCode, PhysicalKey}};
+
+use crate::camera::Camera;
+
+pub struct CameraController2 {
+    pub speed: f32,
+    pub is_up_pressed: bool,
+    pub is_down_pressed: bool,
+    pub is_forward_pressed: bool,
+    pub is_backward_pressed: bool,
+    pub is_left_pressed: bool,
+    pub is_right_pressed: bool,
+}
+
+impl CameraController2 {
+    pub fn new(speed: f32) -> Self {
+        Self {
+            speed,
+            is_up_pressed: false,
+            is_down_pressed: false,
+            is_forward_pressed: false,
+            is_backward_pressed: false,
+            is_left_pressed: false,
+            is_right_pressed: false,
+        }
+    }
+
+    pub fn process_events(&mut self, event: &WindowEvent) -> bool {
+        match event {
+            WindowEvent::KeyboardInput {
+                event:
+                    KeyEvent {
+                        state,
+                        physical_key: PhysicalKey::Code(keycode),
+                        ..
+                    },
+                ..
+            } => {
+                let is_pressed = *state == ElementState::Pressed;
+                match keycode {
+                    KeyCode::Space => {
+                        self.is_up_pressed = is_pressed;
+                        true
+                    }
+                    KeyCode::ShiftLeft => {
+                        self.is_down_pressed = is_pressed;
+                        true
+                    }
+                    KeyCode::KeyW | KeyCode::ArrowUp => {
+                        self.is_forward_pressed = is_pressed;
+                        true
+                    }
+                    KeyCode::KeyA | KeyCode::ArrowLeft => {
+                        self.is_left_pressed = is_pressed;
+                        true
+                    }
+                    KeyCode::KeyS | KeyCode::ArrowDown => {
+                        self.is_backward_pressed = is_pressed;
+                        true
+                    }
+                    KeyCode::KeyD | KeyCode::ArrowRight => {
+                        self.is_right_pressed = is_pressed;
+                        true
+                    }
+                    _ => false,
+                }
+            }
+            _ => false,
+        }
+    }
+
+    pub fn update_camera(&self, camera: &mut Camera) {
+        let forward = camera.target - camera.eye;
+        let forward_norm = forward.normalize();
+        let forward_magnitude = forward.length();
+
+        // Prevents glitching when camera gets too close to the
+        // center of the scene.
+        if self.is_forward_pressed && forward_magnitude > self.speed {
+            camera.eye += forward_norm * self.speed;
+        }
+        if self.is_backward_pressed {
+            camera.eye -= forward_norm * self.speed;
+        }
+
+        let right = forward_norm.cross(camera.up);
+
+        // Redo radius calc in case the up/ down is pressed.
+        let forward = camera.target - camera.eye;
+        let forward_mag = forward.length();
+
+        if self.is_right_pressed {
+            // Rescale the distance between the target and eye so
+            // that it doesn't change. The eye therefore still
+            // lies on the circle made by the target and eye.
+            camera.eye = camera.target - (forward + right * self.speed).normalize() * forward_mag;
+        }
+        if self.is_left_pressed {
+            camera.eye = camera.target - (forward - right * self.speed).normalize() * forward_mag;
+        }
+    }
+}

+ 23 - 0
src/camera_uniform.rs

@@ -0,0 +1,23 @@
+use crate::camera::Camera;
+
+// We need this for Rust to store our data correctly for the shaders
+#[repr(C)]
+// This is so we can store this in a buffer
+#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
+pub struct CameraUniform {
+    // We can't use cgmath with bytemuck directly, so we'll have
+    // to convert the Matrix4 into a 4x4 f32 array
+    pub view_proj: [[f32; 4]; 4],
+}
+
+impl CameraUniform {
+    pub fn new() -> Self {
+        Self {
+            view_proj: glam::Mat4::IDENTITY.to_cols_array_2d(),
+        }
+    }
+
+    pub fn update_view_proj(&mut self, camera: &Camera) {
+        self.view_proj = camera.build_view_projection_matrix().to_cols_array_2d();
+    }
+}

+ 4 - 0
src/main.rs

@@ -2,6 +2,10 @@ mod vertex;
 mod window;
 mod state;
 mod vertex_buffer;
+mod camera;
+mod camera_controller;
+mod camera_uniform;
+mod camera_controller2;
 
 fn main() {
     pollster::block_on(window::run());

+ 18 - 13
src/shader.wgsl

@@ -1,28 +1,33 @@
+// Fragment shader
+
+@fragment
+fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
+    return vec4<f32>(0.0,0.0,1.0, 1.0);
+}
+
 // Vertex shader
+struct CameraUniform {
+    view_proj: mat4x4<f32>,
+};
+@group(0) @binding(0) // 1.
+var<uniform> camera: CameraUniform;
 
 struct VertexInput {
     @location(0) position: vec3<f32>,
-    @location(1) color: vec3<f32>,
-};
+    @location(1) tex_coords: vec2<f32>,
+}
 
 struct VertexOutput {
     @builtin(position) clip_position: vec4<f32>,
-    @location(0) color: vec3<f32>,
-};
+    @location(0) tex_coords: vec2<f32>,
+}
 
 @vertex
 fn vs_main(
     model: VertexInput,
 ) -> VertexOutput {
     var out: VertexOutput;
-    out.color = model.color;
-    out.clip_position = vec4<f32>(model.position, 1.0);
+    out.tex_coords = model.tex_coords;
+    out.clip_position = camera.view_proj * vec4<f32>(model.position, 1.0); // 2.
     return out;
 }
-
-// Fragment shader
-
-@fragment
-fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
-    return vec4<f32>(0.0,0.0,1.0, 1.0);
-}

+ 93 - 14
src/state.rs

@@ -3,7 +3,7 @@ use std::iter;
 use wgpu::util::DeviceExt;
 use winit::{event::WindowEvent, window::Window};
 
-use crate::{vertex::Vertex, vertex_buffer::{VERT2, VERT3, VERTICES}};
+use crate::{camera::{self, Camera}, camera_controller, camera_uniform, vertex::Vertex, vertex_buffer::{VERT2, VERT3, VERTICES}};
 
 
 pub struct State<'a> {
@@ -19,6 +19,11 @@ pub struct State<'a> {
     render_pipeline: wgpu::RenderPipeline,
     vertex_buffer: wgpu::Buffer,
     num_vertices: u32,
+    camera: camera::Camera,
+    camera_buffer: wgpu::Buffer,
+    camera_uniform: camera_uniform::CameraUniform,
+    camera_bind_group: wgpu::BindGroup,
+    camera_controller: camera_controller::CameraController,
 }
 
 impl<'a> State<'a> {
@@ -85,6 +90,75 @@ impl<'a> State<'a> {
         surface.configure(&device, &config);
         //All the above is just for the surface
 
+
+        let vert = VERT3;
+        let num_vertices = vert.len() as u32;
+        //Now the vertex buffer
+        let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
+            label: Some("Vertex Buffer"),
+            usage: wgpu::BufferUsages::VERTEX,
+            contents: bytemuck::cast_slice(vert)
+        });
+
+        //Camera creation
+        let camera = Camera{
+            eye: glam::Vec3::new(0.0, 0.0, 1.0),
+            target: glam::Vec3::ZERO,
+            up: glam::Vec3::Y,
+            aspect: config.width as f32 / config.height as f32,
+            fovy: 30.0,
+            znear: 0.1,
+            zfar: 100.0,
+        };
+
+        //CameraUniform creation
+        let mut camera_uniform = camera_uniform::CameraUniform::new();
+        camera_uniform.update_view_proj(&camera);
+
+        //Camera Buffer
+        let camera_buffer = device.create_buffer_init(
+            &wgpu::util::BufferInitDescriptor{
+                label: Some("Camera Buffer"),
+                contents: bytemuck::cast_slice(&[camera_uniform]),
+                usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST
+            }
+        );
+
+        //Camera Bind Group Layout
+
+        let camera_bind_group_layout = device.create_bind_group_layout(
+            &wgpu::BindGroupLayoutDescriptor {
+                entries: &[
+                    wgpu::BindGroupLayoutEntry{
+                        binding: 0,
+                        visibility: wgpu::ShaderStages::VERTEX,
+                        ty: wgpu::BindingType::Buffer {
+                            ty: wgpu::BufferBindingType::Uniform,
+                            has_dynamic_offset: false,
+                            min_binding_size: None
+                        },
+                        count: None
+                    }
+                ],
+                label: Some("Camera Bind Group Layout")
+            }
+        );
+
+        //Camera Bind Group
+        let camera_bind_group = device.create_bind_group(
+            &wgpu::BindGroupDescriptor {
+                layout: &camera_bind_group_layout,
+                entries: &[
+                    wgpu::BindGroupEntry{
+                        binding: 0,
+                        resource: camera_buffer.as_entire_binding(),
+                    }
+                ],
+                label: Some("Camera Bind Group")
+            }
+        );
+        
+
         //Next is pipeline/shaders
 
         let shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor{
@@ -94,7 +168,9 @@ impl<'a> State<'a> {
 
         let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor{
             label: Some("Render Pipeline Layout"),
-            bind_group_layouts: &[],
+            bind_group_layouts: &[
+                &camera_bind_group_layout
+            ],
             push_constant_ranges: &[]
         });
 
@@ -144,15 +220,8 @@ impl<'a> State<'a> {
             multiview: None,
         });
 
-
-        let vert = VERT3;
-        let num_vertices = vert.len() as u32;
-        //Now the vertex buffer
-        let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
-            label: Some("Vertex Buffer"),
-            usage: wgpu::BufferUsages::VERTEX,
-            contents: bytemuck::cast_slice(vert)
-        });
+        //Camera controller
+        let camera_controller = camera_controller::CameraController::new(0.2);
 
         Self {
             surface,
@@ -164,6 +233,11 @@ impl<'a> State<'a> {
             render_pipeline,
             vertex_buffer,
             num_vertices,
+            camera,
+            camera_buffer,
+            camera_uniform,
+            camera_bind_group,
+            camera_controller
         }
     }
 
@@ -180,12 +254,16 @@ impl<'a> State<'a> {
         }
     }
 
-    #[allow(unused_variables)]
     pub fn input(&mut self, event: &WindowEvent) -> bool {
-        false
+        println!("{:?}", event);
+        self.camera_controller.process_events(event)
     }
 
-    pub fn update(&mut self) {}
+    pub fn update(&mut self) {
+        self.camera_controller.update_camera(&mut self.camera);
+        self.camera_uniform.update_view_proj(&self.camera);
+        self.queue.write_buffer(&self.camera_buffer, 0, bytemuck::cast_slice(&[self.camera_uniform]));
+    }
 
     pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
         let output = self.surface.get_current_texture()?;
@@ -221,6 +299,7 @@ impl<'a> State<'a> {
             });
 
             render_pass.set_pipeline(&self.render_pipeline);
+            render_pass.set_bind_group(0, &self.camera_bind_group, &[]);
             render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
             render_pass.draw(0..self.num_vertices,0..1);
         }

+ 3 - 2
src/vertex_buffer.rs

@@ -19,7 +19,7 @@ pub const VERT2 : &[Vertex] = &[
 ];
 
 //With the lower triangle first
-//works
+//Works!!
 pub const VERT3 : &[Vertex] = &[
     Vertex { position: [-0.5, -0.5, 0.0], color: [1.0, 0.0, 0.0] },
     Vertex { position: [0.5, -0.5, 0.0], color: [0.0, 1.0, 0.0] },
@@ -28,4 +28,5 @@ pub const VERT3 : &[Vertex] = &[
     Vertex { position: [-0.5, -0.5, 0.0], color: [1.0, 0.0, 0.0] },
     Vertex { position: [0.5, 0.5, 0.0], color: [0.0, 1.0, 0.0] },
     Vertex { position: [-0.5, 0.5, 0.0], color: [0.0, 0.0, 1.0] },
-];
+];
+