diff --git a/crates/bevy_gltf/Cargo.toml b/crates/bevy_gltf/Cargo.toml index 8df8933fa7d23..f54e01d3d4fe6 100644 --- a/crates/bevy_gltf/Cargo.toml +++ b/crates/bevy_gltf/Cargo.toml @@ -9,12 +9,12 @@ license = "MIT OR Apache-2.0" keywords = ["bevy"] [features] -pbr_transmission_textures = ["bevy_pbr/pbr_transmission_textures"] +pbr_transmission_textures = ["bevy_material/pbr_transmission_textures"] pbr_multi_layer_material_textures = [ - "bevy_pbr/pbr_multi_layer_material_textures", + "bevy_material/pbr_multi_layer_material_textures", ] -pbr_anisotropy_texture = ["bevy_pbr/pbr_anisotropy_texture"] -pbr_specular_textures = ["bevy_pbr/pbr_specular_textures"] +pbr_anisotropy_texture = ["bevy_material/pbr_anisotropy_texture"] +pbr_specular_textures = ["bevy_material/pbr_specular_textures"] [dependencies] # bevy @@ -29,10 +29,11 @@ bevy_image = { path = "../bevy_image", version = "0.18.0-dev" } bevy_light = { path = "../bevy_light", version = "0.18.0-dev" } bevy_camera = { path = "../bevy_camera", version = "0.18.0-dev" } bevy_math = { path = "../bevy_math", version = "0.18.0-dev" } -bevy_mesh = { path = "../bevy_mesh", version = "0.18.0-dev" } -bevy_pbr = { path = "../bevy_pbr", version = "0.18.0-dev" } +bevy_mesh = { path = "../bevy_mesh", version = "0.18.0-dev", features = [ + "morph", + "bevy_mikktspace", +] } bevy_reflect = { path = "../bevy_reflect", version = "0.18.0-dev" } -bevy_render = { path = "../bevy_render", version = "0.18.0-dev" } bevy_material = { path = "../bevy_material", version = "0.18.0-dev" } bevy_scene = { path = "../bevy_scene", version = "0.18.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.18.0-dev" } diff --git a/crates/bevy_gltf/src/assets.rs b/crates/bevy_gltf/src/assets.rs index bfc920ebcea1f..1b16d3ddf62d0 100644 --- a/crates/bevy_gltf/src/assets.rs +++ b/crates/bevy_gltf/src/assets.rs @@ -6,8 +6,8 @@ use core::ops::Deref; use bevy_animation::AnimationClip; use bevy_asset::{Asset, Handle}; use bevy_ecs::{component::Component, reflect::ReflectComponent}; +use bevy_material::pbr_material::ShortStandardMaterial; use bevy_mesh::{skinning::SkinnedMeshInverseBindposes, Mesh}; -use bevy_pbr::StandardMaterial; use bevy_platform::collections::HashMap; use bevy_reflect::{prelude::ReflectDefault, Reflect, TypePath}; use bevy_scene::Scene; @@ -26,9 +26,9 @@ pub struct Gltf { /// Named meshes loaded from the glTF file. pub named_meshes: HashMap, Handle>, /// All materials loaded from the glTF file. - pub materials: Vec>, + pub materials: Vec>, /// Named materials loaded from the glTF file. - pub named_materials: HashMap, Handle>, + pub named_materials: HashMap, Handle>, /// All nodes loaded from the glTF file. pub nodes: Vec>, /// Named nodes loaded from the glTF file. @@ -158,7 +158,7 @@ impl GltfNode { } } -/// Part of a [`GltfMesh`] that consists of a [`Mesh`], an optional [`StandardMaterial`] and [`GltfExtras`]. +/// Part of a [`GltfMesh`] that consists of a [`Mesh`], an optional [`ShortStandardMaterial`] and [`GltfExtras`]. /// /// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-mesh-primitive). #[derive(Asset, Debug, Clone, TypePath)] @@ -172,7 +172,7 @@ pub struct GltfPrimitive { /// Topology to be rendered. pub mesh: Handle, /// Material to apply to the `mesh`. - pub material: Option>, + pub material: Option>, /// Additional data. pub extras: Option, /// Additional data of the `material`. @@ -185,7 +185,7 @@ impl GltfPrimitive { gltf_mesh: &gltf::Mesh, gltf_primitive: &gltf::Primitive, mesh: Handle, - material: Option>, + material: Option>, extras: Option, material_extras: Option, ) -> Self { diff --git a/crates/bevy_gltf/src/label.rs b/crates/bevy_gltf/src/label.rs index b74d5ab2d6631..6e3aca2756e2c 100644 --- a/crates/bevy_gltf/src/label.rs +++ b/crates/bevy_gltf/src/label.rs @@ -54,16 +54,16 @@ pub enum GltfAssetLabel { }, /// `Texture{}`: glTF Texture as a Bevy [`Image`](bevy_image::prelude::Image) Texture(usize), - /// `Material{}`: glTF Material as a Bevy [`StandardMaterial`](bevy_pbr::StandardMaterial) + /// `Material{}`: glTF Material as a Bevy [`ShortStandardMaterial`](bevy_material::ShortStandardMaterial) Material { /// Index of this material index: usize, - /// Used to set the [`Face`](bevy_render::render_resource::Face) of the material, + /// Used to set the [`Face`](bevy_material::render_resource::Face) of the material, /// useful if it is used with negative scale is_scale_inverted: bool, }, /// `DefaultMaterial`: glTF's default Material as a - /// Bevy [`StandardMaterial`](bevy_pbr::StandardMaterial) + /// Bevy [`ShortStandardMaterial`](bevy_material::ShortStandardMaterial) DefaultMaterial, /// `Animation{}`: glTF Animation as Bevy [`AnimationClip`](bevy_animation::AnimationClip) Animation(usize), diff --git a/crates/bevy_gltf/src/loader/extensions/khr_materials_specular.rs b/crates/bevy_gltf/src/loader/extensions/khr_materials_specular.rs index 83743edf90f66..2be78a4364332 100644 --- a/crates/bevy_gltf/src/loader/extensions/khr_materials_specular.rs +++ b/crates/bevy_gltf/src/loader/extensions/khr_materials_specular.rs @@ -21,7 +21,7 @@ use { /// `KHR_materials_specular` specification requirement that stems from the fact /// that glTF is specified in terms of a specular strength model, not the /// reflectance model that Filament and Bevy use. A workaround, which is noted -/// in the [`StandardMaterial`](bevy_pbr::StandardMaterial) documentation, is to set the reflectance value +/// in the [`ShortStandardMaterial`](bevy_material::ShortStandardMaterial) documentation, is to set the reflectance value /// to 2.0, which spreads the specular map range from [0.0, 1.0] as normal. /// /// See the specification: diff --git a/crates/bevy_gltf/src/loader/gltf_ext/material.rs b/crates/bevy_gltf/src/loader/gltf_ext/material.rs index 4616decccf473..360184935da6e 100644 --- a/crates/bevy_gltf/src/loader/gltf_ext/material.rs +++ b/crates/bevy_gltf/src/loader/gltf_ext/material.rs @@ -1,6 +1,6 @@ +use bevy_material::alpha::AlphaMode; use bevy_material::UvChannel; use bevy_math::Affine2; -use bevy_render::alpha::AlphaMode; use gltf::{json::texture::Info, Material}; diff --git a/crates/bevy_gltf/src/loader/mod.rs b/crates/bevy_gltf/src/loader/mod.rs index 12f69cbc349cb..5b53c12dc8905 100644 --- a/crates/bevy_gltf/src/loader/mod.rs +++ b/crates/bevy_gltf/src/loader/mod.rs @@ -26,17 +26,17 @@ use bevy_image::{ ImageType, TextureError, }; use bevy_light::{DirectionalLight, PointLight, SpotLight}; +use bevy_material::pbr_material::{MarkerMeshMaterial3d, ShortStandardMaterial}; #[cfg(feature = "pbr_transmission_textures")] use bevy_material::UvChannel; +use bevy_material::{mesh::skin::MAX_JOINTS, render_resource::Face}; use bevy_math::{Mat4, Vec3}; use bevy_mesh::{ morph::{MeshMorphWeights, MorphAttributes, MorphTargetImage, MorphWeights}, skinning::{SkinnedMesh, SkinnedMeshInverseBindposes}, Indices, Mesh, Mesh3d, MeshVertexAttribute, PrimitiveTopology, }; -use bevy_pbr::{MeshMaterial3d, StandardMaterial, MAX_JOINTS}; use bevy_platform::collections::{HashMap, HashSet}; -use bevy_render::render_resource::Face; use bevy_scene::Scene; #[cfg(not(target_arch = "wasm32"))] use bevy_tasks::IoTaskPool; @@ -1143,13 +1143,13 @@ async fn load_image<'a, 'b>( } } -/// Loads a glTF material as a bevy [`StandardMaterial`] and returns it. +/// Loads a glTF material as a bevy [`ShortStandardMaterial`] and returns it. fn load_material( material: &Material, load_context: &mut LoadContext, document: &Document, is_scale_inverted: bool, -) -> Handle { +) -> Handle { let material_label = material_label(material, is_scale_inverted); load_context .labeled_asset_scope::<_, ()>(material_label.to_string(), |load_context| { @@ -1303,7 +1303,7 @@ fn load_material( let base_emissive = LinearRgba::rgb(emissive[0], emissive[1], emissive[2]); let emissive = base_emissive * material.emissive_strength().unwrap_or(1.0); - Ok(StandardMaterial { + Ok(ShortStandardMaterial { base_color: Color::linear_rgba(color[0], color[1], color[2], color[3]), base_color_channel, base_color_texture, @@ -1534,9 +1534,7 @@ fn load_node( let mut mesh_entity = parent.spawn(( // TODO: handle missing label handle errors here? Mesh3d(load_context.get_label_handle(primitive_label.to_string())), - MeshMaterial3d::( - load_context.get_label_handle(&material_label), - ), + MarkerMeshMaterial3d(load_context.get_label_handle(&material_label)), )); let target_count = primitive.morph_targets().len(); @@ -1915,9 +1913,9 @@ mod test { use bevy_ecs::{resource::Resource, world::World}; use bevy_image::{Image, ImageLoaderSettings}; use bevy_log::LogPlugin; + use bevy_material::ShortStandardMaterial; use bevy_mesh::skinning::SkinnedMeshInverseBindposes; use bevy_mesh::MeshPlugin; - use bevy_pbr::StandardMaterial; use bevy_scene::ScenePlugin; fn test_app(dir: Dir) -> App { @@ -2408,7 +2406,7 @@ mod test { fn reads_images_in_custom_asset_source() { let (mut app, dir) = test_app_custom_asset_source(); - app.init_asset::(); + app.init_asset::(); // Note: We need the material here since otherwise we don't store the texture handle, which // can result in the image getting dropped leading to the gltf never being loaded with diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index cc671e33ccf5e..f76eb9c2636b4 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -263,7 +263,7 @@ bevy_ui_render = ["dep:bevy_ui_render", "bevy_sprite_render", "bevy_ui"] bevy_solari = ["dep:bevy_solari", "bevy_pbr"] bevy_gizmos = ["dep:bevy_gizmos", "bevy_camera"] bevy_gizmos_render = ["dep:bevy_gizmos_render", "bevy_gizmos"] -bevy_gltf = ["dep:bevy_gltf", "bevy_scene", "bevy_pbr"] +bevy_gltf = ["dep:bevy_gltf", "bevy_material", "bevy_scene", "bevy_pbr"] # Used to disable code that is unsupported when Bevy is dynamically linked dynamic_linking = ["bevy_diagnostic/dynamic_linking"] diff --git a/crates/bevy_internal/src/default_plugins.rs b/crates/bevy_internal/src/default_plugins.rs index 75b47cf5c57e7..a22abdd7ecd5e 100644 --- a/crates/bevy_internal/src/default_plugins.rs +++ b/crates/bevy_internal/src/default_plugins.rs @@ -64,6 +64,8 @@ plugin_group! { bevy_ui:::UiPlugin, #[cfg(feature = "bevy_ui_render")] bevy_ui_render:::UiRenderPlugin, + #[cfg(feature = "bevy_material")] + bevy_material::pbr_material:::ShortMaterialPlugin, #[cfg(feature = "bevy_pbr")] bevy_pbr:::PbrPlugin, // NOTE: Load this after renderer initialization so that it knows about the supported diff --git a/crates/bevy_material/Cargo.toml b/crates/bevy_material/Cargo.toml index e8a35b480f4c2..5e0a966144124 100644 --- a/crates/bevy_material/Cargo.toml +++ b/crates/bevy_material/Cargo.toml @@ -8,6 +8,12 @@ repository = "https://github.com/bevyengine/bevy" license = "MIT OR Apache-2.0" keywords = ["bevy"] +[features] +pbr_transmission_textures = [] +pbr_multi_layer_material_textures = [] +pbr_anisotropy_texture = [] +pbr_specular_textures = [] + [dependencies] # bevy bevy_app = { path = "../bevy_app", version = "0.18.0-dev" } diff --git a/crates/bevy_material/src/lib.rs b/crates/bevy_material/src/lib.rs index 1d372eae6a78f..a91ef56b4594d 100644 --- a/crates/bevy_material/src/lib.rs +++ b/crates/bevy_material/src/lib.rs @@ -5,6 +5,7 @@ extern crate alloc; pub mod alpha; pub mod material; +pub mod mesh; pub mod opaque; pub mod pbr_material; pub mod render; @@ -16,7 +17,7 @@ pub mod render_resource; /// This includes the most common types in this crate, re-exported for your convenience. pub mod prelude { #[doc(hidden)] - pub use crate::alpha::AlphaMode; + pub use crate::{alpha::AlphaMode, pbr_material::ShortMaterialPlugin}; } pub use pbr_material::*; diff --git a/crates/bevy_material/src/mesh/mod.rs b/crates/bevy_material/src/mesh/mod.rs new file mode 100644 index 0000000000000..1ac166094a0af --- /dev/null +++ b/crates/bevy_material/src/mesh/mod.rs @@ -0,0 +1 @@ +pub mod skin; diff --git a/crates/bevy_material/src/mesh/skin.rs b/crates/bevy_material/src/mesh/skin.rs new file mode 100644 index 0000000000000..240129490f41f --- /dev/null +++ b/crates/bevy_material/src/mesh/skin.rs @@ -0,0 +1,34 @@ +use core::mem::size_of; + +use bevy_math::Mat4; + +/// Maximum number of joints supported for skinned meshes. +/// +/// It is used to allocate buffers. +/// The correctness of the value depends on the GPU/platform. +/// The current value is chosen because it is guaranteed to work everywhere. +/// To allow for bigger values, a check must be made for the limits +/// of the GPU at runtime, which would mean not using consts anymore. +pub const MAX_JOINTS: usize = 256; + +/// The total number of joints we support. +/// +/// This is 256 GiB worth of joint matrices, which we will never hit under any +/// reasonable circumstances. +pub const MAX_TOTAL_JOINTS: u32 = 1024 * 1024 * 1024; + +/// The number of joints that we allocate at a time. +/// +/// Some hardware requires that uniforms be allocated on 256-byte boundaries, so +/// we need to allocate 4 64-byte matrices at a time to satisfy alignment +/// requirements. +pub const JOINTS_PER_ALLOCATION_UNIT: u32 = (256 / size_of::()) as u32; + +/// The maximum ratio of the number of entities whose transforms changed to the +/// total number of joints before we re-extract all joints. +/// +/// We use this as a heuristic to decide whether it's worth switching over to +/// fine-grained detection to determine which skins need extraction. If the +/// number of changed entities is over this threshold, we skip change detection +/// and simply re-extract the transforms of all joints. +pub const JOINT_EXTRACTION_THRESHOLD_FACTOR: f64 = 0.25; diff --git a/crates/bevy_material/src/pbr_material.rs b/crates/bevy_material/src/pbr_material.rs index fe54b96a40c40..6a6a2ccfc3ea5 100644 --- a/crates/bevy_material/src/pbr_material.rs +++ b/crates/bevy_material/src/pbr_material.rs @@ -1,4 +1,13 @@ -use bevy_reflect::{std_traits::ReflectDefault, Reflect}; +use bevy_app::{App, Plugin}; +use bevy_asset::{Asset, AssetApp, Handle}; +use bevy_color::{Color, LinearRgba}; +use bevy_ecs::{component::Component, reflect::ReflectComponent}; +use bevy_image::Image; +use bevy_math::Affine2; +use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath}; +use wgpu_types::Face; + +use crate::alpha::AlphaMode; /// An enum to define which UV attribute to use for a texture. /// @@ -12,3 +21,149 @@ pub enum UvChannel { Uv0, Uv1, } + +#[derive(Component, Clone, Debug, Reflect)] +#[reflect(Component, Default, Clone, PartialEq)] +pub struct MarkerMeshMaterial3d(pub Handle); + +impl Default for MarkerMeshMaterial3d { + fn default() -> Self { + Self(Handle::default()) + } +} + +impl PartialEq for MarkerMeshMaterial3d { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl Eq for MarkerMeshMaterial3d {} + +// Data to build a bevy_pbr::StandardMaterial +#[derive(Asset, Debug, TypePath)] +pub struct ShortStandardMaterial { + pub base_color: Color, + pub base_color_channel: UvChannel, + pub base_color_texture: Option>, + pub emissive: LinearRgba, + pub emissive_channel: UvChannel, + pub emissive_texture: Option>, + pub perceptual_roughness: f32, + pub metallic: f32, + pub metallic_roughness_channel: UvChannel, + pub metallic_roughness_texture: Option>, + pub reflectance: f32, + pub specular_tint: Color, + pub specular_transmission: f32, + #[cfg(feature = "pbr_transmission_textures")] + pub specular_transmission_channel: UvChannel, + #[cfg(feature = "pbr_transmission_textures")] + pub specular_transmission_texture: Option>, + pub thickness: f32, + #[cfg(feature = "pbr_transmission_textures")] + pub thickness_channel: UvChannel, + #[cfg(feature = "pbr_transmission_textures")] + pub thickness_texture: Option>, + pub ior: f32, + pub attenuation_distance: f32, + pub attenuation_color: Color, + pub normal_map_channel: UvChannel, + pub normal_map_texture: Option>, + pub occlusion_channel: UvChannel, + pub occlusion_texture: Option>, + pub clearcoat: f32, + pub clearcoat_perceptual_roughness: f32, + pub anisotropy_strength: f32, + pub anisotropy_rotation: f32, + pub double_sided: bool, + pub cull_mode: Option, + pub unlit: bool, + pub alpha_mode: AlphaMode, + pub uv_transform: Affine2, +} + +impl Default for ShortStandardMaterial { + fn default() -> Self { + ShortStandardMaterial { + // White because it gets multiplied with texture values if someone uses + // a texture. + base_color: Color::WHITE, + base_color_channel: UvChannel::Uv0, + base_color_texture: None, + emissive: LinearRgba::BLACK, + emissive_channel: UvChannel::Uv0, + emissive_texture: None, + // Matches Blender's default roughness. + perceptual_roughness: 0.5, + // Metallic should generally be set to 0.0 or 1.0. + metallic: 0.0, + metallic_roughness_channel: UvChannel::Uv0, + metallic_roughness_texture: None, + // Minimum real-world reflectance is 2%, most materials between 2-5% + // Expressed in a linear scale and equivalent to 4% reflectance see + // + reflectance: 0.5, + specular_transmission: 0.0, + #[cfg(feature = "pbr_transmission_textures")] + specular_transmission_channel: UvChannel::Uv0, + #[cfg(feature = "pbr_transmission_textures")] + specular_transmission_texture: None, + thickness: 0.0, + #[cfg(feature = "pbr_transmission_textures")] + thickness_channel: UvChannel::Uv0, + #[cfg(feature = "pbr_transmission_textures")] + thickness_texture: None, + ior: 1.5, + attenuation_color: Color::WHITE, + attenuation_distance: f32::INFINITY, + occlusion_channel: UvChannel::Uv0, + occlusion_texture: None, + normal_map_channel: UvChannel::Uv0, + normal_map_texture: None, + #[cfg(feature = "pbr_specular_textures")] + specular_channel: UvChannel::Uv0, + #[cfg(feature = "pbr_specular_textures")] + specular_texture: None, + specular_tint: Color::WHITE, + #[cfg(feature = "pbr_specular_textures")] + specular_tint_channel: UvChannel::Uv0, + #[cfg(feature = "pbr_specular_textures")] + specular_tint_texture: None, + clearcoat: 0.0, + clearcoat_perceptual_roughness: 0.5, + #[cfg(feature = "pbr_multi_layer_material_textures")] + clearcoat_channel: UvChannel::Uv0, + #[cfg(feature = "pbr_multi_layer_material_textures")] + clearcoat_texture: None, + #[cfg(feature = "pbr_multi_layer_material_textures")] + clearcoat_roughness_channel: UvChannel::Uv0, + #[cfg(feature = "pbr_multi_layer_material_textures")] + clearcoat_roughness_texture: None, + #[cfg(feature = "pbr_multi_layer_material_textures")] + clearcoat_normal_channel: UvChannel::Uv0, + #[cfg(feature = "pbr_multi_layer_material_textures")] + clearcoat_normal_texture: None, + anisotropy_strength: 0.0, + anisotropy_rotation: 0.0, + #[cfg(feature = "pbr_anisotropy_texture")] + anisotropy_channel: UvChannel::Uv0, + #[cfg(feature = "pbr_anisotropy_texture")] + anisotropy_texture: None, + double_sided: false, + cull_mode: Some(Face::Back), + unlit: false, + alpha_mode: AlphaMode::Opaque, + uv_transform: Affine2::IDENTITY, + } + } +} + +#[derive(Default)] +pub struct ShortMaterialPlugin; + +impl Plugin for ShortMaterialPlugin { + fn build(&self, app: &mut App) { + app.init_asset::(); + } +} diff --git a/crates/bevy_pbr/Cargo.toml b/crates/bevy_pbr/Cargo.toml index 96dc4897ccb34..b7beb3333d7ca 100644 --- a/crates/bevy_pbr/Cargo.toml +++ b/crates/bevy_pbr/Cargo.toml @@ -11,11 +11,13 @@ keywords = ["bevy"] [features] webgl = ["bevy_light/webgl"] webgpu = ["bevy_light/webgpu"] -pbr_transmission_textures = [] -pbr_multi_layer_material_textures = [] -pbr_anisotropy_texture = [] +pbr_transmission_textures = ["bevy_material/pbr_transmission_textures"] +pbr_multi_layer_material_textures = [ + "bevy_material/pbr_multi_layer_material_textures", +] +pbr_anisotropy_texture = ["bevy_material/pbr_anisotropy_texture"] +pbr_specular_textures = ["bevy_material/pbr_specular_textures"] experimental_pbr_pcss = ["bevy_light/experimental_pbr_pcss"] -pbr_specular_textures = [] pbr_clustered_decals = [] pbr_light_textures = [] bluenoise_texture = ["bevy_image/ktx2", "bevy_image/zstd"] diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index d7513aaa29520..993ebe84a78a1 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -42,6 +42,7 @@ mod parallax; mod pbr_material; mod prepass; mod render; +mod short; mod ssao; mod ssr; mod volumetric_fog; @@ -69,6 +70,7 @@ pub use parallax::*; pub use pbr_material::*; pub use prepass::*; pub use render::*; +pub use short::*; pub use ssao::*; pub use ssr::*; pub use volumetric_fog::VolumetricFogPlugin; @@ -230,6 +232,7 @@ impl Plugin for PbrPlugin { ..Default::default() }, ScreenSpaceAmbientOcclusionPlugin, + ShortPlugin, FogPlugin, ExtractResourcePlugin::::default(), SyncComponentPlugin::::default(), diff --git a/crates/bevy_pbr/src/render/mesh_bindings.rs b/crates/bevy_pbr/src/render/mesh_bindings.rs index 44211ca242f7f..dc2eaf113f1f2 100644 --- a/crates/bevy_pbr/src/render/mesh_bindings.rs +++ b/crates/bevy_pbr/src/render/mesh_bindings.rs @@ -1,5 +1,6 @@ //! Bind group layout related definitions for the mesh pipeline. +use bevy_material::mesh::skin::MAX_JOINTS; pub use bevy_material::render::MeshLayouts; use bevy_math::Mat4; use bevy_mesh::morph::MAX_MORPH_WEIGHTS; @@ -8,7 +9,7 @@ use bevy_render::{ renderer::{RenderAdapter, RenderDevice}, }; -use crate::{binding_arrays_are_usable, render::skin::MAX_JOINTS, LightmapSlab}; +use crate::{binding_arrays_are_usable, LightmapSlab}; const MORPH_WEIGHT_SIZE: usize = size_of::(); diff --git a/crates/bevy_pbr/src/render/mod.rs b/crates/bevy_pbr/src/render/mod.rs index 6a29823022b58..58fc67a90981b 100644 --- a/crates/bevy_pbr/src/render/mod.rs +++ b/crates/bevy_pbr/src/render/mod.rs @@ -14,4 +14,4 @@ pub use mesh::*; pub use mesh_bindings::MeshLayouts; pub use mesh_view_bindings::*; pub use morph::*; -pub use skin::{extract_skins, prepare_skins, skins_use_uniform_buffers, SkinUniforms, MAX_JOINTS}; +pub use skin::{extract_skins, prepare_skins, skins_use_uniform_buffers, SkinUniforms}; diff --git a/crates/bevy_pbr/src/render/skin.rs b/crates/bevy_pbr/src/render/skin.rs index 93e86d3124de7..aee8171a39acb 100644 --- a/crates/bevy_pbr/src/render/skin.rs +++ b/crates/bevy_pbr/src/render/skin.rs @@ -4,6 +4,9 @@ use std::sync::OnceLock; use bevy_asset::{prelude::AssetChanged, Assets}; use bevy_camera::visibility::ViewVisibility; use bevy_ecs::prelude::*; +use bevy_material::mesh::skin::{ + JOINTS_PER_ALLOCATION_UNIT, JOINT_EXTRACTION_THRESHOLD_FACTOR, MAX_JOINTS, MAX_TOTAL_JOINTS, +}; use bevy_math::Mat4; use bevy_mesh::skinning::{SkinnedMesh, SkinnedMeshInverseBindposes}; use bevy_platform::collections::hash_map::Entry; diff --git a/crates/bevy_pbr/src/short.rs b/crates/bevy_pbr/src/short.rs new file mode 100644 index 0000000000000..1b586bbddb297 --- /dev/null +++ b/crates/bevy_pbr/src/short.rs @@ -0,0 +1,86 @@ +use bevy_app::{App, Plugin, PreUpdate}; +use bevy_asset::Assets; +use bevy_ecs::{ + entity::Entity, + system::{Commands, Query, Res, ResMut}, +}; +use bevy_material::pbr_material::{MarkerMeshMaterial3d, ShortStandardMaterial}; + +use crate::{MeshMaterial3d, StandardMaterial}; + +pub struct ShortPlugin; + +impl Plugin for ShortPlugin { + fn build(&self, app: &mut App) { + // TODO: set this schedule to just after the Marker gets added + app.add_systems(PreUpdate, swap_marker_mesh_material_3d); + } +} + +fn material_from_short_material(material: &ShortStandardMaterial) -> StandardMaterial { + StandardMaterial { + base_color: material.base_color, + base_color_channel: material.base_color_channel.clone(), + base_color_texture: material.base_color_texture.clone(), + emissive: material.emissive, + emissive_channel: material.emissive_channel.clone(), + emissive_texture: material.emissive_texture.clone(), + perceptual_roughness: material.perceptual_roughness, + metallic: material.metallic, + metallic_roughness_channel: material.metallic_roughness_channel.clone(), + metallic_roughness_texture: material.metallic_roughness_texture.clone(), + reflectance: material.reflectance, + specular_tint: material.specular_tint, + specular_transmission: material.specular_transmission, + #[cfg(feature = "pbr_transmission_textures")] + specular_transmission_channel: material.specular_transmission_channel.clone(), + #[cfg(feature = "pbr_transmission_textures")] + specular_transmission_texture: material.specular_transmission_texture.clone(), + thickness: material.thickness, + #[cfg(feature = "pbr_transmission_textures")] + thickness_channel: material.thickness_channel.clone(), + #[cfg(feature = "pbr_transmission_textures")] + thickness_texture: material.thickness_texture.clone(), + ior: material.ior, + attenuation_distance: material.attenuation_distance, + attenuation_color: material.attenuation_color, + normal_map_channel: material.normal_map_channel.clone(), + normal_map_texture: material.normal_map_texture.clone(), + occlusion_channel: material.occlusion_channel.clone(), + occlusion_texture: material.occlusion_texture.clone(), + clearcoat: material.clearcoat, + clearcoat_perceptual_roughness: material.clearcoat_perceptual_roughness, + anisotropy_strength: material.anisotropy_strength, + anisotropy_rotation: material.anisotropy_rotation, + double_sided: material.double_sided, + cull_mode: material.cull_mode, + unlit: material.unlit, + alpha_mode: material.alpha_mode, + uv_transform: material.uv_transform, + ..Default::default() + } +} + +fn swap_marker_mesh_material_3d( + mut commands: Commands, + query: Query<(Entity, &MarkerMeshMaterial3d)>, + short_materials: Res>, + mut materials: ResMut>, +) { + for (entity, marker) in &query { + let content = &marker.0; + + let short_material = short_materials.get(content).unwrap(); + + let material = material_from_short_material(short_material); + + let content2 = materials.add(material); + + let mesh_material_3d = MeshMaterial3d::(content2); + + commands + .entity(entity) + .remove::() + .insert(mesh_material_3d); + } +} diff --git a/crates/bevy_render/src/mesh/skin.rs b/crates/bevy_render/src/mesh/skin.rs index e6ca697a78675..9bf2d2dd0ff9e 100644 --- a/crates/bevy_render/src/mesh/skin.rs +++ b/crates/bevy_render/src/mesh/skin.rs @@ -1,43 +1,13 @@ use core::mem::size_of; use bevy_ecs::prelude::*; +use bevy_material::mesh::skin::JOINTS_PER_ALLOCATION_UNIT; use bevy_math::Mat4; use bevy_render::render_resource::Buffer; use bevy_render::sync_world::{MainEntity, MainEntityHashMap}; use offset_allocator::{Allocation, Allocator}; use smallvec::SmallVec; -/// Maximum number of joints supported for skinned meshes. -/// -/// It is used to allocate buffers. -/// The correctness of the value depends on the GPU/platform. -/// The current value is chosen because it is guaranteed to work everywhere. -/// To allow for bigger values, a check must be made for the limits -/// of the GPU at runtime, which would mean not using consts anymore. -pub const MAX_JOINTS: usize = 256; - -/// The total number of joints we support. -/// -/// This is 256 GiB worth of joint matrices, which we will never hit under any -/// reasonable circumstances. -pub const MAX_TOTAL_JOINTS: u32 = 1024 * 1024 * 1024; - -/// The number of joints that we allocate at a time. -/// -/// Some hardware requires that uniforms be allocated on 256-byte boundaries, so -/// we need to allocate 4 64-byte matrices at a time to satisfy alignment -/// requirements. -pub const JOINTS_PER_ALLOCATION_UNIT: u32 = (256 / size_of::()) as u32; - -/// The maximum ratio of the number of entities whose transforms changed to the -/// total number of joints before we re-extract all joints. -/// -/// We use this as a heuristic to decide whether it's worth switching over to -/// fine-grained detection to determine which skins need extraction. If the -/// number of changed entities is over this threshold, we skip change detection -/// and simply re-extract the transforms of all joints. -pub const JOINT_EXTRACTION_THRESHOLD_FACTOR: f64 = 0.25; - /// The location of the first joint matrix in the skin uniform buffer. #[derive(Clone, Copy)] pub struct SkinByteOffset {