diff options
author | Perttu Ahola <celeron55@gmail.com> | 2012-04-07 23:22:02 +0300 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2012-04-07 23:37:12 +0300 |
commit | 1b078efd5fe3a80011339f90df06e5f55fdbadf3 (patch) | |
tree | 9567556d2c3f0d58be14472c212062bca47e8b7f | |
parent | e8e73d37fb1834208dabac207593030b87db135a (diff) | |
download | minetest-1b078efd5fe3a80011339f90df06e5f55fdbadf3.tar.gz minetest-1b078efd5fe3a80011339f90df06e5f55fdbadf3.tar.bz2 minetest-1b078efd5fe3a80011339f90df06e5f55fdbadf3.zip |
Improve texture atlas generation
-rw-r--r-- | src/tile.cpp | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/src/tile.cpp b/src/tile.cpp index 73c286fb3..9497c4ca9 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -830,7 +830,10 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) JMutexAutoLock lock(m_atlaspointer_cache_mutex); // Create an image of the right size - core::dimension2d<u32> atlas_dim(1024,1024); + core::dimension2d<u32> max_dim = driver->getMaxTextureSize(); + core::dimension2d<u32> atlas_dim(2048,2048); + atlas_dim.Width = MYMIN(atlas_dim.Width, max_dim.Width); + atlas_dim.Height = MYMIN(atlas_dim.Height, max_dim.Height); video::IImage *atlas_img = driver->createImage(video::ECF_A8R8G8B8, atlas_dim); //assert(atlas_img); @@ -871,16 +874,17 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) infostream<<std::endl; // Padding to disallow texture bleeding + // (16 needed if mipmapping is used; otherwise less will work too) s32 padding = 16; - - s32 column_width = 256; s32 column_padding = 16; + s32 column_width = 256; // Space for 16 pieces of 16x16 textures /* First pass: generate almost everything */ core::position2d<s32> pos_in_atlas(0,0); + pos_in_atlas.X = column_padding; pos_in_atlas.Y = padding; for(core::map<std::string, bool>::Iterator @@ -901,8 +905,8 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) core::dimension2d<u32> dim = img2->getDimension(); - // Don't add to atlas if image is large - core::dimension2d<u32> max_size_in_atlas(32,32); + // Don't add to atlas if image is too large + core::dimension2d<u32> max_size_in_atlas(64,64); if(dim.Width > max_size_in_atlas.Width || dim.Height > max_size_in_atlas.Height) { @@ -914,14 +918,14 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) // Wrap columns and stop making atlas if atlas is full if(pos_in_atlas.Y + dim.Height > atlas_dim.Height) { - if(pos_in_atlas.X > (s32)atlas_dim.Width - 256 - padding){ + if(pos_in_atlas.X > (s32)atlas_dim.Width - column_width - column_padding){ errorstream<<"TextureSource::buildMainAtlas(): " <<"Atlas is full, not adding more textures." <<std::endl; break; } pos_in_atlas.Y = padding; - pos_in_atlas.X += column_width + column_padding; + pos_in_atlas.X += column_width + column_padding*2; } /*infostream<<"TextureSource::buildMainAtlas(): Adding \""<<name @@ -967,6 +971,29 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) atlas_img->setPixel(x,dst_y,c); } + for(u32 side=0; side<2; side++) // left and right + for(s32 x0=0; x0<column_padding; x0++) + for(s32 y0=-padding; y0<(s32)dim.Height+padding; y0++) + { + s32 dst_x; + s32 src_x; + if(side==0) + { + dst_x = x0 + pos_in_atlas.X + dim.Width*xwise_tiling; + src_x = pos_in_atlas.X + dim.Width*xwise_tiling - 1; + } + else + { + dst_x = -x0 + pos_in_atlas.X-1; + src_x = pos_in_atlas.X; + } + s32 y = y0 + pos_in_atlas.Y; + s32 src_y = MYMAX(pos_in_atlas.Y, MYMIN(pos_in_atlas.Y + dim.Height - 1, y)); + s32 dst_y = y; + video::SColor c = atlas_img->getPixel(src_x, src_y); + atlas_img->setPixel(dst_x,dst_y,c); + } + img2->drop(); /* |