In order to keep draw calls to a minimum, we need to make use of instancing.
I.e. having a transform buffer go along with the draw call.
Cool! I'm Curious however, as there is no instancing support in ES2 without extensions, would this task open up adding an extension system, ability to bump ES version or would you simply use uniform arrays and pack clones into a vertex array?
How do other 3D tools keep draw calls low with static meshes? UE4 for example. When I was messing with it I had made a huge world with tons of meshes but draw calls were very low.
To get few draw calls you need to batch as much as possible, which is done by sharing as much draw state as you possibly can. Having one material (e.g combination of shaders plus rendering properties such as blending and uniforms) with the same textures that share the same mesh is optimal, and changing any of those components typically breaks batching causing state changes and more draw calls.That is why techniques such as atlasing, dynamic batching and instancing exist. There鈥檚 a lot of tricks to utilize to keep draw calls down, but mostly it comes down to sharing state (and data) as much as possible.
There is quite a lot of batching going on in Defold, but if you want to draw 100 trees with local space materials you鈥檙e gonna get 100 draw calls even though they probably should be instanced. This is definitely an area of improvement for better 3D support and I鈥檓 really excited to see new features being worked on :)
@jhonnyking Speaking of local vs world we need an example of how to properly do world with mesh materials while keeping batching. @dapetcu21 was asking about it. Maybe that's related to this issue?
I guess in UE4 a lot of optimizing is done under the hood. Like they use mega shaders and compile down shaders to only what is used in the project. I don't understand all of it still. :)
To draw huge worlds with lots of models, you'll use instancing.
Keeping state changes to a minimum as Jhonny says, is essential.
Note that for vertex data it is impractical to loop over the data and transform on the CPU, because the meshes are too large. This is what the GPU is built for.
To draw 100 trees fast, you'll use only a few actual meshes (i.e. vertex buffers), and you'll use an instance buffer, which is a list of the transform matrices for each tree instance. This is what this task is about.
As for rendering a mesh in world space, it works exactly the same way as for sprites.
However, there was a bug in there that made the meshes not transform correctly.
Regarding instancing support in OpenGLES, we might allow some setting to the project so that it can initialize to a newer version. We need to support WebGL anyways, so it doesn't seem like a stretch.
Most helpful comment
To draw huge worlds with lots of models, you'll use instancing.
Keeping state changes to a minimum as Jhonny says, is essential.
Note that for vertex data it is impractical to loop over the data and transform on the CPU, because the meshes are too large. This is what the GPU is built for.
To draw 100 trees fast, you'll use only a few actual meshes (i.e. vertex buffers), and you'll use an instance buffer, which is a list of the transform matrices for each tree instance. This is what this task is about.
As for rendering a mesh in world space, it works exactly the same way as for sprites.
However, there was a bug in there that made the meshes not transform correctly.
Regarding instancing support in OpenGLES, we might allow some setting to the project so that it can initialize to a newer version. We need to support WebGL anyways, so it doesn't seem like a stretch.