Added Materials - Removed moon and advanced orbits for now to focus on post processing and materials

This commit is contained in:
Verox001 2025-05-10 19:49:05 +02:00
parent 573e9e9687
commit cb64d94c09
7 changed files with 130 additions and 52 deletions

View File

@ -22,7 +22,7 @@ pub async fn run() {
radius: 6.371e6, radius: 6.371e6,
}); });
let earth_position = sim.bodies[1].position; /*let earth_position = sim.bodies[1].position;
let earth_velocity = sim.bodies[1].velocity; let earth_velocity = sim.bodies[1].velocity;
sim.add_body(Body { sim.add_body(Body {
@ -31,7 +31,7 @@ pub async fn run() {
velocity: earth_velocity + Vector3::new(0.0, 1022.0, 0.0), velocity: earth_velocity + Vector3::new(0.0, 1022.0, 0.0),
mass: 7.342e22, mass: 7.342e22,
radius: 1.737e6, radius: 1.737e6,
}); });*/
} }
let sim_clone = simulator.clone(); let sim_clone = simulator.clone();

View File

@ -9,6 +9,7 @@ mod renderer;
mod instance_manager; mod instance_manager;
mod globals; mod globals;
mod geometry_manager; mod geometry_manager;
mod material;
pub use body::Body; pub use body::Body;

View File

@ -0,0 +1,58 @@
use wgpu::{Buffer, Device, Queue};
use wgpu::util::DeviceExt;
use bytemuck::{Pod, Zeroable};
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct GpuMaterial {
pub albedo: [f32; 3],
pub emissive: [f32; 3],
pub metallic: f32,
pub roughness: f32,
}
pub struct MaterialManager {
materials: Vec<GpuMaterial>,
buffer: Buffer,
pub layout: wgpu::BindGroupLayout,
pub bind_group: wgpu::BindGroup,
}
impl MaterialManager {
pub fn new(device: &Device, materials: Vec<GpuMaterial>) -> Self {
let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Material Buffer"),
contents: bytemuck::cast_slice(&materials),
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
});
let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("Material BindGroupLayout"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: true },
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}],
});
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("Material BindGroup"),
layout: &layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: buffer.as_entire_binding(),
}],
});
Self { materials, buffer, layout, bind_group }
}
pub fn update(&mut self, queue: &Queue) {
queue.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&self.materials));
}
}

View File

@ -4,6 +4,7 @@ use crate::globals::GlobalsManager;
use crate::instance_manager::InstanceManager; use crate::instance_manager::InstanceManager;
use crate::light::LightManager; use crate::light::LightManager;
use wgpu::{Device, Queue, SurfaceTexture, TextureView}; use wgpu::{Device, Queue, SurfaceTexture, TextureView};
use crate::material::MaterialManager;
pub struct RenderInstance { pub struct RenderInstance {
pub position: cgmath::Vector3<f32>, pub position: cgmath::Vector3<f32>,
@ -77,7 +78,7 @@ impl Vertex {
pub struct Renderer { pub struct Renderer {
pipeline: wgpu::RenderPipeline, pipeline: wgpu::RenderPipeline,
depth_texture: TextureView, depth_texture: TextureView,
sample_count: u32, sample_count: u32
} }
impl Renderer { impl Renderer {
@ -86,6 +87,7 @@ impl Renderer {
config: &wgpu::SurfaceConfiguration, config: &wgpu::SurfaceConfiguration,
global_layout: &wgpu::BindGroupLayout, global_layout: &wgpu::BindGroupLayout,
light_manager: &mut LightManager, light_manager: &mut LightManager,
material_manager: &MaterialManager,
camera: &Camera, camera: &Camera,
sample_count: u32, sample_count: u32,
) -> Self { ) -> Self {
@ -109,6 +111,7 @@ impl Renderer {
global_layout, global_layout,
&light_manager.layout, &light_manager.layout,
&cluster_buffers.layout, &cluster_buffers.layout,
&material_manager.layout,
], ],
push_constant_ranges: &[], push_constant_ranges: &[],
}); });
@ -206,6 +209,7 @@ impl Renderer {
light_manager: &mut LightManager, light_manager: &mut LightManager,
geometry: &GeometryManager, geometry: &GeometryManager,
instances: &InstanceManager, instances: &InstanceManager,
material_manager: &mut MaterialManager,
) -> Result<(), wgpu::SurfaceError> { ) -> Result<(), wgpu::SurfaceError> {
// Update uniform buffer // Update uniform buffer
globals.update(queue, camera); globals.update(queue, camera);
@ -220,6 +224,9 @@ impl Renderer {
light_manager.update_cluster_buffers(device, queue, &assignment); light_manager.update_cluster_buffers(device, queue, &assignment);
light_manager.update_gpu(queue); light_manager.update_gpu(queue);
// Update material buffer
material_manager.update(queue);
let multisampled_texture = device.create_texture(&wgpu::TextureDescriptor { let multisampled_texture = device.create_texture(&wgpu::TextureDescriptor {
label: Some("Multisample Target"), label: Some("Multisample Target"),
size: wgpu::Extent3d { size: wgpu::Extent3d {
@ -274,6 +281,7 @@ impl Renderer {
if let Some(clusters) = &light_manager.cluster_buffers { if let Some(clusters) = &light_manager.cluster_buffers {
pass.set_bind_group(2, &clusters.bind_group, &[]); pass.set_bind_group(2, &clusters.bind_group, &[]);
} }
pass.set_bind_group(3, &material_manager.bind_group, &[]);
for shape in geometry.shapes() { for shape in geometry.shapes() {
if let Some(mesh) = geometry.get(&shape) { if let Some(mesh) = geometry.get(&shape) {

View File

@ -62,6 +62,17 @@ var<storage, read> cluster_light_indices: array<u32>;
@group(2) @binding(1) @group(2) @binding(1)
var<storage, read> cluster_offsets: array<vec2<u32>>; var<storage, read> cluster_offsets: array<vec2<u32>>;
struct GpuMaterial {
albedo: vec3<f32>,
emissive: vec3<f32>,
metallic: f32,
roughness: f32,
_pad: vec2<f32>,
};
@group(3) @binding(0)
var<storage, read> materials: array<GpuMaterial>;
@vertex @vertex
fn vs_main(vertex: VertexInput, instance: InstanceInput) -> VSOutput { fn vs_main(vertex: VertexInput, instance: InstanceInput) -> VSOutput {
var out: VSOutput; var out: VSOutput;

View File

@ -1,6 +1,7 @@
use std::collections::HashMap; use std::sync::Mutex;
use cgmath::{InnerSpace, Vector3}; use cgmath::{InnerSpace, Vector3};
use crate::body::Body; use crate::body::Body;
use rayon::prelude::*;
const G: f64 = 6.67430e-11; const G: f64 = 6.67430e-11;
@ -50,10 +51,12 @@ impl Simulator {
let masses: Vec<f64> = self.bodies.iter().map(|b| b.mass).collect(); let masses: Vec<f64> = self.bodies.iter().map(|b| b.mass).collect();
fn compute_accelerations(states: &[State], masses: &[f64], ownership: &HashMap<usize, usize>) -> Vec<Vector3<f64>> { fn compute_accelerations(states: &[State], masses: &[f64]) -> Vec<Vector3<f64>> {
let mut accels = vec![Vector3::new(0.0, 0.0, 0.0); states.len()]; let n = states.len();
let accels = (0..n).map(|_| Mutex::new(Vector3::new(0.0, 0.0, 0.0))).collect::<Vec<_>>();
for (&i, &j) in ownership { (0..n).into_par_iter().for_each(|i| {
for j in (i + 1)..n {
let r = states[j].position - states[i].position; let r = states[j].position - states[i].position;
let dist_sq = r.magnitude2(); let dist_sq = r.magnitude2();
let dist = dist_sq.sqrt(); let dist = dist_sq.sqrt();
@ -64,16 +67,24 @@ impl Simulator {
let force = G * masses[i] * masses[j] / dist_sq; let force = G * masses[i] * masses[j] / dist_sq;
let accel = force * r / (dist * masses[i]); let accel = force * r / (dist * masses[i]);
let accel_j = -force * r / (dist * masses[j]);
accels[i] += accel; {
let mut a_i_lock = accels[i].lock().unwrap();
*a_i_lock += accel;
}
{
let mut a_j_lock = accels[j].lock().unwrap();
*a_j_lock += accel_j;
}
}
});
accels.into_iter().map(|mutex| mutex.into_inner().unwrap()).collect()
} }
accels
}
let ownership = self.compute_soi_owners();
let k1_pos = original_states.iter().map(|s| s.velocity).collect::<Vec<_>>(); let k1_pos = original_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
let k1_vel = compute_accelerations(&original_states, &masses, &ownership); let k1_vel = compute_accelerations(&original_states, &masses);
let mut temp_states: Vec<State> = original_states.iter().enumerate().map(|(i, s)| { let mut temp_states: Vec<State> = original_states.iter().enumerate().map(|(i, s)| {
State { State {
@ -83,7 +94,7 @@ impl Simulator {
}).collect(); }).collect();
let k2_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>(); let k2_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
let k2_vel = compute_accelerations(&temp_states, &masses, &ownership); let k2_vel = compute_accelerations(&temp_states, &masses);
for i in 0..n { for i in 0..n {
temp_states[i].position = original_states[i].position + k2_pos[i] * (dt / 2.0); temp_states[i].position = original_states[i].position + k2_pos[i] * (dt / 2.0);
@ -91,7 +102,7 @@ impl Simulator {
} }
let k3_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>(); let k3_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
let k3_vel = compute_accelerations(&temp_states, &masses, &ownership); let k3_vel = compute_accelerations(&temp_states, &masses);
for i in 0..n { for i in 0..n {
temp_states[i].position = original_states[i].position + k3_pos[i] * dt; temp_states[i].position = original_states[i].position + k3_pos[i] * dt;
@ -99,7 +110,7 @@ impl Simulator {
} }
let k4_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>(); let k4_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
let k4_vel = compute_accelerations(&temp_states, &masses, &ownership); let k4_vel = compute_accelerations(&temp_states, &masses);
for i in 0..n { for i in 0..n {
let body = &mut self.bodies[i]; let body = &mut self.bodies[i];
@ -111,33 +122,6 @@ impl Simulator {
self.time += dt; self.time += dt;
} }
fn compute_soi_owners(&self) -> HashMap<usize, usize> {
let mut ownership = HashMap::new();
for (i, body) in self.bodies.iter().enumerate() {
let mut min_distance = f64::MAX;
let mut dominant_index = None;
for (j, other) in self.bodies.iter().enumerate() {
if i == j {
continue;
}
let r = (body.position - other.position).magnitude();
let soi_radius = r * (body.mass / other.mass).powf(2.0 / 5.0);
if r < soi_radius && r < min_distance {
min_distance = r;
dominant_index = Some(j);
}
}
if let Some(j) = dominant_index {
ownership.insert(i, j);
}
}
ownership
}
pub fn increase_timewarp(&mut self) { pub fn increase_timewarp(&mut self) {
if let Some(new) = self.timewarp.checked_mul(2) { if let Some(new) = self.timewarp.checked_mul(2) {
if new <= MAX_TIMEWARP { if new <= MAX_TIMEWARP {

View File

@ -9,6 +9,7 @@ use crate::geometry_manager::GeometryManager;
use crate::globals::GlobalsManager; use crate::globals::GlobalsManager;
use crate::instance_manager::InstanceManager; use crate::instance_manager::InstanceManager;
use crate::light::{LightManager}; use crate::light::{LightManager};
use crate::material::{GpuMaterial, MaterialManager};
use crate::renderer::{RenderInstance, Renderer}; use crate::renderer::{RenderInstance, Renderer};
pub struct SampleCount(pub u32); pub struct SampleCount(pub u32);
@ -34,6 +35,7 @@ pub struct State<'a> {
pub geometry_manager: GeometryManager, pub geometry_manager: GeometryManager,
pub instance_manager: InstanceManager, pub instance_manager: InstanceManager,
pub light_manager: LightManager, pub light_manager: LightManager,
pub material_manager: MaterialManager,
pub renderer: Renderer, pub renderer: Renderer,
} }
@ -64,11 +66,24 @@ impl<'a> State<'a> {
let instance_manager = InstanceManager::new(&device); let instance_manager = InstanceManager::new(&device);
let mut light_manager = LightManager::new(&device, 100); let mut light_manager = LightManager::new(&device, 100);
let initial_materials = vec![
GpuMaterial {
albedo: [1.0, 1.0, 1.0],
emissive: [0.0, 0.0, 0.0],
metallic: 0.0,
roughness: 0.5,
};
8
];
let mut material_manager = MaterialManager::new(&device, initial_materials);
let renderer = Renderer::new( let renderer = Renderer::new(
&device, &device,
&config, &config,
globals.layout(), globals.layout(),
&mut light_manager, &mut light_manager,
&material_manager,
&camera, &camera,
sample_count.get(), sample_count.get(),
); );
@ -86,6 +101,7 @@ impl<'a> State<'a> {
geometry_manager, geometry_manager,
instance_manager, instance_manager,
light_manager, light_manager,
material_manager,
renderer, renderer,
} }
} }
@ -193,7 +209,7 @@ impl<'a> State<'a> {
&mut self.light_manager, &mut self.light_manager,
&self.geometry_manager, &self.geometry_manager,
&self.instance_manager, &self.instance_manager,
&mut self.material_manager
) )
} }