I've read several articles on texture atlases that say one of the drawbacks is that a given texture inside cannot be tiled. But I just got it working with shaders. I wasn't sure if anyone else has done the same thing because I could not find any other topics posted here that related to the subject so I'm posting my code.
I created a 512x512 texture with 4 subtextures in it, each 256x256.
In the vertex shader I take the incoming uv coordinate and multiply it by 0.5. This puts it in the upper left corner of the image. Then in the fragment shader you simply offset it to the correct part of the entire texture. One thing to keep in mind is that for the upper left image, the maximum x coordinate should be (1 / image width) less than 0.5 and so should the maximum y value. This prevents color bleeding because of linear interpolation.
So here's the vertex shader:
varying vec2 uv_coords;
void main()
{
uv_coords = gl_MultiTexCoord0.st * 0.5;
gl_Position = ftransform();
}
And here's the fragment shader for sampling the subtexture in the upper left of the image.
uniform sampler2D texture;
varying vec2 uv_coords;
void main()
{
uv_coords = mod(uv_coords, 0.49903);
uv_coords.x += 0.5;
uv_coords.x = clamp(uv_coords.x, 0.50093, 1.0);
vec4 color = texture2D(texture, uv_coords);
gl_FragColor = color;
}
And here's the fragment shader if you wanted to sample the subtexture in the upper right.
uniform sampler2D texture;
varying vec2 uv_coords;
void main()
{
uv_coords = mod(uv_coords, 0.49903);
uv_coords.x += 0.5;
uv_coords.x = clamp(uv_coords.x, 0.50093, 1.0);
uv_coords.y = clamp(uv_coords.y, 0.0, 0.49903);
vec4 color = texture2D(texture, uv_coords);
gl_FragColor = color;
}
Its pretty much the same for the bottom 2 subtextures.
I found that this only works with linear filtering and does show color bleeding when used with mipmaps. But I think its ideal for packing, lets say, detail textures into a single large image. That way you could apply several detail textures to say a terrain all in texture unit and leave the other units open to other texture bindings.
Granted I've only run this on a single tiled textured quad so I don't know what the performance implications are. I just wanted to know if anyone else had experimented with something like this and what their results were.
But in my case, I was rendering terrain in my engine with multiple passes. One pass for the base texture and lightmap then several more passes for each group of 3 detail textures and their alpha maps.
But now in a single pass, I'm combining a base texture and lightmap into a single image. Then up to 8 detail textures in a single image and their assoicated alphamaps in the remaining 2 texture units. (2 x RGBA = 8 alpha maps)
And all this can be done in 1 pass with 4 texture units.