godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.13k stars 83 forks source link

Allow drawing meshes manually #8533

Open Redwarx008 opened 10 months ago

Redwarx008 commented 10 months ago

Describe the project you are working on

A 3D Terrain Lod system

Describe the problem or limitation you are having in your project

Today's terrain grid systems are generally block based. Usually we can culling quickly through a quadtree, especially when the number of grid blocks is very large, the camera's violent culling will become very slow.

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

In my case, I used the geomipmap algorithm (which guarantees screen-space pixel error and is ideal for top-down strategy games). When the block size is 32, a 4096*4096 map requires 16384 mesh objects, causing a sharp drop in the number of frames. If the mesh can be drawn manually, I can complete the culling while doing lod level selection through the quadtree.

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

Functionally, I think it should be similar to Unity'sRenderMesh

RenderSever.DrawMesh(RenderParams rparams, Mesh mesh, int submeshIndex, Transform3D objectToWorld)
struct RenderParams
{
  Material material;
  int layer;
  ...
}

RenderMesh just submits the Mesh for rendering.

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

No...

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

It's the render core

Calinou commented 10 months ago

It's already possible to render meshes without going through nodes. Otherwise, debug drawing wouldn't be able to work :slightly_smiling_face:

If culling performance is a problem, there should be a way to disable frustum culling entirely for specific meshes. You can already define a custom AABB in GeometryInstance3D (which removes the need to compute this AABB when a skeleton changes), but using a huge AABB[^1] won't automatically skip culling.

[^1]: Sizes are relative, so "huge AABB" would be an AABB whose shortest axis is longer than the distance between the camera's near and far plane.

Redwarx008 commented 10 months ago

It's already possible to render meshes without going through nodes. Otherwise, debug drawing wouldn't be able to work 🙂

It has already bypassed the node system and already using custom_aabb to set the correct aabb for each mesh. 1

leozzyzheng commented 10 months ago

I think the problem is when rendering large scale terrain, GPU instance is required so MultiMesh must be used. But for terrain rendering in most cause, the mesh we sent to GPU is a flat plane without any height, and sample height map in vertex shader. In this case, the frustum culling might be incorrect on CPU side, we need a way to set custom AABB baked from height map offline. It is available for GeometryInstance3D but can't find any way to set it in MultiMesh.

leozzyzheng commented 10 months ago

Additionally, I think it is a typical situation to do culling on GPU side by compute shader, then indirect draw is required, but I don't see any indirect API in engine documents, is there any roadmap for indirect draw?

fire commented 10 months ago

I'm curious how badly does redrawing every frame perform https://docs.godotengine.org/en/stable/tutorials/3d/procedural_geometry/immediatemesh.html

There's been a long wait for better async and compute shader support in Godot Engine.

fire commented 10 months ago

This proposal might be solved by Add new Mesh resource subtype to enable creating surfaces using RenderingDevice buffers #7209

leozzyzheng commented 10 months ago

I'm curious how badly does redrawing every frame perform https://docs.godotengine.org/en/stable/tutorials/3d/procedural_geometry/immediatemesh.html

There's been a long wait for better async and compute shader support in Godot Engine.

Recreate all mesh vertices at CPU side will be very slow since vertices count might be 100,000 ~ 1,000,000 for a high quality large scale terrain. So drawing with GPU instance and only send unchanged mesh data and change the vertex position at vertex shader stage is the normal way to render terrain.

If compute shader is not available, then set custom AABB for instance draw API is a reasonable feature request I think.