From d5376b41846778f690a25814cca5bc171b29ddeb Mon Sep 17 00:00:00 2001
From: StapleButter <thetotalworm@gmail.com>
Date: Wed, 5 Jul 2017 18:38:10 +0200
Subject: 3D: Y-sorting

---
 src/GPU3D.cpp      | 42 +++++++++++++++++++++++++++++++++---------
 src/GPU3D.h        |  4 ++--
 src/GPU3D_Soft.cpp |  4 ----
 3 files changed, 35 insertions(+), 15 deletions(-)

(limited to 'src')

diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp
index d91daaa..3337d99 100644
--- a/src/GPU3D.cpp
+++ b/src/GPU3D.cpp
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <algorithm>
 #include "NDS.h"
 #include "GPU.h"
 #include "FIFO.h"
@@ -855,6 +856,10 @@ void SubmitPolygon()
     poly->VTop = vtop; poly->VBottom = vbot;
     poly->YTop = ytop; poly->YBottom = ybot;
     poly->XTop = xtop; poly->XBottom = xbot;
+
+    poly->SortKey = (ybot << 8) | ytop;
+    if (poly->Translucent) poly->SortKey |= 0x10000;
+
     poly->WShift = wshift;
     poly->WBuffer = (FlushAttributes & 0x2);
 
@@ -1791,20 +1796,39 @@ void VCount144()
 }
 
 
+bool YSort(Polygon* a, Polygon* b)
+{
+    // Y-sorting rules:
+    // * polygons with lower bottom Y come first
+    // * upon equal bottom Y, polygons with lower top Y come first
+    // * upon equal bottom AND top Y, original ordering is used
+
+    return a->SortKey < b->SortKey;
+}
+
 void VBlank()
 {
     if (FlushRequest)
     {
-        // separate translucent polygons from opaque ones
-
-        u32 io = 0, it = NumOpaquePolygons;
-        for (u32 i = 0; i < NumPolygons; i++)
+        if (NumPolygons)
         {
-            Polygon* poly = &CurPolygonRAM[i];
-            if (poly->Translucent)
-                RenderPolygonRAM[it++] = poly;
-            else
-                RenderPolygonRAM[io++] = poly;
+            // separate translucent polygons from opaque ones
+
+            u32 io = 0, it = NumOpaquePolygons;
+            for (u32 i = 0; i < NumPolygons; i++)
+            {
+                Polygon* poly = &CurPolygonRAM[i];
+                if (poly->Translucent)
+                    RenderPolygonRAM[it++] = poly;
+                else
+                    RenderPolygonRAM[io++] = poly;
+            }
+
+            // apply Y-sorting
+
+            std::stable_sort(RenderPolygonRAM.begin(),
+                RenderPolygonRAM.begin() + ((FlushAttributes & 0x1) ? NumOpaquePolygons : NumPolygons),
+                YSort);
         }
 
         RenderNumPolygons = NumPolygons;
diff --git a/src/GPU3D.h b/src/GPU3D.h
index 8a6beec..d89acf5 100644
--- a/src/GPU3D.h
+++ b/src/GPU3D.h
@@ -60,12 +60,12 @@ typedef struct
     bool IsShadowMask;
     bool IsShadow;
 
-    // data below rather specific to the software renderer
-
     u32 VTop, VBottom; // vertex indices
     s32 YTop, YBottom; // Y coords
     s32 XTop, XBottom; // associated X coords
 
+    u32 SortKey;
+
 } Polygon;
 
 extern u32 RenderDispCnt;
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp
index c55ee1e..7d424e2 100644
--- a/src/GPU3D_Soft.cpp
+++ b/src/GPU3D_Soft.cpp
@@ -1677,10 +1677,6 @@ void ClearBuffers()
 
 void RenderPolygons(bool threaded, Polygon** polygons, int npolys)
 {
-    // sort polygons
-    // TODO: Y-sorting for translucent polygons
-    // TODO: all sorting should be done in GPU3D.cpp
-
     // polygons with ybottom>192 aren't rendered at all
 
     int j = 0;
-- 
cgit v1.2.3