Still verrry simple
uniform vec2 Tile; // Tile size. Range 0.01 to 1.0
uniform vec2 Shift; // Shift tile. Range 0.0 > 1.0
uniform sampler2D Texture; // Texture input
void main()
{
// Fragment coords
vec2 xy = gl_TexCoord[0].xy;
// Tile coords
vec2 phase = fract(xy / Tile) + Shift;
// Wrap tile position
if (phase.x > 1.0)
phase.x = phase.x - 1.0;
if (phase.y > 1.0)
phase.y = phase.y - 1.0;
// Multiply color by texture
vec4 outColor = gl_Color * texture2D(Texture, phase);
// Discard transparent fragments
if (outColor.a == 0.0)
discard;
// Output fragment color
gl_FragColor = outColor;
}
If you plan to implement this shader, you may want to limit to tile dimensions to whole-number divisions of 1.0 (ie 0.5, 0.3333333, 0.25 etc.), so you don’t get partial rows/columns. This is especially true if you’re applying the texture to anything other than a plane, as otherwise it won’t wrap properly.
You can delete the discard conditional if you’re not interested in using textures with transparency. Discarding transparent fragments seems to help with z-fighting issues, and might marginally help performance, so I stuck it in there too.