From 9fb3ca03bda1596d1e1e30eed4885c53b37b0b76 Mon Sep 17 00:00:00 2001 From: Anakin Date: Thu, 19 Jan 2017 17:57:50 +0100 Subject: [PATCH] added specular, ambient light,... need to fix the texutre gamma correction, look at the todos --- QtMeshViewer/Header/FileInterface.h | 2 + QtMeshViewer/Header/OglViewerWidget.h | 4 +- QtMeshViewer/Resources/fshader.glsl | 63 ++++++++++++++++--------- QtMeshViewer/Source/GeometryEngine.cpp | 8 ++++ QtMeshViewer/Source/MshFile.cpp | 1 + QtMeshViewer/Source/OglViewerWidget.cpp | 7 +++ 6 files changed, 61 insertions(+), 24 deletions(-) diff --git a/QtMeshViewer/Header/FileInterface.h b/QtMeshViewer/Header/FileInterface.h index 0a611e3..de2f920 100644 --- a/QtMeshViewer/Header/FileInterface.h +++ b/QtMeshViewer/Header/FileInterface.h @@ -44,6 +44,8 @@ struct Material { QString name; QOpenGLTexture* texture = Q_NULLPTR; bool transparent = false; + float shininess = 80; //TODO: read from file + QVector3D specularColor = {1.0,1.0,1.0}; //TODO: read from file }; class FileInterface : public QObject diff --git a/QtMeshViewer/Header/OglViewerWidget.h b/QtMeshViewer/Header/OglViewerWidget.h index c4cd9b5..fd1e6a7 100644 --- a/QtMeshViewer/Header/OglViewerWidget.h +++ b/QtMeshViewer/Header/OglViewerWidget.h @@ -39,7 +39,9 @@ private: struct { QVector3D position = { 1,1,1 }; - QVector3D intensities = { 1,0.25,0.25 }; + QVector3D intensities = { 1,1,1 }; + float attenuationFactor = 0.2f; + float ambientCoefficient = 0.005f; } m_light; QOpenGLShaderProgram m_program; diff --git a/QtMeshViewer/Resources/fshader.glsl b/QtMeshViewer/Resources/fshader.glsl index f8a9fce..33d3d66 100644 --- a/QtMeshViewer/Resources/fshader.glsl +++ b/QtMeshViewer/Resources/fshader.glsl @@ -5,51 +5,68 @@ precision mediump float; #endif uniform mat3 n_matrix; +uniform vec3 cameraPosition; + uniform sampler2D texture; +uniform float materialShininess; +uniform vec3 materialSpecularColor; + +uniform bool b_transparent; +uniform bool b_light; uniform struct Light { vec3 position; vec3 intensities; + float attenuationFactor; + float ambientCoefficient; } light; -uniform bool b_transparent; -uniform bool b_light; - varying vec2 v_surfaceUV; varying vec3 v_surfacePosition; varying vec3 v_surfaceNormal; void main() { - // variables - vec3 diffuse; - - // get fragment color from texture - vec4 surfaceColor = vec4(texture2D(texture, v_surfaceUV)); - - // if not transparent, ignore alpha value and set it to 1 - if(!b_transparent) - surfaceColor.a = 1.0f; - if(b_light) { - // calculate normals in worldspace + // some values vec3 normalWorld = normalize(n_matrix * v_surfaceNormal); - - //get the surface - light vector (cause this is a point light) + vec4 surfaceColor = vec4(texture2D(texture, v_surfaceUV)); + if(!b_transparent) + surfaceColor.a = 1.0f; vec3 surfaceToLight = normalize(light.position - v_surfacePosition); + vec3 surfaceToCamera = normalize(cameraPosition - v_surfacePosition); - // calculate the brightness depending on the angle + // ambient + vec3 ambient = light.ambientCoefficient * surfaceColor.rgb * light.intensities; + + // diffuse float diffuseCoefficient = max(0.0, dot(normalWorld, surfaceToLight)); + vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities; - // result diffuse color - diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities; + // specular + float specularCoefficient = 0.0; + if(diffuseCoefficient > 0.0) + specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normalWorld))), materialShininess); + vec3 specular = specularCoefficient * materialSpecularColor * light.intensities; + + // attenuation + float distanceToLight = length(light.position - v_surfacePosition); + float attenuation = 1.0 / (1.0 + light.attenuationFactor * pow(distanceToLight, 2)); + + // linear color before gamma correction) + vec3 linearColor = ambient + attenuation * (diffuse + specular); + + // final color after gama correction + vec3 gamma = vec3(1.0/2.2); + gl_FragColor = vec4(pow(linearColor, gamma), surfaceColor.a); } else { - diffuse = surfaceColor.rgb; - } + vec4 surfaceColor = vec4(texture2D(texture, v_surfaceUV)); + if(!b_transparent) + surfaceColor.a = 1.0f; - // put all together - gl_FragColor = vec4(diffuse, surfaceColor.a); + gl_FragColor = surfaceColor; + } } diff --git a/QtMeshViewer/Source/GeometryEngine.cpp b/QtMeshViewer/Source/GeometryEngine.cpp index 3af4db4..fd79dad 100644 --- a/QtMeshViewer/Source/GeometryEngine.cpp +++ b/QtMeshViewer/Source/GeometryEngine.cpp @@ -176,12 +176,16 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program, bool wireframe) for (auto& it : m_drawList) { bool tmp_transparent(false); + float shininess; + QVector3D specularColor; // bind the correct texture if (it.textureIndex < m_materials->size() && m_materials->at(it.textureIndex).texture != Q_NULLPTR) { m_materials->at(it.textureIndex).texture->bind(); tmp_transparent = m_materials->at(it.textureIndex).transparent; + shininess = m_materials->at(it.textureIndex).shininess; + specularColor = m_materials->at(it.textureIndex).specularColor; } else { @@ -197,6 +201,10 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program, bool wireframe) // decide if this is transparent program->setUniformValue("b_transparent", tmp_transparent); + // set some material attributes + program->setUniformValue("materialShininess", shininess); + program->setUniformValue("materialSpecularColor", specularColor); + // Draw cube geometry using indices from VBO 1 if(wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); diff --git a/QtMeshViewer/Source/MshFile.cpp b/QtMeshViewer/Source/MshFile.cpp index 1a1dc5a..1325862 100644 --- a/QtMeshViewer/Source/MshFile.cpp +++ b/QtMeshViewer/Source/MshFile.cpp @@ -217,6 +217,7 @@ void MshFile::analyseMatdChunks(std::list& chunkList) { for (auto& it : chunkList) { + // TODO: don't load default texture, make it NULL //TODO: get information from flags // attributes if (!strcmp("ATRB", it->name)) diff --git a/QtMeshViewer/Source/OglViewerWidget.cpp b/QtMeshViewer/Source/OglViewerWidget.cpp index 3413548..5985ab4 100644 --- a/QtMeshViewer/Source/OglViewerWidget.cpp +++ b/QtMeshViewer/Source/OglViewerWidget.cpp @@ -234,6 +234,13 @@ void OglViewerWidget::paintGL() m_program.setUniformValue("b_light", m_lightOn); m_program.setUniformValue("light.position", m_light.position); m_program.setUniformValue("light.intensities", m_light.intensities); + m_program.setUniformValue("light.attenuationFactor", m_light.attenuationFactor); + m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient); + + // Set camera position + QMatrix4x4 rotateBack; + rotateBack.rotate(m_rotation.inverted()); + m_program.setUniformValue("cameraPosition", rotateBack * (-m_translation)); // Draw cube geometry m_dataEngine->drawGeometry(&m_program, m_wireframe);