diff --git a/QtMeshViewer/Header/GeometryEngine.h b/QtMeshViewer/Header/GeometryEngine.h
index 7464662b95bf0cc627a8641a50177279f85d82e7..5b551e5400b92eb59da321b70de48b952ca4a5a3 100644
--- a/QtMeshViewer/Header/GeometryEngine.h
+++ b/QtMeshViewer/Header/GeometryEngine.h
@@ -34,6 +34,7 @@ private:
 // functions
 private:
 	void clearData();
+	void setupPipeline(QOpenGLShaderProgram * program);
 
 public:
 	void drawGeometry(QOpenGLShaderProgram *program);
diff --git a/QtMeshViewer/Resources/fshader.glsl b/QtMeshViewer/Resources/fshader.glsl
index 4e5d7be601a4f5a6864e2fb229a52fefbb594987..b66d1edb22ec0a38d96d0f3328ea838890fe7563 100644
--- a/QtMeshViewer/Resources/fshader.glsl
+++ b/QtMeshViewer/Resources/fshader.glsl
@@ -22,6 +22,10 @@ uniform struct Light {
 	float ambientCoefficient;
 } light;
 
+attribute vec3 a_polyNorm;
+attribute vec3 a_polyTan;
+attribute vec3 a_polyBiTan;
+
 varying vec2 v_surfaceUV;
 varying vec3 v_surfacePosition;
 varying vec3 v_surfaceNormal;
diff --git a/QtMeshViewer/Source/GeometryEngine.cpp b/QtMeshViewer/Source/GeometryEngine.cpp
index 902f3a5583891c0939fc134e91542dfd09bcecef..da2a7982ec9d3577762021aa921365522088d9d2 100644
--- a/QtMeshViewer/Source/GeometryEngine.cpp
+++ b/QtMeshViewer/Source/GeometryEngine.cpp
@@ -52,26 +52,8 @@ void GeometryEngine::clearData()
 	m_drawList.clear();
 }
 
-void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
+void GeometryEngine::setupPipeline(QOpenGLShaderProgram *program)
 {
-	if (!m_arrayBuf.isCreated() || !m_indexBuf.isCreated())
-		return;
-
-	// Setup
-	// Tell OpenGL which VBOs to use
-	m_arrayBuf.bind();
-	m_indexBuf.bind();
-
-	// Allways normalize by this
-	QMatrix4x4 normMatrix;
-	float maxExtent = std::max(std::max(m_boundings.extents[0], m_boundings.extents[1]), m_boundings.extents[2]);
-	normMatrix.scale(1 / maxExtent);
-	normMatrix.translate(-m_boundings.center[0], -m_boundings.center[1], -m_boundings.center[2]);
-	program->setUniformValue("norm_matrix", normMatrix);
-
-	// Allways use texture unit 0
-	program->setUniformValue("texture", 0);
-
 	// Offset for position
 	quintptr offset = 0;
 
@@ -88,14 +70,63 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
 	program->enableAttributeArray(texcoordLocation);
 	program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData));
 
-	//Offset for normal
+	//Offset for vertexNormal
 	offset += sizeof(QVector2D);
 
 	// Tell OpenGL programmable pipeline how to locate vertex normal data
-	int normLocation = program->attributeLocation("a_normal");
-	program->enableAttributeArray(normLocation);
-	program->setAttributeBuffer(normLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
+	int vertNormLocation = program->attributeLocation("a_normal");
+	program->enableAttributeArray(vertNormLocation);
+	program->setAttributeBuffer(vertNormLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
+
+	//Offset for polygonNormal
+	offset += sizeof(QVector3D);
+
+	// Tell OpenGL programmable pipeline how to locate polygon normal data
+	int polyNormLocation = program->attributeLocation("a_polyNorm");
+	program->enableAttributeArray(polyNormLocation);
+	program->setAttributeBuffer(polyNormLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
+
+	//Offset for polygonTangent
+	offset += sizeof(QVector3D);
+
+	// Tell OpenGL programmable pipeline how to locate polygon tangent data
+	int polyTanLocation = program->attributeLocation("a_polyTan");
+	program->enableAttributeArray(polyTanLocation);
+	program->setAttributeBuffer(polyTanLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
+
+	//Offset for polygonBitangent
+	offset += sizeof(QVector3D);
+
+	// Tell OpenGL programmable pipeline how to locate polygon bitangent data
+	int polyBiTanLocation = program->attributeLocation("a_polyBiTan");
+	program->enableAttributeArray(polyBiTanLocation);
+	program->setAttributeBuffer(polyBiTanLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
+
+}
+
+void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
+{
+	if (!m_arrayBuf.isCreated() || !m_indexBuf.isCreated())
+		return;
+
+	// Setup
+	// Tell OpenGL which VBOs to use
+	m_arrayBuf.bind();
+	m_indexBuf.bind();
+
+	// Allways normalize by this
+	QMatrix4x4 normMatrix;
+	float maxExtent = std::max(std::max(m_boundings.extents[0], m_boundings.extents[1]), m_boundings.extents[2]);
+	normMatrix.scale(1 / maxExtent);
+	normMatrix.translate(-m_boundings.center[0], -m_boundings.center[1], -m_boundings.center[2]);
+	program->setUniformValue("norm_matrix", normMatrix);
+
+	// Allways use texture unit 0
+	program->setUniformValue("texture", 0);
 
+	//setup the pipeline
+	setupPipeline(program);
+	
 	// Paint
 
 	for (auto& it : m_drawList)