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:
Ian Curtis 2018-10-19 20:59:46 +00:00
parent df02d6a753
commit bf4d725970
8 changed files with 108 additions and 1 deletions

View file

@ -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()
{

View file

@ -1305,6 +1305,11 @@ void CLegacy3D::SetSignedShade(bool enable)
{
}
float CLegacy3D::GetLosValue(int layer)
{
return 0.0f;
}
CLegacy3D::CLegacy3D(const Util::Config::Node &config)
: m_config(config)
{

View file

@ -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):

View file

@ -297,6 +297,10 @@ void CNew3D::RenderFrame(void)
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
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

View file

@ -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

View file

@ -174,6 +174,11 @@ bool PolyHeader::SmoothShading()
return (header[1] & 0x8) > 0;
}
bool PolyHeader::NoLosReturn()
{
return (header[1] & 0x1) > 0;
}
//
// header 2
//

View file

@ -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();

View file

@ -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;
}