godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Add per-surface render priority property to MeshInstance3D #7714

Open Nomad1 opened 1 year ago

Nomad1 commented 1 year ago

Describe the project you are working on

UIs where semi-transparent sprites are drawn from the code using RenderingServer or ImmediateMesh/Geometry.

Describe the problem or limitation you are having in your project

Right now surfaces are sorted using the:

However, if we take a closer look, it is merely impossible to provide a custom order for surfaces with the same material and depth sort issues (i.e. UIs). There is even no way to leave the surfaces unsorted.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

We need at least per-surface priority field for manual tinkering. Flag to avoid sorting and use creation order would do as well.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

SortByReverseDepthAndPriority will already do the job if we put valid data to A->sort.priority/B->sort.priority

However it shouldn't be just sdcache->sort.priority = p_material->priority; but something more.

If this enhancement will not be used often, can it be worked around with a few lines of script?

Right now the only workaround is to create a separate instance instead of mesh + surface.

Is there a reason why this should be core and not an add-on in the asset library?

Core functionality.

Calinou commented 1 year ago

Should this property be part of the MeshInstance3D node or the material resource itself?

Nomad1 commented 1 year ago

Definitely not the material - there is already a priority property for them. It could be shown in a MeshInstance3D as well, although I'm speaking about a bit lower level, so it should be somewhere in the C++ code, and accessible with something like RenderingServer::instance_set_surface_priority( RID instance, int surface, int priority )

OhiraKyou commented 1 year ago

Explicit sorting groups are important for environmental art as well.

In Unity, there is a SortingGroup component that can be used to force a group of objects to be sorted together as if they were one object, with an explicit sorting order integer (which can be negative) that is relative to its parent sorting. By nesting these, an explicit sorting hierarchy can be constructed.

I often use this to create water surfaces from layers of modular effects rather than monolithic shaders. The water surface, as a whole, is given a sorting group with a default sorting order (0) so that it is sorted along with the rest of the scene geometry as if it were a single object. Then, within that water surface object, each layer (child object) is given its own sorting group to make the internal layer sorting order explicit.

Example water layers list:

I also explicitly sort water underside layers after the underwater light rays so that the rays are correctly rendered before the topside layers but after the underside layers (underside > rays > topside). This ensures correct sorting when viewed from underwater.

Example layered water screenshot from my Unity project:

2023-06-08  Nytro - Layered Water Surface Effects - 2 (WIP)

Calinou commented 1 year ago

Thanks for detailing your use cases :slightly_smiling_face:

That said, sorting groups are already being tracked in https://github.com/godotengine/godot-proposals/issues/3986, so please continue the discussion there.

Nomad1 commented 1 year ago

Thanks for detailing your use cases 🙂

That said, sorting groups are already being tracked in #3986, so please continue the discussion there.

I still want to clarify that the sorting group issue is a high-level feature that might require separate objects and layers, while what I'm asking for is a low-level adjustment in RenderServer to render surfaces in explicit orders as they were added to a mesh instance.