citra/src/video_core/renderer_software/sw_clipper.h

88 lines
2.4 KiB
C++

// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common/common_types.h"
#include "common/vector_math.h"
#include "video_core/pica_types.h"
namespace Pica {
struct TexturingRegs;
}
namespace SwRenderer {
using Pica::f24;
// NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values
struct Fix12P4 {
Fix12P4() {}
Fix12P4(u16 val) : val(val) {}
static Fix12P4 FromFloat24(f24 flt) {
// TODO: Rounding here is necessary to prevent garbage pixels at
// triangle borders. Is it that the correct solution, though?
return Fix12P4(static_cast<u16>(round(flt.ToFloat32() * 16.0f)));
}
static u16 FracMask() {
return 0xF;
}
static u16 IntMask() {
return static_cast<u16>(~0xF);
}
operator u16() const {
return val;
}
bool operator<(const Fix12P4& oth) const {
return (u16) * this < (u16)oth;
}
private:
u16 val;
};
struct Viewport {
f24 halfsize_x;
f24 offset_x;
f24 halfsize_y;
f24 offset_y;
f24 zscale;
f24 offset_z;
};
/**
* Flips the quaternions if they are opposite to prevent
* interpolating them over the wrong direction.
*/
void FlipQuaternionIfOpposite(Common::Vec4<f24>& a, const Common::Vec4<f24>& b);
/**
* Calculate signed area of the triangle spanned by the three argument vertices.
* The sign denotes an orientation.
**/
int SignedArea(const Common::Vec2<Fix12P4>& vtx1, const Common::Vec2<Fix12P4>& vtx2,
const Common::Vec2<Fix12P4>& vtx3);
/**
* Convert a 3D vector for cube map coordinates to 2D texture coordinates along with the face name.
**/
std::tuple<f24, f24, f24, PAddr> ConvertCubeCoord(f24 u, f24 v, f24 w,
const Pica::TexturingRegs& regs);
/**
* Triangle filling rules: Pixels on the right-sided edge or on flat bottom edges are not
* drawn. Pixels on any other triangle border are drawn. This is implemented with three bias
* values which are added to the barycentric coordinates w0, w1 and w2, respectively.
* NOTE: These are the PSP filling rules. Not sure if the 3DS uses the same ones...
**/
bool IsRightSideOrFlatBottomEdge(const Common::Vec2<Fix12P4>& vtx,
const Common::Vec2<Fix12P4>& line1,
const Common::Vec2<Fix12P4>& line2);
} // namespace SwRenderer