mirror of https://github.com/AxioDL/metaforce.git
Implement CGX & migrate usages to CGX/GX
This commit is contained in:
parent
929bb65417
commit
a3d0da44e2
|
@ -23,6 +23,7 @@
|
|||
#include "Runtime/Character/CTransitionManager.hpp"
|
||||
#include "Runtime/Character/IAnimReader.hpp"
|
||||
#include "Runtime/Graphics/CSkinnedModel.hpp"
|
||||
#include "Runtime/Graphics/CGX.hpp"
|
||||
|
||||
#include <logvisor/logvisor.hpp>
|
||||
|
||||
|
@ -559,7 +560,7 @@ void CAnimData::SetupRender(CSkinnedModel& model, CVertexMorphEffect* morphEffec
|
|||
}
|
||||
|
||||
void CAnimData::DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags) {
|
||||
aurora::gfx::set_chan_mat_src(GX::COLOR0A0, GX::SRC_REG);
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel0, CGraphics::g_LightActive);
|
||||
model.Draw(flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -422,12 +422,12 @@ void CModelData::MultiPassDraw(EWhichModel which, const zeus::CTransform& xf, co
|
|||
}
|
||||
}
|
||||
|
||||
void CModelData::DisintegrateDraw(const CStateManager& mgr, const zeus::CTransform& xf, const CTexture& tex,
|
||||
void CModelData::DisintegrateDraw(const CStateManager& mgr, const zeus::CTransform& xf, CTexture& tex,
|
||||
const zeus::CColor& addColor, float t) {
|
||||
DisintegrateDraw(GetRenderingModel(mgr), xf, tex, addColor, t);
|
||||
}
|
||||
|
||||
void CModelData::DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf, const CTexture& tex,
|
||||
void CModelData::DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf, CTexture& tex,
|
||||
const zeus::CColor& addColor, float t) {
|
||||
zeus::CTransform scaledXf = xf * zeus::CTransform::Scale(x0_scale);
|
||||
CGraphics::SetModelMatrix(scaledXf);
|
||||
|
@ -435,27 +435,13 @@ void CModelData::DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf,
|
|||
const auto aabb = GetBounds(scaledXf);
|
||||
if (x10_animData) {
|
||||
auto& model = PickAnimatedModel(which);
|
||||
// x10_animData->SetupRender(model, CModelFlags{}, {}, ?)
|
||||
model.DoDrawCallback([](auto positions, auto normals) {
|
||||
// TODO
|
||||
x10_animData->SetupRender(model, nullptr, nullptr);
|
||||
model.DoDrawCallback([&](auto positions, auto normals) {
|
||||
g_Renderer->DrawModelDisintegrate(*model.GetModel(), tex, addColor, positions, normals, t);
|
||||
});
|
||||
} else {
|
||||
g_Renderer->DrawModelDisintegrate(*PickStaticModel(which), tex, addColor, {}, {});
|
||||
g_Renderer->DrawModelDisintegrate(*PickStaticModel(which), tex, addColor, nullptr, nullptr, t);
|
||||
}
|
||||
|
||||
// CBooModel::SetDisintegrateTexture(tex.GetTexture());
|
||||
// CModelFlags flags(5, 0, 3, zeus::skWhite);
|
||||
// flags.m_extendedShader = EExtendedShader::Disintegrate;
|
||||
// flags.addColor = addColor;
|
||||
// flags.addColor.a() = t; // Stash T value in here (shader does not care)
|
||||
//
|
||||
// if (x10_animData) {
|
||||
// CSkinnedModel& sModel = PickAnimatedModel(which);
|
||||
// x10_animData->Render(sModel, flags, std::nullopt, nullptr);
|
||||
// } else {
|
||||
// CBooModel& model = *PickStaticModel(which);
|
||||
// model.Draw(flags, nullptr, nullptr);
|
||||
// }
|
||||
}
|
||||
|
||||
void CModelData::ThermalDraw(const zeus::CColor& mulColor, const zeus::CColor& addColor, const CModelFlags& flags) {}
|
||||
|
|
|
@ -126,10 +126,10 @@ public:
|
|||
const zeus::CColor& alphaColor, const zeus::CColor& additiveColor);
|
||||
void MultiPassDraw(EWhichModel which, const zeus::CTransform& xf, const CActorLights* lights,
|
||||
const CModelFlags* flags, u32 count);
|
||||
void DisintegrateDraw(const CStateManager& mgr, const zeus::CTransform& xf, const CTexture& tex,
|
||||
const zeus::CColor& addColor, float t);
|
||||
void DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf, const CTexture& tex,
|
||||
void DisintegrateDraw(const CStateManager& mgr, const zeus::CTransform& xf, CTexture& tex,
|
||||
const zeus::CColor& addColor, float t);
|
||||
void DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf, CTexture& tex, const zeus::CColor& addColor,
|
||||
float t);
|
||||
void ThermalDraw(const zeus::CColor& mulColor, const zeus::CColor& addColor, const CModelFlags& flags);
|
||||
|
||||
CAnimData* GetAnimationData() { return x10_animData.get(); }
|
||||
|
|
|
@ -4,10 +4,9 @@
|
|||
#include "Graphics/CCubeModel.hpp"
|
||||
#include "Graphics/CCubeRenderer.hpp"
|
||||
#include "Graphics/CCubeSurface.hpp"
|
||||
#include "Graphics/CGX.hpp"
|
||||
#include "Graphics/CModel.hpp"
|
||||
|
||||
#include <aurora/model.hpp>
|
||||
|
||||
namespace metaforce {
|
||||
static u32 sReflectionType = 0;
|
||||
static u32 sLastMaterialUnique = UINT32_MAX;
|
||||
|
@ -68,7 +67,7 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur
|
|||
sLastMaterialUnique = groupIdx;
|
||||
|
||||
u32 vatFlags = SBig(*reinterpret_cast<const u32*>(materialDataCur));
|
||||
aurora::gfx::model::set_vtx_desc_compressed(vatFlags);
|
||||
CGX::SetVtxDescv_Compressed(vatFlags);
|
||||
materialDataCur += 8;
|
||||
|
||||
bool packedLightMaps = matFlags.IsSet(CCubeMaterialFlagBits::fLightmapUvArray);
|
||||
|
@ -84,14 +83,14 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur
|
|||
for (u32 i = 0; i < konstCount; ++i) {
|
||||
u32 kColor = SBig(*reinterpret_cast<const u32*>(materialDataCur));
|
||||
materialDataCur += 4;
|
||||
aurora::gfx::set_tev_k_color(static_cast<GX::TevKColorID>(i), kColor);
|
||||
CGX::SetTevKColor(static_cast<GX::TevKColorID>(i), kColor);
|
||||
}
|
||||
}
|
||||
|
||||
u32 blendFactors = SBig(*reinterpret_cast<const u32*>(materialDataCur));
|
||||
materialDataCur += 4;
|
||||
if (g_Renderer->IsInAreaDraw()) {
|
||||
// TODO blackout fog, additive blend
|
||||
CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ONE, GX::BL_ONE, GX::LO_CLEAR);
|
||||
} else {
|
||||
SetupBlendMode(blendFactors, flags, matFlags.IsSet(CCubeMaterialFlagBits::fAlphaTest));
|
||||
}
|
||||
|
@ -135,7 +134,7 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur
|
|||
materialDataCur += 20;
|
||||
texMapTexCoordFlags += 1;
|
||||
finalCCFlags = SBig(*reinterpret_cast<const u32*>(materialDataCur + 8));
|
||||
aurora::gfx::set_tev_reg_color(GX::TEVREG0, 0xc0c0c0c0);
|
||||
GXSetTevColor(GX::TEVREG0, 0xc0c0c0c0);
|
||||
}
|
||||
finalACFlags = SBig(*reinterpret_cast<const u32*>(materialDataCur + 12));
|
||||
HandleTev(firstTev, reinterpret_cast<const u32*>(materialDataCur), texMapTexCoordFlags,
|
||||
|
@ -219,10 +218,10 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur
|
|||
tcgCount += 1;
|
||||
}
|
||||
|
||||
// SetNumIndStages(numIndStages);
|
||||
aurora::gfx::disable_tev_stage(static_cast<ERglTevStage>(finalTevCount));
|
||||
// SetNumTexGens(tcgCount);
|
||||
// SetNumColorChans(finalNumColorChans);
|
||||
CGX::SetNumIndStages(numIndStages);
|
||||
CGX::SetNumTevStages(finalTevCount);
|
||||
CGX::SetNumTexGens(tcgCount);
|
||||
CGX::SetNumChans(finalNumColorChans);
|
||||
}
|
||||
|
||||
void CCubeMaterial::SetCurrentBlack() {
|
||||
|
@ -230,50 +229,47 @@ void CCubeMaterial::SetCurrentBlack() {
|
|||
auto vatFlags = GetVatFlags();
|
||||
|
||||
if (flags.IsSet(CCubeMaterialFlagBits::fDepthSorting) || flags.IsSet(CCubeMaterialFlagBits::fAlphaTest)) {
|
||||
// set fog mode 0x21
|
||||
aurora::gfx::set_blend_mode(ERglBlendMode::Blend, ERglBlendFactor::Zero, ERglBlendFactor::One, ERglLogicOp::Clear);
|
||||
CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ZERO, GX::BL_ONE, GX::LO_CLEAR);
|
||||
} else {
|
||||
// set fog mode 5
|
||||
aurora::gfx::set_blend_mode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::Zero, ERglLogicOp::Clear);
|
||||
CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR);
|
||||
}
|
||||
// set vtx desc flags
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeMaterial::SetupBlendMode(u32 blendFactors, const CModelFlags& flags, bool alphaTest) {
|
||||
auto newSrcFactor = static_cast<ERglBlendFactor>(blendFactors & 0xffff);
|
||||
auto newDstFactor = static_cast<ERglBlendFactor>(blendFactors >> 16 & 0xffff);
|
||||
auto newSrcFactor = static_cast<GX::BlendFactor>(blendFactors & 0xffff);
|
||||
auto newDstFactor = static_cast<GX::BlendFactor>(blendFactors >> 16 & 0xffff);
|
||||
if (alphaTest) {
|
||||
// discard fragments with alpha < 0.25
|
||||
aurora::gfx::set_alpha_discard(true);
|
||||
newSrcFactor = ERglBlendFactor::One;
|
||||
newDstFactor = ERglBlendFactor::Zero;
|
||||
CGX::SetAlphaCompare(GX::GEQUAL, 64, GX::AOP_OR, GX::NEVER, 0);
|
||||
newSrcFactor = GX::BL_ONE;
|
||||
newDstFactor = GX::BL_ZERO;
|
||||
} else {
|
||||
aurora::gfx::set_alpha_discard(false);
|
||||
CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_OR, GX::ALWAYS, 0);
|
||||
}
|
||||
|
||||
if (flags.x0_blendMode > 4 && newSrcFactor == ERglBlendFactor::One) {
|
||||
newSrcFactor = ERglBlendFactor::SrcAlpha;
|
||||
if (newDstFactor == ERglBlendFactor::Zero) {
|
||||
newDstFactor = flags.x0_blendMode > 6 ? ERglBlendFactor::One : ERglBlendFactor::InvSrcAlpha;
|
||||
if (flags.x0_blendMode > 4 && newSrcFactor == GX::BL_ONE) {
|
||||
newSrcFactor = GX::BL_SRCALPHA;
|
||||
if (newDstFactor == GX::BL_ZERO) {
|
||||
newDstFactor = flags.x0_blendMode > 6 ? GX::BL_ONE : GX::BL_INVSRCALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO set fog color zero if dst blend zero
|
||||
aurora::gfx::set_blend_mode(ERglBlendMode::Blend, newSrcFactor, newDstFactor, ERglLogicOp::Clear);
|
||||
CGX::SetBlendMode(GX::BM_BLEND, newSrcFactor, newDstFactor, GX::LO_CLEAR);
|
||||
}
|
||||
|
||||
void CCubeMaterial::HandleDepth(CModelFlagsFlags modelFlags, CCubeMaterialFlags matFlags) {
|
||||
ERglEnum func = ERglEnum::Never;
|
||||
GX::Compare func = GX::NEVER;
|
||||
if (!(modelFlags & CModelFlagBits::DepthTest)) {
|
||||
func = ERglEnum::Always;
|
||||
func = GX::ALWAYS;
|
||||
} else if (modelFlags & CModelFlagBits::DepthGreater) {
|
||||
func = modelFlags & CModelFlagBits::DepthNonInclusive ? ERglEnum::Greater : ERglEnum::GEqual;
|
||||
func = modelFlags & CModelFlagBits::DepthNonInclusive ? GX::GREATER : GX::GEQUAL;
|
||||
} else {
|
||||
func = modelFlags & CModelFlagBits::DepthNonInclusive ? ERglEnum::Less : ERglEnum::LEqual;
|
||||
func = modelFlags & CModelFlagBits::DepthNonInclusive ? GX::LESS : GX::LEQUAL;
|
||||
}
|
||||
bool depthWrite = modelFlags & CModelFlagBits::DepthUpdate && matFlags & CCubeMaterialFlagBits::fDepthWrite;
|
||||
aurora::gfx::set_depth_mode(true, func, depthWrite);
|
||||
CGX::SetZMode(true, func, depthWrite);
|
||||
}
|
||||
|
||||
void CCubeMaterial::ResetCachedMaterials() {
|
||||
|
@ -305,39 +301,40 @@ void CCubeMaterial::EnsureViewDepStateCached(const CCubeSurface* surface) {
|
|||
u32 CCubeMaterial::HandleColorChannels(u32 chanCount, u32 firstChan) {
|
||||
if (CCubeModel::sRenderModelShadow) {
|
||||
if (chanCount != 0) {
|
||||
aurora::gfx::set_chan_amb_color(GX::COLOR1A1, zeus::skBlack);
|
||||
aurora::gfx::set_chan_mat_color(GX::COLOR1A1, zeus::skWhite);
|
||||
CGX::SetChanAmbColor(CGX::EChannelId::Channel1, zeus::skBlack);
|
||||
CGX::SetChanMatColor(CGX::EChannelId::Channel1, zeus::skWhite);
|
||||
|
||||
// TODO chan / lights
|
||||
|
||||
aurora::gfx::set_chan_mat_color(GX::COLOR0A0, zeus::skWhite);
|
||||
auto chan0Lights = CGraphics::g_LightActive & ~CCubeModel::sChannel0DisableLightMask;
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel0, chan0Lights); // TODO use firstChan flags
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel1, CCubeModel::sChannel1EnableLightMask);
|
||||
if (chan0Lights.any()) {
|
||||
CGX::SetChanMatColor(CGX::EChannelId::Channel0, zeus::skWhite);
|
||||
} else {
|
||||
CGX::SetChanMatColor(CGX::EChannelId::Channel0, CGX::GetChanAmbColor(CGX::EChannelId::Channel0));
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (chanCount == 2) {
|
||||
aurora::gfx::set_chan_amb_color(GX::COLOR1A1, zeus::skBlack);
|
||||
aurora::gfx::set_chan_mat_color(GX::COLOR1A1, zeus::skWhite);
|
||||
CGX::SetChanAmbColor(CGX::EChannelId::Channel1, zeus::skBlack);
|
||||
CGX::SetChanMatColor(CGX::EChannelId::Channel1, zeus::skWhite);
|
||||
} else {
|
||||
// TODO chan ctrls
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel1, {});
|
||||
}
|
||||
|
||||
if (chanCount == 0) {
|
||||
// TODO more chan ctrls
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel0, {});
|
||||
} else {
|
||||
auto uVar3 = firstChan & 0xfffffffe;
|
||||
// TODO enabled lights
|
||||
// TODO chan ctrl
|
||||
// if (sEnabledLights == 0) {
|
||||
// aurora::gfx::set_chan_mat_color(GX::COLOR0A0, amb_clr);
|
||||
// } else {
|
||||
aurora::gfx::set_chan_mat_color(GX::COLOR0A0, zeus::skWhite);
|
||||
// }
|
||||
// TODO use firstChan flags
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel0, CGraphics::g_LightActive);
|
||||
if (CGraphics::g_LightActive.any()) {
|
||||
CGX::SetChanMatColor(CGX::EChannelId::Channel0, zeus::skWhite);
|
||||
} else {
|
||||
CGX::SetChanMatColor(CGX::EChannelId::Channel0, CGX::GetChanAmbColor(CGX::EChannelId::Channel0));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
aurora::gfx::set_chan_mat_src(GX::COLOR0A0, GX::SRC_REG);
|
||||
aurora::gfx::set_chan_mat_src(GX::COLOR1A1, GX::SRC_REG);
|
||||
return chanCount;
|
||||
}
|
||||
|
||||
|
@ -348,27 +345,15 @@ void CCubeMaterial::HandleTev(u32 tevCur, const u32* materialDataCur, const u32*
|
|||
const u32 colorOps = SBig(materialDataCur[2]);
|
||||
const u32 alphaOps = SBig(materialDataCur[3]);
|
||||
|
||||
// GXSetTevDirect(tevCur);
|
||||
const CTevCombiners::ColorPass colPass{colorArgs};
|
||||
const CTevCombiners::AlphaPass alphaPass{alphaArgs};
|
||||
const CTevCombiners::CTevOp colorOp{colorOps};
|
||||
const CTevCombiners::CTevOp alphaOp{alphaOps};
|
||||
// TODO does this actually change anything?
|
||||
// if (colorOps == alphaOps && ((colorOps & 0x1FF) == 0x100)) {
|
||||
// colorOp = {true, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, colorOp.x10_regId};
|
||||
// alphaOp = {true, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, colorOp.x10_regId};
|
||||
// }
|
||||
aurora::gfx::update_tev_stage(static_cast<ERglTevStage>(tevCur), colPass, alphaPass, colorOp, alphaOp);
|
||||
const auto stage = static_cast<GX::TevStageID>(tevCur);
|
||||
CGX::SetStandardDirectTev_Compressed(stage, colorArgs, alphaArgs, colorOps, alphaOps);
|
||||
|
||||
u32 tmtcFlags = SBig(*texMapTexCoordFlags);
|
||||
u32 matFlags = SBig(materialDataCur[4]);
|
||||
aurora::gfx::set_tev_order(static_cast<GX::TevStageID>(tevCur), static_cast<GX::TexCoordID>(tmtcFlags & 0xFF),
|
||||
static_cast<GX::TexMapID>(tmtcFlags >> 8 & 0xFF),
|
||||
static_cast<GX::ChannelID>(matFlags & 0xFF));
|
||||
aurora::gfx::set_tev_k_color_sel(static_cast<GX::TevStageID>(tevCur),
|
||||
static_cast<GX::TevKColorSel>(matFlags >> 0x8 & 0xFF));
|
||||
aurora::gfx::set_tev_k_alpha_sel(static_cast<GX::TevStageID>(tevCur),
|
||||
static_cast<GX::TevKAlphaSel>(matFlags >> 0x10 & 0xFF));
|
||||
CGX::SetTevOrder(stage, static_cast<GX::TexCoordID>(tmtcFlags & 0xFF),
|
||||
static_cast<GX::TexMapID>(tmtcFlags >> 8 & 0xFF), static_cast<GX::ChannelID>(matFlags & 0xFF));
|
||||
CGX::SetTevKColorSel(stage, static_cast<GX::TevKColorSel>(matFlags >> 0x8 & 0xFF));
|
||||
CGX::SetTevKAlphaSel(stage, static_cast<GX::TevKAlphaSel>(matFlags >> 0x10 & 0xFF));
|
||||
}
|
||||
|
||||
u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, u32 texMtx, u32 pttTexMtx) {
|
||||
|
@ -405,76 +390,56 @@ void CCubeMaterial::HandleTransparency(u32& finalTevCount, u32& finalKColorCount
|
|||
u32 blendFactors, u32& finalCCFlags, u32& finalACFlags) {
|
||||
if (modelFlags.x0_blendMode == 2) {
|
||||
u16 dstFactor = blendFactors >> 16 & 0xffff;
|
||||
if (dstFactor == 1)
|
||||
if (dstFactor == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (modelFlags.x0_blendMode == 3) {
|
||||
// Stage outputting splatted KAlpha as color to reg0
|
||||
aurora::gfx::update_tev_stage(static_cast<ERglTevStage>(finalTevCount),
|
||||
CTevCombiners::ColorPass{GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_KONST},
|
||||
CTevCombiners::AlphaPass{GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV},
|
||||
CTevCombiners::CTevOp{true, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, GX::TEVREG0},
|
||||
CTevCombiners::CTevOp{true, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, GX::TEVPREV});
|
||||
// GXSetTevColorIn(finalTevCount, TEVCOLORARG_ZERO, TEVCOLORARG_ZERO, TEVCOLORARG_ZERO, TEVCOLORARG_KONST);
|
||||
// GXSetTevAlphaIn(finalTevCount, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_APREV);
|
||||
// GXSetTevColorOp(finalTevCount, 0, 0, 0, 1, 1); // ColorReg0
|
||||
aurora::gfx::set_tev_k_color_sel(static_cast<GX::TevStageID>(finalTevCount),
|
||||
static_cast<GX::TevKColorSel>(finalKColorCount + GX::TEV_KCSEL_K0_A));
|
||||
// GXSetTevKColorSel(finalTevCount, finalKColorCount+28);
|
||||
// GXSetTevAlphaOp(finalTevCount, 0, 0, 0, 1, 0); // AlphaRegPrev
|
||||
// GXSetTevOrder(finalTevCount, 255, 255, 255);
|
||||
// GXSetTevDirect(finalTevCount);
|
||||
auto stage = static_cast<GX::TevStageID>(finalTevCount);
|
||||
CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_KONST);
|
||||
CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV);
|
||||
CGX::SetTevColorOp(stage, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVREG0);
|
||||
CGX::SetTevKColorSel(stage, static_cast<GX::TevKColorSel>(finalKColorCount + GX::TEV_KCSEL_K0_A));
|
||||
CGX::SetTevAlphaOp(stage, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV);
|
||||
CGX::SetTevOrder(stage, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL);
|
||||
CGX::SetTevDirect(stage);
|
||||
|
||||
// Stage interpolating from splatted KAlpha using KColor
|
||||
aurora::gfx::update_tev_stage(static_cast<ERglTevStage>(finalTevCount + 1),
|
||||
CTevCombiners::ColorPass{GX::CC_CPREV, GX::CC_C0, GX::CC_KONST, GX::CC_ZERO},
|
||||
CTevCombiners::AlphaPass{GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV},
|
||||
CTevCombiners::CTevOp{true, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, GX::TEVPREV},
|
||||
CTevCombiners::CTevOp{true, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, GX::TEVPREV});
|
||||
// GXSetTevColorIn(finalTevCount + 1, TEVCOLORARG_CPREV, TEVCOLORARG_C0, TEVCOLORARG_KONST, TEVCOLORARG_ZERO);
|
||||
// GXSetTevAlphaIn(finalTevCount + 1, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_APREV);
|
||||
aurora::gfx::set_tev_k_color_sel(static_cast<GX::TevStageID>(finalTevCount + 1),
|
||||
static_cast<GX::TevKColorSel>(finalKColorCount + GX::TEV_KCSEL_K0));
|
||||
// GXSetTevKColorSel(finalTevCount, finalKColorCount+12);
|
||||
// SetStandardTevColorAlphaOp(finalTevCount + 1);
|
||||
// GXSetTevDirect(finalTevCount + 1);
|
||||
// GXSetTevOrder(finalTevCount + 1, 255, 255, 255);
|
||||
aurora::gfx::set_tev_k_color(static_cast<GX::TevKColorID>(finalKColorCount), modelFlags.x4_color);
|
||||
// GXSetTevKColor(finalKColorCount, modelFlags.x4_color);
|
||||
stage = static_cast<GX::TevStageID>(stage + 1);
|
||||
CGX::SetTevColorIn(stage, GX::CC_CPREV, GX::CC_C0, GX::CC_KONST, GX::CC_ZERO);
|
||||
CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV);
|
||||
CGX::SetTevKColorSel(stage, static_cast<GX::TevKColorSel>(finalKColorCount + GX::TEV_KCSEL_K0));
|
||||
CGX::SetStandardTevColorAlphaOp(stage);
|
||||
CGX::SetTevDirect(stage);
|
||||
CGX::SetTevOrder(stage, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL);
|
||||
CGX::SetTevKColor(static_cast<GX::TevKColorID>(finalKColorCount), modelFlags.x4_color);
|
||||
|
||||
finalKColorCount += 1;
|
||||
finalTevCount += 2;
|
||||
} else {
|
||||
// Mul KAlpha
|
||||
CTevCombiners::AlphaPass alphaPass{GX::CA_ZERO, GX::CA_KONST, GX::CA_APREV, GX::CA_ZERO};
|
||||
u32 tevAlpha = 0x000380C7; // TEVALPHAARG_ZERO, TEVALPHAARG_KONST, TEVALPHAARG_APREV, TEVALPHAARG_ZERO
|
||||
auto stage = static_cast<GX::TevStageID>(finalTevCount);
|
||||
if (modelFlags.x0_blendMode == 8) {
|
||||
// Set KAlpha
|
||||
alphaPass = {GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_KONST};
|
||||
tevAlpha = 0x00031CE7; // TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_KONST
|
||||
CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_KONST); // Set KAlpha
|
||||
} else {
|
||||
CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_KONST, GX::CA_APREV, GX::CA_ZERO); // Mul KAlpha
|
||||
}
|
||||
// Mul KColor
|
||||
CTevCombiners::ColorPass colorPass{GX::CC_ZERO, GX::CC_KONST, GX::CC_CPREV, GX::CC_ZERO};
|
||||
u32 tevColor = 0x000781CF; // TEVCOLORARG_ZERO, TEVCOLORARG_KONST, TEVCOLORARG_CPREV, TEVCOLORARG_ZERO
|
||||
if (modelFlags.x0_blendMode == 2) {
|
||||
// Add KColor
|
||||
colorPass = {GX::CC_ZERO, GX::CC_ONE, GX::CC_CPREV, GX::CC_KONST};
|
||||
tevColor = 0x0007018F; // TEVCOLORARG_ZERO, TEVCOLORARG_ONE, TEVCOLORARG_CPREV, TEVCOLORARG_KONST
|
||||
CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_ONE, GX::CC_CPREV, GX::CC_KONST); // Add KColor
|
||||
} else {
|
||||
CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_KONST, GX::CC_CPREV, GX::CC_ZERO); // Mul KColor
|
||||
}
|
||||
aurora::gfx::update_tev_stage(static_cast<ERglTevStage>(finalTevCount), colorPass, alphaPass, {}, {});
|
||||
// GXSetTevColorIn(finalTevCount)
|
||||
// GXSetTevAlphaIn(finalTevCount)
|
||||
// SetStandardTevColorAlphaOp(finalTevCount);
|
||||
CGX::SetStandardTevColorAlphaOp(stage);
|
||||
|
||||
finalCCFlags = 0x100; // Just clamp, output prev reg
|
||||
finalACFlags = 0x100;
|
||||
// GXSetTevDirect(finalTevCount);
|
||||
// GXSetTevOrder(finalTevCount, 255, 255, 255);
|
||||
aurora::gfx::set_tev_k_color(static_cast<GX::TevKColorID>(finalKColorCount), modelFlags.x4_color);
|
||||
// GXSetTevKColor(finalKColorCount, modelFlags.x4_color);
|
||||
aurora::gfx::set_tev_k_color_sel(static_cast<GX::TevStageID>(finalTevCount),
|
||||
static_cast<GX::TevKColorSel>(finalKColorCount + GX::TEV_KCSEL_K0));
|
||||
// GXSetTevKColorSel(finalTevCount, finalKColorCount+12);
|
||||
aurora::gfx::set_tev_k_alpha_sel(static_cast<GX::TevStageID>(finalTevCount),
|
||||
static_cast<GX::TevKAlphaSel>(finalKColorCount + GX::TEV_KASEL_K0_A));
|
||||
// GXSetTevKAlphaSel(finalTevCount, finalKColorCount+28);
|
||||
|
||||
CGX::SetTevDirect(stage);
|
||||
CGX::SetTevOrder(stage, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL);
|
||||
CGX::SetTevKColor(static_cast<GX::TevKColorID>(finalKColorCount), modelFlags.x4_color);
|
||||
CGX::SetTevKColorSel(stage, static_cast<GX::TevKColorSel>(finalKColorCount + GX::TEV_KCSEL_K0));
|
||||
CGX::SetTevKAlphaSel(stage, static_cast<GX::TevKAlphaSel>(finalKColorCount + GX::TEV_KASEL_K0_A));
|
||||
|
||||
finalTevCount += 1;
|
||||
finalKColorCount += 1;
|
||||
}
|
||||
|
@ -483,16 +448,20 @@ void CCubeMaterial::HandleTransparency(u32& finalTevCount, u32& finalKColorCount
|
|||
u32 CCubeMaterial::HandleReflection(bool usesTevReg2, u32 indTexSlot, u32 r5, u32 finalTevCount, u32 texCount,
|
||||
u32 tcgCount, u32 finalKColorCount, u32& finalCCFlags, u32& finalACFlags) {
|
||||
u32 out = 0;
|
||||
GX::TevColorArg colorArg = GX::CC_KONST;
|
||||
if (usesTevReg2) {
|
||||
// GX_CC_C2
|
||||
colorArg = GX::CC_C2;
|
||||
const auto stage = static_cast<GX::TevStageID>(finalTevCount);
|
||||
CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_C2, GX::CC_KONST, GX::CC_ZERO);
|
||||
CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_A2);
|
||||
CGX::SetTevColorOp(stage, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVREG2);
|
||||
CGX::SetTevAlphaOp(stage, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVREG2);
|
||||
CGX::SetTevOrder(stage, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_ZERO);
|
||||
out = 1;
|
||||
} else {
|
||||
// GX_CC_KONST
|
||||
}
|
||||
aurora::gfx::set_tev_k_color(static_cast<GX::TevKColorID>(finalKColorCount),
|
||||
zeus::CColor{sReflectionAlpha, sReflectionAlpha});
|
||||
aurora::gfx::set_tev_k_color_sel(static_cast<GX::TevStageID>(finalTevCount),
|
||||
static_cast<GX::TevKColorSel>(GX::TEV_KCSEL_K0 + finalKColorCount));
|
||||
CGX::SetTevKColor(static_cast<GX::TevKColorID>(finalKColorCount), zeus::CColor{sReflectionAlpha, sReflectionAlpha});
|
||||
CGX::SetTevKColorSel(static_cast<GX::TevStageID>(finalTevCount),
|
||||
static_cast<GX::TevKColorSel>(GX::TEV_KCSEL_K0 + finalKColorCount));
|
||||
|
||||
const auto stage = static_cast<GX::TevStageID>(finalTevCount + out);
|
||||
// tex = g_Renderer->GetRealReflection
|
||||
|
@ -505,11 +474,16 @@ u32 CCubeMaterial::HandleReflection(bool usesTevReg2, u32 indTexSlot, u32 r5, u3
|
|||
|
||||
// aurora::gfx::set_tev_order(stage, ...)
|
||||
|
||||
return out + 1;
|
||||
return out; //+ 1;
|
||||
}
|
||||
|
||||
void CCubeMaterial::DoPassthru(u32 finalTevCount) {
|
||||
aurora::gfx::disable_tev_stage(static_cast<ERglTevStage>(finalTevCount));
|
||||
const auto stage = static_cast<GX::TevStageID>(finalTevCount);
|
||||
CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_CPREV);
|
||||
CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV);
|
||||
CGX::SetTevOrder(stage, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL);
|
||||
CGX::SetTevDirect(stage);
|
||||
CGX::SetStandardTevColorAlphaOp(stage);
|
||||
}
|
||||
|
||||
void CCubeMaterial::DoModelShadow(u32 texCount, u32 tcgCount) {
|
||||
|
@ -523,8 +497,8 @@ void CCubeMaterial::EnsureTevsDirect() {
|
|||
return;
|
||||
}
|
||||
|
||||
// CGX::SetNumIndStages(0);
|
||||
// CGX::SetTevDirect(sCurrentTevStage);
|
||||
CGX::SetNumIndStages(0);
|
||||
CGX::SetTevDirect(sCurrentTevStage);
|
||||
sCurrentTevStage = GX::NULL_STAGE;
|
||||
}
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -5,22 +5,20 @@
|
|||
#include "Graphics/CCubeSurface.hpp"
|
||||
#include "Graphics/CGraphics.hpp"
|
||||
#include "Graphics/CModel.hpp"
|
||||
|
||||
#include <aurora/model.hpp>
|
||||
#include "Graphics/CGX.hpp"
|
||||
|
||||
namespace metaforce {
|
||||
bool CCubeModel::sRenderModelBlack = false;
|
||||
bool CCubeModel::sRenderModelShadow = false;
|
||||
bool CCubeModel::sUsingPackedLightmaps = false;
|
||||
const CTexture* CCubeModel::sShadowTexture = nullptr;
|
||||
zeus::CTransform CCubeModel::sTextureProjectionTransform;
|
||||
GX::LightMask CCubeModel::sChannel0DisableLightMask;
|
||||
GX::LightMask CCubeModel::sChannel1EnableLightMask;
|
||||
|
||||
static bool sDrawingOccluders = false;
|
||||
static bool sDrawingWireframe = false;
|
||||
|
||||
static zeus::CTransform sTextureProjectionTransform;
|
||||
static u8 sChannel0DisableLightMask = 0;
|
||||
static u8 sChannel1EnableLightMask = 0;
|
||||
|
||||
static zeus::CVector3f sPlayerPosition;
|
||||
|
||||
CCubeModel::CCubeModel(std::vector<CCubeSurface>* surfaces, std::vector<TCachedToken<CTexture>>* textures,
|
||||
|
@ -159,8 +157,8 @@ void CCubeModel::DrawFlat(TConstVectorRef positions, TConstVectorRef normals, ES
|
|||
const auto* surface = x38_firstUnsortedSurf;
|
||||
while (surface != nullptr) {
|
||||
const auto mat = GetMaterialByIndex(surface->GetMaterialIndex());
|
||||
aurora::gfx::model::set_vtx_desc_compressed(mat.GetVertexDesc());
|
||||
aurora::gfx::model::queue_surface(surface->GetDisplayList(), surface->GetDisplayListSize());
|
||||
CGX::SetVtxDescv_Compressed(mat.GetVertexDesc());
|
||||
CGX::CallDisplayList(surface->GetDisplayList(), surface->GetDisplayListSize());
|
||||
surface = surface->GetNextSurface();
|
||||
}
|
||||
}
|
||||
|
@ -168,19 +166,23 @@ void CCubeModel::DrawFlat(TConstVectorRef positions, TConstVectorRef normals, ES
|
|||
const auto* surface = x3c_firstSortedSurf;
|
||||
while (surface != nullptr) {
|
||||
const auto mat = GetMaterialByIndex(surface->GetMaterialIndex());
|
||||
aurora::gfx::model::set_vtx_desc_compressed(mat.GetVertexDesc());
|
||||
aurora::gfx::model::queue_surface(surface->GetDisplayList(), surface->GetDisplayListSize());
|
||||
CGX::SetVtxDescv_Compressed(mat.GetVertexDesc());
|
||||
CGX::CallDisplayList(surface->GetDisplayList(), surface->GetDisplayListSize());
|
||||
surface = surface->GetNextSurface();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCubeModel::DrawNormal(TConstVectorRef positions, TConstVectorRef normals, ESurfaceSelection surfaces) {
|
||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true);
|
||||
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassZero);
|
||||
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
||||
// TODO update fog
|
||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::Zero, ERglBlendFactor::One, ERglLogicOp::Clear);
|
||||
CGX::SetNumIndStages(0);
|
||||
CGX::SetNumTevStages(1);
|
||||
CGX::SetNumTexGens(1);
|
||||
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);
|
||||
CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO);
|
||||
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0);
|
||||
CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ZERO, GX::BL_ONE, GX::LO_CLEAR);
|
||||
DrawFlat(positions, normals, surfaces);
|
||||
}
|
||||
|
||||
|
@ -210,7 +212,7 @@ void CCubeModel::DrawSurface(const CCubeSurface& surface, const CModelFlags& fla
|
|||
auto mat = GetMaterialByIndex(surface.GetMaterialIndex());
|
||||
if (!mat.GetFlags().IsSet(CCubeMaterialFlagBits::fShadowOccluderMesh) || sDrawingOccluders) {
|
||||
mat.SetCurrent(flags, surface, *this);
|
||||
aurora::gfx::model::queue_surface(surface.GetDisplayList(), surface.GetDisplayListSize());
|
||||
CGX::CallDisplayList(surface.GetDisplayList(), surface.GetDisplayListSize());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,8 +247,8 @@ void CCubeModel::DrawSurfaceWireframe(const CCubeSurface& surface) {
|
|||
// TODO convert vertices to line strips and draw
|
||||
}
|
||||
|
||||
void CCubeModel::EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransform& textureProjXf, u8 chan0DisableMask,
|
||||
u8 chan1EnableLightMask) {
|
||||
void CCubeModel::EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransform& textureProjXf,
|
||||
GX::LightMask chan0DisableMask, GX::LightMask chan1EnableLightMask) {
|
||||
sRenderModelShadow = true;
|
||||
sShadowTexture = &shadowTex;
|
||||
sTextureProjectionTransform = textureProjXf;
|
||||
|
@ -257,8 +259,8 @@ void CCubeModel::EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransf
|
|||
void CCubeModel::DisableShadowMaps() { sRenderModelShadow = false; }
|
||||
|
||||
void CCubeModel::SetArraysCurrent() {
|
||||
aurora::gfx::model::set_vertex_buffer(x0_modelInstance.GetVertexPointer());
|
||||
aurora::gfx::model::set_normal_buffer(x0_modelInstance.GetNormalPointer());
|
||||
CGX::SetArray(GX::VA_POS, x0_modelInstance.GetVertexPointer());
|
||||
CGX::SetArray(GX::VA_NRM, x0_modelInstance.GetNormalPointer());
|
||||
SetStaticArraysCurrent();
|
||||
}
|
||||
|
||||
|
@ -278,8 +280,8 @@ void CCubeModel::SetRenderModelBlack(bool v) {
|
|||
}
|
||||
|
||||
void CCubeModel::SetSkinningArraysCurrent(TConstVectorRef positions, TConstVectorRef normals) {
|
||||
aurora::gfx::model::set_vertex_buffer(positions);
|
||||
aurora::gfx::model::set_normal_buffer(normals);
|
||||
CGX::SetArray(GX::VA_POS, positions);
|
||||
CGX::SetArray(GX::VA_NRM, normals);
|
||||
// colors unused
|
||||
SetStaticArraysCurrent();
|
||||
}
|
||||
|
@ -292,20 +294,21 @@ void CCubeModel::SetStaticArraysCurrent() {
|
|||
sUsingPackedLightmaps = false;
|
||||
}
|
||||
if (sUsingPackedLightmaps) {
|
||||
aurora::gfx::model::set_tex0_tc_buffer(packedTexCoords);
|
||||
CGX::SetArray(GX::VA_TEX0, packedTexCoords);
|
||||
} else {
|
||||
aurora::gfx::model::set_tex0_tc_buffer(texCoords);
|
||||
CGX::SetArray(GX::VA_TEX0, texCoords);
|
||||
}
|
||||
aurora::gfx::model::set_tc_buffer(texCoords);
|
||||
// TexCoord1 is currently used for all remaining
|
||||
CGX::SetArray(GX::VA_TEX1, texCoords);
|
||||
CCubeMaterial::KillCachedViewDepState();
|
||||
}
|
||||
|
||||
void CCubeModel::SetUsingPackedLightmaps(bool v) {
|
||||
sUsingPackedLightmaps = v;
|
||||
if (v) {
|
||||
aurora::gfx::model::set_tex0_tc_buffer(x0_modelInstance.GetPackedTCPointer());
|
||||
CGX::SetArray(GX::VA_TEX0, x0_modelInstance.GetPackedTCPointer());
|
||||
} else {
|
||||
aurora::gfx::model::set_tex0_tc_buffer(x0_modelInstance.GetTCPointer());
|
||||
CGX::SetArray(GX::VA_TEX0, x0_modelInstance.GetTCPointer());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ using TConstVectorRef = const std::vector<zeus::CVector3f>*;
|
|||
|
||||
class CCubeModel {
|
||||
friend class CModel;
|
||||
friend class CCubeMaterial;
|
||||
|
||||
private:
|
||||
class ModelInstance {
|
||||
|
@ -110,8 +111,8 @@ public:
|
|||
[[nodiscard]] TConstVectorRef GetNormals() const { return x0_modelInstance.GetNormalPointer(); }
|
||||
[[nodiscard]] TCachedToken<CTexture>& GetTexture(u32 idx) const { return x1c_textures->at(idx); }
|
||||
|
||||
static void EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransform& textureProjXf, u8 chan0DisableMask,
|
||||
u8 chan1EnableLightMask);
|
||||
static void EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransform& textureProjXf,
|
||||
GX::LightMask chan0DisableMask, GX::LightMask chan1EnableLightMask);
|
||||
static void DisableShadowMaps();
|
||||
static void MakeTexturesFromMats(const u8* ptr, std::vector<TCachedToken<CTexture>>& texture, IObjectStore* store,
|
||||
bool b1);
|
||||
|
@ -120,11 +121,6 @@ public:
|
|||
static void SetNewPlayerPositionAndTime(const zeus::CVector3f& pos, const CStopwatch& time);
|
||||
static void SetRenderModelBlack(bool v);
|
||||
|
||||
static bool sRenderModelBlack;
|
||||
static bool sUsingPackedLightmaps;
|
||||
static bool sRenderModelShadow;
|
||||
static const CTexture* sShadowTexture;
|
||||
|
||||
private:
|
||||
void Draw(TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags);
|
||||
void DrawAlphaSurfaces(const CModelFlags& flags);
|
||||
|
@ -132,5 +128,13 @@ private:
|
|||
void DrawSurfaces(const CModelFlags& flags);
|
||||
void SetSkinningArraysCurrent(TConstVectorRef positions, TConstVectorRef normals);
|
||||
void SetStaticArraysCurrent();
|
||||
|
||||
static bool sRenderModelBlack;
|
||||
static bool sUsingPackedLightmaps;
|
||||
static bool sRenderModelShadow;
|
||||
static const CTexture* sShadowTexture;
|
||||
static zeus::CTransform sTextureProjectionTransform;
|
||||
static GX::LightMask sChannel0DisableLightMask;
|
||||
static GX::LightMask sChannel1EnableLightMask;
|
||||
};
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
#include "Runtime/Graphics/CCubeRenderer.hpp"
|
||||
|
||||
#include "Runtime/GameGlobalObjects.hpp"
|
||||
#include "Runtime/Graphics/CDrawable.hpp"
|
||||
#include "Runtime/Graphics/CMetroidModelInstance.hpp"
|
||||
#include "Runtime/Graphics/CDrawablePlaneObject.hpp"
|
||||
#include "Runtime/Graphics/CLight.hpp"
|
||||
#include "Runtime/Graphics/CModel.hpp"
|
||||
#include "Runtime/Particle/CParticleGen.hpp"
|
||||
#include "Runtime/Graphics/CCubeMaterial.hpp"
|
||||
#include "Runtime/Graphics/CCubeModel.hpp"
|
||||
#include "Runtime/Graphics/CCubeSurface.hpp"
|
||||
#include "Runtime/Graphics/CCubeMaterial.hpp"
|
||||
#include "Runtime/Graphics/CDrawable.hpp"
|
||||
#include "Runtime/Graphics/CDrawablePlaneObject.hpp"
|
||||
#include "Runtime/Graphics/CGX.hpp"
|
||||
#include "Runtime/Graphics/CLight.hpp"
|
||||
#include "Runtime/Graphics/CMetroidModelInstance.hpp"
|
||||
#include "Runtime/Graphics/CModel.hpp"
|
||||
#include "Runtime/Particle/CParticleGen.hpp"
|
||||
|
||||
namespace metaforce {
|
||||
static logvisor::Module Log("CCubeRenderer");
|
||||
|
@ -197,15 +198,35 @@ CCubeRenderer::CCubeRenderer(IObjectStore& store, IFactory& resFac) : x8_factory
|
|||
|
||||
CCubeRenderer::~CCubeRenderer() { g_Renderer = nullptr; }
|
||||
|
||||
void CCubeRenderer::GenerateReflectionTex() {}
|
||||
void CCubeRenderer::GenerateFogVolumeRampTex() {}
|
||||
void CCubeRenderer::GenerateSphereRampTex() {}
|
||||
void CCubeRenderer::LoadThermoPalette() {}
|
||||
void CCubeRenderer::ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, const CTexture& maskTex,
|
||||
const CTexture& indTex, const zeus::CColor& modColor,
|
||||
float scale, float offX, float offY) {}
|
||||
void CCubeRenderer::ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor, const CTexture& maskTex) {}
|
||||
void CCubeRenderer::DoPhazonSuitIndirectAlphaBlur(float blurRadius, float f2, const TLockedToken<CTexture>& indTex) {}
|
||||
void CCubeRenderer::GenerateReflectionTex() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::GenerateFogVolumeRampTex() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::GenerateSphereRampTex() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::LoadThermoPalette() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, CTexture& maskTex,
|
||||
CTexture& indTex, const zeus::CColor& modColor, float scale,
|
||||
float offX, float offY) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor, CTexture& maskTex) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::DoPhazonSuitIndirectAlphaBlur(float blurRadius, float f2, const TLockedToken<CTexture>& indTex) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::AddWorldSurfaces(CCubeModel& model) {
|
||||
for (auto* it = model.GetFirstSortedSurface(); it != nullptr; it = it->GetNextSurface()) {
|
||||
|
@ -216,6 +237,7 @@ void CCubeRenderer::AddWorldSurfaces(CCubeModel& model) {
|
|||
Buckets::Insert(pos, bounds, EDrawableType::WorldSurface, it, xb0_viewPlane, static_cast<u16>(blend == 0x50004));
|
||||
}
|
||||
}
|
||||
|
||||
void CCubeRenderer::AddStaticGeometry(const std::vector<CMetroidModelInstance>* geometry,
|
||||
const CAreaRenderOctTree* octTree, s32 areaIdx) {
|
||||
auto search = FindStaticGeometry(geometry);
|
||||
|
@ -448,7 +470,11 @@ void CCubeRenderer::RenderBucketItems(const CAreaListItem* item) {
|
|||
}
|
||||
}
|
||||
}
|
||||
void CCubeRenderer::PostRenderFogs() {}
|
||||
|
||||
void CCubeRenderer::PostRenderFogs() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::SetModelMatrix(const zeus::CTransform& xf) { CGraphics::SetModelMatrix(xf); }
|
||||
|
||||
void CCubeRenderer::HandleUnsortedModel(CAreaListItem* areaItem, CCubeModel& model, const CModelFlags& flags) {
|
||||
|
@ -473,7 +499,10 @@ void CCubeRenderer::HandleUnsortedModelWireframe(CAreaListItem* areaItem, CCubeM
|
|||
}
|
||||
}
|
||||
|
||||
void CCubeRenderer::ActivateLightsForModel(const CAreaListItem* areaItem, CCubeModel& model) {}
|
||||
void CCubeRenderer::ActivateLightsForModel(const CAreaListItem* areaItem, CCubeModel& model) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::AddParticleGen(CParticleGen& gen) {
|
||||
auto bounds = gen.GetBounds();
|
||||
|
||||
|
@ -575,8 +604,8 @@ void CCubeRenderer::BeginScene() {
|
|||
}
|
||||
|
||||
// GXSetPixelFmt(x318_26_requestRGBA6, GX_ZC_LINEAR);
|
||||
aurora::gfx::set_alpha_update(true);
|
||||
aurora::gfx::set_dst_alpha(true, 0.f);
|
||||
GXSetAlphaUpdate(true);
|
||||
GXSetDstAlpha(true, 0.f);
|
||||
CGraphics::BeginScene();
|
||||
}
|
||||
|
||||
|
@ -607,64 +636,164 @@ void CCubeRenderer::BeginPrimitive(IRenderer::EPrimitiveType type, s32 nverts) {
|
|||
x18_primVertCount = nverts;
|
||||
CGraphics::StreamBegin(GX::Primitive(type));
|
||||
}
|
||||
|
||||
void CCubeRenderer::BeginLines(s32 nverts) { BeginPrimitive(EPrimitiveType::Lines, nverts); }
|
||||
|
||||
void CCubeRenderer::BeginLineStrip(s32 nverts) { BeginPrimitive(EPrimitiveType::LineStrip, nverts); }
|
||||
|
||||
void CCubeRenderer::BeginTriangles(s32 nverts) { BeginPrimitive(EPrimitiveType::Triangles, nverts); }
|
||||
|
||||
void CCubeRenderer::BeginTriangleStrip(s32 nverts) { BeginPrimitive(EPrimitiveType::TriangleStrip, nverts); }
|
||||
|
||||
void CCubeRenderer::BeginTriangleFan(s32 nverts) { BeginPrimitive(EPrimitiveType::TriangleFan, nverts); }
|
||||
|
||||
void CCubeRenderer::PrimVertex(const zeus::CVector3f& vertex) {
|
||||
--x18_primVertCount;
|
||||
CGraphics::StreamColor(x2e0_primColor);
|
||||
CGraphics::StreamNormal(x2e4_primNormal);
|
||||
CGraphics::StreamVertex(vertex);
|
||||
}
|
||||
|
||||
void CCubeRenderer::PrimNormal(const zeus::CVector3f& normal) { x2e4_primNormal = normal; }
|
||||
|
||||
void CCubeRenderer::PrimColor(float r, float g, float b, float a) { PrimColor({r, g, b, a}); }
|
||||
|
||||
void CCubeRenderer::PrimColor(const zeus::CColor& color) { x2e0_primColor = color; }
|
||||
|
||||
void CCubeRenderer::EndPrimitive() {
|
||||
while (x18_primVertCount > 0) {
|
||||
PrimVertex(zeus::skZero3f);
|
||||
}
|
||||
CGraphics::StreamEnd();
|
||||
}
|
||||
|
||||
void CCubeRenderer::SetAmbientColor(const zeus::CColor& color) { CGraphics::SetAmbientColor(color); }
|
||||
|
||||
void CCubeRenderer::DrawString(const char* string, s32 x, s32 y) { x10_font.DrawString(string, x, y, zeus::skWhite); }
|
||||
|
||||
u32 CCubeRenderer::GetFPS() { return CGraphics::GetFPS(); }
|
||||
void CCubeRenderer::CacheReflection(IRenderer::TReflectionCallback cb, void* ctx, bool clearAfter) {}
|
||||
void CCubeRenderer::DrawSpaceWarp(const zeus::CVector3f& pt, float strength) {}
|
||||
void CCubeRenderer::DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
|
||||
TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) {}
|
||||
void CCubeRenderer::DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color,
|
||||
TConstVectorRef positions, TConstVectorRef normals) {}
|
||||
void CCubeRenderer::DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) {}
|
||||
void CCubeRenderer::SetWireframeFlags(s32 flags) {}
|
||||
void CCubeRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) {}
|
||||
void CCubeRenderer::RenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb,
|
||||
const TLockedToken<CModel>* model, const CSkinnedModel* sModel) {}
|
||||
void CCubeRenderer::SetThermal(bool thermal, float level, const zeus::CColor& color) {}
|
||||
void CCubeRenderer::SetThermalColdScale(float scale) {}
|
||||
void CCubeRenderer::DoThermalBlendCold() {}
|
||||
void CCubeRenderer::DoThermalBlendHot() {}
|
||||
u32 CCubeRenderer::GetStaticWorldDataSize() { return 0; }
|
||||
|
||||
void CCubeRenderer::SetGXRegister1Color(const zeus::CColor& color) {
|
||||
aurora::gfx::set_tev_reg_color(GX::TevRegID::TEVREG1, color);
|
||||
void CCubeRenderer::CacheReflection(IRenderer::TReflectionCallback cb, void* ctx, bool clearAfter) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::DrawSpaceWarp(const zeus::CVector3f& pt, float strength) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::DrawThermalModel(CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
|
||||
TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) {
|
||||
model.UpdateLastFrame();
|
||||
// TODO
|
||||
// DoThermalModelDraw(model.GetInstance(), multCol, addCol, positions, normals, flags);
|
||||
}
|
||||
|
||||
void CCubeRenderer::DrawModelDisintegrate(CModel& model, CTexture& tex, const zeus::CColor& color,
|
||||
TConstVectorRef positions, TConstVectorRef normals, float t) {
|
||||
tex.Load(GX::TEXMAP0, EClampMode::Clamp);
|
||||
CGX::SetNumIndStages(0);
|
||||
CGX::SetNumTevStages(2);
|
||||
CGX::SetNumTexGens(2);
|
||||
CGX::SetNumChans(0);
|
||||
CGX::SetBlendMode(GX::BM_BLEND, GX::BL_SRCALPHA, GX::BL_INVSRCALPHA, GX::LO_CLEAR);
|
||||
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0);
|
||||
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE1);
|
||||
CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_TEXC);
|
||||
CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_TEXA);
|
||||
CGX::SetTevColorIn(GX::TEVSTAGE1, GX::CC_ZERO, GX::CC_TEXC, GX::CC_CPREV, GX::CC_KONST);
|
||||
CGX::SetTevAlphaIn(GX::TEVSTAGE1, GX::CA_ZERO, GX::CA_TEXA, GX::CA_APREV, GX::CA_ZERO);
|
||||
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL);
|
||||
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP0, GX::COLOR_NULL);
|
||||
CGX::SetTevKColorSel(GX::TEVSTAGE1, GX::TEV_KCSEL_K0);
|
||||
CGX::SetTevKColor(GX::KCOLOR0, color);
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::DrawModelFlat(CModel& model, const CModelFlags& flags, bool unsortedOnly, TConstVectorRef positions,
|
||||
TConstVectorRef normals) {
|
||||
if (flags.x0_blendMode >= 7) {
|
||||
CGX::SetBlendMode(GX::BM_BLEND, GX::BL_SRCALPHA, GX::BL_ONE, GX::LO_CLEAR);
|
||||
} else if (flags.x0_blendMode >= 5) {
|
||||
CGX::SetBlendMode(GX::BM_BLEND, GX::BL_SRCALPHA, GX::BL_INVSRCALPHA, GX::LO_CLEAR);
|
||||
} else {
|
||||
CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR);
|
||||
}
|
||||
CGX::SetZMode(true, flags.x2_flags & CModelFlagBits::DepthTest ? GX::LEQUAL : GX::ALWAYS,
|
||||
flags.x2_flags.IsSet(CModelFlagBits::DepthUpdate));
|
||||
CGX::SetNumTevStages(1);
|
||||
CGX::SetNumTexGens(1);
|
||||
CGX::SetNumChans(0);
|
||||
CGX::SetNumIndStages(0);
|
||||
CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0);
|
||||
CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_KONST);
|
||||
CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_KONST);
|
||||
CGX::SetTevKColor(GX::KCOLOR0, flags.x4_color);
|
||||
CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0);
|
||||
CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A);
|
||||
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL);
|
||||
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0);
|
||||
CGX::SetTevDirect(GX::TEVSTAGE0);
|
||||
CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_POS, GX::IDENTITY, false, GX::PTIDENTITY);
|
||||
model.UpdateLastFrame();
|
||||
model.GetInstance().DrawFlat(positions, normals, unsortedOnly ? ESurfaceSelection::Unsorted : ESurfaceSelection::All);
|
||||
}
|
||||
|
||||
void CCubeRenderer::SetWireframeFlags(s32 flags) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::RenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb,
|
||||
const TLockedToken<CModel>* model, const CSkinnedModel* sModel) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::SetThermal(bool thermal, float level, const zeus::CColor& color) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::SetThermalColdScale(float scale) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::DoThermalBlendCold() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::DoThermalBlendHot() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
u32 CCubeRenderer::GetStaticWorldDataSize() {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CCubeRenderer::SetGXRegister1Color(const zeus::CColor& color) { GXSetTevColor(GX::TevRegID::TEVREG1, color); }
|
||||
|
||||
void CCubeRenderer::SetWorldLightFadeLevel(float level) { x2fc_tevReg1Color = zeus::CColor(level, level, level, 1.f); }
|
||||
|
||||
void CCubeRenderer::PrepareDynamicLights(const std::vector<CLight>& lights) {}
|
||||
void CCubeRenderer::AllocatePhazonSuitMaskTexture() {}
|
||||
void CCubeRenderer::PrepareDynamicLights(const std::vector<CLight>& lights) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::AllocatePhazonSuitMaskTexture() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CCubeRenderer::DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod,
|
||||
const TLockedToken<CTexture>& indTex, const zeus::CColor& indirectMod,
|
||||
float blurRadius, float scale, float offX, float offY) {
|
||||
// TODO
|
||||
aurora::gfx::set_dst_alpha(false, 0.f);
|
||||
GXSetDstAlpha(false, 0.f);
|
||||
}
|
||||
|
||||
void CCubeRenderer::DrawXRayOutline(const zeus::CAABox& aabb) {}
|
||||
void CCubeRenderer::DrawXRayOutline(const zeus::CAABox& aabb) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
std::list<CCubeRenderer::CAreaListItem>::iterator
|
||||
CCubeRenderer::FindStaticGeometry(const std::vector<CMetroidModelInstance>* geometry) {
|
||||
|
@ -687,9 +816,10 @@ void CCubeRenderer::SetupCGraphicsState() {
|
|||
CGraphics::SetModelMatrix({});
|
||||
CTevCombiners::ResetStates();
|
||||
CGraphics::SetAmbientColor({0.4f});
|
||||
// CGX::SetChanMatColor(EChannelId::Channel0, GX::Color{0xFFFFFFFF});
|
||||
CGX::SetChanMatColor(CGX::EChannelId::Channel0, zeus::skWhite);
|
||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true);
|
||||
// CGX::SetChanCtrl(EChannelId::Channel1, false, GX::SRC_REG, GX::LIGHT_NULL, GX::DF_NONE, GX::AF_NONE);
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel1, false, GX::SRC_REG, GX::SRC_REG, GX::LIGHT_NULL, GX::DF_NONE,
|
||||
GX::AF_NONE);
|
||||
CCubeMaterial::EnsureTevsDirect();
|
||||
}
|
||||
|
||||
|
@ -699,6 +829,6 @@ void CCubeRenderer::SetupRendererStates(bool depthWrite) {
|
|||
CGraphics::SetAmbientColor(zeus::skBlack);
|
||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, depthWrite);
|
||||
CCubeMaterial::ResetCachedMaterials();
|
||||
aurora::gfx::set_tev_reg_color(GX::TEVREG1, x2fc_tevReg1Color);
|
||||
GXSetTevColor(GX::TEVREG1, x2fc_tevReg1Color);
|
||||
}
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -97,10 +97,9 @@ private:
|
|||
void GenerateSphereRampTex();
|
||||
void LoadThermoPalette();
|
||||
|
||||
void ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, const CTexture& maskTex,
|
||||
const CTexture& indTex, const zeus::CColor& modColor, float scale, float offX,
|
||||
float offY);
|
||||
void ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor, const CTexture& maskTex);
|
||||
void ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, CTexture& maskTex, CTexture& indTex,
|
||||
const zeus::CColor& modColor, float scale, float offX, float offY);
|
||||
void ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor, CTexture& maskTex);
|
||||
void DoPhazonSuitIndirectAlphaBlur(float blurRadius, float f2, const TLockedToken<CTexture>& indTex);
|
||||
|
||||
public:
|
||||
|
@ -179,11 +178,12 @@ public:
|
|||
u32 GetFPS() override;
|
||||
void CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) override;
|
||||
void DrawSpaceWarp(const zeus::CVector3f& pt, float strength) override;
|
||||
void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
|
||||
void DrawThermalModel(CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
|
||||
TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) override;
|
||||
void DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color,
|
||||
TConstVectorRef positions, TConstVectorRef normals) override;
|
||||
void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) override;
|
||||
void DrawModelDisintegrate(CModel& model, CTexture& tex, const zeus::CColor& color, TConstVectorRef positions,
|
||||
TConstVectorRef normals, float t) override;
|
||||
void DrawModelFlat(CModel& model, const CModelFlags& flags, bool unsortedOnly, TConstVectorRef positions,
|
||||
TConstVectorRef normals) override;
|
||||
void SetWireframeFlags(s32 flags) override;
|
||||
void SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) override;
|
||||
void RenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, const TLockedToken<CModel>* model,
|
||||
|
@ -217,6 +217,9 @@ public:
|
|||
|
||||
void ActivateLightsForModel(const CAreaListItem* areaItem, CCubeModel& model);
|
||||
|
||||
void DoThermalModelDraw(CCubeModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
|
||||
TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags);
|
||||
|
||||
// Getters
|
||||
[[nodiscard]] bool IsInAreaDraw() const { return x318_30_inAreaDraw; }
|
||||
[[nodiscard]] bool IsReflectionDirty() const { return x318_24_refectionDirty; }
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#include "CGX.hpp"
|
||||
|
||||
#include "Graphics/CTexture.hpp"
|
||||
|
||||
namespace metaforce::CGX {
|
||||
SGXState sGXState;
|
||||
|
||||
void ResetGXStates() noexcept {
|
||||
sGXState.x48_descList = nullptr;
|
||||
// GXClearVtxDesc();
|
||||
sGXState.x0_arrayPtrs.fill(nullptr);
|
||||
for (GX::TexMapID id = GX::TEXMAP0; id < GX::MAX_TEXMAP; id = static_cast<GX::TexMapID>(id + 1)) {
|
||||
CTexture::InvalidateTexMap(id);
|
||||
}
|
||||
for (GX::TevKColorID id = GX::KCOLOR0; const auto& item : sGXState.x58_kColors) {
|
||||
GXSetTevKColor(id, item);
|
||||
id = static_cast<GX::TevKColorID>(id + 1);
|
||||
}
|
||||
// GXSetTevSwapModeTable
|
||||
SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0);
|
||||
// GXSetCurrentMtx(0);
|
||||
SetNumIndStages(0);
|
||||
// TODO GXSetIndTexCoordScale
|
||||
for (GX::TevStageID id = GX::TEVSTAGE0; id < GX::MAX_TEVSTAGE; id = static_cast<GX::TevStageID>(id + 1)) {
|
||||
SetTevDirect(id);
|
||||
}
|
||||
// GXSetTexCoordCylWrap
|
||||
// GXSetZTexture
|
||||
}
|
||||
} // namespace metaforce::CGX
|
|
@ -0,0 +1,387 @@
|
|||
#pragma once
|
||||
|
||||
#include "Graphics/GX.hpp"
|
||||
#include "RetroTypes.hpp"
|
||||
|
||||
#include <aurora/model.hpp>
|
||||
#include <zeus/CColor.hpp>
|
||||
|
||||
namespace metaforce::CGX {
|
||||
enum class EChannelId {
|
||||
Channel0, // GX::COLOR0
|
||||
Channel1, // GX::COLOR1
|
||||
};
|
||||
|
||||
struct STevState {
|
||||
u32 x0_colorInArgs = 0;
|
||||
u32 x4_alphaInArgs = 0;
|
||||
u32 x8_colorOps = 0;
|
||||
u32 xc_alphaOps = 0;
|
||||
u32 x10_indFlags = 0;
|
||||
u32 x14_tevOrderFlags = 0;
|
||||
GX::TevKColorSel x18_kColorSel = GX::TEV_KCSEL_1;
|
||||
GX::TevKAlphaSel x19_kAlphaSel = GX::TEV_KASEL_1;
|
||||
};
|
||||
struct STexState {
|
||||
u32 x0_coordGen = 0;
|
||||
};
|
||||
struct SGXState {
|
||||
std::array<void*, 12> x0_arrayPtrs{};
|
||||
std::array<u16, 2> x30_prevChanCtrls{};
|
||||
std::array<u16, 2> x34_chanCtrls{};
|
||||
std::array<GXColor, 2> x38_chanAmbColors;
|
||||
std::array<GXColor, 2> x40_chanMatColors;
|
||||
GX::VtxDescList* x48_descList = nullptr;
|
||||
u8 x4c_dirtyChans = 0;
|
||||
u8 x4d_prevNumChans = 0;
|
||||
u8 x4e_numChans = 0;
|
||||
u8 x4f_numTexGens = 0;
|
||||
u8 x50_numTevStages = 0;
|
||||
u8 x51_numIndStages = 0;
|
||||
u8 x52_zmode = 0;
|
||||
GX::FogType x53_fogType = GX::FOG_NONE;
|
||||
u16 x54_lineWidthAndOffset = 0;
|
||||
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;
|
||||
u32 x248_alphaCompare = 0;
|
||||
float x24c_fogStartZ = 0.f;
|
||||
float x250_fogEndZ = 0.f;
|
||||
float x254_fogNearZ = 0.f;
|
||||
float x258_fogFarZ = 0.f;
|
||||
GXColor x25c_fogColor;
|
||||
};
|
||||
extern SGXState sGXState;
|
||||
|
||||
static inline void update_fog(u32 value) noexcept {
|
||||
if (sGXState.x53_fogType == GX::FOG_NONE || (sGXState.x56_blendMode & 0xE0) == (value & 0xE0)) {
|
||||
return;
|
||||
}
|
||||
if ((value & 0xE0) == 0x20) {
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
|
||||
static inline void FlushState() noexcept {
|
||||
if ((sGXState.x4c_dirtyChans & 1) != 0) {
|
||||
u8 numChans = sGXState.x4e_numChans;
|
||||
GXSetNumChans(numChans);
|
||||
sGXState.x4d_prevNumChans = numChans;
|
||||
}
|
||||
if ((sGXState.x4c_dirtyChans & 2) != 0) {
|
||||
// TODO actually COLOR0
|
||||
auto flags = sGXState.x34_chanCtrls[0];
|
||||
GXSetChanCtrl(GX::COLOR0A0, GXBool(flags & 1), GX::ColorSrc(flags >> 1 & 1), GX::ColorSrc(flags >> 2 & 1),
|
||||
flags >> 3 & 0xFF, GX::DiffuseFn(flags >> 11 & 3), GX::AttnFn(flags >> 13 & 3));
|
||||
sGXState.x30_prevChanCtrls[0] = flags;
|
||||
}
|
||||
if ((sGXState.x4c_dirtyChans & 4) != 0) {
|
||||
// TODO actually COLOR1
|
||||
auto flags = sGXState.x34_chanCtrls[1];
|
||||
GXSetChanCtrl(GX::COLOR1A1, GXBool(flags & 1), GX::ColorSrc(flags >> 1 & 1), GX::ColorSrc(flags >> 2 & 1),
|
||||
flags >> 3 & 0xFF, GX::DiffuseFn(flags >> 11 & 3), GX::AttnFn(flags >> 13 & 3));
|
||||
sGXState.x30_prevChanCtrls[1] = flags;
|
||||
}
|
||||
sGXState.x4c_dirtyChans = 0;
|
||||
}
|
||||
|
||||
static inline void Begin(GX::Primitive primitive, GX::VtxFmt fmt, u16 nverts) noexcept {
|
||||
if (sGXState.x4c_dirtyChans != 0) {
|
||||
FlushState();
|
||||
}
|
||||
// TODO GXBegin(type, fmt, nverts);
|
||||
}
|
||||
|
||||
static inline void CallDisplayList(const void* data, u32 nbytes) noexcept {
|
||||
if (sGXState.x4c_dirtyChans != 0) {
|
||||
FlushState();
|
||||
}
|
||||
GXCallDisplayList(data, nbytes);
|
||||
}
|
||||
|
||||
static inline void End() noexcept {
|
||||
// no-op
|
||||
}
|
||||
|
||||
static inline const GXColor& GetChanAmbColor(EChannelId id) noexcept {
|
||||
const auto idx = std::underlying_type_t<EChannelId>(id);
|
||||
return sGXState.x38_chanAmbColors[idx];
|
||||
}
|
||||
|
||||
void ResetGXStates() noexcept;
|
||||
|
||||
static inline void SetAlphaCompare(GX::Compare comp0, u8 ref0, GX::AlphaOp op, GX::Compare comp1, u8 ref1) noexcept {
|
||||
u32 flags = ref1 << 17 | (comp1 & 7) << 14 | (op & 7) << 11 | ref0 << 3 | (comp0 & 7);
|
||||
if (flags != sGXState.x248_alphaCompare) {
|
||||
sGXState.x248_alphaCompare = flags;
|
||||
GXSetAlphaCompare(comp0, ref0 / 255.f, op, comp1, ref1 / 255.f);
|
||||
// GXSetZCompLoc(comp0 == GX::ALWAYS);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline void SetArray(GX::Attr attr, const std::vector<T>* data) noexcept {
|
||||
if (data != nullptr && sGXState.x0_arrayPtrs[attr - GX::VA_POS] != data) {
|
||||
GXSetArray(attr, data, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetBlendMode(GX::BlendMode mode, GX::BlendFactor srcFac, GX::BlendFactor dstFac,
|
||||
GX::LogicOp op) noexcept {
|
||||
const u16 flags = (op & 0xF) << 8 | (dstFac & 7) << 5 | (srcFac & 7) << 2 | (mode & 3);
|
||||
if (flags != sGXState.x56_blendMode) {
|
||||
update_fog(flags);
|
||||
sGXState.x56_blendMode = flags;
|
||||
GXSetBlendMode(mode, srcFac, dstFac, op);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetChanAmbColor(EChannelId id, const GXColor& color) noexcept {
|
||||
const auto idx = std::underlying_type_t<EChannelId>(id);
|
||||
if (color != sGXState.x38_chanAmbColors[idx]) {
|
||||
sGXState.x38_chanAmbColors[idx] = color;
|
||||
GXSetChanAmbColor(GX::ChannelID(idx + GX::COLOR0A0), color);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetChanCtrl(EChannelId id, GXBool enable, GX::ColorSrc ambSrc, GX::ColorSrc matSrc,
|
||||
GX::LightMask lights, GX::DiffuseFn diffFn, GX::AttnFn attnFn) noexcept {
|
||||
const auto idx = std::underlying_type_t<EChannelId>(id);
|
||||
const u32 flags = (attnFn & 3) << 13 | (diffFn & 3) << 11 | (lights.to_ulong() & 0xFF) << 3 | (matSrc & 1) << 2 |
|
||||
(ambSrc & 1) << 1 | (u8(enable) & 1);
|
||||
sGXState.x34_chanCtrls[idx] = flags;
|
||||
sGXState.x4c_dirtyChans = 7; // TODO
|
||||
}
|
||||
|
||||
// Helper function for common logic
|
||||
static inline void SetChanCtrl(EChannelId id, GX::LightMask lights) noexcept {
|
||||
const bool hasLights = lights.any();
|
||||
SetChanCtrl(id, hasLights, GX::SRC_REG, GX::SRC_REG, lights, hasLights ? GX::DF_CLAMP : GX::DF_NONE,
|
||||
hasLights ? GX::AF_SPOT : GX::AF_NONE);
|
||||
}
|
||||
|
||||
static inline void SetChanMatColor(EChannelId id, const GXColor& color) noexcept {
|
||||
const auto idx = std::underlying_type_t<EChannelId>(id);
|
||||
if (color != sGXState.x40_chanMatColors[idx]) {
|
||||
sGXState.x40_chanMatColors[idx] = color;
|
||||
GXSetChanMatColor(GX::ChannelID(idx + GX::COLOR0A0), color);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetFog(GX::FogType type, float startZ, float endZ, float nearZ, float farZ,
|
||||
const GXColor& color) noexcept {
|
||||
sGXState.x25c_fogColor = color;
|
||||
sGXState.x53_fogType = type;
|
||||
sGXState.x24c_fogStartZ = startZ;
|
||||
sGXState.x250_fogEndZ = endZ;
|
||||
sGXState.x254_fogNearZ = nearZ;
|
||||
sGXState.x258_fogFarZ = farZ;
|
||||
auto fogColor = color;
|
||||
if ((sGXState.x56_blendMode & 0xE0) == 0x20) {
|
||||
fogColor = zeus::skClear;
|
||||
}
|
||||
// TODO
|
||||
// GXSetFog(type, startZ, endZ, nearZ, farZ, fogColor);
|
||||
}
|
||||
|
||||
void SetIndTexMtxSTPointFive(GX::IndTexMtxID id, s8 scaleExp) noexcept;
|
||||
|
||||
void SetLineWidth(u8 width, GX::TexOffset offset) noexcept;
|
||||
|
||||
static inline void SetNumChans(u8 num) noexcept {
|
||||
sGXState.x4c_dirtyChans = 7; // TODO
|
||||
sGXState.x4e_numChans = num;
|
||||
}
|
||||
|
||||
static inline void SetNumIndStages(u8 num) noexcept {
|
||||
auto& state = sGXState.x51_numIndStages;
|
||||
if (num != state) {
|
||||
state = num;
|
||||
GXSetNumIndStages(num);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetNumTevStages(u8 num) noexcept {
|
||||
auto& state = sGXState.x50_numTevStages;
|
||||
if (num != state) {
|
||||
state = num;
|
||||
GXSetNumTevStages(num);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetNumTexGens(u8 num) noexcept {
|
||||
auto& state = sGXState.x4f_numTexGens;
|
||||
if (num != state) {
|
||||
state = num;
|
||||
GXSetNumTexGens(num);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetStandardTevColorAlphaOp(GX::TevStageID stageId) noexcept {
|
||||
auto& state = sGXState.x68_tevStates[stageId];
|
||||
if (state.x8_colorOps != 0x100 || state.xc_alphaOps != 0x100) {
|
||||
state.x8_colorOps = 0x100;
|
||||
state.xc_alphaOps = 0x100;
|
||||
GXSetTevColorOp(stageId, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV);
|
||||
GXSetTevAlphaOp(stageId, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTevAlphaIn(GX::TevStageID stageId, GX::TevAlphaArg a, GX::TevAlphaArg b, GX::TevAlphaArg c,
|
||||
GX::TevAlphaArg d) noexcept {
|
||||
u32 flags = (d & 31) << 15 | (c & 31) << 10 | (b & 31) << 5 | (a & 31);
|
||||
auto& state = sGXState.x68_tevStates[stageId].x4_alphaInArgs;
|
||||
if (flags != state) {
|
||||
state = flags;
|
||||
GXSetTevAlphaIn(stageId, a, b, c, d);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTevAlphaOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale,
|
||||
GXBool clamp, GX::TevRegID outReg) noexcept {
|
||||
u32 flags = (outReg & 3) << 9 | (u8(clamp) & 1) << 8 | (scale & 3) << 6 | (bias & 3) << 4 | (op & 15);
|
||||
auto& state = sGXState.x68_tevStates[stageId].xc_alphaOps;
|
||||
if (flags != state) {
|
||||
state = flags;
|
||||
GXSetTevAlphaOp(stageId, op, bias, scale, clamp, outReg);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTevAlphaOp_Compressed(GX::TevStageID stageId, u32 ops) noexcept {
|
||||
auto& state = sGXState.x68_tevStates[stageId].xc_alphaOps;
|
||||
if (ops != state) {
|
||||
state = ops;
|
||||
GXSetTevAlphaOp(stageId, GX::TevOp(ops & 31), GX::TevBias(ops >> 4 & 3), GX::TevScale(ops >> 6 & 3),
|
||||
GXBool(ops >> 8 & 1), GX::TevRegID(ops >> 9 & 3));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTevColorIn(GX::TevStageID stageId, GX::TevColorArg a, GX::TevColorArg b, GX::TevColorArg c,
|
||||
GX::TevColorArg d) noexcept {
|
||||
u32 flags = (d & 31) << 15 | (c & 31) << 10 | (b & 31) << 5 | (a & 31);
|
||||
auto& state = sGXState.x68_tevStates[stageId].x0_colorInArgs;
|
||||
if (flags != state) {
|
||||
state = flags;
|
||||
GXSetTevColorIn(stageId, a, b, c, d);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTevColorOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale,
|
||||
GXBool clamp, GX::TevRegID outReg) noexcept {
|
||||
u32 flags = (outReg & 3) << 9 | (u8(clamp) & 1) << 8 | (scale & 3) << 6 | (bias & 3) << 4 | (op & 15);
|
||||
auto& state = sGXState.x68_tevStates[stageId].x8_colorOps;
|
||||
if (flags != state) {
|
||||
state = flags;
|
||||
GXSetTevColorOp(stageId, op, bias, scale, clamp, outReg);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTevColorOp_Compressed(GX::TevStageID stageId, u32 ops) noexcept {
|
||||
auto& state = sGXState.x68_tevStates[stageId].x8_colorOps;
|
||||
if (ops != state) {
|
||||
state = ops;
|
||||
GXSetTevColorOp(stageId, GX::TevOp(ops & 31), GX::TevBias(ops >> 4 & 3), GX::TevScale(ops >> 6 & 3),
|
||||
GXBool(ops >> 8 & 1), GX::TevRegID(ops >> 9 & 3));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTevDirect(GX::TevStageID stageId) noexcept {
|
||||
auto& state = sGXState.x68_tevStates[stageId].x10_indFlags;
|
||||
if (state != 0) {
|
||||
state = 0;
|
||||
// TODO
|
||||
// GXSetTevDirect(stageId);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetStandardDirectTev_Compressed(GX::TevStageID stageId, u32 colorArgs, u32 alphaArgs, u32 colorOps,
|
||||
u32 alphaOps) noexcept {
|
||||
auto& state = sGXState.x68_tevStates[stageId];
|
||||
SetTevDirect(stageId);
|
||||
if (state.x0_colorInArgs != colorArgs) {
|
||||
state.x0_colorInArgs = colorArgs;
|
||||
GXSetTevColorIn(stageId, GX::TevColorArg(colorArgs & 31), GX::TevColorArg(colorArgs >> 5 & 31),
|
||||
GX::TevColorArg(colorArgs >> 10 & 31), GX::TevColorArg(colorArgs >> 15 & 31));
|
||||
}
|
||||
if (state.x4_alphaInArgs != alphaArgs) {
|
||||
state.x4_alphaInArgs = alphaArgs;
|
||||
GXSetTevAlphaIn(stageId, GX::TevAlphaArg(alphaArgs & 31), GX::TevAlphaArg(alphaArgs >> 5 & 31),
|
||||
GX::TevAlphaArg(alphaArgs >> 10 & 31), GX::TevAlphaArg(alphaArgs >> 15 & 31));
|
||||
}
|
||||
if (colorOps != alphaOps || (colorOps & 0x1FF) != 0x100) {
|
||||
SetTevColorOp_Compressed(stageId, colorOps);
|
||||
SetTevAlphaOp_Compressed(stageId, alphaOps);
|
||||
} else if (colorOps != state.x8_colorOps || colorOps != state.xc_alphaOps) {
|
||||
state.x8_colorOps = colorOps;
|
||||
state.xc_alphaOps = colorOps;
|
||||
const auto outReg = GX::TevRegID(colorOps >> 9 & 3);
|
||||
GXSetTevColorOp(stageId, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, outReg);
|
||||
GXSetTevAlphaOp(stageId, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, outReg);
|
||||
}
|
||||
}
|
||||
|
||||
void SetTevIndirect(GX::TevStageID stageId, GX::IndTexStageID indStage, GX::IndTexFormat fmt, GX::IndTexBiasSel biasSel,
|
||||
GX::IndTexMtxID mtxSel, GX::IndTexWrap wrapS, GX::IndTexWrap wrapT, GXBool addPrev, GXBool indLod,
|
||||
GX::IndTexAlphaSel alphaSel) noexcept;
|
||||
|
||||
void SetTevIndWarp(GX::TevStageID stageId, GX::IndTexStageID indStage, GXBool signedOffset, GXBool replaceMode,
|
||||
GX::IndTexMtxID mtxSel) noexcept;
|
||||
|
||||
static inline void SetTevKAlphaSel(GX::TevStageID stageId, GX::TevKAlphaSel sel) noexcept {
|
||||
auto& state = sGXState.x68_tevStates[stageId].x19_kAlphaSel;
|
||||
if (sel != state) {
|
||||
state = sel;
|
||||
GXSetTevKAlphaSel(stageId, sel);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTevKColor(GX::TevKColorID id, const GXColor& color) noexcept {
|
||||
auto& state = sGXState.x58_kColors[id];
|
||||
if (color != state) {
|
||||
state = color;
|
||||
GXSetTevKColor(id, color);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTevKColorSel(GX::TevStageID stageId, GX::TevKColorSel sel) noexcept {
|
||||
auto& state = sGXState.x68_tevStates[stageId].x18_kColorSel;
|
||||
if (sel != state) {
|
||||
state = sel;
|
||||
GXSetTevKColorSel(stageId, sel);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTevOrder(GX::TevStageID stageId, GX::TexCoordID texCoord, GX::TexMapID texMap,
|
||||
GX::ChannelID color) noexcept {
|
||||
u32 flags = (color & 0xFF) << 16 | (texMap & 0xFF) << 8 | (texCoord & 0xFF);
|
||||
auto& state = sGXState.x68_tevStates[stageId].x14_tevOrderFlags;
|
||||
if (flags != state) {
|
||||
state = flags;
|
||||
GXSetTevOrder(stageId, texCoord, texMap, color);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetTexCoordGen(GX::TexCoordID dstCoord, GX::TexGenType fn, GX::TexGenSrc src, u32 mtx,
|
||||
GXBool normalize, u32 postMtx) noexcept {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void SetVtxDescv(GX::VtxDescList* descList) noexcept;
|
||||
|
||||
static inline void SetVtxDescv_Compressed(u32 descList) noexcept {
|
||||
// TODO convert to GX::VtxDescList
|
||||
aurora::gfx::model::set_vtx_desc_compressed(descList);
|
||||
}
|
||||
|
||||
static inline void SetZMode(GXBool compareEnable, GX::Compare func, GXBool updateEnable) noexcept {
|
||||
u32 flags = (func & 0xFF) << 2 | (u8(updateEnable) << 1) | (u8(compareEnable) & 1);
|
||||
auto& state = sGXState.x52_zmode;
|
||||
if (flags != state) {
|
||||
state = flags;
|
||||
GXSetZMode(compareEnable, func, updateEnable);
|
||||
}
|
||||
}
|
||||
} // namespace metaforce::CGX
|
|
@ -6,18 +6,19 @@
|
|||
#include "Runtime/Graphics/CTexture.hpp"
|
||||
#include "Runtime/Graphics/Shaders/CTextSupportShader.hpp"
|
||||
#include "Runtime/GuiSys/CGuiSys.hpp"
|
||||
#include "Runtime/Graphics/CGX.hpp"
|
||||
|
||||
#include <zeus/Math.hpp>
|
||||
|
||||
namespace metaforce {
|
||||
CGraphics::CProjectionState CGraphics::g_Proj;
|
||||
CFogState CGraphics::g_Fog;
|
||||
// CFogState CGraphics::g_Fog;
|
||||
float CGraphics::g_ProjAspect = 1.f;
|
||||
u32 CGraphics::g_NumBreakpointsWaiting = 0;
|
||||
u32 CGraphics::g_FlippingState;
|
||||
bool CGraphics::g_LastFrameUsedAbove = false;
|
||||
bool CGraphics::g_InterruptLastFrameUsedAbove = false;
|
||||
std::bitset<aurora::gfx::MaxLights> CGraphics::g_LightActive{};
|
||||
GX::LightMask CGraphics::g_LightActive{};
|
||||
zeus::CTransform CGraphics::g_GXModelView;
|
||||
zeus::CTransform CGraphics::g_GXModelViewInvXpose;
|
||||
zeus::CTransform CGraphics::g_GXModelMatrix = zeus::CTransform();
|
||||
|
@ -56,9 +57,15 @@ const std::array<zeus::CMatrix3f, 6> CGraphics::skCubeBasisMats{{
|
|||
{-1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, -1.f},
|
||||
}};
|
||||
|
||||
// Stream API
|
||||
static EStreamFlags sStreamFlags;
|
||||
static zeus::CColor sQueuedColor;
|
||||
static zeus::CVector2f sQueuedTexCoord;
|
||||
static zeus::CVector3f sQueuedNormal;
|
||||
|
||||
void CGraphics::DisableAllLights() {
|
||||
g_LightActive.reset();
|
||||
aurora::gfx::set_light_state(g_LightActive);
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel0, {});
|
||||
}
|
||||
|
||||
void CGraphics::LoadLight(ERglLight light, const CLight& info) {
|
||||
|
@ -89,50 +96,55 @@ void CGraphics::LoadLight(ERglLight light, const CLight& info) {
|
|||
}
|
||||
|
||||
void CGraphics::EnableLight(ERglLight light) {
|
||||
CGX::SetNumChans(1);
|
||||
if (!g_LightActive.test(light)) {
|
||||
g_LightActive.set(light);
|
||||
aurora::gfx::set_light_state(g_LightActive);
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel0, g_LightActive);
|
||||
}
|
||||
}
|
||||
|
||||
void CGraphics::SetLightState(std::bitset<aurora::gfx::MaxLights> lightState) {
|
||||
void CGraphics::SetLightState(GX::LightMask lightState) {
|
||||
g_LightActive = lightState;
|
||||
aurora::gfx::set_light_state(g_LightActive);
|
||||
const bool hasLights = lightState.any();
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel0, hasLights, GX::SRC_REG,
|
||||
sStreamFlags & EStreamFlagBits::fHasColor ? GX::SRC_VTX : GX::SRC_REG, lightState,
|
||||
hasLights ? GX::DF_CLAMP : GX::DF_NONE, hasLights ? GX::AF_SPOT : GX::AF_NONE);
|
||||
}
|
||||
|
||||
void CGraphics::SetAmbientColor(const zeus::CColor& col) {
|
||||
aurora::gfx::set_chan_amb_color(GX::COLOR0A0, col);
|
||||
aurora::gfx::set_chan_amb_color(GX::COLOR1A1, col);
|
||||
CGX::SetChanAmbColor(CGX::EChannelId::Channel0, col);
|
||||
CGX::SetChanAmbColor(CGX::EChannelId::Channel1, col);
|
||||
}
|
||||
|
||||
void CGraphics::SetFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) {
|
||||
g_Fog.m_mode = mode > ERglFogMode::PerspRevExp2 ? ERglFogMode(int(mode) - 8) : mode;
|
||||
g_Fog.m_color = color;
|
||||
if (CGraphics::g_Proj.x18_far == CGraphics::g_Proj.x14_near || endz == startz) {
|
||||
g_Fog.m_A = 0.f;
|
||||
g_Fog.m_B = 0.5f;
|
||||
g_Fog.m_C = 0.f;
|
||||
} else {
|
||||
float depthrange = CGraphics::g_Proj.x18_far - CGraphics::g_Proj.x14_near;
|
||||
float fogrange = endz - startz;
|
||||
g_Fog.m_A = (CGraphics::g_Proj.x18_far * CGraphics::g_Proj.x14_near) / (depthrange * fogrange);
|
||||
g_Fog.m_B = CGraphics::g_Proj.x18_far / depthrange;
|
||||
g_Fog.m_C = startz / fogrange;
|
||||
}
|
||||
// g_Fog.m_mode = mode > ERglFogMode::PerspRevExp2 ? ERglFogMode(int(mode) - 8) : mode;
|
||||
// g_Fog.m_color = color;
|
||||
// if (CGraphics::g_Proj.x18_far == CGraphics::g_Proj.x14_near || endz == startz) {
|
||||
// g_Fog.m_A = 0.f;
|
||||
// g_Fog.m_B = 0.5f;
|
||||
// g_Fog.m_C = 0.f;
|
||||
// } else {
|
||||
// float depthrange = CGraphics::g_Proj.x18_far - CGraphics::g_Proj.x14_near;
|
||||
// float fogrange = endz - startz;
|
||||
// g_Fog.m_A = (CGraphics::g_Proj.x18_far * CGraphics::g_Proj.x14_near) / (depthrange * fogrange);
|
||||
// g_Fog.m_B = CGraphics::g_Proj.x18_far / depthrange;
|
||||
// g_Fog.m_C = startz / fogrange;
|
||||
// }
|
||||
CGX::SetFog(GX::FogType(mode), startz, endz, g_Proj.x14_near, g_Proj.x18_far, color);
|
||||
}
|
||||
|
||||
void CGraphics::SetDepthWriteMode(bool compare_enable, ERglEnum comp, bool update_enable) {
|
||||
g_depthFunc = comp;
|
||||
aurora::gfx::set_depth_mode(compare_enable, comp, update_enable);
|
||||
CGX::SetZMode(compare_enable, GX::Compare(comp), update_enable);
|
||||
}
|
||||
|
||||
void CGraphics::SetBlendMode(ERglBlendMode mode, ERglBlendFactor src, ERglBlendFactor dst, ERglLogicOp op) {
|
||||
aurora::gfx::set_blend_mode(mode, src, dst, op);
|
||||
CGX::SetBlendMode(GX::BlendMode(mode), GX::BlendFactor(src), GX::BlendFactor(dst), GX::LogicOp(op));
|
||||
}
|
||||
|
||||
void CGraphics::SetCullMode(ERglCullMode mode) {
|
||||
g_cullMode = mode;
|
||||
aurora::gfx::set_cull_mode(mode);
|
||||
GXSetCullMode(GX::CullMode(mode));
|
||||
}
|
||||
|
||||
void CGraphics::BeginScene() {
|
||||
|
@ -140,7 +152,8 @@ void CGraphics::BeginScene() {
|
|||
}
|
||||
|
||||
void CGraphics::EndScene() {
|
||||
aurora::gfx::set_depth_mode(true, ERglEnum::LEqual, true);
|
||||
CGX::SetZMode(true, GX::LEQUAL, true);
|
||||
|
||||
/* Spinwait until g_NumBreakpointsWaiting is 0 */
|
||||
/* ++g_NumBreakpointsWaiting; */
|
||||
/* GXCopyDisp to g_CurrenFrameBuf with clear enabled */
|
||||
|
@ -497,26 +510,18 @@ void CGraphics::SetUseVideoFilter(bool filter) {
|
|||
|
||||
void CGraphics::SetClearColor(const zeus::CColor& color) {
|
||||
g_ClearColor = color;
|
||||
aurora::gfx::set_clear_color(color);
|
||||
GXSetCopyClear(color, g_ClearDepthValue);
|
||||
}
|
||||
|
||||
void CGraphics::SetCopyClear(const zeus::CColor& color, float depth) {
|
||||
g_ClearColor = color;
|
||||
g_ClearDepthValue = depth; // 1.6777215E7 * depth; Metroid Prime needed this to convert float [0,1] depth into 24 bit
|
||||
// range, we no longer have this requirement
|
||||
aurora::gfx::set_clear_color(color);
|
||||
// TODO do we care about depth value?
|
||||
// GXSetCopyClear(g_ClearColor, g_ClearDepthValue);
|
||||
GXSetCopyClear(g_ClearColor, g_ClearDepthValue);
|
||||
}
|
||||
|
||||
void CGraphics::SetIsBeginSceneClearFb(bool clear) { g_IsBeginSceneClearFb = clear; }
|
||||
|
||||
// Stream API
|
||||
static EStreamFlags sStreamFlags;
|
||||
static zeus::CColor sQueuedColor;
|
||||
static zeus::CVector2f sQueuedTexCoord;
|
||||
static zeus::CVector3f sQueuedNormal;
|
||||
|
||||
void CGraphics::SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass) {
|
||||
CTevCombiners::SetupPass(stage, pass);
|
||||
}
|
||||
|
@ -583,13 +588,22 @@ void CGraphics::DrawPrimitive(GX::Primitive primitive, const zeus::CVector3f* po
|
|||
|
||||
void CGraphics::SetTevStates(EStreamFlags flags) noexcept {
|
||||
if (flags & EStreamFlagBits::fHasTexture) {
|
||||
aurora::gfx::set_tev_order(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR0A0);
|
||||
aurora::gfx::set_tev_order(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP1, GX::COLOR0A0);
|
||||
} else {
|
||||
aurora::gfx::set_tev_order(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0);
|
||||
aurora::gfx::set_tev_order(GX::TEVSTAGE1, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0);
|
||||
CGX::SetNumChans(1);
|
||||
CGX::SetNumTexGens(0);
|
||||
CGX::SetNumTevStages(1);
|
||||
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR0A0);
|
||||
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP1, GX::COLOR0A0);
|
||||
} else /* if (flags < 8) ? */ {
|
||||
CGX::SetNumChans(1);
|
||||
CGX::SetNumTexGens(2); // sTextureUsed & 3?
|
||||
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0);
|
||||
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0);
|
||||
}
|
||||
CGX::SetNumIndStages(0);
|
||||
// TODO load TCGs
|
||||
aurora::gfx::set_chan_mat_src(GX::COLOR0A0, flags & EStreamFlagBits::fHasColor ? GX::SRC_VTX : GX::SRC_REG);
|
||||
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,
|
||||
hasLights ? GX::DF_CLAMP : GX::DF_NONE, hasLights ? GX::AF_SPOT : GX::AF_NONE);
|
||||
}
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "Runtime/RetroTypes.hpp"
|
||||
#include "Runtime/Graphics/GX.hpp"
|
||||
#include "Runtime/Graphics/CTevCombiners.hpp"
|
||||
#include "Runtime/ConsoleVariables/CVar.hpp"
|
||||
#include "Runtime/Graphics/CTevCombiners.hpp"
|
||||
#include "Runtime/Graphics/GX.hpp"
|
||||
#include "Runtime/RetroTypes.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
|
@ -25,6 +25,83 @@ extern CVar* g_disableLighting;
|
|||
class CLight;
|
||||
class CTimeProvider;
|
||||
|
||||
enum class ERglCullMode : std::underlying_type_t<GX::CullMode> {
|
||||
None = GX::CULL_NONE,
|
||||
Front = GX::CULL_FRONT,
|
||||
Back = GX::CULL_BACK,
|
||||
All = GX::CULL_ALL,
|
||||
};
|
||||
|
||||
enum class ERglBlendMode : std::underlying_type_t<GX::BlendMode> {
|
||||
None = GX::BM_NONE,
|
||||
Blend = GX::BM_BLEND,
|
||||
Logic = GX::BM_LOGIC,
|
||||
Subtract = GX::BM_SUBTRACT,
|
||||
Max = GX::MAX_BLENDMODE,
|
||||
};
|
||||
|
||||
enum class ERglBlendFactor : std::underlying_type_t<GX::BlendFactor> {
|
||||
Zero = GX::BL_ZERO,
|
||||
One = GX::BL_ONE,
|
||||
SrcColor = GX::BL_SRCCLR,
|
||||
InvSrcColor = GX::BL_INVSRCCLR,
|
||||
SrcAlpha = GX::BL_SRCALPHA,
|
||||
InvSrcAlpha = GX::BL_INVSRCALPHA,
|
||||
DstAlpha = GX::BL_DSTALPHA,
|
||||
InvDstAlpha = GX::BL_INVDSTALPHA,
|
||||
DstColor = GX::BL_DSTCLR,
|
||||
InvDstColor = GX::BL_INVDSTCLR,
|
||||
};
|
||||
|
||||
enum class ERglLogicOp : std::underlying_type_t<GX::LogicOp> {
|
||||
Clear = GX::LO_CLEAR,
|
||||
And = GX::LO_AND,
|
||||
RevAnd = GX::LO_REVAND,
|
||||
Copy = GX::LO_COPY,
|
||||
InvAnd = GX::LO_INVAND,
|
||||
NoOp = GX::LO_NOOP,
|
||||
Xor = GX::LO_XOR,
|
||||
Or = GX::LO_OR,
|
||||
Nor = GX::LO_NOR,
|
||||
Equiv = GX::LO_EQUIV,
|
||||
Inv = GX::LO_INV,
|
||||
RevOr = GX::LO_REVOR,
|
||||
InvCopy = GX::LO_INVCOPY,
|
||||
InvOr = GX::LO_INVOR,
|
||||
NAnd = GX::LO_NAND,
|
||||
Set = GX::LO_SET,
|
||||
};
|
||||
|
||||
enum class ERglAlphaFunc : std::underlying_type_t<GX::Compare> {
|
||||
Never = GX::NEVER,
|
||||
Less = GX::LESS,
|
||||
Equal = GX::EQUAL,
|
||||
LEqual = GX::LEQUAL,
|
||||
Greater = GX::GREATER,
|
||||
NEqual = GX::NEQUAL,
|
||||
GEqual = GX::GEQUAL,
|
||||
Always = GX::ALWAYS,
|
||||
};
|
||||
|
||||
enum class ERglAlphaOp : std::underlying_type_t<GX::AlphaOp> {
|
||||
And = GX::AOP_AND,
|
||||
Or = GX::AOP_OR,
|
||||
Xor = GX::AOP_XOR,
|
||||
XNor = GX::AOP_XNOR,
|
||||
Max = GX::MAX_ALPHAOP,
|
||||
};
|
||||
|
||||
enum class ERglEnum : std::underlying_type_t<GX::Compare> {
|
||||
Never = GX::NEVER,
|
||||
Less = GX::LESS,
|
||||
Equal = GX::EQUAL,
|
||||
LEqual = GX::LEQUAL,
|
||||
Greater = GX::GREATER,
|
||||
NEqual = GX::NEQUAL,
|
||||
GEqual = GX::GEQUAL,
|
||||
Always = GX::ALWAYS,
|
||||
};
|
||||
|
||||
using ERglLight = u8;
|
||||
|
||||
struct SViewport {
|
||||
|
@ -104,14 +181,14 @@ public:
|
|||
|
||||
static CProjectionState g_Proj;
|
||||
static zeus::CVector2f g_CachedDepthRange;
|
||||
static CFogState g_Fog;
|
||||
// static CFogState g_Fog;
|
||||
static SViewport g_Viewport;
|
||||
static float g_ProjAspect;
|
||||
static u32 g_NumBreakpointsWaiting;
|
||||
static u32 g_FlippingState;
|
||||
static bool g_LastFrameUsedAbove;
|
||||
static bool g_InterruptLastFrameUsedAbove;
|
||||
static std::bitset<aurora::gfx::MaxLights> g_LightActive;
|
||||
static GX::LightMask g_LightActive;
|
||||
static zeus::CTransform g_GXModelView;
|
||||
static zeus::CTransform g_GXModelViewInvXpose;
|
||||
static zeus::CTransform g_GXModelMatrix;
|
||||
|
@ -131,7 +208,7 @@ public:
|
|||
static void DisableAllLights();
|
||||
static void LoadLight(ERglLight light, const CLight& info);
|
||||
static void EnableLight(ERglLight light);
|
||||
static void SetLightState(std::bitset<aurora::gfx::MaxLights> lightState);
|
||||
static void SetLightState(GX::LightMask lightState);
|
||||
static void SetAmbientColor(const zeus::CColor& col);
|
||||
static void SetFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color);
|
||||
static void SetDepthWriteMode(bool test, ERglEnum comp, bool write);
|
||||
|
|
|
@ -17,6 +17,7 @@ set(GRAPHICS_SOURCES
|
|||
CVertexMorphEffect.hpp CVertexMorphEffect.cpp
|
||||
CMoviePlayer.hpp CMoviePlayer.cpp
|
||||
CGraphicsPalette.hpp CGraphicsPalette.cpp
|
||||
CGX.hpp CGX.cpp
|
||||
CPVSVisSet.hpp CPVSVisSet.cpp
|
||||
CPVSVisOctree.hpp CPVSVisOctree.cpp
|
||||
CPVSAreaSet.hpp CPVSAreaSet.cpp
|
||||
|
|
|
@ -105,13 +105,15 @@ public:
|
|||
void DrawUnsortedParts(CModelFlags flags);
|
||||
bool IsLoaded(u32 matIdx);
|
||||
|
||||
TVectorRef GetPositions();
|
||||
TConstVectorRef GetPositions() const;
|
||||
TVectorRef GetNormals();
|
||||
TConstVectorRef GetNormals() const;
|
||||
u32 GetNumMaterialSets() const { return x18_matSets.size(); }
|
||||
bool IsOpaque() const { return x28_modelInst->x3c_firstSortedSurf == nullptr; }
|
||||
const zeus::CAABox& GetAABB() const { return x28_modelInst->x20_worldAABB; }
|
||||
[[nodiscard]] TVectorRef GetPositions();
|
||||
[[nodiscard]] TConstVectorRef GetPositions() const;
|
||||
[[nodiscard]] TVectorRef GetNormals();
|
||||
[[nodiscard]] TConstVectorRef GetNormals() const;
|
||||
[[nodiscard]] u32 GetNumMaterialSets() const { return x18_matSets.size(); }
|
||||
[[nodiscard]] bool IsOpaque() const { return x28_modelInst->x3c_firstSortedSurf == nullptr; }
|
||||
[[nodiscard]] const zeus::CAABox& GetAABB() const { return x28_modelInst->x20_worldAABB; }
|
||||
[[nodiscard]] auto& GetInstance() { return *x28_modelInst; }
|
||||
[[nodiscard]] const auto& GetInstance() const { return *x28_modelInst; }
|
||||
|
||||
static void FrameDone();
|
||||
static void EnableTextureTimeout();
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
#include "Graphics/CTevCombiners.hpp"
|
||||
|
||||
#include "Graphics/CGX.hpp"
|
||||
|
||||
namespace metaforce::CTevCombiners {
|
||||
u32 CTevPass::sNextUniquePass = 0;
|
||||
|
||||
void CTevPass::Execute(ERglTevStage stage) const {
|
||||
aurora::gfx::update_tev_stage(stage, x4_colorPass, x14_alphaPass, x24_colorOp, x38_alphaOp);
|
||||
aurora::gfx::set_tev_k_color_sel(static_cast<GX::TevStageID>(stage), GX::TevKColorSel::TEV_KCSEL_8_8);
|
||||
aurora::gfx::set_tev_k_alpha_sel(static_cast<GX::TevStageID>(stage), GX::TevKAlphaSel::TEV_KASEL_8_8);
|
||||
const auto stageId = GX::TevStageID(stage);
|
||||
CGX::SetTevColorIn(stageId, x4_colorPass.x0_a, x4_colorPass.x4_b, x4_colorPass.x8_c, x4_colorPass.xc_d);
|
||||
CGX::SetTevAlphaIn(stageId, x14_alphaPass.x0_a, x14_alphaPass.x4_b, x14_alphaPass.x8_c, x14_alphaPass.xc_d);
|
||||
CGX::SetTevColorOp(stageId, x24_colorOp.x4_op, x24_colorOp.x8_bias, x24_colorOp.xc_scale, x24_colorOp.x0_clamp,
|
||||
x24_colorOp.x10_regId);
|
||||
CGX::SetTevAlphaOp(stageId, x38_alphaOp.x4_op, x38_alphaOp.x8_bias, x38_alphaOp.xc_scale, x38_alphaOp.x0_clamp,
|
||||
x38_alphaOp.x10_regId);
|
||||
CGX::SetTevKColorSel(stageId, GX::TevKColorSel::TEV_KCSEL_8_8);
|
||||
CGX::SetTevKAlphaSel(stageId, GX::TevKAlphaSel::TEV_KASEL_8_8);
|
||||
}
|
||||
|
||||
constexpr u32 maxTevPasses = 2;
|
||||
|
@ -17,10 +25,6 @@ const CTevPass skPassThru{
|
|||
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC},
|
||||
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
|
||||
};
|
||||
const CTevPass skPassZero{
|
||||
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO},
|
||||
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO},
|
||||
};
|
||||
const CTevPass sTevPass805a5698{
|
||||
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_C0, GX::TevColorArg::CC_ZERO},
|
||||
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_A0, GX::TevAlphaArg::CA_ZERO},
|
||||
|
@ -96,16 +100,13 @@ bool SetPassCombiners(ERglTevStage stage, const CTevPass& pass) {
|
|||
|
||||
void RecomputePasses() {
|
||||
sNumEnabledPasses = 1 - static_cast<int>(sValidPasses[maxTevPasses - 1]);
|
||||
for (u32 i = sNumEnabledPasses; i < maxTevPasses; ++i) {
|
||||
aurora::gfx::disable_tev_stage(ERglTevStage(i));
|
||||
}
|
||||
// CGX::SetNumTevStages(sNumEnabledPasses);
|
||||
CGX::SetNumTevStages(sNumEnabledPasses);
|
||||
}
|
||||
|
||||
void ResetStates() {
|
||||
sValidPasses.fill(false);
|
||||
skPassThru.Execute(ERglTevStage::Stage0);
|
||||
sNumEnabledPasses = 1;
|
||||
// CGX::SetNumTevStages(1);
|
||||
CGX::SetNumTevStages(1);
|
||||
}
|
||||
} // namespace metaforce::CTevCombiners
|
||||
|
|
|
@ -3,9 +3,80 @@
|
|||
#include "Graphics/GX.hpp"
|
||||
#include "RetroTypes.hpp"
|
||||
|
||||
#include <aurora/gfx.hpp>
|
||||
namespace metaforce {
|
||||
enum class ERglTevStage : std::underlying_type_t<GX::TevStageID> {
|
||||
Stage0 = GX::TEVSTAGE0,
|
||||
Stage1 = GX::TEVSTAGE1,
|
||||
Stage2 = GX::TEVSTAGE2,
|
||||
Stage3 = GX::TEVSTAGE3,
|
||||
Stage4 = GX::TEVSTAGE4,
|
||||
Stage5 = GX::TEVSTAGE5,
|
||||
Stage6 = GX::TEVSTAGE6,
|
||||
Stage7 = GX::TEVSTAGE7,
|
||||
Stage8 = GX::TEVSTAGE8,
|
||||
Stage9 = GX::TEVSTAGE9,
|
||||
Stage10 = GX::TEVSTAGE10,
|
||||
Stage11 = GX::TEVSTAGE11,
|
||||
Stage12 = GX::TEVSTAGE12,
|
||||
Stage13 = GX::TEVSTAGE13,
|
||||
Stage14 = GX::TEVSTAGE14,
|
||||
Stage15 = GX::TEVSTAGE15,
|
||||
Max = GX::MAX_TEVSTAGE,
|
||||
None = GX::NULL_STAGE,
|
||||
};
|
||||
|
||||
namespace metaforce::CTevCombiners {
|
||||
namespace CTevCombiners {
|
||||
struct CTevOp {
|
||||
bool x0_clamp = true;
|
||||
GX::TevOp x4_op = GX::TevOp::TEV_ADD;
|
||||
GX::TevBias x8_bias = GX::TevBias::TB_ZERO;
|
||||
GX::TevScale xc_scale = GX::TevScale::CS_SCALE_1;
|
||||
GX::TevRegID x10_regId = GX::TevRegID::TEVPREV;
|
||||
|
||||
constexpr CTevOp() = default;
|
||||
constexpr CTevOp(bool clamp, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, GX::TevRegID regId)
|
||||
: x0_clamp(clamp), x4_op(op), x8_bias(bias), xc_scale(scale), x10_regId(regId) {}
|
||||
constexpr CTevOp(u32 compressedDesc)
|
||||
: x0_clamp((compressedDesc >> 8 & 1) != 0)
|
||||
, x4_op(static_cast<GX::TevOp>(compressedDesc & 0xF))
|
||||
, x8_bias(static_cast<GX::TevBias>(compressedDesc >> 4 & 3))
|
||||
, xc_scale(static_cast<GX::TevScale>(compressedDesc >> 6 & 3))
|
||||
, x10_regId(static_cast<GX::TevRegID>(compressedDesc >> 9 & 3)) {}
|
||||
|
||||
auto operator<=>(const CTevOp&) const = default;
|
||||
};
|
||||
struct ColorPass {
|
||||
GX::TevColorArg x0_a;
|
||||
GX::TevColorArg x4_b;
|
||||
GX::TevColorArg x8_c;
|
||||
GX::TevColorArg xc_d;
|
||||
|
||||
constexpr ColorPass(GX::TevColorArg a, GX::TevColorArg b, GX::TevColorArg c, GX::TevColorArg d)
|
||||
: x0_a(a), x4_b(b), x8_c(c), xc_d(d) {}
|
||||
constexpr ColorPass(u32 compressedDesc)
|
||||
: x0_a(static_cast<GX::TevColorArg>(compressedDesc & 0x1F))
|
||||
, x4_b(static_cast<GX::TevColorArg>(compressedDesc >> 5 & 0x1F))
|
||||
, x8_c(static_cast<GX::TevColorArg>(compressedDesc >> 10 & 0x1F))
|
||||
, xc_d(static_cast<GX::TevColorArg>(compressedDesc >> 15 & 0x1F)) {}
|
||||
|
||||
auto operator<=>(const ColorPass&) const = default;
|
||||
};
|
||||
struct AlphaPass {
|
||||
GX::TevAlphaArg x0_a;
|
||||
GX::TevAlphaArg x4_b;
|
||||
GX::TevAlphaArg x8_c;
|
||||
GX::TevAlphaArg xc_d;
|
||||
|
||||
constexpr AlphaPass(GX::TevAlphaArg a, GX::TevAlphaArg b, GX::TevAlphaArg c, GX::TevAlphaArg d)
|
||||
: x0_a(a), x4_b(b), x8_c(c), xc_d(d) {}
|
||||
constexpr AlphaPass(u32 compressedDesc)
|
||||
: x0_a(static_cast<GX::TevAlphaArg>(compressedDesc & 0x1F))
|
||||
, x4_b(static_cast<GX::TevAlphaArg>(compressedDesc >> 5 & 0x1F))
|
||||
, x8_c(static_cast<GX::TevAlphaArg>(compressedDesc >> 10 & 0x1F))
|
||||
, xc_d(static_cast<GX::TevAlphaArg>(compressedDesc >> 15 & 0x1F)) {}
|
||||
|
||||
auto operator<=>(const AlphaPass&) const = default;
|
||||
};
|
||||
class CTevPass {
|
||||
u32 x0_id;
|
||||
ColorPass x4_colorPass;
|
||||
|
@ -29,7 +100,6 @@ public:
|
|||
};
|
||||
|
||||
extern const CTevPass skPassThru;
|
||||
extern const CTevPass skPassZero;
|
||||
extern const CTevPass sTevPass805a5698;
|
||||
extern const CTevPass sTevPass805a5e70;
|
||||
extern const CTevPass sTevPass805a5ebc;
|
||||
|
@ -47,4 +117,5 @@ void DeletePass(ERglTevStage stage);
|
|||
bool SetPassCombiners(ERglTevStage stage, const CTevPass& pass);
|
||||
void RecomputePasses();
|
||||
void ResetStates();
|
||||
} // namespace metaforce::CTevCombiners
|
||||
} // namespace CTevCombiners
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include "../GCNTypes.hpp"
|
||||
|
||||
#include <bit>
|
||||
#include <bitset>
|
||||
|
||||
#include <zeus/CColor.hpp>
|
||||
|
||||
namespace GX {
|
||||
enum Attr {
|
||||
|
@ -303,12 +307,14 @@ enum TevSwapSel {
|
|||
TEV_SWAP3 = 0x3,
|
||||
MAX_TEVSWAP = 0x4,
|
||||
};
|
||||
|
||||
enum TevColorChan {
|
||||
CH_RED = 0x0,
|
||||
CH_GREEN = 0x1,
|
||||
CH_BLUE = 0x2,
|
||||
CH_ALPHA = 0x3,
|
||||
};
|
||||
|
||||
enum TevRegID {
|
||||
TEVPREV = 0,
|
||||
TEVREG0 = 1,
|
||||
|
@ -319,14 +325,14 @@ enum TevRegID {
|
|||
|
||||
enum DiffuseFn {
|
||||
DF_NONE = 0,
|
||||
DF_SIGN,
|
||||
DF_CLAMP,
|
||||
DF_SIGN = 1,
|
||||
DF_CLAMP = 2,
|
||||
};
|
||||
|
||||
enum AttnFn {
|
||||
AF_SPEC = 0,
|
||||
AF_SPOT = 1,
|
||||
AF_NONE,
|
||||
AF_NONE = 2,
|
||||
};
|
||||
|
||||
enum Primitive {
|
||||
|
@ -405,7 +411,7 @@ enum Compare {
|
|||
ALWAYS,
|
||||
};
|
||||
|
||||
enum BlendFactor : uint16_t {
|
||||
enum BlendFactor {
|
||||
BL_ZERO,
|
||||
BL_ONE,
|
||||
BL_SRCCLR,
|
||||
|
@ -413,10 +419,19 @@ enum BlendFactor : uint16_t {
|
|||
BL_SRCALPHA,
|
||||
BL_INVSRCALPHA,
|
||||
BL_DSTALPHA,
|
||||
BL_INVDSTALPHA
|
||||
BL_INVDSTALPHA,
|
||||
BL_DSTCLR,
|
||||
BL_INVDSTCLR,
|
||||
};
|
||||
|
||||
enum TextureFormat : uint32_t {
|
||||
enum CullMode {
|
||||
CULL_NONE,
|
||||
CULL_FRONT,
|
||||
CULL_BACK,
|
||||
CULL_ALL,
|
||||
};
|
||||
|
||||
enum TextureFormat {
|
||||
TF_I4 = 0x0,
|
||||
TF_I8 = 0x1,
|
||||
TF_IA4 = 0x2,
|
||||
|
@ -520,6 +535,7 @@ enum IndTexAlphaSel {
|
|||
ITBA_U,
|
||||
MAX_ITBALPHA,
|
||||
};
|
||||
|
||||
enum IndTexStageID {
|
||||
INDTEXSTAGE0,
|
||||
INDTEXSTAGE1,
|
||||
|
@ -611,6 +627,8 @@ enum LightID {
|
|||
MAX_LIGHT = 0x100,
|
||||
LIGHT_NULL = 0x000,
|
||||
};
|
||||
constexpr u8 MaxLights = std::bit_width<std::underlying_type_t<LightID>>(MAX_LIGHT) - 1;
|
||||
using LightMask = std::bitset<MaxLights>;
|
||||
|
||||
enum FogType {
|
||||
FOG_NONE = 0x00,
|
||||
|
@ -627,3 +645,43 @@ enum FogType {
|
|||
};
|
||||
|
||||
} // namespace GX
|
||||
|
||||
using GXColor = zeus::CColor;
|
||||
using GXBool = bool;
|
||||
|
||||
void GXSetNumChans(u8 num) noexcept;
|
||||
void GXSetNumIndStages(u8 num) noexcept;
|
||||
void GXSetNumTevStages(u8 num) noexcept;
|
||||
void GXSetNumTexGens(u8 num) noexcept;
|
||||
void GXSetTevAlphaIn(GX::TevStageID stageId, GX::TevAlphaArg a, GX::TevAlphaArg b, GX::TevAlphaArg c,
|
||||
GX::TevAlphaArg d) noexcept;
|
||||
void GXSetTevAlphaOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, GXBool clamp,
|
||||
GX::TevRegID outReg) noexcept;
|
||||
void GXSetTevColorIn(GX::TevStageID stageId, GX::TevColorArg a, GX::TevColorArg b, GX::TevColorArg c,
|
||||
GX::TevColorArg d) noexcept;
|
||||
void GXSetTevColorOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, GXBool clamp,
|
||||
GX::TevRegID outReg) noexcept;
|
||||
void GXSetCullMode(GX::CullMode mode) noexcept;
|
||||
void GXSetBlendMode(GX::BlendMode mode, GX::BlendFactor src, GX::BlendFactor dst, GX::LogicOp op) noexcept;
|
||||
void GXSetZMode(GXBool compare_enable, GX::Compare func, GXBool update_enable) noexcept;
|
||||
void GXSetTevColor(GX::TevRegID id, const GXColor& color) noexcept;
|
||||
void GXSetTevKColor(GX::TevKColorID id, const GXColor& color) noexcept;
|
||||
void GXSetAlphaUpdate(GXBool enabled) noexcept;
|
||||
// Originally u8 instead of float
|
||||
void GXSetDstAlpha(GXBool enabled, float value) noexcept;
|
||||
void GXSetCopyClear(const GXColor& color, float depth) noexcept;
|
||||
void GXSetTevOrder(GX::TevStageID id, GX::TexCoordID tcid, GX::TexMapID tmid, GX::ChannelID cid) noexcept;
|
||||
void GXSetTevKColorSel(GX::TevStageID id, GX::TevKColorSel sel) noexcept;
|
||||
void GXSetTevKAlphaSel(GX::TevStageID id, GX::TevKAlphaSel sel) noexcept;
|
||||
void GXSetChanAmbColor(GX::ChannelID id, const GXColor& color) noexcept;
|
||||
void GXSetChanMatColor(GX::ChannelID id, const GXColor& color) noexcept;
|
||||
void GXSetChanCtrl(GX::ChannelID id, GXBool lightingEnabled, GX::ColorSrc ambSrc, GX::ColorSrc matSrc,
|
||||
GX::LightMask lightState, GX::DiffuseFn diffFn, GX::AttnFn attnFn) noexcept;
|
||||
// Originally u8 instead of floats
|
||||
void GXSetAlphaCompare(GX::Compare comp0, float ref0, GX::AlphaOp op, GX::Compare comp1, float ref1) noexcept;
|
||||
void GXSetVtxDescv(GX::VtxDescList* list) noexcept;
|
||||
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 GXCallDisplayList(const void* data, u32 nbytes) noexcept;
|
||||
|
|
|
@ -92,11 +92,12 @@ public:
|
|||
virtual u32 GetFPS() = 0;
|
||||
virtual void CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) = 0;
|
||||
virtual void DrawSpaceWarp(const zeus::CVector3f& pt, float strength) = 0;
|
||||
virtual void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
|
||||
virtual void DrawThermalModel(CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
|
||||
TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) = 0;
|
||||
virtual void DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color,
|
||||
TConstVectorRef positions, TConstVectorRef normals) = 0;
|
||||
virtual void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) = 0;
|
||||
virtual void DrawModelDisintegrate(CModel& model, CTexture& tex, const zeus::CColor& color, TConstVectorRef positions,
|
||||
TConstVectorRef normals, float t) = 0;
|
||||
virtual void DrawModelFlat(CModel& model, const CModelFlags& flags, bool unsortedOnly, TConstVectorRef positions,
|
||||
TConstVectorRef normals) = 0;
|
||||
virtual void SetWireframeFlags(s32 flags) = 0;
|
||||
virtual void SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) = 0;
|
||||
virtual void RenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, const TLockedToken<CModel>* model,
|
||||
|
|
|
@ -332,7 +332,7 @@ void CSamusDoll::Draw(const CStateManager& mgr, float alpha) {
|
|||
|
||||
bool phazonSuit = x44_suit == CPlayerState::EPlayerSuit::Phazon;
|
||||
if (phazonSuit) {
|
||||
aurora::gfx::set_dst_alpha(true, 1.f);
|
||||
GXSetDstAlpha(true, 1.f);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i <= x118_suitModel1and2.size(); ++i) {
|
||||
|
|
|
@ -100,7 +100,7 @@ private:
|
|||
bool x26d_27_enableOPTS : 1;
|
||||
bool x26d_28_enableADV : 1 = false;
|
||||
int x270_MBSP = 0;
|
||||
std::bitset<aurora::gfx::MaxLights> x274_backupLightActive{};
|
||||
GX::LightMask x274_backupLightActive{};
|
||||
std::array<bool, 4> x278_hasVMD{};
|
||||
CRandom16 x27c_randState;
|
||||
std::array<CModVectorElement*, 4> x280_VELSources{};
|
||||
|
|
|
@ -616,7 +616,7 @@ void CActorModelParticles::LightDudeOnFire(CActor& act) {
|
|||
iter->x70_onFire = true;
|
||||
}
|
||||
|
||||
const CTexture* CActorModelParticles::GetAshyTexture(const CActor& act) {
|
||||
CTexture* CActorModelParticles::GetAshyTexture(const CActor& act) {
|
||||
auto iter = FindSystem(act.GetUniqueId());
|
||||
if (iter != x0_items.cend() && iter->xdc_ashy && iter->xdc_ashy.IsLoaded()) {
|
||||
// iter->xdc_ashy->GetBooTexture()->setClampMode(boo::TextureClampMode::ClampToEdge);
|
||||
|
|
|
@ -169,6 +169,6 @@ public:
|
|||
void EnsureFirePopLoaded(CActor& act);
|
||||
void EnsureIceBreakLoaded(CActor& act);
|
||||
void LightDudeOnFire(CActor& act);
|
||||
const CTexture* GetAshyTexture(const CActor& act);
|
||||
CTexture* GetAshyTexture(const CActor& act);
|
||||
};
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -1713,7 +1713,7 @@ void CPatterned::Render(CStateManager& mgr) {
|
|||
(mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot && x402_31_thawed) ||
|
||||
mgr.GetThermalDrawFlag() == EThermalDrawFlag::Bypass) {
|
||||
if (x401_28_burning) {
|
||||
const CTexture* ashy = mgr.GetActorModelParticles()->GetAshyTexture(*this);
|
||||
CTexture* ashy = mgr.GetActorModelParticles()->GetAshyTexture(*this);
|
||||
u8 alpha = GetModelAlphau8(mgr);
|
||||
if (ashy != nullptr && ((!x401_29_laggedBurnDeath && alpha <= 255) || alpha <= 127)) {
|
||||
if (xe5_31_pointGeneratorParticles) {
|
||||
|
|
|
@ -400,7 +400,7 @@ void CScriptPlayerActor::AddToRenderer(const zeus::CFrustum& frustum, CStateMana
|
|||
void CScriptPlayerActor::Render(CStateManager& mgr) {
|
||||
const bool phazonSuit = x2e8_suitRes.GetCharacterNodeId() == 3;
|
||||
if (phazonSuit) {
|
||||
aurora::gfx::set_dst_alpha(true, 1.f);
|
||||
GXSetDstAlpha(true, 1.f);
|
||||
}
|
||||
|
||||
CPhysicsActor::Render(mgr);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
// TODO make this shared?
|
||||
#include "../../../Runtime/Graphics/GX.hpp"
|
||||
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
|
@ -33,77 +34,6 @@ enum class ERglFogMode : uint32_t {
|
|||
OrthoRevExp2 = 0x0F
|
||||
};
|
||||
|
||||
enum class ERglCullMode { None = 0, Front = 1, Back = 2, All = 3 };
|
||||
|
||||
enum class ERglBlendMode { None = 0, Blend = 1, Logic = 2, Subtract = 3 };
|
||||
|
||||
enum class ERglBlendFactor {
|
||||
Zero = 0,
|
||||
One = 1,
|
||||
SrcColor = 2,
|
||||
InvSrcColor = 3,
|
||||
SrcAlpha = 4,
|
||||
InvSrcAlpha = 5,
|
||||
DstAlpha = 6,
|
||||
InvDstAlpha = 7,
|
||||
DstColor = 8,
|
||||
InvDstColor = 9,
|
||||
};
|
||||
|
||||
enum class ERglLogicOp {
|
||||
Clear = 0,
|
||||
And = 1,
|
||||
RevAnd = 2,
|
||||
Copy = 3,
|
||||
InvAnd = 4,
|
||||
NoOp = 5,
|
||||
Xor = 6,
|
||||
Or = 7,
|
||||
Nor = 8,
|
||||
Equiv = 9,
|
||||
Inv = 10,
|
||||
RevOr = 11,
|
||||
InvCopy = 12,
|
||||
InvOr = 13,
|
||||
NAnd = 14,
|
||||
Set = 15
|
||||
};
|
||||
|
||||
enum class ERglAlphaFunc {
|
||||
Never = 0,
|
||||
Less = 1,
|
||||
Equal = 2,
|
||||
LEqual = 3,
|
||||
Greater = 4,
|
||||
NEqual = 5,
|
||||
GEqual = 6,
|
||||
Always = 7
|
||||
};
|
||||
|
||||
enum class ERglAlphaOp { And = 0, Or = 1, Xor = 2, XNor = 3 };
|
||||
|
||||
enum class ERglEnum { Never = 0, Less = 1, Equal = 2, LEqual = 3, Greater = 4, NEqual = 5, GEqual = 6, Always = 7 };
|
||||
|
||||
enum class ERglTevStage : u32 {
|
||||
Stage0,
|
||||
Stage1,
|
||||
Stage2,
|
||||
Stage3,
|
||||
Stage4,
|
||||
Stage5,
|
||||
Stage6,
|
||||
Stage7,
|
||||
Stage8,
|
||||
Stage9,
|
||||
Stage10,
|
||||
Stage11,
|
||||
Stage12,
|
||||
Stage13,
|
||||
Stage14,
|
||||
Stage15,
|
||||
MAX
|
||||
};
|
||||
|
||||
enum class ETexelFormat {
|
||||
Invalid = -1,
|
||||
I4 = 0,
|
||||
|
@ -142,60 +72,6 @@ enum class EStreamFlagBits : u8 {
|
|||
fHasTexture = 0x4,
|
||||
};
|
||||
using EStreamFlags = Flags<EStreamFlagBits>;
|
||||
|
||||
namespace CTevCombiners {
|
||||
struct CTevOp {
|
||||
bool x0_clamp = true;
|
||||
GX::TevOp x4_op = GX::TevOp::TEV_ADD;
|
||||
GX::TevBias x8_bias = GX::TevBias::TB_ZERO;
|
||||
GX::TevScale xc_scale = GX::TevScale::CS_SCALE_1;
|
||||
GX::TevRegID x10_regId = GX::TevRegID::TEVPREV;
|
||||
|
||||
constexpr CTevOp() = default;
|
||||
constexpr CTevOp(bool clamp, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, GX::TevRegID regId)
|
||||
: x0_clamp(clamp), x4_op(op), x8_bias(bias), xc_scale(scale), x10_regId(regId) {}
|
||||
constexpr CTevOp(u32 compressedDesc)
|
||||
: x0_clamp((compressedDesc >> 8 & 1) != 0)
|
||||
, x4_op(static_cast<GX::TevOp>(compressedDesc & 0xF))
|
||||
, x8_bias(static_cast<GX::TevBias>(compressedDesc >> 4 & 3))
|
||||
, xc_scale(static_cast<GX::TevScale>(compressedDesc >> 6 & 3))
|
||||
, x10_regId(static_cast<GX::TevRegID>(compressedDesc >> 9 & 3)) {}
|
||||
|
||||
auto operator<=>(const CTevOp&) const = default;
|
||||
};
|
||||
struct ColorPass {
|
||||
GX::TevColorArg x0_a;
|
||||
GX::TevColorArg x4_b;
|
||||
GX::TevColorArg x8_c;
|
||||
GX::TevColorArg xc_d;
|
||||
|
||||
constexpr ColorPass(GX::TevColorArg a, GX::TevColorArg b, GX::TevColorArg c, GX::TevColorArg d)
|
||||
: x0_a(a), x4_b(b), x8_c(c), xc_d(d) {}
|
||||
constexpr ColorPass(u32 compressedDesc)
|
||||
: x0_a(static_cast<GX::TevColorArg>(compressedDesc & 0x1F))
|
||||
, x4_b(static_cast<GX::TevColorArg>(compressedDesc >> 5 & 0x1F))
|
||||
, x8_c(static_cast<GX::TevColorArg>(compressedDesc >> 10 & 0x1F))
|
||||
, xc_d(static_cast<GX::TevColorArg>(compressedDesc >> 15 & 0x1F)) {}
|
||||
|
||||
auto operator<=>(const ColorPass&) const = default;
|
||||
};
|
||||
struct AlphaPass {
|
||||
GX::TevAlphaArg x0_a;
|
||||
GX::TevAlphaArg x4_b;
|
||||
GX::TevAlphaArg x8_c;
|
||||
GX::TevAlphaArg xc_d;
|
||||
|
||||
constexpr AlphaPass(GX::TevAlphaArg a, GX::TevAlphaArg b, GX::TevAlphaArg c, GX::TevAlphaArg d)
|
||||
: x0_a(a), x4_b(b), x8_c(c), xc_d(d) {}
|
||||
constexpr AlphaPass(u32 compressedDesc)
|
||||
: x0_a(static_cast<GX::TevAlphaArg>(compressedDesc & 0x1F))
|
||||
, x4_b(static_cast<GX::TevAlphaArg>(compressedDesc >> 5 & 0x1F))
|
||||
, x8_c(static_cast<GX::TevAlphaArg>(compressedDesc >> 10 & 0x1F))
|
||||
, xc_d(static_cast<GX::TevAlphaArg>(compressedDesc >> 15 & 0x1F)) {}
|
||||
|
||||
auto operator<=>(const AlphaPass&) const = default;
|
||||
};
|
||||
} // namespace CTevCombiners
|
||||
} // namespace metaforce
|
||||
|
||||
namespace aurora::gfx {
|
||||
|
@ -246,7 +122,6 @@ enum class ZComp : uint8_t {
|
|||
Always,
|
||||
};
|
||||
|
||||
constexpr u32 MaxLights = 8;
|
||||
struct Light {
|
||||
zeus::CVector3f pos{0.f, 0.f, 0.f};
|
||||
zeus::CVector3f dir{0.f, 0.f, -1.f};
|
||||
|
@ -265,36 +140,13 @@ void stream_end() noexcept;
|
|||
// GX state
|
||||
void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHandle& tex, float lod) noexcept;
|
||||
void unbind_texture(GX::TexMapID id) noexcept;
|
||||
void disable_tev_stage(metaforce::ERglTevStage stage) noexcept;
|
||||
void update_tev_stage(metaforce::ERglTevStage stage, const metaforce::CTevCombiners::ColorPass& colPass,
|
||||
const metaforce::CTevCombiners::AlphaPass& alphaPass,
|
||||
const metaforce::CTevCombiners::CTevOp& colorOp,
|
||||
const metaforce::CTevCombiners::CTevOp& alphaOp) noexcept;
|
||||
void set_cull_mode(metaforce::ERglCullMode mode) noexcept;
|
||||
void set_blend_mode(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor src, metaforce::ERglBlendFactor dst,
|
||||
metaforce::ERglLogicOp op) noexcept;
|
||||
void set_depth_mode(bool compare_enable, metaforce::ERglEnum func, bool update_enable) noexcept;
|
||||
void set_tev_reg_color(GX::TevRegID id, const zeus::CColor& color) noexcept;
|
||||
void set_tev_k_color(GX::TevKColorID id, const zeus::CColor& color) noexcept;
|
||||
void set_alpha_update(bool enabled) noexcept;
|
||||
void set_dst_alpha(bool enabled, float value) noexcept;
|
||||
void set_clear_color(const zeus::CColor& color) noexcept;
|
||||
void set_tev_order(GX::TevStageID id, GX::TexCoordID tcid, GX::TexMapID tmid, GX::ChannelID cid) noexcept;
|
||||
void set_tev_k_color_sel(GX::TevStageID id, GX::TevKColorSel sel) noexcept;
|
||||
void set_tev_k_alpha_sel(GX::TevStageID id, GX::TevKAlphaSel sel) noexcept;
|
||||
void set_chan_amb_color(GX::ChannelID id, const zeus::CColor& color) noexcept;
|
||||
void set_chan_mat_color(GX::ChannelID id, const zeus::CColor& color) noexcept;
|
||||
void set_chan_mat_src(GX::ChannelID id, GX::ColorSrc src) noexcept;
|
||||
|
||||
// Model state
|
||||
void set_alpha_discard(bool v);
|
||||
|
||||
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_light_state(std::bitset<MaxLights> bits) noexcept;
|
||||
void set_light_state(GX::LightMask bits) noexcept;
|
||||
void set_viewport(const zeus::CRectangle& rect, float znear, float zfar) noexcept;
|
||||
void set_scissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) noexcept;
|
||||
|
||||
|
|
|
@ -3,11 +3,5 @@
|
|||
#include "common.hpp"
|
||||
|
||||
namespace aurora::gfx::model {
|
||||
void set_vertex_buffer(const std::vector<zeus::CVector3f>* data) noexcept;
|
||||
void set_normal_buffer(const std::vector<zeus::CVector3f>* norm) noexcept;
|
||||
void set_tex0_tc_buffer(const std::vector<Vec2<float>>* tcs) noexcept; // Tex coords for TEX0
|
||||
void set_tc_buffer(const std::vector<Vec2<float>>* tcs) noexcept; // Tex coords for the TEX1-7
|
||||
|
||||
void set_vtx_desc_compressed(u32 vtxDesc) noexcept;
|
||||
void queue_surface(const u8* dlStart, u32 dlSize) noexcept;
|
||||
} // namespace aurora::gfx::model
|
||||
|
|
|
@ -301,10 +301,10 @@ void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv)
|
|||
.storeOp = wgpu::StoreOp::Store,
|
||||
.clearColor =
|
||||
{
|
||||
.r = gfx::gx::g_clearColor.r(),
|
||||
.g = gfx::gx::g_clearColor.g(),
|
||||
.b = gfx::gx::g_clearColor.b(),
|
||||
.a = gfx::gx::g_clearColor.a(),
|
||||
.r = gfx::gx::g_gxState.clearColor.r(),
|
||||
.g = gfx::gx::g_gxState.clearColor.g(),
|
||||
.b = gfx::gx::g_gxState.clearColor.b(),
|
||||
.a = gfx::gx::g_gxState.clearColor.a(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -4,7 +4,119 @@
|
|||
#include "common.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
using aurora::gfx::gx::g_gxState;
|
||||
static logvisor::Module Log("aurora::gx");
|
||||
|
||||
void GXSetNumChans(u8 num) noexcept { g_gxState.numChans = num; }
|
||||
void GXSetNumIndStages(u8 num) noexcept { g_gxState.numIndStages = num; }
|
||||
void GXSetNumTevStages(u8 num) noexcept { g_gxState.numTevStages = num; }
|
||||
void GXSetNumTexGens(u8 num) noexcept { g_gxState.numTexGens = num; }
|
||||
void GXSetTevAlphaIn(GX::TevStageID stageId, GX::TevAlphaArg a, GX::TevAlphaArg b, GX::TevAlphaArg c,
|
||||
GX::TevAlphaArg d) noexcept {
|
||||
g_gxState.tevStages[stageId].alphaPass = {a, b, c, d};
|
||||
}
|
||||
void GXSetTevAlphaOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, bool clamp,
|
||||
GX::TevRegID outReg) noexcept {
|
||||
g_gxState.tevStages[stageId].alphaOp = {op, bias, scale, outReg, clamp};
|
||||
}
|
||||
void GXSetTevColorIn(GX::TevStageID stageId, GX::TevColorArg a, GX::TevColorArg b, GX::TevColorArg c,
|
||||
GX::TevColorArg d) noexcept {
|
||||
g_gxState.tevStages[stageId].colorPass = {a, b, c, d};
|
||||
}
|
||||
void GXSetTevColorOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, bool clamp,
|
||||
GX::TevRegID outReg) noexcept {
|
||||
g_gxState.tevStages[stageId].colorOp = {op, bias, scale, outReg, clamp};
|
||||
}
|
||||
void GXSetCullMode(GX::CullMode mode) noexcept { g_gxState.cullMode = mode; }
|
||||
void GXSetBlendMode(GX::BlendMode mode, GX::BlendFactor src, GX::BlendFactor dst, GX::LogicOp op) noexcept {
|
||||
g_gxState.blendMode = mode;
|
||||
g_gxState.blendFacSrc = src;
|
||||
g_gxState.blendFacDst = dst;
|
||||
g_gxState.blendOp = op;
|
||||
}
|
||||
void GXSetZMode(bool compare_enable, GX::Compare func, bool update_enable) noexcept {
|
||||
g_gxState.depthCompare = compare_enable;
|
||||
g_gxState.depthFunc = func;
|
||||
g_gxState.depthUpdate = update_enable;
|
||||
}
|
||||
void GXSetTevColor(GX::TevRegID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::TEVREG0 || id > GX::TEVREG2) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad tevreg {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.colorRegs[id - 1] = color;
|
||||
}
|
||||
void GXSetTevKColor(GX::TevKColorID id, const zeus::CColor& color) noexcept {
|
||||
if (id >= GX::MAX_KCOLOR) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad kcolor {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.kcolors[id] = color;
|
||||
}
|
||||
void GXSetAlphaUpdate(bool enabled) noexcept { g_gxState.alphaUpdate = enabled; }
|
||||
void GXSetDstAlpha(bool enabled, float value) noexcept {
|
||||
if (enabled) {
|
||||
g_gxState.dstAlpha = value;
|
||||
} else {
|
||||
g_gxState.dstAlpha.reset();
|
||||
}
|
||||
}
|
||||
void GXSetCopyClear(const zeus::CColor& color, float depth) noexcept { g_gxState.clearColor = color; }
|
||||
void GXSetTevOrder(GX::TevStageID id, GX::TexCoordID tcid, GX::TexMapID tmid, GX::ChannelID cid) noexcept {
|
||||
auto& stage = g_gxState.tevStages[id];
|
||||
stage.texCoordId = tcid;
|
||||
stage.texMapId = tmid;
|
||||
stage.channelId = cid;
|
||||
}
|
||||
void GXSetTevKColorSel(GX::TevStageID id, GX::TevKColorSel sel) noexcept { g_gxState.tevStages[id].kcSel = sel; }
|
||||
void GXSetTevKAlphaSel(GX::TevStageID id, GX::TevKAlphaSel sel) noexcept { g_gxState.tevStages[id].kaSel = sel; }
|
||||
void GXSetChanAmbColor(GX::ChannelID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.colorChannelState[id - GX::COLOR0A0].ambColor = color;
|
||||
}
|
||||
void GXSetChanMatColor(GX::ChannelID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.colorChannelState[id - GX::COLOR0A0].matColor = color;
|
||||
}
|
||||
void GXSetChanCtrl(GX::ChannelID id, bool lightingEnabled, GX::ColorSrc ambSrc, GX::ColorSrc matSrc,
|
||||
GX::LightMask lightState, GX::DiffuseFn diffFn, GX::AttnFn attnFn) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
if (diffFn != GX::DF_NONE && diffFn != GX::DF_CLAMP) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled diffuse fn {}"), diffFn);
|
||||
unreachable();
|
||||
}
|
||||
if (attnFn != GX::AF_NONE && attnFn != GX::AF_SPOT) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled attn fn {}"), attnFn);
|
||||
unreachable();
|
||||
}
|
||||
u32 idx = id - GX::COLOR0A0;
|
||||
auto& chan = g_gxState.colorChannelConfig[idx];
|
||||
chan.lightingEnabled = lightingEnabled;
|
||||
chan.ambSrc = ambSrc;
|
||||
chan.matSrc = matSrc;
|
||||
g_gxState.colorChannelState[idx].lightState = lightState;
|
||||
}
|
||||
void GXSetAlphaCompare(GX::Compare comp0, float ref0, GX::AlphaOp op, GX::Compare comp1, float ref1) noexcept {
|
||||
if (comp0 == GX::ALWAYS && comp1 == GX::ALWAYS) {
|
||||
g_gxState.alphaDiscard.reset();
|
||||
} else if (comp0 == GX::GEQUAL && comp1 == GX::NEVER) {
|
||||
g_gxState.alphaDiscard = ref0;
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("GXSetAlphaCompare: unknown operands"));
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
void GXSetVtxDescv(GX::VtxDescList* list) noexcept;
|
||||
|
||||
namespace aurora::gfx {
|
||||
static logvisor::Module Log("aurora::gfx::gx");
|
||||
|
@ -14,51 +126,13 @@ extern std::mutex g_pipelineMutex;
|
|||
|
||||
// GX state
|
||||
void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHandle& tex, float lod) noexcept {
|
||||
gx::g_textures[static_cast<size_t>(id)] = {tex, clamp, lod};
|
||||
gx::g_gxState.textures[static_cast<size_t>(id)] = {tex, clamp, lod};
|
||||
}
|
||||
void unbind_texture(GX::TexMapID id) noexcept { gx::g_textures[static_cast<size_t>(id)].reset(); }
|
||||
|
||||
void set_cull_mode(metaforce::ERglCullMode mode) noexcept { gx::g_cullMode = mode; }
|
||||
void set_blend_mode(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor src, metaforce::ERglBlendFactor dst,
|
||||
metaforce::ERglLogicOp op) noexcept {
|
||||
gx::g_blendMode = mode;
|
||||
gx::g_blendFacSrc = src;
|
||||
gx::g_blendFacDst = dst;
|
||||
gx::g_blendOp = op;
|
||||
}
|
||||
void set_depth_mode(bool compare_enable, metaforce::ERglEnum func, bool update_enable) noexcept {
|
||||
gx::g_depthCompare = compare_enable;
|
||||
gx::g_depthFunc = func;
|
||||
gx::g_depthUpdate = update_enable;
|
||||
}
|
||||
void set_tev_reg_color(GX::TevRegID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::TEVREG0 || id > GX::TEVREG2) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_reg_color: bad reg {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
gx::g_colorRegs[id - 1] = color;
|
||||
}
|
||||
void set_tev_k_color(GX::TevKColorID id, const zeus::CColor& color) noexcept {
|
||||
if (id >= GX::MAX_KCOLOR) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_k_color: bad reg {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
gx::g_kcolors[id] = color;
|
||||
}
|
||||
void set_alpha_update(bool enabled) noexcept { gx::g_alphaUpdate = enabled; }
|
||||
void set_dst_alpha(bool enabled, float value) noexcept {
|
||||
if (enabled) {
|
||||
gx::g_dstAlpha = value;
|
||||
} else {
|
||||
gx::g_dstAlpha.reset();
|
||||
}
|
||||
}
|
||||
void set_clear_color(const zeus::CColor& color) noexcept { gx::g_clearColor = color; }
|
||||
void set_alpha_discard(bool v) { gx::g_alphaDiscard = v; }
|
||||
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_mv = mv;
|
||||
gx::g_mvInv = mv_inv;
|
||||
gx::g_gxState.mv = mv;
|
||||
gx::g_gxState.mvInv = mv_inv;
|
||||
}
|
||||
constexpr zeus::CMatrix4f DepthCorrect{
|
||||
// clang-format off
|
||||
|
@ -68,133 +142,44 @@ constexpr zeus::CMatrix4f DepthCorrect{
|
|||
0.f, 0.f, 0.f, 1.f,
|
||||
// clang-format on
|
||||
};
|
||||
void update_projection(const zeus::CMatrix4f& proj) noexcept { gx::g_proj = DepthCorrect * proj; }
|
||||
void update_fog_state(const metaforce::CFogState& state) noexcept { gx::g_fogState = state; }
|
||||
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 disable_tev_stage(metaforce::ERglTevStage stage) noexcept { gx::g_tevStages[static_cast<size_t>(stage)].reset(); }
|
||||
void update_tev_stage(metaforce::ERglTevStage stage, const metaforce::CTevCombiners::ColorPass& colPass,
|
||||
const metaforce::CTevCombiners::AlphaPass& alphaPass,
|
||||
const metaforce::CTevCombiners::CTevOp& colorOp,
|
||||
const metaforce::CTevCombiners::CTevOp& alphaOp) noexcept {
|
||||
gx::g_tevStages[static_cast<size_t>(stage)] = {colPass, alphaPass, colorOp, alphaOp};
|
||||
void load_light(GX::LightID id, const Light& light) noexcept { gx::g_gxState.lights[std::log2<u32>(id)] = light; }
|
||||
void load_light_ambient(GX::LightID id, const zeus::CColor& ambient) noexcept {
|
||||
gx::g_gxState.lights[std::log2<u32>(id)] = ambient;
|
||||
}
|
||||
|
||||
void set_tev_order(GX::TevStageID id, GX::TexCoordID tcid, GX::TexMapID tmid, GX::ChannelID cid) noexcept {
|
||||
auto& stage = gx::g_tevStages[id];
|
||||
if (!stage) {
|
||||
// Log.report(logvisor::Fatal, FMT_STRING("set_tev_order: disabled stage {}"), id);
|
||||
// unreachable();
|
||||
return;
|
||||
}
|
||||
stage->texCoordId = tcid;
|
||||
stage->texMapId = tmid;
|
||||
stage->channelId = cid;
|
||||
}
|
||||
void set_tev_k_color_sel(GX::TevStageID id, GX::TevKColorSel sel) noexcept {
|
||||
auto& stage = gx::g_tevStages[id];
|
||||
if (!stage) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_k_color_sel: disabled stage {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
stage->kcSel = sel;
|
||||
}
|
||||
void set_tev_k_alpha_sel(GX::TevStageID id, GX::TevKAlphaSel sel) noexcept {
|
||||
auto& stage = gx::g_tevStages[id];
|
||||
if (!stage) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_k_alpha_sel: disabled stage {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
stage->kaSel = sel;
|
||||
}
|
||||
|
||||
void set_chan_amb_color(GX::ChannelID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_chan_amb_color: invalid channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
gx::g_colorChannels[id - GX::COLOR0A0].ambColor = color;
|
||||
}
|
||||
void set_chan_mat_color(GX::ChannelID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_chan_mat_color: invalid channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
gx::g_colorChannels[id - GX::COLOR0A0].matColor = color;
|
||||
}
|
||||
void set_chan_mat_src(GX::ChannelID id, GX::ColorSrc src) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_chan_mat_src: invalid channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
gx::g_colorChannels[id - GX::COLOR0A0].matSrc = src;
|
||||
}
|
||||
|
||||
static inline u8 light_idx(GX::LightID id) {
|
||||
#ifdef _MSC_VER
|
||||
unsigned long r = 0;
|
||||
_BitScanForward(&r, id);
|
||||
return r;
|
||||
#else
|
||||
return __builtin_ctz(id);
|
||||
#endif
|
||||
}
|
||||
void load_light(GX::LightID id, const Light& light) noexcept { gx::g_lights[light_idx(id)] = light; }
|
||||
void load_light_ambient(GX::LightID id, const zeus::CColor& ambient) noexcept { gx::g_lights[light_idx(id)] = ambient; }
|
||||
void set_light_state(std::bitset<MaxLights> bits) noexcept { gx::g_lightState = bits; }
|
||||
void set_light_state(GX::LightMask bits) noexcept { gx::g_gxState.lightState = bits; }
|
||||
|
||||
namespace gx {
|
||||
using gpu::g_device;
|
||||
using gpu::g_graphicsConfig;
|
||||
|
||||
zeus::CMatrix4f g_mv;
|
||||
zeus::CMatrix4f g_mvInv;
|
||||
zeus::CMatrix4f g_proj;
|
||||
metaforce::CFogState g_fogState;
|
||||
metaforce::ERglCullMode g_cullMode;
|
||||
metaforce::ERglBlendMode g_blendMode;
|
||||
metaforce::ERglBlendFactor g_blendFacSrc;
|
||||
metaforce::ERglBlendFactor g_blendFacDst;
|
||||
metaforce::ERglLogicOp g_blendOp;
|
||||
bool g_depthCompare;
|
||||
bool g_depthUpdate;
|
||||
metaforce::ERglEnum g_depthFunc;
|
||||
std::array<zeus::CColor, 3> g_colorRegs;
|
||||
std::array<zeus::CColor, GX::MAX_KCOLOR> g_kcolors;
|
||||
bool g_alphaUpdate;
|
||||
std::optional<float> g_dstAlpha;
|
||||
zeus::CColor g_clearColor = zeus::skClear;
|
||||
bool g_alphaDiscard;
|
||||
GXState g_gxState;
|
||||
|
||||
std::array<SChannelState, 2> g_colorChannels;
|
||||
std::array<LightVariant, MaxLights> g_lights;
|
||||
std::bitset<MaxLights> g_lightState;
|
||||
const TextureBind& get_texture(GX::TexMapID id) noexcept { return g_gxState.textures[static_cast<size_t>(id)]; }
|
||||
|
||||
std::array<std::optional<STevStage>, maxTevStages> g_tevStages;
|
||||
std::array<TextureBind, maxTextures> g_textures;
|
||||
|
||||
const gx::TextureBind& get_texture(GX::TexMapID id) noexcept { return gx::g_textures[static_cast<size_t>(id)]; }
|
||||
|
||||
static inline wgpu::BlendFactor to_blend_factor(metaforce::ERglBlendFactor fac) {
|
||||
static inline wgpu::BlendFactor to_blend_factor(GX::BlendFactor fac) {
|
||||
switch (fac) {
|
||||
case metaforce::ERglBlendFactor::Zero:
|
||||
case GX::BL_ZERO:
|
||||
return wgpu::BlendFactor::Zero;
|
||||
case metaforce::ERglBlendFactor::One:
|
||||
case GX::BL_ONE:
|
||||
return wgpu::BlendFactor::One;
|
||||
case metaforce::ERglBlendFactor::SrcColor:
|
||||
case GX::BL_SRCCLR:
|
||||
return wgpu::BlendFactor::Src;
|
||||
case metaforce::ERglBlendFactor::InvSrcColor:
|
||||
case GX::BL_INVSRCCLR:
|
||||
return wgpu::BlendFactor::OneMinusSrc;
|
||||
case metaforce::ERglBlendFactor::SrcAlpha:
|
||||
case GX::BL_SRCALPHA:
|
||||
return wgpu::BlendFactor::SrcAlpha;
|
||||
case metaforce::ERglBlendFactor::InvSrcAlpha:
|
||||
case GX::BL_INVSRCALPHA:
|
||||
return wgpu::BlendFactor::OneMinusSrcAlpha;
|
||||
case metaforce::ERglBlendFactor::DstAlpha:
|
||||
case GX::BL_DSTALPHA:
|
||||
return wgpu::BlendFactor::DstAlpha;
|
||||
case metaforce::ERglBlendFactor::InvDstAlpha:
|
||||
case GX::BL_INVDSTALPHA:
|
||||
return wgpu::BlendFactor::OneMinusDstAlpha;
|
||||
case metaforce::ERglBlendFactor::DstColor:
|
||||
case GX::BL_DSTCLR:
|
||||
return wgpu::BlendFactor::Dst;
|
||||
case metaforce::ERglBlendFactor::InvDstColor:
|
||||
case GX::BL_INVDSTCLR:
|
||||
return wgpu::BlendFactor::OneMinusDst;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid blend factor {}"), fac);
|
||||
|
@ -202,23 +187,23 @@ static inline wgpu::BlendFactor to_blend_factor(metaforce::ERglBlendFactor fac)
|
|||
}
|
||||
}
|
||||
|
||||
static inline wgpu::CompareFunction to_compare_function(metaforce::ERglEnum func) {
|
||||
static inline wgpu::CompareFunction to_compare_function(GX::Compare func) {
|
||||
switch (func) {
|
||||
case metaforce::ERglEnum::Never:
|
||||
case GX::NEVER:
|
||||
return wgpu::CompareFunction::Never;
|
||||
case metaforce::ERglEnum::Less:
|
||||
case GX::LESS:
|
||||
return wgpu::CompareFunction::Less;
|
||||
case metaforce::ERglEnum::Equal:
|
||||
case GX::EQUAL:
|
||||
return wgpu::CompareFunction::Equal;
|
||||
case metaforce::ERglEnum::LEqual:
|
||||
case GX::LEQUAL:
|
||||
return wgpu::CompareFunction::LessEqual;
|
||||
case metaforce::ERglEnum::Greater:
|
||||
case GX::GREATER:
|
||||
return wgpu::CompareFunction::Greater;
|
||||
case metaforce::ERglEnum::NEqual:
|
||||
case GX::NEQUAL:
|
||||
return wgpu::CompareFunction::NotEqual;
|
||||
case metaforce::ERglEnum::GEqual:
|
||||
case GX::GEQUAL:
|
||||
return wgpu::CompareFunction::GreaterEqual;
|
||||
case metaforce::ERglEnum::Always:
|
||||
case GX::ALWAYS:
|
||||
return wgpu::CompareFunction::Always;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid depth fn {}"), func);
|
||||
|
@ -226,10 +211,10 @@ static inline wgpu::CompareFunction to_compare_function(metaforce::ERglEnum func
|
|||
}
|
||||
}
|
||||
|
||||
static inline wgpu::BlendState to_blend_state(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor srcFac,
|
||||
metaforce::ERglBlendFactor dstFac, std::optional<float> dstAlpha) {
|
||||
if (mode != metaforce::ERglBlendMode::Blend) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("How to {}?"), magic_enum::enum_name(mode));
|
||||
static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFactor srcFac, GX::BlendFactor dstFac,
|
||||
std::optional<float> dstAlpha) {
|
||||
if (mode != GX::BM_BLEND) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("How to {}?"), mode);
|
||||
}
|
||||
const auto colorBlendComponent = wgpu::BlendComponent{
|
||||
.operation = wgpu::BlendOperation::Add,
|
||||
|
@ -258,7 +243,7 @@ static inline wgpu::ColorWriteMask to_write_mask(bool alphaUpdate) {
|
|||
return writeMask;
|
||||
}
|
||||
|
||||
static inline wgpu::PrimitiveState to_primitive_state(GX::Primitive gx_prim, metaforce::ERglCullMode e_cullMode) {
|
||||
static inline wgpu::PrimitiveState to_primitive_state(GX::Primitive gx_prim, GX::CullMode gx_cullMode) {
|
||||
wgpu::PrimitiveTopology primitive = wgpu::PrimitiveTopology::TriangleList;
|
||||
switch (gx_prim) {
|
||||
case GX::TRIANGLES:
|
||||
|
@ -272,14 +257,17 @@ static inline wgpu::PrimitiveState to_primitive_state(GX::Primitive gx_prim, met
|
|||
}
|
||||
wgpu::FrontFace frontFace = wgpu::FrontFace::CCW;
|
||||
wgpu::CullMode cullMode = wgpu::CullMode::None;
|
||||
switch (e_cullMode) {
|
||||
case metaforce::ERglCullMode::Front:
|
||||
switch (gx_cullMode) {
|
||||
case GX::CULL_FRONT:
|
||||
frontFace = wgpu::FrontFace::CW;
|
||||
cullMode = wgpu::CullMode::Front;
|
||||
break;
|
||||
case metaforce::ERglCullMode::Back:
|
||||
case GX::CULL_BACK:
|
||||
cullMode = wgpu::CullMode::Back;
|
||||
break;
|
||||
case GX::CULL_ALL:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Unsupported cull mode {}"), gx_cullMode);
|
||||
unreachable();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -345,29 +333,24 @@ wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderIn
|
|||
|
||||
ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive,
|
||||
const BindGroupRanges& ranges) noexcept {
|
||||
for (size_t idx = 0; const auto& item : g_tevStages) {
|
||||
// Copy until disabled TEV stage (indicating end)
|
||||
if (!item) {
|
||||
break;
|
||||
}
|
||||
config.shaderConfig.tevStages[idx++] = item;
|
||||
for (size_t i = 0; i < g_gxState.numTevStages; ++i) {
|
||||
config.shaderConfig.tevStages[i] = g_gxState.tevStages[i];
|
||||
}
|
||||
config.shaderConfig.channelMatSrcs[0] = g_colorChannels[0].matSrc;
|
||||
config.shaderConfig.channelMatSrcs[1] = g_colorChannels[1].matSrc;
|
||||
config.shaderConfig.alphaDiscard = g_alphaDiscard;
|
||||
config.shaderConfig.colorChannels = g_gxState.colorChannelConfig;
|
||||
config.shaderConfig.alphaDiscard = g_gxState.alphaDiscard;
|
||||
config = {
|
||||
.shaderConfig = config.shaderConfig,
|
||||
.primitive = primitive,
|
||||
.depthFunc = g_depthFunc,
|
||||
.cullMode = g_cullMode,
|
||||
.blendMode = g_blendMode,
|
||||
.blendFacSrc = g_blendFacSrc,
|
||||
.blendFacDst = g_blendFacDst,
|
||||
.blendOp = g_blendOp,
|
||||
.dstAlpha = g_dstAlpha,
|
||||
.depthCompare = g_depthCompare,
|
||||
.depthUpdate = g_depthUpdate,
|
||||
.alphaUpdate = g_alphaUpdate,
|
||||
.depthFunc = g_gxState.depthFunc,
|
||||
.cullMode = g_gxState.cullMode,
|
||||
.blendMode = g_gxState.blendMode,
|
||||
.blendFacSrc = g_gxState.blendFacSrc,
|
||||
.blendFacDst = g_gxState.blendFacDst,
|
||||
.blendOp = g_gxState.blendOp,
|
||||
.dstAlpha = g_gxState.dstAlpha,
|
||||
.depthCompare = g_gxState.depthCompare,
|
||||
.depthUpdate = g_gxState.depthUpdate,
|
||||
.alphaUpdate = g_gxState.alphaUpdate,
|
||||
};
|
||||
// TODO separate shader info from build_shader for async
|
||||
{
|
||||
|
@ -381,51 +364,51 @@ ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primit
|
|||
Range build_uniform(const ShaderInfo& info) noexcept {
|
||||
auto [buf, range] = map_uniform(info.uniformSize);
|
||||
{
|
||||
buf.append(&g_mv, 64);
|
||||
buf.append(&g_mvInv, 64);
|
||||
buf.append(&g_proj, 64);
|
||||
buf.append(&g_gxState.mv, 64);
|
||||
buf.append(&g_gxState.mvInv, 64);
|
||||
buf.append(&g_gxState.proj, 64);
|
||||
}
|
||||
for (int i = 0; i < info.usesTevReg.size(); ++i) {
|
||||
if (!info.usesTevReg.test(i)) {
|
||||
continue;
|
||||
}
|
||||
buf.append(&g_colorRegs[i], 16);
|
||||
}
|
||||
if (info.sampledColorChannels.any()) {
|
||||
zeus::CColor ambient = zeus::skClear;
|
||||
int addedLights = 0;
|
||||
for (int i = 0; i < g_lightState.size(); ++i) {
|
||||
if (!g_lightState.test(i)) {
|
||||
continue;
|
||||
}
|
||||
const auto& variant = g_lights[i];
|
||||
if (std::holds_alternative<zeus::CColor>(variant)) {
|
||||
ambient += std::get<zeus::CColor>(variant);
|
||||
} else if (std::holds_alternative<Light>(variant)) {
|
||||
static_assert(sizeof(Light) == 80);
|
||||
buf.append(&std::get<Light>(variant), sizeof(Light));
|
||||
++addedLights;
|
||||
}
|
||||
}
|
||||
constexpr Light emptyLight{};
|
||||
for (int i = addedLights; i < MaxLights; ++i) {
|
||||
buf.append(&emptyLight, sizeof(Light));
|
||||
}
|
||||
buf.append(&ambient, 16);
|
||||
// fmt::print(FMT_STRING("Added lights: {}, ambient: {},{},{},{}\n"), addedLights, ambient.r(), ambient.g(), ambient.b(), ambient.a());
|
||||
buf.append(&g_gxState.colorRegs[i], 16);
|
||||
}
|
||||
for (int i = 0; i < info.sampledColorChannels.size(); ++i) {
|
||||
if (!info.sampledColorChannels.test(i)) {
|
||||
continue;
|
||||
}
|
||||
buf.append(&g_colorChannels[i].ambColor, 16);
|
||||
buf.append(&g_colorChannels[i].matColor, 16);
|
||||
buf.append(&g_gxState.colorChannelState[i].ambColor, 16);
|
||||
buf.append(&g_gxState.colorChannelState[i].matColor, 16);
|
||||
|
||||
if (g_gxState.colorChannelConfig[i].lightingEnabled) {
|
||||
zeus::CColor ambient = zeus::skClear;
|
||||
int addedLights = 0;
|
||||
for (int li = 0; li < g_gxState.lightState.size(); ++li) {
|
||||
if (!g_gxState.lightState.test(li)) {
|
||||
continue;
|
||||
}
|
||||
const auto& variant = g_gxState.lights[li];
|
||||
if (std::holds_alternative<zeus::CColor>(variant)) {
|
||||
ambient += std::get<zeus::CColor>(variant);
|
||||
} else if (std::holds_alternative<Light>(variant)) {
|
||||
static_assert(sizeof(Light) == 80);
|
||||
buf.append(&std::get<Light>(variant), sizeof(Light));
|
||||
++addedLights;
|
||||
}
|
||||
}
|
||||
constexpr Light emptyLight{};
|
||||
for (int li = addedLights; li < GX::MaxLights; ++li) {
|
||||
buf.append(&emptyLight, sizeof(Light));
|
||||
}
|
||||
buf.append(&ambient, 16);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < info.sampledKcolors.size(); ++i) {
|
||||
if (!info.sampledKcolors.test(i)) {
|
||||
for (int i = 0; i < info.sampledKColors.size(); ++i) {
|
||||
if (!info.sampledKColors.test(i)) {
|
||||
continue;
|
||||
}
|
||||
buf.append(&g_kcolors[i], 16);
|
||||
buf.append(&g_gxState.kcolors[i], 16);
|
||||
}
|
||||
for (int i = 0; i < info.sampledTextures.size(); ++i) {
|
||||
if (!info.sampledTextures.test(i)) {
|
||||
|
@ -480,13 +463,13 @@ GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& confi
|
|||
.size = ranges.packedTcDataRange.second - ranges.packedTcDataRange.first,
|
||||
},
|
||||
};
|
||||
std::array<wgpu::BindGroupEntry, maxTextures> samplerEntries;
|
||||
std::array<wgpu::BindGroupEntry, maxTextures> textureEntries;
|
||||
std::array<wgpu::BindGroupEntry, MaxTextures> samplerEntries;
|
||||
std::array<wgpu::BindGroupEntry, MaxTextures> textureEntries;
|
||||
for (u32 texIdx = 0, i = 0; texIdx < info.sampledTextures.size(); ++texIdx) {
|
||||
if (!info.sampledTextures.test(texIdx)) {
|
||||
continue;
|
||||
}
|
||||
const auto& tex = g_textures[texIdx];
|
||||
const auto& tex = g_gxState.textures[texIdx];
|
||||
if (!tex) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unbound texture {}"), texIdx);
|
||||
unreachable();
|
||||
|
@ -592,8 +575,8 @@ GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const Shader
|
|||
out.samplerLayout = sl;
|
||||
out.textureLayout = tl;
|
||||
} else {
|
||||
std::array<wgpu::BindGroupLayoutEntry, maxTextures> samplerEntries;
|
||||
std::array<wgpu::BindGroupLayoutEntry, maxTextures> textureEntries;
|
||||
std::array<wgpu::BindGroupLayoutEntry, MaxTextures> samplerEntries;
|
||||
std::array<wgpu::BindGroupLayoutEntry, MaxTextures> textureEntries;
|
||||
for (u32 i = 0; i < textureCount; ++i) {
|
||||
samplerEntries[i] = {
|
||||
.binding = i,
|
||||
|
@ -637,7 +620,7 @@ void shutdown() noexcept {
|
|||
// TODO we should probably store this all in g_state.gx instead
|
||||
sUniformBindGroupLayouts.clear();
|
||||
sTextureBindGroupLayouts.clear();
|
||||
g_textures.fill({});
|
||||
g_gxState.textures.fill({});
|
||||
g_gxCachedShaders.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,51 +5,36 @@
|
|||
#include <variant>
|
||||
|
||||
namespace aurora::gfx::gx {
|
||||
extern zeus::CMatrix4f g_mv;
|
||||
extern zeus::CMatrix4f g_mvInv;
|
||||
extern zeus::CMatrix4f g_proj;
|
||||
extern metaforce::CFogState g_fogState;
|
||||
extern metaforce::ERglCullMode g_cullMode;
|
||||
extern metaforce::ERglBlendMode g_blendMode;
|
||||
extern metaforce::ERglBlendFactor g_blendFacSrc;
|
||||
extern metaforce::ERglBlendFactor g_blendFacDst;
|
||||
extern metaforce::ERglLogicOp g_blendOp;
|
||||
extern bool g_depthCompare;
|
||||
extern bool g_depthUpdate;
|
||||
extern metaforce::ERglEnum g_depthFunc;
|
||||
extern std::array<zeus::CColor, 3> g_colorRegs;
|
||||
extern std::array<zeus::CColor, GX::MAX_KCOLOR> g_kcolors;
|
||||
extern bool g_alphaUpdate;
|
||||
extern std::optional<float> g_dstAlpha;
|
||||
extern zeus::CColor g_clearColor;
|
||||
extern bool g_alphaDiscard;
|
||||
constexpr u32 MaxTextures = GX::MAX_TEXMAP;
|
||||
constexpr u32 MaxTevStages = GX::MAX_TEVSTAGE;
|
||||
constexpr u32 MaxColorChannels = 2; // COLOR0A0, COLOR1A1
|
||||
constexpr u32 MaxTevRegs = 3; // TEVREG0-2
|
||||
constexpr u32 MaxKColors = GX::MAX_KCOLOR;
|
||||
|
||||
struct SChannelState {
|
||||
zeus::CColor matColor;
|
||||
zeus::CColor ambColor;
|
||||
GX::ColorSrc matSrc;
|
||||
template <typename Arg, Arg Default>
|
||||
struct TevPass {
|
||||
Arg a = Default;
|
||||
Arg b = Default;
|
||||
Arg c = Default;
|
||||
Arg d = Default;
|
||||
};
|
||||
extern std::array<SChannelState, 2> g_colorChannels;
|
||||
using LightVariant = std::variant<std::monostate, Light, zeus::CColor>;
|
||||
extern std::array<LightVariant, MaxLights> g_lights;
|
||||
extern std::bitset<MaxLights> g_lightState;
|
||||
|
||||
struct STevStage {
|
||||
metaforce::CTevCombiners::ColorPass colorPass;
|
||||
metaforce::CTevCombiners::AlphaPass alphaPass;
|
||||
metaforce::CTevCombiners::CTevOp colorOp;
|
||||
metaforce::CTevCombiners::CTevOp alphaOp;
|
||||
struct TevOp {
|
||||
GX::TevOp op = GX::TevOp::TEV_ADD;
|
||||
GX::TevBias bias = GX::TevBias::TB_ZERO;
|
||||
GX::TevScale scale = GX::TevScale::CS_SCALE_1;
|
||||
GX::TevRegID outReg = GX::TevRegID::TEVPREV;
|
||||
bool clamp = true;
|
||||
};
|
||||
struct TevStage {
|
||||
TevPass<GX::TevColorArg, GX::CC_ZERO> colorPass;
|
||||
TevPass<GX::TevAlphaArg, GX::CA_ZERO> alphaPass;
|
||||
TevOp colorOp;
|
||||
TevOp alphaOp;
|
||||
GX::TevKColorSel kcSel = GX::TEV_KCSEL_1;
|
||||
GX::TevKAlphaSel kaSel = GX::TEV_KASEL_1;
|
||||
GX::TexCoordID texCoordId = GX::TEXCOORD_NULL;
|
||||
GX::TexMapID texMapId = GX::TEXMAP_NULL;
|
||||
GX::ChannelID channelId = GX::COLOR_NULL;
|
||||
|
||||
constexpr STevStage(const metaforce::CTevCombiners::ColorPass& colPass,
|
||||
const metaforce::CTevCombiners::AlphaPass& alphaPass,
|
||||
const metaforce::CTevCombiners::CTevOp& colorOp,
|
||||
const metaforce::CTevCombiners::CTevOp& alphaOp) noexcept
|
||||
: colorPass(colPass), alphaPass(alphaPass), colorOp(colorOp), alphaOp(alphaOp) {}
|
||||
};
|
||||
struct TextureBind {
|
||||
aurora::gfx::TextureHandle handle;
|
||||
|
@ -63,32 +48,72 @@ struct TextureBind {
|
|||
[[nodiscard]] wgpu::SamplerDescriptor get_descriptor() const noexcept;
|
||||
operator bool() const noexcept { return handle; }
|
||||
};
|
||||
// For shader generation
|
||||
struct ColorChannelConfig {
|
||||
GX::ColorSrc matSrc = GX::SRC_REG;
|
||||
GX::ColorSrc ambSrc = GX::SRC_REG;
|
||||
bool lightingEnabled = false;
|
||||
};
|
||||
// For uniform generation
|
||||
struct ColorChannelState {
|
||||
zeus::CColor matColor = zeus::skClear;
|
||||
zeus::CColor ambColor = zeus::skClear;
|
||||
GX::LightMask lightState;
|
||||
};
|
||||
using LightVariant = std::variant<std::monostate, Light, zeus::CColor>;
|
||||
|
||||
constexpr u32 maxTevStages = GX::MAX_TEVSTAGE;
|
||||
extern std::array<std::optional<STevStage>, maxTevStages> g_tevStages;
|
||||
constexpr u32 maxTextures = 8;
|
||||
extern std::array<TextureBind, maxTextures> g_textures;
|
||||
struct GXState {
|
||||
zeus::CMatrix4f mv;
|
||||
zeus::CMatrix4f mvInv;
|
||||
zeus::CMatrix4f proj;
|
||||
metaforce::CFogState fogState;
|
||||
GX::CullMode cullMode = GX::CULL_BACK;
|
||||
GX::BlendMode blendMode = GX::BM_NONE;
|
||||
GX::BlendFactor blendFacSrc = GX::BL_SRCALPHA;
|
||||
GX::BlendFactor blendFacDst = GX::BL_INVSRCALPHA;
|
||||
GX::LogicOp blendOp = GX::LO_CLEAR;
|
||||
GX::Compare depthFunc = GX::LEQUAL;
|
||||
zeus::CColor clearColor = zeus::skBlack;
|
||||
std::optional<float> dstAlpha;
|
||||
std::optional<float> alphaDiscard;
|
||||
std::array<zeus::CColor, MaxTevRegs> colorRegs;
|
||||
std::array<zeus::CColor, GX::MAX_KCOLOR> kcolors;
|
||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannelConfig;
|
||||
std::array<ColorChannelState, MaxColorChannels> colorChannelState;
|
||||
std::array<LightVariant, GX::MaxLights> lights;
|
||||
std::array<TevStage, MaxTevStages> tevStages;
|
||||
std::array<TextureBind, MaxTextures> textures;
|
||||
GX::LightMask lightState;
|
||||
bool depthCompare = true;
|
||||
bool depthUpdate = true;
|
||||
bool alphaUpdate = true;
|
||||
u8 numChans = 0;
|
||||
u8 numIndStages = 0;
|
||||
u8 numTevStages = 0;
|
||||
u8 numTexGens = 0;
|
||||
};
|
||||
extern GXState g_gxState;
|
||||
|
||||
static inline Mat4x4<float> get_combined_matrix() noexcept { return g_proj * g_mv; }
|
||||
static inline Mat4x4<float> get_combined_matrix() noexcept { return g_gxState.proj * g_gxState.mv; }
|
||||
|
||||
void shutdown() noexcept;
|
||||
const TextureBind& get_texture(GX::TexMapID id) noexcept;
|
||||
|
||||
struct ShaderConfig {
|
||||
std::array<std::optional<STevStage>, maxTevStages> tevStages;
|
||||
std::array<GX::ColorSrc, 2> channelMatSrcs;
|
||||
bool alphaDiscard = false;
|
||||
std::array<std::optional<TevStage>, MaxTevStages> tevStages;
|
||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannels;
|
||||
std::optional<float> alphaDiscard;
|
||||
bool denormalizedVertexAttributes = false;
|
||||
bool denormalizedHasNrm = false; // TODO this is a hack
|
||||
};
|
||||
struct PipelineConfig {
|
||||
ShaderConfig shaderConfig;
|
||||
GX::Primitive primitive;
|
||||
metaforce::ERglEnum depthFunc;
|
||||
metaforce::ERglCullMode cullMode;
|
||||
metaforce::ERglBlendMode blendMode;
|
||||
metaforce::ERglBlendFactor blendFacSrc, blendFacDst;
|
||||
metaforce::ERglLogicOp blendOp;
|
||||
GX::Compare depthFunc;
|
||||
GX::CullMode cullMode;
|
||||
GX::BlendMode blendMode;
|
||||
GX::BlendFactor blendFacSrc, blendFacDst;
|
||||
GX::LogicOp blendOp;
|
||||
std::optional<float> dstAlpha;
|
||||
bool depthCompare, depthUpdate, alphaUpdate;
|
||||
};
|
||||
|
@ -105,10 +130,10 @@ struct GXBindGroups {
|
|||
// Output info from shader generation
|
||||
struct ShaderInfo {
|
||||
GXBindGroups bindGroups;
|
||||
std::bitset<maxTextures> sampledTextures;
|
||||
std::bitset<4> sampledKcolors;
|
||||
std::bitset<2> sampledColorChannels;
|
||||
std::bitset<3> usesTevReg;
|
||||
std::bitset<MaxTextures> sampledTextures;
|
||||
std::bitset<MaxKColors> sampledKColors;
|
||||
std::bitset<MaxColorChannels> sampledColorChannels;
|
||||
std::bitset<MaxTevRegs> usesTevReg;
|
||||
u32 uniformSize = 0;
|
||||
bool usesVtxColor : 1 = false;
|
||||
bool usesNormal : 1 = false;
|
||||
|
@ -143,25 +168,41 @@ struct DlVert {
|
|||
} // namespace aurora::gfx::gx
|
||||
|
||||
namespace aurora {
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const metaforce::CTevCombiners::CTevOp& input) {
|
||||
XXH3_64bits_update(&state, &input.x0_clamp, sizeof(bool));
|
||||
XXH3_64bits_update(&state, &input.x4_op, sizeof(metaforce::CTevCombiners::CTevOp::x4_op));
|
||||
XXH3_64bits_update(&state, &input.x8_bias, sizeof(metaforce::CTevCombiners::CTevOp::x8_bias));
|
||||
XXH3_64bits_update(&state, &input.xc_scale, sizeof(metaforce::CTevCombiners::CTevOp::xc_scale));
|
||||
XXH3_64bits_update(&state, &input.x10_regId, sizeof(metaforce::CTevCombiners::CTevOp::x10_regId));
|
||||
template <typename Arg, Arg Default>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::TevPass<Arg, Default>& input) {
|
||||
XXH3_64bits_update(&state, &input.a, sizeof(Arg));
|
||||
XXH3_64bits_update(&state, &input.b, sizeof(Arg));
|
||||
XXH3_64bits_update(&state, &input.c, sizeof(Arg));
|
||||
XXH3_64bits_update(&state, &input.d, sizeof(Arg));
|
||||
}
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::STevStage& input) {
|
||||
XXH3_64bits_update(&state, &input.colorPass, sizeof(gfx::gx::STevStage::colorPass));
|
||||
XXH3_64bits_update(&state, &input.alphaPass, sizeof(gfx::gx::STevStage::alphaPass));
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::TevOp& input) {
|
||||
XXH3_64bits_update(&state, &input.op, sizeof(gfx::gx::TevOp::op));
|
||||
XXH3_64bits_update(&state, &input.bias, sizeof(gfx::gx::TevOp::bias));
|
||||
XXH3_64bits_update(&state, &input.scale, sizeof(gfx::gx::TevOp::scale));
|
||||
XXH3_64bits_update(&state, &input.outReg, sizeof(gfx::gx::TevOp::outReg));
|
||||
XXH3_64bits_update(&state, &input.clamp, sizeof(bool));
|
||||
}
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::TevStage& input) {
|
||||
xxh3_update(state, input.colorPass);
|
||||
xxh3_update(state, input.alphaPass);
|
||||
xxh3_update(state, input.colorOp);
|
||||
xxh3_update(state, input.alphaOp);
|
||||
XXH3_64bits_update(&state, &input.kcSel, sizeof(gfx::gx::STevStage::kcSel));
|
||||
XXH3_64bits_update(&state, &input.kaSel, sizeof(gfx::gx::STevStage::kaSel));
|
||||
XXH3_64bits_update(&state, &input.texCoordId, sizeof(gfx::gx::STevStage::texCoordId));
|
||||
XXH3_64bits_update(&state, &input.texMapId, sizeof(gfx::gx::STevStage::texMapId));
|
||||
XXH3_64bits_update(&state, &input.channelId, sizeof(gfx::gx::STevStage::channelId));
|
||||
XXH3_64bits_update(&state, &input.kcSel, sizeof(gfx::gx::TevStage::kcSel));
|
||||
XXH3_64bits_update(&state, &input.kaSel, sizeof(gfx::gx::TevStage::kaSel));
|
||||
XXH3_64bits_update(&state, &input.texCoordId, sizeof(gfx::gx::TevStage::texCoordId));
|
||||
XXH3_64bits_update(&state, &input.texMapId, sizeof(gfx::gx::TevStage::texMapId));
|
||||
XXH3_64bits_update(&state, &input.channelId, sizeof(gfx::gx::TevStage::channelId));
|
||||
}
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ColorChannelConfig& input) {
|
||||
XXH3_64bits_update(&state, &input.lightingEnabled, sizeof(gfx::gx::ColorChannelConfig::lightingEnabled));
|
||||
XXH3_64bits_update(&state, &input.matSrc, sizeof(gfx::gx::ColorChannelConfig::matSrc));
|
||||
if (input.lightingEnabled) {
|
||||
// Unused when lighting is disabled
|
||||
XXH3_64bits_update(&state, &input.ambSrc, sizeof(gfx::gx::ColorChannelConfig::ambSrc));
|
||||
}
|
||||
}
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input) {
|
||||
|
@ -171,10 +212,12 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input)
|
|||
}
|
||||
xxh3_update(state, *item);
|
||||
}
|
||||
for (const auto& item : input.channelMatSrcs) {
|
||||
XXH3_64bits_update(&state, &item, sizeof(GX::ColorSrc));
|
||||
for (const auto& item : input.colorChannels) {
|
||||
xxh3_update(state, item);
|
||||
}
|
||||
if (input.alphaDiscard) {
|
||||
XXH3_64bits_update(&state, &*input.alphaDiscard, sizeof(float));
|
||||
}
|
||||
XXH3_64bits_update(&state, &input.alphaDiscard, sizeof(bool));
|
||||
XXH3_64bits_update(&state, &input.denormalizedVertexAttributes, sizeof(bool));
|
||||
XXH3_64bits_update(&state, &input.denormalizedHasNrm, sizeof(bool));
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ static logvisor::Module Log("aurora::gfx::gx");
|
|||
|
||||
std::unordered_map<ShaderRef, std::pair<wgpu::ShaderModule, gx::ShaderInfo>> g_gxCachedShaders;
|
||||
|
||||
static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const STevStage& stage, ShaderInfo& info) {
|
||||
static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const TevStage& stage, ShaderInfo& info) {
|
||||
switch (arg) {
|
||||
case GX::CC_CPREV:
|
||||
return "prev.rgb";
|
||||
|
@ -105,64 +105,64 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const STe
|
|||
case GX::TEV_KCSEL_1_8:
|
||||
return "(1.0/8.0)";
|
||||
case GX::TEV_KCSEL_K0:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.rgb";
|
||||
case GX::TEV_KCSEL_K1:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.rgb";
|
||||
case GX::TEV_KCSEL_K2:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.rgb";
|
||||
case GX::TEV_KCSEL_K3:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.rgb";
|
||||
case GX::TEV_KCSEL_K0_R:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.r";
|
||||
case GX::TEV_KCSEL_K1_R:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.r";
|
||||
case GX::TEV_KCSEL_K2_R:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.r";
|
||||
case GX::TEV_KCSEL_K3_R:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.r";
|
||||
case GX::TEV_KCSEL_K0_G:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.g";
|
||||
case GX::TEV_KCSEL_K1_G:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.g";
|
||||
case GX::TEV_KCSEL_K2_G:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.g";
|
||||
case GX::TEV_KCSEL_K3_G:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.g";
|
||||
case GX::TEV_KCSEL_K0_B:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.b";
|
||||
case GX::TEV_KCSEL_K1_B:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.b";
|
||||
case GX::TEV_KCSEL_K2_B:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.b";
|
||||
case GX::TEV_KCSEL_K3_B:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.b";
|
||||
case GX::TEV_KCSEL_K0_A:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.a";
|
||||
case GX::TEV_KCSEL_K1_A:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.a";
|
||||
case GX::TEV_KCSEL_K2_A:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.a";
|
||||
case GX::TEV_KCSEL_K3_A:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.a";
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid kcSel {}"), stage.kcSel);
|
||||
|
@ -177,7 +177,7 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const STe
|
|||
}
|
||||
}
|
||||
|
||||
static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const STevStage& stage, ShaderInfo& info) {
|
||||
static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const TevStage& stage, ShaderInfo& info) {
|
||||
switch (arg) {
|
||||
case GX::CA_APREV:
|
||||
return "prev.a";
|
||||
|
@ -232,52 +232,52 @@ static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const STe
|
|||
case GX::TEV_KASEL_1_8:
|
||||
return "(1.0/8.0)";
|
||||
case GX::TEV_KASEL_K0_R:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.r";
|
||||
case GX::TEV_KASEL_K1_R:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.r";
|
||||
case GX::TEV_KASEL_K2_R:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.r";
|
||||
case GX::TEV_KASEL_K3_R:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.r";
|
||||
case GX::TEV_KASEL_K0_G:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.g";
|
||||
case GX::TEV_KASEL_K1_G:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.g";
|
||||
case GX::TEV_KASEL_K2_G:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.g";
|
||||
case GX::TEV_KASEL_K3_G:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.g";
|
||||
case GX::TEV_KASEL_K0_B:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.b";
|
||||
case GX::TEV_KASEL_K1_B:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.b";
|
||||
case GX::TEV_KASEL_K2_B:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.b";
|
||||
case GX::TEV_KASEL_K3_B:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.b";
|
||||
case GX::TEV_KASEL_K0_A:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.a";
|
||||
case GX::TEV_KASEL_K1_A:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.a";
|
||||
case GX::TEV_KASEL_K2_A:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.a";
|
||||
case GX::TEV_KASEL_K3_A:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.a";
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid kaSel {}"), stage.kaSel);
|
||||
|
@ -352,34 +352,34 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
|||
break;
|
||||
}
|
||||
Log.report(logvisor::Info, FMT_STRING(" tevStages[{}]:"), i);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_a: {}"), stage->colorPass.x0_a);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_b: {}"), stage->colorPass.x4_b);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_c: {}"), stage->colorPass.x8_c);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_d: {}"), stage->colorPass.xc_d);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_a: {}"), stage->alphaPass.x0_a);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_b: {}"), stage->alphaPass.x4_b);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_c: {}"), stage->alphaPass.x8_c);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_d: {}"), stage->alphaPass.xc_d);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_clamp: {}"), stage->colorOp.x0_clamp);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_op: {}"), stage->colorOp.x4_op);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_bias: {}"), stage->colorOp.x8_bias);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_scale: {}"), stage->colorOp.xc_scale);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_reg_id: {}"), stage->colorOp.x10_regId);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_clamp: {}"), stage->alphaOp.x0_clamp);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_op: {}"), stage->alphaOp.x4_op);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_bias: {}"), stage->alphaOp.x8_bias);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_scale: {}"), stage->alphaOp.xc_scale);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_reg_id: {}"), stage->alphaOp.x10_regId);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_a: {}"), stage->colorPass.a);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_b: {}"), stage->colorPass.b);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_c: {}"), stage->colorPass.c);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_d: {}"), stage->colorPass.d);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_a: {}"), stage->alphaPass.a);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_b: {}"), stage->alphaPass.b);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_c: {}"), stage->alphaPass.c);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_d: {}"), stage->alphaPass.d);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_clamp: {}"), stage->colorOp.clamp);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_op: {}"), stage->colorOp.op);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_bias: {}"), stage->colorOp.bias);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_scale: {}"), stage->colorOp.scale);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_reg_id: {}"), stage->colorOp.outReg);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_clamp: {}"), stage->alphaOp.clamp);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_op: {}"), stage->alphaOp.op);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_bias: {}"), stage->alphaOp.bias);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_scale: {}"), stage->alphaOp.scale);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_reg_id: {}"), stage->alphaOp.outReg);
|
||||
Log.report(logvisor::Info, FMT_STRING(" kc_sel: {}"), stage->kcSel);
|
||||
Log.report(logvisor::Info, FMT_STRING(" ka_sel: {}"), stage->kaSel);
|
||||
Log.report(logvisor::Info, FMT_STRING(" texCoordId: {}"), stage->texCoordId);
|
||||
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.channelMatSrcs.size(); ++i) {
|
||||
// Log.report(logvisor::Info, FMT_STRING(" channelMatSrcs[{}]: {}"), i, config.channelMatSrcs[i]);
|
||||
// }
|
||||
// Log.report(logvisor::Info, FMT_STRING(" alphaDiscard: {}"), config.alphaDiscard);
|
||||
Log.report(logvisor::Info, FMT_STRING(" denormalizedVertexAttributes: {}"), config.denormalizedVertexAttributes);
|
||||
}
|
||||
|
||||
|
@ -396,14 +396,16 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
|||
if (config.denormalizedVertexAttributes) {
|
||||
vtxInAttrs += "\n @location(0) in_pos: vec3<f32>";
|
||||
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
|
||||
vtxXfrAttrsPre += "\n var obj_pos = vec4<f32>(in_pos, 1.0);"
|
||||
vtxXfrAttrsPre +=
|
||||
"\n var obj_pos = vec4<f32>(in_pos, 1.0);"
|
||||
"\n var mv_pos = ubuf.mv * obj_pos;"
|
||||
"\n out.pos = ubuf.proj * mv_pos;";
|
||||
if (config.denormalizedHasNrm) {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) nrm: vec3<f32>;"), locIdx);
|
||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_nrm: vec3<f32>"), ++locIdx);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.nrm = in_nrm;"));
|
||||
vtxXfrAttrsPre += "\n var obj_norm = vec4<f32>(in_nrm, 0.0);"
|
||||
vtxXfrAttrsPre +=
|
||||
"\n var obj_norm = vec4<f32>(in_nrm, 0.0);"
|
||||
"\n var mv_norm = ubuf.mv_inv * obj_norm;";
|
||||
info.usesNormal = true;
|
||||
}
|
||||
|
@ -429,7 +431,8 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
"\n , @location(1) in_uv_0_4_idx: vec4<i32>"
|
||||
"\n , @location(2) in_uv_5_7_idx: vec4<i32>";
|
||||
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
|
||||
vtxXfrAttrsPre += "\n var obj_pos = vec4<f32>(v_verts.data[in_pos_nrm_idx[0]].xyz, 1.0);"
|
||||
vtxXfrAttrsPre +=
|
||||
"\n var obj_pos = vec4<f32>(v_verts.data[in_pos_nrm_idx[0]].xyz, 1.0);"
|
||||
"\n var obj_norm = vec4<f32>(v_verts.data[in_pos_nrm_idx[1]].xyz, 0.0);"
|
||||
"\n var mv_pos = ubuf.mv * obj_pos;"
|
||||
"\n var mv_norm = ubuf.mv_inv * obj_norm;"
|
||||
|
@ -444,7 +447,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
}
|
||||
{
|
||||
std::string outReg;
|
||||
switch (stage->colorOp.x10_regId) {
|
||||
switch (stage->colorOp.outReg) {
|
||||
case GX::TevRegID::TEVPREV:
|
||||
outReg = "prev";
|
||||
break;
|
||||
|
@ -461,23 +464,21 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
info.usesTevReg.set(2);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("TODO: colorOp outReg {}"), stage->colorOp.x10_regId);
|
||||
Log.report(logvisor::Fatal, FMT_STRING("TODO: colorOp outReg {}"), stage->colorOp.outReg);
|
||||
}
|
||||
std::string op =
|
||||
fmt::format(FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||
color_arg_reg(stage->colorPass.x0_a, idx, *stage, info),
|
||||
color_arg_reg(stage->colorPass.x4_b, idx, *stage, info),
|
||||
color_arg_reg(stage->colorPass.x8_c, idx, *stage, info),
|
||||
color_arg_reg(stage->colorPass.xc_d, idx, *stage, info), tev_op(stage->colorOp.x4_op),
|
||||
tev_bias(stage->colorOp.x8_bias), tev_scale(stage->colorOp.xc_scale));
|
||||
if (stage->colorOp.x0_clamp) {
|
||||
std::string op = fmt::format(
|
||||
FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||
color_arg_reg(stage->colorPass.a, idx, *stage, info), color_arg_reg(stage->colorPass.b, idx, *stage, info),
|
||||
color_arg_reg(stage->colorPass.c, idx, *stage, info), color_arg_reg(stage->colorPass.d, idx, *stage, info),
|
||||
tev_op(stage->colorOp.op), tev_bias(stage->colorOp.bias), tev_scale(stage->colorOp.scale));
|
||||
if (stage->colorOp.clamp) {
|
||||
op = fmt::format(FMT_STRING("clamp(vec3<f32>({}), vec3<f32>(0.0), vec3<f32>(1.0))"), op);
|
||||
}
|
||||
fragmentFn += fmt::format(FMT_STRING("\n {0} = vec4<f32>({1}, {0}.a);"), outReg, op);
|
||||
}
|
||||
{
|
||||
std::string outReg;
|
||||
switch (stage->alphaOp.x10_regId) {
|
||||
switch (stage->alphaOp.outReg) {
|
||||
case GX::TevRegID::TEVPREV:
|
||||
outReg = "prev.a";
|
||||
break;
|
||||
|
@ -494,16 +495,14 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
info.usesTevReg.set(2);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("TODO: alphaOp outReg {}"), stage->alphaOp.x10_regId);
|
||||
Log.report(logvisor::Fatal, FMT_STRING("TODO: alphaOp outReg {}"), stage->alphaOp.outReg);
|
||||
}
|
||||
std::string op =
|
||||
fmt::format(FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||
alpha_arg_reg(stage->alphaPass.x0_a, idx, *stage, info),
|
||||
alpha_arg_reg(stage->alphaPass.x4_b, idx, *stage, info),
|
||||
alpha_arg_reg(stage->alphaPass.x8_c, idx, *stage, info),
|
||||
alpha_arg_reg(stage->alphaPass.xc_d, idx, *stage, info), tev_op(stage->alphaOp.x4_op),
|
||||
tev_bias(stage->alphaOp.x8_bias), tev_scale(stage->alphaOp.xc_scale));
|
||||
if (stage->alphaOp.x0_clamp) {
|
||||
std::string op = fmt::format(
|
||||
FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||
alpha_arg_reg(stage->alphaPass.a, idx, *stage, info), alpha_arg_reg(stage->alphaPass.b, idx, *stage, info),
|
||||
alpha_arg_reg(stage->alphaPass.c, idx, *stage, info), alpha_arg_reg(stage->alphaPass.d, idx, *stage, info),
|
||||
tev_op(stage->alphaOp.op), tev_bias(stage->alphaOp.bias), tev_scale(stage->alphaOp.scale));
|
||||
if (stage->alphaOp.clamp) {
|
||||
op = fmt::format(FMT_STRING("clamp({}, 0.0, 1.0)"), op);
|
||||
}
|
||||
fragmentFn += fmt::format(FMT_STRING("\n {0} = {1};"), outReg, op);
|
||||
|
@ -518,19 +517,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
fragmentFnPre += fmt::format(FMT_STRING("\n var tevreg{0} = ubuf.tevreg{0};"), i);
|
||||
info.uniformSize += 16;
|
||||
}
|
||||
if (info.sampledColorChannels.any()) {
|
||||
uniformPre += "\n"
|
||||
"struct Light {\n"
|
||||
" pos: vec3<f32>;\n"
|
||||
" dir: vec3<f32>;\n"
|
||||
" color: vec4<f32>;\n"
|
||||
" lin_att: vec3<f32>;\n"
|
||||
" ang_att: vec3<f32>;\n"
|
||||
"};";
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n lights: array<Light, {}>;"), MaxLights);
|
||||
uniBufAttrs += "\n lighting_ambient: vec4<f32>;";
|
||||
info.uniformSize += (80 * MaxLights) + 16;
|
||||
}
|
||||
bool addedLightStruct = false;
|
||||
for (int i = 0; i < info.sampledColorChannels.size(); ++i) {
|
||||
if (!info.sampledColorChannels.test(i)) {
|
||||
continue;
|
||||
|
@ -540,26 +527,30 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_mat: vec4<f32>;"), i);
|
||||
info.uniformSize += 32;
|
||||
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), locIdx++, i);
|
||||
|
||||
if (config.channelMatSrcs[i] == GX::SRC_VTX) {
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
if (!info.usesVtxColor) {
|
||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_clr: vec4<f32>"), locIdx);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = in_clr;"), i);
|
||||
}
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("SRC_VTX unsupported with normalized vertex attributes"));
|
||||
if (config.colorChannels[i].lightingEnabled) {
|
||||
if (!addedLightStruct) {
|
||||
uniformPre +=
|
||||
"\n"
|
||||
"struct Light {\n"
|
||||
" pos: vec3<f32>;\n"
|
||||
" dir: vec3<f32>;\n"
|
||||
" color: vec4<f32>;\n"
|
||||
" lin_att: vec3<f32>;\n"
|
||||
" ang_att: vec3<f32>;\n"
|
||||
"};";
|
||||
addedLightStruct = true;
|
||||
}
|
||||
info.usesVtxColor = true;
|
||||
} else {
|
||||
// TODO only perform lighting on CC0 when enabled
|
||||
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n lights{}: array<Light, {}>;"), i, GX::MaxLights);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n lighting_ambient{}: vec4<f32>;"), i);
|
||||
info.uniformSize += (80 * GX::MaxLights) + 16;
|
||||
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), locIdx++, i);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING(R"""(
|
||||
{{
|
||||
var lighting = ubuf.lighting_ambient + ubuf.cc{0}_amb;
|
||||
var lighting = ubuf.lighting_ambient{0} + ubuf.cc{0}_amb;
|
||||
for (var i = 0; i < {1}; i = i + 1) {{
|
||||
var light = ubuf.lights[i];
|
||||
var light = ubuf.lights{0}[i];
|
||||
var delta = mv_pos.xyz - light.pos;
|
||||
var dist = length(delta);
|
||||
var delta_norm = delta / dist;
|
||||
|
@ -575,12 +566,27 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
lighting = lighting + vec4<f32>(this_color, 0.0);
|
||||
}}
|
||||
out.cc{0} = clamp(lighting, vec4<f32>(0.0), vec4<f32>(1.0));
|
||||
}})"""), i, MaxLights);
|
||||
}})"""),
|
||||
i, GX::MaxLights);
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||
} else if (config.colorChannels[i].matSrc == GX::SRC_VTX) {
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
if (!info.usesVtxColor) {
|
||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_clr: vec4<f32>"), locIdx);
|
||||
}
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), locIdx++, i);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = in_clr;"), i);
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("SRC_VTX unsupported with normalized vertex attributes"));
|
||||
}
|
||||
info.usesVtxColor = true;
|
||||
} else {
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = ubuf.cc{0}_mat;"), i);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < info.sampledKcolors.size(); ++i) {
|
||||
if (!info.sampledKcolors.test(i)) {
|
||||
for (int i = 0; i < info.sampledKColors.size(); ++i) {
|
||||
if (!info.sampledKColors.test(i)) {
|
||||
continue;
|
||||
}
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n kcolor{}: vec4<f32>;"), i);
|
||||
|
@ -622,6 +628,9 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
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);
|
||||
}
|
||||
|
||||
const auto shaderSource =
|
||||
fmt::format(FMT_STRING(R"""({uniformPre}
|
||||
|
|
|
@ -54,10 +54,10 @@ static const std::vector<zeus::CVector3f>* nrmData;
|
|||
static const std::vector<Vec2<float>>* tex0TcData;
|
||||
static const std::vector<Vec2<float>>* tcData;
|
||||
|
||||
void set_vertex_buffer(const std::vector<zeus::CVector3f>* data) noexcept { vtxData = data; }
|
||||
void set_normal_buffer(const std::vector<zeus::CVector3f>* norm) noexcept { nrmData = norm; }
|
||||
void set_tex0_tc_buffer(const std::vector<Vec2<float>>* tcs) noexcept { tex0TcData = tcs; }
|
||||
void set_tc_buffer(const std::vector<Vec2<float>>* tcs) noexcept { tcData = tcs; }
|
||||
// void set_vertex_buffer(const std::vector<zeus::CVector3f>* data) noexcept { vtxData = data; }
|
||||
// void set_normal_buffer(const std::vector<zeus::CVector3f>* norm) noexcept { nrmData = norm; }
|
||||
// void set_tex0_tc_buffer(const std::vector<Vec2<float>>* tcs) noexcept { tex0TcData = tcs; }
|
||||
// void set_tc_buffer(const std::vector<Vec2<float>>* tcs) noexcept { tcData = tcs; }
|
||||
|
||||
enum class VertexFormat : u8 {
|
||||
F32F32,
|
||||
|
@ -233,3 +233,27 @@ void render(const State& state, const DrawData& data, const wgpu::RenderPassEnco
|
|||
pass.DrawIndexed(data.indexCount);
|
||||
}
|
||||
} // namespace aurora::gfx::model
|
||||
|
||||
void GXSetArray(GX::Attr attr, const void* data, u8 stride) noexcept {
|
||||
switch (attr) {
|
||||
case GX::VA_POS:
|
||||
aurora::gfx::model::vtxData = static_cast<const std::vector<zeus::CVector3f>*>(data);
|
||||
break;
|
||||
case GX::VA_NRM:
|
||||
aurora::gfx::model::nrmData = static_cast<const std::vector<zeus::CVector3f>*>(data);
|
||||
break;
|
||||
case GX::VA_TEX0:
|
||||
aurora::gfx::model::tex0TcData = static_cast<const std::vector<aurora::Vec2<float>>*>(data);
|
||||
break;
|
||||
case GX::VA_TEX1:
|
||||
aurora::gfx::model::tcData = static_cast<const std::vector<aurora::Vec2<float>>*>(data);
|
||||
break;
|
||||
default:
|
||||
aurora::gfx::model::Log.report(logvisor::Fatal, FMT_STRING("GXSetArray: invalid attr {}"), attr);
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
void GXCallDisplayList(const void* data, u32 nbytes) noexcept {
|
||||
aurora::gfx::model::queue_surface(static_cast<const u8*>(data), nbytes);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue