diff options
| author | 2014-12-31 15:19:40 +0100 | |
|---|---|---|
| committer | 2014-12-31 16:32:56 +0100 | |
| commit | 9675d19b47865c2dac5e662f5a265589bd03a283 (patch) | |
| tree | a3d244d641f8da998096dd72d761878464aa70d8 /src/video_core/rasterizer.cpp | |
| parent | Pica: Cleanup color conversion. (diff) | |
| download | yuzu-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.cpp | 69 |
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 | ||
| 58 | void ProcessTriangle(const VertexShader::OutputVertex& v0, | 58 | // NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values |
| 59 | const VertexShader::OutputVertex& v1, | 59 | struct 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: | 74 | private: |
| 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 | */ | ||
| 84 | static 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 | ||
| 93 | void 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 |