working shadows kinda

This commit is contained in:
Flima Desktop 2025-12-03 21:28:27 +00:00
parent 45ec2fd936
commit d3d2437fa2
4 changed files with 118 additions and 39 deletions

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use macroquad::prelude as mq; use macroquad::prelude as mq;
use nalgebra as na; use nalgebra as na;
use rapier3d::prelude as rp; use rapier3d::prelude::{self as rp, ColliderHandle};
fn random_color() -> mq::Color { fn random_color() -> mq::Color {
return mq::Color::new( return mq::Color::new(
@ -53,12 +53,17 @@ impl World {
); );
} }
pub fn position_of_rb( pub fn clear_ofb(&mut self) {
&self, let mut coll_to_del: Vec<ColliderHandle> = Vec::new();
rigid_body_handle: rp::RigidBodyHandle, for (handle, col) in self.colliders.iter() {
) -> Option<na::Vector3<f32>> { if (col.translation().y < -15.0) {
let body = self.bodies.get(rigid_body_handle)?; coll_to_del.push(handle);
return Some(*body.translation()); }
}
for handle in coll_to_del {
self.colliders
.remove(handle, &mut self.island_manager, &mut self.bodies, false);
}
} }
pub fn position_of_collider( pub fn position_of_collider(
@ -138,3 +143,30 @@ impl Default for World {
}; };
} }
} }
pub fn collider_world_aabb(world: &World, handle: rp::ColliderHandle) -> (mq::Vec3, mq::Vec3) {
use rp::ShapeType;
let pos: glam::Vec3 = world.position_of_collider(handle).unwrap().into();
let shape = world.colliders.get(handle).unwrap().shape();
match shape.shape_type() {
ShapeType::Cuboid => {
let he: glam::Vec3 = (shape.as_cuboid().unwrap().half_extents * 2.0).into();
let min = mq::vec3(pos.x - he.x * 0.5, pos.y - he.y * 0.5, pos.z - he.z * 0.5);
let max = mq::vec3(pos.x + he.x * 0.5, pos.y + he.y * 0.5, pos.z + he.z * 0.5);
(min, max)
}
ShapeType::Ball => {
let r = shape.as_ball().unwrap().radius;
let min = pos - mq::vec3(r, r, r);
let max = pos + mq::vec3(r, r, r);
(min, max)
}
_ => {
// Default fallback
(pos - mq::vec3(1.0, 1.0, 1.0), pos + mq::vec3(1.0, 1.0, 1.0))
}
}
}

View File

@ -8,7 +8,6 @@ mod camera;
mod rendering; mod rendering;
mod graphics_util; mod graphics_util;
use graphics_util::*;
use crate::rendering::Renderer; use crate::rendering::Renderer;
@ -19,20 +18,21 @@ async fn main() {
// Physics Initialization // Physics Initialization
world.register_free_collider( world.register_free_collider(
ColliderBuilder::cuboid(100.0, 10.0, 100.0) ColliderBuilder::cuboid(50.0, 5.0, 50.0)
.restitution(0.2) .restitution(0.5)
.build(), .build(),
None, None,
); );
add_objects(&mut world); add_objects(&mut world);
let mut i = 0;
loop { loop {
renderer.update_camera(); renderer.update_camera();
if mq::is_key_pressed(mq::KeyCode::L) { if mq::is_key_pressed(mq::KeyCode::L) {
renderer renderer
.light .light
.set_location(renderer.camera.position, renderer.camera.front); .set_location(renderer.camera.position, renderer.camera.front);
renderer.update_light(); renderer.update_light(&world);
println!( println!(
"Light Pos: {}, Light Front Vec{}", "Light Pos: {}, Light Front Vec{}",
renderer.light.position, renderer.light.front renderer.light.position, renderer.light.front
@ -50,7 +50,13 @@ async fn main() {
world.step(); world.step();
renderer.draw(&mut world); renderer.draw(&mut world);
mq::next_frame().await mq::next_frame().await;
i += 1;
if i > 30 {
world.clear_ofb();
renderer.update_light(&world);
}
} }
} }
@ -63,8 +69,8 @@ fn add_objects(world: &mut World) {
.build(), .build(),
); );
world.register_collider( world.register_collider(
ColliderBuilder::cuboid(10.0, 10.0, 10.0) ColliderBuilder::cuboid(5.0, 5.0, 5.0)
.restitution(0.5) .restitution(0.3)
.build(), .build(),
body, body,
None, None,

View File

@ -1,10 +1,10 @@
use crate::{ use crate::{
camera::{self as cam, FirstPersonCamera}, camera::{self as cam, FirstPersonCamera},
engine::World, engine::{self, World},
graphics_util::draw_cuboid, graphics_util::draw_cuboid,
}; };
use macroquad::prelude as mq; use macroquad::prelude as mq;
use macroquad::ui::{hash, Ui}; use macroquad::ui::hash;
use rapier3d::prelude::*; use rapier3d::prelude::*;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
@ -143,7 +143,7 @@ impl Renderer {
}, },
mq::MaterialParams { mq::MaterialParams {
pipeline_params: mq::PipelineParams { pipeline_params: mq::PipelineParams {
cull_face: macroquad::miniquad::CullFace::Back, // cull_face: macroquad::miniquad::CullFace::Back,
depth_test: mq::Comparison::LessOrEqual, depth_test: mq::Comparison::LessOrEqual,
depth_write: true, depth_write: true,
..Default::default() ..Default::default()
@ -182,7 +182,6 @@ impl Renderer {
}; };
r.light r.light
.set_location(mq::vec3(10.0, 40.0, 10.0), mq::Vec3::NEG_Y); .set_location(mq::vec3(10.0, 40.0, 10.0), mq::Vec3::NEG_Y);
r.update_light();
r.apply_config(); r.apply_config();
return r; return r;
} }
@ -193,15 +192,57 @@ impl Renderer {
pub fn update_camera(&mut self) { pub fn update_camera(&mut self) {
self.camera.update(mq::get_frame_time()); self.camera.update(mq::get_frame_time());
} }
pub fn update_light(&mut self) { pub fn update_light(&mut self, world: &World) {
let light_view = self.light.view_matrix;
let mut min_ls = mq::vec3(f32::MAX, f32::MAX, f32::MAX);
let mut max_ls = mq::vec3(f32::MIN, f32::MIN, f32::MIN);
// 1. iterate all world objects
for (handle, _) in world.colliders.iter() {
let (min_ws, max_ws) = engine::collider_world_aabb(world, handle);
// 2. get 8 corners of the world-space AABB
for &corner in &[
mq::vec3(min_ws.x, min_ws.y, min_ws.z),
mq::vec3(min_ws.x, min_ws.y, max_ws.z),
mq::vec3(min_ws.x, max_ws.y, min_ws.z),
mq::vec3(min_ws.x, max_ws.y, max_ws.z),
mq::vec3(max_ws.x, min_ws.y, min_ws.z),
mq::vec3(max_ws.x, min_ws.y, max_ws.z),
mq::vec3(max_ws.x, max_ws.y, min_ws.z),
mq::vec3(max_ws.x, max_ws.y, max_ws.z),
] {
// 3. transform to light space
let p = light_view.transform_point3(corner);
min_ls.x = min_ls.x.min(p.x);
min_ls.y = min_ls.y.min(p.y);
min_ls.z = min_ls.z.min(p.z);
max_ls.x = max_ls.x.max(p.x);
max_ls.y = max_ls.y.max(p.y);
max_ls.z = max_ls.z.max(p.z);
}
}
// 4. build tight-fitting orthographic projection
self.light.projection_matrix = mq::Mat4::orthographic_rh(
min_ls.x, max_ls.x, // left/right
min_ls.y, max_ls.y, // bottom/top
-max_ls.z, -min_ls.z, // near/far (RH coordinate system)
);
// 5. upload to materials
let light_space_matrix = self.light.get_space_matrix(); let light_space_matrix = self.light.get_space_matrix();
self.base_material self.base_material
.set_uniform(MaterialUni::LightPosition.as_str(), self.light.position); .set_uniform("light_position", self.light.position);
self.base_material self.base_material
.set_uniform(MaterialUni::LightSpaceMatrix.as_str(), light_space_matrix); .set_uniform("light_space_matrix", light_space_matrix);
self.depth_material self.depth_material
.set_uniform(MaterialUni::LightSpaceMatrix.as_str(), light_space_matrix); .set_uniform("light_space_matrix", light_space_matrix);
} }
fn render_depth(&mut self, mut world: &mut World) { fn render_depth(&mut self, mut world: &mut World) {
mq::set_camera(&mq::Camera3D { mq::set_camera(&mq::Camera3D {
position: self.light.position, position: self.light.position,
@ -211,7 +252,7 @@ impl Renderer {
..Default::default() ..Default::default()
}); });
mq::gl_use_material(&self.depth_material); mq::gl_use_material(&self.depth_material);
mq::clear_background(mq::DARKGRAY); mq::clear_background(mq::BLACK);
draw_world(&mut world, None); draw_world(&mut world, None);
mq::gl_use_default_material(); mq::gl_use_default_material();
mq::set_default_camera(); mq::set_default_camera();
@ -220,12 +261,12 @@ impl Renderer {
.set_texture("shadow_map", self.depth_target.texture.clone()); .set_texture("shadow_map", self.depth_target.texture.clone());
} }
fn render_default(&mut self, mut world: &mut World) { fn render_default(&mut self, mut world: &mut World) {
mq::clear_background(mq::LIGHTGRAY); mq::clear_background(mq::DARKGRAY);
self.camera.apply(); self.camera.apply();
draw_world(&mut world, Some(&self.base_material)); draw_world(&mut world, Some(&self.base_material));
mq::draw_sphere(self.light.position, 0.25, None, mq::WHITE); // mq::draw_sphere(self.light.position, 0.25, None, mq::WHITE);
mq::draw_grid(20, 1., mq::BLACK, mq::GRAY); mq::draw_grid(20, 1., mq::BLACK, mq::GRAY);
mq::gl_use_default_material(); mq::gl_use_default_material();
@ -233,17 +274,17 @@ impl Renderer {
} }
fn render_ui(&mut self) { fn render_ui(&mut self) {
mq::set_default_camera(); mq::set_default_camera();
// mq::draw_texture_ex( mq::draw_texture_ex(
// &self.depth_target.texture, &self.depth_target.texture,
// 0., 320.,
// 0., 20.,
// mq::WHITE, mq::WHITE,
// mq::DrawTextureParams { mq::DrawTextureParams {
// flip_y: true, flip_y: true,
// dest_size: Some(mq::vec2(200.0, 200.0)), dest_size: Some(mq::vec2(200.0, 200.0)),
// ..Default::default() ..Default::default()
// }, },
// ); );
macroquad::ui::root_ui().window( macroquad::ui::root_ui().window(
hash!("MaterialWindow"), hash!("MaterialWindow"),
mq::vec2(20.0, 20.0), mq::vec2(20.0, 20.0),

View File

@ -22,9 +22,9 @@ impl MaterialUi {
render_shadows_bool: true, render_shadows_bool: true,
shadow_step_count: 1, shadow_step_count: 1,
shadow_step_size: 1, shadow_step_size: 1,
shadow_min_bias: 0.0, shadow_min_bias: 5.0,
shadow_fac_bias: 0.0, shadow_fac_bias: 1.0,
shadow_max_bias: 0.0, shadow_max_bias: 100.0,
} }
} }
pub fn apply(&self, material: &macroquad::prelude::Material) { pub fn apply(&self, material: &macroquad::prelude::Material) {