diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 46977b147..c4cf2b84b 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -38,6 +38,7 @@ varying vec3 vPosition; // precision must be considered). varying vec3 worldPosition; varying lowp vec4 varColor; +varying lowp vec3 hwColor; #ifdef GL_ES varying mediump vec2 varTexCoord; #else @@ -375,7 +376,7 @@ void main(void) #endif color = base.rgb; - vec4 col = vec4(color.rgb * varColor.rgb, 1.0); + vec4 col = vec4(color * hwColor * varColor.rgb, 1.0); #ifdef ENABLE_DYNAMIC_SHADOWS if (f_shadow_strength > 0.0) { diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index bcb4ab4fb..89cdec90d 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -17,6 +17,7 @@ varying vec3 vPosition; // precision must be considered). varying vec3 worldPosition; varying lowp vec4 varColor; +varying lowp vec3 hwColor; // The centroid keyword ensures that after interpolation the texture coordinates // lie within the same bounds when MSAA is en- and disabled. // This fixes the stripes problem with nearest-neighbor textures and MSAA. @@ -226,6 +227,8 @@ void main(void) varColor = clamp(color, 0.0, 1.0); + hwColor = inVertexTangent.xyz; + #ifdef ENABLE_DYNAMIC_SHADOWS if (f_shadow_strength > 0.0) { #if MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 5e724d05e..3551b6e8c 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -139,7 +139,7 @@ void Camera::step(f32 dtime) if (m_wield_change_timer >= 0 && was_under_zero) { m_wieldnode->setItem(m_wield_item_next, m_client); - m_wieldnode->setNodeLightColor(m_player_light_color); + m_wieldnode->setColor(m_player_light_color); } if (m_view_bobbing_state != 0) @@ -552,7 +552,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio) m_wieldnode->setRotation(wield_rotation); m_player_light_color = player->light_color; - m_wieldnode->setNodeLightColor(m_player_light_color); + m_wieldnode->setColor(m_player_light_color); // Set render distance updateViewingRange(); diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 6512c4a06..8720284fe 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -922,11 +922,11 @@ void GenericCAO::setNodeLight(const video::SColor &light_color) { if (m_prop.visual == "wielditem" || m_prop.visual == "item") { if (m_wield_meshnode) - m_wield_meshnode->setNodeLightColor(light_color); + m_wield_meshnode->setColor(light_color); return; } - if (m_enable_shaders) { + /*if (m_enable_shaders) { if (m_prop.visual == "upright_sprite") { if (!m_meshnode) return; @@ -942,7 +942,7 @@ void GenericCAO::setNodeLight(const video::SColor &light_color) material.EmissiveColor = light_color; } } - } else { + } else {*/ if (m_meshnode) { setMeshColor(m_meshnode->getMesh(), light_color); } else if (m_animated_meshnode) { @@ -950,7 +950,7 @@ void GenericCAO::setNodeLight(const video::SColor &light_color) } else if (m_spritenode) { m_spritenode->setColor(light_color); } - } + //} } u16 GenericCAO::getLightPosition(v3s16 *pos) diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 6bb9c234b..8dea839ff 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -1137,9 +1137,9 @@ void drawItemStack( if (p.needColorize(c)) { buf->setDirty(scene::EBT_VERTEX); if (imesh->needs_shading) - colorizeMeshBuffer(buf, &c); + colorizeMeshBufferTangents(buf, &c); else - setMeshBufferColor(buf, c); + setMeshBufferTangentsColor(buf, c); } video::SMaterial &material = buf->getMaterial(); diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 903148beb..21685bccd 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -630,7 +630,8 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs { PreMeshBuffer &p = collector.prebuffers[layer][i]; - applyTileColor(p); + if (!m_enable_shaders) + applyTileColor(p); // Generate animation data // - Cracks @@ -717,10 +718,25 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs p.layer.applyMaterialOptions(material); } - scene::SMeshBuffer *buf = new scene::SMeshBuffer(); + scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents(); buf->Material = material; + + std::vector tangents; + + // Copy S3DVertex to S3DVertexTangents + for (auto &v : p.vertices) { + video::SColor &c = p.layer.color; + v3f hw_color{0.0f}; + + if (m_enable_shaders) { + hw_color.X = c.getRed() / 255.0f; + hw_color.Y = c.getGreen() / 255.0f; + hw_color.Z = c.getBlue() / 255.0f; + } + tangents.emplace_back(v.Pos, v.Normal, v.Color, v.TCoords, hw_color); + } if (p.layer.isTransparent()) { - buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0); + buf->append(&tangents[0], tangents.size(), nullptr, 0); MeshTriangle t; t.buffer = buf; @@ -733,7 +749,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs m_transparent_triangles.push_back(t); } } else { - buf->append(&p.vertices[0], p.vertices.size(), + buf->append(&tangents[0], tangents.size(), &p.indices[0], p.indices.size()); } mesh->addMeshBuffer(buf); @@ -829,20 +845,19 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, if (!m_enable_shaders && (daynight_ratio != m_last_daynight_ratio)) { video::SColorf day_color; get_sunlight_color(&day_color, daynight_ratio); - for (auto &daynight_diff : m_daynight_diffs) { auto *mesh = m_mesh[daynight_diff.first.first]; mesh->setDirty(scene::EBT_VERTEX); // force reload to VBO scene::IMeshBuffer *buf = mesh-> getMeshBuffer(daynight_diff.first.second); - video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices(); + video::S3DVertexTangents *vertices = (video::S3DVertexTangents*)buf->getVertices(); + for (const auto &j : daynight_diff.second) final_color_blend(&(vertices[j.first].Color), j.second, day_color); } m_last_daynight_ratio = daynight_ratio; } - return true; } @@ -861,7 +876,7 @@ void MapBlockMesh::updateTransparentBuffers(v3f camera_pos, v3s16 block_pos) // arrange index sequences into partial buffers m_transparent_buffers.clear(); - scene::SMeshBuffer *current_buffer = nullptr; + scene::SMeshBufferTangents *current_buffer = nullptr; std::vector current_strain; for (auto i : triangle_refs) { const auto &t = m_transparent_triangles[i]; @@ -885,7 +900,7 @@ void MapBlockMesh::consolidateTransparentBuffers() { m_transparent_buffers.clear(); - scene::SMeshBuffer *current_buffer = nullptr; + scene::SMeshBufferTangents *current_buffer = nullptr; std::vector current_strain; // use the fact that m_transparent_triangles is already arranged by buffer diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index 98a5c6ca6..ccab91461 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -74,7 +74,7 @@ struct MeshMakeData class MeshTriangle { public: - scene::SMeshBuffer *buffer; + scene::SMeshBufferTangents *buffer; u16 p1, p2, p3; v3f centroid; float areaSQ; @@ -152,7 +152,7 @@ class MapBlockBspTree class PartialMeshBuffer { public: - PartialMeshBuffer(scene::SMeshBuffer *buffer, std::vector &&vertex_indexes) : + PartialMeshBuffer(scene::SMeshBufferTangents *buffer, std::vector &&vertex_indexes) : m_buffer(buffer), m_vertex_indexes(std::move(vertex_indexes)) {} @@ -162,7 +162,7 @@ class PartialMeshBuffer void beforeDraw() const; void afterDraw() const; private: - scene::SMeshBuffer *m_buffer; + scene::SMeshBufferTangents *m_buffer; mutable std::vector m_vertex_indexes; }; diff --git a/src/client/mesh.cpp b/src/client/mesh.cpp index 711f7e1c6..1a50e9550 100644 --- a/src/client/mesh.cpp +++ b/src/client/mesh.cpp @@ -53,50 +53,55 @@ void applyFacesShading(video::SColor &color, const v3f &normal) applyShadeFactor(color, 0.670820f * x2 + 1.000000f * y2 + 0.836660f * z2); } +template +std::array getCubeVertices(video::SColor c) +{ + return std::array{ + // Up + T(-0.5,+0.5,-0.5, 0,1,0, c, 0,1), + T(-0.5,+0.5,+0.5, 0,1,0, c, 0,0), + T(+0.5,+0.5,+0.5, 0,1,0, c, 1,0), + T(+0.5,+0.5,-0.5, 0,1,0, c, 1,1), + // Down + T(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0), + T(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0), + T(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1), + T(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1), + // Right + T(+0.5,-0.5,-0.5, 1,0,0, c, 0,1), + T(+0.5,+0.5,-0.5, 1,0,0, c, 0,0), + T(+0.5,+0.5,+0.5, 1,0,0, c, 1,0), + T(+0.5,-0.5,+0.5, 1,0,0, c, 1,1), + // Left + T(-0.5,-0.5,-0.5, -1,0,0, c, 1,1), + T(-0.5,-0.5,+0.5, -1,0,0, c, 0,1), + T(-0.5,+0.5,+0.5, -1,0,0, c, 0,0), + T(-0.5,+0.5,-0.5, -1,0,0, c, 1,0), + // Back + T(-0.5,-0.5,+0.5, 0,0,1, c, 1,1), + T(+0.5,-0.5,+0.5, 0,0,1, c, 0,1), + T(+0.5,+0.5,+0.5, 0,0,1, c, 0,0), + T(-0.5,+0.5,+0.5, 0,0,1, c, 1,0), + // Front + T(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1), + T(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0), + T(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0), + T(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1), + }; +} + scene::IAnimatedMesh* createCubeMesh(v3f scale) { video::SColor c(255,255,255,255); - video::S3DVertex vertices[24] = - { - // Up - video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1), - video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0), - video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0), - video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1), - // Down - video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0), - video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0), - video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1), - video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1), - // Right - video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1), - video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0), - video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0), - video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1), - // Left - video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1), - video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1), - video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0), - video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0), - // Back - video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1), - video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1), - video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0), - video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0), - // Front - video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1), - video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0), - video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0), - video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1), - }; + std::array vertices = getCubeVertices(c); u16 indices[6] = {0,1,2,2,3,0}; scene::SMesh *mesh = new scene::SMesh(); for (u32 i=0; i<6; ++i) { scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - buf->append(vertices + 4 * i, 4, indices, 6); + buf->append(&vertices[0] + 4 * i, 4, indices, 6); // Set default material buf->getMaterial().Lighting = false; buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; @@ -115,9 +120,39 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale) return anim_mesh; } +scene::IAnimatedMesh* createCubeMeshTangents(v3f scale) +{ + video::SColor c(255,255,255,255); + + std::array vertices = getCubeVertices(c); + u16 indices[6] = {0,1,2,2,3,0}; + + scene::SMesh *mesh = new scene::SMesh(); + for (u32 i=0; i<6; ++i) + { + scene::IMeshBuffer *buf = new scene::SMeshBufferTangents(); + buf->append(&vertices[0] + 4 * i, 4, indices, 6); + // Set default material + buf->getMaterial().Lighting = false; + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + buf->getMaterial().forEachTexture([] (auto &tex) { + tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; + tex.MagFilter = video::ETMAGF_NEAREST; + }); + // Add mesh buffer to mesh + mesh->addMeshBuffer(buf); + buf->drop(); + } + + scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh); + mesh->drop(); + scaleMeshTangents(anim_mesh, scale); // also recalculates bounding box + return anim_mesh; +} + void scaleMesh(scene::IMesh *mesh, v3f scale) { - if (mesh == NULL) + if (!mesh) return; aabb3f bbox; @@ -126,11 +161,9 @@ void scaleMesh(scene::IMesh *mesh, v3f scale) u32 mc = mesh->getMeshBufferCount(); for (u32 j = 0; j < mc; j++) { scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); - const u32 stride = getVertexPitchFromType(buf->getVertexType()); - u32 vertex_count = buf->getVertexCount(); - u8 *vertices = (u8 *)buf->getVertices(); - for (u32 i = 0; i < vertex_count; i++) - ((video::S3DVertex *)(vertices + i * stride))->Pos *= scale; + video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); + for (u32 i = 0; i < buf->getVertexCount(); i++) + vertices[i].Pos *= scale; buf->recalculateBoundingBox(); @@ -143,9 +176,9 @@ void scaleMesh(scene::IMesh *mesh, v3f scale) mesh->setBoundingBox(bbox); } -void translateMesh(scene::IMesh *mesh, v3f vec) +void scaleMeshTangents(scene::IMesh *mesh, v3f scale) { - if (mesh == NULL) + if (!mesh) return; aabb3f bbox; @@ -154,11 +187,35 @@ void translateMesh(scene::IMesh *mesh, v3f vec) u32 mc = mesh->getMeshBufferCount(); for (u32 j = 0; j < mc; j++) { scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); - const u32 stride = getVertexPitchFromType(buf->getVertexType()); - u32 vertex_count = buf->getVertexCount(); - u8 *vertices = (u8 *)buf->getVertices(); - for (u32 i = 0; i < vertex_count; i++) - ((video::S3DVertex *)(vertices + i * stride))->Pos += vec; + video::S3DVertexTangents *vertices = (video::S3DVertexTangents*)buf->getVertices(); + for (u32 i = 0; i < buf->getVertexCount(); i++) + vertices[i].Pos *= scale; + + buf->recalculateBoundingBox(); + + // calculate total bounding box + if (j == 0) + bbox = buf->getBoundingBox(); + else + bbox.addInternalBox(buf->getBoundingBox()); + } + mesh->setBoundingBox(bbox); +} + +void translateMeshTangents(scene::IMesh *mesh, v3f vec) +{ + if (!mesh) + return; + + aabb3f bbox; + bbox.reset(0, 0, 0); + + u32 mc = mesh->getMeshBufferCount(); + for (u32 j = 0; j < mc; j++) { + scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); + video::S3DVertex *vertices = (video::S3DVertexTangents*)buf->getVertices(); + for (u32 i = 0; i < buf->getVertexCount(); i++) + vertices[i].Pos += vec; buf->recalculateBoundingBox(); @@ -173,11 +230,20 @@ void translateMesh(scene::IMesh *mesh, v3f vec) void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor &color) { - const u32 stride = getVertexPitchFromType(buf->getVertexType()); - u32 vertex_count = buf->getVertexCount(); - u8 *vertices = (u8 *) buf->getVertices(); - for (u32 i = 0; i < vertex_count; i++) - ((video::S3DVertex *) (vertices + i * stride))->Color = color; + video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); + for (u32 i = 0; i < buf->getVertexCount(); i++) + vertices[i].Color = color; +} + +void setMeshBufferTangentsColor(scene::IMeshBuffer *buf, + const video::SColor &color, const video::SColor &hw_color) +{ + video::S3DVertexTangents *vertices = (video::S3DVertexTangents*)buf->getVertices(); + + for (u32 i = 0; i < buf->getVertexCount(); i++) { + vertices[i].Color = color; + vertices[i].Tangent = v3f(hw_color.getRed(), hw_color.getGreen(), hw_color.getBlue()); + } } void setAnimatedMeshColor(scene::IAnimatedMeshSceneNode *node, const video::SColor &color) @@ -189,44 +255,47 @@ void setAnimatedMeshColor(scene::IAnimatedMeshSceneNode *node, const video::SCol void setMeshColor(scene::IMesh *mesh, const video::SColor &color) { - if (mesh == NULL) + if (!mesh) return; - u32 mc = mesh->getMeshBufferCount(); - for (u32 j = 0; j < mc; j++) + for (u32 j = 0; j < mesh->getMeshBufferCount(); j++) setMeshBufferColor(mesh->getMeshBuffer(j), color); } +/*void setMeshTangentsColor(scene::IMesh *mesh, const video::SColor &color, + const video::SColor &hw_color) +{ + if (!mesh) + return; + + for (u32 j = 0; j < mesh->getMeshBufferCount(); j++) + setMeshBufferTangentsColor(mesh->getMeshBuffer(j), color, hw_color); +}*/ + void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count) { - const u32 stride = getVertexPitchFromType(buf->getVertexType()); assert(buf->getVertexCount() >= count); - u8 *vertices = (u8 *) buf->getVertices(); + video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); for (u32 i = 0; i < count; i++) - ((video::S3DVertex*) (vertices + i * stride))->TCoords = uv[i]; + vertices[i].TCoords = uv[i]; } -template +template static void applyToMesh(scene::IMesh *mesh, const F &fn) { - u16 mc = mesh->getMeshBufferCount(); - for (u16 j = 0; j < mc; j++) { + for (u16 j = 0; j < mesh->getMeshBufferCount(); j++) { scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); - const u32 stride = getVertexPitchFromType(buf->getVertexType()); - u32 vertex_count = buf->getVertexCount(); - char *vertices = reinterpret_cast(buf->getVertices()); - for (u32 i = 0; i < vertex_count; i++) - fn(reinterpret_cast(vertices + i * stride)); + T *vertices = (T*)buf->getVertices(); + for (u32 i = 0; i < buf->getVertexCount(); i++) + fn(&vertices[i]); } } -void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolor) +void colorizeMeshBufferTangents(scene::IMeshBuffer *buf, const video::SColor *buffercolor) { - const u32 stride = getVertexPitchFromType(buf->getVertexType()); - u32 vertex_count = buf->getVertexCount(); - u8 *vertices = (u8 *) buf->getVertices(); - for (u32 i = 0; i < vertex_count; i++) { - video::S3DVertex *vertex = (video::S3DVertex *) (vertices + i * stride); + video::S3DVertexTangents *vertices = (video::S3DVertexTangents*)buf->getVertices(); + for (u32 i = 0; i < buf->getVertexCount(); i++) { + video::S3DVertexTangents *vertex = &vertices[i]; video::SColor *vc = &(vertex->Color); // Reset color *vc = *buffercolor; @@ -235,27 +304,6 @@ void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolo } } -void setMeshColorByNormalXYZ(scene::IMesh *mesh, - const video::SColor &colorX, - const video::SColor &colorY, - const video::SColor &colorZ) -{ - if (!mesh) - return; - auto colorizator = [=] (video::S3DVertex *vertex) { - f32 x = fabs(vertex->Normal.X); - f32 y = fabs(vertex->Normal.Y); - f32 z = fabs(vertex->Normal.Z); - if (x >= y && x >= z) - vertex->Color = colorX; - else if (y >= z) - vertex->Color = colorY; - else - vertex->Color = colorZ; - }; - applyToMesh(mesh, colorizator); -} - void setMeshColorByNormal(scene::IMesh *mesh, const v3f &normal, const video::SColor &color) { @@ -265,37 +313,47 @@ void setMeshColorByNormal(scene::IMesh *mesh, const v3f &normal, if (vertex->Normal == normal) vertex->Color = color; }; - applyToMesh(mesh, colorizator); + applyToMesh(mesh, colorizator); } -template +template static void rotateMesh(scene::IMesh *mesh, float degrees) { degrees *= M_PI / 180.0f; float c = std::cos(degrees); float s = std::sin(degrees); - auto rotator = [c, s] (video::S3DVertex *vertex) { + auto rotator = [c, s] (T *vertex) { float u = vertex->Pos.*U; float v = vertex->Pos.*V; vertex->Pos.*U = c * u - s * v; vertex->Pos.*V = s * u + c * v; }; - applyToMesh(mesh, rotator); + applyToMesh(mesh, rotator); } void rotateMeshXYby(scene::IMesh *mesh, f64 degrees) { - rotateMesh<&v3f::X, &v3f::Y>(mesh, degrees); + rotateMesh(mesh, degrees); } void rotateMeshXZby(scene::IMesh *mesh, f64 degrees) { - rotateMesh<&v3f::X, &v3f::Z>(mesh, degrees); + rotateMesh(mesh, degrees); +} + +void rotateMeshTangentsXZby(scene::IMesh *mesh, f64 degrees) +{ + rotateMesh(mesh, degrees); } void rotateMeshYZby(scene::IMesh *mesh, f64 degrees) { - rotateMesh<&v3f::Y, &v3f::Z>(mesh, degrees); + rotateMesh(mesh, degrees); +} + +void rotateMeshTangentsYZby(scene::IMesh *mesh, f64 degrees) +{ + rotateMesh(mesh, degrees); } void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir) @@ -357,7 +415,7 @@ scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer) { switch (mesh_buffer->getVertexType()) { case video::EVT_STANDARD: { - video::S3DVertex *v = (video::S3DVertex *) mesh_buffer->getVertices(); + video::S3DVertex *v = (video::S3DVertex*)mesh_buffer->getVertices(); u16 *indices = mesh_buffer->getIndices(); scene::SMeshBuffer *cloned_buffer = new scene::SMeshBuffer(); cloned_buffer->append(v, mesh_buffer->getVertexCount(), indices, @@ -366,7 +424,7 @@ scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer) } case video::EVT_2TCOORDS: { video::S3DVertex2TCoords *v = - (video::S3DVertex2TCoords *) mesh_buffer->getVertices(); + (video::S3DVertex2TCoords*)mesh_buffer->getVertices(); u16 *indices = mesh_buffer->getIndices(); scene::SMeshBufferLightMap *cloned_buffer = new scene::SMeshBufferLightMap(); @@ -376,7 +434,7 @@ scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer) } case video::EVT_TANGENTS: { video::S3DVertexTangents *v = - (video::S3DVertexTangents *) mesh_buffer->getVertices(); + (video::S3DVertexTangents*)mesh_buffer->getVertices(); u16 *indices = mesh_buffer->getIndices(); scene::SMeshBufferTangents *cloned_buffer = new scene::SMeshBufferTangents(); diff --git a/src/client/mesh.h b/src/client/mesh.h index 0c3e8942e..e8306e41d 100644 --- a/src/client/mesh.h +++ b/src/client/mesh.h @@ -38,27 +38,33 @@ void applyFacesShading(video::SColor &color, const v3f &normal); */ scene::IAnimatedMesh* createCubeMesh(v3f scale); +scene::IAnimatedMesh* createCubeMeshTangents(v3f scale); + /* Multiplies each vertex coordinate by the specified scaling factors (componentwise vector multiplication). */ void scaleMesh(scene::IMesh *mesh, v3f scale); +void scaleMeshTangents(scene::IMesh *mesh, v3f scale); /* Translate each vertex coordinate by the specified vector. */ -void translateMesh(scene::IMesh *mesh, v3f vec); +void translateMeshTangents(scene::IMesh *mesh, v3f vec); /*! * Sets a constant color for all vertices in the mesh buffer. */ void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor &color); +void setMeshBufferTangentsColor(scene::IMeshBuffer *buf, + const video::SColor &color, const video::SColor &hw_color=video::SColor(0xFFFFFFFF)); /* Set a constant color for all vertices in the mesh */ void setMeshColor(scene::IMesh *mesh, const video::SColor &color); - +void setMeshTangentsColor(scene::IMesh *mesh, const video::SColor &color, + const video::SColor &hw_color=video::SColor(0xFFFFFFFF)); /* Sets texture coords for vertices in the mesh buffer. @@ -75,18 +81,7 @@ void setAnimatedMeshColor(scene::IAnimatedMeshSceneNode *node, const video::SCol * Overwrites the color of a mesh buffer. * The color is darkened based on the normal vector of the vertices. */ -void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolor); - -/* - Set the color of all vertices in the mesh. - For each vertex, determine the largest absolute entry in - the normal vector, and choose one of colorX, colorY or - colorZ accordingly. -*/ -void setMeshColorByNormalXYZ(scene::IMesh *mesh, - const video::SColor &colorX, - const video::SColor &colorY, - const video::SColor &colorZ); +void colorizeMeshBufferTangents(scene::IMeshBuffer *buf, const video::SColor *buffercolor); void setMeshColorByNormal(scene::IMesh *mesh, const v3f &normal, const video::SColor &color); @@ -102,7 +97,9 @@ void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir); */ void rotateMeshXYby (scene::IMesh *mesh, f64 degrees); void rotateMeshXZby (scene::IMesh *mesh, f64 degrees); +void rotateMeshTangentsXZby(scene::IMesh *mesh, f64 degrees); void rotateMeshYZby (scene::IMesh *mesh, f64 degrees); +void rotateMeshTangentsYZby(scene::IMesh *mesh, f64 degrees); /* * Clone the mesh buffer. @@ -139,5 +136,5 @@ bool checkMeshNormals(scene::IMesh *mesh); Set the MinFilter, MagFilter and AnisotropicFilter properties of a texture layer according to the three relevant boolean values found in the Minetest settings. -*/ +*/ void setMaterialFilters(video::SMaterialLayer &tex, bool bilinear, bool trilinear, bool anisotropic); diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index 66f89efb1..182862dfd 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -45,23 +45,22 @@ static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y) { const f32 r = 0.5; - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents(); video::SColor c(255,255,255,255); v3f scale(1.0, 1.0, 0.1); - // Front and back { - video::S3DVertex vertices[8] = { + video::S3DVertexTangents vertices[8] = { // z- - video::S3DVertex(-r,+r,-r, 0,0,-1, c, 0,0), - video::S3DVertex(+r,+r,-r, 0,0,-1, c, 1,0), - video::S3DVertex(+r,-r,-r, 0,0,-1, c, 1,1), - video::S3DVertex(-r,-r,-r, 0,0,-1, c, 0,1), + video::S3DVertexTangents(-r,+r,-r, 0,0,-1, c, 0,0), + video::S3DVertexTangents(+r,+r,-r, 0,0,-1, c, 1,0), + video::S3DVertexTangents(+r,-r,-r, 0,0,-1, c, 1,1), + video::S3DVertexTangents(-r,-r,-r, 0,0,-1, c, 0,1), // z+ - video::S3DVertex(-r,+r,+r, 0,0,+1, c, 0,0), - video::S3DVertex(-r,-r,+r, 0,0,+1, c, 0,1), - video::S3DVertex(+r,-r,+r, 0,0,+1, c, 1,1), - video::S3DVertex(+r,+r,+r, 0,0,+1, c, 1,0), + video::S3DVertexTangents(-r,+r,+r, 0,0,+1, c, 0,0), + video::S3DVertexTangents(-r,-r,+r, 0,0,+1, c, 0,1), + video::S3DVertexTangents(+r,-r,+r, 0,0,+1, c, 1,1), + video::S3DVertexTangents(+r,+r,+r, 0,0,+1, c, 1,0), }; u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4}; buf->append(vertices, 8, indices, 12); @@ -76,17 +75,17 @@ static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y) f32 x1 = pixelpos_x + pixelsize_x; f32 tex0 = (i + 0.1) * pixelsize_x; f32 tex1 = (i + 0.9) * pixelsize_x; - video::S3DVertex vertices[8] = { + video::S3DVertexTangents vertices[8] = { // x- - video::S3DVertex(x0,-r,-r, -1,0,0, c, tex0,1), - video::S3DVertex(x0,-r,+r, -1,0,0, c, tex1,1), - video::S3DVertex(x0,+r,+r, -1,0,0, c, tex1,0), - video::S3DVertex(x0,+r,-r, -1,0,0, c, tex0,0), + video::S3DVertexTangents(x0,-r,-r, -1,0,0, c, tex0,1), + video::S3DVertexTangents(x0,-r,+r, -1,0,0, c, tex1,1), + video::S3DVertexTangents(x0,+r,+r, -1,0,0, c, tex1,0), + video::S3DVertexTangents(x0,+r,-r, -1,0,0, c, tex0,0), // x+ - video::S3DVertex(x1,-r,-r, +1,0,0, c, tex0,1), - video::S3DVertex(x1,+r,-r, +1,0,0, c, tex0,0), - video::S3DVertex(x1,+r,+r, +1,0,0, c, tex1,0), - video::S3DVertex(x1,-r,+r, +1,0,0, c, tex1,1), + video::S3DVertexTangents(x1,-r,-r, +1,0,0, c, tex0,1), + video::S3DVertexTangents(x1,+r,-r, +1,0,0, c, tex0,0), + video::S3DVertexTangents(x1,+r,+r, +1,0,0, c, tex1,0), + video::S3DVertexTangents(x1,-r,+r, +1,0,0, c, tex1,1), }; u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4}; buf->append(vertices, 8, indices, 12); @@ -97,17 +96,17 @@ static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y) f32 y1 = -pixelpos_y; f32 tex0 = (i + 0.1) * pixelsize_y; f32 tex1 = (i + 0.9) * pixelsize_y; - video::S3DVertex vertices[8] = { + video::S3DVertexTangents vertices[8] = { // y- - video::S3DVertex(-r,y0,-r, 0,-1,0, c, 0,tex0), - video::S3DVertex(+r,y0,-r, 0,-1,0, c, 1,tex0), - video::S3DVertex(+r,y0,+r, 0,-1,0, c, 1,tex1), - video::S3DVertex(-r,y0,+r, 0,-1,0, c, 0,tex1), + video::S3DVertexTangents(-r,y0,-r, 0,-1,0, c, 0,tex0), + video::S3DVertexTangents(+r,y0,-r, 0,-1,0, c, 1,tex0), + video::S3DVertexTangents(+r,y0,+r, 0,-1,0, c, 1,tex1), + video::S3DVertexTangents(-r,y0,+r, 0,-1,0, c, 0,tex1), // y+ - video::S3DVertex(-r,y1,-r, 0,+1,0, c, 0,tex0), - video::S3DVertex(-r,y1,+r, 0,+1,0, c, 0,tex1), - video::S3DVertex(+r,y1,+r, 0,+1,0, c, 1,tex1), - video::S3DVertex(+r,y1,-r, 0,+1,0, c, 1,tex0), + video::S3DVertexTangents(-r,y1,-r, 0,+1,0, c, 0,tex0), + video::S3DVertexTangents(-r,y1,+r, 0,+1,0, c, 0,tex1), + video::S3DVertexTangents(+r,y1,+r, 0,+1,0, c, 1,tex1), + video::S3DVertexTangents(+r,y1,-r, 0,+1,0, c, 1,tex0), }; u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4}; buf->append(vertices, 8, indices, 12); @@ -117,7 +116,7 @@ static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y) scene::SMesh *mesh = new scene::SMesh(); mesh->addMeshBuffer(buf); buf->drop(); - scaleMesh(mesh, scale); // also recalculates bounding box + scaleMeshTangents(mesh, scale); // also recalculates bounding box return mesh; } @@ -144,7 +143,7 @@ class ExtrusionMeshCache: public IReferenceCounted m_extrusion_meshes[resolution] = createExtrusionMesh(resolution, resolution); } - m_cube = createCubeMesh(v3f(1.0, 1.0, 1.0)); + m_cube = createCubeMeshTangents(v3f(1.0, 1.0, 1.0)); } // Destructor virtual ~ExtrusionMeshCache() @@ -345,14 +344,16 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n, p.layer.texture = frame.texture; p.layer.normal_texture = frame.normal_texture; } + std::vector tangents; for (video::S3DVertex &v : p.vertices) { v.Color.setAlpha(255); + tangents.emplace_back(v); } - scene::SMeshBuffer *buf = new scene::SMeshBuffer(); + scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents(); buf->Material.setTexture(0, p.layer.texture); p.layer.applyMaterialOptions(buf->Material); mesh->addMeshBuffer(buf); - buf->append(&p.vertices[0], p.vertices.size(), + buf->append(&tangents[0], tangents.size(), &p.indices[0], p.indices.size()); buf->drop(); colors->push_back( @@ -374,7 +375,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che scene::SMesh *mesh = nullptr; if (m_enable_shaders) { - u32 shader_id = shdrsrc->getShader("object_shader", TILE_MATERIAL_BASIC, NDT_NORMAL); + u32 shader_id = shdrsrc->getShader("nodes_shader", TILE_MATERIAL_BASIC, NDT_NORMAL); m_material_type = shdrsrc->getShaderInfo(shader_id).material; } @@ -500,33 +501,37 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che void WieldMeshSceneNode::setColor(video::SColor c) { + if (!m_meshnode) + return; + assert(!m_lighting); scene::IMesh *mesh = m_meshnode->getMesh(); if (!mesh) return; - u8 red = c.getRed(); - u8 green = c.getGreen(); - u8 blue = c.getBlue(); - const u32 mc = mesh->getMeshBufferCount(); if (mc > m_colors.size()) m_colors.resize(mc); for (u32 j = 0; j < mc; j++) { video::SColor bc(m_base_color); m_colors[j].applyOverride(bc); - video::SColor buffercolor(255, - bc.getRed() * red / 255, - bc.getGreen() * green / 255, - bc.getBlue() * blue / 255); + scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); + video::SColor buffercolor(255, + bc.getRed() * c.getRed() / 255, + bc.getGreen() * c.getGreen() / 255, + bc.getBlue() * c.getBlue() / 255); + if (m_colors[j].needColorize(buffercolor)) { buf->setDirty(scene::EBT_VERTEX); - if (m_enable_shaders) - setMeshBufferColor(buf, buffercolor); + if (m_enable_shaders) { + setMeshBufferTangentsColor(buf, + video::SColor(255, c.getRed(), c.getGreen(), c.getBlue()), + video::SColor(255, bc.getRed() / 255, bc.getGreen() / 255, bc.getBlue() / 255)); + } else - colorizeMeshBuffer(buf, &buffercolor); + colorizeMeshBufferTangents(buf, &buffercolor); } } } @@ -619,15 +624,15 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) mesh = cloneMesh(cube); cube->drop(); if (f.drawtype == NDT_FLOWINGLIQUID) { - scaleMesh(mesh, v3f(1.2, 0.03, 1.2)); - translateMesh(mesh, v3f(0, -0.57, 0)); + scaleMeshTangents(mesh, v3f(1.2, 0.03, 1.2)); + translateMeshTangents(mesh, v3f(0, -0.57, 0)); } else - scaleMesh(mesh, v3f(1.2, 1.2, 1.2)); + scaleMeshTangents(mesh, v3f(1.2, 1.2, 1.2)); // add overlays postProcessNodeMesh(mesh, f, false, false, nullptr, &result->buffer_colors, true); if (f.drawtype == NDT_ALLFACES) - scaleMesh(mesh, v3f(f.visual_scale)); + scaleMeshTangents(mesh, v3f(f.visual_scale)); break; } case NDT_PLANTLIKE: { @@ -656,7 +661,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) n.setParam2(*def.place_param2); mesh = createSpecialNodeMesh(client, n, &result->buffer_colors, f); - scaleMesh(mesh, v3f(0.12, 0.12, 0.12)); + scaleMeshTangents(mesh, v3f(0.12, 0.12, 0.12)); break; } } @@ -674,8 +679,8 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) material.Lighting = false; } - rotateMeshXZby(mesh, -45); - rotateMeshYZby(mesh, -30); + rotateMeshTangentsXZby(mesh, -45); + rotateMeshTangentsYZby(mesh, -30); } // might need to be re-colorized, this is done only when needed @@ -728,7 +733,7 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; material.MaterialTypeParam = 0.5f; } - scaleMesh(mesh, v3f(2.0, 2.0, 2.0)); + scaleMeshTangents(mesh, v3f(2.0, 2.0, 2.0)); return mesh; }