mirror of https://github.com/AxioDL/metaforce.git
Initial support for proper GXSetAlphaCompare logic, needs more testing to verify it works properly
This commit is contained in:
parent
9e546931f4
commit
a84bc64358
|
@ -108,14 +108,7 @@ void GXSetChanCtrl(GX::ChannelID id, bool lightingEnabled, GX::ColorSrc ambSrc,
|
|||
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();
|
||||
}
|
||||
g_gxState.alphaCompare = {comp0, ref0, op, comp1, ref1};
|
||||
}
|
||||
void GXSetTexCoordGen2(GX::TexCoordID dst, GX::TexGenType type, GX::TexGenSrc src, GX::TexMtx mtx, GXBool normalize,
|
||||
GX::PTTexMtx postMtx) noexcept {
|
||||
|
@ -422,7 +415,7 @@ ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primit
|
|||
for (u8 i = 0; i < g_gxState.numTexGens; ++i) {
|
||||
config.shaderConfig.tcgs[i] = g_gxState.tcgs[i];
|
||||
}
|
||||
config.shaderConfig.alphaDiscard = g_gxState.alphaDiscard;
|
||||
config.shaderConfig.alphaCompare = g_gxState.alphaCompare;
|
||||
if (std::any_of(config.shaderConfig.vtxAttrs.begin(), config.shaderConfig.vtxAttrs.end(),
|
||||
[](const auto type) { return type == GX::INDEX8 || type == GX::INDEX16; })) {
|
||||
config.shaderConfig.hasIndexedAttributes = true;
|
||||
|
|
|
@ -99,6 +99,15 @@ struct TevSwap {
|
|||
operator bool() const { return *this != TevSwap{}; }
|
||||
};
|
||||
|
||||
struct AlphaCompare {
|
||||
GX::Compare comp0 = GX::ALWAYS;
|
||||
float ref0 = 0.f;
|
||||
GX::AlphaOp op = GX::AOP_AND;
|
||||
GX::Compare comp1 = GX::ALWAYS;
|
||||
float ref1 = 0.f;
|
||||
bool operator==(const AlphaCompare& other) const = default;
|
||||
operator bool() const { return *this != AlphaCompare{}; }
|
||||
};
|
||||
struct GXState {
|
||||
zeus::CMatrix4f mv;
|
||||
zeus::CMatrix4f mvInv;
|
||||
|
@ -112,7 +121,7 @@ struct GXState {
|
|||
GX::Compare depthFunc = GX::LEQUAL;
|
||||
zeus::CColor clearColor = zeus::skBlack;
|
||||
std::optional<float> dstAlpha;
|
||||
std::optional<float> alphaDiscard;
|
||||
AlphaCompare alphaCompare;
|
||||
std::array<zeus::CColor, MaxTevRegs> colorRegs;
|
||||
std::array<zeus::CColor, GX::MAX_KCOLOR> kcolors;
|
||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannelConfig;
|
||||
|
@ -152,7 +161,7 @@ struct ShaderConfig {
|
|||
std::array<std::optional<TevStage>, MaxTevStages> tevStages;
|
||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannels;
|
||||
std::array<TcgConfig, MaxTexCoord> tcgs;
|
||||
std::optional<float> alphaDiscard;
|
||||
AlphaCompare alphaCompare;
|
||||
bool hasIndexedAttributes = false;
|
||||
bool operator==(const ShaderConfig&) const = default;
|
||||
};
|
||||
|
@ -281,8 +290,8 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input)
|
|||
for (const auto& item : input.tcgs) {
|
||||
xxh3_update(state, item);
|
||||
}
|
||||
if (input.alphaDiscard) {
|
||||
XXH3_64bits_update(&state, &*input.alphaDiscard, sizeof(float));
|
||||
if (input.alphaCompare) {
|
||||
XXH3_64bits_update(&state, &input.alphaCompare, sizeof(gfx::gx::AlphaCompare));
|
||||
}
|
||||
XXH3_64bits_update(&state, &input.hasIndexedAttributes, sizeof(gfx::gx::ShaderConfig::hasIndexedAttributes));
|
||||
}
|
||||
|
|
|
@ -344,6 +344,31 @@ static std::string_view tev_bias(GX::TevBias bias) {
|
|||
}
|
||||
}
|
||||
|
||||
static std::string alpha_compare(GX::Compare comp, float ref, bool& valid) {
|
||||
switch (comp) {
|
||||
case GX::NEVER:
|
||||
return "false";
|
||||
case GX::LESS:
|
||||
return fmt::format(FMT_STRING("(prev.a < {}f)"), ref);
|
||||
case GX::LEQUAL:
|
||||
return fmt::format(FMT_STRING("(prev.a <= {}f)"), ref);
|
||||
case GX::EQUAL:
|
||||
return fmt::format(FMT_STRING("(prev.a == {}f)"), ref);
|
||||
case GX::NEQUAL:
|
||||
return fmt::format(FMT_STRING("(prev.a != {}f)"), ref);
|
||||
case GX::GEQUAL:
|
||||
return fmt::format(FMT_STRING("(prev.a >= {}f)"), ref);
|
||||
case GX::GREATER:
|
||||
return fmt::format(FMT_STRING("(prev.a < {}f)"), ref);
|
||||
case GX::ALWAYS:
|
||||
valid = false;
|
||||
return "true";
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid compare {}"), comp);
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
static std::string_view tev_scale(GX::TevScale scale) {
|
||||
switch (scale) {
|
||||
case GX::CS_SCALE_1:
|
||||
|
@ -468,7 +493,9 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
|||
tcg.postMtx, tcg.type, tcg.normalize);
|
||||
}
|
||||
}
|
||||
Log.report(logvisor::Info, FMT_STRING(" alphaDiscard: {}"), config.alphaDiscard.value_or(0.f));
|
||||
Log.report(logvisor::Info, FMT_STRING(" alphaCompare: comp0 {} ref0 {} op {} comp1 {} ref1 {}"),
|
||||
config.alphaCompare.comp0, config.alphaCompare.ref0, config.alphaCompare.op, config.alphaCompare.comp1,
|
||||
config.alphaCompare.ref1);
|
||||
Log.report(logvisor::Info, FMT_STRING(" hasIndexedAttributes: {}"), config.hasIndexedAttributes);
|
||||
Log.report(logvisor::Info, FMT_STRING(" fogType: {}"), config.fogType);
|
||||
}
|
||||
|
@ -810,9 +837,35 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
texBindIdx, i);
|
||||
++texBindIdx;
|
||||
}
|
||||
if (config.alphaDiscard) {
|
||||
fragmentFn += fmt::format(FMT_STRING("\n if (prev.a < {}f) {{ discard; }}"), *config.alphaDiscard);
|
||||
|
||||
if (config.alphaCompare) {
|
||||
bool comp0Valid = true;
|
||||
bool comp1Valid = true;
|
||||
std::string comp0 = alpha_compare(config.alphaCompare.comp0, config.alphaCompare.ref0, comp0Valid);
|
||||
std::string comp1 = alpha_compare(config.alphaCompare.comp1, config.alphaCompare.ref1, comp1Valid);
|
||||
if (comp0Valid || comp1Valid) {
|
||||
switch (config.alphaCompare.op) {
|
||||
case GX::AOP_AND:
|
||||
fragmentFn += fmt::format(FMT_STRING("\n if (!({} && {})) {{ discard; }}"), comp0, comp1);
|
||||
break;
|
||||
case GX::AOP_OR:
|
||||
fragmentFn += fmt::format(FMT_STRING("\n if (!({} || {})) {{ discard; }}"), comp0, comp1);
|
||||
break;
|
||||
case GX::AOP_XOR:
|
||||
fragmentFn += fmt::format(FMT_STRING("\n if (!({} ^^ {})) {{ discard; }}"), comp0, comp1);
|
||||
break;
|
||||
case GX::AOP_XNOR:
|
||||
fragmentFn += fmt::format(FMT_STRING("\n if (({} ^^ {})) {{ discard; }}"), comp0, comp1);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid alpha compare op {}"), config.alphaCompare.op);
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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}
|
||||
|
|
Loading…
Reference in New Issue