Ghastrod преди 1 година
родител
ревизия
0b25bfdbc1
променени са 7 файла, в които са добавени 221 реда и са изтрити 7 реда
  1. 56 0
      src/camera/camera_buffer.rs
  2. 87 0
      src/camera/camera_controller.rs
  3. 30 0
      src/camera/camera_struct.rs
  4. 21 0
      src/camera/camera_uniform.rs
  5. 4 0
      src/camera/mod.rs
  6. 22 7
      src/lib.rs
  7. 1 0
      src/main.rs

+ 56 - 0
src/camera/camera_buffer.rs

@@ -0,0 +1,56 @@
+use wgpu::{util::DeviceExt, SurfaceConfiguration};
+
+use super::camera_struct;
+
+
+
+pub fn new(device: wgpu::Device, config: SurfaceConfiguration)->(camera_struct::Camera, super::camera_uniform::CameraUniform, wgpu::Buffer, wgpu::BindGroup, wgpu::BindGroupLayout){
+    let cam : camera_struct::Camera = camera_struct::Camera {
+        eye: (0.0, 1.0, 2.0).into(),
+        target: (0.0,0.0,0.0).into(),
+        up: glam::Vec3::Y,
+        aspect: config.width as f32 / config.height as f32,
+        fovy: 45.0,
+        znear: 0.1,
+        zfar:100.0,
+    };
+
+
+    let mut camera_uniform1 = super::camera_uniform::CameraUniform::new();
+    camera_uniform1.update_view_proj(&cam);
+
+    let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
+        label: Some("Camera Buffer"),
+        contents: bytemuck::cast_slice(&[camera_uniform1]),
+        usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST
+    });
+
+    let camera_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor{
+        label: Some("Camera Bind group layout"),
+        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,
+            }
+        ]
+    });
+
+    let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor{
+        label: Some("Camera Bind Group"),
+        layout: &camera_bind_group_layout,
+        entries: &[
+            wgpu::BindGroupEntry{
+                binding: 0,
+                resource: camera_buffer.as_entire_binding()
+            }
+        ]
+    });
+
+    return (cam, camera_uniform1, camera_buffer, camera_bind_group, camera_bind_group_layout)
+}

+ 87 - 0
src/camera/camera_controller.rs

@@ -0,0 +1,87 @@
+use glam::{Vec3};
+use winit::event::WindowEvent;
+use winit::event::WindowEvent::KeyboardInput;
+struct CameraController {
+    speed: f32,
+    is_forward_pressed: bool,
+    is_backward_pressed: bool,
+    is_left_pressed: bool,
+    is_right_pressed: bool,
+}
+
+impl CameraController {
+    fn new(speed: f32) -> Self {
+        Self {
+            speed,
+            is_forward_pressed: false,
+            is_backward_pressed: false,
+            is_left_pressed: false,
+            is_right_pressed: false,
+        }
+    }
+
+    fn process_events(&mut self, event: &WindowEvent) -> bool {
+        match event {
+            WindowEvent::KeyboardInput {
+                input: KeyboardInput {
+                    state,
+                    virtual_keycode: Some(keycode),
+                    ..
+                },
+                ..
+            } => {
+                let is_pressed = *state == ElementState::Pressed;
+                match keycode {
+                    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,
+        }
+    }
+
+    fn update_camera(&self, camera: &mut Camera) {
+        // Calculate direction vector
+        let forward = camera.target - camera.eye;
+        let forward_norm = forward.normalize();
+
+        // Forward/backward movement
+        if self.is_forward_pressed && forward.length() > self.speed {
+            camera.eye += forward_norm * self.speed;
+        }
+        if self.is_backward_pressed {
+            camera.eye -= forward_norm * self.speed;
+        }
+
+        // Right vector using cross product
+        let right = forward_norm.cross(camera.up);
+
+        // Recalculate forward vector (optional)
+        let forward = camera.target - camera.eye;
+
+        // Left/right movement - maintain distance to target
+        if self.is_right_pressed {
+            let new_forward = (forward + right * self.speed).normalize();
+            camera.eye = camera.target - new_forward * forward.length();
+        }
+        if self.is_left_pressed {
+            let new_forward = (forward - right * self.speed).normalize();
+            camera.eye = camera.target - new_forward * forward.length();
+        }
+    }
+}

+ 30 - 0
src/camera/camera_struct.rs

@@ -0,0 +1,30 @@
+use glam::{Mat4, Vec4, Vec3};
+
+const OPENGL_TO_WGPU_MATRIX: Mat4 = 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.5),
+    Vec4::new(0.0, 0.0, 0.0, 1.0),
+);
+
+pub struct Camera {
+    pub eye: Vec3,
+    pub target: Vec3,
+    pub up: Vec3,
+    pub aspect: f32,
+    pub fovy: f32,
+    pub znear: f32,
+    pub zfar: f32,
+}
+
+impl Camera {
+    pub fn build_view_projection_matrix(&self) -> Mat4 {
+        // 1.
+        let view = Mat4::look_at_rh(self.eye, self.target, self.up);
+        // 2.
+        let proj = Mat4::perspective_rh(self.fovy.to_radians(), self.aspect, self.znear, self.zfar);
+
+        // 3.
+        return OPENGL_TO_WGPU_MATRIX * proj * view;
+    }
+}

+ 21 - 0
src/camera/camera_uniform.rs

@@ -0,0 +1,21 @@
+// 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
+    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: &super::camera_struct::Camera) {
+        self.view_proj = camera.build_view_projection_matrix().to_cols_array_2d();
+    }
+}

+ 4 - 0
src/camera/mod.rs

@@ -0,0 +1,4 @@
+pub mod camera_struct;
+pub mod camera_controller;
+pub mod camera_uniform;
+pub mod camera_buffer;

+ 22 - 7
src/lib.rs

@@ -1,5 +1,6 @@
 use std::iter;
 
+use camera::{camera_buffer, camera_struct::Camera, camera_uniform};
 use wgpu::{util::DeviceExt, BlendState, ColorTargetState, PipelineLayoutDescriptor, RenderPipelineDescriptor};
 use winit::{
     event::*,
@@ -7,6 +8,7 @@ use winit::{
     keyboard::{KeyCode, PhysicalKey},
     window::{Window, WindowBuilder},
 };
+mod camera;
 
 #[cfg(target_arch = "wasm32")]
 use wasm_bindgen::prelude::*;
@@ -19,6 +21,10 @@ struct State<'a> {
     size: winit::dpi::PhysicalSize<u32>,
     render_pipeline : wgpu::RenderPipeline,
     vertex_buffer: wgpu::Buffer,
+    camera: camera::camera_struct::Camera,
+    camera_buffer : wgpu::Buffer,
+    camera_bind_group: wgpu::BindGroup,
+    camera_uniform : camera_uniform::CameraUniform,
     // The window must be declared after the surface so
     // it gets dropped after it as the surface contains
     // unsafe references to the window's resources.
@@ -96,10 +102,21 @@ impl<'a> State<'a> {
         });
         
 
+
+        let plan1 = generate_plane();
+        let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
+            label: Some("Vertex Buffer 1"),
+            contents: bytemuck::cast_slice(todo!()),
+            usage: wgpu::BufferUsages::VERTEX,
+        });
+
+        let (camera, camera_uniform, camera_buffer,camera_bind_group, camera_bind_group_layout) = camera_buffer::new(device, config);
+
+
         let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor{
             label: Some("Pipeline Layout"),
             bind_group_layouts: &[
-
+                &camera_bind_group_layout,
             ],
             push_constant_ranges: &[]
         });
@@ -140,12 +157,6 @@ impl<'a> State<'a> {
             }),
             multiview: None
         });
-        let plan1 = generate_plane();
-        let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
-            label: Some("Vertex Buffer 1"),
-            contents: bytemuck::cast_slice(todo!()),
-            usage: wgpu::BufferUsages::VERTEX,
-        });
 
 
         Self {
@@ -157,6 +168,10 @@ impl<'a> State<'a> {
             config,
             size,
             window,
+            camera,
+            camera_bind_group,
+            camera_buffer,
+            camera_uniform,
         }
     }
 

+ 1 - 0
src/main.rs

@@ -2,6 +2,7 @@ use wgpu5::run;
 
 use crate::object::generate_plane;
 
+mod camera;
 mod window;
 mod object;
 fn main() {