Skip to content

DepthPrepass doesn't respect changing alpha_mode from Opaque to Blend. #19150

Closed
@eero-lehtinen

Description

@eero-lehtinen

Bevy version

main 95470df

SystemInfo { os: "Windows 11 Pro", kernel: "26100", cpu: "AMD Ryzen 9 9950X 16-Core Processor", core_count: "16", memory: "31.2 GiB" }

AdapterInfo { name: "NVIDIA GeForce RTX 3070 Ti", vendor: 4318, device: 9346, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "576.28", backend: Vulkan }

What you did

I added a depth prepass to the camera and changed the alpha mode of an entity with StandardMaterial from Opaque to Blend in the 3d_scene example.

Example:

use bevy::{core_pipeline::prepass::DepthPrepass, prelude::*};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .insert_resource(ClearColor(Color::BLACK))
        .add_systems(Startup, setup)
        .add_systems(Update, update)
        .run();
}

#[derive(Component)]
struct Shape;

/// set up a simple 3D scene
fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    // circular base
    commands.spawn((
        Mesh3d(meshes.add(Circle::new(4.0))),
        MeshMaterial3d(materials.add(Color::WHITE)),
        Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
    ));
    // cube
    commands.spawn((
        Shape,
        Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
        MeshMaterial3d(materials.add(Color::srgba_u8(124, 144, 255, 50))),
        Transform::from_xyz(0.0, 0.5, 0.0),
    ));
    // light
    commands.spawn((
        PointLight {
            shadows_enabled: true,
            ..default()
        },
        Transform::from_xyz(4.0, 8.0, 4.0),
    ));
    // camera
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
        DepthPrepass,
    ));
}

fn update(
    keyboard_input: Res<ButtonInput<KeyCode>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
    mut mat_q: Query<&mut MeshMaterial3d<StandardMaterial>, With<Shape>>,
) {
    if keyboard_input.just_pressed(KeyCode::Space) {
        if let Ok(mat) = mat_q.single_mut() {
            let m = materials.get_mut(&mat.0).unwrap();
            m.alpha_mode = if m.alpha_mode == AlphaMode::Opaque {
                AlphaMode::Blend
            } else {
                AlphaMode::Opaque
            };
        };
    }
}

What went wrong

At first the alpha mode is blend, and looks transparent as it should.

Image

Then pressing space makes it opaque, it looks opaque as it should.

Image

Then once more pressing space the material goes back to blend, but you can see through the white circle, which is wrong. I assume the reason is that DepthPrepass doesn't "realize" that the object is not opaque anymore and doesn't bother to draw anything behind it. Might be a retained rendering issue.

Image

Additional information

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-RenderingDrawing game state to the screenC-BugAn unexpected or incorrect behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions