diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index e345a7e88..e682aca88 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -44,6 +44,8 @@ uniform vec2 windowSize; uniform float fov; varying vec3 vNormal; +varying vec3 vTangent; +varying vec3 vBinormal; varying vec3 vPosition; // World position in the visible world (i.e. relative to the cameraOffset.) // This can be used for many shader effects without loss of precision. @@ -100,36 +102,6 @@ vec3 gnoise(vec3 p){ ); } -float snoise(vec3 p) -{ - vec3 a = floor(p); - vec3 d = p - a; - d = d * d * (3.0 - 2.0 * d); - - vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0); - vec4 k1 = perm(b.xyxy); - vec4 k2 = perm(k1.xyxy + b.zzww); - - vec4 c = k2 + a.zzzz; - vec4 k3 = perm(c); - vec4 k4 = perm(c + 1.0); - - vec4 o1 = fract(k3 * (1.0 / 41.0)); - vec4 o2 = fract(k4 * (1.0 / 41.0)); - - vec4 o3 = o2 * d.z + o1 * (1.0 - d.z); - vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x); - - return o4.y * d.y + o4.x * (1.0 - d.y); -} - -vec3 hnoise(vec3 p) { - vec3 g = gnoise(p); - float s = snoise(p); - g *= 3.0 / (1.0 + exp(-16.0 * (s - 0.5))) - 1.5; - return g; -} - vec2 wave_noise(vec3 p, float off) { return (gnoise(p + vec3(0.0, 0.0, off)) * 0.4 + gnoise(2.0 * p + vec3(0.0, off, off)) * 0.2 + gnoise(3.0 * p + vec3(0.0, off, off)) * 0.225 + gnoise(4.0 * p + vec3(-off, off, 0.0)) * 0.2).xz; } @@ -457,13 +429,11 @@ vec3 getBumpMap(vec2 uv) { float fx0y0 = texture2D(baseTexture, uv).r; float fx1y0 = texture2D(baseTexture, uv + vec2(dr.x, 0.0)).r; float fx0y1 = texture2D(baseTexture, uv + vec2(0.0, dr.y)).r; + // We get the gradient using partial derivatives vec2 gradient = 0.1 * vec2((fx1y0 - fx0y0) / dr.x, (fx0y1 - fx0y0) / dr.y) + 0.05 * gnoise(vec3(2.0 * uv / texelSize0, 0.0)).xy; - // Compute a set of orthonormal basis vectors representing the node's surface plane. - vec3 orth1 = normalize(cross(vNormal, mix(vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, -1.0), step(0.9, abs(vNormal.y))))); - vec3 orth2 = normalize(cross(vNormal, orth1)); - // The normal is computed using the partial derivatives along the texture space x and y axes. - // These axes in world space are assumed to be parallel to the basis vectors we defined before. - return orth1 * gradient.x + orth2 * gradient.y; + vec3 tangent_space = normalize(vec3(gradient, 1.0)); + // Convert tangent space information to real space + return -vTangent * tangent_space.x + vBinormal * tangent_space.y + vNormal * tangent_space.z; } #endif @@ -501,10 +471,10 @@ void main(void) // When applied to all blocks, these bump maps produce irritating Moiré effects. // So we hide the bump maps when close up. float moire_factor = abs(dot(vNormal, viewVec)); - bump_normal *= mtsmoothstep(0.4 * moire_factor, 0.2 * moire_factor, length(eyeVec) * fov / windowSize.x); - fNormal = normalize(vNormal + bump_normal); + moire_factor = mtsmoothstep(0.4 * moire_factor, 0.2 * moire_factor, length(eyeVec) * fov / windowSize.x); + fNormal = normalize(mix(fNormal, bump_normal, moire_factor)); float adj_cosLight = max(1e-5, dot(fNormal, -v_LightDirection)); -#else +#else float adj_cosLight = cosLight; #endif @@ -642,7 +612,7 @@ void main(void) // Note: clarity = (1 - fogginess) float clarity = clamp(fogShadingParameter - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - + #ifdef ENABLE_TINTED_FOG float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b); // Prevent zero division. diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 8f48cb30b..57c2d568a 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -7,6 +7,8 @@ uniform highp vec3 cameraOffset; uniform float animationTimer; varying vec3 vNormal; +varying vec3 vTangent; +varying vec3 vBinormal; varying vec3 vPosition; // World position in the visible world (i.e. relative to the cameraOffset.) // This can be used for many shader effects without loss of precision. @@ -209,6 +211,8 @@ void main(void) normalPass = normalize((inVertexNormal+1)/2); #endif vNormal = inVertexNormal; + vTangent = inVertexTangent.xyz; + vBinormal = inVertexBinormal.xyz; // Calculate color. vec4 color = inVertexColor; diff --git a/client/shaders/second_stage/opengl_fragment.glsl b/client/shaders/second_stage/opengl_fragment.glsl index e15e26803..3492917d1 100644 --- a/client/shaders/second_stage/opengl_fragment.glsl +++ b/client/shaders/second_stage/opengl_fragment.glsl @@ -111,11 +111,6 @@ vec3 screen_space_dither(highp vec2 frag_coord) { } #endif -float sFunction(float x, float a) { - x = 2.0 * x - 1.0; - return 0.5 * sign(x) * pow(abs(x), a) + 0.5; -} - void main(void) { vec2 uv = varTexCoord.st; diff --git a/client/shaders/volumetric_light/opengl_fragment.glsl b/client/shaders/volumetric_light/opengl_fragment.glsl index 86f012551..0a2bba60e 100644 --- a/client/shaders/volumetric_light/opengl_fragment.glsl +++ b/client/shaders/volumetric_light/opengl_fragment.glsl @@ -53,7 +53,7 @@ float sampleVolumetricLight(vec2 uv, vec3 lightVec, float rawDepth) // We use the depth map to approximate the effect of depth on the light intensity. // The exponent was chosen based on aesthetic preference. // To make this phsyically accurate, the brightness here should scale linearly with depth, - // but this would make the godrays either too faint or too strong in many cases. + // but this would make the godrays either too faint or too strong in many cases. return result / samples * pow(texture2D(depthmap, uv).r, 128.0); #else return result / samples; diff --git a/irr/include/IMeshManipulator.h b/irr/include/IMeshManipulator.h index de3d84416..7dd0e46fd 100644 --- a/irr/include/IMeshManipulator.h +++ b/irr/include/IMeshManipulator.h @@ -42,6 +42,26 @@ public: virtual void recalculateNormals(IMeshBuffer *buffer, bool smooth = false, bool angleWeighted = false) const = 0; + //! Recalculates tangents, requires a tangent mesh + /** \param mesh Mesh on which the operation is performed. + \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the mesh are used unchanged. + \param smooth If the normals shall be smoothed. + \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. + */ + virtual void recalculateTangents(IMesh* mesh, + bool recalculateNormals = false, bool smooth = false, + bool angleWeighted = false) const = 0; + + //! Recalculates tangents, requires a tangent mesh buffer + /** \param buffer Meshbuffer on which the operation is performed. + \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the buffer are used unchanged. + \param smooth If the normals shall be smoothed. + \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. + */ + virtual void recalculateTangents(IMeshBuffer* buffer, + bool recalculateNormals = false, bool smooth = false, + bool angleWeighted = false) const = 0; + //! Scales the actual mesh, not a scene node. /** \param mesh Mesh on which the operation is performed. \param factor Scale factor for each axis. */ diff --git a/irr/src/CMeshManipulator.cpp b/irr/src/CMeshManipulator.cpp index 67b22a07e..556a17507 100644 --- a/irr/src/CMeshManipulator.cpp +++ b/irr/src/CMeshManipulator.cpp @@ -80,6 +80,335 @@ void recalculateNormalsT(IMeshBuffer *buffer, bool smooth, bool angleWeighted) } } +namespace +{ + void calculateTangents( + core::vector3df& normal, + core::vector3df& tangent, + core::vector3df& binormal, + const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices + const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords + { + // choose one of them: + //#define USE_NVIDIA_GLH_VERSION // use version used by nvidia in glh headers +#define USE_IRR_VERSION + +#ifdef USE_IRR_VERSION + + core::vector3df v1 = vt1 - vt2; + core::vector3df v2 = vt3 - vt1; + normal = v2.crossProduct(v1); + normal.normalize(); + + // binormal + + f32 deltaX1 = tc1.X - tc2.X; + f32 deltaX2 = tc3.X - tc1.X; + binormal = (v1 * deltaX2) - (v2 * deltaX1); + binormal.normalize(); + + // tangent + + f32 deltaY1 = tc1.Y - tc2.Y; + f32 deltaY2 = tc3.Y - tc1.Y; + tangent = (v1 * deltaY2) - (v2 * deltaY1); + tangent.normalize(); + + // adjust + + core::vector3df txb = tangent.crossProduct(binormal); + if (txb.dotProduct(normal) < 0.0f) + { + tangent *= -1.0f; + binormal *= -1.0f; + } + +#endif // USE_IRR_VERSION + +#ifdef USE_NVIDIA_GLH_VERSION + + tangent.set(0, 0, 0); + binormal.set(0, 0, 0); + + core::vector3df v1(vt2.X - vt1.X, tc2.X - tc1.X, tc2.Y - tc1.Y); + core::vector3df v2(vt3.X - vt1.X, tc3.X - tc1.X, tc3.Y - tc1.Y); + + core::vector3df txb = v1.crossProduct(v2); + if (!core::iszero(txb.X)) + { + tangent.X = -txb.Y / txb.X; + binormal.X = -txb.Z / txb.X; + } + + v1.X = vt2.Y - vt1.Y; + v2.X = vt3.Y - vt1.Y; + txb = v1.crossProduct(v2); + + if (!core::iszero(txb.X)) + { + tangent.Y = -txb.Y / txb.X; + binormal.Y = -txb.Z / txb.X; + } + + v1.X = vt2.Z - vt1.Z; + v2.X = vt3.Z - vt1.Z; + txb = v1.crossProduct(v2); + + if (!core::iszero(txb.X)) + { + tangent.Z = -txb.Y / txb.X; + binormal.Z = -txb.Z / txb.X; + } + + tangent.normalize(); + binormal.normalize(); + + normal = tangent.crossProduct(binormal); + normal.normalize(); + + binormal = tangent.crossProduct(normal); + binormal.normalize(); + + core::plane3d pl(vt1, vt2, vt3); + + if (normal.dotProduct(pl.Normal) < 0.0f) + normal *= -1.0f; + +#endif // USE_NVIDIA_GLH_VERSION + } + + + //! Recalculates tangents for a tangent mesh buffer + template + void recalculateTangentsT(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) + { + if (!buffer || (buffer->getVertexType() != video::EVT_TANGENTS)) + return; + + const u32 vtxCnt = buffer->getVertexCount(); + const u32 idxCnt = buffer->getIndexCount(); + + T* idx = reinterpret_cast(buffer->getIndices()); + video::S3DVertexTangents* v = + (video::S3DVertexTangents*)buffer->getVertices(); + + if (smooth) + { + u32 i; + + for (i = 0; i != vtxCnt; ++i) + { + if (recalculateNormals) + v[i].Normal.set(0.f, 0.f, 0.f); + v[i].Tangent.set(0.f, 0.f, 0.f); + v[i].Binormal.set(0.f, 0.f, 0.f); + } + + //Each vertex gets the sum of the tangents and binormals from the faces around it + for (i = 0; i < idxCnt; i += 3) + { + // if this triangle is degenerate, skip it! + if (v[idx[i + 0]].Pos == v[idx[i + 1]].Pos || + v[idx[i + 0]].Pos == v[idx[i + 2]].Pos || + v[idx[i + 1]].Pos == v[idx[i + 2]].Pos + /*|| + v[idx[i+0]].TCoords == v[idx[i+1]].TCoords || + v[idx[i+0]].TCoords == v[idx[i+2]].TCoords || + v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */ + ) + continue; + + //Angle-weighted normals look better, but are slightly more CPU intensive to calculate + core::vector3df weight(1.f, 1.f, 1.f); + if (angleWeighted) + weight = irr::scene::getAngleWeight(v[i + 0].Pos, v[i + 1].Pos, v[i + 2].Pos); // writing irr::scene:: necessary for borland + core::vector3df localNormal; + core::vector3df localTangent; + core::vector3df localBinormal; + + calculateTangents( + localNormal, + localTangent, + localBinormal, + v[idx[i + 0]].Pos, + v[idx[i + 1]].Pos, + v[idx[i + 2]].Pos, + v[idx[i + 0]].TCoords, + v[idx[i + 1]].TCoords, + v[idx[i + 2]].TCoords); + + if (recalculateNormals) + v[idx[i + 0]].Normal += localNormal * weight.X; + v[idx[i + 0]].Tangent += localTangent * weight.X; + v[idx[i + 0]].Binormal += localBinormal * weight.X; + + calculateTangents( + localNormal, + localTangent, + localBinormal, + v[idx[i + 1]].Pos, + v[idx[i + 2]].Pos, + v[idx[i + 0]].Pos, + v[idx[i + 1]].TCoords, + v[idx[i + 2]].TCoords, + v[idx[i + 0]].TCoords); + + if (recalculateNormals) + v[idx[i + 1]].Normal += localNormal * weight.Y; + v[idx[i + 1]].Tangent += localTangent * weight.Y; + v[idx[i + 1]].Binormal += localBinormal * weight.Y; + + calculateTangents( + localNormal, + localTangent, + localBinormal, + v[idx[i + 2]].Pos, + v[idx[i + 0]].Pos, + v[idx[i + 1]].Pos, + v[idx[i + 2]].TCoords, + v[idx[i + 0]].TCoords, + v[idx[i + 1]].TCoords); + + if (recalculateNormals) + v[idx[i + 2]].Normal += localNormal * weight.Z; + v[idx[i + 2]].Tangent += localTangent * weight.Z; + v[idx[i + 2]].Binormal += localBinormal * weight.Z; + } + + // Normalize the tangents and binormals + if (recalculateNormals) + { + for (i = 0; i != vtxCnt; ++i) + v[i].Normal.normalize(); + } + for (i = 0; i != vtxCnt; ++i) + { + v[i].Tangent.normalize(); + v[i].Binormal.normalize(); + } + } + else + { + core::vector3df localNormal; + for (u32 i = 0; i < idxCnt; i += 3) + { + calculateTangents( + localNormal, + v[idx[i + 0]].Tangent, + v[idx[i + 0]].Binormal, + v[idx[i + 0]].Pos, + v[idx[i + 1]].Pos, + v[idx[i + 2]].Pos, + v[idx[i + 0]].TCoords, + v[idx[i + 1]].TCoords, + v[idx[i + 2]].TCoords); + if (recalculateNormals) + v[idx[i + 0]].Normal = localNormal; + + calculateTangents( + localNormal, + v[idx[i + 1]].Tangent, + v[idx[i + 1]].Binormal, + v[idx[i + 1]].Pos, + v[idx[i + 2]].Pos, + v[idx[i + 0]].Pos, + v[idx[i + 1]].TCoords, + v[idx[i + 2]].TCoords, + v[idx[i + 0]].TCoords); + if (recalculateNormals) + v[idx[i + 1]].Normal = localNormal; + + calculateTangents( + localNormal, + v[idx[i + 2]].Tangent, + v[idx[i + 2]].Binormal, + v[idx[i + 2]].Pos, + v[idx[i + 0]].Pos, + v[idx[i + 1]].Pos, + v[idx[i + 2]].TCoords, + v[idx[i + 0]].TCoords, + v[idx[i + 1]].TCoords); + if (recalculateNormals) + v[idx[i + 2]].Normal = localNormal; + } + } + } +} + + +//! Recalculates tangents for a tangent mesh buffer +void CMeshManipulator::recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) const +{ + if (buffer && (buffer->getVertexType() == video::EVT_TANGENTS)) + { + if (buffer->getIndexType() == video::EIT_16BIT) + recalculateTangentsT(buffer, recalculateNormals, smooth, angleWeighted); + else + recalculateTangentsT(buffer, recalculateNormals, smooth, angleWeighted); + } +} + + +//! Recalculates tangents for all tangent mesh buffers +void CMeshManipulator::recalculateTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) const +{ + if (!mesh) + return; + + const u32 meshBufferCount = mesh->getMeshBufferCount(); + for (u32 b = 0; b < meshBufferCount; ++b) + { + recalculateTangents(mesh->getMeshBuffer(b), recalculateNormals, smooth, angleWeighted); + } +} + + +namespace +{ + //! Creates a planar texture mapping on the meshbuffer + template + void makePlanarTextureMappingT(scene::IMeshBuffer* buffer, f32 resolution) + { + u32 idxcnt = buffer->getIndexCount(); + T* idx = reinterpret_cast(buffer->getIndices()); + + for (u32 i = 0; i < idxcnt; i += 3) + { + core::plane3df p(buffer->getPosition(idx[i + 0]), buffer->getPosition(idx[i + 1]), buffer->getPosition(idx[i + 2])); + p.Normal.X = fabsf(p.Normal.X); + p.Normal.Y = fabsf(p.Normal.Y); + p.Normal.Z = fabsf(p.Normal.Z); + // calculate planar mapping worldspace coordinates + + if (p.Normal.X > p.Normal.Y && p.Normal.X > p.Normal.Z) + { + for (u32 o = 0; o != 3; ++o) + { + buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).Y * resolution; + buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Z * resolution; + } + } + else + if (p.Normal.Y > p.Normal.X && p.Normal.Y > p.Normal.Z) + { + for (u32 o = 0; o != 3; ++o) + { + buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).X * resolution; + buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Z * resolution; + } + } + else + { + for (u32 o = 0; o != 3; ++o) + { + buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).X * resolution; + buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Y * resolution; + } + } + } + } +} + //! Recalculates all normals of the mesh buffer. /** \param buffer: Mesh buffer on which the operation is performed. */ void CMeshManipulator::recalculateNormals(IMeshBuffer *buffer, bool smooth, bool angleWeighted) const diff --git a/irr/src/CMeshManipulator.h b/irr/src/CMeshManipulator.h index 0377d6a3a..58b8e9ffc 100644 --- a/irr/src/CMeshManipulator.h +++ b/irr/src/CMeshManipulator.h @@ -29,6 +29,12 @@ public: \param smooth: Whether to use smoothed normals. */ void recalculateNormals(IMeshBuffer *buffer, bool smooth = false, bool angleWeighted = false) const override; + //! Recalculates tangents, requires a tangent mesh buffer + virtual void recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false) const _IRR_OVERRIDE_; + + //! Recalculates tangents, requires a tangent mesh + virtual void recalculateTangents(IMesh* mesh, bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false) const _IRR_OVERRIDE_; + //! Clones a static IMesh into a modifiable SMesh. SMesh *createMeshCopy(scene::IMesh *mesh) const override; diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 071b03132..5bbd54c8a 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -40,10 +40,11 @@ with this program; if not, write to the Free Software Foundation, Inc., MeshMakeData */ -MeshMakeData::MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders): +MeshMakeData::MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders, bool use_tangent_vertices): side_length(side_length), nodedef(ndef), - m_use_shaders(use_shaders) + m_use_shaders(use_shaders), + m_use_tangent_vertices(use_tangent_vertices) {} void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos) @@ -617,6 +618,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs for (auto &m : m_mesh) m = make_irr(); m_enable_shaders = data->m_use_shaders; + m_use_tangent_vertices = data->m_use_tangent_vertices; auto mesh_grid = client->getMeshGrid(); v3s16 bp = data->m_blockpos; @@ -752,27 +754,44 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs p.layer.applyMaterialOptions(material); } - scene::SMeshBuffer *buf = new scene::SMeshBuffer(); - buf->Material = material; - if (p.layer.isTransparent()) { - buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0); - - MeshTriangle t; - t.buffer = buf; - m_transparent_triangles.reserve(p.indices.size() / 3); - for (u32 i = 0; i < p.indices.size(); i += 3) { - t.p1 = p.indices[i]; - t.p2 = p.indices[i + 1]; - t.p3 = p.indices[i + 2]; - t.updateAttributes(); - m_transparent_triangles.push_back(t); - } - } else { - buf->append(&p.vertices[0], p.vertices.size(), + if (m_use_tangent_vertices && !p.layer.isTransparent()) { + scene::SMeshBufferTangents* buf = new scene::SMeshBufferTangents(); + buf->Material = material; + std::vector vertices; + vertices.reserve(p.vertices.size()); + for (video::S3DVertex &v : p.vertices) + vertices.push_back(video::S3DVertexTangents(v.Pos, v.Normal, v.Color, v.TCoords)); + buf->append(&vertices[0], vertices.size(), &p.indices[0], p.indices.size()); + buf->recalculateBoundingBox(); + scene::IMeshManipulator* meshmanip = + client->getSceneManager()->getMeshManipulator(); + meshmanip->recalculateTangents(buf); + mesh->addMeshBuffer(buf); + buf->drop(); + } else { + scene::SMeshBuffer *buf = new scene::SMeshBuffer(); + buf->Material = material; + if (p.layer.isTransparent()) { + buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0); + + MeshTriangle t; + t.buffer = buf; + m_transparent_triangles.reserve(p.indices.size() / 3); + for (u32 i = 0; i < p.indices.size(); i += 3) { + t.p1 = p.indices[i]; + t.p2 = p.indices[i + 1]; + t.p3 = p.indices[i + 2]; + t.updateAttributes(); + m_transparent_triangles.push_back(t); + } + } else { + buf->append(&p.vertices[0], p.vertices.size(), + &p.indices[0], p.indices.size()); + } + mesh->addMeshBuffer(buf); + buf->drop(); } - mesh->addMeshBuffer(buf); - buf->drop(); } if (mesh) { diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index c52df5ed3..56b23a4a3 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -51,8 +51,9 @@ struct MeshMakeData const NodeDefManager *nodedef; bool m_use_shaders; + bool m_use_tangent_vertices; - MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders); + MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders, bool use_tangent_vertices = false); /* Copy block data manually (to allow optimizations by the caller) @@ -251,6 +252,7 @@ private: v3f m_bounding_sphere_center; bool m_enable_shaders; + bool m_use_tangent_vertices; // Must animate() be called before rendering? bool m_has_animation; diff --git a/src/client/mesh_generator_thread.cpp b/src/client/mesh_generator_thread.cpp index 21656aa6e..a48b7fdf0 100644 --- a/src/client/mesh_generator_thread.cpp +++ b/src/client/mesh_generator_thread.cpp @@ -55,6 +55,7 @@ MeshUpdateQueue::MeshUpdateQueue(Client *client): m_client(client) { m_cache_enable_shaders = g_settings->getBool("enable_shaders"); + m_cache_use_tangent_vertices = m_cache_enable_shaders && g_settings->getBool("enable_bumpmaps"); m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); } @@ -192,7 +193,7 @@ void MeshUpdateQueue::done(v3s16 pos) void MeshUpdateQueue::fillDataFromMapBlocks(QueuedMeshUpdate *q) { auto mesh_grid = m_client->getMeshGrid(); - MeshMakeData *data = new MeshMakeData(m_client->ndef(), MAP_BLOCKSIZE * mesh_grid.cell_size, m_cache_enable_shaders); + MeshMakeData *data = new MeshMakeData(m_client->ndef(), MAP_BLOCKSIZE * mesh_grid.cell_size, m_cache_enable_shaders, m_cache_use_tangent_vertices); q->data = data; data->fillBlockDataBegin(q->p); diff --git a/src/client/mesh_generator_thread.h b/src/client/mesh_generator_thread.h index 607bc66df..5b6729364 100644 --- a/src/client/mesh_generator_thread.h +++ b/src/client/mesh_generator_thread.h @@ -86,6 +86,7 @@ private: // TODO: Add callback to update these when g_settings changes bool m_cache_enable_shaders; + bool m_cache_use_tangent_vertices; bool m_cache_smooth_lighting; void fillDataFromMapBlocks(QueuedMeshUpdate *q); diff --git a/src/lighting.h b/src/lighting.h index 85e62b9d0..38c3e70de 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -68,7 +68,7 @@ struct Vignette { * Colors in ASL CDL follow the following equation: * * out = pow(in * slope + offset, power) - * + * */ struct ColorDecisionList { core::vector3df slope{1.2, 1.0, 0.8};