diff --git a/src/shaders/basicShader.frag b/src/shaders/basicShader.frag index 384b55c..bda0a55 100644 --- a/src/shaders/basicShader.frag +++ b/src/shaders/basicShader.frag @@ -13,6 +13,7 @@ uniform vec3 pointLight[3]; uniform vec4 pointLightCol[3]; uniform mat3 normalMatrix; uniform bool useNormalMap; +uniform bool useToon; in vec3 fNormal; in vec3 fPosition; @@ -22,98 +23,141 @@ in vec2 texCoords; out vec4 fColor; -vec4 calcDirLight(vec4 tex, vec3 fPos, vec3 fNorm) { - // Get lighting vectors - vec3 LightDirection = normalize(lDirection); - vec3 nviewDirection = normalize(fPos); - vec3 nfNormal; +const int lightLevels = 7; - if(useNormalMap) { - vec3 vNorm = texture(texNormal, texCoords).rgb; - nfNormal = normalMatrix * normalize(2 * vNorm - 1); - } else { - nfNormal = normalize(fNorm); - } +vec4 calcDirLight(vec4 tex, vec3 fPos, vec3 fNorm, mat3 tbn) { + // Get lighting vectors + vec3 LightDirection = tbn * normalize(lDirection); + vec3 nviewDirection = tbn * normalize(fPos); + vec3 nfNormal; + + if(useNormalMap) { + vec3 vNorm = texture(texNormal, texCoords).rgb; + nfNormal = normalize(2 * vNorm - 1); + } else { + nfNormal = normalize(tbn * fNorm); + } // Compute diffuse component - float diff = 0.2*max(0.0, dot(nfNormal, -LightDirection)); + float diff = 0.2*max(0.0, dot(nfNormal, -LightDirection)); // Compute specular component - vec3 Rl = reflect(-LightDirection, nfNormal); - float spec = 0.2*pow(max(0.0, dot(/*normalMatrix */ Rl, nviewDirection)), 64); + vec3 Rl = reflect(-LightDirection, nfNormal); + float spec = 0.2*pow(max(0.0, dot(Rl, -nviewDirection)), 64); - // Compute ambient component - float amb = 0.2; + // Compute ambient component + float amb = 0.2; - float mult = 1;//max(0.0, -LightDirection.y+1.5); + float mult = 2; - //return vec4(0); - return vec4(tex.xyz * (diff + amb + spec) * mult, tex.w); + float luminance = (diff + amb + spec); + + if(useToon){ + luminance = floor(luminance * lightLevels) / lightLevels; + } + + //return vec4(0); + return vec4(tex.xyz * luminance * mult, tex.w); } -vec4 calcPointLight(vec4 tex, vec3 fPos, vec3 fNorm, int i) { - // Get lighting vectors - vec3 LightDirection = normalize(pointLight[i] + fPos); - // vec3 nfNormal = normalize(fNorm); - vec3 nviewDirection = normalize(fPos); - vec3 nfNormal; +vec4 calcPointLight(vec4 tex, vec3 fPos, vec3 fNorm, mat3 tbn, int i) { + // Get lighting vectors + vec3 LightDirection = tbn * normalize(pointLight[i] + fPos); + // vec3 nfNormal = normalize(fNorm); + vec3 nviewDirection = tbn * normalize(fPos); + vec3 nfNormal; - if(useNormalMap) { - vec3 vNorm = texture(texNormal, texCoords).rgb; - //nfNormal = normalize(normalMatrix * vNorm); - nfNormal = normalMatrix * normalize(2 * vNorm - 1); - } else { - nfNormal = normalize(fNorm); - } + if(useNormalMap) { + vec3 vNorm = texture(texNormal, texCoords).rgb; + //nfNormal = normalize(normalMatrix * vNorm); + nfNormal = normalize(2 * vNorm - 1); + } else { + nfNormal = normalize(tbn * fNorm); + } - // Attenuation + // Attenuation float distance = length(nviewDirection - pointLight[i] - fPos) / 3; float attenuation = 0.5 + 1 / max(0.25, distance * distance); - // Compute diffuse component - float diff = 0.3 * max(0.0, dot(nfNormal, LightDirection)); + // Compute diffuse component + float diff = 0.0 * max(0.0, dot(nfNormal, LightDirection)); - // Compute specular component - vec3 Rl = reflect(-LightDirection, /*normalMatrix */ nfNormal); + // Compute specular component + vec3 Rl = reflect(-LightDirection, /*normalMatrix */ nfNormal); float spec = 0.5 * pow(max(0.0, dot(Rl, nviewDirection)), 32); - // Compute ambient component + // Compute ambient component float amb = 0.2; - return vec4(pointLightCol[i].xyz * attenuation * (amb + diff + spec) * tex.xyz, pointLightCol[i].w); + float luminance = (diff + amb + spec); + + if(useToon){ + luminance = floor(luminance * lightLevels) / lightLevels; + } + return vec4(pointLightCol[i].xyz * attenuation * luminance * tex.xyz, pointLightCol[i].w); } + +// ==================================================== +// CODE RÉFÉRENCÉ +// https://gamedev.stackexchange.com/questions/86530/is-it-possible-to-calculate-the-tbn-matrix-in-the-fragment-shader +// ==================================================== + +mat3 cotangent_frame( vec3 N, vec3 p, vec2 uv ) +{ + // get edge vectors of the pixel triangle + vec3 dp1 = dFdx( p ); + vec3 dp2 = dFdy( p ); + vec2 duv1 = dFdx( uv ); + vec2 duv2 = dFdy( uv ); + + // solve the linear system + vec3 dp2perp = cross( dp2, N ); + vec3 dp1perp = cross( N, dp1 ); + vec3 T = dp2perp * duv1.x + dp1perp * duv2.x; + vec3 B = dp2perp * duv1.y + dp1perp * duv2.y; + + // construct a scale-invariant frame + float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) ); + return mat3( T * invmax, B * invmax, N ); +} + +// ==================================================== +// FIN DU CODE RÉFÉRENCÉ +// ==================================================== + void main() { - vec4 texColor; - + vec4 texColor; + mat3 tbn = cotangent_frame(fNormal, fPosition, texCoords); if(isPickingMode){ - fColor = ifColor; - }else{ - if(drawTextures) { - texColor = texture(texCol, texCoords); - } else { - texColor = ifColor; - } - - if(isLightSource) { - fColor = texColor; - } else if(isSky) { - fColor = skyMult * normalize(texColor*texColor*texColor*2/1.41)*2; - } else if(isPhong) { - // Get lighting vectors - vec3 LightDirection = normalize(lDirection); - vec3 nfNormal = normalize(fNormal); - vec3 nviewDirection = normalize(fPosition); - - fColor = calcDirLight(texColor, fPosition, fNormal) - + calcPointLight(texColor, fPosition, fNormal, 0)/4 - + calcPointLight(texColor, fPosition, fNormal, 1)/4 - + calcPointLight(texColor, fPosition, fNormal, 2)/4; - } else { - fColor = texColor + ifColor; - } - } + fColor = ifColor; +}else{ + if(drawTextures) { + texColor = texture(texCol, texCoords); +} else { + texColor = ifColor; +} + + if(isLightSource) { + fColor = texColor; +} else if(isSky) { + fColor = skyMult * normalize(texColor*texColor*texColor*2/1.41)*2; +} else if(isPhong) { + // Get lighting vectors + vec3 LightDirection = normalize(lDirection); + vec3 nfNormal = normalize(fNormal); + vec3 nviewDirection = normalize(fPosition); + mat3 tbn = cotangent_frame(fNormal, fPosition, texCoords); + + fColor = calcDirLight(texColor, fPosition, fNormal, tbn) + + calcPointLight(texColor, fPosition, fNormal, tbn, 0)/4 + + calcPointLight(texColor, fPosition, fNormal, tbn, 1)/4 + + calcPointLight(texColor, fPosition, fNormal, tbn, 2)/4; +} else { + fColor = texColor + ifColor; +} +} } diff --git a/src/shaders/basicShader.vert b/src/shaders/basicShader.vert index ec89d4d..3ec3011 100644 --- a/src/shaders/basicShader.vert +++ b/src/shaders/basicShader.vert @@ -11,6 +11,7 @@ uniform bool isPhong; uniform bool isLightSource; uniform bool isPickingMode; uniform vec3 pointLight[3]; +uniform bool useToon; in vec4 vPosition; in vec3 vNormal; @@ -23,72 +24,72 @@ out vec3 fNormal; out vec3 vfNormal; vec4 calcDirLight(vec4 eye, vec3 fPos, vec3 fNorm) { - // Get lighting vectors - vec3 LightDirection = normalize(lDirection); + // Get lighting vectors + vec3 LightDirection = normalize(lDirection); vec3 nfNormal = normalize(fNorm); - vec3 nviewDirection = normalize(fPos); + vec3 nviewDirection = normalize(fPos); - // Compute diffuse component - float diff = 0.65 * max(0.0, dot(nfNormal, LightDirection)); + // Compute diffuse component + float diff = 0.65 * max(0.0, dot(nfNormal, LightDirection)); - // Compute specular component + // Compute specular component //vec3 Rl = normalize(-LightDirection+2.0*nfNormal*dot(nfNormal,LightDirection)); vec3 Rl = reflect(-LightDirection, fNorm); float spec = 0.1*pow(max(0.0, dot(Rl, nviewDirection)), 16); - // Compute ambient component - vec3 amb = vec3(0.1); + // Compute ambient component + vec3 amb = vec3(0.1); - // Vertex color (currently static, to be replaced with texture) - vec4 color = ifColor; + // Vertex color (currently static, to be replaced with texture) + vec4 color = ifColor; return color * vec4(amb + diff + spec, 1); } vec4 calcPointLight(vec4 eye, vec3 fPos, vec3 fNorm, int i) { - // Get lighting vectors - vec3 LightDirection = normalize(pointLight[i] - fPos); - vec3 nfNormal = normalize(fNorm); - vec3 nviewDirection = normalize(fPos); + // Get lighting vectors + vec3 LightDirection = normalize(pointLight[i] - fPos); + vec3 nfNormal = normalize(fNorm); + vec3 nviewDirection = normalize(fPos); - // Attenuation - float distance = length(pointLight[i] - nviewDirection); - float attenuation = 1.0f / (distance * distance); + // Attenuation + float distance = length(pointLight[i] - nviewDirection); + float attenuation = 1.0f / (distance * distance); - // Compute diffuse component - float diff = attenuation * 0.65 * max(0.0, dot(nfNormal, LightDirection)); + // Compute diffuse component + float diff = attenuation * 0.65 * max(0.0, dot(nfNormal, LightDirection)); - // Compute specular component - vec3 Rl = normalize(-LightDirection+2.0*nfNormal*dot(nfNormal,LightDirection)); - float spec = attenuation * 0.1*pow(max(0.0, dot(Rl, nviewDirection)), 16); + // Compute specular component + vec3 Rl = normalize(-LightDirection+2.0*nfNormal*dot(nfNormal,LightDirection)); + float spec = attenuation * 0.1*pow(max(0.0, dot(Rl, nviewDirection)), 16); - // Compute ambient component - vec3 amb = attenuation * vec3(0.1); + // Compute ambient component + vec3 amb = attenuation * vec3(0.1); - // Vertex color (currently static, to be replaced with texture) - vec4 color = ifColor; + // Vertex color (currently static, to be replaced with texture) + vec4 color = ifColor; - return 0.3 * color * vec4(amb + diff + spec, 1); + return 0.3 * color * vec4(amb + diff + spec, 1); } void main() { - vec4 vEyeCoord = mvMatrix * vPosition; - gl_Position = projMatrix * vEyeCoord; - fPosition = -vEyeCoord.xyz; - fNormal = normalMatrix * vNormal; + vec4 vEyeCoord = mvMatrix * vPosition; + gl_Position = projMatrix * vEyeCoord; + fPosition = -vEyeCoord.xyz; + fNormal = normalMatrix * vNormal; - texCoords = vUv; + texCoords = vUv; - ifColor = color; + ifColor = color; if(!isPickingMode && !isPhong && !isSky && !isLightSource) { - ifColor = calcDirLight(vEyeCoord, fPosition, fNormal) - + calcPointLight(vEyeCoord, fPosition, fNormal, 0) - + calcPointLight(vEyeCoord, fPosition, fNormal, 1) - + calcPointLight(vEyeCoord, fPosition, fNormal, 2); - } + ifColor = calcDirLight(vEyeCoord, fPosition, fNormal) + + calcPointLight(vEyeCoord, fPosition, fNormal, 0) + + calcPointLight(vEyeCoord, fPosition, fNormal, 1) + + calcPointLight(vEyeCoord, fPosition, fNormal, 2); + } } diff --git a/src/viewer/simpleViewer.cpp b/src/viewer/simpleViewer.cpp index 24c2ad2..04d9496 100644 --- a/src/viewer/simpleViewer.cpp +++ b/src/viewer/simpleViewer.cpp @@ -700,8 +700,13 @@ void Viewer::initShaders() if ((m_isPickingModeLoc = m_program->uniformLocation("isPickingMode")) < 0) qDebug() << "Unable to find m_shader location for" << "isPickingMode" << m_program->log(); + if ((m_useToonShading = m_program->uniformLocation("useToon")) < 0) + qDebug() << "Unable to find m_shader location for" << "useToon" << m_program->log(); + } + m_program->setUniformValue(m_isPhongLoc, true); + m_program->setUniformValue(m_useToonShading, true); m_program->setUniformValue(m_drawTextLoc, false); m_program->setUniformValue(m_isPickingModeLoc, false); m_program->setUniformValue(m_useNormalMap, true); diff --git a/src/viewer/simpleViewer.h b/src/viewer/simpleViewer.h index d880a6d..bd8b49a 100644 --- a/src/viewer/simpleViewer.h +++ b/src/viewer/simpleViewer.h @@ -131,11 +131,13 @@ private: QOpenGLShaderProgram *skyboxRenderShaderProgram; QOpenGLShaderProgram *m_program; QOpenGLShaderProgram *objShader; + int m_vPositionLocation; int m_texColor; int m_texNormal; int m_colorLocation; - int m_useNormalMap; + int m_useNormalMap; + int m_useToonShading; int m_projMatrixLocation; int m_mvMatrixLocation;