diff --git a/src/client.cpp b/src/client.cpp index 2dc537782b0d..ed5ff96fefad 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -263,6 +263,9 @@ Client::Client( m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); m_cache_enable_shaders = g_settings->getBool("enable_shaders"); + m_cache_use_tangent_vertices = m_cache_enable_shaders && ( + g_settings->getBool("enable_bumpmapping") || + g_settings->getBool("enable_parallax_occlusion")); } void Client::Stop() @@ -1582,7 +1585,8 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent) Create a task to update the mesh of the block */ - MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders); + MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders, + m_cache_use_tangent_vertices); { //TimeTaker timer("data fill"); diff --git a/src/client.h b/src/client.h index 98a8bc12970c..c16e9b77aee6 100644 --- a/src/client.h +++ b/src/client.h @@ -677,6 +677,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef // TODO: Add callback to update these when g_settings changes bool m_cache_smooth_lighting; bool m_cache_enable_shaders; + bool m_cache_use_tangent_vertices; DISABLE_CLASS_COPY(Client); }; diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index 9486220e0138..8b3d3c0dd1f8 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -33,24 +33,26 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/directiontables.h" #include -static void applyFacesShading(video::SColor& color, float factor) +static void applyFacesShading(video::SColor &color, const float factor) { - color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255)); - color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255)); + color.setRed(core::clamp(core::round32(color.getRed() * factor), 0, 255)); + color.setGreen(core::clamp(core::round32(color.getGreen() * factor), 0, 255)); } /* MeshMakeData */ -MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders): +MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders, + bool use_tangent_vertices): m_vmanip(), m_blockpos(-1337,-1337,-1337), m_crack_pos_relative(-1337, -1337, -1337), m_smooth_lighting(false), m_show_hud(false), m_gamedef(gamedef), - m_use_shaders(use_shaders) + m_use_shaders(use_shaders), + m_use_tangent_vertices(use_tangent_vertices) {} void MeshMakeData::fill(MapBlock *block) @@ -1032,6 +1034,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): m_daynight_diffs() { m_enable_shaders = data->m_use_shaders; + m_use_tangent_vertices = data->m_use_tangent_vertices; if (g_settings->getBool("enable_minimap")) { m_minimap_mapblock = new MinimapMapblock; @@ -1064,15 +1067,14 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): Convert FastFaces to MeshCollector */ - MeshCollector collector; + MeshCollector collector(m_use_tangent_vertices); { // avg 0ms (100ms spikes when loading textures the first time) // (NOTE: probably outdated) //TimeTaker timer2("MeshCollector building"); - for(u32 i=0; iColor; - if (!vc.getBlue()) { - if (vertex->Normal.Y < -0.5) { - applyFacesShading (vc, 0.447213); - } else if (vertex->Normal.X > 0.5) { - applyFacesShading (vc, 0.670820); - } else if (vertex->Normal.X < -0.5) { - applyFacesShading (vc, 0.670820); - } else if (vertex->Normal.Z > 0.5) { - applyFacesShading (vc, 0.836660); - } else if (vertex->Normal.Z < -0.5) { - applyFacesShading (vc, 0.836660); + if (!vc->getBlue()) { + if (Normal->Y < -0.5) { + applyFacesShading(*vc, 0.447213); + } else if (Normal->X > 0.5) { + applyFacesShading(*vc, 0.670820); + } else if (Normal->X < -0.5) { + applyFacesShading(*vc, 0.670820); + } else if (Normal->Z > 0.5) { + applyFacesShading(*vc, 0.836660); + } else if (Normal->Z < -0.5) { + applyFacesShading(*vc, 0.836660); } } - if(!m_enable_shaders) - { + if (!m_enable_shaders) { // - Classic lighting (shaders handle this by themselves) // Set initial real color and store for later updates - u8 day = vc.getRed(); - u8 night = vc.getGreen(); - finalColorBlend(vc, day, night, 1000); - if(day != night) + u8 day = vc->getRed(); + u8 night = vc->getGreen(); + finalColorBlend(*vc, day, night, 1000); + if (day != night) { m_daynight_diffs[i][j] = std::make_pair(day, night); + } } } @@ -1201,34 +1211,46 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): p.tile.applyMaterialOptions(material); } - // Create meshbuffer - scene::SMeshBuffer *buf = new scene::SMeshBuffer(); - // Set material - buf->Material = material; - // Add to mesh - scene::SMesh *mesh = (scene::SMesh *)m_mesh; - mesh->addMeshBuffer(buf); - // Mesh grabbed it - buf->drop(); - buf->append(&p.vertices[0], p.vertices.size(), - &p.indices[0], p.indices.size()); -} - m_camera_offset = camera_offset; + scene::SMesh *mesh = (scene::SMesh *)m_mesh; + + // Create meshbuffer, add to mesh + if (m_use_tangent_vertices) { + scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents(); + // Set material + buf->Material = material; + // Add to mesh + mesh->addMeshBuffer(buf); + // Mesh grabbed it + buf->drop(); + buf->append(&p.tangent_vertices[0], p.tangent_vertices.size(), + &p.indices[0], p.indices.size()); + } else { + scene::SMeshBuffer *buf = new scene::SMeshBuffer(); + // Set material + buf->Material = material; + // Add to mesh + mesh->addMeshBuffer(buf); + // Mesh grabbed it + buf->drop(); + buf->append(&p.vertices[0], p.vertices.size(), + &p.indices[0], p.indices.size()); + } + } /* Do some stuff to the mesh */ + m_camera_offset = camera_offset; + translateMesh(m_mesh, + intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS)); - translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS)); - - if (m_enable_shaders) { - scene::IMeshManipulator* meshmanip = m_gamedef->getSceneManager()->getMeshManipulator(); - scene::IMesh* tangentMesh = meshmanip->createMeshWithTangents(m_mesh); - m_mesh->drop(); - m_mesh = tangentMesh; + if (m_use_tangent_vertices) { + scene::IMeshManipulator* meshmanip = + m_gamedef->getSceneManager()->getMeshManipulator(); + meshmanip->recalculateTangents(m_mesh, true, false, false); } - if(m_mesh) + if (m_mesh) { #if 0 // Usually 1-700 faces and 1-7 materials @@ -1400,17 +1422,30 @@ void MeshCollector::append(const TileSpec &tile, p = &prebuffers[prebuffers.size() - 1]; } - u32 vertex_count = p->vertices.size(); - for (u32 i = 0; i < numIndices; i++) { + u32 vertex_count; + if (m_use_tangent_vertices) { + vertex_count = p->tangent_vertices.size(); + p->tangent_vertices.reserve(vertex_count + numVertices); + for (u32 i = 0; i < numVertices; i++) { + video::S3DVertexTangents vert(vertices[i].Pos, vertices[i].Normal, + vertices[i].Color, vertices[i].TCoords); + p->tangent_vertices.push_back(vert); + } + } else { + vertex_count = p->vertices.size(); + p->vertices.reserve(vertex_count + numVertices); + for (u32 i = 0; i < numVertices; i++) { + video::S3DVertex vert(vertices[i].Pos, vertices[i].Normal, + vertices[i].Color, vertices[i].TCoords); + p->vertices.push_back(vert); + } + } + + p->indices.reserve(p->indices.size() + numIndices); + for (u32 i = 0; i < numIndices; i++) { u32 j = indices[i] + vertex_count; p->indices.push_back(j); } - - for (u32 i = 0; i < numVertices; i++) { - video::S3DVertex vert(vertices[i].Pos, vertices[i].Normal, - vertices[i].Color, vertices[i].TCoords); - p->vertices.push_back(vert); - } } /* @@ -1446,15 +1481,28 @@ void MeshCollector::append(const TileSpec &tile, p = &prebuffers[prebuffers.size() - 1]; } - u32 vertex_count = p->vertices.size(); + u32 vertex_count; + if (m_use_tangent_vertices) { + vertex_count = p->tangent_vertices.size(); + p->tangent_vertices.reserve(vertex_count + numVertices); + for (u32 i = 0; i < numVertices; i++) { + video::S3DVertexTangents vert(vertices[i].Pos + pos, + vertices[i].Normal, c, vertices[i].TCoords); + p->tangent_vertices.push_back(vert); + } + } else { + vertex_count = p->vertices.size(); + p->vertices.reserve(vertex_count + numVertices); + for (u32 i = 0; i < numVertices; i++) { + video::S3DVertex vert(vertices[i].Pos + pos, + vertices[i].Normal, c, vertices[i].TCoords); + p->vertices.push_back(vert); + } + } + + p->indices.reserve(p->indices.size() + numIndices); for (u32 i = 0; i < numIndices; i++) { u32 j = indices[i] + vertex_count; p->indices.push_back(j); } - - for (u32 i = 0; i < numVertices; i++) { - video::S3DVertex vert(vertices[i].Pos + pos, vertices[i].Normal, - c, vertices[i].TCoords); - p->vertices.push_back(vert); - } } diff --git a/src/mapblock_mesh.h b/src/mapblock_mesh.h index 421e8f2b39d2..987490408171 100644 --- a/src/mapblock_mesh.h +++ b/src/mapblock_mesh.h @@ -46,8 +46,10 @@ struct MeshMakeData IGameDef *m_gamedef; bool m_use_shaders; + bool m_use_tangent_vertices; - MeshMakeData(IGameDef *gamedef, bool use_shaders); + MeshMakeData(IGameDef *gamedef, bool use_shaders, + bool use_tangent_vertices = false); /* Copy central data directly from block, and other data from @@ -130,6 +132,7 @@ class MapBlockMesh IShaderSource *m_shdrsrc; bool m_enable_shaders; + bool m_use_tangent_vertices; // Must animate() be called before rendering? bool m_has_animation; @@ -167,11 +170,19 @@ struct PreMeshBuffer TileSpec tile; std::vector indices; std::vector vertices; + std::vector tangent_vertices; }; struct MeshCollector { std::vector prebuffers; + bool m_use_tangent_vertices; + + MeshCollector(bool use_tangent_vertices): + m_use_tangent_vertices(use_tangent_vertices) + { + } + void append(const TileSpec &material, const video::S3DVertex *vertices, u32 numVertices, const u16 *indices, u32 numIndices);