diff --git a/Source/Geometry/Mesh/imstkPointSet.cpp b/Source/Geometry/Mesh/imstkPointSet.cpp
index b2a1c7527642a0e4d29c7f354975b4de2a795e5f..702c81b67b10df8ca1338a6b510447eef97bc6b2 100644
--- a/Source/Geometry/Mesh/imstkPointSet.cpp
+++ b/Source/Geometry/Mesh/imstkPointSet.cpp
@@ -218,6 +218,17 @@ PointSet::getPointDataArray(const std::string& arrayName) const
     return &(it->second);
 }
 
+bool
+PointSet::hasPointDataArray(const std::string& arrayName) const
+{
+    auto it = m_pointDataMap.find(arrayName);
+    if (it == m_pointDataMap.end())
+    {
+        return false;
+    }
+    return true;
+}
+
 size_t
 PointSet::getNumVertices() const
 {
diff --git a/Source/Geometry/Mesh/imstkPointSet.h b/Source/Geometry/Mesh/imstkPointSet.h
index 479336e455bfd9240c5eb5c620513d3370eebc54..3f7f2ddd2002f750a45e540f5d259fd888581f2d 100644
--- a/Source/Geometry/Mesh/imstkPointSet.h
+++ b/Source/Geometry/Mesh/imstkPointSet.h
@@ -144,6 +144,11 @@ public:
     ///
     const StdVectorOfVectorf* getPointDataArray(const std::string& arrayName) const;
 
+    ///
+    /// \brief Check if a specific data array exists.
+    ///
+    bool hasPointDataArray(const std::string& arrayName) const;
+
     ///
     /// \brief Returns the number of total vertices in the mesh
     ///
diff --git a/Source/Geometry/Mesh/imstkSurfaceMesh.cpp b/Source/Geometry/Mesh/imstkSurfaceMesh.cpp
index 4ce703802bd01ae8583e95089f4c50d7d3ae6b52..b019a66b2929a54b8164fed93bae70d874fbbf89 100644
--- a/Source/Geometry/Mesh/imstkSurfaceMesh.cpp
+++ b/Source/Geometry/Mesh/imstkSurfaceMesh.cpp
@@ -62,6 +62,7 @@ SurfaceMesh::clear()
     m_vertexNeighborVertices.clear();
     m_triangleNormals.clear();
     m_vertexNormals.clear();
+    m_triangleTangents.clear();
 }
 
 void
@@ -135,6 +136,7 @@ void
 SurfaceMesh::computeTrianglesNormals()
 {
     m_triangleNormals.resize(m_trianglesVertices.size());
+    m_triangleTangents.resize(m_trianglesVertices.size());
 
     for (size_t triangleId = 0; triangleId < m_triangleNormals.size(); ++triangleId)
     {
@@ -145,6 +147,35 @@ SurfaceMesh::computeTrianglesNormals()
 
         m_triangleNormals.at(triangleId) = ((p1 - p0).cross(p2 - p0)).normalized();
     }
+
+    bool hasUVs = this->hasPointDataArray(m_defaultTCoords);
+    const StdVectorOfVectorf* UVs;
+
+    if (hasUVs)
+    {
+        UVs = this->getPointDataArray(m_defaultTCoords);
+    }
+
+    if (hasUVs)
+    {
+        for (size_t triangleId = 0; triangleId < m_triangleNormals.size(); ++triangleId)
+        {
+            const auto& t  = m_trianglesVertices.at(triangleId);
+            const auto& p0 = m_vertexPositions.at(t.at(0));
+            const auto& p1 = m_vertexPositions.at(t.at(1));
+            const auto& p2 = m_vertexPositions.at(t.at(2));
+            const auto& uv0 = (*UVs)[t.at(0)];
+            const auto& uv1 = (*UVs)[t.at(1)];
+            const auto& uv2 = (*UVs)[t.at(2)];
+
+            auto diffPos1 = p1 - p0;
+            auto diffPos2 = p2 - p0;
+            float diffUV1[2] = { uv1[0] - uv0[0], uv1[1] - uv0[1] };
+            float diffUV2[2] = { uv2[0] - uv0[0], uv2[1] - uv0[1] };
+
+            m_triangleTangents.at(triangleId) = (diffPos1 * diffUV2[1] - diffPos2 * diffUV1[0]) / (diffUV1[0] * diffUV2[1] - diffUV1[1] * diffUV2[0]);
+        }
+    }
 }
 
 void
@@ -158,21 +189,33 @@ SurfaceMesh::computeVertexNormals()
     }
 
     m_vertexNormals.resize(m_vertexPositions.size());
+    m_vertexTangents.resize(m_vertexPositions.size());
 
     this->computeTrianglesNormals();
 
     StdVectorOfVec3d temp_normals(m_vertexNormals.size());
+    StdVectorOfVec3d temp_tangents(m_vertexTangents.size());
     for (size_t vertexId = 0; vertexId < m_vertexNormals.size(); ++vertexId)
     {
         temp_normals[vertexId] = Vec3d(0, 0, 0);
+        temp_tangents[vertexId] = Vec3d(0, 0, 0);
         for (const size_t& triangleId : m_vertexNeighborTriangles.at(vertexId))
         {
             temp_normals[vertexId] += m_triangleNormals[triangleId];
+            temp_tangents[vertexId] += m_triangleTangents[triangleId];
         }
     }
 
     // Correct for UV seams
-    Vec3d normal;
+    Vec3d normal, tangent;
+    bool hasUVs = this->hasPointDataArray(m_defaultTCoords);
+    const StdVectorOfVectorf* UVs;
+
+    if (hasUVs)
+    {
+        UVs = this->getPointDataArray(m_defaultTCoords);
+    }
+
     for (size_t vertexId = 0; vertexId < m_vertexNormals.size(); ++vertexId)
     {
         NormalGroup group = {m_vertexPositions[vertexId], m_vertexNormals[vertexId]};
@@ -195,6 +238,13 @@ SurfaceMesh::computeVertexNormals()
 
         normal.normalize();
         m_vertexNormals[vertexId] = normal;
+
+        if (hasUVs)
+        {
+            tangent = temp_tangents[vertexId];
+            tangent.normalize();
+            m_vertexTangents[vertexId] = tangent;
+        }
     }
 }
 
diff --git a/Source/Geometry/Mesh/imstkSurfaceMesh.h b/Source/Geometry/Mesh/imstkSurfaceMesh.h
index e0438af10a27b33caeec8b099b41f5a733672592..f208c72167a61660bbdde8649bada2708c574912 100644
--- a/Source/Geometry/Mesh/imstkSurfaceMesh.h
+++ b/Source/Geometry/Mesh/imstkSurfaceMesh.h
@@ -236,6 +236,7 @@ protected:
     std::vector<NeighborsType> m_vertexNeighborVertices; ///> Neighbor vertices to vertices
 
     StdVectorOfVec3d m_triangleNormals; ///> Normals to the triangles
+    StdVectorOfVec3d m_triangleTangents; ///> Tangents to the triangles
     StdVectorOfVec3d m_vertexNormals; ///> Normals of the vertices
     StdVectorOfVec3d m_vertexTangents; ///> Tangents of the vertices
 
diff --git a/Source/Rendering/VulkanRenderer/VulkanShaders/mesh/mesh_vert.vert b/Source/Rendering/VulkanRenderer/VulkanShaders/mesh/mesh_vert.vert
index b80e71979c04a53fd472cf78c7c58ab459cfcc4c..c0b6d92db3d65c9328427756f99509a6f2c36c65 100644
--- a/Source/Rendering/VulkanRenderer/VulkanShaders/mesh/mesh_vert.vert
+++ b/Source/Rendering/VulkanRenderer/VulkanShaders/mesh/mesh_vert.vert
@@ -47,6 +47,7 @@ void main(void)
     vec4 tangent = normalize(locals.transform * vec4(normalize(vertexTangent), 0.0));
 
     vec4 bitangent = vec4(cross(normal.xyz, tangent.xyz), 0.0);
+    tangent = vec4(cross(bitangent.xyz, normal.xyz), 0.0);
 
     vertex.TBN = mat3(tangent.xyz, bitangent.xyz, normal.xyz);