working shadows kinda
This commit is contained in:
parent
45ec2fd936
commit
d3d2437fa2
|
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
20
src/main.rs
20
src/main.rs
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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: ¯oquad::prelude::Material) {
|
pub fn apply(&self, material: ¯oquad::prelude::Material) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue