Work in progress towards 2D lighting
This commit is contained in:
58
Cargo.lock
generated
58
Cargo.lock
generated
@@ -43,9 +43,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107"
|
||||
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"getrandom",
|
||||
@@ -1494,7 +1494,7 @@ version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc9fcd393c3daaaf5909008a1d948319d538b79c51871e4df0993260260a94e4"
|
||||
dependencies = [
|
||||
"ahash 0.8.2",
|
||||
"ahash 0.8.3",
|
||||
"epaint",
|
||||
"nohash-hasher",
|
||||
]
|
||||
@@ -1563,7 +1563,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ba04741be7f6602b1a1b28f1082cce45948a7032961c52814f8946b28493300"
|
||||
dependencies = [
|
||||
"ab_glyph",
|
||||
"ahash 0.8.2",
|
||||
"ahash 0.8.3",
|
||||
"atomic_refcell",
|
||||
"bytemuck",
|
||||
"emath",
|
||||
@@ -2524,6 +2524,15 @@ dependencies = [
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom8"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "5.0.0"
|
||||
@@ -2617,18 +2626,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.5.7"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9"
|
||||
checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b"
|
||||
dependencies = [
|
||||
"num_enum_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.5.7"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce"
|
||||
checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
@@ -2842,19 +2851,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "pretty-type-name"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8815d101cfb4cb491154896bdab292a395a7ac9ab185a9941a2f5be0135900d"
|
||||
checksum = "f0f73cdaf19b52e6143685c3606206e114a4dfa969d6b14ec3894c88eb38bd4b"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.2.1"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9"
|
||||
checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"thiserror",
|
||||
"toml",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3370,6 +3378,23 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "729bfd096e40da9c001f778f5cdecbd2957929a24e10e5883d9392220a751581"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"nom8",
|
||||
"toml_datetime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.37"
|
||||
@@ -3700,9 +3725,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "webbrowser"
|
||||
version = "0.8.4"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e74f5ff7786c4c21f61ba8e30ea29c9745f06fca0a4a02d083b3c662583399e8"
|
||||
checksum = "769f1a8831de12cad7bd6f9693b15b1432d93a151557810f617f626af823acae"
|
||||
dependencies = [
|
||||
"core-foundation",
|
||||
"dirs",
|
||||
@@ -3713,7 +3738,6 @@ dependencies = [
|
||||
"raw-window-handle 0.5.0",
|
||||
"url",
|
||||
"web-sys",
|
||||
"windows 0.43.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -1,12 +1,37 @@
|
||||
struct VertexOutput {
|
||||
@builtin(position) clip_position: vec4<f32>,
|
||||
struct FragmentInput {
|
||||
@builtin(position) fragment_coordinate: vec4<f32>,
|
||||
@location(0) world_position: vec4<f32>,
|
||||
@location(1) world_normal: vec3<f32>,
|
||||
@location(2) uv: vec2<f32>,
|
||||
};
|
||||
|
||||
struct TileLight {
|
||||
color: vec4<f32>,
|
||||
intensity: f32,
|
||||
position: vec2<f32>,
|
||||
};
|
||||
|
||||
struct CanvasMaterial {
|
||||
ambient_color: vec4<f32>,
|
||||
tile_lights: array<TileLight, 256u>,
|
||||
number_of_lights: u32,
|
||||
};
|
||||
|
||||
|
||||
@group(1) @binding(0)
|
||||
var<uniform> canvas_material: CanvasMaterial;
|
||||
|
||||
@fragment
|
||||
fn fragment(input: VertexOutput) -> @location(0) vec4<f32> {
|
||||
var output_color = vec4<f32>(input.uv, 1.0, 1.0);
|
||||
fn fragment(input: FragmentInput) -> @location(0) vec4<f32> {
|
||||
var output_color = canvas_material.ambient_color;
|
||||
|
||||
var lighting = vec4<f32>();
|
||||
for (var i: u32 = 0u; i < canvas_material.number_of_lights; i++) {
|
||||
var luminance = canvas_material.tile_lights[i].intensity * pow(length(canvas_material.tile_lights[i].position - input.world_position.xy), -1.7) * 2.0;
|
||||
lighting += vec4<f32>(luminance * canvas_material.tile_lights[i].color.rgb, 0.0);
|
||||
}
|
||||
|
||||
output_color += lighting;
|
||||
|
||||
return output_color;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
mod tile_light;
|
||||
|
||||
use crate::grid;
|
||||
use bevy::{
|
||||
prelude::*,
|
||||
reflect::TypeUuid,
|
||||
render::render_resource::{AsBindGroup, ShaderRef},
|
||||
sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle},
|
||||
render::{
|
||||
render_resource::{encase, AsBindGroup, OwnedBindingResource, ShaderRef, ShaderType},
|
||||
renderer::RenderQueue,
|
||||
RenderApp, RenderStage,
|
||||
},
|
||||
sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle, RenderMaterials2d},
|
||||
};
|
||||
use tile_light::{
|
||||
extract_tile_lights, prepare_tile_lights, TileLight, TileLights, TileLightsUniform,
|
||||
};
|
||||
pub(crate) use tile_light::EmissiveTile;
|
||||
|
||||
pub struct CanvasPlugin;
|
||||
|
||||
@@ -12,17 +22,92 @@ impl Plugin for CanvasPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_plugin(Material2dPlugin::<CanvasMaterial>::default())
|
||||
.add_startup_system(spawn_canvas);
|
||||
|
||||
app.sub_app_mut(RenderApp)
|
||||
.init_resource::<TileLights>()
|
||||
.add_system_to_stage(RenderStage::Extract, extract_tile_lights)
|
||||
.add_system_to_stage(RenderStage::Prepare, prepare_canvas_material);
|
||||
// .add_system_to_stage(RenderStage::Prepare, prepare_tile_lights);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(AsBindGroup, TypeUuid, Clone)]
|
||||
#[uuid = "24f83f6e-e52d-41a6-bf1d-0e46e57a4995"]
|
||||
struct CanvasMaterial {}
|
||||
struct CanvasMaterial {
|
||||
#[uniform(0)]
|
||||
ambient_color: Color,
|
||||
#[uniform(0)]
|
||||
tile_lights: tile_light::TileLightsUniform,
|
||||
#[uniform(0)]
|
||||
number_of_lights: u32,
|
||||
}
|
||||
|
||||
impl Default for CanvasMaterial {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
ambient_color: Color::rgb(0.1, 0.1, 0.1),
|
||||
number_of_lights: 0,
|
||||
tile_lights: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(ShaderType)]
|
||||
struct CanvasMaterialUniform {
|
||||
ambient_color: Color,
|
||||
tile_lights: tile_light::TileLightsUniform,
|
||||
number_of_lights: u32,
|
||||
}
|
||||
|
||||
impl Material2d for CanvasMaterial {
|
||||
fn fragment_shader() -> ShaderRef {
|
||||
"canvas_shader.wgsl".into()
|
||||
}
|
||||
|
||||
// fn specialize(
|
||||
// descriptor: &mut bevy::render::render_resource::RenderPipelineDescriptor,
|
||||
// layout: &bevy::render::mesh::MeshVertexBufferLayout,
|
||||
// key: bevy::sprite::Material2dKey<Self>,
|
||||
// ) -> Result<(), bevy::render::render_resource::SpecializedMeshPipelineError> {
|
||||
// if let Some(layouts) = descriptor.layout {
|
||||
// layouts.push(BindGr);
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
}
|
||||
|
||||
fn prepare_canvas_material(
|
||||
materials: Res<RenderMaterials2d<CanvasMaterial>>,
|
||||
canvas_query: Query<&Handle<CanvasMaterial>>,
|
||||
tile_light_query: Query<&TileLight>,
|
||||
render_queue: Res<RenderQueue>,
|
||||
) {
|
||||
let tile_lights = tile_light_query.iter().cloned().collect::<Vec<_>>();
|
||||
let mut tile_lights_uniform = tile_light::TileLightsUniform::default();
|
||||
// tile_lights_uniform.data.copy_from_slice(&tile_lights);
|
||||
|
||||
let len = tile_lights.len().min(256);
|
||||
let src = &tile_lights[..len];
|
||||
let dst = &mut tile_lights_uniform.data[..len];
|
||||
dst.copy_from_slice(src);
|
||||
|
||||
for handle in canvas_query.iter() {
|
||||
if let Some(material) = materials.get(handle) {
|
||||
let binding = &material.bindings[0];
|
||||
if let OwnedBindingResource::Buffer(cur_buffer) = binding {
|
||||
let mut buffer = encase::UniformBuffer::new(Vec::new());
|
||||
buffer
|
||||
.write(&CanvasMaterialUniform {
|
||||
ambient_color: Color::rgb_u8(12, 12, 12),
|
||||
tile_lights: tile_lights_uniform.clone(),
|
||||
number_of_lights: tile_lights.len() as _,
|
||||
})
|
||||
.unwrap();
|
||||
render_queue.write_buffer(cur_buffer, 0, buffer.as_ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_canvas(
|
||||
@@ -33,7 +118,7 @@ fn spawn_canvas(
|
||||
commands
|
||||
.spawn(MaterialMesh2dBundle {
|
||||
mesh: mesh_assets.add(Mesh::from(shape::Quad::default())).into(),
|
||||
material: canvas_material_assets.add(CanvasMaterial {}),
|
||||
material: canvas_material_assets.add(CanvasMaterial::default()),
|
||||
transform: Transform::from_scale(Vec3::splat(
|
||||
grid::SEGMENT_SIZE * f32::from(grid::SIZE),
|
||||
)),
|
||||
|
||||
88
src/canvas/tile_light.rs
Normal file
88
src/canvas/tile_light.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
use bevy::{
|
||||
math::Vec3Swizzles,
|
||||
prelude::*,
|
||||
render::{
|
||||
render_resource::{ShaderType, UniformBuffer},
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
Extract,
|
||||
},
|
||||
sprite::Material2dPipeline,
|
||||
};
|
||||
|
||||
use super::CanvasMaterial;
|
||||
|
||||
const MAX_TILE_LIGHTS: usize = 256;
|
||||
|
||||
#[derive(Component, Clone, Copy)]
|
||||
pub(crate) struct EmissiveTile {
|
||||
pub intensity: f32,
|
||||
}
|
||||
|
||||
impl Default for EmissiveTile {
|
||||
fn default() -> Self {
|
||||
Self { intensity: 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default, ShaderType, Component)]
|
||||
pub(super) struct TileLight {
|
||||
color: Color,
|
||||
intensity: f32,
|
||||
position: Vec2,
|
||||
}
|
||||
|
||||
#[derive(Default, Resource)]
|
||||
pub(super) struct TileLights(UniformBuffer<TileLightsUniform>);
|
||||
|
||||
#[derive(ShaderType, Clone)]
|
||||
pub(super) struct TileLightsUniform {
|
||||
pub data: Box<[TileLight; MAX_TILE_LIGHTS]>,
|
||||
}
|
||||
|
||||
impl Default for TileLightsUniform {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
data: Box::new([TileLight::default(); MAX_TILE_LIGHTS]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TileLights {
|
||||
fn set(&mut self, lights: &[TileLight]) {
|
||||
let len = lights.len().min(MAX_TILE_LIGHTS);
|
||||
let src = &lights[..len];
|
||||
let dst = &mut self.0.get_mut().data[..len];
|
||||
dst.copy_from_slice(src);
|
||||
}
|
||||
|
||||
fn write_buffer(&mut self, render_device: &RenderDevice, render_queue: &RenderQueue) {
|
||||
self.0.write_buffer(render_device, render_queue);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn extract_tile_lights(
|
||||
mut commands: Commands,
|
||||
emissive_sprite_query: Extract<Query<(Entity, &EmissiveTile, &Sprite, &GlobalTransform)>>,
|
||||
) {
|
||||
for (entity, emissive_sprite, sprite, global_transform) in emissive_sprite_query.iter() {
|
||||
commands.get_or_spawn(entity).insert(TileLight {
|
||||
color: sprite.color,
|
||||
intensity: emissive_sprite.intensity,
|
||||
position: global_transform.translation().xy(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn prepare_tile_lights(
|
||||
render_device: Res<RenderDevice>,
|
||||
render_queue: Res<RenderQueue>,
|
||||
canvas_material_pipeline: Res<Material2dPipeline<CanvasMaterial>>,
|
||||
light_query: Query<&TileLight>,
|
||||
mut tile_lights: ResMut<TileLights>,
|
||||
) {
|
||||
let lights = light_query.iter().cloned().collect::<Vec<_>>();
|
||||
tile_lights.set(&lights);
|
||||
tile_lights.write_buffer(&render_device, &render_queue);
|
||||
|
||||
// canvas_material_pipeline.
|
||||
}
|
||||
@@ -63,6 +63,7 @@ fn spawn_fruit_system(mut commands: Commands, coordinate_query: Query<&grid::Coo
|
||||
})
|
||||
.insert(fruit_coordinate)
|
||||
.insert(Fruit)
|
||||
.insert(crate::canvas::EmissiveTile { intensity: 1.0 })
|
||||
.insert(Name::new("Fruit"));
|
||||
}
|
||||
|
||||
|
||||
@@ -75,10 +75,11 @@ fn setup_system(mut commands: Commands) {
|
||||
..Default::default()
|
||||
})
|
||||
.insert(Name::new("Orthographic Camera"))
|
||||
.insert(BloomSettings {
|
||||
threshold: 0.7,
|
||||
..Default::default()
|
||||
});
|
||||
// .insert(BloomSettings {
|
||||
// threshold: 0.7,
|
||||
// ..Default::default()
|
||||
// })
|
||||
;
|
||||
}
|
||||
|
||||
fn camera_move_system(
|
||||
|
||||
@@ -129,6 +129,7 @@ fn create_snake_segment(commands: &mut Commands, grid_position: grid::Coordinate
|
||||
})
|
||||
.insert(SnakeSegment)
|
||||
.insert(grid_position)
|
||||
.insert(crate::canvas::EmissiveTile { intensity: 1.0 })
|
||||
.id()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user