DS GX: Automatically normalize winding culling calculations (fixes #699)

This commit is contained in:
Vicki Pfau 2017-04-27 02:50:23 -07:00
parent 78a22d6674
commit 507256e682
3 changed files with 70 additions and 3 deletions

View File

@ -3,6 +3,7 @@ Features:
- DS GX: Toon shading
Bugfixes:
- DS GX: Fix vertex texture transformation (fixes mgba.io/i/702)
- DS GX: Automatically normalize winding culling calculations (fixes mgba.io/i/699)
Misc:
- DS GX: Clean up and unify texture mapping

View File

@ -53,6 +53,51 @@ static inline unsigned clz32(uint32_t bits) {
#endif
}
static inline unsigned clz64(uint64_t bits) {
#if defined(__GNUC__) || __clang__
if (!bits) {
return 64;
}
return __builtin_clzll(bits);
#else
static const int table[256] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (bits & 0xFF00000000000000) {
return table[bits >> 56];
} else if (bits & 0x00FF000000000000) {
return table[bits >> 48] + 8;
} else if (bits & 0x0000FF0000000000) {
return table[bits >> 40] + 16;
} else if (bits & 0x000000FF00000000) {
return table[bits >> 32] + 24;
} else if (bits & 0x00000000FF000000) {
return table[bits >> 24] + 32;
} else if (bits & 0x0000000000FF0000) {
return table[bits >> 16] + 40;
} else if (bits & 0x000000000000FF00) {
return table[bits >> 8] + 48;
}
return table[bits] + 56;
#endif
}
static inline uint32_t toPow2(uint32_t bits) {
if (!bits) {
return 0;

View File

@ -7,6 +7,7 @@
#include <mgba/internal/ds/ds.h>
#include <mgba/internal/ds/io.h>
#include <mgba-util/math.h>
mLOG_DEFINE_CATEGORY(DS_GX, "DS GX", "ds.gx");
@ -237,6 +238,7 @@ static bool _clipPolygon(struct DSGX* gx, struct DSGXPolygon* poly) {
int64_t ny = 0;
int64_t nz = 0;
int64_t dot = 0;
int rank = 30;
for (v = 0; v < poly->verts; ++v) {
struct DSGXVertex* v0 = &gx->pendingVertices[poly->vertIds[v]];
struct DSGXVertex* v1;
@ -251,9 +253,28 @@ static bool _clipPolygon(struct DSGX* gx, struct DSGXPolygon* poly) {
v1 = &gx->pendingVertices[poly->vertIds[v + 1 - poly->verts]];
v2 = &gx->pendingVertices[poly->vertIds[v + 2 - poly->verts]];
}
nx = ((int64_t) v0->viewCoord[1] * v2->viewCoord[3] - (int64_t) v0->viewCoord[3] * v2->viewCoord[1]) >> 24;
ny = ((int64_t) v0->viewCoord[3] * v2->viewCoord[0] - (int64_t) v0->viewCoord[0] * v2->viewCoord[3]) >> 24;
nz = ((int64_t) v0->viewCoord[0] * v2->viewCoord[1] - (int64_t) v0->viewCoord[1] * v2->viewCoord[0]) >> 24;
nx = ((int64_t) v0->viewCoord[1] * v2->viewCoord[3] - (int64_t) v0->viewCoord[3] * v2->viewCoord[1]);
ny = ((int64_t) v0->viewCoord[3] * v2->viewCoord[0] - (int64_t) v0->viewCoord[0] * v2->viewCoord[3]);
nz = ((int64_t) v0->viewCoord[0] * v2->viewCoord[1] - (int64_t) v0->viewCoord[1] * v2->viewCoord[0]);
int rx = 64 - clz64(nx >= 0 ? nx : -nx);
int ry = 64 - clz64(ny >= 0 ? ny : -ny);
int rz = 64 - clz64(nz >= 0 ? nz : -nz);
if (ry > rx) {
rx = ry;
}
if (rz > rx) {
rx = rz;
}
if (rx > 30) {
nx >>= rx - 30;
ny >>= rx - 30;
nz >>= rx - 30;
}
if (rx > rank) {
dot >>= rx - rank;
rank = rx;
}
dot += nx * v1->viewCoord[0] + ny * v1->viewCoord[1] + nz * v1->viewCoord[3];
}
if (!DSGXPolygonAttrsIsBackFace(poly->polyParams) && dot < 0) {