- Home /
Texture2D.Apply Optimization or Alternative
(Questions are at the bottom)
This is in response/reference to another question I had that was closed: http://answers.unity3d.com/questions/436414/drawing-a-display-panel-with-textures.html
I ended up writing a little library thing that enables me to draw boxes and rounded boxes (and soon text and polygons) on textures and then update them every time I call a certain function. For example (in this picture), the white boxes grow larger upwards as time goes on. By this I mean...
I've optimized this fairly well so that it only has to Apply the pixels once every time I call the update function (It makes a base texture and then stores all drawing instructions for other shapes in an array so that when I need to update it, it redraws all the new things with new values and then applys it).
Unfortunately, this still doesn't seem to be enough. Here's the problem
Update rate:0.01sec | FPS: ~60
Update rate:0.1sec | FPS: ~80
Update rate:0.5sec | FPS: ~90
Update rate:1sec | FPS: ~95
To make it look smooth, it needs a smaller update rate. 0.1 seconds is what I usually go with but it isn't ideal (0.01 is sooo smooth). The FPS loss only grows when I have more than one panel. Even if I make the rate something say 1 second, the fps is high but there is visual lag when making multiple panels.
My questions:
How can I optimize this any more? As I said in my other question that got closed, I was able to do something like this in Garrys Mod with Lua and it ran much faster and was much more complex. I even remember duplicating it multiple times and my fps drop was minimal.
Should I just throw this away and switch to using vertices with a custom shader? How would I go about drawing text? Rounded boxes? It just seems like a hacky way to do what I want especially as these panels grow in complexity. I'm not even sure this would have the functionality I need either...
Are your textures as low-resolution as they appear in the image (about 32x32 pixels)? If so, there should be no problem at all. If not, then I suggest either making them so, or as an extension of the answers to the previously-closed question, don't use pixel manipulation, ins$$anonymous$$d model that as a grey rectangle with a stretched yellow or white rectangle on top of it.
In my experience, pixel-manipulation is rarely a useful way to do anything (excluding shader-based RenderTexture manipulation, which is awesomely powerful).
in very general terms are you famliar with 2DToolkit ? it is very widely used for 2D, and does everything in 1 drawcall
Haha, ohh, I didn't think about the texture resolution, It's at 128x128. That's probably a problem. Ill try messing with that a bit. The padding between the side walls of the bars is 3 pixels on all sides. Ill try and make the resolution smaller. Sad though because That's pretty limiting.
And as for the 2D toolkit, this is a 3D game and Im just drawing displays to the player in 2D (3D panel with 2D graphics on it). I assume that everything I'm drawing does it in one draw call as well. Thanks for the info though but I'll stick to writing this one myself.
for example notice my long article on "glyph designer and T$$anonymous$$" ... http://answers.unity3d.com/questions/384623/setting-font-size-according-to-screen-dpi.html?sort=oldest
regarding you mention type, i don't think there's a faster way to do type
regarding the specific images you posted of the three thermometers.
that should cause you no trouble whatsoever: you could use 2DT$$anonymous$$ (or just "some boxes" or just "some quads with color on them") and you could render that moving constantly at ultimate performance.
I'm confused why you are using SetPixels here.
it seems utterly irrelevant -- I would not use Set/GetPixels in any way to do anything like this, it's totally and completely different.
Just draw some white, gray and yellow planes. There are many ways to do it, all straightforward!
I suggest SetPixels was the totally wrong approach here. That is only used in extremely obscure situations, it has no connection to this, I'd say.
Hope it helps!
@waz -- I could easily do that at 20 million frames a second, using 2kx2k textures!
it's a good point his textures are probably TOO S$$anonymous$$ALL. but why use textures? just make a rectangle and color it. it could not be easier
I just don't know how clear one can be, coburn ...
Do not use SetPixels here. It is utterly and totally unrelated to what you are trying to do
Just to be crytsal clear. Are you familiar with using "localScale"?
For example ere is a superb answer :) regarding that ..
http://answers.unity3d.com/questions/432009/resizing-a-gameobject-based-on-mouse-position.html
it's that simple to make shapes like that. one line of code.
HOnestly to be crystal clear -- if you are using "SetPixels" IN ANY WAY for this it is totally totally wrong. What you are doing is incredibly simple, one or two lines of code.
Answer by Waz · Apr 30, 2013 at 12:17 PM
Either making the textures smaller (eg. 32x32 - still 1024 pixels to twiddle), or as an extension of the answers to the previously-closed question, don't use pixel manipulation, instead model that as a grey rectangle with a stretched yellow or white rectangle on top of it.
In my experience, pixel-manipulation is rarely a useful way to do anything (excluding shader-based RenderTexture manipulation, which is awesomely powerful).
(converted from comment)
Alright, I have two more questions if you can answer them? Can I display text using boxes? How would I draw boxes over other boxes? Wouldn't they z-fight?
@coburn, that's an excellent question -- the z fighting.
if what you mean is: you have the text (a mesh) and a background for it (let's call it "card") which would have to sit just "underneath" it
But you're swinging them around in 3D, so as you say could be z-fighting and similar issues.
personally I would just ensure the angle is always moderate, the distance from the camera is O$$anonymous$$, and a small gap works fine.
now you can cut the mesh in to the background , you can merge the mesh. that is fantastic IF IT DOES NOT CHANGE TOO OFTEN. ngui does things like this, which is why it can be slow
another approach is along these lines ..
Create a rende rtarget for all your visible cards. I.e. one big one for all the cards. Eg. if your cards are 60x100, and you have 6 visible at a time, create a 600x100 rendertexture.
Create a new camera just viewing this, and set up all your cards in 2D in there
Set the camera draw order to be smaller than your main camera.
In code, create a sprite collection at runtime using this, and create the sprites themselves (very easy with T$$anonymous$$2D say)
write a $$anonymous$$iscript to turn off rendering this rendertarget, and have some manual update to tell it the contents has changed.
the overhead will be constant (unlike building new mesh every time)
so you see it can be quite a tricky issue,
the dvil is really in the details and betyond this question, you would have to tell us about whether the text needs to change etc etc
ANOTHER WAY TO APPROACH THAT PROBLE$$anonymous$$ ...
use three cameras, actually all in identical position etc
one for your scene,
one for the gray background "card"
one for the red mesh type
in SO$$anonymous$$E (but not all) situations this, I think, would work well.
ie, the card+type would appear absolutely perfectly correct "in the scene" -- although you would not be able to have anything in front of it, as it would come to the front magically.
hope it helps!
@Cob, also note that depending on what you're doing. You can do a typical "9 part stretch" .. you know? that is a huge and typical solution to this sort of problem. it's incredibly handy. (again it's built-in to 2DT$$anonymous$$ and other similar products since everyone wants it)