mirror of https://github.com/AxioDL/metaforce.git
aurora: Start implementing TCGs
This commit is contained in:
parent
cdcfc7eccc
commit
af856de6a8
|
@ -162,24 +162,24 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur
|
|||
u32 fullTcgCount = SBig(*tcgs);
|
||||
tcgCount = std::min(fullTcgCount, 2u);
|
||||
for (u32 i = 0; i < tcgCount; ++i) {
|
||||
// TODO set TCG
|
||||
CGX::SetTexCoordGen(GX::TexCoordID(i), SBig(tcgs[i + 1]));
|
||||
}
|
||||
tcgs += fullTcgCount + 1;
|
||||
} else {
|
||||
tcgCount = SBig(*tcgs);
|
||||
for (u32 i = 0; i < tcgCount; ++i) {
|
||||
// TODO set TCG
|
||||
CGX::SetTexCoordGen(GX::TexCoordID(i), SBig(tcgs[i + 1]));
|
||||
}
|
||||
tcgs += tcgCount + 1;
|
||||
}
|
||||
|
||||
const u32* uvAnim = tcgs;
|
||||
u32 animCount = uvAnim[1];
|
||||
u32 animCount = SBig(uvAnim[1]);
|
||||
uvAnim += 2;
|
||||
u32 texMtx = 30;
|
||||
u32 pttTexMtx = 64;
|
||||
u32 texMtx = GX::TEXMTX0;
|
||||
u32 pttTexMtx = GX::PTTEXMTX0;
|
||||
for (u32 i = 0; i < animCount; ++i) {
|
||||
u32 size = HandleAnimatedUV(uvAnim, texMtx, pttTexMtx);
|
||||
u32 size = HandleAnimatedUV(uvAnim, static_cast<GX::TexMtx>(texMtx), static_cast<GX::PTTexMtx>(pttTexMtx));
|
||||
if (size == 0)
|
||||
break;
|
||||
uvAnim += size;
|
||||
|
@ -356,31 +356,73 @@ void CCubeMaterial::HandleTev(u32 tevCur, const u32* materialDataCur, const u32*
|
|||
CGX::SetTevKAlphaSel(stage, static_cast<GX::TevKAlphaSel>(matFlags >> 0x10 & 0xFF));
|
||||
}
|
||||
|
||||
u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, u32 texMtx, u32 pttTexMtx) {
|
||||
constexpr zeus::CTransform MvPostXf{
|
||||
{zeus::CVector3f{0.5f, 0.f, 0.f}, {0.f, 0.f, 0.f}, {0.f, 0.5f, 0.f}},
|
||||
{0.5f, 0.5f, 1.f},
|
||||
};
|
||||
|
||||
u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, GX::TexMtx texMtx, GX::PTTexMtx pttTexMtx) {
|
||||
u32 type = SBig(*uvAnim);
|
||||
const float* params = reinterpret_cast<const float*>(uvAnim + 1);
|
||||
switch (type) {
|
||||
case 0:
|
||||
// TODO
|
||||
case 0: {
|
||||
auto xf = CGraphics::g_GXModelViewInvXpose;
|
||||
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
||||
GXLoadTexMtxImm(&MvPostXf, pttTexMtx, GX::MTX3x4);
|
||||
return 1;
|
||||
case 1:
|
||||
// TODO
|
||||
}
|
||||
case 1: {
|
||||
auto xf = CGraphics::g_GXModelViewInvXpose;
|
||||
xf.origin = CGraphics::g_ViewMatrix.inverse() * CGraphics::g_GXModelMatrix.origin;
|
||||
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
||||
GXLoadTexMtxImm(&MvPostXf, pttTexMtx, GX::MTX3x4);
|
||||
return 1;
|
||||
case 2:
|
||||
// TODO
|
||||
}
|
||||
case 2: {
|
||||
const float f1 = SBig(params[0]);
|
||||
const float f2 = SBig(params[1]);
|
||||
const float f3 = SBig(params[2]);
|
||||
const float f4 = SBig(params[3]);
|
||||
const float seconds = CGraphics::GetSecondsMod900();
|
||||
const auto xf = zeus::CTransform::Translate(seconds * f3 + f1, seconds * f4 + f2, 0.f);
|
||||
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
||||
return 5;
|
||||
case 3:
|
||||
// TODO
|
||||
}
|
||||
case 3: {
|
||||
const float angle = CGraphics::GetSecondsMod900() * SBig(params[1]) + SBig(params[0]);
|
||||
const float acos = std::cos(angle);
|
||||
const float asin = std::sin(angle);
|
||||
zeus::CTransform xf;
|
||||
xf.basis[0][0] = acos;
|
||||
xf.basis[0][1] = asin;
|
||||
xf.basis[1][0] = -asin;
|
||||
xf.basis[1][1] = acos;
|
||||
xf.origin[0] = (1.f - (acos - asin)) * 0.5f;
|
||||
xf.origin[1] = (1.f - (asin + acos)) * 0.5f;
|
||||
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
||||
return 3;
|
||||
}
|
||||
case 4:
|
||||
case 5:
|
||||
case 5: {
|
||||
// TODO
|
||||
zeus::CTransform xf;
|
||||
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
||||
return 5;
|
||||
case 6:
|
||||
}
|
||||
case 6: {
|
||||
// TODO
|
||||
zeus::CTransform xf;
|
||||
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
||||
GXLoadTexMtxImm(&xf, pttTexMtx, GX::MTX3x4);
|
||||
return 1;
|
||||
case 7:
|
||||
}
|
||||
case 7: {
|
||||
// TODO
|
||||
return 2;
|
||||
zeus::CTransform xf;
|
||||
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
||||
GXLoadTexMtxImm(&xf, pttTexMtx, GX::MTX3x4);
|
||||
return 3;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ private:
|
|||
static void HandleDepth(CModelFlagsFlags modelFlags, CCubeMaterialFlags matFlags);
|
||||
static u32 HandleColorChannels(u32 chanCount, u32 firstChan);
|
||||
static void HandleTev(u32 tevCur, const u32* materialDataCur, const u32* texMapTexCoordFlags, bool shadowMapsEnabled);
|
||||
static u32 HandleAnimatedUV(const u32* uvAnim, u32 texMtx, u32 pttTexMtx);
|
||||
static u32 HandleAnimatedUV(const u32* uvAnim, GX::TexMtx texMtx, GX::PTTexMtx pttTexMtx);
|
||||
static void HandleTransparency(u32& finalTevCount, u32& finalKColorCount, const CModelFlags& modelFlags,
|
||||
u32 blendFactors, u32& finalCCFlags, u32& finalACFlags);
|
||||
static u32 HandleReflection(bool usesTevReg2, u32 indTexSlot, u32 r5, u32 finalTevCount, u32 texCount, u32 tcgCount,
|
||||
|
|
|
@ -176,7 +176,7 @@ void CCubeModel::DrawFlat(TConstVectorRef positions, TConstVectorRef normals, ES
|
|||
void CCubeModel::DrawNormal(TConstVectorRef positions, TConstVectorRef normals, ESurfaceSelection surfaces) {
|
||||
CGX::SetNumIndStages(0);
|
||||
CGX::SetNumTevStages(1);
|
||||
CGX::SetNumTexGens(1);
|
||||
CGX::SetNumTexGens(1); // TODO should this be 0?
|
||||
CGX::SetZMode(true, GX::LEQUAL, true);
|
||||
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL);
|
||||
CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO);
|
||||
|
|
|
@ -44,7 +44,7 @@ struct SGXState {
|
|||
u16 x56_blendMode = 0;
|
||||
std::array<GXColor, GX::MAX_KCOLOR> x58_kColors;
|
||||
std::array<STevState, GX::MAX_TEVSTAGE> x68_tevStates;
|
||||
std::array<STexState, GX::MAX_TEXMAP> x228_texStates;
|
||||
std::array<STexState, GX::MAX_TEXCOORD> x228_texStates;
|
||||
u32 x248_alphaCompare = 0;
|
||||
float x24c_fogStartZ = 0.f;
|
||||
float x250_fogEndZ = 0.f;
|
||||
|
@ -367,9 +367,25 @@ static inline void SetTevOrder(GX::TevStageID stageId, GX::TexCoordID texCoord,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void SetTexCoordGen(GX::TexCoordID dstCoord, GX::TexGenType fn, GX::TexGenSrc src, u32 mtx,
|
||||
GXBool normalize, u32 postMtx) noexcept {
|
||||
// TODO
|
||||
static inline void SetTexCoordGen(GX::TexCoordID dstCoord, GX::TexGenType fn, GX::TexGenSrc src, GX::TexMtx mtx,
|
||||
GXBool normalize, GX::PTTexMtx postMtx) noexcept {
|
||||
u32 flags = ((postMtx - GX::PTTEXMTX0) & 63) << 15 | (u8(normalize) & 1) << 14 | ((mtx - GX::TEXMTX0) & 31) << 9 |
|
||||
(src & 31) << 4 | (fn & 15);
|
||||
auto& state = sGXState.x228_texStates[dstCoord].x0_coordGen;
|
||||
if (flags != state) {
|
||||
state = flags;
|
||||
GXSetTexCoordGen2(dstCoord, fn, src, mtx, normalize, postMtx);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTexCoordGen(GX::TexCoordID dstCoord, u32 flags) noexcept {
|
||||
auto& state = sGXState.x228_texStates[dstCoord].x0_coordGen;
|
||||
if (flags != state) {
|
||||
state = flags;
|
||||
GXSetTexCoordGen2(dstCoord, GX::TexGenType(flags & 15), GX::TexGenSrc(flags >> 4 & 31),
|
||||
GX::TexMtx((flags >> 9 & 31) + GX::TEXMTX0), GXBool(flags >> 14 & 1),
|
||||
GX::PTTexMtx((flags >> 15 & 63) + GX::PTTEXMTX0));
|
||||
}
|
||||
}
|
||||
|
||||
void SetVtxDescv(GX::VtxDescList* descList) noexcept;
|
||||
|
|
|
@ -185,8 +185,7 @@ void CGraphics::Render2D(CTexture& tex, u32 x, u32 y, u32 w, u32 h, const zeus::
|
|||
const auto oldLights = g_LightActive;
|
||||
SetOrtho(-g_Viewport.x10_halfWidth, g_Viewport.x10_halfWidth, g_Viewport.x14_halfHeight, -g_Viewport.x14_halfHeight,
|
||||
-1.f, -10.f);
|
||||
// disable Y/Z swap TODO do we need to do this elsewhere?
|
||||
aurora::gfx::update_model_view(zeus::CMatrix4f{}, zeus::CMatrix4f{});
|
||||
GXLoadPosMtxImm({}, GX::PNMTX0);
|
||||
DisableAllLights();
|
||||
SetCullMode(ERglCullMode::None);
|
||||
tex.Load(GX::TEXMAP0, EClampMode::Repeat);
|
||||
|
@ -252,12 +251,13 @@ void CGraphics::SetViewMatrix() {
|
|||
else
|
||||
g_GXModelView = g_CameraMatrix * g_GXModelMatrix;
|
||||
/* Load position matrix */
|
||||
GXLoadPosMtxImm(g_GXModelView, GX::PNMTX0);
|
||||
/* Inverse-transpose */
|
||||
g_GXModelViewInvXpose = g_GXModelView.inverse();
|
||||
g_GXModelViewInvXpose.origin.zeroOut();
|
||||
g_GXModelViewInvXpose.basis.transpose();
|
||||
/* Load normal matrix */
|
||||
aurora::gfx::update_model_view(g_GXModelView.toMatrix4f(), g_GXModelViewInvXpose.toMatrix4f());
|
||||
GXLoadNrmMtxImm(g_GXModelViewInvXpose, GX::PNMTX0);
|
||||
}
|
||||
|
||||
void CGraphics::SetModelMatrix(const zeus::CTransform& xf) {
|
||||
|
@ -365,12 +365,14 @@ void CGraphics::SetOrtho(float left, float right, float top, float bottom, float
|
|||
}
|
||||
|
||||
void CGraphics::FlushProjection() {
|
||||
const auto mtx = GetPerspectiveProjectionMatrix();
|
||||
if (g_Proj.x0_persp) {
|
||||
// Convert and load persp
|
||||
GXSetProjection(mtx, GX::PERSPECTIVE);
|
||||
} else {
|
||||
// Convert and load ortho
|
||||
GXSetProjection(mtx, GX::ORTHOGRAPHIC);
|
||||
}
|
||||
aurora::gfx::update_projection(GetPerspectiveProjectionMatrix());
|
||||
}
|
||||
|
||||
zeus::CVector2i CGraphics::ProjectPoint(const zeus::CVector3f& point) {
|
||||
|
@ -460,17 +462,19 @@ void CGraphics::SetViewport(int leftOff, int bottomOff, int width, int height) {
|
|||
CachedVP.position[1] = bottomOff;
|
||||
CachedVP.size[0] = width;
|
||||
CachedVP.size[1] = height;
|
||||
aurora::gfx::set_viewport(CachedVP, g_CachedDepthRange[0], g_CachedDepthRange[1]);
|
||||
GXSetViewport(CachedVP.position[0], CachedVP.position[1], CachedVP.size[0], CachedVP.size[1], g_CachedDepthRange[0],
|
||||
g_CachedDepthRange[1]);
|
||||
}
|
||||
|
||||
void CGraphics::SetScissor(int leftOff, int bottomOff, int width, int height) {
|
||||
aurora::gfx::set_scissor(leftOff, bottomOff, width, height);
|
||||
GXSetScissor(leftOff, bottomOff, width, height);
|
||||
}
|
||||
|
||||
void CGraphics::SetDepthRange(float znear, float zfar) {
|
||||
g_CachedDepthRange[0] = znear;
|
||||
g_CachedDepthRange[1] = zfar;
|
||||
aurora::gfx::set_viewport(CachedVP, g_CachedDepthRange[0], g_CachedDepthRange[1]);
|
||||
GXSetViewport(CachedVP.position[0], CachedVP.position[1], CachedVP.size[0], CachedVP.size[1], g_CachedDepthRange[0],
|
||||
g_CachedDepthRange[1]);
|
||||
}
|
||||
|
||||
CTimeProvider* CGraphics::g_ExternalTimeProvider = nullptr;
|
||||
|
@ -600,7 +604,8 @@ void CGraphics::SetTevStates(EStreamFlags flags) noexcept {
|
|||
}
|
||||
CGX::SetNumChans(1);
|
||||
CGX::SetNumIndStages(0);
|
||||
// TODO load TCGs
|
||||
CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY);
|
||||
CGX::SetTexCoordGen(GX::TEXCOORD1, GX::TG_MTX2x4, GX::TG_TEX1, GX::IDENTITY, false, GX::PTIDENTITY);
|
||||
const bool hasLights = g_LightActive.any();
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel0, hasLights, GX::SRC_REG,
|
||||
flags & EStreamFlagBits::fHasColor ? GX::SRC_VTX : GX::SRC_REG, g_LightActive,
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include <bitset>
|
||||
|
||||
#include <zeus/CColor.hpp>
|
||||
#include <zeus/CMatrix4f.hpp>
|
||||
#include <zeus/CTransform.hpp>
|
||||
|
||||
namespace GX {
|
||||
enum Attr {
|
||||
|
@ -246,7 +248,8 @@ enum TexGenSrc {
|
|||
TG_TEXCOORD5,
|
||||
TG_TEXCOORD6,
|
||||
TG_COLOR0,
|
||||
TG_COLOR1
|
||||
TG_COLOR1,
|
||||
MAX_TEXGENSRC = 0xFF,
|
||||
};
|
||||
|
||||
enum TexMtx {
|
||||
|
@ -644,6 +647,24 @@ enum FogType {
|
|||
FOG_ORTHO_REVEXP2 = 0x0F,
|
||||
};
|
||||
|
||||
enum PosNrmMtx {
|
||||
PNMTX0,
|
||||
PNMTX1,
|
||||
PNMTX2,
|
||||
PNMTX3,
|
||||
PNMTX4,
|
||||
PNMTX5,
|
||||
PNMTX6,
|
||||
PNMTX7,
|
||||
PNMTX8,
|
||||
PNMTX9,
|
||||
};
|
||||
|
||||
enum ProjectionType {
|
||||
PERSPECTIVE,
|
||||
ORTHOGRAPHIC,
|
||||
};
|
||||
|
||||
} // namespace GX
|
||||
|
||||
using GXColor = zeus::CColor;
|
||||
|
@ -684,4 +705,13 @@ void GXClearVtxDesc() noexcept;
|
|||
void GXSetArray(GX::Attr attr, const void* data, u8 stride) noexcept;
|
||||
void GXSetTevDirect(GX::TevStageID stageId) noexcept;
|
||||
void GXSetFog(GX::FogType type, float startZ, float endZ, float nearZ, float farZ, const GXColor& color) noexcept;
|
||||
void GXSetFogColor(const GXColor& color) noexcept;
|
||||
void GXCallDisplayList(const void* data, u32 nbytes) noexcept;
|
||||
void GXSetTexCoordGen2(GX::TexCoordID dst, GX::TexGenType type, GX::TexGenSrc src, GX::TexMtx mtx, GXBool normalize,
|
||||
GX::PTTexMtx postMtx) noexcept;
|
||||
void GXLoadTexMtxImm(const void* data, u32 id /* GX::TexMtx or GX::PTTexMtx */, GX::TexMtxType type) noexcept;
|
||||
void GXLoadPosMtxImm(const zeus::CTransform& xf, GX::PosNrmMtx id) noexcept;
|
||||
void GXLoadNrmMtxImm(const zeus::CTransform& xf, GX::PosNrmMtx id) noexcept;
|
||||
void GXSetProjection(const zeus::CMatrix4f& mtx, GX::ProjectionType type) noexcept;
|
||||
void GXSetViewport(float left, float top, float width, float height, float nearZ, float farZ) noexcept;
|
||||
void GXSetScissor(u32 left, u32 top, u32 width, u32 height) noexcept;
|
||||
|
|
|
@ -15,6 +15,7 @@ struct Vec2 {
|
|||
T x{};
|
||||
T y{};
|
||||
|
||||
constexpr Vec2() = default;
|
||||
constexpr Vec2(T x, T y) : x(x), y(y) {}
|
||||
constexpr Vec2(const zeus::CVector2f& vec) : x(vec.x()), y(vec.y()) {}
|
||||
};
|
||||
|
@ -24,6 +25,7 @@ struct Vec3 {
|
|||
T y{};
|
||||
T z{};
|
||||
|
||||
constexpr Vec3() = default;
|
||||
constexpr Vec3(T x, T y, T z) : x(x), y(y), z(z) {}
|
||||
constexpr Vec3(const zeus::CVector3f& vec) : x(vec.x()), y(vec.y()), z(vec.z()) {}
|
||||
};
|
||||
|
@ -34,20 +36,34 @@ struct Vec4 {
|
|||
T z{};
|
||||
T w{};
|
||||
|
||||
constexpr Vec4() = default;
|
||||
constexpr Vec4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {}
|
||||
constexpr Vec4(const zeus::CVector4f& vec) : x(vec.x()), y(vec.y()), z(vec.z()), w(vec.w()) {}
|
||||
constexpr Vec4(const zeus::CColor& color) : x(color.r()), y(color.g()), z(color.b()), w(color.a()) {}
|
||||
};
|
||||
template <typename T>
|
||||
struct Mat4x2 {
|
||||
Vec2<T> m0{};
|
||||
Vec2<T> m1{};
|
||||
Vec2<T> m2{};
|
||||
Vec2<T> m3{};
|
||||
|
||||
constexpr Mat4x2() = default;
|
||||
constexpr Mat4x2(const Vec2<T>& m0, const Vec2<T>& m1, const Vec2<T>& m2, const Vec2<T>& m3)
|
||||
: m0(m0), m1(m1), m2(m2), m3(m3) {}
|
||||
};
|
||||
template <typename T>
|
||||
struct Mat4x4 {
|
||||
Vec4<T> m0{};
|
||||
Vec4<T> m1{};
|
||||
Vec4<T> m2{};
|
||||
Vec4<T> m3{};
|
||||
|
||||
constexpr Mat4x4() = default;
|
||||
constexpr Mat4x4(const Vec4<T>& m0, const Vec4<T>& m1, const Vec4<T>& m2, const Vec4<T>& m3)
|
||||
: m0(m0), m1(m1), m2(m2), m3(m3) {}
|
||||
constexpr Mat4x4(const zeus::CMatrix4f& m) : m0(m[0]), m1(m[1]), m2(m[2]), m3(m[3]) {}
|
||||
constexpr Mat4x4(const zeus::CTransform& m) : Mat4x4(m.toMatrix4f()) {}
|
||||
};
|
||||
constexpr Mat4x4<float> Mat4x4_Identity{
|
||||
Vec4<float>{1.f, 0.f, 0.f, 0.f},
|
||||
|
|
|
@ -141,12 +141,10 @@ void stream_end() noexcept;
|
|||
void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHandle& tex, float lod) noexcept;
|
||||
void unbind_texture(GX::TexMapID id) noexcept;
|
||||
|
||||
void update_model_view(const zeus::CMatrix4f& mv, const zeus::CMatrix4f& mv_inv) noexcept;
|
||||
void update_projection(const zeus::CMatrix4f& proj) noexcept;
|
||||
void update_fog_state(const metaforce::CFogState& state) noexcept;
|
||||
void load_light(GX::LightID id, const Light& light) noexcept;
|
||||
void load_light_ambient(GX::LightID id, const zeus::CColor& ambient) noexcept;
|
||||
void set_viewport(const zeus::CRectangle& rect, float znear, float zfar) noexcept;
|
||||
void set_viewport(float left, float top, float width, float height, float znear, float zfar) noexcept;
|
||||
void set_scissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) noexcept;
|
||||
|
||||
void resolve_color(const ClipRect& rect, uint32_t bind, bool clear_depth) noexcept;
|
||||
|
|
|
@ -55,7 +55,10 @@ struct Command {
|
|||
CommandType type;
|
||||
union Data {
|
||||
struct SetViewportCommand {
|
||||
zeus::CRectangle rect;
|
||||
float left;
|
||||
float top;
|
||||
float width;
|
||||
float height;
|
||||
float znear;
|
||||
float zfar;
|
||||
} setViewport;
|
||||
|
@ -443,8 +446,7 @@ void render(const wgpu::RenderPassEncoder& pass) {
|
|||
switch (cmd.type) {
|
||||
case CommandType::SetViewport: {
|
||||
const auto& vp = cmd.data.setViewport;
|
||||
pass.SetViewport(vp.rect.position.x(), vp.rect.position.y(), vp.rect.size.x(), vp.rect.size.y(), vp.znear,
|
||||
vp.zfar);
|
||||
pass.SetViewport(vp.left, vp.top, vp.width, vp.height, vp.znear, vp.zfar);
|
||||
} break;
|
||||
case CommandType::SetScissor: {
|
||||
const auto& sc = cmd.data.setScissor;
|
||||
|
|
|
@ -116,7 +116,73 @@ void GXSetAlphaCompare(GX::Compare comp0, float ref0, GX::AlphaOp op, GX::Compar
|
|||
unreachable();
|
||||
}
|
||||
}
|
||||
void GXSetVtxDescv(GX::VtxDescList* list) noexcept;
|
||||
void GXSetTexCoordGen2(GX::TexCoordID dst, GX::TexGenType type, GX::TexGenSrc src, GX::TexMtx mtx, GXBool normalize,
|
||||
GX::PTTexMtx postMtx) noexcept {
|
||||
if (dst < GX::TEXCOORD0 || dst > GX::TEXCOORD7) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid tex coord {}"), dst);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.tcgs[dst] = {type, src, mtx, postMtx, normalize};
|
||||
}
|
||||
void GXLoadTexMtxImm(const void* data, u32 id, GX::TexMtxType type) noexcept {
|
||||
if ((id < GX::TEXMTX0 || id > GX::IDENTITY) && (id < GX::PTTEXMTX0 || id > GX::PTIDENTITY)) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid tex mtx {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
if (id >= GX::PTTEXMTX0) {
|
||||
if (type != GX::MTX3x4) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid pt mtx type {}"), type);
|
||||
unreachable();
|
||||
}
|
||||
const auto idx = (id - GX::PTTEXMTX0) / 3;
|
||||
g_gxState.ptTexMtxs[idx] = *static_cast<const zeus::CTransform*>(data);
|
||||
} else {
|
||||
const auto idx = (id - GX::TEXMTX0) / 3;
|
||||
switch (type) {
|
||||
case GX::MTX3x4:
|
||||
g_gxState.texMtxs[idx] = aurora::Mat4x4<float>{*static_cast<const zeus::CTransform*>(data)};
|
||||
break;
|
||||
case GX::MTX2x4:
|
||||
g_gxState.texMtxs[idx] = *static_cast<const aurora::Mat4x2<float>*>(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void GXLoadPosMtxImm(const zeus::CTransform& xf, GX::PosNrmMtx id) noexcept {
|
||||
if (id != GX::PNMTX0) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid pn mtx {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.mv = xf.toMatrix4f();
|
||||
}
|
||||
void GXLoadNrmMtxImm(const zeus::CTransform& xf, GX::PosNrmMtx id) noexcept {
|
||||
if (id != GX::PNMTX0) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid pn mtx {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.mvInv = xf.toMatrix4f();
|
||||
}
|
||||
constexpr zeus::CMatrix4f DepthCorrect{
|
||||
// clang-format off
|
||||
1.f, 0.f, 0.f, 0.f,
|
||||
0.f, 1.f, 0.f, 0.f,
|
||||
0.f, 0.f, 0.5f, 0.5f,
|
||||
0.f, 0.f, 0.f, 1.f,
|
||||
// clang-format on
|
||||
};
|
||||
void GXSetProjection(const zeus::CMatrix4f& mtx, GX::ProjectionType type) noexcept {
|
||||
if (type == GX::PERSPECTIVE) {
|
||||
g_gxState.proj = DepthCorrect * mtx;
|
||||
} else {
|
||||
g_gxState.proj = mtx;
|
||||
}
|
||||
}
|
||||
void GXSetViewport(float left, float top, float width, float height, float nearZ, float farZ) noexcept {
|
||||
aurora::gfx::set_viewport(left, top, width, height, nearZ, farZ);
|
||||
}
|
||||
void GXSetScissor(u32 left, u32 top, u32 width, u32 height) noexcept {
|
||||
aurora::gfx::set_scissor(left, top, width, height);
|
||||
}
|
||||
|
||||
namespace aurora::gfx {
|
||||
static logvisor::Module Log("aurora::gfx::gx");
|
||||
|
@ -130,19 +196,6 @@ void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHan
|
|||
}
|
||||
void unbind_texture(GX::TexMapID id) noexcept { gx::g_gxState.textures[static_cast<size_t>(id)].reset(); }
|
||||
|
||||
void update_model_view(const zeus::CMatrix4f& mv, const zeus::CMatrix4f& mv_inv) noexcept {
|
||||
gx::g_gxState.mv = mv;
|
||||
gx::g_gxState.mvInv = mv_inv;
|
||||
}
|
||||
constexpr zeus::CMatrix4f DepthCorrect{
|
||||
// clang-format off
|
||||
1.f, 0.f, 0.f, 0.f,
|
||||
0.f, 1.f, 0.f, 0.f,
|
||||
0.f, 0.f, 0.5f, 0.5f,
|
||||
0.f, 0.f, 0.f, 1.f,
|
||||
// clang-format on
|
||||
};
|
||||
void update_projection(const zeus::CMatrix4f& proj) noexcept { gx::g_gxState.proj = DepthCorrect * proj; }
|
||||
void update_fog_state(const metaforce::CFogState& state) noexcept { gx::g_gxState.fogState = state; }
|
||||
|
||||
void load_light(GX::LightID id, const Light& light) noexcept { gx::g_gxState.lights[std::log2<u32>(id)] = light; }
|
||||
|
@ -338,6 +391,9 @@ ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primit
|
|||
for (u8 i = 0; i < g_gxState.numChans; ++i) {
|
||||
config.shaderConfig.colorChannels[i] = g_gxState.colorChannelConfig[i];
|
||||
}
|
||||
for (u8 i = 0; i < g_gxState.numTexGens; ++i) {
|
||||
config.shaderConfig.tcgs[i] = g_gxState.tcgs[i];
|
||||
}
|
||||
config.shaderConfig.alphaDiscard = g_gxState.alphaDiscard;
|
||||
config = {
|
||||
.shaderConfig = config.shaderConfig,
|
||||
|
@ -412,6 +468,39 @@ Range build_uniform(const ShaderInfo& info) noexcept {
|
|||
}
|
||||
buf.append(&g_gxState.kcolors[i], 16);
|
||||
}
|
||||
for (int i = 0; i < info.usesTexMtx.size(); ++i) {
|
||||
if (!info.usesTexMtx.test(i)) {
|
||||
continue;
|
||||
}
|
||||
switch (info.texMtxTypes[i]) {
|
||||
case GX::TG_MTX2x4:
|
||||
if (std::holds_alternative<Mat4x2<float>>(g_gxState.texMtxs[i])) {
|
||||
buf.append(&std::get<Mat4x2<float>>(g_gxState.texMtxs[i]), 32);
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("expected 2x4 mtx in idx {}"), i);
|
||||
unreachable();
|
||||
}
|
||||
break;
|
||||
case GX::TG_MTX3x4:
|
||||
if (std::holds_alternative<Mat4x4<float>>(g_gxState.texMtxs[i])) {
|
||||
const auto& mat = std::get<Mat4x4<float>>(g_gxState.texMtxs[i]);
|
||||
buf.append(&mat, 64);
|
||||
} else {
|
||||
// Log.report(logvisor::Fatal, FMT_STRING("expected 3x4 mtx in idx {}"), i);
|
||||
buf.append(&Mat4x4_Identity, 64);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled tex mtx type {}"), info.texMtxTypes[i]);
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < info.usesPTTexMtx.size(); ++i) {
|
||||
if (!info.usesPTTexMtx.test(i)) {
|
||||
continue;
|
||||
}
|
||||
buf.append(&g_gxState.ptTexMtxs[i], 48);
|
||||
}
|
||||
for (int i = 0; i < info.sampledTextures.size(); ++i) {
|
||||
if (!info.sampledTextures.test(i)) {
|
||||
continue;
|
||||
|
|
|
@ -10,6 +10,9 @@ constexpr u32 MaxTevStages = GX::MAX_TEVSTAGE;
|
|||
constexpr u32 MaxColorChannels = 2; // COLOR0A0, COLOR1A1
|
||||
constexpr u32 MaxTevRegs = 3; // TEVREG0-2
|
||||
constexpr u32 MaxKColors = GX::MAX_KCOLOR;
|
||||
constexpr u32 MaxTexMtx = 10;
|
||||
constexpr u32 MaxPTTexMtx = 20;
|
||||
constexpr u32 MaxTexCoord = GX::MAX_TEXCOORD;
|
||||
|
||||
template <typename Arg, Arg Default>
|
||||
struct TevPass {
|
||||
|
@ -61,6 +64,15 @@ struct ColorChannelState {
|
|||
GX::LightMask lightState;
|
||||
};
|
||||
using LightVariant = std::variant<std::monostate, Light, zeus::CColor>;
|
||||
// Mat4x4 used instead of Mat4x3 for padding purposes
|
||||
using TexMtxVariant = std::variant<std::monostate, Mat4x2<float>, Mat4x4<float>>;
|
||||
struct TcgConfig {
|
||||
GX::TexGenType type = GX::TG_MTX2x4;
|
||||
GX::TexGenSrc src = GX::MAX_TEXGENSRC;
|
||||
GX::TexMtx mtx = GX::IDENTITY;
|
||||
GX::PTTexMtx postMtx = GX::PTIDENTITY;
|
||||
bool normalize = false;
|
||||
};
|
||||
|
||||
struct GXState {
|
||||
zeus::CMatrix4f mv;
|
||||
|
@ -83,6 +95,9 @@ struct GXState {
|
|||
std::array<LightVariant, GX::MaxLights> lights;
|
||||
std::array<TevStage, MaxTevStages> tevStages;
|
||||
std::array<TextureBind, MaxTextures> textures;
|
||||
std::array<TexMtxVariant, MaxTexMtx> texMtxs;
|
||||
std::array<Mat4x4<float>, MaxPTTexMtx> ptTexMtxs;
|
||||
std::array<TcgConfig, MaxTexCoord> tcgs;
|
||||
bool depthCompare = true;
|
||||
bool depthUpdate = true;
|
||||
bool alphaUpdate = true;
|
||||
|
@ -101,6 +116,7 @@ const TextureBind& get_texture(GX::TexMapID id) noexcept;
|
|||
struct ShaderConfig {
|
||||
std::array<std::optional<TevStage>, MaxTevStages> tevStages;
|
||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannels;
|
||||
std::array<TcgConfig, MaxTexCoord> tcgs;
|
||||
std::optional<float> alphaDiscard;
|
||||
bool denormalizedVertexAttributes = false;
|
||||
bool denormalizedHasNrm = false; // TODO this is a hack
|
||||
|
@ -133,6 +149,9 @@ struct ShaderInfo {
|
|||
std::bitset<MaxKColors> sampledKColors;
|
||||
std::bitset<MaxColorChannels> sampledColorChannels;
|
||||
std::bitset<MaxTevRegs> usesTevReg;
|
||||
std::bitset<MaxTexMtx> usesTexMtx;
|
||||
std::bitset<MaxPTTexMtx> usesPTTexMtx;
|
||||
std::array<GX::TexGenType, MaxTexMtx> texMtxTypes;
|
||||
u32 uniformSize = 0;
|
||||
bool usesVtxColor : 1 = false;
|
||||
bool usesNormal : 1 = false;
|
||||
|
@ -204,6 +223,14 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ColorChannelConfig&
|
|||
}
|
||||
}
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::TcgConfig& input) {
|
||||
XXH3_64bits_update(&state, &input.type, sizeof(gfx::gx::TcgConfig::type));
|
||||
XXH3_64bits_update(&state, &input.src, sizeof(gfx::gx::TcgConfig::src));
|
||||
XXH3_64bits_update(&state, &input.mtx, sizeof(gfx::gx::TcgConfig::mtx));
|
||||
XXH3_64bits_update(&state, &input.postMtx, sizeof(gfx::gx::TcgConfig::postMtx));
|
||||
XXH3_64bits_update(&state, &input.normalize, sizeof(gfx::gx::TcgConfig::normalize));
|
||||
}
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input) {
|
||||
for (const auto& item : input.tevStages) {
|
||||
if (!item) {
|
||||
|
@ -214,6 +241,9 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input)
|
|||
for (const auto& item : input.colorChannels) {
|
||||
xxh3_update(state, item);
|
||||
}
|
||||
for (const auto& item : input.tcgs) {
|
||||
xxh3_update(state, item);
|
||||
}
|
||||
if (input.alphaDiscard) {
|
||||
XXH3_64bits_update(&state, &*input.alphaDiscard, sizeof(float));
|
||||
}
|
||||
|
|
|
@ -334,6 +334,16 @@ static std::string_view tev_scale(GX::TevScale scale) {
|
|||
}
|
||||
}
|
||||
|
||||
static std::string in_uv(u32 idx) {
|
||||
if (idx == 0) {
|
||||
return "v_packed_uvs.data[in_uv_0_4_idx[0]]";
|
||||
}
|
||||
if (idx < 4) {
|
||||
return fmt::format(FMT_STRING("v_uvs.data[in_uv_0_4_idx[{}]]"), idx);
|
||||
}
|
||||
return fmt::format(FMT_STRING("v_uvs.data[in_uv_5_7_idx[{}]]"), idx - 4);
|
||||
}
|
||||
|
||||
std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& config) noexcept {
|
||||
const auto hash = xxh3_hash(config);
|
||||
if (g_gxCachedShaders.contains(hash)) {
|
||||
|
@ -376,10 +386,19 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
|||
Log.report(logvisor::Info, FMT_STRING(" texMapId: {}"), stage->texMapId);
|
||||
Log.report(logvisor::Info, FMT_STRING(" channelId: {}"), stage->channelId);
|
||||
}
|
||||
// for (int i = 0; i < config.channelMatSrcs.size(); ++i) {
|
||||
// Log.report(logvisor::Info, FMT_STRING(" channelMatSrcs[{}]: {}"), i, config.channelMatSrcs[i]);
|
||||
// }
|
||||
// Log.report(logvisor::Info, FMT_STRING(" alphaDiscard: {}"), config.alphaDiscard);
|
||||
for (int i = 0; i < config.colorChannels.size(); ++i) {
|
||||
const auto& chan = config.colorChannels[i];
|
||||
Log.report(logvisor::Info, FMT_STRING(" colorChannels[{}]: enabled {} mat {} amb {}"), i, chan.lightingEnabled,
|
||||
chan.matSrc, chan.ambSrc);
|
||||
}
|
||||
for (int i = 0; i < config.tcgs.size(); ++i) {
|
||||
const auto& tcg = config.tcgs[i];
|
||||
if (tcg.src != GX::MAX_TEXGENSRC) {
|
||||
Log.report(logvisor::Info, FMT_STRING(" tcg[{}]: src {} mtx {} post {} type {} norm {}"), i, tcg.src, tcg.mtx,
|
||||
tcg.postMtx, tcg.type, tcg.normalize);
|
||||
}
|
||||
}
|
||||
Log.report(logvisor::Info, FMT_STRING(" alphaDiscard: {}"), config.alphaDiscard.value_or(0.f));
|
||||
Log.report(logvisor::Info, FMT_STRING(" denormalizedVertexAttributes: {}"), config.denormalizedVertexAttributes);
|
||||
}
|
||||
|
||||
|
@ -593,6 +612,78 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
info.uniformSize += 16;
|
||||
}
|
||||
size_t texBindIdx = 0;
|
||||
for (int i = 0; i < info.sampledTextures.size(); ++i) {
|
||||
if (!info.sampledTextures.test(i)) {
|
||||
continue;
|
||||
}
|
||||
const auto& tcg = config.tcgs[i];
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), locIdx, i);
|
||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_tex{}_uv: vec2<f32>"), locIdx + 1, i);
|
||||
// TODO check tcg src for denorm?
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0} = vec4<f32>(in_tex{0}_uv, 0.0, 1.0);"), i);
|
||||
} else {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), locIdx, i);
|
||||
if (tcg.src >= GX::TG_TEX0 && tcg.src <= GX::TG_TEX7) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>({}, 0.0, 1.0);"), i, in_uv(tcg.src - GX::TG_TEX0));
|
||||
} else if (tcg.src == GX::TG_POS) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>(obj_pos.xyz, 1.0);"), i);
|
||||
} else if (tcg.src == GX::TG_NRM) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>(obj_norm.xyz, 1.0);"), i);
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled tcg src {}"), tcg.src);
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
// TODO this all assumes MTX3x4 currently
|
||||
if (tcg.mtx == GX::IDENTITY) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_tmp = tc{0}.xyz;"), i);
|
||||
} else {
|
||||
u32 texMtxIdx = (tcg.mtx - GX::TEXMTX0) / 3;
|
||||
info.usesTexMtx.set(texMtxIdx);
|
||||
info.texMtxTypes[texMtxIdx] = tcg.type;
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_tmp = ubuf.texmtx{1} * tc{0};"), i, texMtxIdx);
|
||||
}
|
||||
if (tcg.normalize) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n tc{0}_tmp = normalize(tc{0}_tmp);"), i);
|
||||
}
|
||||
if (tcg.postMtx == GX::PTIDENTITY) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_proj = tc{0}_tmp;"), i);
|
||||
} else {
|
||||
u32 postMtxIdx = (tcg.postMtx - GX::PTTEXMTX0) / 3;
|
||||
info.usesPTTexMtx.set(postMtxIdx);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_proj = ubuf.postmtx{1} * vec4<f32>(tc{0}_tmp.xyz, 1.0);"), i, postMtxIdx);
|
||||
}
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{0}_uv = tc{0}_proj.xy;"), i);
|
||||
fragmentFnPre += fmt::format(
|
||||
FMT_STRING("\n var sampled{0} = textureSampleBias(tex{0}, tex{0}_samp, in.tex{0}_uv, ubuf.tex{0}_lod);"), i);
|
||||
locIdx++;
|
||||
}
|
||||
for (int i = 0; i < info.usesTexMtx.size(); ++i) {
|
||||
if (!info.usesTexMtx.test(i)) {
|
||||
continue;
|
||||
}
|
||||
switch (info.texMtxTypes[i]) {
|
||||
case GX::TG_MTX2x4:
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n texmtx{}: mat4x2<f32>;"), i);
|
||||
info.uniformSize += 32;
|
||||
break;
|
||||
case GX::TG_MTX3x4:
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n texmtx{}: mat4x3<f32>;"), i);
|
||||
info.uniformSize += 64;
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled tex mtx type {}"), info.texMtxTypes[i]);
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < info.usesPTTexMtx.size(); ++i) {
|
||||
if (!info.usesPTTexMtx.test(i)) {
|
||||
continue;
|
||||
}
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n postmtx{}: mat4x3<f32>;"), i);
|
||||
info.uniformSize += 64;
|
||||
}
|
||||
for (int i = 0; i < info.sampledTextures.size(); ++i) {
|
||||
if (!info.sampledTextures.test(i)) {
|
||||
continue;
|
||||
|
@ -607,29 +698,9 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
"var tex{}: texture_2d<f32>;"),
|
||||
texBindIdx, i);
|
||||
++texBindIdx;
|
||||
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), locIdx, i);
|
||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_tex{}_uv: vec2<f32>"), locIdx + 1, i);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{0}_uv = in_tex{0}_uv;"), i);
|
||||
} else {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), locIdx, i);
|
||||
if (i < 4) {
|
||||
if (i == 0) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_packed_uvs.data[in_uv_0_4_idx[{}]];"), i, i);
|
||||
} else {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_uvs.data[in_uv_0_4_idx[{}]];"), i, i);
|
||||
}
|
||||
} else {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_uvs.data[in_uv_5_7_idx[{}]];"), i, i - 4);
|
||||
}
|
||||
}
|
||||
fragmentFnPre += fmt::format(
|
||||
FMT_STRING("\n var sampled{0} = textureSampleBias(tex{0}, tex{0}_samp, in.tex{0}_uv, ubuf.tex{0}_lod);"), i);
|
||||
locIdx++;
|
||||
}
|
||||
if (config.alphaDiscard) {
|
||||
fragmentFn += fmt::format(FMT_STRING("\n if (prev.a < {}f) {{ discard; }}"), *config.alphaDiscard);
|
||||
fragmentFn += fmt::format(FMT_STRING("\n if (prev.a < {}f) {{ discard; }}"), *config.alphaDiscard);
|
||||
}
|
||||
|
||||
const auto shaderSource =
|
||||
|
|
Loading…
Reference in New Issue