From f454e39740d724bcb331a0206b43b4cb0900318a Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Thu, 1 Jul 2021 21:46:11 +0200 Subject: [PATCH 1/8] bevy_render2/bevy_pbr2: Update to wgpu 0.9 / naga 0.5 (#19) --- pipelined/bevy_pbr2/Cargo.toml | 2 +- pipelined/bevy_pbr2/src/render/pbr.wgsl | 7 ++++++- pipelined/bevy_render2/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pipelined/bevy_pbr2/Cargo.toml b/pipelined/bevy_pbr2/Cargo.toml index e59352a998a6f..613b36a298b2e 100644 --- a/pipelined/bevy_pbr2/Cargo.toml +++ b/pipelined/bevy_pbr2/Cargo.toml @@ -29,4 +29,4 @@ bitflags = "1.2" # direct dependency required for derive macro bytemuck = { version = "1", features = ["derive"] } crevice = { path = "../../crates/crevice" } -wgpu = "0.8" +wgpu = "0.9" diff --git a/pipelined/bevy_pbr2/src/render/pbr.wgsl b/pipelined/bevy_pbr2/src/render/pbr.wgsl index ac76008202837..5c5a34da085e4 100644 --- a/pipelined/bevy_pbr2/src/render/pbr.wgsl +++ b/pipelined/bevy_pbr2/src/render/pbr.wgsl @@ -356,7 +356,12 @@ fn fetch_shadow(light_id: i32, homogeneous_coords: vec4) -> f32 { // compute texture coordinates for shadow lookup let light_local = homogeneous_coords.xy * flip_correction * proj_correction + vec2(0.5, 0.5); // do the lookup, using HW PCF and comparison - return textureSampleCompare(shadow_textures, shadow_textures_sampler, light_local, i32(light_id), homogeneous_coords.z * proj_correction); + // NOTE: Due to the non-uniform control flow above, we must use the Level variant of + // textureSampleCompare to avoid undefined behaviour due to some of the fragments in + // a quad (2x2 fragments) being processed not being sampled, and this messing with + // mip-mapping functionality. The shadow maps have no mipmaps so Level just samples + // from LOD 0. + return textureSampleCompareLevel(shadow_textures, shadow_textures_sampler, light_local, i32(light_id), homogeneous_coords.z * proj_correction); } struct FragmentInput { diff --git a/pipelined/bevy_render2/Cargo.toml b/pipelined/bevy_render2/Cargo.toml index b8366c3100701..00d17d27c945f 100644 --- a/pipelined/bevy_render2/Cargo.toml +++ b/pipelined/bevy_render2/Cargo.toml @@ -29,7 +29,7 @@ bevy_utils = { path = "../../crates/bevy_utils", version = "0.5.0" } image = { version = "0.23.12", default-features = false } # misc -wgpu = "0.8" +wgpu = "0.9" naga = { git = "https://github.com/gfx-rs/naga", rev = "0cf5484bba530f1134badbd2a1c1a8e9daf2e9c3", features = ["glsl-in", "spv-out", "spv-in", "wgsl-in"] } serde = { version = "1", features = ["derive"] } bitflags = "1.2.1" From 5de75a541ffddc42f9bc6c5731e45623852a3cca Mon Sep 17 00:00:00 2001 From: John Date: Thu, 1 Jul 2021 19:03:33 -0400 Subject: [PATCH 2/8] Fixed issue where transform buffer wasn't creating new bindings on resize. (#7) --- pipelined/bevy_pbr2/src/render/light.rs | 3 ++- pipelined/bevy_pbr2/src/render/mod.rs | 33 ++++++++++++++++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/pipelined/bevy_pbr2/src/render/light.rs b/pipelined/bevy_pbr2/src/render/light.rs index e9d678d4f9ac8..de5b021160bdc 100644 --- a/pipelined/bevy_pbr2/src/render/light.rs +++ b/pipelined/bevy_pbr2/src/render/light.rs @@ -433,12 +433,13 @@ impl Draw for DrawShadowMesh { &[view_uniform_offset.offset], ); + let transform_bindgroup_key = mesh_meta.mesh_transform_bind_group_key.unwrap(); pass.set_bind_group( 1, mesh_meta .into_inner() .mesh_transform_bind_group - .as_ref() + .get_value(transform_bindgroup_key) .unwrap(), &[extracted_mesh.transform_binding_offset], ); diff --git a/pipelined/bevy_pbr2/src/render/mod.rs b/pipelined/bevy_pbr2/src/render/mod.rs index 86066d94bed6b..445d921d630cb 100644 --- a/pipelined/bevy_pbr2/src/render/mod.rs +++ b/pipelined/bevy_pbr2/src/render/mod.rs @@ -420,7 +420,8 @@ struct MeshDrawInfo { pub struct MeshMeta { transform_uniforms: DynamicUniformVec, material_bind_groups: FrameSlabMap, - mesh_transform_bind_group: Option, + mesh_transform_bind_group: FrameSlabMap, + mesh_transform_bind_group_key: Option>, mesh_draw_info: Vec, } @@ -502,16 +503,21 @@ pub fn queue_meshes( } let transform_uniforms = &mesh_meta.transform_uniforms; - mesh_meta.mesh_transform_bind_group.get_or_insert_with(|| { - render_device.create_bind_group(&BindGroupDescriptor { - entries: &[BindGroupEntry { - binding: 0, - resource: transform_uniforms.binding(), - }], - label: None, - layout: &pbr_shaders.mesh_layout, - }) - }); + mesh_meta.mesh_transform_bind_group.next_frame(); + mesh_meta.mesh_transform_bind_group_key = + Some(mesh_meta.mesh_transform_bind_group.get_or_insert_with( + transform_uniforms.uniform_buffer().unwrap().id(), + || { + render_device.create_bind_group(&BindGroupDescriptor { + entries: &[BindGroupEntry { + binding: 0, + resource: transform_uniforms.binding(), + }], + label: None, + layout: &pbr_shaders.mesh_layout, + }) + }, + )); for (entity, view, view_lights, mut transparent_phase) in views.iter_mut() { // TODO: cache this? let view_bind_group = render_device.create_bind_group(&BindGroupDescriptor { @@ -736,7 +742,10 @@ impl Draw for DrawPbr { ); pass.set_bind_group( 1, - mesh_meta.mesh_transform_bind_group.as_ref().unwrap(), + mesh_meta + .mesh_transform_bind_group + .get_value(mesh_meta.mesh_transform_bind_group_key.unwrap()) + .unwrap(), &[extracted_mesh.transform_binding_offset], ); let mesh_draw_info = &mesh_meta.mesh_draw_info[draw_key]; From bbb69ea52555bb39a92c1f1590a3312e49bd2884 Mon Sep 17 00:00:00 2001 From: bilsen <40690317+bilsen@users.noreply.github.com> Date: Fri, 2 Jul 2021 01:09:46 +0200 Subject: [PATCH 3/8] Allows resizing of windows (#8) --- pipelined/bevy_render2/src/view/window.rs | 29 +++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/pipelined/bevy_render2/src/view/window.rs b/pipelined/bevy_render2/src/view/window.rs index 3173da919cc2d..67a3ec50a16e1 100644 --- a/pipelined/bevy_render2/src/view/window.rs +++ b/pipelined/bevy_render2/src/view/window.rs @@ -117,19 +117,22 @@ pub fn prepare_windows( .entry(window.id) .or_insert_with(|| render_device.create_swap_chain(surface, &swap_chain_descriptor)); - let frame = if let Ok(swap_chain_frame) = swap_chain.get_current_frame() { - swap_chain_frame - } else { - let swap_chain = window_surfaces - .swap_chains - .entry(window.id) - .or_insert_with(|| { - render_device.create_swap_chain(surface, &swap_chain_descriptor) - }); - - swap_chain - .get_current_frame() - .expect("Failed to acquire next swap chain texture!") + let frame = match swap_chain.get_current_frame() { + Ok(swap_chain_frame) => { + swap_chain_frame + }, + Err(wgpu::SwapChainError::Outdated) => { + let new_swap_chain = render_device.create_swap_chain(surface, &swap_chain_descriptor); + let frame = new_swap_chain.get_current_frame().expect("Error recreating swap chain"); + window_surfaces.swap_chains.insert( + window.id, + new_swap_chain + ); + frame + }, + err => { + err.expect("Failed to acquire next swap chain texture!") + } }; window.swap_chain_frame = Some(TextureView::from(frame)); From c0b6d05a2a35f4724d70ef9af0e4680e042c4e6f Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Fri, 2 Jul 2021 01:12:35 +0200 Subject: [PATCH 4/8] bevy_pbr2: pbr.wgsl: Fix the orthographic projection check (#17) --- pipelined/bevy_pbr2/src/render/pbr.wgsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipelined/bevy_pbr2/src/render/pbr.wgsl b/pipelined/bevy_pbr2/src/render/pbr.wgsl index 5c5a34da085e4..0e5066b73ecd5 100644 --- a/pipelined/bevy_pbr2/src/render/pbr.wgsl +++ b/pipelined/bevy_pbr2/src/render/pbr.wgsl @@ -427,7 +427,7 @@ fn fragment(in: FragmentInput) -> [[location(0)]] vec4 { // # endif var V: vec3; - if (view.view_proj.z.z != 1.0) { // If the projection is not orthographic + if (view.view_proj.w.w != 1.0) { // If the projection is not orthographic // Only valid for a perpective projection V = normalize(view.world_position.xyz - in.world_position.xyz); } else { From c16a030a9eedbce961f87b2037149244c3711570 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Fri, 2 Jul 2021 01:23:11 +0200 Subject: [PATCH 5/8] Do not queue sprites/meshes if there are no views (#13) * bevy_sprite2/_pbr2: Do not queue sprites/meshes if there are no views --- pipelined/bevy_pbr2/src/render/mod.rs | 4 ++++ .../src/render_resource/uniform_vec.rs | 10 ++++++++++ .../bevy_render2/src/renderer/render_device.rs | 5 ++++- pipelined/bevy_sprite2/src/render/mod.rs | 17 ++++++++++++++++- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/pipelined/bevy_pbr2/src/render/mod.rs b/pipelined/bevy_pbr2/src/render/mod.rs index 445d921d630cb..92ff97d231c16 100644 --- a/pipelined/bevy_pbr2/src/render/mod.rs +++ b/pipelined/bevy_pbr2/src/render/mod.rs @@ -488,6 +488,10 @@ pub fn queue_meshes( ) { let mesh_meta = mesh_meta.into_inner(); + if view_meta.uniforms.len() == 0 { + return; + } + light_meta.shadow_view_bind_group.get_or_insert_with(|| { render_device.create_bind_group(&BindGroupDescriptor { entries: &[BindGroupEntry { diff --git a/pipelined/bevy_render2/src/render_resource/uniform_vec.rs b/pipelined/bevy_render2/src/render_resource/uniform_vec.rs index 18134740ce892..164b1c895e963 100644 --- a/pipelined/bevy_render2/src/render_resource/uniform_vec.rs +++ b/pipelined/bevy_render2/src/render_resource/uniform_vec.rs @@ -44,6 +44,11 @@ impl UniformVec { }) } + #[inline] + pub fn len(&self) -> usize { + self.values.len() + } + #[inline] pub fn capacity(&self) -> usize { self.capacity @@ -145,6 +150,11 @@ impl DynamicUniformVec { self.uniform_vec.binding() } + #[inline] + pub fn len(&self) -> usize { + self.uniform_vec.len() + } + #[inline] pub fn capacity(&self) -> usize { self.uniform_vec.capacity() diff --git a/pipelined/bevy_render2/src/renderer/render_device.rs b/pipelined/bevy_render2/src/renderer/render_device.rs index 2063a95ead12e..2cb437c1222ee 100644 --- a/pipelined/bevy_render2/src/renderer/render_device.rs +++ b/pipelined/bevy_render2/src/renderer/render_device.rs @@ -36,7 +36,10 @@ impl RenderDevice { /// Creates a shader module from either SPIR-V or WGSL source code. #[inline] - pub fn create_shader_module<'a>(&self, desc: impl Into>) -> wgpu::ShaderModule { + pub fn create_shader_module<'a>( + &self, + desc: impl Into>, + ) -> wgpu::ShaderModule { self.device.create_shader_module(&desc.into()) } diff --git a/pipelined/bevy_sprite2/src/render/mod.rs b/pipelined/bevy_sprite2/src/render/mod.rs index 3e1de274f7878..1c2e1b80065b3 100644 --- a/pipelined/bevy_sprite2/src/render/mod.rs +++ b/pipelined/bevy_sprite2/src/render/mod.rs @@ -2,7 +2,18 @@ use crate::Sprite; use bevy_asset::{Assets, Handle}; use bevy_ecs::{prelude::*, system::SystemState}; use bevy_math::{Mat4, Vec2, Vec3, Vec4Swizzles}; -use bevy_render2::{core_pipeline::Transparent2dPhase, mesh::{shape::Quad, Indices, Mesh, VertexAttributeValues}, render_asset::RenderAssets, render_graph::{Node, NodeRunError, RenderGraphContext}, render_phase::{Draw, DrawFunctions, Drawable, RenderPhase, TrackedRenderPass}, render_resource::*, renderer::{RenderContext, RenderDevice}, shader::Shader, texture::{BevyDefault, Image}, view::{ViewMeta, ViewUniform, ViewUniformOffset}}; +use bevy_render2::{ + core_pipeline::Transparent2dPhase, + mesh::{shape::Quad, Indices, Mesh, VertexAttributeValues}, + render_asset::RenderAssets, + render_graph::{Node, NodeRunError, RenderGraphContext}, + render_phase::{Draw, DrawFunctions, Drawable, RenderPhase, TrackedRenderPass}, + render_resource::*, + renderer::{RenderContext, RenderDevice}, + shader::Shader, + texture::{BevyDefault, Image}, + view::{ViewMeta, ViewUniform, ViewUniformOffset}, +}; use bevy_transform::components::GlobalTransform; use bevy_utils::slab::{FrameSlabMap, FrameSlabMapKey}; use bytemuck::{Pod, Zeroable}; @@ -276,6 +287,10 @@ pub fn queue_sprites( gpu_images: Res>, mut views: Query<&mut RenderPhase>, ) { + if view_meta.uniforms.len() == 0 { + return; + } + // TODO: define this without needing to check every frame sprite_meta.view_bind_group.get_or_insert_with(|| { render_device.create_bind_group(&BindGroupDescriptor { From 30e4b8d1a8aaad75828ba90c74eda82c9226f828 Mon Sep 17 00:00:00 2001 From: Jonas Matser Date: Fri, 2 Jul 2021 01:48:55 +0200 Subject: [PATCH 6/8] Omnilight shadow map wgsl (#15) --- crates/bevy_wgpu/Cargo.toml | 2 +- examples/3d/3d_scene_pipelined.rs | 117 +++++++++++++++-- pipelined/bevy_pbr2/src/render/light.rs | 165 +++++++++++++++++------- pipelined/bevy_pbr2/src/render/mod.rs | 4 +- pipelined/bevy_pbr2/src/render/pbr.wgsl | 57 +++++--- 5 files changed, 267 insertions(+), 78 deletions(-) diff --git a/crates/bevy_wgpu/Cargo.toml b/crates/bevy_wgpu/Cargo.toml index 66940cb55a17b..30b4581e99a10 100644 --- a/crates/bevy_wgpu/Cargo.toml +++ b/crates/bevy_wgpu/Cargo.toml @@ -29,7 +29,7 @@ bevy_winit = { path = "../bevy_winit", optional = true, version = "0.5.0" } bevy_utils = { path = "../bevy_utils", version = "0.5.0" } # other -wgpu = "0.8" +wgpu = "0.9" futures-lite = "1.4.0" crossbeam-channel = "0.5.0" crossbeam-utils = "0.8.1" diff --git a/examples/3d/3d_scene_pipelined.rs b/examples/3d/3d_scene_pipelined.rs index 186c745df5b21..9d2ae6be0a0fc 100644 --- a/examples/3d/3d_scene_pipelined.rs +++ b/examples/3d/3d_scene_pipelined.rs @@ -3,9 +3,9 @@ use bevy::{ diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, ecs::prelude::*, input::Input, - math::Vec3, - pbr2::{OmniLightBundle, PbrBundle, StandardMaterial}, - prelude::{App, Assets, KeyCode, Transform}, + math::{Quat, Vec3}, + pbr2::{OmniLight, OmniLightBundle, PbrBundle, StandardMaterial}, + prelude::{App, Assets, BuildChildren, KeyCode, Transform}, render2::{ camera::PerspectiveCameraBundle, color::Color, @@ -42,6 +42,32 @@ fn setup( }), ..Default::default() }); + + let mut transform = Transform::from_xyz(2.5, 2.5, 0.0); + transform.rotate(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2)); + commands.spawn_bundle(PbrBundle { + mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })), + transform, + material: materials.add(StandardMaterial { + base_color: Color::INDIGO, + perceptual_roughness: 1.0, + ..Default::default() + }), + ..Default::default() + }); + + let mut transform = Transform::from_xyz(0.0, 2.5, -2.5); + transform.rotate(Quat::from_rotation_x(std::f32::consts::FRAC_PI_2)); + commands.spawn_bundle(PbrBundle { + mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })), + transform, + material: materials.add(StandardMaterial { + base_color: Color::INDIGO, + perceptual_roughness: 1.0, + ..Default::default() + }), + ..Default::default() + }); // cube commands .spawn_bundle(PbrBundle { @@ -69,14 +95,89 @@ fn setup( ..Default::default() }) .insert(Movable); + // light - commands.spawn_bundle(OmniLightBundle { - transform: Transform::from_xyz(5.0, 8.0, 2.0), - ..Default::default() - }); + commands + .spawn_bundle(OmniLightBundle { + // transform: Transform::from_xyz(5.0, 8.0, 2.0), + transform: Transform::from_xyz(1.0, 2.0, 0.0), + omni_light: OmniLight { + color: Color::RED, + ..Default::default() + }, + ..Default::default() + }) + .with_children(|builder| { + builder.spawn_bundle(PbrBundle { + mesh: meshes.add(Mesh::from(shape::UVSphere { + radius: 0.1, + ..Default::default() + })), + material: materials.add(StandardMaterial { + base_color: Color::RED, + emissive: Color::rgba_linear(100.0, 0.0, 0.0, 0.0), + ..Default::default() + }), + ..Default::default() + }); + }); + + // light + commands + .spawn_bundle(OmniLightBundle { + // transform: Transform::from_xyz(5.0, 8.0, 2.0), + transform: Transform::from_xyz(-1.0, 2.0, 0.0), + omni_light: OmniLight { + color: Color::GREEN, + ..Default::default() + }, + ..Default::default() + }) + .with_children(|builder| { + builder.spawn_bundle(PbrBundle { + mesh: meshes.add(Mesh::from(shape::UVSphere { + radius: 0.1, + ..Default::default() + })), + material: materials.add(StandardMaterial { + base_color: Color::GREEN, + emissive: Color::rgba_linear(0.0, 100.0, 0.0, 0.0), + ..Default::default() + }), + ..Default::default() + }); + }); + + // light + commands + .spawn_bundle(OmniLightBundle { + // transform: Transform::from_xyz(5.0, 8.0, 2.0), + transform: Transform::from_xyz(0.0, 4.0, 0.0), + omni_light: OmniLight { + color: Color::BLUE, + ..Default::default() + }, + ..Default::default() + }) + .with_children(|builder| { + builder.spawn_bundle(PbrBundle { + mesh: meshes.add(Mesh::from(shape::UVSphere { + radius: 0.1, + ..Default::default() + })), + material: materials.add(StandardMaterial { + base_color: Color::BLUE, + emissive: Color::rgba_linear(0.0, 0.0, 100.0, 0.0), + ..Default::default() + }), + ..Default::default() + }); + }); + // camera commands.spawn_bundle(PerspectiveCameraBundle { - transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), + transform: Transform::from_xyz(-2.0, 5.0, 7.5) + .looking_at(Vec3::new(0.0, 2.0, 0.0), Vec3::Y), ..Default::default() }); } diff --git a/pipelined/bevy_pbr2/src/render/light.rs b/pipelined/bevy_pbr2/src/render/light.rs index de5b021160bdc..345a437eef300 100644 --- a/pipelined/bevy_pbr2/src/render/light.rs +++ b/pipelined/bevy_pbr2/src/render/light.rs @@ -1,6 +1,6 @@ use crate::{AmbientLight, ExtractedMeshes, MeshMeta, OmniLight, PbrShaders}; use bevy_ecs::{prelude::*, system::SystemState}; -use bevy_math::{Mat4, Vec3, Vec4}; +use bevy_math::{const_vec3, Mat4, Vec3, Vec4}; use bevy_render2::{ color::Color, core_pipeline::Transparent3dPhase, @@ -34,10 +34,12 @@ pub struct ExtractedPointLight { #[derive(Copy, Clone, AsStd140, Default, Debug)] pub struct GpuLight { color: Vec4, - range: f32, - radius: f32, + // proj: Mat4, position: Vec3, - view_proj: Mat4, + inverse_square_range: f32, + radius: f32, + near: f32, + far: f32, } #[repr(C)] @@ -54,7 +56,7 @@ pub const MAX_OMNI_LIGHTS: usize = 10; pub const SHADOW_SIZE: Extent3d = Extent3d { width: 1024, height: 1024, - depth_or_array_layers: MAX_OMNI_LIGHTS as u32, + depth_or_array_layers: 6 * MAX_OMNI_LIGHTS as u32, }; pub const SHADOW_FORMAT: TextureFormat = TextureFormat::Depth32Float; @@ -148,7 +150,7 @@ impl FromWorld for ShadowShaders { topology: PrimitiveTopology::TriangleList, strip_index_format: None, front_face: FrontFace::Ccw, - cull_mode: Some(Face::Back), + cull_mode: None, polygon_mode: PolygonMode::Fill, clamp_depth: false, conservative: false, @@ -193,8 +195,52 @@ pub fn extract_lights( } } +// Can't do `Vec3::Y * -1.0` because mul isn't const +const NEGATIVE_X: Vec3 = const_vec3!([-1.0, 0.0, 0.0]); +const NEGATIVE_Y: Vec3 = const_vec3!([0.0, -1.0, 0.0]); +const NEGATIVE_Z: Vec3 = const_vec3!([0.0, 0.0, -1.0]); + +struct CubeMapFace { + target: Vec3, + up: Vec3, +} + +// see https://www.khronos.org/opengl/wiki/Cubemap_Texture +const CUBE_MAP_FACES: [CubeMapFace; 6] = [ + // 0 GL_TEXTURE_CUBE_MAP_POSITIVE_X + CubeMapFace { + target: NEGATIVE_X, + up: NEGATIVE_Y, + }, + // 1 GL_TEXTURE_CUBE_MAP_NEGATIVE_X + CubeMapFace { + target: Vec3::X, + up: NEGATIVE_Y, + }, + // 2 GL_TEXTURE_CUBE_MAP_POSITIVE_Y + CubeMapFace { + target: NEGATIVE_Y, + up: Vec3::Z, + }, + // 3 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y + CubeMapFace { + target: Vec3::Y, + up: NEGATIVE_Z, + }, + // 4 GL_TEXTURE_CUBE_MAP_POSITIVE_Z + CubeMapFace { + target: NEGATIVE_Z, + up: NEGATIVE_Y, + }, + // 5 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + CubeMapFace { + target: Vec3::Z, + up: NEGATIVE_Y, + }, +]; + pub struct ViewLight { - pub depth_texture: TextureView, + pub depth_texture_view: TextureView, } pub struct ViewLights { @@ -248,59 +294,79 @@ pub fn prepare_lights( }; // TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query - for (i, light) in lights.iter().enumerate().take(MAX_OMNI_LIGHTS) { - let depth_texture_view = - light_depth_texture - .texture - .create_view(&TextureViewDescriptor { - label: None, - format: None, - dimension: Some(TextureViewDimension::D2), - aspect: TextureAspect::All, - base_mip_level: 0, - mip_level_count: None, - base_array_layer: i as u32, - array_layer_count: NonZeroU32::new(1), - }); - - let view_transform = GlobalTransform::from_translation(light.transform.translation) - .looking_at(Vec3::default(), Vec3::Y); - // TODO: configure light projection based on light configuration + for (light_index, light) in lights.iter().enumerate().take(MAX_OMNI_LIGHTS) { let projection = Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1, light.range); - gpu_lights.lights[i] = GpuLight { + // ignore scale because we don't want to effectively scale light radius and range + // by applying those as a view transform to shadow map rendering of objects + // and ignore rotation because we want the shadow map projections to align with the axes + let view_translation = GlobalTransform::from_translation(light.transform.translation); + + for (face_index, CubeMapFace { target, up }) in CUBE_MAP_FACES.iter().enumerate() { + // use the cubemap projection direction + let view_rotation = GlobalTransform::identity().looking_at(*target, *up); + + let depth_texture_view = + light_depth_texture + .texture + .create_view(&TextureViewDescriptor { + label: None, + format: None, + dimension: Some(TextureViewDimension::D2), + aspect: TextureAspect::All, + base_mip_level: 0, + mip_level_count: None, + base_array_layer: (light_index * 6 + face_index) as u32, + array_layer_count: NonZeroU32::new(1), + }); + + let view_light_entity = commands + .spawn() + .insert_bundle(( + ViewLight { depth_texture_view }, + ExtractedView { + width: SHADOW_SIZE.width, + height: SHADOW_SIZE.height, + transform: view_translation * view_rotation, + projection, + }, + RenderPhase::::default(), + )) + .id(); + view_lights.push(view_light_entity); + } + + gpu_lights.lights[light_index] = GpuLight { // premultiply color by intensity // we don't use the alpha at all, so no reason to multiply only [0..3] color: (light.color.as_rgba_linear() * light.intensity).into(), radius: light.radius.into(), position: light.transform.translation.into(), - range: 1.0 / (light.range * light.range), - // this could technically be copied to the gpu from the light's ViewUniforms - view_proj: projection * view_transform.compute_matrix().inverse(), + inverse_square_range: 1.0 / (light.range * light.range), + near: 0.1, + far: light.range, + // proj: projection, }; - - let view_light_entity = commands - .spawn() - .insert_bundle(( - ViewLight { - depth_texture: depth_texture_view, - }, - ExtractedView { - width: SHADOW_SIZE.width, - height: SHADOW_SIZE.height, - transform: view_transform.clone(), - projection, - }, - RenderPhase::::default(), - )) - .id(); - view_lights.push(view_light_entity); } + let light_depth_texture_view = + light_depth_texture + .texture + .create_view(&TextureViewDescriptor { + label: None, + format: None, + dimension: Some(TextureViewDimension::CubeArray), + aspect: TextureAspect::All, + base_mip_level: 0, + mip_level_count: None, + base_array_layer: 0 as u32, + array_layer_count: None, + }); + commands.entity(entity).insert(ViewLights { light_depth_texture: light_depth_texture.texture, - light_depth_texture_view: light_depth_texture.default_view, + light_depth_texture_view, lights: view_lights, gpu_light_binding_index: light_meta.view_gpu_lights.push(gpu_lights), }); @@ -356,7 +422,7 @@ impl Node for ShadowPassNode { label: Some("shadow_pass"), color_attachments: &[], depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { - view: &view_light.depth_texture, + view: &view_light.depth_texture_view, depth_ops: Some(Operations { load: LoadOp::Clear(1.0), store: true, @@ -422,7 +488,8 @@ impl Draw for DrawShadowMesh { self.params.get(world); let view_uniform_offset = views.get(view).unwrap(); let extracted_mesh = &extracted_meshes.into_inner().meshes[draw_key]; - pass.set_render_pipeline(&shadow_shaders.into_inner().pipeline); + let shadow_shaders = shadow_shaders.into_inner(); + pass.set_render_pipeline(&shadow_shaders.pipeline); pass.set_bind_group( 0, light_meta diff --git a/pipelined/bevy_pbr2/src/render/mod.rs b/pipelined/bevy_pbr2/src/render/mod.rs index 92ff97d231c16..c791f5c7e4058 100644 --- a/pipelined/bevy_pbr2/src/render/mod.rs +++ b/pipelined/bevy_pbr2/src/render/mod.rs @@ -68,7 +68,7 @@ impl FromWorld for PbrShaders { has_dynamic_offset: true, // TODO: change this to ViewUniform::std140_size_static once crevice fixes this! // Context: https://github.com/LPGhatguy/crevice/issues/29 - min_binding_size: BufferSize::new(1264), + min_binding_size: BufferSize::new(512), }, count: None, }, @@ -79,7 +79,7 @@ impl FromWorld for PbrShaders { ty: BindingType::Texture { multisampled: false, sample_type: TextureSampleType::Depth, - view_dimension: TextureViewDimension::D2Array, + view_dimension: TextureViewDimension::CubeArray, }, count: None, }, diff --git a/pipelined/bevy_pbr2/src/render/pbr.wgsl b/pipelined/bevy_pbr2/src/render/pbr.wgsl index 0e5066b73ecd5..975862081a277 100644 --- a/pipelined/bevy_pbr2/src/render/pbr.wgsl +++ b/pipelined/bevy_pbr2/src/render/pbr.wgsl @@ -40,7 +40,7 @@ fn vertex(vertex: Vertex) -> VertexOutput { // of normals out.world_normal = mat3x3(mesh.transform.x.xyz, mesh.transform.y.xyz, mesh.transform.z.xyz) * vertex.normal; return out; -} +} // From the Filament design doc // https://google.github.io/filament/Filament.html#table_symbols @@ -89,10 +89,12 @@ struct StandardMaterial { struct OmniLight { color: vec4; - range: f32; - radius: f32; + // projection: mat4x4; position: vec3; - view_projection: mat4x4; + inverse_square_range: f32; + radius: f32; + near: f32; + far: f32; }; [[block]] @@ -115,7 +117,7 @@ let FLAGS_UNLIT_BIT: u32 = 32u; [[group(0), binding(1)]] var lights: Lights; [[group(0), binding(2)]] -var shadow_textures: texture_depth_2d_array; +var shadow_textures: texture_depth_cube_array; [[group(0), binding(3)]] var shadow_textures_sampler: sampler_comparison; @@ -301,7 +303,7 @@ fn omni_light( let light_to_frag = light.position.xyz - world_position.xyz; let distance_square = dot(light_to_frag, light_to_frag); let rangeAttenuation = - getDistanceAttenuation(distance_square, light.range); + getDistanceAttenuation(distance_square, light.inverse_square_range); // Specular. // Representative Point Area Lights. @@ -346,22 +348,41 @@ fn omni_light( return ((diffuse + specular_light) * light.color.rgb) * (rangeAttenuation * NoL); } -fn fetch_shadow(light_id: i32, homogeneous_coords: vec4) -> f32 { - if (homogeneous_coords.w <= 0.0) { - return 1.0; - } - // compensate for the Y-flip difference between the NDC and texture coordinates - let flip_correction = vec2(0.5, -0.5); - let proj_correction = 1.0 / homogeneous_coords.w; - // compute texture coordinates for shadow lookup - let light_local = homogeneous_coords.xy * flip_correction * proj_correction + vec2(0.5, 0.5); +fn fetch_shadow(light_id: i32, frag_position: vec4) -> f32 { + let light = lights.omni_lights[light_id]; + + // because the shadow maps align with the axes and the frustum planes are at 45 degrees + // we can get the worldspace depth by taking the largest absolute axis + let frag_ls = light.position.xyz - frag_position.xyz; + let abs_position_ls = abs(frag_ls); + let major_axis_magnitude = max(abs_position_ls.x, max(abs_position_ls.y, abs_position_ls.z)); + + // do a full projection + // vec4 clip = light.projection * vec4(0.0, 0.0, -major_axis_magnitude, 1.0); + // float depth = (clip.z / clip.w); + + // alternatively do only the necessary multiplications using near/far + let proj_r = light.far / (light.near - light.far); + let z = -major_axis_magnitude * proj_r + light.near * proj_r; + let w = major_axis_magnitude; + let depth = z / w; + + // let shadow = texture(samplerCubeArrayShadow(t_Shadow, s_Shadow), vec4(frag_ls, i), depth - bias); + + // manual depth testing + // float shadow = texture(samplerCubeArray(t_Shadow, s_Shadow), vec4(-frag_ls, 6 * i)).r; + // shadow = depth > shadow ? 0.0 : 1.0; + // o_Target = vec4(vec3(shadow * 20 - 19, depth * 20 - 19, 0.0), 1.0); + // o_Target = vec4(vec3(shadow * 20 - 19), 1.0); + // do the lookup, using HW PCF and comparison // NOTE: Due to the non-uniform control flow above, we must use the Level variant of // textureSampleCompare to avoid undefined behaviour due to some of the fragments in // a quad (2x2 fragments) being processed not being sampled, and this messing with // mip-mapping functionality. The shadow maps have no mipmaps so Level just samples // from LOD 0. - return textureSampleCompareLevel(shadow_textures, shadow_textures_sampler, light_local, i32(light_id), homogeneous_coords.z * proj_correction); + let bias = 0.0001; + return textureSampleCompareLevel(shadow_textures, shadow_textures_sampler, frag_ls, i32(light_id), depth - bias); } struct FragmentInput { @@ -453,7 +474,7 @@ fn fragment(in: FragmentInput) -> [[location(0)]] vec4 { for (var i: i32 = 0; i < i32(lights.num_lights); i = i + 1) { let light = lights.omni_lights[i]; let light_contrib = omni_light(in.world_position.xyz, light, roughness, NdotV, N, V, R, F0, diffuse_color); - let shadow = fetch_shadow(i, light.view_projection * in.world_position); + let shadow = fetch_shadow(i, in.world_position); light_accum = light_accum + light_contrib * shadow; } @@ -474,4 +495,4 @@ fn fragment(in: FragmentInput) -> [[location(0)]] vec4 { } return output_color; -} \ No newline at end of file +} From d0c3185c2349f29357224ac9e573767b75afb789 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Thu, 1 Jul 2021 16:54:58 -0700 Subject: [PATCH 7/8] omni light -> point light --- examples/3d/3d_scene_pipelined.rs | 14 +++++++------- examples/3d/pbr_pipelined.rs | 6 +++--- pipelined/bevy_pbr2/src/bundle.rs | 6 +++--- pipelined/bevy_pbr2/src/light.rs | 8 ++++---- pipelined/bevy_pbr2/src/render/light.rs | 18 +++++++++--------- pipelined/bevy_pbr2/src/render/pbr.wgsl | 14 +++++++------- pipelined/bevy_render2/src/view/window.rs | 22 ++++++++++------------ 7 files changed, 43 insertions(+), 45 deletions(-) diff --git a/examples/3d/3d_scene_pipelined.rs b/examples/3d/3d_scene_pipelined.rs index 9d2ae6be0a0fc..97801d9796fbd 100644 --- a/examples/3d/3d_scene_pipelined.rs +++ b/examples/3d/3d_scene_pipelined.rs @@ -4,7 +4,7 @@ use bevy::{ ecs::prelude::*, input::Input, math::{Quat, Vec3}, - pbr2::{OmniLight, OmniLightBundle, PbrBundle, StandardMaterial}, + pbr2::{PbrBundle, PointLight, PointLightBundle, StandardMaterial}, prelude::{App, Assets, BuildChildren, KeyCode, Transform}, render2::{ camera::PerspectiveCameraBundle, @@ -98,10 +98,10 @@ fn setup( // light commands - .spawn_bundle(OmniLightBundle { + .spawn_bundle(PointLightBundle { // transform: Transform::from_xyz(5.0, 8.0, 2.0), transform: Transform::from_xyz(1.0, 2.0, 0.0), - omni_light: OmniLight { + point_light: PointLight { color: Color::RED, ..Default::default() }, @@ -124,10 +124,10 @@ fn setup( // light commands - .spawn_bundle(OmniLightBundle { + .spawn_bundle(PointLightBundle { // transform: Transform::from_xyz(5.0, 8.0, 2.0), transform: Transform::from_xyz(-1.0, 2.0, 0.0), - omni_light: OmniLight { + point_light: PointLight { color: Color::GREEN, ..Default::default() }, @@ -150,10 +150,10 @@ fn setup( // light commands - .spawn_bundle(OmniLightBundle { + .spawn_bundle(PointLightBundle { // transform: Transform::from_xyz(5.0, 8.0, 2.0), transform: Transform::from_xyz(0.0, 4.0, 0.0), - omni_light: OmniLight { + point_light: PointLight { color: Color::BLUE, ..Default::default() }, diff --git a/examples/3d/pbr_pipelined.rs b/examples/3d/pbr_pipelined.rs index 2aa96016291a5..470326cab3e9d 100644 --- a/examples/3d/pbr_pipelined.rs +++ b/examples/3d/pbr_pipelined.rs @@ -1,7 +1,7 @@ use bevy::{ ecs::prelude::*, math::Vec3, - pbr2::{OmniLight, OmniLightBundle, PbrBundle, StandardMaterial}, + pbr2::{PbrBundle, PointLight, PointLightBundle, StandardMaterial}, prelude::{App, Assets, Transform}, render2::{ camera::{OrthographicCameraBundle, OrthographicProjection}, @@ -64,9 +64,9 @@ fn setup( ..Default::default() }); // light - commands.spawn_bundle(OmniLightBundle { + commands.spawn_bundle(PointLightBundle { transform: Transform::from_translation(Vec3::new(50.0, 50.0, 50.0)), - omni_light: OmniLight { + point_light: PointLight { intensity: 50000., range: 100., ..Default::default() diff --git a/pipelined/bevy_pbr2/src/bundle.rs b/pipelined/bevy_pbr2/src/bundle.rs index dd9043d1db7af..933384edd6ded 100644 --- a/pipelined/bevy_pbr2/src/bundle.rs +++ b/pipelined/bevy_pbr2/src/bundle.rs @@ -1,4 +1,4 @@ -use crate::{OmniLight, StandardMaterial}; +use crate::{PointLight, StandardMaterial}; use bevy_asset::Handle; use bevy_ecs::bundle::Bundle; use bevy_render2::mesh::Mesh; @@ -25,8 +25,8 @@ impl Default for PbrBundle { /// A component bundle for "light" entities #[derive(Debug, Bundle, Default)] -pub struct OmniLightBundle { - pub omni_light: OmniLight, +pub struct PointLightBundle { + pub point_light: PointLight, pub transform: Transform, pub global_transform: GlobalTransform, } diff --git a/pipelined/bevy_pbr2/src/light.rs b/pipelined/bevy_pbr2/src/light.rs index 24e9709ae15d7..d2451abb8b262 100644 --- a/pipelined/bevy_pbr2/src/light.rs +++ b/pipelined/bevy_pbr2/src/light.rs @@ -2,19 +2,19 @@ use bevy_ecs::reflect::ReflectComponent; use bevy_reflect::Reflect; use bevy_render2::color::Color; -/// An omnidirectional light +/// A light that emits light in all directions from a central point. #[derive(Debug, Clone, Copy, Reflect)] #[reflect(Component)] -pub struct OmniLight { +pub struct PointLight { pub color: Color, pub intensity: f32, pub range: f32, pub radius: f32, } -impl Default for OmniLight { +impl Default for PointLight { fn default() -> Self { - OmniLight { + PointLight { color: Color::rgb(1.0, 1.0, 1.0), intensity: 200.0, range: 20.0, diff --git a/pipelined/bevy_pbr2/src/render/light.rs b/pipelined/bevy_pbr2/src/render/light.rs index 345a437eef300..df1be8368c264 100644 --- a/pipelined/bevy_pbr2/src/render/light.rs +++ b/pipelined/bevy_pbr2/src/render/light.rs @@ -1,4 +1,4 @@ -use crate::{AmbientLight, ExtractedMeshes, MeshMeta, OmniLight, PbrShaders}; +use crate::{AmbientLight, ExtractedMeshes, MeshMeta, PbrShaders, PointLight}; use bevy_ecs::{prelude::*, system::SystemState}; use bevy_math::{const_vec3, Mat4, Vec3, Vec4}; use bevy_render2::{ @@ -11,7 +11,7 @@ use bevy_render2::{ render_resource::*, renderer::{RenderContext, RenderDevice}, texture::*, - view::{ExtractedView, ViewUniform, ViewUniformOffset}, + view::{ExtractedView, ViewUniformOffset}, }; use bevy_transform::components::GlobalTransform; use crevice::std140::AsStd140; @@ -46,17 +46,17 @@ pub struct GpuLight { #[derive(Copy, Clone, Debug, AsStd140)] pub struct GpuLights { // TODO: this comes first to work around a WGSL alignment issue. We need to solve this issue before releasing the renderer rework - lights: [GpuLight; MAX_OMNI_LIGHTS], + lights: [GpuLight; MAX_POINT_LIGHTS], ambient_color: Vec4, len: u32, } -// NOTE: this must be kept in sync MAX_OMNI_LIGHTS in pbr.frag -pub const MAX_OMNI_LIGHTS: usize = 10; +// NOTE: this must be kept in sync MAX_POINT_LIGHTS in pbr.frag +pub const MAX_POINT_LIGHTS: usize = 10; pub const SHADOW_SIZE: Extent3d = Extent3d { width: 1024, height: 1024, - depth_or_array_layers: 6 * MAX_OMNI_LIGHTS as u32, + depth_or_array_layers: 6 * MAX_POINT_LIGHTS as u32, }; pub const SHADOW_FORMAT: TextureFormat = TextureFormat::Depth32Float; @@ -178,7 +178,7 @@ impl FromWorld for ShadowShaders { pub fn extract_lights( mut commands: Commands, ambient_light: Res, - lights: Query<(Entity, &OmniLight, &GlobalTransform)>, + lights: Query<(Entity, &PointLight, &GlobalTransform)>, ) { commands.insert_resource(ExtractedAmbientLight { color: ambient_light.color, @@ -290,11 +290,11 @@ pub fn prepare_lights( let mut gpu_lights = GpuLights { ambient_color: ambient_color.into(), len: lights.iter().len() as u32, - lights: [GpuLight::default(); MAX_OMNI_LIGHTS], + lights: [GpuLight::default(); MAX_POINT_LIGHTS], }; // TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query - for (light_index, light) in lights.iter().enumerate().take(MAX_OMNI_LIGHTS) { + for (light_index, light) in lights.iter().enumerate().take(MAX_POINT_LIGHTS) { let projection = Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1, light.range); diff --git a/pipelined/bevy_pbr2/src/render/pbr.wgsl b/pipelined/bevy_pbr2/src/render/pbr.wgsl index 975862081a277..fa2f555db6dbe 100644 --- a/pipelined/bevy_pbr2/src/render/pbr.wgsl +++ b/pipelined/bevy_pbr2/src/render/pbr.wgsl @@ -87,7 +87,7 @@ struct StandardMaterial { flags: u32; }; -struct OmniLight { +struct PointLight { color: vec4; // projection: mat4x4; position: vec3; @@ -101,7 +101,7 @@ struct OmniLight { struct Lights { // NOTE: this array size must be kept in sync with the constants defined bevy_pbr2/src/render/light.rs // TODO: this can be removed if we move to storage buffers for light arrays - omni_lights: array; + point_lights: array; ambient_color: vec4; num_lights: u32; }; @@ -296,8 +296,8 @@ fn reinhard_extended_luminance(color: vec3, max_white_l: f32) -> vec3 return change_luminance(color, l_new); } -fn omni_light( - world_position: vec3, light: OmniLight, roughness: f32, NdotV: f32, N: vec3, V: vec3, +fn point_light( + world_position: vec3, light: PointLight, roughness: f32, NdotV: f32, N: vec3, V: vec3, R: vec3, F0: vec3, diffuseColor: vec3 ) -> vec3 { let light_to_frag = light.position.xyz - world_position.xyz; @@ -349,7 +349,7 @@ fn omni_light( } fn fetch_shadow(light_id: i32, frag_position: vec4) -> f32 { - let light = lights.omni_lights[light_id]; + let light = lights.point_lights[light_id]; // because the shadow maps align with the axes and the frustum planes are at 45 degrees // we can get the worldspace depth by taking the largest absolute axis @@ -472,8 +472,8 @@ fn fragment(in: FragmentInput) -> [[location(0)]] vec4 { // accumulate color var light_accum: vec3 = vec3(0.0); for (var i: i32 = 0; i < i32(lights.num_lights); i = i + 1) { - let light = lights.omni_lights[i]; - let light_contrib = omni_light(in.world_position.xyz, light, roughness, NdotV, N, V, R, F0, diffuse_color); + let light = lights.point_lights[i]; + let light_contrib = point_light(in.world_position.xyz, light, roughness, NdotV, N, V, R, F0, diffuse_color); let shadow = fetch_shadow(i, in.world_position); light_accum = light_accum + light_contrib * shadow; } diff --git a/pipelined/bevy_render2/src/view/window.rs b/pipelined/bevy_render2/src/view/window.rs index 67a3ec50a16e1..ddae464da516c 100644 --- a/pipelined/bevy_render2/src/view/window.rs +++ b/pipelined/bevy_render2/src/view/window.rs @@ -118,21 +118,19 @@ pub fn prepare_windows( .or_insert_with(|| render_device.create_swap_chain(surface, &swap_chain_descriptor)); let frame = match swap_chain.get_current_frame() { - Ok(swap_chain_frame) => { - swap_chain_frame - }, + Ok(swap_chain_frame) => swap_chain_frame, Err(wgpu::SwapChainError::Outdated) => { - let new_swap_chain = render_device.create_swap_chain(surface, &swap_chain_descriptor); - let frame = new_swap_chain.get_current_frame().expect("Error recreating swap chain"); - window_surfaces.swap_chains.insert( - window.id, - new_swap_chain - ); + let new_swap_chain = + render_device.create_swap_chain(surface, &swap_chain_descriptor); + let frame = new_swap_chain + .get_current_frame() + .expect("Error recreating swap chain"); + window_surfaces + .swap_chains + .insert(window.id, new_swap_chain); frame - }, - err => { - err.expect("Failed to acquire next swap chain texture!") } + err => err.expect("Failed to acquire next swap chain texture!"), }; window.swap_chain_frame = Some(TextureView::from(frame)); From 9a79b79bb88125f1a24649a732e4cd32fe586e9e Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Thu, 1 Jul 2021 18:05:20 -0700 Subject: [PATCH 8/8] fix clippy --- crates/bevy_app/src/ci_testing.rs | 12 +- crates/bevy_core/src/time/timer.rs | 34 +- crates/bevy_dylib/src/lib.rs | 3 +- crates/bevy_ecs/src/entity/mod.rs | 5 + crates/bevy_ecs/src/system/mod.rs | 8 +- .../src/camera/visible_entities.rs | 10 +- crates/bevy_tasks/src/countdown_event.rs | 5 +- .../bevy_transform/src/hierarchy/hierarchy.rs | 5 +- crates/bevy_window/src/raw_window_handle.rs | 4 +- crates/crevice/crevice-derive/src/lib.rs | 6 +- crates/crevice/src/lib.rs | 2 + examples/2d/sprite.rs | 2 +- examples/tools/bevymark_pipelined.rs | 8 +- pipelined/bevy_pbr2/src/lib.rs | 2 +- pipelined/bevy_pbr2/src/render/light.rs | 10 +- pipelined/bevy_pbr2/src/render/mod.rs | 5 +- pipelined/bevy_render2/src/camera/mod.rs | 2 +- pipelined/bevy_render2/src/color/color.rs | 1234 ---------------- pipelined/bevy_render2/src/color/mod.rs | 1237 ++++++++++++++++- .../bevy_render2/src/core_pipeline/mod.rs | 24 +- pipelined/bevy_render2/src/mesh/mesh/mod.rs | 7 + .../bevy_render2/src/render_graph/context.rs | 18 +- .../bevy_render2/src/render_graph/graph.rs | 15 +- .../src/render_resource/uniform_vec.rs | 10 + pipelined/bevy_render2/src/texture/image.rs | 6 +- pipelined/bevy_sprite2/src/render/mod.rs | 5 +- src/lib.rs | 3 +- 27 files changed, 1347 insertions(+), 1335 deletions(-) delete mode 100644 pipelined/bevy_render2/src/color/color.rs diff --git a/crates/bevy_app/src/ci_testing.rs b/crates/bevy_app/src/ci_testing.rs index 21e22bec04e9a..dc8865a166696 100644 --- a/crates/bevy_app/src/ci_testing.rs +++ b/crates/bevy_app/src/ci_testing.rs @@ -1,7 +1,6 @@ -use serde::Deserialize; - -use crate::{app::AppExit, AppBuilder}; +use crate::app::{App, AppExit}; use bevy_ecs::system::IntoSystem; +use serde::Deserialize; /// Configuration for automated testing on CI #[derive(Deserialize)] @@ -23,16 +22,15 @@ fn ci_testing_exit_after( *current_frame += 1; } -pub(crate) fn setup_app(app_builder: &mut AppBuilder) -> &mut AppBuilder { +pub(crate) fn setup_app(app: &mut App) -> &mut App { let filename = std::env::var("CI_TESTING_CONFIG").unwrap_or_else(|_| "ci_testing_config.ron".to_string()); let config: CiTestingConfig = ron::from_str( &std::fs::read_to_string(filename).expect("error reading CI testing configuration file"), ) .expect("error deserializing CI testing configuration file"); - app_builder - .insert_resource(config) + app.insert_resource(config) .add_system(ci_testing_exit_after.system()); - app_builder + app } diff --git a/crates/bevy_core/src/time/timer.rs b/crates/bevy_core/src/time/timer.rs index 290d73e7c197f..329fcbeb1b94e 100644 --- a/crates/bevy_core/src/time/timer.rs +++ b/crates/bevy_core/src/time/timer.rs @@ -375,10 +375,10 @@ mod tests { t.tick(Duration::from_secs_f32(0.25)); assert_eq!(t.elapsed_secs(), 0.25); assert_eq!(t.duration(), Duration::from_secs_f32(10.0)); - assert_eq!(t.finished(), false); - assert_eq!(t.just_finished(), false); + assert!(!t.finished()); + assert!(!t.just_finished()); assert_eq!(t.times_finished(), 0); - assert_eq!(t.repeating(), false); + assert!(!t.repeating()); assert_eq!(t.percent(), 0.025); assert_eq!(t.percent_left(), 0.975); // Ticking while paused changes nothing @@ -386,26 +386,26 @@ mod tests { t.tick(Duration::from_secs_f32(500.0)); assert_eq!(t.elapsed_secs(), 0.25); assert_eq!(t.duration(), Duration::from_secs_f32(10.0)); - assert_eq!(t.finished(), false); - assert_eq!(t.just_finished(), false); + assert!(!t.finished()); + assert!(!t.just_finished()); assert_eq!(t.times_finished(), 0); - assert_eq!(t.repeating(), false); + assert!(!t.repeating()); assert_eq!(t.percent(), 0.025); assert_eq!(t.percent_left(), 0.975); // Tick past the end and make sure elapsed doesn't go past 0.0 and other things update t.unpause(); t.tick(Duration::from_secs_f32(500.0)); assert_eq!(t.elapsed_secs(), 10.0); - assert_eq!(t.finished(), true); - assert_eq!(t.just_finished(), true); + assert!(t.finished()); + assert!(t.just_finished()); assert_eq!(t.times_finished(), 1); assert_eq!(t.percent(), 1.0); assert_eq!(t.percent_left(), 0.0); // Continuing to tick when finished should only change just_finished t.tick(Duration::from_secs_f32(1.0)); assert_eq!(t.elapsed_secs(), 10.0); - assert_eq!(t.finished(), true); - assert_eq!(t.just_finished(), false); + assert!(t.finished()); + assert!(!t.just_finished()); assert_eq!(t.times_finished(), 0); assert_eq!(t.percent(), 1.0); assert_eq!(t.percent_left(), 0.0); @@ -418,25 +418,25 @@ mod tests { t.tick(Duration::from_secs_f32(0.75)); assert_eq!(t.elapsed_secs(), 0.75); assert_eq!(t.duration(), Duration::from_secs_f32(2.0)); - assert_eq!(t.finished(), false); - assert_eq!(t.just_finished(), false); + assert!(!t.finished()); + assert!(!t.just_finished()); assert_eq!(t.times_finished(), 0); - assert_eq!(t.repeating(), true); + assert!(t.repeating()); assert_eq!(t.percent(), 0.375); assert_eq!(t.percent_left(), 0.625); // Tick past the end and make sure elapsed wraps t.tick(Duration::from_secs_f32(1.5)); assert_eq!(t.elapsed_secs(), 0.25); - assert_eq!(t.finished(), true); - assert_eq!(t.just_finished(), true); + assert!(t.finished()); + assert!(t.just_finished()); assert_eq!(t.times_finished(), 1); assert_eq!(t.percent(), 0.125); assert_eq!(t.percent_left(), 0.875); // Continuing to tick should turn off both finished & just_finished for repeating timers t.tick(Duration::from_secs_f32(1.0)); assert_eq!(t.elapsed_secs(), 1.25); - assert_eq!(t.finished(), false); - assert_eq!(t.just_finished(), false); + assert!(!t.finished()); + assert!(!t.just_finished()); assert_eq!(t.times_finished(), 0); assert_eq!(t.percent(), 0.625); assert_eq!(t.percent_left(), 0.375); diff --git a/crates/bevy_dylib/src/lib.rs b/crates/bevy_dylib/src/lib.rs index 9cea45597b66e..b39929bea6c71 100644 --- a/crates/bevy_dylib/src/lib.rs +++ b/crates/bevy_dylib/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(clippy::single_component_path_imports)] + //! Forces dynamic linking of Bevy. //! //! Dynamically linking Bevy makes the "link" step much faster. This can be achieved by adding @@ -8,5 +10,4 @@ // Force linking of the main bevy crate #[allow(unused_imports)] -#[allow(clippy::single_component_path_imports)] use bevy_internal; diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index 7160ed6acc3c2..7be98eac0e621 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -428,6 +428,11 @@ impl Entities { /// Allocates space for entities previously reserved with `reserve_entity` or /// `reserve_entities`, then initializes each one using the supplied function. + /// + /// # Safety + /// Flush _must_ set the entity location to the correct ArchetypeId for the given Entity + /// each time init is called. This _can_ be ArchetypeId::invalid(), provided the Entity has + /// not been assigned to an Archetype. pub unsafe fn flush(&mut self, mut init: impl FnMut(Entity, &mut EntityLocation)) { let free_cursor = self.free_cursor.get_mut(); let current_free_cursor = *free_cursor; diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index 2dc7716a54b72..c05dfc7f80b3c 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -324,7 +324,7 @@ mod tests { run_system(&mut world, sys.system()); // ensure the system actually ran - assert_eq!(*world.get_resource::().unwrap(), true); + assert!(*world.get_resource::().unwrap()); } #[test] @@ -353,7 +353,7 @@ mod tests { } run_system(&mut world, validate_removed.system()); - assert_eq!(*world.get_resource::().unwrap(), true, "system ran"); + assert!(*world.get_resource::().unwrap(), "system ran"); } #[test] @@ -371,7 +371,7 @@ mod tests { ); // ensure the system actually ran - assert_eq!(*world.get_resource::().unwrap(), true); + assert!(*world.get_resource::().unwrap()); } #[test] fn world_collections_system() { @@ -414,7 +414,7 @@ mod tests { run_system(&mut world, sys.system()); // ensure the system actually ran - assert_eq!(*world.get_resource::().unwrap(), true); + assert!(*world.get_resource::().unwrap()); } #[test] diff --git a/crates/bevy_render/src/camera/visible_entities.rs b/crates/bevy_render/src/camera/visible_entities.rs index 1fd0a9da460bc..46b7f3b31867a 100644 --- a/crates/bevy_render/src/camera/visible_entities.rs +++ b/crates/bevy_render/src/camera/visible_entities.rs @@ -167,14 +167,12 @@ mod rendering_mask_tests { "default masks match each other" ); - assert_eq!( - RenderLayers::layer(0).intersects(&RenderLayers::layer(1)), - false, + assert!( + !RenderLayers::layer(0).intersects(&RenderLayers::layer(1)), "masks with differing layers do not match" ); - assert_eq!( - RenderLayers(0).intersects(&RenderLayers(0)), - false, + assert!( + !RenderLayers(0).intersects(&RenderLayers(0)), "empty masks don't match" ); assert_eq!( diff --git a/crates/bevy_tasks/src/countdown_event.rs b/crates/bevy_tasks/src/countdown_event.rs index 84f5b7213a4c0..9f672fe16ba0b 100644 --- a/crates/bevy_tasks/src/countdown_event.rs +++ b/crates/bevy_tasks/src/countdown_event.rs @@ -125,10 +125,7 @@ mod tests { let listener3 = event.listen(); // Verify that we are still blocked - assert_eq!( - false, - listener2.wait_timeout(instant::Duration::from_millis(10)) - ); + assert!(!listener2.wait_timeout(instant::Duration::from_millis(10))); // Notify all and verify the remaining listener is notified event.notify(std::usize::MAX); diff --git a/crates/bevy_transform/src/hierarchy/hierarchy.rs b/crates/bevy_transform/src/hierarchy/hierarchy.rs index 2bbbd946bd4c3..338a6e12733c2 100644 --- a/crates/bevy_transform/src/hierarchy/hierarchy.rs +++ b/crates/bevy_transform/src/hierarchy/hierarchy.rs @@ -123,9 +123,8 @@ mod tests { { let children = world.get::(grandparent_entity).unwrap(); - assert_eq!( - children.iter().any(|&i| i == parent_entity), - false, + assert!( + !children.iter().any(|&i| i == parent_entity), "grandparent should no longer know about its child which has been removed" ); } diff --git a/crates/bevy_window/src/raw_window_handle.rs b/crates/bevy_window/src/raw_window_handle.rs index 2393975490f9d..76f1411261c80 100644 --- a/crates/bevy_window/src/raw_window_handle.rs +++ b/crates/bevy_window/src/raw_window_handle.rs @@ -15,7 +15,7 @@ impl RawWindowHandleWrapper { /// have constraints on where/how this handle can be used. For example, some platforms don't support doing window /// operations off of the main thread. The caller must ensure the [`RawWindowHandle`] is only used in valid contexts. pub unsafe fn get_handle(&self) -> HasRawWindowHandleWrapper { - HasRawWindowHandleWrapper(self.0.clone()) + HasRawWindowHandleWrapper(self.0) } } @@ -32,6 +32,6 @@ pub struct HasRawWindowHandleWrapper(RawWindowHandle); // SAFE: the caller has validated that this is a valid context to get RawWindowHandle unsafe impl HasRawWindowHandle for HasRawWindowHandleWrapper { fn raw_window_handle(&self) -> RawWindowHandle { - self.0.clone() + self.0 } } diff --git a/crates/crevice/crevice-derive/src/lib.rs b/crates/crevice/crevice-derive/src/lib.rs index ee7bfe1d3434c..a4fbac11ae8e4 100644 --- a/crates/crevice/crevice-derive/src/lib.rs +++ b/crates/crevice/crevice-derive/src/lib.rs @@ -246,11 +246,7 @@ impl EmitOptions { // For testing purposes, we can optionally generate type layout // information using the type-layout crate. - let type_layout_derive = if cfg!(feature = "test_type_layout") { - quote!(#[derive(::type_layout::TypeLayout)]) - } else { - quote!() - }; + let type_layout_derive = quote!(); quote! { #[allow(non_snake_case)] diff --git a/crates/crevice/src/lib.rs b/crates/crevice/src/lib.rs index 89b7d4fddbeed..076f2c7ce4d78 100644 --- a/crates/crevice/src/lib.rs +++ b/crates/crevice/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(clippy::all)] + /*! [![GitHub CI Status](https://github.com/LPGhatguy/crevice/workflows/CI/badge.svg)](https://github.com/LPGhatguy/crevice/actions) [![crevice on crates.io](https://img.shields.io/crates/v/crevice.svg)](https://crates.io/crates/crevice) diff --git a/examples/2d/sprite.rs b/examples/2d/sprite.rs index b71d3b6407f12..1c5e9c8a7c6a5 100644 --- a/examples/2d/sprite.rs +++ b/examples/2d/sprite.rs @@ -9,7 +9,7 @@ fn main() { fn setup( mut commands: Commands, - asset_server: Res, + _asset_server: Res, // mut materials: ResMut>, ) { // let texture_handle = asset_server.load("branding/icon.png"); diff --git a/examples/tools/bevymark_pipelined.rs b/examples/tools/bevymark_pipelined.rs index 4789853fe30e1..b2e80850e381e 100644 --- a/examples/tools/bevymark_pipelined.rs +++ b/examples/tools/bevymark_pipelined.rs @@ -13,7 +13,7 @@ use bevy::{ use rand::Rng; const BIRDS_PER_SECOND: u32 = 10000; -const BASE_COLOR: Color = Color::rgb(5.0, 5.0, 5.0); +const _BASE_COLOR: Color = Color::rgb(5.0, 5.0, 5.0); const GRAVITY: f32 = -9.8 * 100.0; const MAX_VELOCITY: f32 = 750.; const BIRD_SCALE: f32 = 0.15; @@ -66,8 +66,8 @@ struct BirdTexture(Handle); fn setup( mut commands: Commands, - window: Res, - mut counter: ResMut, + _window: Res, + _counter: ResMut, asset_server: Res, ) { // spawn_birds(&mut commands, &window, &mut counter, 10); @@ -129,7 +129,7 @@ fn setup( #[allow(clippy::too_many_arguments)] fn mouse_handler( mut commands: Commands, - asset_server: Res, + _asset_server: Res, time: Res