working shadows somewhat????
This commit is contained in:
parent
51cd254ddb
commit
7a3f5fce9f
|
|
@ -0,0 +1,123 @@
|
||||||
|
use macroquad::prelude::*;
|
||||||
|
|
||||||
|
const MOVE_SPEED: f32 = 1.0;
|
||||||
|
const LOOK_SPEED: f32 = 0.01;
|
||||||
|
|
||||||
|
pub struct FirstPersonCamera {
|
||||||
|
pub position: Vec3,
|
||||||
|
yaw: f32,
|
||||||
|
pitch: f32,
|
||||||
|
|
||||||
|
pub front: Vec3,
|
||||||
|
pub right: Vec3,
|
||||||
|
pub up: Vec3,
|
||||||
|
world_up: Vec3,
|
||||||
|
|
||||||
|
grabbed: bool,
|
||||||
|
last_mouse: Vec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FirstPersonCamera {
|
||||||
|
pub fn new(position: Vec3) -> Self {
|
||||||
|
let yaw: f32 = 1.18;
|
||||||
|
let pitch: f32 = 0.0;
|
||||||
|
let world_up = vec3(0.0, 1.0, 0.0);
|
||||||
|
|
||||||
|
let front = vec3(
|
||||||
|
yaw.cos() * pitch.cos(),
|
||||||
|
pitch.sin(),
|
||||||
|
yaw.sin() * pitch.cos(),
|
||||||
|
)
|
||||||
|
.normalize();
|
||||||
|
|
||||||
|
let right = front.cross(world_up).normalize();
|
||||||
|
let up = right.cross(front).normalize();
|
||||||
|
|
||||||
|
let grabbed = true;
|
||||||
|
set_cursor_grab(grabbed);
|
||||||
|
show_mouse(!grabbed);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
position,
|
||||||
|
yaw,
|
||||||
|
pitch,
|
||||||
|
front,
|
||||||
|
right,
|
||||||
|
up,
|
||||||
|
world_up,
|
||||||
|
grabbed,
|
||||||
|
last_mouse: mouse_position().into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_vectors(&mut self) {
|
||||||
|
self.front = vec3(
|
||||||
|
self.yaw.cos() * self.pitch.cos(),
|
||||||
|
self.pitch.sin(),
|
||||||
|
self.yaw.sin() * self.pitch.cos(),
|
||||||
|
)
|
||||||
|
.normalize();
|
||||||
|
|
||||||
|
self.right = self.front.cross(self.world_up).normalize();
|
||||||
|
self.up = self.right.cross(self.front).normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_mouse(&mut self, delta: f32) {
|
||||||
|
let mouse: Vec2 = mouse_position().into();
|
||||||
|
let mouse_delta = mouse - self.last_mouse;
|
||||||
|
self.last_mouse = mouse;
|
||||||
|
|
||||||
|
if !self.grabbed {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.yaw += mouse_delta.x * delta * LOOK_SPEED;
|
||||||
|
self.pitch -= mouse_delta.y * delta * LOOK_SPEED;
|
||||||
|
|
||||||
|
// clamp pitch
|
||||||
|
self.pitch = self.pitch.clamp(-1.5, 1.5);
|
||||||
|
|
||||||
|
self.update_vectors();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_keyboard(&mut self) {
|
||||||
|
if is_key_down(KeyCode::W) {
|
||||||
|
self.position += self.front * MOVE_SPEED;
|
||||||
|
}
|
||||||
|
if is_key_down(KeyCode::S) {
|
||||||
|
self.position -= self.front * MOVE_SPEED;
|
||||||
|
}
|
||||||
|
if is_key_down(KeyCode::A) {
|
||||||
|
self.position -= self.right * MOVE_SPEED;
|
||||||
|
}
|
||||||
|
if is_key_down(KeyCode::D) {
|
||||||
|
self.position += self.right * MOVE_SPEED;
|
||||||
|
}
|
||||||
|
if is_key_down(KeyCode::LeftShift) {
|
||||||
|
self.position += Vec3::Y * MOVE_SPEED;
|
||||||
|
}
|
||||||
|
if is_key_down(KeyCode::LeftControl) {
|
||||||
|
self.position -= Vec3::Y * MOVE_SPEED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, delta: f32) {
|
||||||
|
if is_key_pressed(KeyCode::Tab) {
|
||||||
|
self.grabbed = !self.grabbed;
|
||||||
|
set_cursor_grab(self.grabbed);
|
||||||
|
show_mouse(!self.grabbed);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.handle_keyboard();
|
||||||
|
self.handle_mouse(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply(&self) {
|
||||||
|
set_camera(&Camera3D {
|
||||||
|
position: self.position,
|
||||||
|
up: self.up,
|
||||||
|
target: self.position + self.front,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
120
src/main.rs
120
src/main.rs
|
|
@ -1,4 +1,3 @@
|
||||||
use glam::Quat;
|
|
||||||
use macroquad::prelude as mq;
|
use macroquad::prelude as mq;
|
||||||
use rapier3d::prelude::*;
|
use rapier3d::prelude::*;
|
||||||
|
|
||||||
|
|
@ -6,110 +5,65 @@ mod engine;
|
||||||
use engine::*;
|
use engine::*;
|
||||||
|
|
||||||
mod camera;
|
mod camera;
|
||||||
|
mod rendering;
|
||||||
|
|
||||||
mod graphics_util;
|
mod graphics_util;
|
||||||
use graphics_util::*;
|
use graphics_util::*;
|
||||||
|
|
||||||
|
use crate::rendering::Renderer;
|
||||||
|
|
||||||
#[macroquad::main("3D")]
|
#[macroquad::main("3D")]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
// Graphics Initialization
|
let mut world = World::default();
|
||||||
let vertex = include_str!("shaders/shader.vert");
|
let mut renderer = Renderer::new();
|
||||||
let fragment = include_str!("shaders/shader.frag");
|
|
||||||
|
|
||||||
let material = mq::load_material(
|
|
||||||
mq::ShaderSource::Glsl { vertex, fragment },
|
|
||||||
mq::MaterialParams {
|
|
||||||
pipeline_params: mq::PipelineParams {
|
|
||||||
depth_test: mq::Comparison::LessOrEqual,
|
|
||||||
depth_write: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
uniforms: vec![mq::UniformDesc::new(
|
|
||||||
"render_normals_bool",
|
|
||||||
mq::UniformType::Int1,
|
|
||||||
)],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
material.set_uniform("render_normals_bool", 0);
|
|
||||||
|
|
||||||
// Physics Initialization
|
// Physics Initialization
|
||||||
let mut world = World::default();
|
|
||||||
world.register_free_collider(
|
world.register_free_collider(
|
||||||
ColliderBuilder::cuboid(50.0, 0.1, 50.0)
|
ColliderBuilder::cuboid(50.0, 10.0, 50.0)
|
||||||
.restitution(0.5)
|
.restitution(0.2)
|
||||||
.build(),
|
.build(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
add_objects(&mut world);
|
||||||
|
|
||||||
for i in 0..10 {
|
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();
|
||||||
|
println!(
|
||||||
|
"Light Pos: {}, Light Front Vec{}",
|
||||||
|
renderer.light.position, renderer.light.front
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if mq::is_key_pressed(mq::KeyCode::C) {
|
||||||
|
add_objects(&mut world);
|
||||||
|
}
|
||||||
|
// Physics Simulation
|
||||||
|
world.step();
|
||||||
|
renderer.draw(&mut world);
|
||||||
|
|
||||||
|
mq::next_frame().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_objects(world: &mut World) {
|
||||||
|
for i in 0..1 {
|
||||||
let body = world.register_body(
|
let body = world.register_body(
|
||||||
RigidBodyBuilder::dynamic()
|
RigidBodyBuilder::dynamic()
|
||||||
.translation(vector![0.0, 10.0 + i as f32, 0.0])
|
.translation(vector![0.0, 50.0 + i as f32, 0.0])
|
||||||
.rotation(vector![std::f32::consts::PI / 4.2, i as f32, i as f32])
|
.rotation(vector![std::f32::consts::PI / 4.2, i as f32, i as f32])
|
||||||
.build(),
|
.build(),
|
||||||
);
|
);
|
||||||
world.register_collider(
|
world.register_collider(
|
||||||
ColliderBuilder::cuboid(0.5, 0.5, 0.5)
|
ColliderBuilder::cuboid(3.0, 3.0, 3.0)
|
||||||
.restitution(0.5)
|
.restitution(1.0)
|
||||||
.build(),
|
.build(),
|
||||||
body,
|
body,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cam: camera::FirstPersonCamera =
|
|
||||||
camera::FirstPersonCamera::new(mq::vec3(0.0, 10.0, -5.0));
|
|
||||||
loop {
|
|
||||||
// Physics Simulation
|
|
||||||
world.step();
|
|
||||||
|
|
||||||
// Graphics Rendering
|
|
||||||
mq::clear_background(mq::LIGHTGRAY);
|
|
||||||
cam.update(mq::get_frame_time());
|
|
||||||
cam.apply();
|
|
||||||
|
|
||||||
mq::draw_grid(20, 1., mq::BLACK, mq::GRAY);
|
|
||||||
|
|
||||||
for (handle, coll) in world.colliders.iter() {
|
|
||||||
let position: glam::Vec3 = world.position_of_collider(handle).unwrap().into();
|
|
||||||
let rotation = *coll.rotation();
|
|
||||||
unsafe {
|
|
||||||
let context = mq::get_internal_gl().quad_gl;
|
|
||||||
|
|
||||||
context.push_model_matrix(mq::Mat4::from_rotation_translation(
|
|
||||||
rotation.into(),
|
|
||||||
position,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
let color = world.collider_data.get(&handle).unwrap().color;
|
|
||||||
match coll.shape().shape_type() {
|
|
||||||
ShapeType::Ball => {
|
|
||||||
mq::draw_sphere(
|
|
||||||
mq::vec3(0.0, 0.0, 0.0),
|
|
||||||
coll.shape().as_ball().unwrap().radius,
|
|
||||||
None,
|
|
||||||
color,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ShapeType::Cuboid => {
|
|
||||||
mq::gl_use_material(&material);
|
|
||||||
draw_cuboid(
|
|
||||||
mq::vec3(0.0, 0.0, 0.0),
|
|
||||||
(coll.shape().as_cuboid().unwrap().half_extents * 2.0).into(),
|
|
||||||
color,
|
|
||||||
);
|
|
||||||
mq::gl_use_default_material();
|
|
||||||
}
|
|
||||||
_ => println!("Not implemented.. Skipping"),
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
let context = mq::get_internal_gl().quad_gl;
|
|
||||||
context.pop_model_matrix();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mq::next_frame().await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,252 @@
|
||||||
|
use crate::{
|
||||||
|
camera::{self as cam, FirstPersonCamera},
|
||||||
|
engine::World,
|
||||||
|
graphics_util::draw_cuboid,
|
||||||
|
};
|
||||||
|
use macroquad::prelude as mq;
|
||||||
|
use rapier3d::prelude::*;
|
||||||
|
|
||||||
|
const DEPTH_MAP_SIZE: u32 = 512;
|
||||||
|
const ENABLE_SHADOWS: bool = true;
|
||||||
|
|
||||||
|
const LIGHT_PROJECTION_SIZE: f32 = 20.0;
|
||||||
|
const LIGHT_NEAR: f32 = 10.0;
|
||||||
|
const LIGHT_FAR: f32 = 100.0;
|
||||||
|
|
||||||
|
pub struct Light {
|
||||||
|
projection_matrix: mq::Mat4,
|
||||||
|
view_matrix: mq::Mat4,
|
||||||
|
pub position: mq::Vec3,
|
||||||
|
pub front: mq::Vec3,
|
||||||
|
}
|
||||||
|
impl Light {
|
||||||
|
pub fn new() -> Light {
|
||||||
|
let mut l = Light {
|
||||||
|
projection_matrix: mq::Mat4::orthographic_rh(
|
||||||
|
-LIGHT_PROJECTION_SIZE,
|
||||||
|
LIGHT_PROJECTION_SIZE,
|
||||||
|
-LIGHT_PROJECTION_SIZE,
|
||||||
|
LIGHT_PROJECTION_SIZE,
|
||||||
|
LIGHT_NEAR,
|
||||||
|
LIGHT_FAR,
|
||||||
|
),
|
||||||
|
view_matrix: mq::Mat4::NAN,
|
||||||
|
position: mq::Vec3::NAN,
|
||||||
|
front: mq::Vec3::NAN,
|
||||||
|
};
|
||||||
|
l.set_location(mq::vec3(5.0, 10.0, 0.0), mq::Vec3::NEG_Y);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
pub fn set_location(&mut self, position: mq::Vec3, front: mq::Vec3) {
|
||||||
|
self.position = position;
|
||||||
|
self.front = front;
|
||||||
|
self.view_matrix =
|
||||||
|
mq::Mat4::look_at_rh(self.position, self.position + self.front, mq::Vec3::Y);
|
||||||
|
}
|
||||||
|
pub fn get_space_matrix(&self) -> mq::Mat4 {
|
||||||
|
return self.projection_matrix * self.view_matrix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Renderer {
|
||||||
|
base_material: mq::Material,
|
||||||
|
depth_material: mq::Material,
|
||||||
|
depth_target: mq::RenderTarget,
|
||||||
|
pub light: Light,
|
||||||
|
pub camera: cam::FirstPersonCamera,
|
||||||
|
has_light_moved: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderer {
|
||||||
|
pub fn new() -> Renderer {
|
||||||
|
let material = mq::load_material(
|
||||||
|
mq::ShaderSource::Glsl {
|
||||||
|
vertex: include_str!("shaders/shader.vert"),
|
||||||
|
fragment: include_str!("shaders/shader.frag"),
|
||||||
|
},
|
||||||
|
mq::MaterialParams {
|
||||||
|
pipeline_params: mq::PipelineParams {
|
||||||
|
cull_face: macroquad::miniquad::CullFace::Front,
|
||||||
|
depth_test: mq::Comparison::LessOrEqual,
|
||||||
|
depth_write: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
uniforms: vec![
|
||||||
|
mq::UniformDesc::new("render_normals_bool", mq::UniformType::Int1),
|
||||||
|
mq::UniformDesc::new("render_shadows_bool", mq::UniformType::Int1),
|
||||||
|
mq::UniformDesc::new("light_position", mq::UniformType::Float3),
|
||||||
|
mq::UniformDesc::new("light_space_matrix", mq::UniformType::Mat4),
|
||||||
|
],
|
||||||
|
textures: vec![String::from("shadow_map")],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
material.set_uniform("render_normals_bool", 0);
|
||||||
|
material.set_uniform("render_shadows_bool", ENABLE_SHADOWS);
|
||||||
|
|
||||||
|
let depth_material = mq::load_material(
|
||||||
|
mq::ShaderSource::Glsl {
|
||||||
|
vertex: include_str!("shaders/depth.vert"),
|
||||||
|
fragment: include_str!("shaders/depth.frag"),
|
||||||
|
},
|
||||||
|
mq::MaterialParams {
|
||||||
|
pipeline_params: mq::PipelineParams {
|
||||||
|
// cull_face: macroquad::miniquad::CullFace::Back,
|
||||||
|
depth_test: mq::Comparison::LessOrEqual,
|
||||||
|
depth_write: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
uniforms: vec![mq::UniformDesc::new(
|
||||||
|
"light_space_matrix",
|
||||||
|
mq::UniformType::Mat4,
|
||||||
|
)],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let depth_map_texture = mq::render_target_ex(
|
||||||
|
DEPTH_MAP_SIZE,
|
||||||
|
DEPTH_MAP_SIZE,
|
||||||
|
mq::RenderTargetParams {
|
||||||
|
sample_count: 1,
|
||||||
|
depth: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
depth_map_texture
|
||||||
|
.texture
|
||||||
|
.set_filter(mq::FilterMode::Nearest);
|
||||||
|
|
||||||
|
let light = Light::new();
|
||||||
|
let camera = FirstPersonCamera::new(mq::vec3(10.0, 50.0, 10.0));
|
||||||
|
let mut r = Renderer {
|
||||||
|
base_material: material,
|
||||||
|
depth_material,
|
||||||
|
depth_target: depth_map_texture,
|
||||||
|
light,
|
||||||
|
camera,
|
||||||
|
has_light_moved: true,
|
||||||
|
};
|
||||||
|
r.light
|
||||||
|
.set_location(mq::vec3(10.0, 40.0, 10.0), mq::Vec3::NEG_Y);
|
||||||
|
r.update_light();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
pub fn update_camera(&mut self) {
|
||||||
|
self.camera.update(mq::get_frame_time());
|
||||||
|
}
|
||||||
|
pub fn update_light(&mut self) {
|
||||||
|
let light_space_matrix = self.light.get_space_matrix();
|
||||||
|
self.base_material
|
||||||
|
.set_uniform("light_position", self.light.position);
|
||||||
|
self.base_material
|
||||||
|
.set_uniform("light_space_matrix", light_space_matrix);
|
||||||
|
self.depth_material
|
||||||
|
.set_uniform("light_space_matrix", light_space_matrix);
|
||||||
|
self.has_light_moved = true;
|
||||||
|
}
|
||||||
|
fn render_depth(&mut self, mut world: &mut World) {
|
||||||
|
mq::set_camera(&mq::Camera3D {
|
||||||
|
position: self.light.position,
|
||||||
|
target: self.light.position + self.light.front,
|
||||||
|
up: mq::Vec3::Y,
|
||||||
|
render_target: Some(self.depth_target.clone()),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
mq::gl_use_material(&self.depth_material);
|
||||||
|
mq::clear_background(mq::DARKGRAY);
|
||||||
|
draw_world(&mut world, None);
|
||||||
|
mq::gl_use_default_material();
|
||||||
|
mq::set_default_camera();
|
||||||
|
|
||||||
|
self.base_material
|
||||||
|
.set_texture("shadow_map", self.depth_target.texture.clone());
|
||||||
|
}
|
||||||
|
fn render_default(&mut self, mut world: &mut World) {
|
||||||
|
mq::clear_background(mq::LIGHTGRAY);
|
||||||
|
self.camera.apply();
|
||||||
|
|
||||||
|
draw_world(&mut world, Some(&self.base_material));
|
||||||
|
|
||||||
|
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();
|
||||||
|
mq::set_default_camera();
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
pub fn draw(&mut self, mut world: &mut World) {
|
||||||
|
if ENABLE_SHADOWS {
|
||||||
|
self.render_depth(&mut world);
|
||||||
|
self.has_light_moved = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.render_default(&mut world);
|
||||||
|
|
||||||
|
self.render_ui();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_world(world: &mut World, material: Option<&mq::Material>) {
|
||||||
|
for (handle, coll) in world.colliders.iter() {
|
||||||
|
let position: glam::Vec3 = world.position_of_collider(handle).unwrap().into();
|
||||||
|
let rotation = *coll.rotation();
|
||||||
|
unsafe {
|
||||||
|
let context = mq::get_internal_gl().quad_gl;
|
||||||
|
|
||||||
|
context.push_model_matrix(mq::Mat4::from_rotation_translation(
|
||||||
|
rotation.into(),
|
||||||
|
position,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let color = world.collider_data.get(&handle).unwrap().color;
|
||||||
|
match coll.shape().shape_type() {
|
||||||
|
ShapeType::Ball => {
|
||||||
|
mq::draw_sphere(
|
||||||
|
mq::vec3(0.0, 0.0, 0.0),
|
||||||
|
coll.shape().as_ball().unwrap().radius,
|
||||||
|
None,
|
||||||
|
color,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ShapeType::Cuboid => {
|
||||||
|
match material {
|
||||||
|
Some(mat) => {
|
||||||
|
mq::gl_use_material(&mat);
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
draw_cuboid(
|
||||||
|
mq::vec3(0.0, 0.0, 0.0),
|
||||||
|
(coll.shape().as_cuboid().unwrap().half_extents * 2.0).into(),
|
||||||
|
color,
|
||||||
|
);
|
||||||
|
match material {
|
||||||
|
Some(_) => {
|
||||||
|
mq::gl_use_default_material();
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => println!("Not implemented.. Skipping"),
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
let context = mq::get_internal_gl().quad_gl;
|
||||||
|
context.pop_model_matrix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in float dist_to_cam;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
float c = gl_FragCoord.z * gl_FragCoord.w;
|
||||||
|
FragColor = vec4(c, c, c, c);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
#version 330 core
|
||||||
|
attribute vec3 position;
|
||||||
|
attribute vec3 normal; // Ensure this attribute exists!
|
||||||
|
|
||||||
|
uniform mat4 Model;
|
||||||
|
uniform mat4 light_space_matrix; // This will be the Light Space Matrix (LSM)
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 pos = position;
|
||||||
|
gl_Position = light_space_matrix * Model * vec4(pos, 1.0);
|
||||||
|
}
|
||||||
|
|
@ -1,22 +1,86 @@
|
||||||
|
|
||||||
#version 330 core
|
#version 330 core
|
||||||
|
|
||||||
in vec4 v_normal;
|
in vec4 v_normal;
|
||||||
in vec4 color;
|
in vec4 color;
|
||||||
in vec3 light_direction;
|
in vec3 light_direction;
|
||||||
|
in vec4 v_light_space_position; // New: Position transformed by LightSpaceMatrix
|
||||||
|
|
||||||
uniform int render_normals_bool;
|
uniform int render_normals_bool;
|
||||||
|
uniform int render_shadows_bool;
|
||||||
|
uniform sampler2D shadow_map; // New: Depth map texture
|
||||||
|
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
|
||||||
const float ambient_strenght = 0.3;
|
const float ambient_strenght = 0.3;
|
||||||
const float diffuse_strenght = 0.7;
|
const float diffuse_strenght = 0.7;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the shadow factor (0.0 for shadow, 1.0 for lit).
|
||||||
|
*/
|
||||||
|
float calculate_shadow() {
|
||||||
|
float min_bias = 0.003;
|
||||||
|
float max_bias = 0.01;
|
||||||
|
float dot_product = dot(normalize(v_normal.xyz), normalize(light_direction));
|
||||||
|
float bias = max(max_bias * (1.0 - dot_product), min_bias);
|
||||||
|
|
||||||
|
// float bias = 0;
|
||||||
|
|
||||||
|
// 1. Perspective divide to get Normalized Device Coordinates (NDC)
|
||||||
|
vec3 proj_coords = v_light_space_position.xyz / v_light_space_position.w;
|
||||||
|
|
||||||
|
// 2. Transform to texture coordinates (0 to 1 range)
|
||||||
|
vec2 tex_coords = proj_coords.xy * 0.5 + 0.5;
|
||||||
|
|
||||||
|
// 3. Get the closest depth from the light's perspective (shadow map)
|
||||||
|
// We sample the red channel since Macroquad's depth texture stores depth data there.
|
||||||
|
float closest_depth = texture(shadow_map, tex_coords).r;
|
||||||
|
|
||||||
|
// 4. Get the current fragment's depth from the light's perspective
|
||||||
|
// float current_depth = proj_coords.z;
|
||||||
|
float current_depth = proj_coords.z * 0.5 + 0.5;
|
||||||
|
// float current_depth = v_light_space_position.z;
|
||||||
|
// 5. Check if the fragment is outside the light frustum
|
||||||
|
if (tex_coords.x > 1.0 || tex_coords.x < 0.0 || tex_coords.y > 1.0 || tex_coords.y < 0.0 || current_depth > 1.0) {
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// float shadow = 0.0;
|
||||||
|
// vec2 texelSize = 1.0 / textureSize(shadow_map, 0);
|
||||||
|
// int x_ran = 1;
|
||||||
|
// for (int x = -x_ran; x <= x_ran; x++)
|
||||||
|
// {
|
||||||
|
// for (int y = -x_ran; y <= x_ran; y++)
|
||||||
|
// {
|
||||||
|
// float pcfDepth = texture(shadow_map, tex_coords + vec2(x, y) * texelSize).x;
|
||||||
|
// shadow += current_depth - bias > pcfDepth ? 0.0 : 1.0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// shadow = current_depth - bias > closest_depth ? 0.0 : 1.0;
|
||||||
|
|
||||||
|
// shadow /= ((2 * x_ran) + 1) * ((2 * x_ran) + 1);
|
||||||
|
|
||||||
|
// 6. Compare depths with a bias: if current depth > closest depth, we are in shadow (0.0)
|
||||||
|
float shadow = current_depth - bias > closest_depth ? 0.0 : 1.0;
|
||||||
|
|
||||||
|
return min(max(shadow, 0), 1);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float diff = max(dot(normalize(vec3(v_normal.x, v_normal.y, v_normal.z)), normalize(light_direction)), 0) * diffuse_strenght;
|
float diff = max(dot(normalize(vec3(v_normal.x, v_normal.y, v_normal.z)), normalize(light_direction)), 0) * diffuse_strenght;
|
||||||
|
|
||||||
if (render_normals_bool == 1) {
|
if (render_normals_bool == 1) {
|
||||||
FragColor = vec4(v_normal);
|
FragColor = vec4(v_normal);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
if (render_shadows_bool == 1) {
|
||||||
FragColor = color * (1 / 256.0) * (ambient_strenght + diff);
|
float lighting = ambient_strenght + diff;
|
||||||
|
FragColor = normalize(v_normal) * lighting;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float shadow_factor = calculate_shadow();
|
||||||
|
|
||||||
|
float lighting = ambient_strenght + diff * shadow_factor;
|
||||||
|
|
||||||
|
FragColor = normalize(abs(v_normal)) * lighting;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#version 330 core
|
#version 330 core
|
||||||
|
|
||||||
attribute vec3 position;
|
attribute vec3 position;
|
||||||
|
|
@ -7,14 +6,25 @@ attribute vec4 normal;
|
||||||
|
|
||||||
uniform mat4 Model;
|
uniform mat4 Model;
|
||||||
uniform mat4 Projection;
|
uniform mat4 Projection;
|
||||||
|
uniform mat4 light_space_matrix; // New uniform for the light's view-projection matrix
|
||||||
|
uniform vec3 light_position;
|
||||||
|
|
||||||
out vec4 v_normal;
|
out vec4 v_normal;
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
out vec3 light_direction;
|
out vec3 light_direction;
|
||||||
|
out vec4 v_light_space_position; // New: Output for shadow calculation
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 light_dir = vec4(1.0, 1.0, 0.0, 0.0) * Model;
|
vec4 world_poisition = Model * vec4(position, 1.0);
|
||||||
light_direction = vec3(light_dir.x, light_dir.y, light_dir.z);
|
vec3 direction_to_light = light_position - world_poisition.xyz;
|
||||||
|
|
||||||
|
// Transform the fragment position into the light's clip space
|
||||||
|
v_light_space_position = light_space_matrix * world_poisition;
|
||||||
|
|
||||||
|
// Original lighting setup
|
||||||
|
light_direction = normalize(direction_to_light);
|
||||||
|
|
||||||
color = color0;
|
color = color0;
|
||||||
v_normal = normal;
|
v_normal = Model * normal;
|
||||||
gl_Position = Projection * Model * vec4(position, 1.0);
|
gl_Position = Projection * Model * vec4(position, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue