From 6f6c98c671f62410561fd6253e48b5617d8b3505 Mon Sep 17 00:00:00 2001 From: Ian Curtis Date: Mon, 11 May 2020 09:05:46 +0000 Subject: [PATCH] The translator map seems to work with paletted colour values too, and the result is not clamped. Colours are passed to the GPU as unsigned bytes to multiplying by 16 will overflow, so we do the logic in the shader. If we passed floats we could skip the shader logic. --- Src/Graphics/New3D/Model.h | 1 + Src/Graphics/New3D/New3D.cpp | 8 +------- Src/Graphics/New3D/PolyHeader.cpp | 20 ++++++++++---------- Src/Graphics/New3D/R3DShader.cpp | 7 +++++++ Src/Graphics/New3D/R3DShader.h | 2 ++ Src/Graphics/New3D/R3DShaderQuads.h | 14 +++++++++++++- Src/Graphics/New3D/R3DShaderTriangles.h | 14 +++++++++++++- 7 files changed, 47 insertions(+), 19 deletions(-) diff --git a/Src/Graphics/New3D/Model.h b/Src/Graphics/New3D/Model.h index 3d8b829..5c0e0b5 100644 --- a/Src/Graphics/New3D/Model.h +++ b/Src/Graphics/New3D/Model.h @@ -150,6 +150,7 @@ struct Mesh bool layered = false; // stencil poly bool highPriority = false; // rendered over the top bool transLSelect = false; // actually the transparency layer, false = layer 0, true = layer 1 + bool translatorMap = false; // colours are multiplied by 16 // lighting bool fixedShading = false; diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index 1e5535a..c8cd6f5 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -994,6 +994,7 @@ void CNew3D::SetMeshValues(SortingMesh *currentMesh, PolyHeader &ph) currentMesh->shininess = ph.Shininess(); currentMesh->specularValue = ph.SpecularValue(); currentMesh->fogIntensity = ph.LightModifier(); + currentMesh->translatorMap = ph.TranslatorMap(); if (currentMesh->textured) { @@ -1135,16 +1136,9 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data) p.faceColour[0] = ((m_polyRAM[m_colorTableAddr + colorIdx] >> 16) & 0xFF); } else { - p.faceColour[0] = ((ph.header[4] >> 24)); p.faceColour[1] = ((ph.header[4] >> 16) & 0xFF); p.faceColour[2] = ((ph.header[4] >> 8) & 0xFF); - - if (ph.TranslatorMap()) { - p.faceColour[0] = std::min((p.faceColour[0] * 255) / 16, 255); // When the translator map is enabled, max colour seems to be 16. Why not 4 bits? - p.faceColour[1] = std::min((p.faceColour[1] * 255) / 16, 255); // We clamp the result because virtua on will overflow for only the smoke effects - p.faceColour[2] = std::min((p.faceColour[2] * 255) / 16, 255); // It's passing 33 instead of a max of 16. - } } p.faceColour[3] = ph.Transparency(); diff --git a/Src/Graphics/New3D/PolyHeader.cpp b/Src/Graphics/New3D/PolyHeader.cpp index dee93fe..12dfae0 100644 --- a/Src/Graphics/New3D/PolyHeader.cpp +++ b/Src/Graphics/New3D/PolyHeader.cpp @@ -398,16 +398,16 @@ UINT64 PolyHeader::Hash() hash |= (UINT64)(header[3] & 0xFF); // bits 0-7 tex width / height / uv smooth hash |= (UINT64)(((header[4] & 0x1F) << 1) | ((header[5] >> 7) & 1)) << 8; // bits 8-13 x offset hash |= (UINT64)(header[5] & 0x1F) << 14; // bits 14-18 y offset - hash |= (UINT64)Page() << 19; // bits 19 page - hash |= (UINT64)DoubleSided() << 20; // bits 20 double sided - hash |= (UINT64)AlphaTest() << 21; // bits 21 contour processing - hash |= (UINT64)PolyAlpha() << 22; // bits 22 poly alpha processing - hash |= (UINT64)(header[2] & 0xFF) << 23; // bits 23-30 microtexture / uv mirror - hash |= (UINT64)SpecularEnabled() << 31; // bits 31 enable specular reflection - hash |= (UINT64)SmoothShading() << 32; // bits 32 smooth shading - hash |= (UINT64)FixedShading() << 33; // bits 33 fixed shading - hash |= (UINT64)(header[0] >> 26) << 34; // bits 34-39 specular coefficient (opacity) - hash |= (UINT64)(header[6] & 0x3FFFF) << 40; // bits 40-57 Translucency pattern select / disable lighting / Polygon light modifier / Texture enable / Texture format / Shininess / High priority / Layered polygon / Translucency mode + hash |= (UINT64)((header[4] & 0xC0) >> 6) << 19; // bits 19-20 page / translatormap + hash |= (UINT64)DoubleSided() << 21; // bits 21 double sided + hash |= (UINT64)AlphaTest() << 22; // bits 22 contour processing + hash |= (UINT64)PolyAlpha() << 23; // bits 23 poly alpha processing + hash |= (UINT64)(header[2] & 0xFF) << 24; // bits 24-31 microtexture / uv mirror + hash |= (UINT64)SpecularEnabled() << 32; // bits 32 enable specular reflection + hash |= (UINT64)SmoothShading() << 33; // bits 33 smooth shading + hash |= (UINT64)FixedShading() << 34; // bits 34 fixed shading + hash |= (UINT64)(header[0] >> 26) << 35; // bits 35-40 specular coefficient (opacity) + hash |= (UINT64)(header[6] & 0x3FFFF) << 41; // bits 41-58 Translucency pattern select / disable lighting / Polygon light modifier / Texture enable / Texture format / Shininess / High priority / Layered polygon / Translucency mode return hash; } diff --git a/Src/Graphics/New3D/R3DShader.cpp b/Src/Graphics/New3D/R3DShader.cpp index 363e113..6797650 100644 --- a/Src/Graphics/New3D/R3DShader.cpp +++ b/Src/Graphics/New3D/R3DShader.cpp @@ -29,6 +29,7 @@ void R3DShader::Start() m_layered = false; m_textureInverted = false; m_fixedShading = false; + m_translatorMap = false; m_modelScale = 1.0f; m_shininess = 0; m_specularValue = 0; @@ -111,6 +112,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_locTranslatorMap = glGetUniformLocation(m_shaderProgram, "translatorMap"); m_locSpotEllipse = glGetUniformLocation(m_shaderProgram, "spotEllipse"); m_locSpotRange = glGetUniformLocation(m_shaderProgram, "spotRange"); @@ -226,6 +228,11 @@ void R3DShader::SetMeshUniforms(const Mesh* m) m_fixedShading = m->fixedShading; } + if (m_dirtyMesh || m->translatorMap != m_translatorMap) { + glUniform1i(m_locTranslatorMap, m->translatorMap); + m_translatorMap = m->translatorMap; + } + if (m_dirtyMesh || m->wrapModeU != m_texWrapMode[0] || m->wrapModeV != m_texWrapMode[1]) { m_texWrapMode[0] = m->wrapModeU; m_texWrapMode[1] = m->wrapModeV; diff --git a/Src/Graphics/New3D/R3DShader.h b/Src/Graphics/New3D/R3DShader.h index 92d10e0..73a0656 100644 --- a/Src/Graphics/New3D/R3DShader.h +++ b/Src/Graphics/New3D/R3DShader.h @@ -48,6 +48,7 @@ private: GLint m_locBaseTexSize; GLint m_locTextureInverted; GLint m_locTexWrapMode; + GLint m_locTranslatorMap; // cached mesh values bool m_textured1; @@ -60,6 +61,7 @@ private: float m_specularValue; bool m_specularEnabled; bool m_fixedShading; + bool m_translatorMap; bool m_layered; float m_microTexScale; diff --git a/Src/Graphics/New3D/R3DShaderQuads.h b/Src/Graphics/New3D/R3DShaderQuads.h index 44541fd..0c86aeb 100644 --- a/Src/Graphics/New3D/R3DShaderQuads.h +++ b/Src/Graphics/New3D/R3DShaderQuads.h @@ -9,6 +9,7 @@ static const char *vertexShaderR3DQuads = R"glsl( uniform float modelScale; uniform mat4 modelMat; uniform mat4 projMat; +uniform bool translatorMap; // attributes in vec4 inVertex; @@ -30,6 +31,17 @@ out VS_OUT float discardPoly; // can't have varying bool (glsl spec) } vs_out; +vec4 GetColour(vec4 colour) +{ + vec4 c = colour; + + if(translatorMap) { + c.rgb *= 16.0; + } + + return c; +} + float CalcBackFace(in vec3 viewVertex) { vec3 vt = viewVertex - vec3(0.0); @@ -44,7 +56,7 @@ void main(void) vs_out.viewVertex = vec3(modelMat * inVertex); vs_out.viewNormal = (mat3(modelMat) * inNormal) / modelScale; vs_out.discardPoly = CalcBackFace(vs_out.viewVertex); - vs_out.color = inColour; + vs_out.color = GetColour(inColour); vs_out.texCoord = inTexCoord; vs_out.fixedShade = inFixedShade; gl_Position = projMat * modelMat * inVertex; diff --git a/Src/Graphics/New3D/R3DShaderTriangles.h b/Src/Graphics/New3D/R3DShaderTriangles.h index 07ec61c..01c6b88 100644 --- a/Src/Graphics/New3D/R3DShaderTriangles.h +++ b/Src/Graphics/New3D/R3DShaderTriangles.h @@ -9,6 +9,7 @@ static const char *vertexShaderR3D = R"glsl( uniform float modelScale; uniform mat4 modelMat; uniform mat4 projMat; +uniform bool translatorMap; // attributes attribute vec4 inVertex; @@ -26,6 +27,17 @@ varying vec4 fsColor; varying float fsDiscard; // can't have varying bool (glsl spec) varying float fsFixedShade; +vec4 GetColour(vec4 colour) +{ + vec4 c = colour; + + if(translatorMap) { + c.rgb *= 16.0; + } + + return c; +} + float CalcBackFace(in vec3 viewVertex) { vec3 vt = viewVertex - vec3(0.0); @@ -40,7 +52,7 @@ void main(void) fsViewVertex = vec3(modelMat * inVertex); fsViewNormal = (mat3(modelMat) * inNormal) / modelScale; fsDiscard = CalcBackFace(fsViewVertex); - fsColor = inColour; + fsColor = GetColour(inColour); fsTexCoord = inTexCoord; fsFixedShade = inFixedShade; gl_Position = projMat * modelMat * inVertex;