bevy icon indicating copy to clipboard operation
bevy copied to clipboard

AlphaMode Blend - Z ordering errors

Open IDEDARY opened this issue 1 year ago • 4 comments

Bevy version

Version 0.12.1 or Bevy main, latest commit: e94297f

`AdapterInfo { name: "NVIDIA GeForce RTX 3060 Laptop GPU", vendor: 4318, device: 9504, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "535.154.05", backend: Vulkan }`

What you did

I used AlphaMode:Blend on Standard Material slapped onto Quad mesh

https://github.com/bevyengine/bevy/assets/49441831/3eacad4a-682a-42f3-90ff-c13b81e9e6d5

What went wrong

The Z-ordering is most likely breaking under different camera angles. Most likely a math error somewhere in the blending pipeline. You can see the semi-transparent texture blinking in certain moments. The text's alpha is 100% and black background is 75%. The issue only happens when AlphaMode is set to Blend

Additional information

The code for replicating this should be simple. I did not do anything to rendering, but I encountered it while developing UI library. The code is currently private and WIP, but I can provide it early if people are interested to fix this issue.

IDEDARY avatar Jan 29 '24 20:01 IDEDARY

This issue is also present in billboard crate for text. It happens whenever 2 or more transparent meshes are on top of each other. Just transparent background and billboard text mesh is enough to break things. image

I thought that stacking transparent images is edge-case, but it turned out that it is also triggered by 3D non-transparent text, which I assume also uses blend mode under the hood.

This just bumped the issues severity and I now consider it a blocker for Bevy's future world-space UI.

IDEDARY avatar Feb 01 '24 18:02 IDEDARY

I cannot reproduce it with the 3d/texture example. Could you provide a reproduction project?

floppyhammer avatar Feb 04 '24 05:02 floppyhammer

The Z-ordering is most likely breaking under different camera angles. Most likely a math error somewhere in the blending pipeline.

There is no way to correctly sort transparent objects correctly in all scenarios when drawing them separately. Bevy sorts transparent objects based on their distance to the camera, which is common practice.

From what I can tell this is working correctly in your example, even if the result looks odd. To get the expected behavior, either change the origin of the 3D models used or apply a depth bias in the material to force the desired sorting, see bevy_pbr::StandardMaterial:

https://github.com/bevyengine/bevy/blob/71be08af68e081cab466f3bbe3728c30db3a94f7/crates/bevy_pbr/src/pbr_material.rs#L374-L384

Related: #5656, #2223

CptPotato avatar Feb 04 '24 13:02 CptPotato

I cannot reproduce it with the 3d/texture example. Could you provide a reproduction project?

Of course, here it is https://github.com/IDEDARY/Bevycom/tree/bevy-issue-z-ordering

The Z-ordering is most likely breaking under different camera angles. Most likely a math error somewhere in the blending pipeline.

There is no way to correctly sort transparent objects correctly in all scenarios when drawing them separately. Bevy sorts transparent objects based on their distance to the camera, which is common practice.

From what I can tell this is working correctly in your example, even if the result looks odd. To get the expected behavior, either change the origin of the 3D models used or apply a depth bias in the material to force the desired sorting, see bevy_pbr::StandardMaterial:

https://github.com/bevyengine/bevy/blob/71be08af68e081cab466f3bbe3728c30db3a94f7/crates/bevy_pbr/src/pbr_material.rs#L374-L384

Related: #5656, #2223

Ok, that seems like it might be able to do something. I will try it later

IDEDARY avatar Feb 08 '24 09:02 IDEDARY

It seems the calculated distance is wrong under some camera angles, which results in wrong sorted render order.

Correct case:

translation Vec3(9.0, -182.5, -170.0) distance -1005.19183
translation Vec3(9.0, -182.5, 30.0) distance -840.30206
translation Vec3(9.0, -182.5, 230.0) distance -675.4123
translation Vec3(-2.5, 202.5, -140.0) distance -846.68134
translation Vec3(-2.5, 202.5, 60.0) distance -681.79156
translation Vec3(-2.5, 202.5, 260.0) distance -516.90186

The correct render order is 1->4->2->5->3->6.

Wrong case:

translation Vec3(9.0, -182.5, -170.0) distance -990.4487
translation Vec3(9.0, -182.5, 30.0) distance -846.5717
translation Vec3(9.0, -182.5, 230.0) distance -702.69476
translation Vec3(-2.5, 202.5, -140.0) distance -829.6107
translation Vec3(-2.5, 202.5, 60.0) distance -685.73376
translation Vec3(-2.5, 202.5, 260.0) distance -541.8568

Now the order became 1->2->4->3->5->6.

floppyhammer avatar Feb 19 '24 09:02 floppyhammer

This issue is also present in billboard crate for text. It happens whenever 2 or more transparent meshes are on top of each other. Just transparent background and billboard text mesh is enough to break things. image

I thought that stacking transparent images is edge-case, but it turned out that it is also triggered by 3D non-transparent text, which I assume also uses blend mode under the hood.

This just bumped the issues severity and I now consider it a blocker for Bevy's future world-space UI.

@IDEDARY Could you help test the PR in this case?

floppyhammer avatar Feb 20 '24 09:02 floppyhammer

Update: The PR mentioned here was closed as it did not solve the issue completely. I also made reproducible: bare bones reproducible

IDEDARY avatar Mar 14 '24 14:03 IDEDARY

This still exists in 0.13.2:

https://github.com/bevyengine/bevy/assets/52322338/7c7d1030-3189-43b0-826c-9d42f2ab536d

These are basically just PBR bundles of cuboid meshes with standard materials set from colors, but with AlphaMode::Blend set.

@alice-i-cecile do you see any hope for this to get a fix for 0.14? Hoping to avoid waiting for 0.15 for using transparency.

EDIT: I also tried @IDEDARY 's repro above but changed to Bevy main branch just to make sure it isn't already fixed, and I see the bug there as well

torsteingrindvik avatar May 21 '24 11:05 torsteingrindvik

The only way to fix this is order-independent transparency. Plain apps blending by ordering draws by their transform origins in view space only works up to a point. If you have intersecting triangles or situations like in the original video then what bevy currently supports out of the box will not be sufficient.

superdump avatar May 21 '24 14:05 superdump

Agreed on the need for order-independent-transparency. @IceSentry had a really lovely implementation that I'd be happy to see upstreamed by him or someone else. No chance it makes it for 0.14 though.

alice-i-cecile avatar May 21 '24 15:05 alice-i-cecile