From a47b91ccccd6af2802cab03c8e8c55196c2c5137 Mon Sep 17 00:00:00 2001 From: Gagnus <20407779+gagnus@users.noreply.github.com> Date: Tue, 2 Jul 2024 19:02:05 +0100 Subject: [PATCH] Added feature switch to default Standard Material's new anisotropy texture to off (#14048) # Objective - Standard Material is starting to run out of samplers (currently uses 13 with no additional features off, I think in 0.13 it was 12). - This change adds a new feature switch, modelled on the other ones which add features to Standard Material, to turn off the new anisotropy feature by default. ## Solution - feature + texture define ## Testing - Anisotropy example still works fine - Other samples work fine - Standard Material now takes 12 samplers by default on my Mac instead of 13 ## Migration Guide - Add feature pbr_anisotropy_texture if you are using that texture in any standard materials. --------- Co-authored-by: John Payne <20407779+johngpayne@users.noreply.github.com> --- Cargo.toml | 5 +- crates/bevy_gltf/Cargo.toml | 1 + crates/bevy_gltf/src/loader.rs | 8 +++ crates/bevy_internal/Cargo.toml | 6 +++ crates/bevy_pbr/Cargo.toml | 1 + crates/bevy_pbr/src/pbr_material.rs | 51 ++++++++++++-------- crates/bevy_pbr/src/render/mesh.rs | 3 ++ crates/bevy_pbr/src/render/pbr_bindings.wgsl | 2 + crates/bevy_pbr/src/render/pbr_fragment.wgsl | 2 + docs/cargo_features.md | 1 + 10 files changed, 59 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 153b2ab185..8c0b6d82c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -318,6 +318,9 @@ pbr_multi_layer_material_textures = [ "bevy_internal/pbr_multi_layer_material_textures", ] +# Enable support for anisotropy texture in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs +pbr_anisotropy_texture = ["bevy_internal/pbr_anisotropy_texture"] + # Enable some limitations to be able to use WebGL2. Please refer to the [WebGL2 and WebGPU](https://github.com/bevyengine/bevy/tree/latest/examples#webgl2-and-webgpu) section of the examples README for more information on how to run Wasm builds with WebGPU. webgl2 = ["bevy_internal/webgl"] @@ -3239,7 +3242,7 @@ wasm = true name = "anisotropy" path = "examples/3d/anisotropy.rs" doc-scrape-examples = true -required-features = ["jpeg"] +required-features = ["jpeg", "pbr_anisotropy_texture"] [package.metadata.example.anisotropy] name = "Anisotropy" diff --git a/crates/bevy_gltf/Cargo.toml b/crates/bevy_gltf/Cargo.toml index 831543a801..488eae7af9 100644 --- a/crates/bevy_gltf/Cargo.toml +++ b/crates/bevy_gltf/Cargo.toml @@ -12,6 +12,7 @@ keywords = ["bevy"] dds = ["bevy_render/dds"] pbr_transmission_textures = ["bevy_pbr/pbr_transmission_textures"] pbr_multi_layer_material_textures = [] +pbr_anisotropy_texture = [] [dependencies] # bevy diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 07a96746ee..796447fe7b 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -1099,7 +1099,9 @@ fn load_material( clearcoat_normal_texture: clearcoat.clearcoat_normal_texture, anisotropy_strength: anisotropy.anisotropy_strength.unwrap_or_default() as f32, anisotropy_rotation: anisotropy.anisotropy_rotation.unwrap_or_default() as f32, + #[cfg(feature = "pbr_anisotropy_texture")] anisotropy_channel: anisotropy.anisotropy_channel, + #[cfg(feature = "pbr_anisotropy_texture")] anisotropy_texture: anisotropy.anisotropy_texture, ..Default::default() } @@ -1910,11 +1912,14 @@ impl ClearcoatExtension { struct AnisotropyExtension { anisotropy_strength: Option, anisotropy_rotation: Option, + #[cfg(feature = "pbr_anisotropy_texture")] anisotropy_channel: UvChannel, + #[cfg(feature = "pbr_anisotropy_texture")] anisotropy_texture: Option>, } impl AnisotropyExtension { + #[allow(unused_variables)] fn parse( load_context: &mut LoadContext, document: &Document, @@ -1925,6 +1930,7 @@ impl AnisotropyExtension { .get("KHR_materials_anisotropy")? .as_object()?; + #[cfg(feature = "pbr_anisotropy_texture")] let (anisotropy_channel, anisotropy_texture) = extension .get("anisotropyTexture") .and_then(|value| value::from_value::(value.clone()).ok()) @@ -1939,7 +1945,9 @@ impl AnisotropyExtension { Some(AnisotropyExtension { anisotropy_strength: extension.get("anisotropyStrength").and_then(Value::as_f64), anisotropy_rotation: extension.get("anisotropyRotation").and_then(Value::as_f64), + #[cfg(feature = "pbr_anisotropy_texture")] anisotropy_channel: anisotropy_channel.unwrap_or_default(), + #[cfg(feature = "pbr_anisotropy_texture")] anisotropy_texture, }) } diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 1dd13530f9..c25e44c101 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -111,6 +111,12 @@ pbr_multi_layer_material_textures = [ "bevy_gltf?/pbr_multi_layer_material_textures", ] +# Anisotropy texture in `StandardMaterial`: +pbr_anisotropy_texture = [ + "bevy_pbr?/pbr_anisotropy_texture", + "bevy_gltf?/pbr_anisotropy_texture", +] + # Optimise for WebGL2 webgl = [ "bevy_core_pipeline?/webgl", diff --git a/crates/bevy_pbr/Cargo.toml b/crates/bevy_pbr/Cargo.toml index 86a2f32d43..68636a925a 100644 --- a/crates/bevy_pbr/Cargo.toml +++ b/crates/bevy_pbr/Cargo.toml @@ -13,6 +13,7 @@ webgl = [] webgpu = [] pbr_transmission_textures = [] pbr_multi_layer_material_textures = [] +pbr_anisotropy_texture = [] shader_format_glsl = ["bevy_render/shader_format_glsl"] trace = ["bevy_render/trace"] ios_simulator = ["bevy_render/ios_simulator"] diff --git a/crates/bevy_pbr/src/pbr_material.rs b/crates/bevy_pbr/src/pbr_material.rs index cac90eb7dd..d6277ae001 100644 --- a/crates/bevy_pbr/src/pbr_material.rs +++ b/crates/bevy_pbr/src/pbr_material.rs @@ -215,8 +215,8 @@ pub struct StandardMaterial { /// /// **Important:** The [`StandardMaterial::diffuse_transmission`] property must be set to a value higher than 0.0, /// or this texture won't have any effect. - #[texture(19)] - #[sampler(20)] + #[cfg_attr(feature = "pbr_transmission_textures", texture(19))] + #[cfg_attr(feature = "pbr_transmission_textures", sampler(20))] #[cfg(feature = "pbr_transmission_textures")] pub diffuse_transmission_texture: Option>, @@ -256,8 +256,8 @@ pub struct StandardMaterial { /// /// **Important:** The [`StandardMaterial::specular_transmission`] property must be set to a value higher than 0.0, /// or this texture won't have any effect. - #[texture(15)] - #[sampler(16)] + #[cfg_attr(feature = "pbr_transmission_textures", texture(15))] + #[cfg_attr(feature = "pbr_transmission_textures", sampler(16))] #[cfg(feature = "pbr_transmission_textures")] pub specular_transmission_texture: Option>, @@ -285,8 +285,8 @@ pub struct StandardMaterial { /// /// **Important:** The [`StandardMaterial::thickness`] property must be set to a value higher than 0.0, /// or this texture won't have any effect. - #[texture(17)] - #[sampler(18)] + #[cfg_attr(feature = "pbr_transmission_textures", texture(17))] + #[cfg_attr(feature = "pbr_transmission_textures", sampler(18))] #[cfg(feature = "pbr_transmission_textures")] pub thickness_texture: Option>, @@ -420,8 +420,8 @@ pub struct StandardMaterial { /// main [`StandardMaterial::clearcoat`] factor. /// /// As this is a non-color map, it must not be loaded as sRGB. - #[texture(21)] - #[sampler(22)] + #[cfg_attr(feature = "pbr_multi_layer_material_textures", texture(21))] + #[cfg_attr(feature = "pbr_multi_layer_material_textures", sampler(22))] #[cfg(feature = "pbr_multi_layer_material_textures")] pub clearcoat_texture: Option>, @@ -445,8 +445,8 @@ pub struct StandardMaterial { /// [`StandardMaterial::clearcoat_perceptual_roughness`] factor. /// /// As this is a non-color map, it must not be loaded as sRGB. - #[texture(23)] - #[sampler(24)] + #[cfg_attr(feature = "pbr_multi_layer_material_textures", texture(23))] + #[cfg_attr(feature = "pbr_multi_layer_material_textures", sampler(24))] #[cfg(feature = "pbr_multi_layer_material_textures")] pub clearcoat_roughness_texture: Option>, @@ -467,8 +467,8 @@ pub struct StandardMaterial { /// in both [`StandardMaterial::normal_map_texture`] and this field. /// /// As this is a non-color map, it must not be loaded as sRGB. - #[texture(25)] - #[sampler(26)] + #[cfg_attr(feature = "pbr_multi_layer_material_textures", texture(25))] + #[cfg_attr(feature = "pbr_multi_layer_material_textures", sampler(26))] #[cfg(feature = "pbr_multi_layer_material_textures")] pub clearcoat_normal_texture: Option>, @@ -513,6 +513,7 @@ pub struct StandardMaterial { /// The UV channel to use for the [`StandardMaterial::anisotropy_texture`]. /// /// Defaults to [`UvChannel::Uv0`]. + #[cfg(feature = "pbr_anisotropy_texture")] pub anisotropy_channel: UvChannel, /// An image texture that allows the @@ -536,8 +537,9 @@ pub struct StandardMaterial { /// /// [`KHR_materials_anisotropy` specification]: /// https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_anisotropy/README.md - #[texture(13)] - #[sampler(14)] + #[cfg_attr(feature = "pbr_anisotropy_texture", texture(13))] + #[cfg_attr(feature = "pbr_anisotropy_texture", sampler(14))] + #[cfg(feature = "pbr_anisotropy_texture")] pub anisotropy_texture: Option>, /// Support two-sided lighting by automatically flipping the normals for "back" faces @@ -814,7 +816,9 @@ impl Default for StandardMaterial { 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, flip_normal_map_y: false, double_sided: false, @@ -999,8 +1003,11 @@ impl AsBindGroupShaderType for StandardMaterial { } } - if self.anisotropy_texture.is_some() { - flags |= StandardMaterialFlags::ANISOTROPY_TEXTURE; + #[cfg(feature = "pbr_anisotropy_texture")] + { + if self.anisotropy_texture.is_some() { + flags |= StandardMaterialFlags::ANISOTROPY_TEXTURE; + } } #[cfg(feature = "pbr_multi_layer_material_textures")] @@ -1207,10 +1214,14 @@ impl From<&StandardMaterial> for StandardMaterialKey { StandardMaterialKey::NORMAL_MAP_UV, material.normal_map_channel != UvChannel::Uv0, ); - key.set( - StandardMaterialKey::ANISOTROPY_UV, - material.anisotropy_channel != UvChannel::Uv0, - ); + + #[cfg(feature = "pbr_anisotropy_texture")] + { + key.set( + StandardMaterialKey::ANISOTROPY_UV, + material.anisotropy_channel != UvChannel::Uv0, + ); + } #[cfg(feature = "pbr_multi_layer_material_textures")] { diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 76ddbdb653..949e747e1b 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -1642,6 +1642,9 @@ impl SpecializedMeshPipeline for MeshPipeline { if cfg!(feature = "pbr_multi_layer_material_textures") { shader_defs.push("PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED".into()); } + if cfg!(feature = "pbr_anisotropy_texture") { + shader_defs.push("PBR_ANISOTROPY_TEXTURE_SUPPORTED".into()); + } let mut bind_group_layout = vec![self.get_view_layout(key.into()).clone()]; diff --git a/crates/bevy_pbr/src/render/pbr_bindings.wgsl b/crates/bevy_pbr/src/render/pbr_bindings.wgsl index f4a02f512b..731fba343f 100644 --- a/crates/bevy_pbr/src/render/pbr_bindings.wgsl +++ b/crates/bevy_pbr/src/render/pbr_bindings.wgsl @@ -15,8 +15,10 @@ @group(2) @binding(10) var normal_map_sampler: sampler; @group(2) @binding(11) var depth_map_texture: texture_2d; @group(2) @binding(12) var depth_map_sampler: sampler; +#ifdef PBR_ANISOTROPY_TEXTURE_SUPPORTED @group(2) @binding(13) var anisotropy_texture: texture_2d; @group(2) @binding(14) var anisotropy_sampler: sampler; +#endif #ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED @group(2) @binding(15) var specular_transmission_texture: texture_2d; @group(2) @binding(16) var specular_transmission_sampler: sampler; diff --git a/crates/bevy_pbr/src/render/pbr_fragment.wgsl b/crates/bevy_pbr/src/render/pbr_fragment.wgsl index 2f5f4e7429..2c4989a6ad 100644 --- a/crates/bevy_pbr/src/render/pbr_fragment.wgsl +++ b/crates/bevy_pbr/src/render/pbr_fragment.wgsl @@ -420,6 +420,7 @@ fn pbr_input_from_standard_material( // // This code comes from the `KHR_materials_anisotropy` spec: // +#ifdef PBR_ANISOTROPY_TEXTURE_SUPPORTED #ifdef VERTEX_TANGENTS #ifdef STANDARD_MATERIAL_ANISOTROPY @@ -456,6 +457,7 @@ fn pbr_input_from_standard_material( #endif // STANDARD_MATERIAL_ANISOTROPY #endif // VERTEX_TANGENTS +#endif // PBR_ANISOTROPY_TEXTURE_SUPPORTED #endif // LOAD_PREPASS_NORMALS diff --git a/docs/cargo_features.md b/docs/cargo_features.md index 7778f0d18b..4d903516f7 100644 --- a/docs/cargo_features.md +++ b/docs/cargo_features.md @@ -71,6 +71,7 @@ The default feature set enables most of the expected features of a game engine, |meshlet_processor|Enables processing meshes into meshlet meshes for bevy_pbr| |minimp3|MP3 audio format support (through minimp3)| |mp3|MP3 audio format support| +|pbr_anisotropy_texture|Enable support for anisotropy texture in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| |pbr_multi_layer_material_textures|Enable support for multi-layer material textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| |pbr_transmission_textures|Enable support for transmission-related textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| |pnm|PNM image format support, includes pam, pbm, pgm and ppm|