all repos — mgba @ 1ecdcf31cc5da86c43f18f6117832dffc8e76767

mGBA Game Boy Advance Emulator

DS GX: Fix perspective correction
Vicki Pfau vi@endrift.com
Wed, 01 Mar 2017 03:29:04 -0800
commit

1ecdcf31cc5da86c43f18f6117832dffc8e76767

parent

2b64d45906d5b687d4cf240a140dee7a48cf1aad

2 files changed, 14 insertions(+), 11 deletions(-)

jump to
M src/ds/gx.csrc/ds/gx.c

@@ -177,6 +177,7 @@ // TODO: What to do if w is 0?

gx->currentVertex.vx = (gx->currentVertex.vx + gx->currentVertex.vw) * (int64_t) (gx->viewportWidth << 12) / (gx->currentVertex.vw * 2) + (gx->viewportX1 << 12); gx->currentVertex.vy = (gx->currentVertex.vy + gx->currentVertex.vw) * (int64_t) (gx->viewportHeight << 12) / (gx->currentVertex.vw * 2) + (gx->viewportY1 << 12); + gx->currentVertex.vw = 0x1000000 / gx->currentVertex.vw; struct DSGXVertex* vbuf = gx->vertexBuffer[gx->bufferIndex]; vbuf[gx->vertexIndex] = gx->currentVertex;
M src/ds/gx/software.csrc/ds/gx/software.c

@@ -48,7 +48,6 @@ return 0;

} static bool _edgeToSpan(struct DSGXSoftwareSpan* span, const struct DSGXSoftwareEdge* edge, int index, int32_t y) { - // TODO: Perspective correction int32_t height = edge->y1 - edge->y0; int64_t yw = (y << 12) - edge->y0; if (!height) {

@@ -67,12 +66,13 @@ span->ep[index] = span->ep[0];

span->ep[0].x = temp; index = 0; } - span->ep[index].w = ((int64_t) (edge->w1 - edge->w0) * yw) / height + edge->w0; - span->ep[index].cr = ((int32_t) (edge->cr1 - edge->cr0) * yw) / height + edge->cr0; - span->ep[index].cg = ((int32_t) (edge->cg1 - edge->cg0) * yw) / height + edge->cg0; - span->ep[index].cb = ((int32_t) (edge->cb1 - edge->cb0) * yw) / height + edge->cb0; - span->ep[index].s = ((int32_t) (edge->s1 - edge->s0) * yw) / height + edge->s0; - span->ep[index].t = ((int32_t) (edge->t1 - edge->t0) * yw) / height + edge->t0; + int32_t w = ((int64_t) (edge->w1 - edge->w0) * yw) / height + edge->w0; + span->ep[index].w = w; + span->ep[index].cr = (((int32_t) (edge->cr1 * edge->w1 - edge->cr0 * edge->w0) * yw) / height + edge->cr0 * edge->w0) / w; + span->ep[index].cg = (((int32_t) (edge->cg1 * edge->w1 - edge->cg0 * edge->w0) * yw) / height + edge->cg0 * edge->w0) / w; + span->ep[index].cb = (((int32_t) (edge->cb1 * edge->w1 - edge->cb0 * edge->w0) * yw) / height + edge->cb0 * edge->w0) / w; + span->ep[index].s = (((int32_t) (edge->s1 * edge->w1 - edge->s0 * edge->w0) * yw) / height + edge->s0 * edge->w0) / w; + span->ep[index].t = (((int32_t) (edge->t1 * edge->w1 - edge->t0 * edge->w0) * yw) / height + edge->t0 * edge->w0) / w; return true; }

@@ -109,11 +109,13 @@ xw = 0;

} else if (xw > width) { xw = width; } - uint32_t w = ((int64_t) (span->ep[0].w - span->ep[1].w) * xw) / width + span->ep[1].w; + int32_t w0 = span->ep[0].w; + int32_t w1 = span->ep[1].w; + int32_t w = ((int64_t) (w1 - w0) * xw) / width + w0; - uint64_t r = ((span->ep[1].cr * (int64_t) span->ep[0].w - span->ep[0].cr * (int64_t) span->ep[1].w) * xw) / width + span->ep[0].cr * (int64_t) span->ep[1].w; - uint64_t g = ((span->ep[1].cg * (int64_t) span->ep[0].w - span->ep[0].cg * (int64_t) span->ep[1].w) * xw) / width + span->ep[0].cg * (int64_t) span->ep[1].w; - uint64_t b = ((span->ep[1].cb * (int64_t) span->ep[0].w - span->ep[0].cb * (int64_t) span->ep[1].w) * xw) / width + span->ep[0].cb * (int64_t) span->ep[1].w; + uint64_t r = ((span->ep[1].cr * (int64_t) w1 - span->ep[0].cr * (int64_t) w0) * xw) / width + span->ep[0].cr * (int64_t) w0; + uint64_t g = ((span->ep[1].cg * (int64_t) w1 - span->ep[0].cg * (int64_t) w0) * xw) / width + span->ep[0].cg * (int64_t) w0; + uint64_t b = ((span->ep[1].cb * (int64_t) w1 - span->ep[0].cb * (int64_t) w0) * xw) / width + span->ep[0].cb * (int64_t) w0; r /= w; g /= w; b /= w;