summaryrefslogtreecommitdiff
path: root/src/video_core/rasterizer.cpp
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2014-12-31 15:19:40 +0100
committerGravatar Tony Wasserka2014-12-31 16:32:56 +0100
commit9675d19b47865c2dac5e662f5a265589bd03a283 (patch)
treea3d244d641f8da998096dd72d761878464aa70d8 /src/video_core/rasterizer.cpp
parentPica: Cleanup color conversion. (diff)
downloadyuzu-9675d19b47865c2dac5e662f5a265589bd03a283.tar.gz
yuzu-9675d19b47865c2dac5e662f5a265589bd03a283.tar.xz
yuzu-9675d19b47865c2dac5e662f5a265589bd03a283.zip
Pica/Rasterizer: Make orient2d a free function and rename it to SignedArea.
Diffstat (limited to 'src/video_core/rasterizer.cpp')
-rw-r--r--src/video_core/rasterizer.cpp69
1 files changed, 38 insertions, 31 deletions
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 4dfc21885..9850e517a 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -55,30 +55,45 @@ static void SetDepth(int x, int y, u16 value) {
55 *(depth_buffer + x + y * registers.framebuffer.GetWidth()) = value; 55 *(depth_buffer + x + y * registers.framebuffer.GetWidth()) = value;
56} 56}
57 57
58void ProcessTriangle(const VertexShader::OutputVertex& v0, 58// NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values
59 const VertexShader::OutputVertex& v1, 59struct Fix12P4 {
60 const VertexShader::OutputVertex& v2) 60 Fix12P4() {}
61{ 61 Fix12P4(u16 val) : val(val) {}
62 // NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values
63 struct Fix12P4 {
64 Fix12P4() {}
65 Fix12P4(u16 val) : val(val) {}
66 62
67 static u16 FracMask() { return 0xF; } 63 static u16 FracMask() { return 0xF; }
68 static u16 IntMask() { return (u16)~0xF; } 64 static u16 IntMask() { return (u16)~0xF; }
69 65
70 operator u16() const { 66 operator u16() const {
71 return val; 67 return val;
72 } 68 }
73 69
74 bool operator < (const Fix12P4& oth) const { 70 bool operator < (const Fix12P4& oth) const {
75 return (u16)*this < (u16)oth; 71 return (u16)*this < (u16)oth;
76 } 72 }
77 73
78 private: 74private:
79 u16 val; 75 u16 val;
80 }; 76};
77
78/**
79 * Calculate signed area of the triangle spanned by the three argument vertices.
80 * The sign denotes an orientation.
81 *
82 * @todo define orientation concretely.
83 */
84static int SignedArea (const Math::Vec2<Fix12P4>& vtx1,
85 const Math::Vec2<Fix12P4>& vtx2,
86 const Math::Vec2<Fix12P4>& vtx3) {
87 const auto vec1 = Math::MakeVec(vtx2 - vtx1, 0);
88 const auto vec2 = Math::MakeVec(vtx3 - vtx1, 0);
89 // TODO: There is a very small chance this will overflow for sizeof(int) == 4
90 return Math::Cross(vec1, vec2).z;
91};
81 92
93void ProcessTriangle(const VertexShader::OutputVertex& v0,
94 const VertexShader::OutputVertex& v1,
95 const VertexShader::OutputVertex& v2)
96{
82 // vertex positions in rasterizer coordinates 97 // vertex positions in rasterizer coordinates
83 auto FloatToFix = [](float24 flt) { 98 auto FloatToFix = [](float24 flt) {
84 return Fix12P4(static_cast<unsigned short>(flt.ToFloat32() * 16.0f)); 99 return Fix12P4(static_cast<unsigned short>(flt.ToFloat32() * 16.0f));
@@ -86,14 +101,6 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
86 auto ScreenToRasterizerCoordinates = [FloatToFix](const Math::Vec3<float24> vec) { 101 auto ScreenToRasterizerCoordinates = [FloatToFix](const Math::Vec3<float24> vec) {
87 return Math::Vec3<Fix12P4>{FloatToFix(vec.x), FloatToFix(vec.y), FloatToFix(vec.z)}; 102 return Math::Vec3<Fix12P4>{FloatToFix(vec.x), FloatToFix(vec.y), FloatToFix(vec.z)};
88 }; 103 };
89 static auto orient2d = [](const Math::Vec2<Fix12P4>& vtx1,
90 const Math::Vec2<Fix12P4>& vtx2,
91 const Math::Vec2<Fix12P4>& vtx3) {
92 const auto vec1 = Math::MakeVec(vtx2 - vtx1, 0);
93 const auto vec2 = Math::MakeVec(vtx3 - vtx1, 0);
94 // TODO: There is a very small chance this will overflow for sizeof(int) == 4
95 return Math::Cross(vec1, vec2).z;
96 };
97 104
98 Math::Vec3<Fix12P4> vtxpos[3]{ ScreenToRasterizerCoordinates(v0.screenpos), 105 Math::Vec3<Fix12P4> vtxpos[3]{ ScreenToRasterizerCoordinates(v0.screenpos),
99 ScreenToRasterizerCoordinates(v1.screenpos), 106 ScreenToRasterizerCoordinates(v1.screenpos),
@@ -107,7 +114,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
107 if (registers.cull_mode != Regs::CullMode::KeepAll) { 114 if (registers.cull_mode != Regs::CullMode::KeepAll) {
108 // Cull away triangles which are wound clockwise. 115 // Cull away triangles which are wound clockwise.
109 // TODO: A check for degenerate triangles ("== 0") should be considered for CullMode::KeepAll 116 // TODO: A check for degenerate triangles ("== 0") should be considered for CullMode::KeepAll
110 if (orient2d(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) <= 0) 117 if (SignedArea(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) <= 0)
111 return; 118 return;
112 } 119 }
113 120
@@ -153,9 +160,9 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
153 for (u16 x = min_x; x < max_x; x += 0x10) { 160 for (u16 x = min_x; x < max_x; x += 0x10) {
154 161
155 // Calculate the barycentric coordinates w0, w1 and w2 162 // Calculate the barycentric coordinates w0, w1 and w2
156 int w0 = bias0 + orient2d(vtxpos[1].xy(), vtxpos[2].xy(), {x, y}); 163 int w0 = bias0 + SignedArea(vtxpos[1].xy(), vtxpos[2].xy(), {x, y});
157 int w1 = bias1 + orient2d(vtxpos[2].xy(), vtxpos[0].xy(), {x, y}); 164 int w1 = bias1 + SignedArea(vtxpos[2].xy(), vtxpos[0].xy(), {x, y});
158 int w2 = bias2 + orient2d(vtxpos[0].xy(), vtxpos[1].xy(), {x, y}); 165 int w2 = bias2 + SignedArea(vtxpos[0].xy(), vtxpos[1].xy(), {x, y});
159 int wsum = w0 + w1 + w2; 166 int wsum = w0 + w1 + w2;
160 167
161 // If current pixel is not covered by the current primitive 168 // If current pixel is not covered by the current primitive