#Backface Culling Problem

9 messages · Page 1 of 1 (latest)

waxen geyser
#

I want to load a character into my game, which has an outline (anime style) already included in the GLB file. However, when I load it, my character appears black (see image).

The model’s mapper told me that I need to enable backface culling, but I can't find how to do that in Bevy. When I enable it in Blender (see image), the outline is displayed correctly.

  commands.spawn(SceneRoot(asset_server.load(GltfAssetLabel::Scene(0).from_asset("entities/player/player_idle.glb"))))
        .insert(Name::new("WorldPlayer"))
        .insert(NoFrustumCulling)
        .insert(AnimatedPlayer)
        .insert(Transform::from_xyz(40.0, 0.249, 40.0))
        .insert(ThirdPersonCameraTarget)
        .insert(WorldPlayer::default())
        .insert(LivingEntity)
        .insert(RigidBody::Dynamic)
        .insert(Velocity::default())
        .insert(GravityScale(2.5))
        .insert(Damping {
            angular_damping: 2.0,
            linear_damping: 2.0
        })
        .insert(LockedAxes::ROTATION_LOCKED_X | LockedAxes::ROTATION_LOCKED_Z)
        .insert(Collider::capsule(Vec3::new(0.0, 0.2, 0.0), Vec3::new(0.0, 1.6, 0.0), 0.2))
        .insert(KinematicCharacterController {
            max_slope_climb_angle: 45_f32.to_radians(),
            min_slope_slide_angle: 35_f32.to_radians(),
            autostep: Some(CharacterAutostep {
                include_dynamic_bodies: true,
                min_width: CharacterLength::Absolute(0.05),
                max_height: CharacterLength::Absolute(0.55)
            }),
            snap_to_ground: Some(CharacterLength::Absolute(0.075)),
            ..default()
        });

Can someone help me with this?
Thanks in advance! 😃

dark jackal
#

standard material component has a field called cull_mode, maybe you can try it

waxen geyser
#

Is there a way to use SceneRoot's? One Character can have many meshes, its this a problem for the performance?

high trail
#

in principle you should not need to customize anything because glTF already has a field to control culling:
https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_material_doublesided
But it's possible that the GLB file does not properly set this field to false (in which case the best solution would be to fix the file instead of working around it in code) or that Bevy isn't making use of the field (in which case the best solution would be to make Bevy do so)

odd swan
#

this is unrelated to the problem but, using insert to insert components is slow-ish, it is best to decrease the number of calls to it as much as possible, and you can do it by using tuples

#

it is slow because each call to it causes an archtype change, and the data needs to be moved to different storage

dark jackal
dark jackal
# waxen geyser Is there a way to use SceneRoot's? One Character can have many meshes, its this ...

If you really want to try it, I will share the meshlet code I studied last time for your reference. ```rust
fn build_meshlet(
trigger: Trigger<SceneInstanceReady>,
mut commands: Commands,
scenes: Res<Assets<Scene>>,
mut meshes: ResMut<Assets<Mesh>>,
asset_server: Res<AssetServer>,
scene_query: Query<&SceneRoot, With<Model>>,
) {
println!("scene ready");
if let Ok(root) = scene_query.get(trigger.target()) {
if let Some(scene) = scenes.get(root.id()) {
println!("found id");
for entity in scene.world.iter_entities() {
println!("entity : {:?}",entity.get::<Name>().unwrap_or(&Name::new("noname")));
if let Some(mesh_handle) = entity.get::<Mesh3d>() {
if let Some(mesh) = meshes.get_mut(mesh_handle.id()) {
mesh.compute_normals();
match mesh.generate_tangents() {
Ok(()) => {
println!("mesh generate_tangents OK");
}
Err(e) => {
println!("mesh generate_tangents : {e}");
}
}
println!("try to update mesh");
match MeshletMesh::from_mesh(mesh, 4) {
Ok(meshlet_mesh) => {
println!("update mesh to meshlet !");
let meshlet_handle = asset_server.add(meshlet_mesh);
commands
.entity(entity.id())
.insert(MeshletMesh3d(meshlet_handle));
commands.entity(entity.id()).remove::<Mesh3d>();
}
Err(e) => {
println!("convert meshlet error: {e}");
}
}
}
}
}
}
}
}