88 lines
2.4 KiB
C++
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
|