Texture atlasing (resolved)

Is it possible to atlas textures for the GUI.Box and GUI.Button methods?

I was playing with these last night and I can not figure a way to pass the UVs into the functions.

My texture is a 512x512 split into 64x64 icons and I want to draw one of the icons onto either a Box or a Button but I can not figure out how - I can only draw the whole texture page onto each Box / Button.

TIA,
mjjw

Well I’ve managed to draw a texture in this way.

I am using a GUI.BeginGroup to create a clipping rectangle and then using an offset to ensure that only the relevant part of the texture is drawn - works like a charm.

I don’t know if the GUI will be texture batching for improved performance? But it does make my GUI textures more manageable this way - one big atlas instead of lots of smaller files.

:smile:

I was also wondering about this.

Currently I have a play controls panel with 5 buttons, each using their own customStyle in my guiSkin. Each button has its own normal, active, and hover states. This means I have 5 x 3 = 15 different textures, all 24x24 px in size (not a power of two either, boo!).

Could anyone answer:
Does unity do any optimising for me behind the scenes, or should I look into creating a texture atlas for all the buttons? Ie: creating the styles on the fly by reading pixels off the texture atlas, rather than having them predefined in the guiSkin?

Cheers!

GUI.DrawTexture needs a clipping option – although your workaround seems neat.

Hi again, just wondering if anyone had an answer for this?

Cheers :smile:

I quite doubt that will make any particular difference, aside from being more annoying to program.

–Eric

Yeah, prob for the number of textures in my example the difference won’t be noticeable…
but I actually have considerably more buttons…

I have a set of 5 buttons…
another set of 5 buttons…
another set of 3 buttons…
plus 8 small images I’m using for icons.

that’s already 47 small but non-power of 2 images.

I dunno, all logic is screaming at me that this must be inefficient… I’d like to know if unity is being clever in the background with them.

When you build your application for deployment, from what I know, Unity compresses all images the best it can in the final build. Tons of optimization goes on at build time.

Hi mjjw,
I’m just trying out your solution using the group as the clipping mask… but my style isn’t listening to its contentOffset parameter! Any idea why? (essentially whatever values I put in the X and Y, the texture remains in the same position:

My texture atlas for this test is 124x78 pixels and contains four textures each 62x39 pixels.

this is the line I’m using to offset content on my style containing the texture atlas:

tempStyle.contentOffset = new Vector2(62,0);

and this is in OnGUI:

GUI.BeginGroup(new Rect(0,0,62,39));

GUI.Label(new Rect(0, 0, 62, 39),"", tempStyle);

GUI.EndGroup();

bump cheers :smile:

I also can’t seem to get contentOffset to do anything.

I am using Unity for iPhone.

I have a texture atlas of seven 68 by 64 frames in a single texture. The texture has been padded with transparency to be 512 total pixels wide to make it a power of 2.

Here is my code but contentOffset is ignored no matter what I set it to.

GUI.BeginGroup(new Rect(0,0,68,64));

GUIStyle myStyle = new GUIStyle();
myStyle.normal.background = animationStrip;
myStyle.contentOffset = new Vector2(68,0);
GUI.Label(new Rect(0,0,512,64), “”, myStyle);

GUI.EndGroup();

Thanks!

Not sure why contentoffset is not getting applied - it definately should. Could you file a bug on that one and post the ticket number? then I can see it in context.

In the mean time, rather than mucking about with contentOffset, why don’t you just move the label around?

For performance though, this is not the way to go. I’ve looked into batching the draw calls - but correctly detecting a group clipping a texture will probably always throw you off whatever fast path we’ll add.

Why do you want to have all textures in an atlas? If its for easier editing, I use Save For Web. That lets me have one photoshop file for e.g. the editor skin, which gets saved into 200+ individual images. Works like a charm.

Thanks for the reply Nicholas. I’m not committed to using a texture alias. I am trying to find the best way to created 2D cell animation using only UnityGUI. Between the docs, the forums, and the Wiki, the solutions are very vague.

Is the best way to use texture atlases with and Group clipping rectangles or is it better to use arrays of textures?

Thanks!

Hi everyone,

I would like to follow up on this.

@nicholas: My main and only concern is the render framerate on the iPhone. For this reason I carefully count the number of draw calls my application is making. My current GUI needs to draw 20 icons on a page. Is it possible to draw all those with a single draw call?

My approach is to put all of my icon textures into a single atlas. Then, I want to define 20 GUIStyles, all referencing the same texture but each with an appropriate offset. I want to then call GUI.Box() 20 times, giving the 20 GUIStyles as a parameter, one to each call. Then, I want to discover that because all the calls were referencing the same material, the system batched the 20 calls I just made and drew all 20 icons in a single draw call.

Is this possible?

Thank you!
pfg

No, this is nit currently possible. The fastest way to something like this would be to generate or author a mesh which has all your 2d elements, and then write custom code to handle tha touches.

If you’re overlaying 20 buttons on top if live action, that would be the way to go. Otoh, if you’re essentially making a menu screen, however, You can probably get away with ignoring the performance Implications of the 20 draw calls.

Nich