Tiling textures within an atlas? Possible?

If one has tileable textures, and wants to take advantage of batching by putting them on an atlas (say 8 x 256 on a 1024) - Can you make your UV’s tile over a small section of that atlas in Blender? To tile the UVs with one single image/material is easy, but I’m not sure if you can tile using a section of an image/material.

Can you?

To tile you basically need the texture to extend from one edge of the texture atlas to the opposite. Which means that you can tile on one direction and have strips of long tiling textures. They would have to be laid out as strips that tile across their length.

Could be used for some things.

The only other method I can think of is to slice your mesh into tiling sections, similar to per face mapping which does essentially the same thing. It’s not very efficient or practical on anything but the simplest geometry so probably not what you wanted to hear.

Unfortunately, that’s what I thought.

Regular structures ( like wall panels ) I can “tile” by hand, but there are enough irregular shapes in most designs where that’s not possible without creating way too much geometry if I had to make one face per “tile” by hand. Oh well. Guess I’ll have to keep watching that balance between design and practicality…

(You’d think that if it works tiling from 0 - 255, you could tile from 256-511…)

This s a flat plane being tiled 4x4 however as long as the geometry is the same and the UV’s the same you should be able to tile a section of an Atlas.

Below shows a 512x512 Atlas with only the grass section of the Atlas being used and tiled on my geometry 16 times.

The bottom of the image is the scene played back in Unity. You have to have MIP maps turned off though.

How do you set up the UVs for that?

Here’s a test example I was working with:

The walls are hand placed UV’s from a texture atlas, but the floor and dirt pile are tiled textures that are stand-alone. How would I set up the UV’s (in Blender in my case) so it would pull from part the the same atlas as the wall?

(And I assume that the mip maps would cause edging if you left them on…)

Yeah thats what I meant by face mapping. It works well so long as you have fairly simple geometry.

Ah sorry, I mis-understood your real issue of the irregular poly shapes.

Yes you can do atlas tiling WITHOUT faking it with repeating geometry.

There are “currently” some restrictions.

  1. unless the textures on your atlas have similar boundaries you will have to use point filtering.
  2. when using point filtering, your textures have to have laser accurate boundaries, not so much as a pixel width off of any edge.
  3. You will have to get a special mip map generator specifically made for texture atlases, or create your own, so that there is ZERO bleed over
  4. You will have to use the dds format for your textures so that Unity does not “process” them (causing bleed over)
  5. to batch effectively…you need to use vert colors to mark what tri’s get what part of the atlas
  6. Last but not least…you need a custom shader to handle the tiling.

It’s basic math really, when the shader processes the pixels…it goes through each pixel used from your textures one pixel at a time.

It gets ONE UV coordinate from where the pixel “should” be found, remember…it’s one pixel at a time that gets fetched from the atlas(all shaders do this)
So the trick is…to have to tell the shader…if the coordinate is outside your desired region, to “roll” the value.

let’s say we’re talking about a texture atlas that is 256x256 right?
And lets say it’s a 2x2 atlas right?
ok, so if you want the top left texture, then valid uv’s are 0 to 0 .5 for u, and 1 to .5 for v (y space is inverted, zero is at the bottom)

…O <-current pixel U = 39.9, V = 18.2

<-------------- U ------------->
0,1’‘’‘’‘’‘’‘’‘’‘’‘’’ .5,1 ‘’‘’‘’‘’‘’‘’‘’‘’‘’ 1,1
|xxxxxxxxxx|…|
|xxxxxxxxxx|…|
|xxxxxxxxxx|…|
|xxxxxxxxxx|…|
0,.5’‘’‘’‘’‘’‘’‘’‘’‘’’ .5,.5’‘’‘’‘’‘’‘’‘’‘’‘’’ 1,.5…V
|…|…|
|…|…|
|…|…|
|…|…|
0,0 ‘’‘’‘’‘’‘’‘’‘’‘’‘’ .5,0’‘’‘’‘’‘’‘’‘’‘’‘’’ 1,0

So you want to “MOD” the U value of you uv’s from 0 to .5
and you want to “MOD” your V value of your uv’s from .5 to 1

so…let’s say your shader is drawing a tri you made in a modeling package

…and you tiled the f#$k out of your uvs…

the current pixel its trying to fetch is way outside of normalized texture boundaries…

like say U = 39.9, V = 18.2 …way way way off of the sheet

if you “modulo” the coordinate by your atlas cell width you get your new u coordinate
39.9 mod 0.5 = 0.4

the modulo instruction gets the remainder of a division before resulting to a fraction.

and lucky for us shaders do support a mod instruction or this would be very messy stuff
mod the V coordinate by .5 too ( if it was 18.2, then it would be .2 right?)
because 18.2 mod 0.5 = 0.2

so this pixel that was supposed to be fetched from your atlas at 39.9,18.2 is now going to be fetched from 0.4, 0.2

All you have to do now is offset these coordinates by the atlas offset for U and V

which if we want the top left…
we add 0.0 to u (no offset required in this case but we’re making a formula so we have to add something even if we’re adding nothing, a zero
we add 0.5 for V, because the top left texture starts half way up the V axis

in shorthand…

U = meshUV.U //UV coords for EACH pixel, remember, fragments get processed ONE pixel at a time
V = meshUV.V
tileScale = 0.5 // the width of each tile

// use vert colors to mark every tri for where it uses which part of the atlas as an offset
// vert colors have valid values from 0.0 to 1.0 for RGB&A
UOffset = vertColor.R // the horizontal offset from the left edge of the atlas
VOffest = vertColor.G // the vertical offset from the bottom of the atlas

newU = U mod tileScale
newU += UOffset

newV = V mod tileScale
newV += VOffset

I know this works because I am doing it, can’t release my code for legal reasons, but I can discuss the method I use.

1 Like

Do we have full support for FP3.0 in our shaders?
It would be extremely beneficial to have it…
ULTRA ULTRA ULTRA cheap, fast and extremely efficient.

I would buy Unity 4 JUST for this if it fully supported these inputs and outputs…

COLOR Input primary color
COLOR0
COL
COL0

COLOR1 Input secondary color
COL1

TEX0 Input texture coordinate sets 0
TEXCOORD0

TEX1 Input texture coordinate sets 1
TEXCOORD1

TEX2 Input texture coordinate sets 2
TEXCOORD2

TEX3 Input texture coordinate sets 3
TEXCOORD3

TEX4 Input texture coordinate sets 4
TEXCOORD4

TEX5 Input texture coordinate sets 5
TEXCOORD5

TEX6 Input texture coordinate sets 6
TEXCOORD6

TEX7 Input texture coordinate sets 7
TEXCOORD7

FOGP Input fog color (XYZ) and factor (W)
FOG

Uniform Input Semantics

Sixteen texture units are supported:

Binding Semantic Name Corresponding Data

TEXUNIT0 Texture unit 0
TEXUNIT1 Texture unit 1

TEXUNIT15 Texture unit 15

It should be possible to tile within the vertex shader at a decent speed.

  • just did a quick google… it is:

http://www.ogre3d.org/forums/viewtopic.php?f=1&t=70650

Although you probably would have less headache relying on dynamic batching :slight_smile:

That should work, indeed, but that means we have a different Shader for each texture within our texture atlas. That means a different material to use a different shader for each texture, right?

So… For, say 30 texture, with this solution we have
30 materials, each with a different shader, all with the same texture atlas.
I don’t think it is more optimized than having
30 materials, each with a different shader, each with a different texture.

Because, from what I’ve read, it’s the number of materials that has a high impact on draw calls :confused:

Any better solution nowadays? This thread is 4 years old !

You should be able to bypass that limitation by assigning the “texture” bounds via MaterialParamBlock! All objects would have the same material and be statically batcheable.