Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shapes do not respect Z index in 2D #144

Open
tqwewe opened this issue Feb 19, 2022 · 9 comments
Open

Shapes do not respect Z index in 2D #144

tqwewe opened this issue Feb 19, 2022 · 9 comments

Comments

@tqwewe
Copy link

tqwewe commented Feb 19, 2022

Typically with sprites in bevy, you can draw on top of other things by using the Z translation as ordering.

Shapes drawn with this crate don't seem to respect the Z ordering provided in the translation.

@lordbenedikt
Copy link

I have the same issue. I found that Z ordering is arbitrary with these shapes. I ran the same program several times without any changes and the ordering changed.

@wrnrlr
Copy link

wrnrlr commented Aug 18, 2022

In my experience this is not true. With this little system I can always make sure the orange line is drawn over the blue line.

fn setup_paint(mut cmd: Commands) {
  cmd.spawn_bundle(Camera2dBundle::default());
  let options = StrokeOptions::default().with_line_width(LINE_WIDTH);
  let mut path_builder = PathBuilder::new();
  path_builder.move_to(Vec2::ZERO);
  path_builder.line_to(100.0 * Vec2::ONE);
  let line = path_builder.build();
  cmd.spawn_bundle(GeometryBuilder::build_as(&line, DrawMode::Stroke(StrokeMode{color:Color::BLUE, options}), Transform::from_translation(Vec3::new(0.0, 0.0, 1.0))));
  cmd.spawn_bundle(GeometryBuilder::build_as(&line, DrawMode::Stroke(StrokeMode{color:Color::ORANGE, options}), Transform::from_translation(Vec3::new(0.0, 0.0, 4.0))));
}

Also from reading the code in src/rendering/mod.rs it states that it does:

  transparent_phase.add(Transparent2d {
      entity: *visible_entity,
      draw_function: draw_shape,
      pipeline: pipeline_id,
      // The 2d render items are sorted according to their z value before rendering,
      // in order to get correct transparency
      sort_key: FloatOrd(mesh_z),
      // This material is not batched
      batch_range: None,
  });

and the vertex shader just uses the z position of the clip_position.

I was confused myself about this because I was trying negative values for z which don't show at all. I think this is confusion between how z buffer and depth buffer work.

Please feel free to create an example if you see other behaviour.

@andrewexton373
Copy link

I've also got this same problem. In the game I'm working on I've got 2 entities, one for the player and another for the base station (spawn point essentially). The ordering of these being drawn is non deterministic and the z-index seems to be disregarded. My repository https://github.com/andrewexton373/geometry-wars is an example of this problem occurring, and the gif in the README shows the non deterministic ordering results when the player is over the base.

let base_station = commands.spawn()
            .insert_bundle(lyon::GeometryBuilder::build_as(
                &base_shape,
                lyon::DrawMode::Outlined {
                    fill_mode: lyon::FillMode::color(Color::MIDNIGHT_BLUE),
                    outline_mode: lyon::StrokeMode::new(Color::WHITE, 5.0),
                },
                Transform { translation: Vec3::new(0.0, 0.0, -100.0), ..Default::default() }
            ))

 let player = commands.spawn()
            .insert(Player::new())
            .insert_bundle(lyon::GeometryBuilder::build_as(
                &player_shape,
                lyon::DrawMode::Outlined {
                    fill_mode: lyon::FillMode::color(Color::CYAN),
                    outline_mode: lyon::StrokeMode::new(Color::WHITE, 2.0),
                },
                Transform {
                    translation: Vec3::new(0.0, 0.0, 100.0),
                    ..Default::default()
                }
            ))

@wrnrlr
Copy link

wrnrlr commented Oct 15, 2022

Interesting, I remember playing around with the depth/z value and I found/(remember) that negative values don't work.
Could you try with only positive values.

@andrewexton373
Copy link

Just tried it with 10.0 for the player and 100.0 for the base. Still have the issue with these z values.

@andrewexton373
Copy link

I saw this snippet in the code, so it seems like the z-index should already be taken into account for rendering:

transparent_phase.add(Transparent2d {
                    entity: *visible_entity,
                    draw_function: draw_shape,
                    pipeline: pipeline_id,
                    // The 2d render items are sorted according to their z value before rendering,
                    // in order to get correct transparency
                    sort_key: FloatOrd(mesh_z),
                    // This material is not batched
                    batch_range: None,
                });

I'm not sure if there's a bug here or somewhere related. I'll try and reproduce the issue in a simpler project.

@andrewexton373
Copy link

I wasn't able to reproduce the issue by modifying your dynamic shape example to have 2 overlapping shapes, so now I'm beginning to think it might have something to do with my use of rapier2d in conjunction with this project that's introducing the issue?

@andrewexton373
Copy link

I'm not entirely sure here, but I was able to solve this in a hacky way by making a system to force set the player Transform's Z to be above the shape I was clipping with. I think rapier2d may have been setting the Transform's Z unknowingly and I discovered that with the bevy_inspector_egui. Here's the system I used:

    // FIXME: is this really the only way? I feel like rapier2d is messing with the z-value...
    fn keep_player_on_top(
        mut player_query: Query<(&mut Player, &mut Transform), (With<Player>, Without<Crosshair>)>
    ) {
        for (player, mut transform) in player_query.iter_mut() {
            transform.translation.z = 100.0;
        }
    }

@seivan
Copy link

seivan commented Jun 4, 2024

There's probably some plugin system running that alters the z before rendering. That's why your hack is working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants