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 nalgebra as na;
use rapier3d::prelude as rp;
use rapier3d::prelude::{self as rp, ColliderHandle};
fn random_color() -> mq::Color {
return mq::Color::new(
@ -53,12 +53,17 @@ impl World {
);
}
pub fn position_of_rb(
&self,
rigid_body_handle: rp::RigidBodyHandle,
) -> Option<na::Vector3<f32>> {
let body = self.bodies.get(rigid_body_handle)?;
return Some(*body.translation());
pub fn clear_ofb(&mut self) {
let mut coll_to_del: Vec<ColliderHandle> = Vec::new();
for (handle, col) in self.colliders.iter() {
if (col.translation().y < -15.0) {
coll_to_del.push(handle);
}
}
for handle in coll_to_del {
self.colliders
.remove(handle, &mut self.island_manager, &mut self.bodies, false);
}
}
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 graphics_util;
use graphics_util::*;
use crate::rendering::Renderer;
@ -19,20 +18,21 @@ async fn main() {
// Physics Initialization
world.register_free_collider(
ColliderBuilder::cuboid(100.0, 10.0, 100.0)
.restitution(0.2)
ColliderBuilder::cuboid(50.0, 5.0, 50.0)
.restitution(0.5)
.build(),
None,
);
add_objects(&mut world);
let mut i = 0;
loop {
renderer.update_camera();
if mq::is_key_pressed(mq::KeyCode::L) {
renderer
.light
.set_location(renderer.camera.position, renderer.camera.front);
renderer.update_light();
renderer.update_light(&world);
println!(
"Light Pos: {}, Light Front Vec{}",
renderer.light.position, renderer.light.front
@ -50,7 +50,13 @@ async fn main() {
world.step();
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(),
);
world.register_collider(
ColliderBuilder::cuboid(10.0, 10.0, 10.0)
.restitution(0.5)
ColliderBuilder::cuboid(5.0, 5.0, 5.0)
.restitution(0.3)
.build(),
body,
None,

View File

@ -1,10 +1,10 @@
use crate::{
camera::{self as cam, FirstPersonCamera},
engine::World,
engine::{self, World},
graphics_util::draw_cuboid,
};
use macroquad::prelude as mq;
use macroquad::ui::{hash, Ui};
use macroquad::ui::hash;
use rapier3d::prelude::*;
use strum::IntoEnumIterator;
@ -143,7 +143,7 @@ impl Renderer {
},
mq::MaterialParams {
pipeline_params: mq::PipelineParams {
cull_face: macroquad::miniquad::CullFace::Back,
// cull_face: macroquad::miniquad::CullFace::Back,
depth_test: mq::Comparison::LessOrEqual,
depth_write: true,
..Default::default()
@ -182,7 +182,6 @@ impl Renderer {
};
r.light
.set_location(mq::vec3(10.0, 40.0, 10.0), mq::Vec3::NEG_Y);
r.update_light();
r.apply_config();
return r;
}
@ -193,15 +192,57 @@ impl Renderer {
pub fn update_camera(&mut self) {
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();
self.base_material
.set_uniform(MaterialUni::LightPosition.as_str(), self.light.position);
.set_uniform("light_position", self.light.position);
self.base_material
.set_uniform(MaterialUni::LightSpaceMatrix.as_str(), light_space_matrix);
.set_uniform("light_space_matrix", light_space_matrix);
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) {
mq::set_camera(&mq::Camera3D {
position: self.light.position,
@ -211,7 +252,7 @@ impl Renderer {
..Default::default()
});
mq::gl_use_material(&self.depth_material);
mq::clear_background(mq::DARKGRAY);
mq::clear_background(mq::BLACK);
draw_world(&mut world, None);
mq::gl_use_default_material();
mq::set_default_camera();
@ -220,12 +261,12 @@ impl Renderer {
.set_texture("shadow_map", self.depth_target.texture.clone());
}
fn render_default(&mut self, mut world: &mut World) {
mq::clear_background(mq::LIGHTGRAY);
mq::clear_background(mq::DARKGRAY);
self.camera.apply();
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::gl_use_default_material();
@ -233,17 +274,17 @@ impl Renderer {
}
fn render_ui(&mut self) {
mq::set_default_camera();
// mq::draw_texture_ex(
// &self.depth_target.texture,
// 0.,
// 0.,
// mq::WHITE,
// mq::DrawTextureParams {
// flip_y: true,
// dest_size: Some(mq::vec2(200.0, 200.0)),
// ..Default::default()
// },
// );
mq::draw_texture_ex(
&self.depth_target.texture,
320.,
20.,
mq::WHITE,
mq::DrawTextureParams {
flip_y: true,
dest_size: Some(mq::vec2(200.0, 200.0)),
..Default::default()
},
);
macroquad::ui::root_ui().window(
hash!("MaterialWindow"),
mq::vec2(20.0, 20.0),

View File

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