godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.15k stars 96 forks source link

Expose the starting vertex position and number of primitives to be drawn in ImmediateGeometry #2705

Open DexterZ101 opened 3 years ago

DexterZ101 commented 3 years ago

Describe the project you are working on

I'm working on an RTS game which consist of lots of dynamic procedural mesh, such as 3D trail, debug lines etc,,,

Describe the problem or limitation you are having in your project

ATM 3D trails are created by Clearing the IG and adding the vertices again even with same previous length because that's how IG work.

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

Since the vertices are already put in IG, it would be nice if the vertices can be expose and edited and give the user to define the StartingVertex position and the number of PrimitiveCounts to be drawn.

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


ImmediateGeomrtry m_IG = new ImmediateGeometry()
//
m_IG.Begin( Mesh.PrimitiveType.Lines )
{
   // Line 1
   m_IG.AddVertex( new Vector3(0, 0,0) )
   m_IG.AddVertex( new Vector3(0,10,0) )

   // Line 2
   m_IG.AddVertex( new Vector3(0,  0,0) )
   m_IG.AddVertex( new Vector3(0,-10,0) )

   // Line 3
   m_IG.AddVertex( new Vector3(0,  0,0) )
   m_IG.AddVertex( new Vector3(0,-20,0) )

   // Etc..

}
m_IG.End();

// FEATURES TO BE  ADDED

//-- Somewhere in the code we can edit vertices or define VertexOffset and 
//   the number of PrimitiveCount to be render without Clearing and recreating
//   the vertices again in the IG.

// EG.  Modified the vertices value which is already been defined above
//       say wanted to edit the value of Line 1.
//
m_IG.Vertices( 0, new Vector3( 1,1,1)    );
m_IG.Vertices( 1, new Vector3( 10,10,10) );

// Let the user specify STARTING VERTEX offset and numbers of PRIMITIVE COUNT

// EG. If wanted to render the Line 1 only
//
m_IG.StartingVertex    = 0;
m_IG.PrimitiveCounts = 1;

// EG. If wanted to render the Line 2 and Line 3 only
//       2 primitives counts starting vertices 2.
//
m_IG.StartingVertex   = 2;
m_IG.PrimitiveCounts = 2;

to make the example simpler to understand I'll just use primitive lines,

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

Sure but clearing and creating the vertices everything in IG might be slow,

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

This will benefit everyone because it's out of the box features : )

Calinou commented 3 years ago

Note that ImmediateGeometry is not reimplemented in the master branch yet and may be readded in a slightly different form.

In 3.x, ImmediateGeometry is slow to render and may not be worth it over using ArrayMesh, SurfaceTool or a shader to manipulate the vertices.

DexterZ101 commented 3 years ago

Hello Calinou,

The new tittle is exactly what I have in mind, hopefully it can be implemented whenever it will be readded and can change the vertices information that's already been added along with it's starting vertex position and primitives count.

Many Thanks! DexterZ

clayjohn commented 3 years ago

I would prefer to see this kind of functionality added to the mesh API instead. I think it would make more sense there given the purpose of the two APIs

ImmediateGeometry is meant to give users a way to quickly put a mesh together each frame. It is much slower than using an ArrayMesh, but it is much faster than recreating an ArrayMesh every frame. Accordingly, ImmediateGeometry is best used when you have to update every vertex (or most vertices) per frame.

The mesh API already has mesh_surface_update_region which allows users to just updated a specific portion of the mesh. This is ideal for the use-case you describe. During regular frames, no data needs to pass from the CPU to the GPU and you get the full speed of using a mesh, you only incur the cost of updating on the frames that you update and only for as much of the buffer as you choose to update.

The big problem with mesh_surface_update_region is that it requires the user to understand how the vertex data is laid out on the GPU. Accordingly, something like what you propose would be nice, maybe a mesh_surface_update_vertex() function or something similar. It wouldn't be as fast as update_region, but it would be easy to use.

Similar with the starting_vertex and primitive_count feature. Internally, when drawing a mesh, OpenGL asks for the starting vertex and how many vertices to draw. This could be exposed to the user for regular meshes.

DexterZ101 commented 3 years ago

Hello ClayJohn,

I'm playing with SurfaceTool and ImmediateGoemetry for my procedural mesh and looking for this kind of solution.

It's nice to know that the vertex data can be updated using mesh_surface_update_region and I think this will suffice what I'm looking for, the only lacking is specifying the StartVertexPosition and PrimitiveCount ^_^y

If this can be implemented in any tool whether in SurfaceTool, ImmediateGoemetry or directly to mesh-surface that would be great, super cool if implemented in a user friendly manner.

If the vertex data can be buffered and define once at the same token we can update it, the processing will be much faster because there is no clearing of previous vertex data and setting it up again and we are sure it will be drawn in a single draw call.

During XNA time I can create millions of lines and triangle using DrawUserIndexPrimitives because I can buffer the vertex data I needed a head of time and update only the vertices position and set the vertex offset and number of primitives.

Many thanks and kind regards,

DexterZ

Calinou commented 2 years ago

The ImmediateGeometry node was removed in favor of the ImmediateMesh resource in 4.0 (which you can add to a MeshInstance3D or MultiMeshInsatance3D). Does that change anything about this proposal?