Yes you can do atlas tiling WITHOUT faking it with repeating geometry.
There are “currently” some restrictions.
- unless the textures on your atlas have similar boundaries you will have to use point filtering.
- when using point filtering, your textures have to have laser accurate boundaries, not so much as a pixel width off of any edge.
- 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
- You will have to use the dds format for your textures so that Unity does not “process” them (causing bleed over)
- to batch effectively…you need to use vert colors to mark what tri’s get what part of the atlas
- 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.