How to "merge" sprites in defold

Second try:

Removed unused graphics in GUI with boxes, sprites etc.

The “unit-menu” dropped from 124 to 107 frames. Logic… there was the “old” menu etc outof the view and other crap. Removed it to drop down the drawcalls. Have to continue the cleanup.

(btw, just posting this for beginners to prevent questions).

Maybe there should be another optimisation-thread?

@stephenkalisch I suggest you have a look at this great writeup on draw calls in defold by @Mattias_Hedberg to get you started :slight_smile:

3 Likes

My experience of optimisations.
This post awesome!

The main things that helped me:

  • use 1x1 alpha sprite in gui instead of empty nodes;
  • node layers;
  • replace tinting sprites with pre tined textures.
3 Likes

Thanks @AGulev.

I’ve seen your post already. Not sure how it works.
1x1 alpha sprite? I’ve added a 1x1 colored pixel, f.e. orange and added the texture for the box-node. but it “fades out”. Like you can see here (first button START)

Ah now… you mean for empty nodes. Dont have any yet. Tying your example I realized: textured boxes reduces the drawcalls by 1 instead of just colored boxes o.O

added a simple layer and added all nodes to it. no effect.

last point “tinting sprites” not sure what you mean…

btw: Very nice game you are on! Really like the graphics :wink:

1 Like

step by step:

  1. 1x1
    Sometimes you need empty node for right position of children.
    Bad a node without texture (break a batch) open full image by click:

Good (alpha texture should be in the same atlas as other gui items):

2 . Node layers
Different types of nodes break batch.

Bad when all nodes has the same layer or has no layer. All nodes draw one by one like in yours “Outline window” and if some text (for example) into box node, it will break batch.

Good all different types of node has own layer (draw order). For example all box nodes has an “img” layer, and all text node has “txt” layer. Sometimes you need to draw text under the box node, then you need one more layer for it.

3 . Tinting sprites.
If you change tint using sprite.set_constant, and it will be static (it is not an animation, just change tint once) You can change tint in photoshop and use this texture in game. It will help to reduce drawcalls count.

Ok. got the layers (always 2: one for boxes called “img” and one for the text-nodes called “txt”). changed on (hopefully) every gui.

Reduces the drawcalls by half! In the main menu there was 38 calls, now 23. In game (no building menus open), at 23 drawcalls, was 42.

Have to continue optimizing. Opening a unit-menu for building punshes the drawcalls from 23 to 90.
The reason is the dynamicly generated “pop-up-build-menu”.

Here…a question to @britzl and the other Pro’s… If I clone a node-tree, does the cloned one also clones the layer-config from the template? Or do I have to set it for the clones?

3 Likes

Does using GUI templates impact to the draw-calls?

I am using linked GUIs: unitmenu and buildmenu.

hm…
I dont know why the unit and structure menu takes about 70 drawcalls for 90 nodes.

both menues are now based on 2 layers.

Are you changing the color of the nodes? That would break the batches. Does all of the box nodes have an image assigned from the same texture?

hm…
I use box-nodes with different colors. I thought this would be the most “hardware-friendly” way (and I like simple looks).
All the dynamic (cloned) buttons have a coloured box as background. its about 15 buttons containing a background box-node, a box-node with a sprite and 2 text-nodes with 2 different fonts (sizes).

The content of the “ingameGUI” which will be activated after clicking on a unit or structure which takes about these 70 are in the last screenshot. The button left top is a template. it will be cloned depending on a table content which is actually 8 entries.
there is also a nearly same GUI (for structures)- dont have these small buttons in the middle - rest the same. also 7 dynamic buttons.

These 2 GUIs activated (happens if you click on unit OR structure) takes all the performance.

I could give you screens, source or access if you like.

I’ve saw this kind of solving and handling in some examples and thought it would be a good way.
Maybe I should handle it all in one GUI (unit and structure).
I have a couple of GUIs actually.

I was wrong. Box nodes with different colors does not break the batch. Sorry about that.

You’re welcome to invite me (bjorn.ritzl@king.com) to the project and I’ll take a look.

Uploaded and added you to the dev-team :slight_smile: Thanks so far.

Some things I’ve noticed when looking at the unit.gui:

  • You’re using two layers; img and txt. The thing is that you’re using both the system font and your own font and you assign all text nodes to the layer txt regardless of font. This will break batching every time the font changes. Solution: Use one font or use more layers (one per font).
  • The node structure_underconstruction is assigned to the img layer but it is set as semi transparent (alpha = 0.3). I believe this will break a batch.
  • The node move_selector doesn’t have a texture but it is assigned to the img layer (and it’s semi transparent). This will break the batch. Create an image, add it to the atlas and use the image instead.
  • The node buildmenu/button_buildstructure_base doesn’t have a texture assigned either.

I believe the above couple of issues are causing all of the additional draw calls in that gui scene.

1 Like

Thanks so far @britzl.

hm… that means every box-node needs to have a texture?

if there is any transparency there has to be a separate layer?

for each font a layer?

OMG. Nearly everything designed is a “batch-breaker”.

There should be a separate thread which explains the batches :wink:

Like I’ve said, I’ve coded this game in another language which is no engine. There, I have to code a couple of procedures (was a basic language). One for unit-tracks, one for kind of particles, one for units, one for … etc. There I had to take priority who many such procedures will become called and what content. I needed 1 month for optimizations. So I compare your batches like classes our routines which handels specific stuff. one for box-nodes, one for textured-box-nodes, one for text-nodes etc. If you mix up too much some classes/routines has to be called twice - thats what its meant to “break a batch”, right? layers seems a way to handle that if I understand the docs and you right.

Is there any “batch” list, priority or anything to read for a deeper understanding or understanding at what “situation” a batch breaks?

What we are talking about really is the work of the GPU and OpenGL. Two things are involved here:

  1. Giving OpenGL instructions to set up the render state. Which shader should be used? Which texture? Which blend mode? And so on.
  2. Instructions sent to the GPU to draw a mesh. These are the draw calls.

The initial setup of the render state is expensive. Telling the GPU to draw a mesh isn’t.

Defold will try to batch draw calls that have the same render state (ie the same texture, shader, blend mode etc).

When I write “break a batch” what I really mean is that if we have a long list of things in the game (for instance sprites) that have the same properties they will all be drawn in a single draw call. This is good. BUT if I have one sprite with another material or with another blend mode and stick that into the middle of my long list of otherwise identical sprites then I’m breaking the batch of draw calls. What would otherwise have resulted in 1 draw call now results in 3 draw calls. This is bad.

The documented that has already been linked previously covers this: Draw calls and Defold

To clarify:

Rendering of sprites, spine models, particle fx etc

  • Rendering is based on z-order, back to front.
  • Components on different depths will be batched unless one of the following is different from the previous component:
  • Component type (sprite, spine, particle, label, model)
  • Texture
  • Material
  • Blend mode, tint etc
  • Collection proxies
  • Note: Each particle emitter will result in a draw call

Rendering of gui scenes

  • Rendering is based on the order of the nodes in the outline, depth first
  • Nodes will be batched unless one of the following is different from the previous node:
  • Node type (box, text, pie)
  • Texture
  • Blend mode
  • Font
  • Stencil settings

Layers are used to group different nodes to reduce the number of draw calls. Some images:



5 Likes

Big thanks @britzl!

Very detailed answer. Its principially what I thought and what I meant with my posting. Without an engine (only some sprite commands) you have to write your own “Batches” etc.

But now it is a clear thing what it is about.

As I asked for a “list of breaking batches” its exactly that: “sprite with different texture” etc.
Does your posting includes all states of breaking/changing a batch? Or are there much more “mistakes” to make ?

1 Like

I believe my list should be complete, but I’ll gladly let @sven, @Mathias_Westerdahl or @sicher correct me!

1 Like

in my case, I already use layers to reduce the drawcalls. but thats not enough. there are different sprites for each box and in every background box are 2 different fonts o.O

So does it make sense to “group” the boxes without textures to one layer, the all-different-texture-boxes to another layer and for each text-box-font a layer (2 diff. fonts = 2 layers)?

oh by the way… texture in a box… I’ve “played” a bit with the settings, is there no setting to “repeat” a texture?
Also if I try to “stretch” a texture, f.e. a 1x1 pixel or 10x10 (one color) to fit to the whole box-node?

//EDIT:
I’ve did it like said above and decreased the drawcalls from 92 to 31 o.O. Now this GUI takes about 10 drawcalls.

Reduced round about 100 drawcalls now! wow. Knowledge is power! :wink:

thanks again :slight_smile: @britzl you’re doing a great job to help devs here! applause

1 Like

Hey there.

Just asking again, maybe there is something I’ve missed to the main theme…

Is there a way to have 2 or more sprites on a gameobject and rotate them diffrently?

In the example I am trying to have a tank (tracks) and a gun. the gun Needs to be rotated , tracks stay as they are.

Is it possible?

You probably want sub GOs for each of the sprite elements which are parented to the main tank GO so that each sub element can have its own transform while still being transformed by main tank position.