Hey guys,
I came up with a terrain multitexturing technique that works great but it doesn’t run fast enough on intel / older graphics cards. I don’t know if there’s anything I can really do about this. My game runs at 60fps on my ATI card but will hover at around 8-10fps on my intel HD 4000. I was wondering if anyone could look at my technique / GLSL code and see if there’s anything significant I could do to improve it?
My other solution is to just have an option to disable multitexturing on slower PCs, where they would instead just use a single texture with coloured polygons. This kind of sucks because the map/level will look a lot worse but maybe it’s the only other way.
Because of some PC’s only supporting 4 texture units, instead I am using a 2048x2048 “virtual texture” (See image below)
This allows me to have as many textures as I want (up to 32) as long as they fit inside the virtual texture (as “tiles” like in a spritesheet), with a maximum of 4 textures blended per pixel.
My technique requires 4 textures.
- Colour map (just for painting colours on the terrain, omitted from the code)
- Virtual texture (described above)
- Tile map (contains 4 tiles for each pixel) where R=0 is tile 0, R = 1 is tile 1, up to 32. EG. RGBA=(0,1,2,3) will be the first 4 tiles
- Mix map (contains opacity of the 4 tile textures for each pixel, for blending them together)
I also pass an array of tiles (x,y,width,height) so that I can calculate the location on the virtual texture for each pixel.
I send 2 sets of UV coords to the shader, worldUV is the true polygon UV coordinates, mixmapUV is the polygon’s UV coordinates relative to the map bounds (from 0 to 1).
I multiply the UV coordinates by the tile size so that smaller textures don’t repeat more than larger (higher quality) textures.
If something isn’t clear please let me know!
uniform vec4 tiles[MAX_MAP_TEXTURES]; //contains the x,y,width,height of each tile in the virtual texture
uniform sampler2D tileTexture; //contains 4 texture indexes used to get the texture tile from the virtual texture
uniform sampler2D virtualTexture; //2048x2048 packed texture containing all individual terrain textures
uniform sampler2D mixmapTexture; //contains opacity to blend a maximum of 4 textures together
vec4 calculateColour(vec2 worldUV, vec2 mixmapUV)
{
vec4 textureLocations = texture2D(tileTexture, mixmapUV);
vec4 mixmapColour = texture2D(mixmapTexture, mixmapUV);
vec4 finalColour = vec4(0.0,0.0,0.0,1.0);
for(int i=0;i<4;i++)
{
int tileLoc = int(textureLocations[i]*256.0);
vec4 tile = tiles[tileLoc];
float minTextureSize = min(tile.p, tile.q);
vec2 wrapped = vec2(tile.s + abs(mod(worldUV.x * minTextureSize, tile.p)), tile.t + abs(mod(worldUV.y * minTextureSize, tile.q)));
textureColours[i] = texture2D(virtualTexture, wrapped);
finalColour.rgb = mix(finalColour.rgb, textureColours[i].rgb, mixmapColour[i]);
}
return finalColour;
}