bevyengine / bevyengine/bevy

2D: Changes to Z-ordering of entities with custom materials (not sprites) not reflected properly in rendering

Open
#24,826 3 comments 1 reaction 0 assignees View on GitHub
A-Rendering C-Bug I-Regression S-Needs-Review
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 16h
Merged PRs (30d)
171

Description

## Bevy version and features

This bug appears on `0.19`, and on `main` (`306aaed`), but does not appear on `0.18.1`.
Using default features.

## Relevant system information

Hardware info:
```ignore
AdapterInfo { name: "AMD Radeon RX 9070 (RADV GFX1201)", vendor: 4098, device: 30032, device_type: DiscreteGpu, driver: "radv", driver_info: "Mesa 26.1.1", backend: Vulkan }
```

## What you did / what went wrong

I originally noticed this bug due to some entities in my game not being rendered in certain situations. While comparing render world and main world, I noticed that the z-ordering values seemed to be off-sync.

To reproduce, I set up two entities with a `ColorMaterial` that uses `AlphaMode2d::Blend`. Using `AlphaMode2d::Opaque` will not run into this bug. I couldn't reproduce this bug using `Sprite` directly, even if I gave it an `color` with an alpha. However, in my game I used neither `ColorMaterial` nor `Sprite` but a custom material, so this bug doesn't seem specific to `ColorMaterial`.

I set the `Transform` of one of the entities below the other, then after some frames, I update it to be above the other. I expect that change to be visible in the world because the moved entity should now be visible above the other. However, nothing changes visually, until I manually mark the `ColorMaterial` of the moved entity as changed (There is probably a cleaner way to trigger the necessary recomputation, but I don't understand the rendering internals well enough).

Here is a minimal-ish reproduction, this example moves the blue square above the green one after 100 frames but nothing happens, then after 300 frames, it marks the `ColorMaterial` of the blue square as changed and the change becomes visible.

```rust
use std::ops::DerefMut;

use bevy::prelude::*;

#[derive(Component)]
struct BlueSquare;

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

fn setup(
mut commands: Commands,
mut meshes: ResMut>,
mut materials: ResMut>,
) {
commands.spawn(Camera2d);

let square_mesh = meshes.add(Rectangle::new(200.0, 200.0));

commands.spawn((
BlueSquare,
Mesh2d(square_mesh.clone()),
MeshMaterial2d(materials.add(Color::srgba(0.0, 0.25, 1.0, 0.9))),
Transform::from_xyz(0.0, 0.0, 0.05),
));

commands.spawn((
Mesh2d(square_mesh),
MeshMaterial2d(materials.add(Color::srgba(0.0, 1.0, 0.0, 0.9))),
Transform::from_xyz(50.0, 0.0, 1.0),
));
}

fn update(
mut frame: Local,
mut materials: ResMut>,
mut blue_transform_query: Query<&mut Transform, With>,
blue_material_query: Query<&MeshMaterial2d, With>,
) {
*frame += 1;
if *frame == 100 {
for mut transform in &mut blue_transform_query {
transform.translation.z = 2.05;
}
println!("Blue square was moved up, but we see no visual change.");
}

if *frame == 300 {
for handle in &blue_material_query {
// Mark as changed, don't actually change anything
let _ = materials.get_mut(handle).unwrap().deref_mut();
println!("Marked blue square material as changed, now we see a change.");
}
}
}
```

## Additional information

While googling I found #24628 - might be related, since its also referring to 0.19 and says that it's related to z-ordering, but I am not sure

Contributor guide

Open the contributing guide

Research direction

Start with the minimal Rust reproduction in the issue and compare its behavior on 0.18.1, 0.19, and main. Trace the rendering path for Transform z-order changes on blended ColorMaterial and custom materials, especially the update that occurs only after the material is marked changed. Done means changing an entity's z position updates its visible ordering without mutating its material.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
computer-graphics, game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.