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

View File

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

View File

@ -1,6 +1,7 @@
use std::collections::HashMap;
use std::sync::Mutex;
use cgmath::{InnerSpace, Vector3};
use crate::body::Body;
use rayon::prelude::*;
const G: f64 = 6.67430e-11;
@ -50,10 +51,12 @@ impl Simulator {
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>> {
let mut accels = vec![Vector3::new(0.0, 0.0, 0.0); states.len()];
fn compute_accelerations(states: &[State], masses: &[f64]) -> Vec<Vector3<f64>> {
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 dist_sq = r.magnitude2();
let dist = dist_sq.sqrt();
@ -64,16 +67,24 @@ impl Simulator {
let force = G * masses[i] * masses[j] / dist_sq;
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_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)| {
State {
@ -83,7 +94,7 @@ impl Simulator {
}).collect();
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 {
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_vel = compute_accelerations(&temp_states, &masses, &ownership);
let k3_vel = compute_accelerations(&temp_states, &masses);
for i in 0..n {
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_vel = compute_accelerations(&temp_states, &masses, &ownership);
let k4_vel = compute_accelerations(&temp_states, &masses);
for i in 0..n {
let body = &mut self.bodies[i];
@ -111,33 +122,6 @@ impl Simulator {
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) {
if let Some(new) = self.timewarp.checked_mul(2) {
if new <= MAX_TIMEWARP {

View File

@ -9,6 +9,7 @@ use crate::geometry_manager::GeometryManager;
use crate::globals::GlobalsManager;
use crate::instance_manager::InstanceManager;
use crate::light::{LightManager};
use crate::material::{GpuMaterial, MaterialManager};
use crate::renderer::{RenderInstance, Renderer};
pub struct SampleCount(pub u32);
@ -34,6 +35,7 @@ pub struct State<'a> {
pub geometry_manager: GeometryManager,
pub instance_manager: InstanceManager,
pub light_manager: LightManager,
pub material_manager: MaterialManager,
pub renderer: Renderer,
}
@ -64,11 +66,24 @@ impl<'a> State<'a> {
let instance_manager = InstanceManager::new(&device);
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(
&device,
&config,
globals.layout(),
&mut light_manager,
&material_manager,
&camera,
sample_count.get(),
);
@ -86,6 +101,7 @@ impl<'a> State<'a> {
geometry_manager,
instance_manager,
light_manager,
material_manager,
renderer,
}
}
@ -193,7 +209,7 @@ impl<'a> State<'a> {
&mut self.light_manager,
&self.geometry_manager,
&self.instance_manager,
&mut self.material_manager
)
}