diff --git a/crates/flare3d/Cargo.toml b/crates/flare3d/Cargo.toml deleted file mode 100644 index 603e272..0000000 --- a/crates/flare3d/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "flare3d" -version = "0.1.0" -edition = "2021" -authors = ["KrLite"] -description = "Rust reimplementation of the blaze3d renderer, based on Wgpu" -repository = "https://github.com/rimecraft-rs/rimecraft/" -license = "AGPL-3.0-or-later" -categories = ["game-development"] - -[badges] -maintenance = { status = "actively-developed" } - -[dependencies] -color_space = "0.5" -# Wgpu -image = "0.24" -glam = "0.25.0" -winit = { version = "0.29", default-features = false, features = [ - "rwh_05", - "rwh_06", - "x11", - "wayland", - "wayland-dlopen", - "wayland-csd-adwaita", -] } -wgpu = "0.19" -tracing = "0.1" -bytemuck = { version = "1.4", features = ["derive"] } -anyhow = "1.0" -futures-executor = "0.3" - -[target.'cfg(target_os = "macos")'.dependencies] -display-link = { git = "https://github.com/BrainiumLLC/display-link", rev = "32780138c65ee3981d0fa44f321bb9946146a580" } - -[lints] -workspace = true diff --git a/crates/flare3d/example/Cargo.toml b/crates/flare3d/example/Cargo.toml deleted file mode 100644 index e4fa211..0000000 --- a/crates/flare3d/example/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "flare3d-example" -version = "0.1.0" -edition = "2021" -authors = ["KrLite"] -description = "Example of Flare3d" -repository = "https://github.com/rimecraft-rs/rimecraft/" -license = "AGPL-3.0-or-later" -categories = ["game-development"] - -[badges] -maintenance = { status = "actively-developed" } - -[dependencies] -flare3d = { path = "../" } -winit = "0.29" -wgpu = "0.19" -futures-executor = "0.3" - -[target.'cfg(target_os = "macos")'.dependencies] -display-link = { git = "https://github.com/BrainiumLLC/display-link", rev = "32780138c65ee3981d0fa44f321bb9946146a580" } diff --git a/crates/flare3d/example/src/main.rs b/crates/flare3d/example/src/main.rs deleted file mode 100644 index ca7a1ab..0000000 --- a/crates/flare3d/example/src/main.rs +++ /dev/null @@ -1,6 +0,0 @@ -use flare3d::window::Window; - -#[allow(unused_variables)] -fn main() { - let window = Window::new(); -} diff --git a/crates/flare3d/readme.md b/crates/flare3d/readme.md deleted file mode 100644 index 15fa02f..0000000 --- a/crates/flare3d/readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# Flare 3D - -Rust reimplementation of the blaze3d renderer, based on Wgpu. \ No newline at end of file diff --git a/crates/flare3d/src/happy-tree.png b/crates/flare3d/src/happy-tree.png deleted file mode 100644 index fc86db3..0000000 Binary files a/crates/flare3d/src/happy-tree.png and /dev/null differ diff --git a/crates/flare3d/src/lib.rs b/crates/flare3d/src/lib.rs deleted file mode 100644 index 4c8d643..0000000 --- a/crates/flare3d/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! # Flare3D -//! -//! Rust reimplementation of the blaze3d renderer, based on Wgpu. - -pub mod state; -pub mod texture; -pub mod window; diff --git a/crates/flare3d/src/shader.wgsl b/crates/flare3d/src/shader.wgsl deleted file mode 100644 index 5a30de3..0000000 --- a/crates/flare3d/src/shader.wgsl +++ /dev/null @@ -1,50 +0,0 @@ -struct InstanceInput { - @location(5) model_matrix_0: vec4f, - @location(6) model_matrix_1: vec4f, - @location(7) model_matrix_2: vec4f, - @location(8) model_matrix_3: vec4f, -}; - -struct CameraUniform { - view_proj: mat4x4f, -}; -@group(1) @binding(0) -var camera: CameraUniform; - -struct VertexInput { - @location(0) position: vec3f, - @location(1) tex_coords: vec2f, -} - -struct VertexOutput { - @builtin(position) clip_position: vec4f, - @location(0) tex_coords: vec2f, -} - -@vertex -fn vs_main( - model: VertexInput, - instance: InstanceInput, -) -> VertexOutput { - let model_matrix = mat4x4f( - instance.model_matrix_0, - instance.model_matrix_1, - instance.model_matrix_2, - instance.model_matrix_3, - ); - - var out: VertexOutput; - out.tex_coords = model.tex_coords; - out.clip_position = camera.view_proj * model_matrix * vec4f(model.position, 1.0); - return out; -} - -@group(0) @binding(0) -var t_diffuse: texture_2d; -@group(0) @binding(1) -var s_diffuse: sampler; - -@fragment -fn fs_main(in: VertexOutput) -> @location(0) vec4f { - return textureSample(t_diffuse, s_diffuse, in.tex_coords); -} diff --git a/crates/flare3d/src/state/camera.rs b/crates/flare3d/src/state/camera.rs deleted file mode 100644 index f97724c..0000000 --- a/crates/flare3d/src/state/camera.rs +++ /dev/null @@ -1,305 +0,0 @@ -//! Camera implementations. - -use glam::{Mat4, Quat, Vec3}; -use winit::{ - event::{ElementState, KeyEvent, WindowEvent}, - keyboard::{KeyCode, PhysicalKey}, -}; - -/// Represents a camera with position, direction, and perspective parameters. -#[derive(Debug, Copy, Clone)] -pub struct Camera { - /// Camera position. - pub eye: Vec3, - /// Camera direction. - pub direction: Vec3, - - /// Aspect ratio of the viewport. - pub aspect: f32, - /// Field of view in the y direction. - pub fov_y: f32, - - /// Near frustum plane. - pub z_near: f32, - /// Far frustum plane. - pub z_far: f32, -} - -impl Camera { - /// Eular pitch in radians. - pub fn pitch(&self) -> f32 { - self.direction.y.atan2(self.direction.x) - } - - /// Eular yaw in radians. - pub fn yaw(&self) -> f32 { - self.direction.z.atan2(self.direction.x) - } - /// Eular pitch in degrees. - pub fn pitch_deg(&self) -> f32 { - self.pitch().to_degrees() - } - - /// Eular yaw in degrees. - pub fn yaw_deg(&self) -> f32 { - self.yaw().to_degrees() - } -} - -impl Camera { - /// Builds the view projection matrix for the camera. - pub fn build_view_projection_matrix(&self) -> Mat4 { - let view = Mat4::look_at_rh(self.eye, self.eye + self.direction, Vec3::Y); - let proj = Mat4::perspective_rh(self.fov_y.to_radians(), self.aspect, self.z_near, self.z_far); - - proj * view - } - - /// Builds the orthographic projection matrix for the camera. - pub fn build_orthographic_projection_matrix(&self) -> Mat4 { - let view = Mat4::look_at_rh(self.eye, self.eye + self.direction, Vec3::Y); - let proj = Mat4::orthographic_rh( - -self.fov_y * self.z_near, - self.fov_y * self.z_near, - -self.fov_y * self.z_near, - self.fov_y * self.z_near, - self.z_near, - self.z_far, - ); - - proj * view - } -} - -/// Represents a camera uniform buffer object. -#[repr(C)] -#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] -pub struct CameraUniform { - view_proj: [[f32; 4]; 4], -} - -impl CameraUniform { - /// Creates a new camera uniform buffer object. - pub fn new() -> Self { - Self { - view_proj: Mat4::IDENTITY.to_cols_array_2d(), - } - } - - /// Updates the projection matrix from a [Mat4]. - pub fn update_proj(&mut self, proj: Mat4) { - self.view_proj = proj.to_cols_array_2d() - } - - /// Updates the view or orthographic projection matrix of a [Camera]. - pub fn update_view_or_orthographic_proj(&mut self, is_orthographic: bool, camera: &Camera) { - if is_orthographic { - self.update_orthographic_proj(camera); - } else { - self.update_view_proj(camera); - } - } - - /// Updates the view projection matrix of a [Camera]. - pub fn update_view_proj(&mut self, camera: &Camera) { - self.update_proj(camera.build_view_projection_matrix()) - } - - /// Updates the orthographic projection matrix of a [Camera]. - pub fn update_orthographic_proj(&mut self, camera: &Camera) { - self.update_proj(camera.build_orthographic_projection_matrix()) - } -} - -/// Represents a camera controller. -#[derive(Debug)] -pub struct CameraController { - speed: f32, - - mv: Vec3, - mv_lerp: f32, - - forwarding: bool, - backwarding: bool, - strafing_left: bool, - strafing_right: bool, - flying: bool, - diving: bool, - - turn_up: bool, - turn_down: bool, - turn_left: bool, - turn_right: bool, - - is_orthographic: bool, -} - -impl CameraController { - /// Creates a new camera controller. - pub fn new(speed: f32) -> Self { - Self { - speed, - forwarding: false, - backwarding: false, - strafing_left: false, - strafing_right: false, - flying: false, - diving: false, - - turn_up: false, - turn_down: false, - turn_left: false, - turn_right: false, - - mv_lerp: 0.1, - mv: Vec3::ZERO, - is_orthographic: false, - } - } - - pub fn is_orthographic(&self) -> bool { - self.is_orthographic - } - - /// Processes a window event. - pub fn process_events(&mut self, event: &WindowEvent) -> bool { - match event { - WindowEvent::KeyboardInput { - event: - KeyEvent { - state, - physical_key: PhysicalKey::Code(key_code), - .. - }, - .. - } => { - let is_pressed = *state == ElementState::Pressed; - match key_code { - KeyCode::KeyW | KeyCode::KeyA | KeyCode::KeyS | KeyCode::KeyD => { - if is_pressed { - match key_code { - KeyCode::KeyW => { - self.forwarding = true; - } - KeyCode::KeyS => { - self.backwarding = true; - } - KeyCode::KeyA => { - self.strafing_left = true; - } - KeyCode::KeyD => { - self.strafing_right = true; - } - _ => unreachable!(), - } - } else { - match key_code { - KeyCode::KeyW => { - self.forwarding = false; - } - KeyCode::KeyS => { - self.backwarding = false; - } - KeyCode::KeyA => { - self.strafing_left = false; - } - KeyCode::KeyD => { - self.strafing_right = false; - } - _ => unreachable!(), - } - } - - true - } - - KeyCode::Space => { - self.flying = is_pressed; - true - } - KeyCode::ShiftLeft | KeyCode::ShiftRight => { - self.diving = is_pressed; - true - } - KeyCode::ArrowUp | KeyCode::KeyK => { - self.turn_up = is_pressed; - true - } - KeyCode::ArrowDown | KeyCode::KeyJ => { - self.turn_down = is_pressed; - true - } - KeyCode::ArrowLeft | KeyCode::KeyH => { - self.turn_left = is_pressed; - true - } - KeyCode::ArrowRight | KeyCode::KeyL => { - self.turn_right = is_pressed; - true - } - KeyCode::KeyO => { - self.is_orthographic = is_pressed; - true - } - _ => false, - } - } - _ => false, - } - } - - /// Updates a [Camera]. - pub fn update_camera(&mut self, camera: &mut Camera) { - let plane_normal = Vec3::Y; - let forward = camera.direction - (camera.direction.dot(plane_normal) * plane_normal); - let forward_normal = forward.normalize(); - let right_normal = forward_normal.cross(plane_normal).normalize(); - - // Movement - - let mut mv_target = Vec3::ZERO; - - if self.forwarding { - mv_target += forward_normal; - } - if self.backwarding { - mv_target -= forward_normal; - } - - if self.strafing_left { - mv_target -= right_normal; - } - if self.strafing_right { - mv_target += right_normal; - } - - if self.flying { - mv_target += plane_normal; - } - if self.diving { - mv_target -= plane_normal; - } - - mv_target = if mv_target == Vec3::ZERO { Vec3::ZERO } else { mv_target.normalize() * self.speed }; - self.mv = self.mv.lerp(mv_target, self.mv_lerp); - - camera.eye += self.mv; - - // Rotation - - let rotation = 1.0_f32.to_radians(); - - if self.turn_right { - camera.direction = Quat::from_rotation_y(-rotation) * camera.direction; - } - if self.turn_left { - camera.direction = Quat::from_rotation_y(rotation) * camera.direction; - } - if self.turn_up { - camera.direction = Quat::from_axis_angle(right_normal, rotation) * camera.direction; - } - if self.turn_down { - camera.direction = Quat::from_axis_angle(right_normal, -rotation) * camera.direction; - } - } -} diff --git a/crates/flare3d/src/state/instance.rs b/crates/flare3d/src/state/instance.rs deleted file mode 100644 index 0226bf8..0000000 --- a/crates/flare3d/src/state/instance.rs +++ /dev/null @@ -1,58 +0,0 @@ -//! Instance implementations. - -use glam::{Mat4, Quat, Vec3}; - -/// Reperesents an instance with a position and rotation. -#[derive(Debug, Copy, Clone)] -pub struct Instance { - pub position: Vec3, - pub rotation: Quat, -} - -impl Instance { - pub fn to_raw(&self) -> InstanceRaw { - InstanceRaw { - model: (Mat4::from_translation(self.position) * Mat4::from_quat(self.rotation)) - .to_cols_array_2d(), - } - } -} - -/// A raw instance with a model matrix. -#[repr(C)] -#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] -pub struct InstanceRaw { - pub model: [[f32; 4]; 4], -} - -impl InstanceRaw { - pub fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { - use std::mem; - wgpu::VertexBufferLayout { - array_stride: mem::size_of::() as wgpu::BufferAddress, - step_mode: wgpu::VertexStepMode::Instance, - attributes: &[ - wgpu::VertexAttribute { - offset: 0, - shader_location: 5, - format: wgpu::VertexFormat::Float32x4, - }, - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress, - shader_location: 6, - format: wgpu::VertexFormat::Float32x4, - }, - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress, - shader_location: 7, - format: wgpu::VertexFormat::Float32x4, - }, - wgpu::VertexAttribute { - offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress, - shader_location: 8, - format: wgpu::VertexFormat::Float32x4, - }, - ], - } - } -} diff --git a/crates/flare3d/src/state/mod.rs b/crates/flare3d/src/state/mod.rs deleted file mode 100644 index 8984476..0000000 --- a/crates/flare3d/src/state/mod.rs +++ /dev/null @@ -1,393 +0,0 @@ -//! State implementations. - -pub mod camera; -pub mod instance; -pub mod vertex; - -use std::sync::Arc; - -use glam::{Quat, Vec3}; -use wgpu::util::DeviceExt; -use winit::{event::WindowEvent, event_loop::EventLoop, window::Window}; - -use crate::texture::Texture; - -use camera::{Camera, CameraController, CameraUniform}; -use instance::{Instance, InstanceRaw}; -use vertex::Vertex; - -const VERTICES: &[Vertex] = &[ - Vertex { - position: [-0.0868241, 0.49240386, 0.0], - tex_coords: [0.4131759, 0.00759614], - }, - Vertex { - position: [-0.49513406, 0.06958647, 0.0], - tex_coords: [0.0048659444, 0.43041354], - }, - Vertex { - position: [-0.21918549, -0.44939706, 0.0], - tex_coords: [0.28081453, 0.949397], - }, - Vertex { - position: [0.35966998, -0.3473291, 0.0], - tex_coords: [0.85967, 0.84732914], - }, - Vertex { - position: [0.44147372, 0.2347359, 0.0], - tex_coords: [0.9414737, 0.2652641], - }, -]; - -const INDICES: &[u16] = &[0, 1, 4, 1, 2, 4, 2, 3, 4]; -const NUM_INSTANCES_PER_ROW: u32 = 1000; -const INSTANCE_DISPLACEMENT: Vec3 = Vec3::new( - NUM_INSTANCES_PER_ROW as f32 * 0.5, - 0.0, - NUM_INSTANCES_PER_ROW as f32 * 0.5, -); - -#[derive(Debug)] -pub struct State<'s> { - pub window: Arc, - pub size: winit::dpi::PhysicalSize, - - surface: wgpu::Surface<'s>, - device: wgpu::Device, - queue: wgpu::Queue, - config: wgpu::SurfaceConfiguration, - render_pipeline: wgpu::RenderPipeline, - vertex_buffer: wgpu::Buffer, - index_buffer: wgpu::Buffer, - diffuse_bind_group: wgpu::BindGroup, - diffuse_texture: Texture, - camera: Camera, - camera_uniform: CameraUniform, - camera_buffer: wgpu::Buffer, - camera_bind_group: wgpu::BindGroup, - camera_controller: CameraController, - instances: Vec, - instance_buffer: wgpu::Buffer, - depth_texture: Texture, -} - -impl<'s> State<'s> { - pub async fn new(event_loop: &EventLoop<()>) -> State<'s> { - let window = Arc::new(Window::new(event_loop).unwrap()); - let size = window.inner_size(); - - let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: wgpu::Backends::all(), - ..Default::default() - }); - - let surface = instance.create_surface(window.clone()).unwrap(); - let adapter = instance - .request_adapter(&wgpu::RequestAdapterOptions { - power_preference: wgpu::PowerPreference::default(), - compatible_surface: Some(&surface), - force_fallback_adapter: false, - }) - .await - .unwrap(); - - let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - required_features: wgpu::Features::empty(), - required_limits: wgpu::Limits::default(), - label: None, - }, - None, - ) - .await - .unwrap(); - - let caps = surface.get_capabilities(&adapter); - let config = wgpu::SurfaceConfiguration { - usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - format: caps.formats[0], - width: size.width, - height: size.height, - present_mode: wgpu::PresentMode::Fifo, - alpha_mode: Default::default(), - view_formats: vec![], - desired_maximum_frame_latency: 0, - }; - surface.configure(&device, &config); - - let diffuse_bytes = include_bytes!("../happy-tree.png"); - let diffuse_texture = - Texture::from_bytes(&device, &queue, diffuse_bytes, "happy-tree.png").unwrap(); - - let texture_bind_group_layout = - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - multisampled: false, - view_dimension: wgpu::TextureViewDimension::D2, - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - label: Some("texture_bind_group_layout"), - }); - let diffuse_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &texture_bind_group_layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&diffuse_texture.view), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler), - }, - ], - label: Some("diffuse_bind_group"), - }); - - let camera = Camera { - eye: (0.0, 1.0, 2.0).into(), - direction: Vec3::X, - aspect: config.width as f32 / config.height as f32, - fov_y: 45.0, - z_near: 0.1, - z_far: 100.0, - }; - - let mut camera_uniform = CameraUniform::new(); - camera_uniform.update_view_proj(&camera); - - 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, - }); - 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"), - }); - 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"), - }); - - let depth_texture = Texture::create_depth_texture(&device, &config, "depth_texture"); - - let shader = device.create_shader_module(wgpu::include_wgsl!("../shader.wgsl")); - let render_pipeline_layout = - device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Render Pipeline Layout"), - bind_group_layouts: &[&texture_bind_group_layout, &camera_bind_group_layout], - push_constant_ranges: &[], - }); - let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Render Pipeline"), - layout: Some(&render_pipeline_layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: "vs_main", - buffers: &[Vertex::desc(), InstanceRaw::desc()], - }, - fragment: Some(wgpu::FragmentState { - module: &shader, - entry_point: "fs_main", - targets: &[Some(wgpu::ColorTargetState { - format: config.format, - blend: Some(wgpu::BlendState::REPLACE), - write_mask: wgpu::ColorWrites::ALL, - })], - }), - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: Some(wgpu::Face::Back), - polygon_mode: wgpu::PolygonMode::Fill, - unclipped_depth: false, - conservative: false, - }, - depth_stencil: Some(wgpu::DepthStencilState { - format: Texture::DEPTH_FORMAT, - depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::Less, - stencil: wgpu::StencilState::default(), - bias: wgpu::DepthBiasState::default(), - }), - multisample: wgpu::MultisampleState { - count: 1, - mask: !0, - alpha_to_coverage_enabled: false, - }, - multiview: None, - }); - - let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(VERTICES), - usage: wgpu::BufferUsages::VERTEX, - }); - let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Index Buffer"), - contents: bytemuck::cast_slice(INDICES), - usage: wgpu::BufferUsages::INDEX, - }); - - let camera_controller = CameraController::new(0.2); - - let instances = (0..NUM_INSTANCES_PER_ROW) - .flat_map(|z| { - (0..NUM_INSTANCES_PER_ROW).map(move |x| { - let position = Vec3 { - x: x as f32, - y: 0.0, - z: z as f32, - } - INSTANCE_DISPLACEMENT; - - let rotation = if position.length().abs() <= std::f32::EPSILON { - Quat::from_axis_angle(Vec3::Z, 0.0) - } else { - Quat::from_axis_angle(position.normalize(), std::f32::consts::FRAC_PI_4) - }; - - Instance { position, rotation } - }) - }) - .collect::>(); - - let instance_data = instances.iter().map(Instance::to_raw).collect::>(); - let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Instance Buffer"), - contents: bytemuck::cast_slice(&instance_data), - usage: wgpu::BufferUsages::VERTEX, - }); - - Self { - window, - size, - surface, - device, - queue, - config, - render_pipeline, - vertex_buffer, - index_buffer, - diffuse_bind_group, - diffuse_texture, - camera, - camera_uniform, - camera_buffer, - camera_bind_group, - camera_controller, - instances, - instance_buffer, - depth_texture, - } - } -} - -impl<'s> State<'s> { - pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize) { - if new_size.width > 0 && new_size.height > 0 { - self.size = new_size; - self.config.width = new_size.width; - self.config.height = new_size.height; - self.surface.configure(&self.device, &self.config); - } - self.depth_texture = - Texture::create_depth_texture(&self.device, &self.config, "depth_texture"); - } - - pub fn update(&mut self) { - self.camera_controller.update_camera(&mut self.camera); - self.camera_uniform.update_view_or_orthographic_proj(self.camera_controller.is_orthographic(), &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()?; - let view = output - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - let mut encoder = self - .device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Render Encoder"), - }); - - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("Render Pass"), - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color { - r: 1.0, - g: 0.2, - b: 0.9, - a: 1.0, - }), - store: wgpu::StoreOp::Store, - }, - })], - depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { - view: &self.depth_texture.view, - depth_ops: Some(wgpu::Operations { - load: wgpu::LoadOp::Clear(1.0), - store: wgpu::StoreOp::Store, - }), - stencil_ops: None, - }), - ..Default::default() - }); - - render_pass.set_pipeline(&self.render_pipeline); - render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]); - render_pass.set_bind_group(1, &self.camera_bind_group, &[]); - render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); - render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..)); - render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16); - - render_pass.draw_indexed(0..INDICES.len() as _, 0, 0..self.instances.len() as _); - } - - self.queue.submit(std::iter::once(encoder.finish())); - output.present(); - - Ok(()) - } - - pub fn input(&mut self, event: &WindowEvent) -> bool { - self.camera_controller.process_events(event) - } -} diff --git a/crates/flare3d/src/state/vertex.rs b/crates/flare3d/src/state/vertex.rs deleted file mode 100644 index 46c96b9..0000000 --- a/crates/flare3d/src/state/vertex.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! Vertex implementations. - -/// Represents a vertex with position and texture coordinates. -#[repr(C)] -#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] -pub struct Vertex { - pub position: [f32; 3], - pub tex_coords: [f32; 2], -} - -impl Vertex { - pub fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { - wgpu::VertexBufferLayout { - array_stride: std::mem::size_of::() as wgpu::BufferAddress, - step_mode: wgpu::VertexStepMode::Vertex, - attributes: &[ - wgpu::VertexAttribute { - offset: 0, - shader_location: 0, - format: wgpu::VertexFormat::Float32x3, - }, - wgpu::VertexAttribute { - offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress, - shader_location: 1, - format: wgpu::VertexFormat::Float32x2, - }, - ], - } - } -} diff --git a/crates/flare3d/src/texture.rs b/crates/flare3d/src/texture.rs deleted file mode 100644 index e5d6547..0000000 --- a/crates/flare3d/src/texture.rs +++ /dev/null @@ -1,133 +0,0 @@ -//! Texture implementations. - -use anyhow::*; -use image::GenericImageView; - -/// Represents a texture. -#[derive(Debug)] -pub struct Texture { - pub texture: wgpu::Texture, - pub view: wgpu::TextureView, - pub sampler: wgpu::Sampler, -} - -impl Texture { - pub fn from_bytes( - device: &wgpu::Device, - queue: &wgpu::Queue, - bytes: &[u8], - label: &str, - ) -> Result { - let img = image::load_from_memory(bytes)?; - Self::from_image(device, queue, &img, Some(label)) - } - - pub fn from_image( - device: &wgpu::Device, - queue: &wgpu::Queue, - img: &image::DynamicImage, - label: Option<&str>, - ) -> Result { - let rgba = img.as_rgba8().unwrap(); - let dimensions = img.dimensions(); - - let size = wgpu::Extent3d { - width: dimensions.0, - height: dimensions.1, - depth_or_array_layers: 1, - }; - - let texture = device.create_texture(&wgpu::TextureDescriptor { - label, - size, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, - view_formats: &[], - }); - - queue.write_texture( - wgpu::ImageCopyTexture { - aspect: wgpu::TextureAspect::All, - texture: &texture, - mip_level: 0, - origin: wgpu::Origin3d::ZERO, - }, - rgba, - wgpu::ImageDataLayout { - offset: 0, - bytes_per_row: std::num::NonZeroU32::new(4 * dimensions.0) - .map(std::num::NonZeroU32::get), - rows_per_image: std::num::NonZeroU32::new(dimensions.1) - .map(std::num::NonZeroU32::get), - }, - size, - ); - - let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); - let sampler = device.create_sampler(&wgpu::SamplerDescriptor { - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Nearest, - mipmap_filter: wgpu::FilterMode::Nearest, - ..Default::default() - }); - - Ok(Self { - texture, - view, - sampler, - }) - } -} - -impl Texture { - pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; - - pub fn create_depth_texture( - device: &wgpu::Device, - config: &wgpu::SurfaceConfiguration, - label: &str, - ) -> Self { - let size = wgpu::Extent3d { - width: config.width, - height: config.height, - depth_or_array_layers: 1, - }; - let desc = wgpu::TextureDescriptor { - label: Some(label), - size, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: Self::DEPTH_FORMAT, - usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, - view_formats: &[], - }; - let texture = device.create_texture(&desc); - - let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); - let sampler = device.create_sampler(&wgpu::SamplerDescriptor { - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, - mipmap_filter: wgpu::FilterMode::Nearest, - compare: Some(wgpu::CompareFunction::LessEqual), - lod_min_clamp: 0.0, - lod_max_clamp: 200.0, - ..Default::default() - }); - - Self { - texture, - view, - sampler, - } - } -} diff --git a/crates/flare3d/src/window.rs b/crates/flare3d/src/window.rs deleted file mode 100644 index ec7637e..0000000 --- a/crates/flare3d/src/window.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! Window implementations. - -use winit::{ - event::*, - event_loop::{ControlFlow, EventLoop}, -}; - -use crate::state::State; - -/// Represents a window with a [State]. -#[derive(Debug)] -pub struct Window<'w> { - state: State<'w>, -} - -impl<'w> Window<'w> { - pub fn new() -> Window<'w> { - let event_loop = EventLoop::new().unwrap(); - let mut state: State<'_> = futures_executor::block_on(State::new(&event_loop)); - - #[cfg(target_os = "macos")] - let (_dl, semaphore) = { - use std::sync::{Arc, Condvar, Mutex}; - - let pair = Arc::new((Mutex::new(false), Condvar::new())); - - let pair2 = Arc::clone(&pair); - let mut dl = display_link::DisplayLink::new(move |_ts| { - let (lock, cvar) = &*pair2; - let mut do_redraw = lock.lock().unwrap(); - *do_redraw = true; - - cvar.notify_one(); - }) - .unwrap(); - - dl.resume().unwrap(); - - (dl, pair) - }; - - event_loop - .run(|event, target| { - target.set_control_flow(ControlFlow::Wait); - - match event { - Event::WindowEvent { window_id, event } if window_id == state.window.id() => { - if !state.input(&event) { - match event { - WindowEvent::CloseRequested => target.exit(), - WindowEvent::Resized(physical_size) => { - state.resize(physical_size); - } - WindowEvent::RedrawRequested => { - state.update(); - match state.render() { - Ok(_) => {} - Err(wgpu::SurfaceError::Lost) => state.resize(state.size), - Err(wgpu::SurfaceError::OutOfMemory) => target.exit(), - Err(e) => eprintln!("{:?}", e), - } - } - _ => (), - } - } - } - - Event::AboutToWait => { - #[cfg(target_os = "macos")] - { - let (lock, cvar) = &*semaphore; - let mut do_redraw = lock.lock().unwrap(); - - while !*do_redraw { - do_redraw = cvar.wait(do_redraw).unwrap(); - } - - *do_redraw = false; - } - - state.window.request_redraw(); - } - _ => (), - } - }) - .unwrap(); - - Self { state } - } -}