Reducing draw calls with atlasing -- does anybody care?

Hi. Sorry if I’m asking a pretty basic question, but I couldn’t find a clear answer on that.

I’m a total noob in UE, but I have ~10 years in Unity, and there was a lot about texture atlasing to reduce draw calls. Dynamic batching and everything related.

I wounder – what approach is used in UE? For example, I have a lot of small objects (could be both static and dynamic) that share a material (shader), but each one has its own texture.

Do I need to care about that in UE? And if yes, is there any tool/plugin that will help me to pack textures in an atlas and automatically remap the UVs, but leaving the scene and all objects modifiable / movable in the editor (means it doesn’t bake it into a single mesh)?

Or there’s some magic about the UE renderer that draw calls don’t mean much?

The main thing you’ll get from packing is memory reduction, because all the materials are using the same texture.

You get one draw call per mesh per material in any case.

So if you have 500 items on the screen all using the same material, but different UVs, you’ll get 500 draw calls.

There are no ‘in engine’ tools for atlasing, but there’s probably stuff on the marketplace.

might aswell use standard material instancing. it should improve performance enough. you should get drawcalls but they are not as severe. the worst enemy of the pipeliine in changing shader code. you stall everything. if you run one shader and different textures you only change the data that is the input. the other advantage is that the lod system can manage the texture lods in a memory bound scenario. a huge atlas always gotta be fully loaded even if not all the lod is used.

UE has built in tools for texture arrays, which are generally superior to atlases. It does have some limitations of its own (for example at array elements must have the same sampler properties, like size and mipmap settings.)
Keep in mind that while these techniques may reduce draw calls, but they may also increase memory due to have potentially unused textures loaded… so just be very considerate when deciding what textures belong in an array together.

1 Like

Really? Hard to believe. So UE doesn’t have any dynamic batching to make this in 1 draw call? Because GPU-vise it is definitely could be done.

Yes, it does, instancing. Then it’s 1 draw call. But they all have to be the same mesh and material :slight_smile:

So, different meshes with the same material don’t combine into 1 draw call? I’m double checking because that’s what Unity does for ages – it automatically packs all such meshes into 1 combined mesh and push this data as 1 draw call into the GPU. And does that seamlessly for you each frame, so you don’t ever think about that.

Draw calls = Meshes * materials ( without instancing )

You can try it yourself with ‘stat unit’

At any rate, draw calls often aren’t the bottleneck. With UE5, Lumen and VSM calculations are very likely to be causing much more of a headache.

Thanks a lot! Will try to wrap my head around that.

1 Like

well… you can do that in ue too. say… you have littering in your scene. 500 things but using 20-30 different meshes with materials. first of all you use instances to dupe them. and you use material instances to not create new shaders. it draws every material instance and amount of instances existing. that would be the 20-30 draw calls from the material instances. at draw time the vertex and texture data is mosdef already on the gpu. it does not batch this in software. in multithreaded rendering this may be batched and is just a couple of draw commands. but essentially one call cause you set the shader only once. the rest is instanced materials.

set core shader
set mesh buffer
set instance buffer
set input texture
draw mesh instances
set mesh buffer
set instance buffer
set input texture
draw mesh instances

this is a kinda fast path cause you don’t have to rebuild the render pipeline. this is what would be stalling.

They do with Nanite, but not with the regular pipeline.