cocos / cocos-engine

Cocos simplifies game creation and distribution with Cocos Creator, a free, open-source, cross-platform game engine. Empowering millions of developers to create high-performance, engaging 2D/3D games and instant web entertainment.
https://www.cocos.com/en/creator
Other
5.5k stars 1.58k forks source link

[2D] [iOS web] Sprite is not rendered with RenderRoot2D and Camera.Far = 1000 (default value) #16715

Open idchlife opened 5 months ago

idchlife commented 5 months ago

Cocos Creator version

3.8.1, 3.8.2

System information

iOS Safari/Other browsers (17.2.1)

Issue description

Tested with multiple iOS devices. iOS (17.2.1)

The problem is RenderRoot2D with Camera.Far = 1000 works everywhere except iOS devices.

It seems iOS WebKit fails in test "pos.z > camera.far". It calculates basically "1000 > 1000 === true" on iOS devices, or something like that.

It was a very stange behaviour since rendering worked nicely everywhere except iOS devices. So debugging this one was a total disaster.

I assume it would be nice to change RenderRoot2D applying .z to 999. Or change default Camera.Far to 1001 or something.

WORKAROUND: make Camera.Far greater than 1000.

Relevant error log output

No errors.

Steps to reproduce

1) Create 2D game. 2) Add camera. Default Far option is 1000 3) Add sprites on scene. 4) Add RenderRoot2D to some sprites. 5) Launch preview or build on iOS device. See that nodes with RenderRoot2D are not rendered.

Minimal reproduction project

No response

GengineJS commented 4 months ago

Hello, I am using the same IOS version as you, and I followed the steps you provided to run the scenario using Safari and Chrome without any rendering issues. Could you provide a demo that can be reproduced?

GengineJS commented 4 months ago

Putting the canvas on the far plane does indeed lead to other issues due to precision on some platforms. So, if you have a reproducible demo to help with troubleshooting, that would be best. Thank you.

idchlife commented 4 months ago

@GengineJS

iphone-2d-renderroot-repro.zip

Check Camera.Far

If it's 1000 - some sprites are invisible. If above 1000 - all visible.

I tested with iPhone preview with QR code.

GengineJS commented 4 months ago

In your demo, sprites are placed on both the near and far planes, which could lead to rendering issues on some platforms due to floating-point precision, as I mentioned earlier. From the demo, I can infer that you intend to manually sort the nodes. However, UI nodes disable depth writing and depth testing during rendering. Therefore, nodes positioned last will be rendered last, and the rendering order is independent of their 3D positions. Hence, you can move the nodes of SomeAboveEverything and SomeBackground to the same plane position as SomeForeground.

idchlife commented 4 months ago

In your demo, sprites are placed on both the near and far planes, which could lead to rendering issues on some platforms due to floating-point precision, as I mentioned earlier. From the demo, I can infer that you intend to manually sort the nodes. However, UI nodes disable depth writing and depth testing during rendering. Therefore, nodes positioned last will be rendered last, and the rendering order is independent of their 3D positions. Hence, you can move the nodes of SomeAboveEverything and SomeBackground to the same plane position as SomeForeground.

Is this a bug and is it fixable in the code of the editor?

Reproduction demo is just for the case of reproducing the situation. In project I worked on, real world project, I had to position UI nodes somewhat like in this reproduction demo. And then I encountered this behaviour.

Unfortunately, "Just position nodes below, they will be in front" approach is not that applicable in complex projects with prefabs, prefab replacings, multiple layers, 2-part objects (imagine a barrel in 2d, you are in front of it's back side but behind front side), UI loaders, UI notifications, moving camera etc.