diff options
-rw-r--r-- | src/client.cpp | 6 | ||||
-rw-r--r-- | src/client.h | 1 | ||||
-rw-r--r-- | src/mapblock_mesh.cpp | 178 | ||||
-rw-r--r-- | src/mapblock_mesh.h | 13 |
4 files changed, 131 insertions, 67 deletions
diff --git a/src/client.cpp b/src/client.cpp index 2dc537782..ed5ff96fe 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 98a8bc129..c16e9b77a 100644 --- a/src/client.h +++ b/src/client.h @@ -677,6 +677,7 @@ private: // 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 9486220e0..8b3d3c0dd 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 <IMeshManipulator.h> -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; i<fastfaces_new.size(); i++) - { + for (u32 i = 0; i < fastfaces_new.size(); i++) { FastFace &f = fastfaces_new[i]; const u16 indices[] = {0,1,2,2,3,0}; @@ -1150,35 +1152,43 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): p.tile.texture = animation_frame.texture; } - for(u32 j = 0; j < p.vertices.size(); j++) - { - video::S3DVertex *vertex = &p.vertices[j]; + u32 vertex_count = m_use_tangent_vertices ? + p.tangent_vertices.size() : p.vertices.size(); + for (u32 j = 0; j < vertex_count; j++) { + v3f *Normal; + video::SColor *vc; + if (m_use_tangent_vertices) { + vc = &p.tangent_vertices[j].Color; + Normal = &p.tangent_vertices[j].Normal; + } else { + vc = &p.vertices[j].Color; + Normal = &p.vertices[j].Normal; + } // Note applyFacesShading second parameter is precalculated sqrt // value for speed improvement // Skip it for lightsources and top faces. - video::SColor &vc = vertex->Color; - 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 421e8f2b3..987490408 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 @@ private: 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<u16> indices; std::vector<video::S3DVertex> vertices; + std::vector<video::S3DVertexTangents> tangent_vertices; }; struct MeshCollector { std::vector<PreMeshBuffer> 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); |