Skip to content

Commit

Permalink
StandardMaterial: expose a cull_mode option
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rib committed Feb 18, 2022
1 parent b3a1db6 commit 2b2a186
Showing 1 changed file with 14 additions and 0 deletions.
14 changes: 14 additions & 0 deletions crates/bevy_pbr/src/pbr_material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,15 @@ pub struct StandardMaterial {
pub reflectance: f32,
pub normal_map_texture: Option<Handle<Image>>,
pub occlusion_texture: Option<Handle<Image>>,
/// 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<Face>,
pub unlit: bool,
pub alpha_mode: AlphaMode,
}
Expand Down Expand Up @@ -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,
}
Expand Down Expand Up @@ -153,6 +162,7 @@ pub struct GpuStandardMaterial {
pub flags: StandardMaterialFlags,
pub base_color_texture: Option<Handle<Image>>,
pub alpha_mode: AlphaMode,
pub cull_mode: Option<Face>
}

impl RenderAsset for StandardMaterial {
Expand Down Expand Up @@ -320,13 +330,15 @@ impl RenderAsset for StandardMaterial {
has_normal_map,
base_color_texture: material.base_color_texture,
alpha_mode: material.alpha_mode,
cull_mode: material.cull_mode,
})
}
}

#[derive(Clone, PartialEq, Eq, Hash)]
pub struct StandardMaterialKey {
normal_map: bool,
cull_mode: Option<Face>
}

impl SpecializedMaterial for StandardMaterial {
Expand All @@ -335,6 +347,7 @@ impl SpecializedMaterial for StandardMaterial {
fn key(render_asset: &<Self as RenderAsset>::PreparedAsset) -> Self::Key {
StandardMaterialKey {
normal_map: render_asset.has_normal_map,
cull_mode: render_asset.cull_mode,
}
}

Expand All @@ -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();
}
Expand Down

0 comments on commit 2b2a186

Please sign in to comment.