From b13ee649bebef0b3b05d2e113862c7adc0bd4859 Mon Sep 17 00:00:00 2001 From: hheik <4469778+hheik@users.noreply.github.com> Date: Thu, 7 Dec 2023 02:21:51 +0200 Subject: [PATCH] wip: Added ShadowMesh component --- src/game/camera.rs | 3 ++- src/game/darkness.rs | 57 +++++++++++++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/game/camera.rs b/src/game/camera.rs index 006e5da..54d6bf8 100644 --- a/src/game/camera.rs +++ b/src/game/camera.rs @@ -5,7 +5,7 @@ use bevy::render::camera::ScalingMode; use bevy::{input::mouse::MouseMotion, transform::TransformSystem}; use bevy_ecs_ldtk::prelude::*; -use super::darkness::{PointLight2D, SpotLight2D}; +use super::darkness::{PointLight2D, ShadowMesh, SpotLight2D}; pub struct GameCameraPlugin; @@ -95,6 +95,7 @@ fn camera_setup(mut commands: Commands) { ComputedVisibility::default(), CameraRoomRestraint, PointLight2D { radius: 30.0 }, + ShadowMesh::default(), )); } diff --git a/src/game/darkness.rs b/src/game/darkness.rs index 2b0c36c..689d6d6 100644 --- a/src/game/darkness.rs +++ b/src/game/darkness.rs @@ -28,6 +28,7 @@ impl Plugin for DarknessPlugin { fn build(&self, app: &mut App) { app.register_type::() .register_type::() + .register_type::() .register_type::() .register_asset_reflect::() .add_plugins(Material2dPlugin::::default()) @@ -86,6 +87,18 @@ pub(crate) struct GpuSpotLight2D { #[reflect(Component)] pub struct VisibilityBlocker; +#[derive(Reflect, Default, Debug, Clone, Copy)] +pub struct ShadowVertex { + pub point: Vec2, + pub angle: f32, +} + +#[derive(Component, Reflect, Default, Debug, Clone)] +#[reflect(Component)] +pub struct ShadowMesh { + pub vertices: Vec, +} + fn add_to_level( mut commands: Commands, mut level_events: EventReader, @@ -150,9 +163,9 @@ fn add_to_level( DarknessMeshBundle { transform: Transform::from_xyz(0.0, 0.0, 100.0), mesh: Mesh2dHandle(meshes.add(plane)), - material: materials.add(DarknessMaterial::new( - Color::rgba(0.0, 0.0, 0.0, 0.75), - Some(images.add(Image::new( + material: materials.add(DarknessMaterial { + color: Color::rgba(0.0, 0.0, 0.0, 0.75), + shadowmap_texture: Some(images.add(Image::new( Extent3d { width: width as u32, height: height as u32, @@ -162,7 +175,8 @@ fn add_to_level( vec![0; width * height * 4], bevy::render::render_resource::TextureFormat::R32Float, ))), - )), + ..default() + }), ..default() }, )); @@ -175,6 +189,7 @@ fn add_to_level( } fn prepare_lights( + mut shadow_mesh_query: Query<&mut ShadowMesh>, mut materials: ResMut>, mut images: ResMut>, mut debug_draw: ResMut, @@ -184,11 +199,11 @@ fn prepare_lights( transform_query: Query<&GlobalTransform>, collider_query: Query<&Collider>, material_query: Query<&Handle>, - point_light_query: Query<(&GlobalTransform, &PointLight2D)>, - spot_light_query: Query<(&GlobalTransform, &SpotLight2D)>, + point_light_query: Query<(&GlobalTransform, &PointLight2D, Entity)>, + spot_light_query: Query<(&GlobalTransform, &SpotLight2D, Entity)>, ) { - let point_lights: Vec<(_, _)> = point_light_query.iter().collect(); - let spot_lights: Vec<(_, _)> = spot_light_query.iter().collect(); + let point_lights: Vec<(_, _, _)> = point_light_query.iter().collect(); + let spot_lights: Vec<(_, _, _)> = spot_light_query.iter().collect(); for handle in &material_query { let material = match materials.get_mut(handle) { Some(material) => material, @@ -207,7 +222,7 @@ fn prepare_lights( point_lights .iter() .enumerate() - .for_each(|(i, (transform, light))| { + .for_each(|(i, (transform, light, entity))| { let rect = light.aabb(); let polygon = get_light_geometry( &rapier_context, @@ -220,10 +235,23 @@ fn prepare_lights( ), ); + if let Ok(mut shadow_mesh) = shadow_mesh_query.get_mut(*entity) { + shadow_mesh.vertices = polygon + .iter() + .map(|point| ShadowVertex { + point: *point, + angle: f32::atan2( + point.y - transform.translation().y, + point.x - transform.translation().x, + ), + }) + .collect() + } + if debug_mode.enabled { - for (i, arr) in polygon.iter().as_slice().windows(2).enumerate() { - let p1 = arr[0]; - let p2 = arr[1]; + for i in 0..polygon.len() { + let p1 = polygon[i]; + let p2 = polygon[(i + 1) % polygon.len()]; let t1 = i as f32 / polygon.len() as f32; let t2 = (i + 1) as f32 / polygon.len() as f32; let color1 = Color::rgba(1.0 - t1, t1, 0.0, 1.0); @@ -242,6 +270,7 @@ fn prepare_lights( position: transform.translation().truncate(), radius: light.radius, }; + // TODO: Remove when shadowmapping is done for x in 0..SHADOWMAP_RESOLUTION { let offset = (i * SHADOWMAP_RESOLUTION + x) * 4; let distance = light.radius; @@ -257,7 +286,7 @@ fn prepare_lights( spot_lights .iter() .enumerate() - .for_each(|(i, (transform, light))| { + .for_each(|(i, (transform, light, entity))| { material.spot_lights[i] = GpuSpotLight2D { position: transform.translation().truncate(), radius: light.radius, @@ -267,6 +296,7 @@ fn prepare_lights( padding2: 0, padding3: 0, }; + // TODO: Remove when shadowmapping is done for x in 0..SHADOWMAP_RESOLUTION { let offset = ((i + MAX_POINT_LIGHTS) * SHADOWMAP_RESOLUTION + x) * 4; let distance = x as f32 / SHADOWMAP_RESOLUTION as f32 * light.radius; @@ -347,7 +377,6 @@ fn get_light_geometry( .for_each(|ray| polygon.push(aabb.center() + *ray)); } - polygon.push(*polygon.first().unwrap()); polygon }