From 06d403d546057680535ce8760bc448ac517397f7 Mon Sep 17 00:00:00 2001 From: Anakin Date: Mon, 6 Feb 2017 14:53:05 +0100 Subject: [PATCH] support normal map now, support "glow" now, update preview.jpg --- QtMeshViewer/Resources/fshader.glsl | 140 ++++++++++++++---------- QtMeshViewer/Resources/vshader.glsl | 20 +++- QtMeshViewer/Source/GeometryEngine.cpp | 31 +++--- QtMeshViewer/Source/MshFile.cpp | 2 +- QtMeshViewer/Source/OglViewerWidget.cpp | 4 +- preview.jpg | Bin 44438 -> 50787 bytes 6 files changed, 114 insertions(+), 83 deletions(-) diff --git a/QtMeshViewer/Resources/fshader.glsl b/QtMeshViewer/Resources/fshader.glsl index d78d02a..12256d7 100644 --- a/QtMeshViewer/Resources/fshader.glsl +++ b/QtMeshViewer/Resources/fshader.glsl @@ -1,21 +1,26 @@ +#version 450 #ifdef GL_ES // Set default precision to medium precision mediump int; precision mediump float; #endif -uniform mat3 n_matrix; +uniform mat3 normalMatrix; uniform vec3 cameraPosition; -uniform sampler2D texture; -uniform sampler2D secondTexture; -uniform float materialShininess; -uniform vec3 materialSpecularColor; +uniform sampler2D tx0; +uniform sampler2D tx1; -uniform bool b_transparent; -uniform bool b_specular; -uniform bool b_normalmap; -uniform bool b_light; +uniform struct Material { + float shininess; + vec3 specularColor; + bool isTransparent; + bool hasSpecularmap; + bool hasNormalmap; + bool isGlow; +} material; + +uniform bool useLight; uniform struct Light { vec4 position; @@ -24,82 +29,99 @@ 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; +varying vec3 v_polyNorm; +varying vec3 v_polyTan; +varying vec3 v_polyBiTan; void main() { - if(b_light) + if(useLight && !material.isGlow) { - // some values - mat3 tbn = transpose(mat3(a_polyTan, a_polyBiTan, a_polyNorm)); - - vec3 finalNormal = normalize(n_matrix * v_surfaceNormal); - - // if(b_normalmap) - // { - // finalNormal = texture2D(secondTexture, v_surfaceUV).rgb; - // finalNormal = normalize(finalNormal * 2.0 -1.0) - // } - - vec4 surfaceColor = vec4(texture2D(texture, v_surfaceUV)); + // get the color and undo gamma correction + vec4 surfaceColor = vec4(texture2D(tx0, v_surfaceUV)); surfaceColor.rgb = pow(surfaceColor.rgb, vec3(2.2)); - - vec3 surfaceToLight; - float attenuation; - // directional light - if(light.position.w == 0.0f) - { - surfaceToLight = normalize(light.position.xyz); - } - // point light - else - { - surfaceToLight = normalize(light.position.xyz - v_surfacePosition); - } - - float distanceToLight = length(light.position.xyz - v_surfacePosition); - attenuation = 1.0 / (1.0 + light.attenuationFactor * pow(distanceToLight, 2)); + // attenutation depending on the distance to the light + float distanceToLight = length(light.position.xyz - v_surfacePosition); + float attenuation = 1.0 / (1.0 + light.attenuationFactor * pow(distanceToLight, 2)); + + // normal vector + vec3 normal = normalize(normalMatrix * v_surfaceNormal); + + // direction from surface to light depending on the light type + vec3 surfaceToLight; + if(light.position.w == 0.0) // directional light + surfaceToLight = normalize(light.position.xyz); + else // point light + surfaceToLight = normalize(light.position.xyz - v_surfacePosition); + + // direction from surface to camera vec3 surfaceToCamera = normalize(cameraPosition - v_surfacePosition); - // ambient + // adjust the values if material has normal map + if(material.hasNormalmap) + { + vec3 surfaceTangent = normalize(normalMatrix * v_polyTan); + vec3 surfaceBitangent = normalize(normalMatrix * -v_polyBiTan); + vec3 surfaceNormal = normalize(normalMatrix * v_surfaceNormal); + mat3 tbn = transpose(mat3(surfaceTangent, surfaceBitangent, surfaceNormal)); + normal = texture2D(tx1, v_surfaceUV).rgb; + normal = normalize(normal * 2.0 -1.0); + surfaceToLight = tbn * surfaceToLight; + surfaceToCamera = tbn * surfaceToCamera; + } + + + ///////////////////////////////////////////////////////////////////////////////////// + // ambient component + vec3 ambient = light.ambientCoefficient * surfaceColor.rgb * light.intensities; - // diffuse - float diffuseCoefficient = max(0.0, dot(finalNormal, surfaceToLight)); + + ///////////////////////////////////////////////////////////////////////////////////// + // diffuse component + + float diffuseCoefficient = max(0.0, dot(normal, surfaceToLight)); vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities; - // specular + + ///////////////////////////////////////////////////////////////////////////////////// + // specular component + float specularCoefficient = 0.0; if(diffuseCoefficient > 0.0) - specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, finalNormal))), materialShininess); - vec3 specColor; - if(b_specular) - specColor = vec3(surfaceColor.a); - else - specColor = materialSpecularColor; + specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), material.shininess); + + float specularWeight = 1; + if(material.hasSpecularmap) + specularWeight = surfaceColor.a; + vec3 specColor = specularWeight * material.specularColor; + vec3 specular = specularCoefficient * specColor * light.intensities; - // linear color before gamma correction) + ///////////////////////////////////////////////////////////////////////////////////// + // linear color before gamma correction vec3 linearColor = ambient + attenuation * (diffuse + specular); - // final color after gama correction + ///////////////////////////////////////////////////////////////////////////////////// + // gama correction vec3 gamma = vec3(1.0/2.2); - if(!b_transparent) - surfaceColor.a = 1.0f; + + if(!material.isTransparent) + surfaceColor.a = 1.0; + gl_FragColor = vec4(pow(linearColor, gamma), surfaceColor.a); } + // don't use light else { - vec4 surfaceColor = vec4(texture2D(texture, v_surfaceUV)); - if(!b_transparent) - surfaceColor.a = 1.0f; + vec4 surfaceColor = vec4(texture2D(tx0, v_surfaceUV)); + + if(!material.isTransparent) + surfaceColor.a = 1.0; gl_FragColor = surfaceColor; } diff --git a/QtMeshViewer/Resources/vshader.glsl b/QtMeshViewer/Resources/vshader.glsl index 19b792c..3b75892 100644 --- a/QtMeshViewer/Resources/vshader.glsl +++ b/QtMeshViewer/Resources/vshader.glsl @@ -1,29 +1,39 @@ +#version 450 #ifdef GL_ES // Set default precision to medium precision mediump int; precision mediump float; #endif -uniform mat4 vp_matrix; -uniform mat4 norm_matrix; -uniform mat4 m_matrix; +uniform mat4 viewProjection; +uniform mat4 normalizeModel; +uniform mat4 modelMatrix; attribute vec4 a_position; attribute vec2 a_texcoord; attribute vec3 a_normal; +attribute vec3 a_polyNorm; +attribute vec3 a_polyTan; +attribute vec3 a_polyBiTan; varying vec2 v_surfaceUV; varying vec3 v_surfacePosition; varying vec3 v_surfaceNormal; +varying vec3 v_polyNorm; +varying vec3 v_polyTan; +varying vec3 v_polyBiTan; void main() { // Calculate vertex position in screen space - gl_Position = vp_matrix * norm_matrix * m_matrix * a_position; + gl_Position = viewProjection * normalizeModel * modelMatrix * a_position; // Pass data to fragment shader // Value will be automatically interpolated to fragments inside polygon faces v_surfaceUV = a_texcoord; - v_surfacePosition = vec3(norm_matrix * m_matrix * a_position); + v_surfacePosition = vec3(normalizeModel * modelMatrix * a_position); v_surfaceNormal = a_normal; + v_polyNorm = a_polyNorm; + v_polyTan = a_polyTan; + v_polyBiTan = a_polyBiTan; } diff --git a/QtMeshViewer/Source/GeometryEngine.cpp b/QtMeshViewer/Source/GeometryEngine.cpp index 570e55c..1cc1004 100644 --- a/QtMeshViewer/Source/GeometryEngine.cpp +++ b/QtMeshViewer/Source/GeometryEngine.cpp @@ -5,7 +5,6 @@ #include "..\Header\OutputDevice.h" #include -#include "..\Header\Profiler.h" ///////////////////////////////////////////////////////////////////////// // constructor/destructor @@ -119,11 +118,11 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program) 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); + program->setUniformValue("normalizeModel", normMatrix); // Allways use texture unit 0 and 1 - program->setUniformValue("texture", 0); - program->setUniformValue("secondTexture", 1); + program->setUniformValue("tx0", 0); + program->setUniformValue("tx1", 1); //setup the pipeline setupPipeline(program); @@ -135,6 +134,7 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program) bool tmp_transparent(false); bool tmp_specular(false); bool tmp_normalmap(false); + bool tmp_glow(false); float shininess(0.0); QVector3D specularColor; @@ -155,6 +155,9 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program) m_materials->at(it.textureIndex).texture1->bind(1); } } + + if (m_materials->at(it.textureIndex).flags[0] || m_materials->at(it.textureIndex).flags[1] || m_materials->at(it.textureIndex).rendertype == 1) + tmp_glow = true; } else { @@ -163,19 +166,18 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program) } // Set model matrix - program->setUniformValue("m_matrix", it.modelMatrix); + program->setUniformValue("modelMatrix", it.modelMatrix); // Set normal matrix - program->setUniformValue("n_matrix", (normMatrix * it.modelMatrix).normalMatrix()); - - // set some more values - program->setUniformValue("b_transparent", tmp_transparent); - program->setUniformValue("b_specular", tmp_specular); - program->setUniformValue("b_normalmap", tmp_normalmap); + program->setUniformValue("normalMatrix", (normMatrix * it.modelMatrix).normalMatrix()); // set some material attributes - program->setUniformValue("materialShininess", shininess); - program->setUniformValue("materialSpecularColor", specularColor); + program->setUniformValue("material.shininess", shininess); + program->setUniformValue("material.specularColor", specularColor); + program->setUniformValue("material.isTransparent", tmp_transparent); + program->setUniformValue("material.hasSpecularmap", tmp_specular); + program->setUniformValue("material.hasNormalmap", tmp_normalmap); + program->setUniformValue("material.isGlow", tmp_glow); // Draw cube geometry using indices from VBO 1 glDrawElements(GL_TRIANGLES, it.size, GL_UNSIGNED_INT, (void*)(it.offset * sizeof(GLuint))); @@ -185,7 +187,6 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program) void GeometryEngine::loadFile(QString filePath) { - TIC("Start"); // cleanup old stuff and recreate buffers clearData(); m_arrayBuf.create(); @@ -260,7 +261,5 @@ void GeometryEngine::loadFile(QString filePath) clearData(); OutputDevice::getInstance()->print(QString(e.what()), 2); } - - TOC("End"); } diff --git a/QtMeshViewer/Source/MshFile.cpp b/QtMeshViewer/Source/MshFile.cpp index 96676f3..3d510a9 100644 --- a/QtMeshViewer/Source/MshFile.cpp +++ b/QtMeshViewer/Source/MshFile.cpp @@ -921,7 +921,7 @@ void MshFile::loadTexture(QOpenGLTexture *& destination, QString filepath, QStri if (!loadSuccess) { OutputDevice::getInstance()->print("WARNING: texture not found or corrupted: " + filename, 1); - + //TODO: use the correct diffuse color or return with null img = QImage(1, 1, QImage::Format_RGB32); img.fill(QColor(m_materials->back().diffuseColor[0] * 255, m_materials->back().diffuseColor[1] * 255, m_materials->back().diffuseColor[2] * 255)); filename += " *"; diff --git a/QtMeshViewer/Source/OglViewerWidget.cpp b/QtMeshViewer/Source/OglViewerWidget.cpp index 62916af..9399da8 100644 --- a/QtMeshViewer/Source/OglViewerWidget.cpp +++ b/QtMeshViewer/Source/OglViewerWidget.cpp @@ -143,10 +143,10 @@ void OglViewerWidget::paintGL() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set view-projection matrix - m_program.setUniformValue("vp_matrix", m_projection * m_camera->getMatrix()); + m_program.setUniformValue("viewProjection", m_projection * m_camera->getMatrix()); // Set Light values - m_program.setUniformValue("b_light", m_lightOn); + m_program.setUniformValue("useLight", 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); diff --git a/preview.jpg b/preview.jpg index 2d250f71df00a3778001294af9a32accd7d47821..3dd55da2e5c34b72e57b7e27ec030d173acd6e03 100644 GIT binary patch delta 23481 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 Cs9`z) delta 16739 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�UM+nqNo8$9MWv16dM(Oz_K0yO=?zTyy1a>}SP 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