From 922b1c9fd162f69a23a477c5d7d0e3238473f272 Mon Sep 17 00:00:00 2001 From: Arkitu <85173315+Arkitu@users.noreply.github.com> Date: Sun, 20 Jul 2025 10:14:32 +0200 Subject: [PATCH] add interpolation setting to pbr based on 0.16.1 release --- crates/bevy_pbr/src/interpolation.rs | 9 +++++ crates/bevy_pbr/src/lib.rs | 2 + crates/bevy_pbr/src/pbr_material.rs | 44 +++++++++++++++++++--- crates/bevy_pbr/src/render/forward_io.wgsl | 8 ++++ 4 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 crates/bevy_pbr/src/interpolation.rs diff --git a/crates/bevy_pbr/src/interpolation.rs b/crates/bevy_pbr/src/interpolation.rs new file mode 100644 index 0000000000..21cb3d4342 --- /dev/null +++ b/crates/bevy_pbr/src/interpolation.rs @@ -0,0 +1,9 @@ +use bevy_reflect::{std_traits::ReflectDefault, Reflect}; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Default, Reflect)] +#[reflect(Default, Clone, PartialEq)] +pub enum InterpolationMethod { + #[default] + Linear, + Flat, +} diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 1810bc67eb..fed1be7437 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -31,6 +31,7 @@ pub mod decal; pub mod deferred; mod extended_material; mod fog; +mod interpolation; mod light; mod light_probe; mod lightmap; @@ -53,6 +54,7 @@ pub use components::*; pub use decal::clustered::ClusteredDecalPlugin; pub use extended_material::*; pub use fog::*; +pub use interpolation::*; pub use light::*; pub use light_probe::*; pub use lightmap::*; diff --git a/crates/bevy_pbr/src/pbr_material.rs b/crates/bevy_pbr/src/pbr_material.rs index fd1babd8ec..c3867c9890 100644 --- a/crates/bevy_pbr/src/pbr_material.rs +++ b/crates/bevy_pbr/src/pbr_material.rs @@ -386,6 +386,23 @@ pub struct StandardMaterial { /// /// [`Mesh::generate_tangents`]: bevy_render::mesh::Mesh::generate_tangents /// [`Mesh::with_generated_tangents`]: bevy_render::mesh::Mesh::with_generated_tangents + /// + /// # Usage + /// + /// ``` + /// # use bevy_asset::{AssetServer, Handle}; + /// # use bevy_ecs::change_detection::Res; + /// # use bevy_image::{Image, ImageLoaderSettings}; + /// # + /// fn load_normal_map(asset_server: Res) { + /// let normal_handle: Handle = asset_server.load_with_settings( + /// "textures/parallax_example/cube_normal.png", + /// // The normal map texture is in linear color space. Lighting won't look correct + /// // if `is_srgb` is `true`, which is the default. + /// |settings: &mut ImageLoaderSettings| settings.is_srgb = false, + /// ); + /// } + /// ``` #[texture(9)] #[sampler(10)] #[dependency] @@ -752,6 +769,8 @@ pub struct StandardMaterial { /// The transform applied to the UVs corresponding to `ATTRIBUTE_UV_0` on the mesh before sampling. Default is identity. pub uv_transform: Affine2, + + pub interpolation_method: InterpolationMethod, } impl StandardMaterial { @@ -907,6 +926,7 @@ impl Default for StandardMaterial { opaque_render_method: OpaqueRendererMethod::Auto, deferred_lighting_pass_id: DEFAULT_PBR_DEFERRED_LIGHTING_PASS_ID, uv_transform: Affine2::IDENTITY, + interpolation_method: InterpolationMethod::Linear, } } } @@ -1185,7 +1205,8 @@ impl AsBindGroupShaderType for StandardMaterial { bitflags! { /// The pipeline key for `StandardMaterial`, packed into 64 bits. - #[derive(Clone, Copy, PartialEq, Eq, Hash)] + #[repr(C)] + #[derive(Clone, Copy, PartialEq, Eq, Hash, bytemuck::Pod, bytemuck::Zeroable)] pub struct StandardMaterialKey: u64 { const CULL_FRONT = 0x000001; const CULL_BACK = 0x000002; @@ -1210,6 +1231,7 @@ bitflags! { const CLEARCOAT_NORMAL_UV = 0x100000; const SPECULAR_UV = 0x200000; const SPECULAR_TINT_UV = 0x400000; + const FLAT_INTERPOLATION = 0x800000; const DEPTH_BIAS = 0xffffffff_00000000; } } @@ -1334,18 +1356,24 @@ impl From<&StandardMaterial> for StandardMaterialKey { ); } + key.set( + StandardMaterialKey::FLAT_INTERPOLATION, + material.interpolation_method == InterpolationMethod::Flat, + ); + key.insert(StandardMaterialKey::from_bits_retain( // Casting to i32 first to ensure the full i32 range is preserved. // (wgpu expects the depth_bias as an i32 when this is extracted in a later step) (material.depth_bias as i32 as u64) << STANDARD_MATERIAL_KEY_DEPTH_BIAS_SHIFT, )); + key } } impl Material for StandardMaterial { fn fragment_shader() -> ShaderRef { - PBR_SHADER_HANDLE.into() + shader_ref(bevy_asset::embedded_path!("render/pbr.wgsl")) } #[inline] @@ -1381,11 +1409,11 @@ impl Material for StandardMaterial { } fn prepass_fragment_shader() -> ShaderRef { - PBR_PREPASS_SHADER_HANDLE.into() + shader_ref(bevy_asset::embedded_path!("render/pbr_prepass.wgsl")) } fn deferred_fragment_shader() -> ShaderRef { - PBR_SHADER_HANDLE.into() + shader_ref(bevy_asset::embedded_path!("render/pbr.wgsl")) } #[cfg(feature = "meshlet")] @@ -1404,7 +1432,7 @@ impl Material for StandardMaterial { } fn specialize( - _pipeline: &MaterialPipeline, + _pipeline: &MaterialPipeline, descriptor: &mut RenderPipelineDescriptor, _layout: &MeshVertexBufferLayoutRef, key: MaterialPipelineKey, @@ -1499,9 +1527,14 @@ impl Material for StandardMaterial { StandardMaterialKey::SPECULAR_TINT_UV, "STANDARD_MATERIAL_SPECULAR_TINT_UV_B", ), + ( + StandardMaterialKey::FLAT_INTERPOLATION, + "STANDARD_MATERIAL_FLAT_INTERPOLATION", + ), ] { if key.bind_group_data.intersects(flags) { shader_defs.push(shader_def.into()); + descriptor.vertex.shader_defs.push(shader_def.into()); } } } @@ -1524,6 +1557,7 @@ impl Material for StandardMaterial { depth_stencil.bias.constant = (key.bind_group_data.bits() >> STANDARD_MATERIAL_KEY_DEPTH_BIAS_SHIFT) as i32; } + Ok(()) } } diff --git a/crates/bevy_pbr/src/render/forward_io.wgsl b/crates/bevy_pbr/src/render/forward_io.wgsl index 99f2ecced7..044d5d8b7e 100644 --- a/crates/bevy_pbr/src/render/forward_io.wgsl +++ b/crates/bevy_pbr/src/render/forward_io.wgsl @@ -34,7 +34,11 @@ struct VertexOutput { // and `frag coord` when used as a fragment stage input @builtin(position) position: vec4, @location(0) world_position: vec4, +#ifdef STANDARD_MATERIAL_FLAT_INTERPOLATION + @location(1) @interpolate(flat) world_normal: vec3, +#else @location(1) world_normal: vec3, +#endif #ifdef VERTEX_UVS_A @location(2) uv: vec2, #endif @@ -45,8 +49,12 @@ struct VertexOutput { @location(4) world_tangent: vec4, #endif #ifdef VERTEX_COLORS +#ifdef STANDARD_MATERIAL_FLAT_INTERPOLATION + @location(5) @interpolate(flat) color: vec4, +#else @location(5) color: vec4, #endif +#endif #ifdef VERTEX_OUTPUT_INSTANCE_INDEX @location(6) @interpolate(flat) instance_index: u32, #endif