Godot version:
3.1.1
I'm going to have a (simple) custom physics simulation in C++ for a bunch (thousands) of 2D bullets, and couldn't find a nice way in the current API to render them. Each bullet may have a different texture, though most will have one of a few very common textures.
I feel like the best way to render these would be instanced rendering using a texture atlas for the bullets, but I don't see how I could do this using the Godot API. It would be nice to have something like MultiMesh for 2d textured rectangles, except each instance can specify a different part of an atlas to pull from, as well as specify a different rectangle size.
Additionally, it would be useful to be able to specify a parameter for all instances at once, using a PoolArray (e.g. use a PoolVector2Array to specify all positions). All bullets will always be moving, so I will need to update all of their positions each frame (Other parameters may change less frequently). I don't want to have to incur the cost of a function call for each bullet, when setting instance parameters through the bindings produced by godot-cpp.
Methods in the current API I have considered, and what I think the issues with them are:
For context, I'm doing a custom simulation because I want the simulation to be deterministic across platforms, hardware, etc. To do that, I'm using fixed precision fractions (implemented with integer math).
What a great coincidence! I was just thinking about adding a MultiMeshInstance2D node today. The MultiMesh API is already made to work with 2D. So you can already do what you are describing above if you are willing to access the VisualServer directly (described here http://docs.godotengine.org/en/latest/tutorials/optimization/using_servers.html). But it would also be nice to have a MultiMeshInstance2D node to make this more accessible.
Thanks, I'll try to do it with the method you suggested. Do you know whether each call to multimesh_set_transform (or other setters) does anything expensive like send data to the GPU? Or is it all sent in one batch when drawing actually happens?
It all goes in one batch when drawing happens, and only gets resent to GPU if it has been updated. So if you call multimesh_set_transform every frame then it will update every frame, but not each time it is called.
If you are comfortable with C++ it is worth looking at how CPUParticles2D are implemented.
Thanks.
How many bullets are we talking about here? I'm driving up to 20k sprites using C#. The primary bottleneck is the need to pool, and the math behind the movement code.
I don't think I would have more than 100k (that will be a hard limit), and probably I'll have much less than that, so based on what you said I guess I can hold off on trying to do it this way unless I find I need to based on profiling. I might still use draw commands instead of sprites though since in my current code it will be easier if the interface between my state and drawing is stateless.
I have a hard time fitting 2000 bullets on the screen. And up to 20k are performing fine with sprites. So i don't think theres much need for a multi mesh 2D. If its grid locked we have tilemaps.
The game I'm working on involves viewing many smaller resolution instances of the same game (like Tetris 99), which is where my 100k upper limit guess comes from (1000 bullets in one instance times 100 instances). I know the player doesn't really need full rendering from every tiny-sized instance of the game, but this is the easiest way for now to render those other instances (and if it doesn't look too ugly I can keep it as an optional setting).
Most helpful comment
What a great coincidence! I was just thinking about adding a MultiMeshInstance2D node today. The MultiMesh API is already made to work with 2D. So you can already do what you are describing above if you are willing to access the VisualServer directly (described here http://docs.godotengine.org/en/latest/tutorials/optimization/using_servers.html). But it would also be nice to have a MultiMeshInstance2D node to make this more accessible.