From bf4d72597066f9d5223aac4ef2897f2f0e344be0 Mon Sep 17 00:00:00 2001 From: Ian Curtis Date: Fri, 19 Oct 2018 20:59:46 +0000 Subject: [PATCH] Smooth texture repeat makes no sense for alpha/contour textures with pixel dilate. HW seems to treat them as non smooth anyway. Also implement some line of sight stuff, used by Scud. Really need to check the threading/synchronisation of the register reads but it basically works. --- Src/Graphics/IRender3D.h | 1 + Src/Graphics/Legacy3D/Legacy3D.cpp | 5 +++ Src/Graphics/Legacy3D/Legacy3D.h | 10 +++++ Src/Graphics/New3D/New3D.cpp | 59 +++++++++++++++++++++++++++++- Src/Graphics/New3D/New3D.h | 14 +++++++ Src/Graphics/New3D/PolyHeader.cpp | 5 +++ Src/Graphics/New3D/PolyHeader.h | 1 + Src/Model3/Real3D.cpp | 14 +++++++ 8 files changed, 108 insertions(+), 1 deletion(-) diff --git a/Src/Graphics/IRender3D.h b/Src/Graphics/IRender3D.h index 38c2759..9d3088a 100644 --- a/Src/Graphics/IRender3D.h +++ b/Src/Graphics/IRender3D.h @@ -20,6 +20,7 @@ public: virtual bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes) = 0; virtual void SetSunClamp(bool enable) = 0; virtual void SetSignedShade(bool enable) = 0; + virtual float GetLosValue(int layer) = 0; virtual ~IRender3D() { diff --git a/Src/Graphics/Legacy3D/Legacy3D.cpp b/Src/Graphics/Legacy3D/Legacy3D.cpp index 18e289f..8fa7828 100644 --- a/Src/Graphics/Legacy3D/Legacy3D.cpp +++ b/Src/Graphics/Legacy3D/Legacy3D.cpp @@ -1303,6 +1303,11 @@ void CLegacy3D::SetSunClamp(bool enable) void CLegacy3D::SetSignedShade(bool enable) { +} + +float CLegacy3D::GetLosValue(int layer) +{ + return 0.0f; } CLegacy3D::CLegacy3D(const Util::Config::Node &config) diff --git a/Src/Graphics/Legacy3D/Legacy3D.h b/Src/Graphics/Legacy3D/Legacy3D.h index c50beec..d10a553 100644 --- a/Src/Graphics/Legacy3D/Legacy3D.h +++ b/Src/Graphics/Legacy3D/Legacy3D.h @@ -348,6 +348,16 @@ public: */ void SetSignedShade(bool enable); + /* + * GetLosValue(int layer); + * + * Gets the line of sight value for the priority layer + * + * Parameters: + * layer Priority layer to read from + */ + float GetLosValue(int layer); + /* * CLegacy3D(void): * ~CLegacy3D(void): diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index 1eea344..bcfb39a 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -297,6 +297,10 @@ void CNew3D::RenderFrame(void) m_nfPairs[i].zFar = std::numeric_limits::max(); } + for (int i = 0; i < 4; i++) { + m_lineOfSight[i] = 0; + } + // release any resources from last frame m_polyBufferRam.clear(); // clear dyanmic model memory buffer m_nodes.clear(); // memory will grow during the object life time, that's fine, no need to shrink to fit @@ -351,6 +355,10 @@ void CNew3D::RenderFrame(void) m_r3dFrameBuffers.SetFBO(Layer::colour); hasOverlay = RenderScene(pri, renderOverlay, Layer::colour); + if (!renderOverlay && ProcessLos(pri)) { + ProcessLos(pri); + } + glDepthFunc(GL_LESS); // alpha polys seem to use gl_less (ocean hunter) m_r3dShader.DiscardAlpha(false); // render only translucent pixels @@ -370,7 +378,6 @@ void CNew3D::RenderFrame(void) } m_r3dFrameBuffers.DisableFBO(); // draw to back buffer normally - } void CNew3D::BeginFrame(void) @@ -1010,6 +1017,11 @@ void CNew3D::SetMeshValues(SortingMesh *currentMesh, PolyHeader &ph) bool smoothU = ph.TexSmoothU(); bool smoothV = ph.TexSmoothV(); + if (ph.AlphaTest()) { + smoothU = false; // smooth wrap makes no sense for alpha tested polys with pixel dilate + smoothV = false; + } + if (ph.TexUMirror()) { if (smoothU) currentMesh->wrapModeU = Mesh::TexWrapMode::mirror; else currentMesh->wrapModeU = Mesh::TexWrapMode::mirrorClamp; @@ -1643,4 +1655,49 @@ void CNew3D::SetSignedShade(bool enable) m_shadeIsSigned = enable; } +float CNew3D::GetLosValue(int layer) +{ + return m_lineOfSight[layer]; +} + +void CNew3D::TranslateLosPosition(int inX, int inY, int& outX, int& outY) +{ + // remap real3d 496x384 to our new viewport + inY = 384 - inY; + + outX = m_xOffs + int(inX * m_xRatio); + outY = m_yOffs + int(inY * m_yRatio); +} + +bool CNew3D::ProcessLos(int priority) +{ + for (const auto &n : m_nodes) { + if (n.viewport.priority == priority) { + if (n.viewport.losPosX || n.viewport.losPosY) { + + int losX, losY; + TranslateLosPosition(n.viewport.losPosX, n.viewport.losPosY, losX, losY); + + float depth; + glReadPixels(losX, losY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); + + if (depth < 0.99f || depth == 1.0f) { // kinda guess work but when depth = 1, haven't drawn anything, when 0.99~ drawing sky somewhere far + return false; + } + + depth = 2.0f * depth - 1.0f; + + float zNear = m_nfPairs[priority].zNear; + float zFar = m_nfPairs[priority].zFar; + float zVal = 2.0f * zNear * zFar / (zFar + zNear - depth * (zFar - zNear)); + + m_lineOfSight[priority] = zVal; + return true; + } + } + } + + return false; +} + } // New3D diff --git a/Src/Graphics/New3D/New3D.h b/Src/Graphics/New3D/New3D.h index 697b1e9..f7f3efd 100644 --- a/Src/Graphics/New3D/New3D.h +++ b/Src/Graphics/New3D/New3D.h @@ -163,6 +163,16 @@ public: */ void SetSignedShade(bool enable); + /* + * GetLosValue(int layer); + * + * Gets the line of sight value for the priority layer + * + * Parameters: + * layer Priority layer to read from + */ + float GetLosValue(int layer); + /* * CRender3D(config): * ~CRender3D(void): @@ -207,6 +217,8 @@ private: bool SkipLayer(int layer); void SetRenderStates(); void DisableRenderStates(); + void TranslateLosPosition(int inX, int inY, int& outX, int& outY); + bool ProcessLos(int priority); void CalcTexOffset(int offX, int offY, int page, int x, int y, int& newX, int& newY); @@ -250,6 +262,8 @@ private: NodeAttributes m_nodeAttribs; Mat4 m_modelMat; // current modelview matrix + float m_lineOfSight[4]; + Vertex m_prev[4]; // these are class variables because sega bass fishing starts meshes with shared vertices from the previous one UINT16 m_prevTexCoords[4][2]; // basically relying on undefined behavour diff --git a/Src/Graphics/New3D/PolyHeader.cpp b/Src/Graphics/New3D/PolyHeader.cpp index a092b70..dee93fe 100644 --- a/Src/Graphics/New3D/PolyHeader.cpp +++ b/Src/Graphics/New3D/PolyHeader.cpp @@ -174,6 +174,11 @@ bool PolyHeader::SmoothShading() return (header[1] & 0x8) > 0; } +bool PolyHeader::NoLosReturn() +{ + return (header[1] & 0x1) > 0; +} + // // header 2 // diff --git a/Src/Graphics/New3D/PolyHeader.h b/Src/Graphics/New3D/PolyHeader.h index f614368..a285aa3 100644 --- a/Src/Graphics/New3D/PolyHeader.h +++ b/Src/Graphics/New3D/PolyHeader.h @@ -105,6 +105,7 @@ public: bool PolyColor(); // if false uses LUT from ram bool FixedShading(); bool SmoothShading(); + bool NoLosReturn(); // no line of sight return (still not exactly how sure this attribute is used yet) //header 2 bool TexUMirror(); diff --git a/Src/Model3/Real3D.cpp b/Src/Model3/Real3D.cpp index a3f2b1a..86519d6 100644 --- a/Src/Model3/Real3D.cpp +++ b/Src/Model3/Real3D.cpp @@ -771,6 +771,20 @@ uint32_t CReal3D::ReadRegister(unsigned reg) return 0xfdffffff | m_pingPong; #endif } + + else if (reg >= 20 && reg<=32) { // line of sight registers + + int index = (reg - 20) / 4; + float val = Render3D->GetLosValue(index); + + if (val) { + //val = 1.0f / val; // test program indicate z values are 1 over + return 0xffffffff; // infinity + } + + return *(uint32_t*)(&val); + } + return 0xffffffff; }