mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-25 23:25:40 +00:00
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.
This commit is contained in:
parent
df02d6a753
commit
bf4d725970
|
@ -20,6 +20,7 @@ public:
|
||||||
virtual bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes) = 0;
|
virtual bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes) = 0;
|
||||||
virtual void SetSunClamp(bool enable) = 0;
|
virtual void SetSunClamp(bool enable) = 0;
|
||||||
virtual void SetSignedShade(bool enable) = 0;
|
virtual void SetSignedShade(bool enable) = 0;
|
||||||
|
virtual float GetLosValue(int layer) = 0;
|
||||||
|
|
||||||
virtual ~IRender3D()
|
virtual ~IRender3D()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1305,6 +1305,11 @@ void CLegacy3D::SetSignedShade(bool enable)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float CLegacy3D::GetLosValue(int layer)
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
CLegacy3D::CLegacy3D(const Util::Config::Node &config)
|
CLegacy3D::CLegacy3D(const Util::Config::Node &config)
|
||||||
: m_config(config)
|
: m_config(config)
|
||||||
{
|
{
|
||||||
|
|
|
@ -348,6 +348,16 @@ public:
|
||||||
*/
|
*/
|
||||||
void SetSignedShade(bool enable);
|
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):
|
||||||
* ~CLegacy3D(void):
|
* ~CLegacy3D(void):
|
||||||
|
|
|
@ -297,6 +297,10 @@ void CNew3D::RenderFrame(void)
|
||||||
m_nfPairs[i].zFar = std::numeric_limits<float>::max();
|
m_nfPairs[i].zFar = std::numeric_limits<float>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
m_lineOfSight[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// release any resources from last frame
|
// release any resources from last frame
|
||||||
m_polyBufferRam.clear(); // clear dyanmic model memory buffer
|
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
|
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);
|
m_r3dFrameBuffers.SetFBO(Layer::colour);
|
||||||
hasOverlay = RenderScene(pri, renderOverlay, 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)
|
glDepthFunc(GL_LESS); // alpha polys seem to use gl_less (ocean hunter)
|
||||||
|
|
||||||
m_r3dShader.DiscardAlpha(false); // render only translucent pixels
|
m_r3dShader.DiscardAlpha(false); // render only translucent pixels
|
||||||
|
@ -370,7 +378,6 @@ void CNew3D::RenderFrame(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_r3dFrameBuffers.DisableFBO(); // draw to back buffer normally
|
m_r3dFrameBuffers.DisableFBO(); // draw to back buffer normally
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNew3D::BeginFrame(void)
|
void CNew3D::BeginFrame(void)
|
||||||
|
@ -1010,6 +1017,11 @@ void CNew3D::SetMeshValues(SortingMesh *currentMesh, PolyHeader &ph)
|
||||||
bool smoothU = ph.TexSmoothU();
|
bool smoothU = ph.TexSmoothU();
|
||||||
bool smoothV = ph.TexSmoothV();
|
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 (ph.TexUMirror()) {
|
||||||
if (smoothU) currentMesh->wrapModeU = Mesh::TexWrapMode::mirror;
|
if (smoothU) currentMesh->wrapModeU = Mesh::TexWrapMode::mirror;
|
||||||
else currentMesh->wrapModeU = Mesh::TexWrapMode::mirrorClamp;
|
else currentMesh->wrapModeU = Mesh::TexWrapMode::mirrorClamp;
|
||||||
|
@ -1643,4 +1655,49 @@ void CNew3D::SetSignedShade(bool enable)
|
||||||
m_shadeIsSigned = 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
|
} // New3D
|
||||||
|
|
|
@ -163,6 +163,16 @@ public:
|
||||||
*/
|
*/
|
||||||
void SetSignedShade(bool enable);
|
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(config):
|
||||||
* ~CRender3D(void):
|
* ~CRender3D(void):
|
||||||
|
@ -207,6 +217,8 @@ private:
|
||||||
bool SkipLayer(int layer);
|
bool SkipLayer(int layer);
|
||||||
void SetRenderStates();
|
void SetRenderStates();
|
||||||
void DisableRenderStates();
|
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);
|
void CalcTexOffset(int offX, int offY, int page, int x, int y, int& newX, int& newY);
|
||||||
|
|
||||||
|
@ -250,6 +262,8 @@ private:
|
||||||
NodeAttributes m_nodeAttribs;
|
NodeAttributes m_nodeAttribs;
|
||||||
Mat4 m_modelMat; // current modelview matrix
|
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
|
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
|
UINT16 m_prevTexCoords[4][2]; // basically relying on undefined behavour
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,11 @@ bool PolyHeader::SmoothShading()
|
||||||
return (header[1] & 0x8) > 0;
|
return (header[1] & 0x8) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PolyHeader::NoLosReturn()
|
||||||
|
{
|
||||||
|
return (header[1] & 0x1) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// header 2
|
// header 2
|
||||||
//
|
//
|
||||||
|
|
|
@ -105,6 +105,7 @@ public:
|
||||||
bool PolyColor(); // if false uses LUT from ram
|
bool PolyColor(); // if false uses LUT from ram
|
||||||
bool FixedShading();
|
bool FixedShading();
|
||||||
bool SmoothShading();
|
bool SmoothShading();
|
||||||
|
bool NoLosReturn(); // no line of sight return (still not exactly how sure this attribute is used yet)
|
||||||
|
|
||||||
//header 2
|
//header 2
|
||||||
bool TexUMirror();
|
bool TexUMirror();
|
||||||
|
|
|
@ -771,6 +771,20 @@ uint32_t CReal3D::ReadRegister(unsigned reg)
|
||||||
return 0xfdffffff | m_pingPong;
|
return 0xfdffffff | m_pingPong;
|
||||||
#endif
|
#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;
|
return 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue