From 2b2a186fd358b8a976ac35f3480a76f5e2dff8bc Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Fri, 18 Feb 2022 20:07:48 +0000 Subject: [PATCH] StandardMaterial: expose a cull_mode option This makes it possible for materials to configure front or back face culling, or disable culling. Initially I looked at specializing the Mesh which currently controls this state but conceptually it seems more appropriate to control this at the material level, not the mesh level. _Just for reference this also seems to be consistent with Unity where materials/shaders can configure the culling mode between front/back/off - as opposed to configuring any culling state when importing a mesh._ After some archaeology, trying to understand how this might relate to the existing 'double_sided' option, it was determined that double_sided is a more high level lighting option originally from Filament that will cause the normals for back faces to be flipped. For sake of avoiding complexity, but keeping control this currently keeps the options orthogonal, and adds some clarifying documentation for `double_sided`. This won't affect any existing apps since there hasn't been a way to disable backface culling up until now, so the option was essentially redundant. double_sided support could potentially be updated to imply disabling of backface culling. --- crates/bevy_pbr/src/pbr_material.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crates/bevy_pbr/src/pbr_material.rs b/crates/bevy_pbr/src/pbr_material.rs index 6be68dfdd3e64..3384b10a92263 100644 --- a/crates/bevy_pbr/src/pbr_material.rs +++ b/crates/bevy_pbr/src/pbr_material.rs @@ -47,7 +47,15 @@ pub struct StandardMaterial { pub reflectance: f32, pub normal_map_texture: Option>, pub occlusion_texture: Option>, + /// Support two-sided lighting by automatically flipping the normals for "back" faces + /// within the PBR lighting shader. + /// Defaults to false. + /// This does not automatically configure backface culling, which can be done via + /// `cull_mode`. pub double_sided: bool, + /// Whether to cull the "front", "back" or neither side of a mesh + /// defaults to `Face::Back` + pub cull_mode: Option, pub unlit: bool, pub alpha_mode: AlphaMode, } @@ -76,6 +84,7 @@ impl Default for StandardMaterial { occlusion_texture: None, normal_map_texture: None, double_sided: false, + cull_mode: Some(Face::Back), unlit: false, alpha_mode: AlphaMode::Opaque, } @@ -153,6 +162,7 @@ pub struct GpuStandardMaterial { pub flags: StandardMaterialFlags, pub base_color_texture: Option>, pub alpha_mode: AlphaMode, + pub cull_mode: Option } impl RenderAsset for StandardMaterial { @@ -320,6 +330,7 @@ impl RenderAsset for StandardMaterial { has_normal_map, base_color_texture: material.base_color_texture, alpha_mode: material.alpha_mode, + cull_mode: material.cull_mode, }) } } @@ -327,6 +338,7 @@ impl RenderAsset for StandardMaterial { #[derive(Clone, PartialEq, Eq, Hash)] pub struct StandardMaterialKey { normal_map: bool, + cull_mode: Option } impl SpecializedMaterial for StandardMaterial { @@ -335,6 +347,7 @@ impl SpecializedMaterial for StandardMaterial { fn key(render_asset: &::PreparedAsset) -> Self::Key { StandardMaterialKey { normal_map: render_asset.has_normal_map, + cull_mode: render_asset.cull_mode, } } @@ -347,6 +360,7 @@ impl SpecializedMaterial for StandardMaterial { .shader_defs .push(String::from("STANDARDMATERIAL_NORMAL_MAP")); } + descriptor.primitive.cull_mode = key.cull_mode; if let Some(label) = &mut descriptor.label { *label = format!("pbr_{}", *label).into(); }