Просмотр исходного кода

SwRasterizer: implement custom clip plane

wwylele 9 лет назад
Родитель
Сommit
ea51a3af26
2 измененных файлов с 25 добавлено и 4 удалено
  1. 12 2
      src/video_core/regs_rasterizer.h
  2. 13 2
      src/video_core/swrasterizer/clipper.cpp

+ 12 - 2
src/video_core/regs_rasterizer.h

@@ -5,10 +5,10 @@
 #pragma once
 
 #include <array>
-
 #include "common/bit_field.h"
 #include "common/common_funcs.h"
 #include "common/common_types.h"
+#include "video_core/pica_types.h"
 
 namespace Pica {
 
@@ -31,7 +31,17 @@ struct RasterizerRegs {
 
     BitField<0, 24, u32> viewport_size_y;
 
-    INSERT_PADDING_WORDS(0x9);
+    INSERT_PADDING_WORDS(0x3);
+
+    BitField<0, 1, u32> clip_enable;
+    BitField<0, 24, u32> clip_coef[4]; // float24
+
+    Math::Vec4<float24> GetClipCoef() const {
+        return {float24::FromRaw(clip_coef[0]), float24::FromRaw(clip_coef[1]),
+                float24::FromRaw(clip_coef[2]), float24::FromRaw(clip_coef[3])};
+    }
+
+    INSERT_PADDING_WORDS(0x1);
 
     BitField<0, 24, u32> viewport_depth_range;      // float24
     BitField<0, 24, u32> viewport_depth_near_plane; // float24

+ 13 - 2
src/video_core/swrasterizer/clipper.cpp

@@ -127,8 +127,7 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu
 
     // Simple implementation of the Sutherland-Hodgman clipping algorithm.
     // TODO: Make this less inefficient (currently lots of useless buffering overhead happens here)
-    for (auto edge : clipping_edges) {
-
+    auto Clip = [&](const ClippingEdge& edge) {
         std::swap(input_list, output_list);
         output_list->clear();
 
@@ -147,12 +146,24 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu
             }
             reference_vertex = &vertex;
         }
+    };
+
+    for (auto edge : clipping_edges) {
+        Clip(edge);
 
         // Need to have at least a full triangle to continue...
         if (output_list->size() < 3)
             return;
     }
 
+    if (g_state.regs.rasterizer.clip_enable) {
+        ClippingEdge custom_edge{-g_state.regs.rasterizer.GetClipCoef()};
+        Clip(custom_edge);
+
+        if (output_list->size() < 3)
+            return;
+    }
+
     InitScreenCoordinates((*output_list)[0]);
     InitScreenCoordinates((*output_list)[1]);