Split face colour from per vertex poly colour. Fixes colour bleeding between connected polys in harley.

This commit is contained in:
Ian Curtis 2016-05-07 15:28:04 +00:00
parent 595e24ad60
commit ded3168060
3 changed files with 58 additions and 30 deletions

View file

@ -30,6 +30,7 @@ struct R3DPoly
{ {
Vertex v[4]; // just easier to have them as an array Vertex v[4]; // just easier to have them as an array
float faceNormal[3]; // we need this to help work out poly winding, i assume the h/w uses this instead of calculating normals itself float faceNormal[3]; // we need this to help work out poly winding, i assume the h/w uses this instead of calculating normals itself
float faceColour[4]; // per face colour
int number = 4; int number = 4;
}; };

View file

@ -732,7 +732,7 @@ void CNew3D::RenderViewport(UINT32 addr)
} }
} }
void CNew3D::CopyVertexData(R3DPoly& r3dPoly, std::vector<Poly>& polyArray) void CNew3D::CopyVertexData(const R3DPoly& r3dPoly, std::vector<Poly>& polyArray)
{ {
//==================== //====================
Poly p; Poly p;
@ -757,6 +757,13 @@ void CNew3D::CopyVertexData(R3DPoly& r3dPoly, std::vector<Poly>& polyArray)
p.p3 = r3dPoly.v[0]; p.p3 = r3dPoly.v[0];
} }
//multiply face attributes with vertex attributes if required
for (int i = 0; i < 4; i++) {
p.p1.color[i] = (UINT8)(p.p1.color[i] * r3dPoly.faceColour[i]);
p.p2.color[i] = (UINT8)(p.p2.color[i] * r3dPoly.faceColour[i]);
p.p3.color[i] = (UINT8)(p.p3.color[i] * r3dPoly.faceColour[i]);
}
polyArray.emplace_back(p); polyArray.emplace_back(p);
if (r3dPoly.number == 4) { if (r3dPoly.number == 4) {
@ -772,6 +779,13 @@ void CNew3D::CopyVertexData(R3DPoly& r3dPoly, std::vector<Poly>& polyArray)
p.p3 = r3dPoly.v[2]; p.p3 = r3dPoly.v[2];
} }
//multiply face attributes with vertex attributes if required
for (int i = 0; i < 4; i++) {
p.p1.color[i] = (UINT8)(p.p1.color[i] * r3dPoly.faceColour[i]);
p.p2.color[i] = (UINT8)(p.p2.color[i] * r3dPoly.faceColour[i]);
p.p3.color[i] = (UINT8)(p.p3.color[i] * r3dPoly.faceColour[i]);
}
polyArray.emplace_back(p); polyArray.emplace_back(p);
} }
} }
@ -887,6 +901,37 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
} }
} }
// copy face attributes
for (i = 0; i < p.number; i++) {
if ((ph.header[1] & 2) == 0) {
UINT32 colorIdx = (ph.header[4] >> 8) & 0x7FF;
p.faceColour[2] = (m_polyRAM[0x400 + colorIdx] & 0xFF) / 255.f;
p.faceColour[1] = ((m_polyRAM[0x400 + colorIdx] >> 8) & 0xFF) / 255.f;
p.faceColour[0] = ((m_polyRAM[0x400 + colorIdx] >> 16) & 0xFF) / 255.f;
}
else {
if (ph.ColorDisabled()) { // no colours were set
p.faceColour[0] = 1.0f;
p.faceColour[1] = 1.0f;
p.faceColour[2] = 1.0f;
}
else {
p.faceColour[0] = ((ph.header[4] >> 24)) / 255.f;
p.faceColour[1] = ((ph.header[4] >> 16) & 0xFF) / 255.f;
p.faceColour[2] = ((ph.header[4] >> 8) & 0xFF) / 255.f;
}
}
if ((ph.header[6] & 0x00800000)) { // if set, polygon is opaque
p.faceColour[3] = 1.0f;
}
else {
p.faceColour[3] = ph.Transparency() / 255.f;
}
}
// if we have flat shading, we can't re-use normals from shared vertices // if we have flat shading, we can't re-use normals from shared vertices
for (i = 0; i < p.number && !ph.SmoothShading(); i++) { for (i = 0; i < p.number && !ph.SmoothShading(); i++) {
p.v[i].normal[0] = p.faceNormal[0]; p.v[i].normal[0] = p.faceNormal[0];
@ -894,7 +939,8 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
p.v[i].normal[2] = p.faceNormal[2]; p.v[i].normal[2] = p.faceNormal[2];
} }
for (; j < p.number; j++) // remaining vertices are new and defined here // remaining vertices are new and defined here
for (; j < p.number; j++)
{ {
// Fetch vertices // Fetch vertices
UINT32 ix = data[0]; UINT32 ix = data[0];
@ -914,37 +960,18 @@ void CNew3D::CacheModel(Model *m, const UINT32 *data)
p.v[j].normal[2] = (INT8)(iz & 0xFF) / 128.f; p.v[j].normal[2] = (INT8)(iz & 0xFF) / 128.f;
} }
if ((ph.header[1] & 2) == 0) {
UINT32 colorIdx = ((ph.header[4] >> 8) & 0x7FF);
p.v[j].color[2] = (m_polyRAM[0x400 + colorIdx] & 0xFF);
p.v[j].color[1] = (m_polyRAM[0x400 + colorIdx] >> 8) & 0xFF;
p.v[j].color[0] = (m_polyRAM[0x400 + colorIdx] >> 16) & 0xFF;
}
else {
if (ph.ColorDisabled()) { // no colours were set
p.v[j].color[0] = 255;
p.v[j].color[1] = 255;
p.v[j].color[2] = 255;
}
else {
p.v[j].color[0] = (ph.header[4] >> 24);
p.v[j].color[1] = (ph.header[4] >> 16) & 0xFF;
p.v[j].color[2] = (ph.header[4] >> 8) & 0xFF;
}
}
if (ph.FixedShading() && ph.LightEnabled()) { if (ph.FixedShading() && ph.LightEnabled()) {
float shade = ((ix+128) & 0xFF) / 255.f; UINT8 shade = (UINT8)((ix + 128) & 0xFF);
p.v[j].color[0] = (UINT8)(p.v[j].color[0] * shade); p.v[j].color[0] = shade; // hardware doesn't really have per vertex colours, only per poly
p.v[j].color[1] = (UINT8)(p.v[j].color[1] * shade); p.v[j].color[1] = shade;
p.v[j].color[2] = (UINT8)(p.v[j].color[2] * shade); p.v[j].color[2] = shade;
}
if ((ph.header[6] & 0x00800000)) { // if set, polygon is opaque
p.v[j].color[3] = 255; p.v[j].color[3] = 255;
} }
else { else {
p.v[j].color[3] = ph.Transparency(); p.v[j].color[0] = 255;
p.v[j].color[1] = 255;
p.v[j].color[2] = 255;
p.v[j].color[3] = 255;
} }
float texU, texV = 0; float texU, texV = 0;

View file

@ -168,7 +168,7 @@ private:
// building the scene // building the scene
void CacheModel(Model *m, const UINT32 *data); void CacheModel(Model *m, const UINT32 *data);
void CopyVertexData(R3DPoly& r3dPoly, std::vector<Poly>& polyArray); void CopyVertexData(const R3DPoly& r3dPoly, std::vector<Poly>& polyArray);
void RenderScene(int priority, bool alpha); void RenderScene(int priority, bool alpha);
float Determinant3x3(const float m[16]); float Determinant3x3(const float m[16]);