diff --git a/Src/Graphics/New3D/Model.h b/Src/Graphics/New3D/Model.h index 4da3081..8ef6b67 100644 --- a/Src/Graphics/New3D/Model.h +++ b/Src/Graphics/New3D/Model.h @@ -149,6 +149,7 @@ struct Mesh // lighting bool fixedShading = false; + bool smoothShading = false; bool lighting = false; bool specular = false; float shininess = 0; diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index a26f8d7..d494eb5 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -1246,6 +1246,7 @@ void CNew3D::SetMeshValues(SortingMesh *currentMesh, PolyHeader &ph) currentMesh->fogIntensity = ph.LightModifier(); currentMesh->translatorMap = ph.TranslatorMap(); currentMesh->noLosReturn = ph.NoLosReturn(); + currentMesh->smoothShading = ph.SmoothShading(); if (currentMesh->textured) { diff --git a/Src/Graphics/New3D/R3DShader.cpp b/Src/Graphics/New3D/R3DShader.cpp index 5855b5d..ba2cd45 100644 --- a/Src/Graphics/New3D/R3DShader.cpp +++ b/Src/Graphics/New3D/R3DShader.cpp @@ -31,6 +31,7 @@ void R3DShader::Start() m_noLosReturn = false; m_textureInverted = false; m_fixedShading = false; + m_smoothShading = false; m_translatorMap = false; m_modelScale = 1.0f; m_nodeAlpha = 1.0f; @@ -132,6 +133,7 @@ bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader) m_locSpecularValue = glGetUniformLocation(m_shaderProgram, "specularValue"); m_locSpecularEnabled = glGetUniformLocation(m_shaderProgram, "specularEnabled"); m_locFixedShading = glGetUniformLocation(m_shaderProgram, "fixedShading"); + m_locSmoothShading = glGetUniformLocation(m_shaderProgram, "smoothShading"); m_locTranslatorMap = glGetUniformLocation(m_shaderProgram, "translatorMap"); m_locSpotEllipse = glGetUniformLocation(m_shaderProgram, "spotEllipse"); @@ -294,6 +296,11 @@ void R3DShader::SetMeshUniforms(const Mesh* m) m_fixedShading = m->fixedShading; } + if (m_dirtyMesh || m->smoothShading != m_smoothShading) { + glUniform1i(m_locSmoothShading, m->smoothShading); + m_smoothShading = m->smoothShading; + } + if (m_dirtyMesh || m->translatorMap != m_translatorMap) { glUniform1i(m_locTranslatorMap, m->translatorMap); m_translatorMap = m->translatorMap; diff --git a/Src/Graphics/New3D/R3DShader.h b/Src/Graphics/New3D/R3DShader.h index 610b8d0..734728a 100644 --- a/Src/Graphics/New3D/R3DShader.h +++ b/Src/Graphics/New3D/R3DShader.h @@ -67,6 +67,7 @@ private: float m_specularValue; bool m_specularEnabled; bool m_fixedShading; + bool m_smoothShading; bool m_translatorMap; bool m_polyAlpha; int m_texturePage; @@ -109,6 +110,7 @@ private: GLint m_locSpecularValue; GLint m_locSpecularEnabled; GLint m_locFixedShading; + GLint m_locSmoothShading; GLint m_locSpotEllipse; GLint m_locSpotRange; diff --git a/Src/Graphics/New3D/R3DShaderQuads.h b/Src/Graphics/New3D/R3DShaderQuads.h index 33866c7..6b93586 100644 --- a/Src/Graphics/New3D/R3DShaderQuads.h +++ b/Src/Graphics/New3D/R3DShaderQuads.h @@ -216,6 +216,7 @@ uniform float fogStart; uniform float fogAttenuation; uniform float fogAmbient; uniform bool fixedShading; +uniform bool smoothShading; uniform int hardwareStep; uniform int colourLayer; uniform bool polyAlpha; @@ -464,20 +465,27 @@ void main() // for now assume fixed shading doesn't work with specular if (specularEnabled) { - float exponent, NdotL, specularFactor; - vec4 biasIndex, expIndex, multIndex; + float specularFactor; - // Always clamp floor to zero, we don't want deep black areas - NdotL = max(0.0,sunFactor); + if (smoothShading) + { + // Always clamp floor to zero + float NdotL = max(0.0, sunFactor); - expIndex = vec4(8.0, 16.0, 32.0, 64.0); - multIndex = vec4(2.0, 2.0, 3.0, 4.0); - biasIndex = vec4(0.95, 0.95, 1.05, 1.0); - exponent = expIndex[int(shininess)] / biasIndex[int(shininess)]; - - specularFactor = pow(NdotL, exponent); - specularFactor *= multIndex[int(shininess)]; - specularFactor *= biasIndex[int(shininess)]; + vec4 expIndex = vec4(8.0, 16.0, 32.0, 64.0); + vec4 multIndex = vec4(1.6, 1.6, 2.4, 3.2); + float exponent = expIndex[int(shininess)]; + + specularFactor = pow(NdotL, exponent); + specularFactor *= multIndex[int(shininess)]; + } + else + { + // flat shaded polys use Phong reflection model (R dot V) without any exponent or multiplier + // V = (0.0, 0.0, 1.0) is used by Model 3 as a fast approximation, so R dot V = R.z + vec3 R = reflect(-sunVector, fsViewNormal); + specularFactor = max(0.0, R.z); + } specularFactor *= specularValue; specularFactor *= lighting[1].x; diff --git a/Src/Graphics/New3D/R3DShaderTriangles.h b/Src/Graphics/New3D/R3DShaderTriangles.h index e6968d7..ee45bda 100644 --- a/Src/Graphics/New3D/R3DShaderTriangles.h +++ b/Src/Graphics/New3D/R3DShaderTriangles.h @@ -104,6 +104,7 @@ uniform float fogStart; uniform float fogAttenuation; uniform float fogAmbient; uniform bool fixedShading; +uniform bool smoothShading; uniform int hardwareStep; uniform int colourLayer; uniform bool polyAlpha; @@ -235,20 +236,27 @@ void main() // for now assume fixed shading doesn't work with specular if (specularEnabled) { - float exponent, NdotL, specularFactor; - vec4 biasIndex, expIndex, multIndex; + float specularFactor; - // Always clamp floor to zero, we don't want deep black areas - NdotL = max(0.0,sunFactor); + if (smoothShading) + { + // Always clamp floor to zero + float NdotL = max(0.0, sunFactor); - expIndex = vec4(8.0, 16.0, 32.0, 64.0); - multIndex = vec4(2.0, 2.0, 3.0, 4.0); - biasIndex = vec4(0.95, 0.95, 1.05, 1.0); - exponent = expIndex[int(shininess)] / biasIndex[int(shininess)]; - - specularFactor = pow(NdotL, exponent); - specularFactor *= multIndex[int(shininess)]; - specularFactor *= biasIndex[int(shininess)]; + vec4 expIndex = vec4(8.0, 16.0, 32.0, 64.0); + vec4 multIndex = vec4(1.6, 1.6, 2.4, 3.2); + float exponent = expIndex[int(shininess)]; + + specularFactor = pow(NdotL, exponent); + specularFactor *= multIndex[int(shininess)]; + } + else + { + // flat shaded polys use Phong reflection model (R dot V) without any exponent or multiplier + // V = (0.0, 0.0, 1.0) is used by Model 3 as a fast approximation, so R dot V = R.z + vec3 R = reflect(-sunVector, fsViewNormal); + specularFactor = max(0.0, R.z); + } specularFactor *= specularValue; specularFactor *= lighting[1].x;