SoftGPU: Detect through-mode rectangles from triangle strips

This commit is contained in:
Henrik Rydgård 2019-10-22 23:46:26 +02:00
parent 58568632e8
commit 510229b68b
3 changed files with 41 additions and 3 deletions

View File

@ -625,6 +625,10 @@ public:
*this = *this / f;
}
bool operator ==(const Vec4 &other) const {
return x == other.x && y == other.y && z == other.z && w == other.w;
}
T Length2() const
{
return x*x + y*y + z*z + w*w;

View File

@ -198,7 +198,7 @@ void ProcessRect(const VertexData& v0, const VertexData& v1)
// Color and depth values of second vertex are used for the whole rectangle
buf[0].color0 = buf[1].color0 = buf[2].color0 = buf[3].color0;
buf[0].color1 = buf[1].color1 = buf[2].color1 = buf[3].color1;
buf[0].color1 = buf[1].color1 = buf[2].color1 = buf[3].color1; // is color1 ever used in through mode?
buf[0].clippos.w = buf[1].clippos.w = buf[2].clippos.w = buf[3].clippos.w = 1.0f;
buf[0].fogdepth = buf[1].fogdepth = buf[2].fogdepth = buf[3].fogdepth = 1.0f;

View File

@ -319,8 +319,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
VertexReader vreader(buf, vtxfmt, vertex_type);
const int max_vtcs_per_prim = 3;
static VertexData data[max_vtcs_per_prim];
static VertexData data[4]; // Normally max verts per prim is 3, but we temporarily need 4 to detect rectangles from strips.
// This is the index of the next vert in data (or higher, may need modulus.)
static int data_index = 0;
@ -439,6 +438,41 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
// Don't draw a triangle when loading the first two vertices.
int skip_count = data_index >= 2 ? 0 : 2 - data_index;
// If index count == 4, check if we can convert to a rectangle.
// This is for Darkstalkers (and should speed up many 2D games).
if (vertex_count == 4 && gstate.isModeThrough()) {
for (int vtx = 0; vtx < 4; ++vtx) {
if (indices) {
vreader.Goto(ConvertIndex(vtx) - index_lower_bound);
}
else {
vreader.Goto(vtx);
}
data[vtx] = ReadVertex(vreader);
}
// OK, now let's look at data to detect rectangles. There are a few possibilities
// but we focus on Darkstalkers for now.
if (data[0].screenpos.x == data[1].screenpos.x &&
data[0].screenpos.y == data[2].screenpos.y &&
data[2].screenpos.x == data[3].screenpos.x &&
data[1].screenpos.y == data[3].screenpos.y &&
data[1].screenpos.y > data[0].screenpos.y && // Avoid rotation handling
data[2].screenpos.x > data[0].screenpos.x &&
data[0].texturecoords.x == data[1].texturecoords.x &&
data[0].texturecoords.y == data[2].texturecoords.y &&
data[2].texturecoords.x == data[3].texturecoords.x &&
data[1].texturecoords.y == data[3].texturecoords.y &&
data[1].texturecoords.y > data[0].texturecoords.y &&
data[2].texturecoords.x > data[0].texturecoords.x &&
data[0].color0 == data[1].color0 &&
data[1].color0 == data[2].color0 &&
data[2].color0 == data[3].color0) {
// It's a rectangle!
Clipper::ProcessRect(data[0], data[3]);
}
}
for (int vtx = 0; vtx < vertex_count; ++vtx) {
if (indices) {
vreader.Goto(ConvertIndex(vtx) - index_lower_bound);