Refactored and structured code to reduce load in state

This commit is contained in:
Verox001 2025-05-08 20:24:00 +02:00
parent f4484ba335
commit 31d4d53316
9 changed files with 179 additions and 195 deletions

View File

@ -1,5 +1,5 @@
use cgmath::{Rotation3, Vector3};
use solar_engine::{Application, Body, InputEvent, Key, Light, LightType, MouseButton, Simulator};
use solar_engine::{Application, Body, InputEvent, Key, Light, MouseButton, RenderInstance, Shape, Simulator};
use std::sync::{Arc, RwLock};
use std::thread;
@ -74,7 +74,7 @@ pub async fn run() {
.iter()
.enumerate()
.map(|(i, b)| {
solar_engine::RenderInstance {
RenderInstance {
position: ((b.position / 1.496e11) - sun_pos).cast::<f32>().unwrap(),
rotation: cgmath::Quaternion::from_angle_z(cgmath::Deg(0.0)),
color: match i {
@ -83,7 +83,7 @@ pub async fn run() {
_ => [0.5, 0.5, 0.5],
},
scale: 0.05,
shape: solar_engine::Shape::Sphere,
shape: Shape::Sphere,
always_lit: i == 0, // Sun
is_transparent: false,
}

View File

@ -1,5 +1,5 @@
use wgpu::{Device, Queue, Surface, SurfaceConfiguration};
use crate::render::SampleCount;
use crate::state::SampleCount;
pub struct DeviceManager<'a> {
pub surface: Surface<'a>,

View File

@ -1,7 +1,19 @@
use std::collections::HashMap;
use wgpu::{Device, Buffer};
use crate::render::{create_circle_vertices, create_sphere_vertices, Geometry, Shape, Vertex};
use wgpu::util::DeviceExt;
use crate::renderer::Vertex;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Shape {
Circle,
Sphere,
}
pub struct Geometry {
pub(crate) vertex_buffer: Buffer,
pub(crate) index_buffer: Buffer,
pub(crate) index_count: u32,
}
pub struct GeometryManager {
pub geometries: HashMap<Shape, Geometry>,
@ -58,3 +70,73 @@ impl GeometryManager {
}
}
}
pub fn create_circle_vertices(segment_count: usize, radius: f32, color: [f32; 3]) -> (Vec<Vertex>, Vec<u16>) {
let mut vertices = vec![Vertex {
position: [0.0, 0.0, 0.0],
color,
normal: [0.0, 0.0, 1.0],
}];
let mut indices = vec![];
for i in 0..=segment_count {
let theta = (i as f32) / (segment_count as f32) * std::f32::consts::TAU;
let x = radius * theta.cos();
let y = radius * theta.sin();
vertices.push(Vertex {
position: [x, y, 0.0],
color,
normal: [0.0, 0.0, 1.0],
});
}
for i in 1..=segment_count {
indices.push(0);
indices.push(i as u16);
indices.push((i % segment_count + 1) as u16);
}
(vertices, indices)
}
pub fn create_sphere_vertices(stacks: usize, slices: usize, radius: f32, color: [f32; 3]) -> (Vec<Vertex>, Vec<u16>) {
let mut vertices = Vec::new();
let mut indices = Vec::new();
for i in 0..=stacks {
let phi = std::f32::consts::PI * (i as f32) / (stacks as f32);
let y = phi.cos();
let r = phi.sin();
for j in 0..=slices {
let theta = 2.0 * std::f32::consts::PI * (j as f32) / (slices as f32);
let x = r * theta.cos();
let z = r * theta.sin();
let normal = [x, y, z];
vertices.push(Vertex {
position: [x * radius, y * radius, z * radius],
color,
normal,
});
}
}
for i in 0..stacks {
for j in 0..slices {
let first = i * (slices + 1) + j;
let second = first + slices + 1;
indices.push(first as u16);
indices.push(second as u16);
indices.push((first + 1) as u16);
indices.push(second as u16);
indices.push((second + 1) as u16);
indices.push((first + 1) as u16);
}
}
(vertices, indices)
}

View File

@ -1,5 +1,4 @@
use crate::camera::Camera;
use crate::render::Globals;
use wgpu::{BindGroup, BindGroupLayout, Buffer, Device, Queue};
use bytemuck::{Pod, Zeroable};
use wgpu::util::DeviceExt;

View File

@ -1,7 +1,8 @@
use crate::render::{InstanceRaw, RenderInstance, Shape};
use wgpu::{Buffer, Device, Queue};
use wgpu::util::DeviceExt;
use std::mem::size_of;
use crate::geometry_manager::Shape;
use crate::renderer::{InstanceRaw, RenderInstance};
pub struct InstanceManager {
instances: Vec<RenderInstance>,

View File

@ -1,7 +1,6 @@
mod body;
mod simulator;
mod state;
mod render;
mod application;
mod input;
mod camera;
@ -19,15 +18,16 @@ pub use simulator::distance_squared;
pub use application::StateApplication as Application;
pub use render::RenderInstance;
pub use render::Shape;
pub use state::State;
pub use renderer::RenderInstance;
pub use light::Light;
pub use light::LightType;
pub use geometry_manager::Shape;
pub use input::Key;
pub use input::map_winit_key;
pub use input::InputEvent;
pub use input::MouseButton;
pub use light::Light;
pub use light::LightType;
pub use input::MouseButton;

View File

@ -1,167 +0,0 @@
#[repr(C)]
#[derive(Clone, Copy, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Globals {
pub view_proj: [[f32; 4]; 4],
pub resolution: [f32; 2],
pub _padding: [f32; 2],
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Shape {
Circle,
Sphere,
}
pub struct Geometry {
pub(crate) vertex_buffer: wgpu::Buffer,
pub(crate) index_buffer: wgpu::Buffer,
pub(crate) index_count: u32,
}
pub struct RenderInstance {
pub position: cgmath::Vector3<f32>,
pub rotation: cgmath::Quaternion<f32>,
pub color: [f32; 3],
pub scale: f32,
pub shape: Shape,
pub always_lit: bool,
pub is_transparent: bool
}
impl RenderInstance {
pub fn to_raw(&self) -> InstanceRaw {
let model = cgmath::Matrix4::from_translation(self.position)
* cgmath::Matrix4::from(self.rotation)
* cgmath::Matrix4::from_scale(self.scale);
InstanceRaw {
model: model.into(),
color: self.color,
flags: (self.always_lit as u32) | ((self.is_transparent as u32) << 1)
}
}
}
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct InstanceRaw {
model: [[f32; 4]; 4],
color: [f32; 3],
flags: u32,
}
impl InstanceRaw {
pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: size_of::<InstanceRaw>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute { offset: 0, shader_location: 5, format: wgpu::VertexFormat::Float32x4 },
wgpu::VertexAttribute { offset: 16, shader_location: 6, format: wgpu::VertexFormat::Float32x4 },
wgpu::VertexAttribute { offset: 32, shader_location: 7, format: wgpu::VertexFormat::Float32x4 },
wgpu::VertexAttribute { offset: 48, shader_location: 8, format: wgpu::VertexFormat::Float32x4 },
wgpu::VertexAttribute { offset: 64, shader_location: 9, format: wgpu::VertexFormat::Float32x3 },
wgpu::VertexAttribute { offset: 76, shader_location: 10, format: wgpu::VertexFormat::Uint32 },
],
}
}
}
pub struct SampleCount(pub u32);
impl SampleCount {
pub fn get(&self) -> u32 {
self.0
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Vertex {
pub(crate) position: [f32; 3],
pub(crate) color: [f32; 3],
pub(crate) normal: [f32; 3],
}
impl Vertex {
const ATTRIBS: [wgpu::VertexAttribute; 3] =
wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x3];
pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &Self::ATTRIBS,
}
}
}
pub fn create_circle_vertices(segment_count: usize, radius: f32, color: [f32; 3]) -> (Vec<Vertex>, Vec<u16>) {
let mut vertices = vec![Vertex {
position: [0.0, 0.0, 0.0],
color,
normal: [0.0, 0.0, 1.0],
}];
let mut indices = vec![];
for i in 0..=segment_count {
let theta = (i as f32) / (segment_count as f32) * std::f32::consts::TAU;
let x = radius * theta.cos();
let y = radius * theta.sin();
vertices.push(Vertex {
position: [x, y, 0.0],
color,
normal: [0.0, 0.0, 1.0],
});
}
for i in 1..=segment_count {
indices.push(0);
indices.push(i as u16);
indices.push((i % segment_count + 1) as u16);
}
(vertices, indices)
}
pub fn create_sphere_vertices(stacks: usize, slices: usize, radius: f32, color: [f32; 3]) -> (Vec<Vertex>, Vec<u16>) {
let mut vertices = Vec::new();
let mut indices = Vec::new();
for i in 0..=stacks {
let phi = std::f32::consts::PI * (i as f32) / (stacks as f32);
let y = phi.cos();
let r = phi.sin();
for j in 0..=slices {
let theta = 2.0 * std::f32::consts::PI * (j as f32) / (slices as f32);
let x = r * theta.cos();
let z = r * theta.sin();
let normal = [x, y, z];
vertices.push(Vertex {
position: [x * radius, y * radius, z * radius],
color,
normal,
});
}
}
for i in 0..stacks {
for j in 0..slices {
let first = i * (slices + 1) + j;
let second = first + slices + 1;
indices.push(first as u16);
indices.push(second as u16);
indices.push((first + 1) as u16);
indices.push(second as u16);
indices.push((second + 1) as u16);
indices.push((first + 1) as u16);
}
}
(vertices, indices)
}

View File

@ -1,12 +1,79 @@
use crate::camera::Camera;
use crate::geometry_manager::GeometryManager;
use crate::geometry_manager::{GeometryManager, Shape};
use crate::globals::GlobalsManager;
use crate::instance_manager::InstanceManager;
use crate::light::LightManager;
use crate::render::{Geometry, InstanceRaw, Shape};
use std::collections::HashMap;
use wgpu::{Device, Queue, SurfaceTexture, TextureView};
pub struct RenderInstance {
pub position: cgmath::Vector3<f32>,
pub rotation: cgmath::Quaternion<f32>,
pub color: [f32; 3],
pub scale: f32,
pub shape: Shape,
pub always_lit: bool,
pub is_transparent: bool
}
impl RenderInstance {
pub fn to_raw(&self) -> InstanceRaw {
let model = cgmath::Matrix4::from_translation(self.position)
* cgmath::Matrix4::from(self.rotation)
* cgmath::Matrix4::from_scale(self.scale);
InstanceRaw {
model: model.into(),
color: self.color,
flags: (self.always_lit as u32) | ((self.is_transparent as u32) << 1)
}
}
}
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct InstanceRaw {
model: [[f32; 4]; 4],
color: [f32; 3],
flags: u32,
}
impl InstanceRaw {
pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: size_of::<InstanceRaw>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute { offset: 0, shader_location: 5, format: wgpu::VertexFormat::Float32x4 },
wgpu::VertexAttribute { offset: 16, shader_location: 6, format: wgpu::VertexFormat::Float32x4 },
wgpu::VertexAttribute { offset: 32, shader_location: 7, format: wgpu::VertexFormat::Float32x4 },
wgpu::VertexAttribute { offset: 48, shader_location: 8, format: wgpu::VertexFormat::Float32x4 },
wgpu::VertexAttribute { offset: 64, shader_location: 9, format: wgpu::VertexFormat::Float32x3 },
wgpu::VertexAttribute { offset: 76, shader_location: 10, format: wgpu::VertexFormat::Uint32 },
],
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Vertex {
pub(crate) position: [f32; 3],
pub(crate) color: [f32; 3],
pub(crate) normal: [f32; 3],
}
impl Vertex {
const ATTRIBS: [wgpu::VertexAttribute; 3] =
wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x3];
pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &Self::ATTRIBS,
}
}
}
pub struct Renderer {
pipeline: wgpu::RenderPipeline,
depth_texture: TextureView,
@ -52,7 +119,7 @@ impl Renderer {
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_main"),
buffers: &[crate::render::Vertex::desc(), InstanceRaw::desc()],
buffers: &[Vertex::desc(), InstanceRaw::desc()],
compilation_options: Default::default(),
},
fragment: Some(wgpu::FragmentState {

View File

@ -1,21 +1,23 @@
use std::cmp::max;
use std::collections::HashMap;
use std::sync::{Arc};
use cgmath::{perspective, Deg, Matrix4, Point3, Vector3};
use log::info;
use pollster::FutureExt;
use wgpu::util::DeviceExt;
use wgpu::{Adapter, BindGroup, BindGroupLayout, Device, Instance, PresentMode, Queue, Surface, SurfaceCapabilities, SurfaceConfiguration, SurfaceError};
use wgpu::{Adapter, Device, Instance, PresentMode, Queue, Surface, SurfaceCapabilities, SurfaceConfiguration, SurfaceError};
use winit::dpi::PhysicalSize;
use winit::window::{Window};
use crate::camera::Camera;
use crate::device_manager::DeviceManager;
use crate::geometry_manager::GeometryManager;
use crate::globals::GlobalsManager;
use crate::instance_manager::InstanceManager;
use crate::light::{ClusterBuffers, GpuLight, LightManager};
use crate::render::{create_circle_vertices, create_sphere_vertices, Geometry, Globals, InstanceRaw, RenderInstance, SampleCount, Shape, Vertex};
use crate::renderer::Renderer;
use crate::light::{LightManager};
use crate::renderer::{RenderInstance, Renderer};
pub struct SampleCount(pub u32);
impl SampleCount {
pub fn get(&self) -> u32 {
self.0
}
}
pub struct State<'a> {
surface: Surface<'a>,