PK ‚ýJëüœ%ÌÌ diff.patchdiff -ur --binary model3emu/Src/Graphics/New3D/Model.cpp model3emu-patch/Src/Graphics/New3D/Model.cpp --- model3emu/Src/Graphics/New3D/Model.cpp 2017-07-29 14:28:38.000000000 +0200 +++ model3emu-patch/Src/Graphics/New3D/Model.cpp 2017-07-29 00:33:10.000000000 +0200 @@ -8,6 +8,7 @@ currentTexOffsetY = 0; currentPage = 0; currentClipStatus = Clip::INTERCEPT; + currentModelScale = 0; } bool NodeAttributes::Push() @@ -25,6 +26,7 @@ na.texOffsetX = currentTexOffsetX; na.texOffsetY = currentTexOffsetY; na.clip = currentClipStatus; + na.modelScale = currentModelScale; m_vecAttribs.push_back(na); @@ -43,6 +45,7 @@ currentTexOffsetX = last->texOffsetX; currentTexOffsetY = last->texOffsetY; currentClipStatus = last->clip; + currentModelScale = last->modelScale; m_vecAttribs.pop_back(); @@ -60,6 +63,7 @@ currentTexOffsetX = 0; currentTexOffsetY = 0; currentClipStatus = Clip::INTERCEPT; + currentModelScale = 0; m_vecAttribs.clear(); } diff -ur --binary model3emu/Src/Graphics/New3D/Model.h model3emu-patch/Src/Graphics/New3D/Model.h --- model3emu/Src/Graphics/New3D/Model.h 2017-07-29 14:28:38.000000000 +0200 +++ model3emu-patch/Src/Graphics/New3D/Model.h 2017-07-29 00:33:10.000000000 +0200 @@ -83,6 +83,7 @@ bool clockWise = true; // we need to check if the matrix will change the winding bool layered = false; // stencil poly bool highPriority = false; // rendered over the top + float modelScale = 0.0f; // lighting bool lighting = false; @@ -166,6 +167,7 @@ int currentTexOffsetY; int currentPage; Clip currentClipStatus; + float currentModelScale; private: @@ -175,6 +177,7 @@ int texOffsetY; int page; Clip clip; + float modelScale; }; std::vector m_vecAttribs; }; diff -ur --binary model3emu/Src/Graphics/New3D/New3D.cpp model3emu-patch/Src/Graphics/New3D/New3D.cpp --- model3emu/Src/Graphics/New3D/New3D.cpp 2017-07-29 14:28:38.000000000 +0200 +++ model3emu-patch/Src/Graphics/New3D/New3D.cpp 2017-07-29 00:33:10.000000000 +0200 @@ -486,6 +486,11 @@ // multiply matrix, if specified else if (matrixOffset) { MultMatrix(matrixOffset,m_modelMat); + // Get model scale: + // Is the correct value set only for culling nodes + // with multiplication matrix applied ? + if (!m_offset && (node[0x00] & 0x02)) + m_nodeAttribs.currentModelScale = *(float *)&node[0x01]; } uCullRadius = node[9 - m_offset] & 0xFFFF; @@ -766,7 +771,7 @@ vp->lightingParams[0] = *(float *)&vpnode[0x05]; // sun X vp->lightingParams[1] = -*(float *)&vpnode[0x06]; // sun Y (- to convert to ogl cordinate system) vp->lightingParams[2] = -*(float *)&vpnode[0x04]; // sun Z (- to convert to ogl cordinate system) - vp->lightingParams[3] = std::max(0.f, std::min(*(float *)&vpnode[0x07], 1.0f)); // sun intensity (clamp to 0-1) + vp->lightingParams[3] = *(float *)&vpnode[0x07]; // sun intensity vp->lightingParams[4] = (float)((vpnode[0x24] >> 8) & 0xFF) * (1.0f / 255.0f); // ambient intensity vp->lightingParams[5] = 0.0; // reserved @@ -774,6 +779,9 @@ m_vpAmbient = vp->lightingParams[4]; // cache this + // Sunlight clamping hack (for Magical Truck Adventure) + if (!(vp->lightingParams[3] < 2.0f)) vp->lightingParams[3] /= 255.0f; + // Spotlight int spotColorIdx = (vpnode[0x20] >> 11) & 7; // spotlight color index int spotFogColorIdx = (vpnode[0x20] >> 8) & 7; // spotlight on fog color index @@ -989,6 +997,7 @@ currentMesh->polyAlpha = ph.PolyAlpha(); currentMesh->lighting = ph.LightEnabled() && !ph.FixedShading(); currentMesh->highPriority = ph.HighPriority(); + currentMesh->modelScale = m_nodeAttribs.currentModelScale; if (ph.Layered() || (!ph.TexEnabled() && ph.PolyAlpha())) { currentMesh->layered = true; diff -ur --binary model3emu/Src/Graphics/New3D/R3DShader.cpp model3emu-patch/Src/Graphics/New3D/R3DShader.cpp --- model3emu/Src/Graphics/New3D/R3DShader.cpp 2017-07-29 14:28:38.000000000 +0200 +++ model3emu-patch/Src/Graphics/New3D/R3DShader.cpp 2017-07-29 14:32:25.989257800 +0200 @@ -5,21 +5,80 @@ static const char *vertexShaderR3D = R"glsl( +#define ROUND_PRECISION 100.0 + // uniforms uniform float fogIntensity; uniform float fogDensity; uniform float fogStart; +uniform float modelScale; +uniform bool lightEnable; // lighting enabled (1.0) or luminous (0.0), drawn at full intensity -//outputs to fragment shader +// outputs to fragment shader varying float fsFogFactor; varying vec3 fsViewVertex; varying vec3 fsViewNormal; // per vertex normal vector varying vec4 fsColor; +// helper functions +vec3 getScale(in mat3 matrix) +{ + vec3 scale; + + scale.x = length(matrix[0]); + scale.y = length(matrix[1]); + scale.z = length(matrix[2]); + + return scale; +} + +ivec3 roundVec(in vec3 vector) +{ + ivec3 roundVec; + + roundVec = int(round(vector * vec3(ROUND_PRECISION))); + + return roundVec; +} + +bool isIsotropic(in vec3 vector) +{ + bool isIsotropic; + vec3 roundVec; + + roundVec = roundVec(vector) / vec3(ROUND_PRECISION); + isIsotropic = (abs(roundVec.x - roundVec.y) < 0.1 && abs(roundVec.x - roundVec.z) < 0.1); + + return isIsotropic; +} + +// MAIN void main(void) { + mat3 norMatrix = mat3(gl_ModelViewMatrix); + vec3 verNormal = gl_Normal; + + if (lightEnable) { + vec3 scaleFactor = getScale(norMatrix); + vec3 scaleFactorR = roundVec(scaleFactor) / vec3(ROUND_PRECISION); + bool isoScale = isIsotropic(scaleFactorR); + + if (isoScale) { + if (scaleFactorR == vec3(1.0)) { + /// Skip normalization of zero vectors (division by zero) /// + float verNorLength = length(verNormal); + if (verNorLength > 0.0) + verNormal /= vec3(verNorLength); + } + else if (scaleFactorR.x > 1.0) + verNormal /= scaleFactor; + else if (scaleFactorR.x < 1.0 && modelScale > 0.0) + verNormal /= scaleFactor; + } + } + fsViewVertex = vec3(gl_ModelViewMatrix * gl_Vertex); - fsViewNormal = normalize(gl_NormalMatrix * gl_Normal); + fsViewNormal = norMatrix * verNormal; float z = length(fsViewVertex); fsFogFactor = fogIntensity * clamp(fogStart + z * fogDensity, 0.0, 1.0); @@ -200,6 +259,7 @@ m_shininess = 0; m_specularCoefficient = 0; m_microTexScale = 0; + m_modelScale = 0.0f; m_matDet = MatDet::notset; @@ -255,6 +315,7 @@ m_locSpotRange = glGetUniformLocation(m_shaderProgram, "spotRange"); m_locSpotColor = glGetUniformLocation(m_shaderProgram, "spotColor"); m_locSpotFogColor = glGetUniformLocation(m_shaderProgram, "spotFogColor"); + m_locModelScale = glGetUniformLocation(m_shaderProgram, "modelScale"); return success; } @@ -337,6 +398,11 @@ m_specularCoefficient = m->specularCoefficient; } + if (m_dirtyMesh || m->modelScale != m_modelScale) { + glUniform1f(m_locModelScale, m->modelScale); + m_modelScale = m->modelScale; + } + if (m_dirtyMesh || m->layered != m_layered) { m_layered = m->layered; if (m_layered) { diff -ur --binary model3emu/Src/Graphics/New3D/R3DShader.h model3emu-patch/Src/Graphics/New3D/R3DShader.h --- model3emu/Src/Graphics/New3D/R3DShader.h 2017-07-29 14:28:38.000000000 +0200 +++ model3emu-patch/Src/Graphics/New3D/R3DShader.h 2017-07-29 00:33:10.000000000 +0200 @@ -35,6 +35,7 @@ GLint m_locMicroTexScale; GLint m_locBaseTexSize; GLint m_locTextureInverted; + GLint m_locModelScale; // cached mesh values bool m_textured1; @@ -50,6 +51,7 @@ float m_microTexScale; float m_baseTexSize[2]; bool m_textureInverted; + float m_modelScale; // cached model values enum class MatDet { notset, negative, positive, zero }; PK ‚ýJëüœ%ÌÌ $ diff.patch Ö¬PLuÓÖ¬PLuÓƒý‹úÓPK\ô