Hey all, I just need to ask quick, I'm working on an iPhone game using most likely 'Shiva' or 'Unity' and I'm making some railings for snowboards ect to grind on and whatnot.
I've modelled the railings into 2m long 'blocks' and each block has a different shape, this is so I can combine these different small blocks to get a wide variety of different railings.
Now, should each Individual block have its own small texture? If so how big? 128? 64? Or should all the blocks be thrown onto one larger texture? 512? 1024?
Replies
god, that's convoluted....
ex. 1 1024^2 map is more efficient than 4 512^2 maps, even tho the amount of texture space is technically the same..
as far as what size you should use would depend primarily(not completely) on the distance it's going to be viewed from most of the time.(i.e. how big is it going to be on the screen)
http://en.wikipedia.org/wiki/Texture_atlas
http://www.gamasutra.com/features/20060126/ivanov_01.shtml
and it usually not only saves bandwidth but also performance because there are less objects to loop through and probably some other technical reasons.
I am working on a maxscript myself soon that transfers textures via RTT from many objects into 1 big atlas texture. Alternatively there should be already some interesting scripts from Nvidia and on Scriptspot.com for max.
When renderers actually get to the part where they start drawing stuff (after deciding what needs to be drawn) the process involves looping through the materials and drawing everything that uses that material.
To change a material means grinding everything to a halt, and then reading in a new texture and any shader programs / misc material settings to go with it, and then starting everything up again, sending a new batch of vertices. This is often the slowest part of rendering. It takes much longer to do all that, then it would have taken just to keep rendering triangles. If there are no materials to change, you can go ahead and send everything in one batch.
After that stage, the transparent surfaces have to be drawn. They need to be sorted and drawn from furthest to nearest, regardless of what material they use. Which means that for every transparent surface drawn, a state change will have to occur. Expensive!
Any time you can batch materials up into one sheet, do it.
Also, anytime you can keep all your textures the same size, do that too. Because it's a lot faster and easier to just upload one texture over top of one already in memory than it is to erase the old one, reclaim that chunk of memory, and then upload the new one that is a different size, causing vram fragmentation.
That's why some people will standardize to one texture sheet size. When it comes time to change what textures are loaded, it's simply a matter of overwriting all the ones that now unused. If each level is known more than 20 512x512 sheets, then you just need to allocate that big block once. There is no need to keep managing memory and making a mess of it.
You need to be wise on how you assign materials.
For example, bunching texture's (atlas) isn't always the best route ::
Object A, B, and C all have the same texture, but only B is visible, thus, the WHOLE texture atlas is sent through your bus and kept in memory. I don't know how intelligent the IPhone's graphic driver is (telling by their openGL support, not very).
Hope that told the other side of the coin well - best to you!
Your atlas is going to have more than 3 objects on it, and usually it will have all objects on it. So you only send upload the atlas once and then don't have to keep binding it.
Even if you have a few atlases and bind them all once each frame, the cost of those will stay constant, regardless of how many objects are visible each frame. (as opposed to wildly fluctuating render times on a per frame basis).
I'd rather load the same texture each frame and draw a variable number of objects then have a bunch of logic to figure out a series of states changes which would be slower anyways.
The other case would be a bit over engineered for no real gain.
I'd say it depends on your platform and engine pipeline, ultimately.
These days with the current consoles though, I think most engines would be good with larger sheets or atlas'.
On Forza 3 we used lots of textures but IIRC they were atlas'd by the engine.
I think the PS2 only did hardware accelerated triangle rasterising, while the vertices were transformed and lit in software. So throwing around textures wouldn't be as much of a bottleneck as they are on modern GPU designs.
The iphone is running an OpenGl 2.0 compatible PowerVR GL Chip, which is a bit different in the different models.
The 360/PS3 are running similar ATI and nVidia GPUs.
Programming them is pretty similar other than tweaking for memory and speed.
An engine doesn't have much say in that stuff these days, as it's mostly a collection of code that organizes how stuff is fed to the GPU. Culling, batch organizing, etc... And then it's simple a matter of calling the only functions in the API that send vertices to be drawn.
With current GPU tech, drawing a whole scene from an atlas will always be faster than swapping out textures. But the best size for the atlas will be different from GPU to GPU, as they have their own max texture sizes. Having it all on one material also helps counter the problems of having small batches, which can also be slow in some situations.
I wish stuff like that would standardize for a decade at a time, so these conversations wouldn't have to be filled with vaguerities. Vaguerities is a word right? Fuck it, I'm making it a word if it's isn't one already. Get Webster on it.
Just one extra thing. For Atlases to work, your texture coordinates need to all be within the 0-1 range.
Currently Im almost entirely blowing all my environment UVs well beyond the 1:1 square in order to tile parts of the texture... is this totally incompatable with atlas style textures? How is tiling dealt with in this situation?
If you have 100 textures that all go from 0-1, you can tile them 10x10 on an atlas, and all the texture coords just get changed based on it's textures position in the new grid. The first one is 0-0.1, the second is 0.1-0.2, etc...
You can't do that with tiled textures because, obviously, you can't go beyond their borders, because then you've gone into a new texture's space.
There is nothing 'special' about an atlas texture from the eyes of a GPU. It's just one big sheet that gets loaded at once to cut down on the cost of changing states.
But for older pipeline, ie iphone you wouldnt have that possibility. But for unique stuff nearly all platforms these days would favor an atlas, for the reasons Daark mentioned (stall,state change).
I wrote some long winded post about state changes somewhere around here. :poly136:
The GPU works like a factory. You tweak a few settings and then turn the machines on. They crunch away at tons of vertices simultaneously. But then as soon as you need to change the states, you have to shut down the factory and tweak all the dials on the machinery.
Changing states is actually very fast, it's just the longest operation to complete, and nothing else is getting done while they change. So all real time renderers look to change states as few times as possible.