1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-08-11 17:51:04 +00:00

work-in-progress texture atlas optimization

This commit is contained in:
Perttu Ahola 2011-02-10 02:13:03 +02:00
parent 949383a2f7
commit 1704badc30
21 changed files with 1496 additions and 271 deletions

View file

@ -273,13 +273,32 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p,
video::SColor c = video::SColor(alpha,li,li,li);
face.vertices[0] = video::S3DVertex(vertex_pos[0], zerovector, c,
core::vector2d<f32>(0,1));
face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c,
core::vector2d<f32>(abs_scale,1));
face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c,
core::vector2d<f32>(0,1));
face.vertices[2] = video::S3DVertex(vertex_pos[2], zerovector, c,
core::vector2d<f32>(abs_scale,0));
face.vertices[3] = video::S3DVertex(vertex_pos[3], zerovector, c,
core::vector2d<f32>(0,0));
face.vertices[3] = video::S3DVertex(vertex_pos[3], zerovector, c,
core::vector2d<f32>(abs_scale,0));
/*float x0 = (float)tile.tx/256.0;
float y0 = (float)tile.ty/256.0;
float w = ((float)tile.tw + 1.0)/256.0;
float h = ((float)tile.th + 1.0)/256.0;*/
float x0 = tile.texture.pos.X;
float y0 = tile.texture.pos.Y;
float w = tile.texture.size.X;
float h = tile.texture.size.Y;
face.vertices[0] = video::S3DVertex(vertex_pos[0], zerovector, c,
core::vector2d<f32>(x0+w*abs_scale, y0+h));
face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c,
core::vector2d<f32>(x0, y0+h));
face.vertices[2] = video::S3DVertex(vertex_pos[2], zerovector, c,
core::vector2d<f32>(x0, y0));
face.vertices[3] = video::S3DVertex(vertex_pos[3], zerovector, c,
core::vector2d<f32>(x0+w*abs_scale, y0));
face.tile = tile;
//DEBUG
@ -318,11 +337,26 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
}
if(mod.type == NODEMOD_CRACK)
{
/*
Get texture id, translate it to name, append stuff to
name, get texture id
*/
// Get original texture name
u32 orig_id = spec.texture.id;
std::string orig_name = g_texturesource->getTextureName(orig_id);
// Create new texture name
std::ostringstream os;
os<<"[crack"<<mod.param;
textureid_t tid = g_irrlicht->getTextureId(os.str());
spec.spec.addTid(tid);
os<<orig_name<<"^[crack"<<mod.param;
//os<<orig_name<<"^[progressbar0.5";
//os<<"mese.png";
// Get new texture
u32 new_id = g_texturesource->getTextureId(os.str());
dstream<<"MapBlock::getNodeTile(): Switching from "
<<orig_name<<" to "<<os.str()<<" ("
<<orig_id<<" to "<<new_id<<")"<<std::endl;
spec.texture = g_texturesource->getTexture(new_id);
}
}
@ -406,7 +440,9 @@ void MapBlock::updateFastFaceRow(
TileSpec tile0_next;
TileSpec tile1_next;
u8 light_next = 0;
// If at last position, there is nothing to compare to and
// the face must be drawn anyway
if(j != length - 1)
{
p_next = p + translate_dir;
@ -426,7 +462,31 @@ void MapBlock::updateFastFaceRow(
continuous_tiles_count++;
if(next_is_different)
// This is set to true if the texture doesn't allow more tiling
bool end_of_texture = false;
/*
If there is no texture, it can be tiled infinitely.
If tiled==0, it means the texture can be tiled infinitely.
Otherwise check tiled agains continuous_tiles_count.
This check has to be made for both tiles, because this is
a bit hackish and we know which one we're using only when
the decision to make the faces is made.
*/
if(tile0.texture.atlas != NULL && tile0.texture.tiled != 0)
{
if(tile0.texture.tiled <= continuous_tiles_count)
end_of_texture = true;
}
if(tile1.texture.atlas != NULL && tile1.texture.tiled != 0)
{
if(tile1.texture.tiled <= continuous_tiles_count)
end_of_texture = true;
}
//end_of_texture = true; //DEBUG
if(next_is_different || end_of_texture)
{
/*
Create a face if there should be one
@ -684,10 +744,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
Convert FastFaces to SMesh
*/
scene::SMesh *mesh_new = NULL;
mesh_new = new scene::SMesh();
MeshCollector collector;
if(fastfaces_new.size() > 0)
@ -708,8 +764,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
FastFace &f = fastfaces_new[i];
const u16 indices[] = {0,1,2,2,3,0};
video::ITexture *texture = g_irrlicht->getTexture(f.tile.spec);
//video::ITexture *texture = g_irrlicht->getTexture(f.tile.spec);
video::ITexture *texture = f.tile.texture.atlas;
if(texture == NULL)
continue;
@ -717,11 +774,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
f.tile.applyMaterialOptions(material);
/*if(f.tile.alpha != 255)
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
else
material.MaterialType = video::EMT_SOLID;*/
collector.append(material, f.vertices, 4, indices, 6);
}
}
@ -742,7 +794,11 @@ void MapBlock::updateMesh(u32 daynight_ratio)
material_water1.setFlag(video::EMF_BILINEAR_FILTER, false);
material_water1.setFlag(video::EMF_FOG_ENABLE, true);
material_water1.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
material_water1.setTexture(0, g_irrlicht->getTexture("water.png"));
//TODO
//material_water1.setTexture(0, g_irrlicht->getTexture("water.png"));
AtlasPointer pa_water1 = g_texturesource->getTexture(
g_texturesource->getTextureId("water.png"));
material_water1.setTexture(0, pa_water1.atlas);
// New-style leaves material
video::SMaterial material_leaves1;
@ -751,7 +807,11 @@ void MapBlock::updateMesh(u32 daynight_ratio)
material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
material_leaves1.setTexture(0, g_irrlicht->getTexture("leaves.png"));
//TODO
//material_leaves1.setTexture(0, g_irrlicht->getTexture("leaves.png"));
AtlasPointer pa_leaves1 = g_texturesource->getTexture(
g_texturesource->getTextureId("leaves.png"));
material_leaves1.setTexture(0, pa_leaves1.atlas);
for(s16 z=0; z<MAP_BLOCKSIZE; z++)
for(s16 y=0; y<MAP_BLOCKSIZE; y++)
@ -804,7 +864,8 @@ void MapBlock::updateMesh(u32 daynight_ratio)
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
material.MaterialType
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
if(dir == v3s16(0,-1,0))
//TODO
/*if(dir == v3s16(0,-1,0))
material.setTexture(0,
g_irrlicht->getTexture("torch_on_floor.png"));
else if(dir == v3s16(0,1,0))
@ -816,7 +877,7 @@ void MapBlock::updateMesh(u32 daynight_ratio)
g_irrlicht->getTexture("torch_on_floor.png"));
else
material.setTexture(0,
g_irrlicht->getTexture("torch.png"));
g_irrlicht->getTexture("torch.png"));*/
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
@ -974,14 +1035,18 @@ void MapBlock::updateMesh(u32 daynight_ratio)
video::S3DVertex vertices[4] =
{
/*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
/*video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y1()),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y0()),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y0()),
};
/*
@ -1048,10 +1113,18 @@ void MapBlock::updateMesh(u32 daynight_ratio)
{
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
/*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y1()),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y0()),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y0()),
};
for(s32 i=0; i<4; i++)
@ -1092,10 +1165,18 @@ void MapBlock::updateMesh(u32 daynight_ratio)
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
/*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y1()),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_water1.x1(), pa_water1.y0()),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_water1.x0(), pa_water1.y0()),
};
for(s32 i=0; i<4; i++)
@ -1120,10 +1201,18 @@ void MapBlock::updateMesh(u32 daynight_ratio)
{
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
/*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
pa_leaves1.x0(), pa_leaves1.y1()),
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
pa_leaves1.x1(), pa_leaves1.y1()),
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c,
pa_leaves1.x1(), pa_leaves1.y0()),
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
pa_leaves1.x0(), pa_leaves1.y0()),
};
if(j == 0)
@ -1173,6 +1262,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
Add stuff from collector to mesh
*/
scene::SMesh *mesh_new = NULL;
mesh_new = new scene::SMesh();
collector.fillMesh(mesh_new);
/*
@ -1191,13 +1283,25 @@ void MapBlock::updateMesh(u32 daynight_ratio)
mesh_new = NULL;
}
// Use VBO for mesh (this just would set this for ever buffer)
// This will lead to infinite memory usage because or irrlicht.
//mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
/*std::cout<<"MapBlock has "<<fastfaces_new.size()<<" faces "
<<"and uses "<<mesh_new->getMeshBufferCount()
<<" materials (meshbuffers)"<<std::endl;*/
if(mesh_new)
{
#if 0
// Usually 1-700 faces and 1-7 materials
std::cout<<"Updated MapBlock has "<<fastfaces_new.size()<<" faces "
<<"and uses "<<mesh_new->getMeshBufferCount()
<<" materials (meshbuffers)"<<std::endl;
#endif
// Use VBO for mesh (this just would set this for ever buffer)
// This will lead to infinite memory usage because or irrlicht.
//mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
/*
NOTE: If that is enabled, some kind of a queue to the main
thread should be made which would call irrlicht to delete
the hardware buffer and then delete the mesh
*/
}
/*
Replace the mesh