mirror of https://github.com/AxioDL/metaforce.git
Implement fog
This commit is contained in:
parent
9062e54c76
commit
ec5f188063
|
@ -801,7 +801,7 @@ void CCubeRenderer::SetWireframeFlags(s32 flags) {
|
|||
}
|
||||
|
||||
void CCubeRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) {
|
||||
// TODO
|
||||
CGraphics::SetFog(x318_28_disableFog ? ERglFogMode::None : mode, startz, endz, color);
|
||||
}
|
||||
|
||||
void CCubeRenderer::RenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb,
|
||||
|
|
|
@ -59,10 +59,10 @@ static inline void update_fog(u32 value) noexcept {
|
|||
return;
|
||||
}
|
||||
if ((value & 0xE0) == 0x20) {
|
||||
// TODO
|
||||
GXSetFogColor(zeus::skClear);
|
||||
return;
|
||||
}
|
||||
// TODO
|
||||
GXSetFogColor(sGXState.x25c_fogColor);
|
||||
}
|
||||
|
||||
static inline void FlushState() noexcept {
|
||||
|
@ -186,8 +186,7 @@ static inline void SetFog(GX::FogType type, float startZ, float endZ, float near
|
|||
if ((sGXState.x56_blendMode & 0xE0) == 0x20) {
|
||||
fogColor = zeus::skClear;
|
||||
}
|
||||
// TODO
|
||||
// GXSetFog(type, startZ, endZ, nearZ, farZ, fogColor);
|
||||
GXSetFog(type, startZ, endZ, nearZ, farZ, fogColor);
|
||||
}
|
||||
|
||||
void SetIndTexMtxSTPointFive(GX::IndTexMtxID id, s8 scaleExp) noexcept;
|
||||
|
|
|
@ -117,19 +117,6 @@ void CGraphics::SetAmbientColor(const zeus::CColor& 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;
|
||||
// }
|
||||
CGX::SetFog(GX::FogType(mode), startz, endz, g_Proj.x14_near, g_Proj.x18_far, color);
|
||||
}
|
||||
|
||||
|
|
|
@ -183,6 +183,10 @@ void GXSetViewport(float left, float top, float width, float height, float nearZ
|
|||
void GXSetScissor(u32 left, u32 top, u32 width, u32 height) noexcept {
|
||||
aurora::gfx::set_scissor(left, top, width, height);
|
||||
}
|
||||
void GXSetFog(GX::FogType type, float startZ, float endZ, float nearZ, float farZ, const GXColor& color) noexcept {
|
||||
g_gxState.fog = {type, startZ, endZ, nearZ, farZ, color};
|
||||
}
|
||||
void GXSetFogColor(const GXColor& color) noexcept { g_gxState.fog.color = color; }
|
||||
|
||||
namespace aurora::gfx {
|
||||
static logvisor::Module Log("aurora::gfx::gx");
|
||||
|
@ -196,8 +200,6 @@ void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHan
|
|||
}
|
||||
void unbind_texture(GX::TexMapID id) noexcept { gx::g_gxState.textures[static_cast<size_t>(id)].reset(); }
|
||||
|
||||
void update_fog_state(const metaforce::CFogState& state) noexcept { gx::g_gxState.fogState = state; }
|
||||
|
||||
void load_light(GX::LightID id, const Light& light) noexcept { gx::g_gxState.lights[std::log2<u32>(id)] = light; }
|
||||
void load_light_ambient(GX::LightID id, const zeus::CColor& ambient) noexcept {
|
||||
gx::g_gxState.lights[std::log2<u32>(id)] = ambient;
|
||||
|
@ -395,6 +397,7 @@ ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primit
|
|||
config.shaderConfig.tcgs[i] = g_gxState.tcgs[i];
|
||||
}
|
||||
config.shaderConfig.alphaDiscard = g_gxState.alphaDiscard;
|
||||
config.shaderConfig.fogType = g_gxState.fog.type;
|
||||
config = {
|
||||
.shaderConfig = config.shaderConfig,
|
||||
.primitive = primitive,
|
||||
|
@ -501,6 +504,25 @@ Range build_uniform(const ShaderInfo& info) noexcept {
|
|||
}
|
||||
buf.append(&g_gxState.ptTexMtxs[i], 48);
|
||||
}
|
||||
if (info.usesFog) {
|
||||
const auto& state = g_gxState.fog;
|
||||
struct Fog {
|
||||
zeus::CColor color = state.color;
|
||||
float a = 0.f;
|
||||
float b = 0.5f;
|
||||
float c = 0.f;
|
||||
float pad = FLT_MAX;
|
||||
} fog{};
|
||||
static_assert(sizeof(Fog) == 32);
|
||||
if (state.nearZ != state.farZ && state.startZ != state.endZ) {
|
||||
const float depthRange = state.farZ - state.nearZ;
|
||||
const float fogRange = state.endZ - state.startZ;
|
||||
fog.a = (state.farZ * state.nearZ) / (depthRange * fogRange);
|
||||
fog.b = state.farZ / depthRange;
|
||||
fog.c = state.startZ / fogRange;
|
||||
}
|
||||
buf.append(&fog, 32);
|
||||
}
|
||||
for (int i = 0; i < info.sampledTextures.size(); ++i) {
|
||||
if (!info.sampledTextures.test(i)) {
|
||||
continue;
|
||||
|
|
|
@ -73,12 +73,20 @@ struct TcgConfig {
|
|||
GX::PTTexMtx postMtx = GX::PTIDENTITY;
|
||||
bool normalize = false;
|
||||
};
|
||||
struct FogState {
|
||||
GX::FogType type = GX::FOG_NONE;
|
||||
float startZ = 0.f;
|
||||
float endZ = 0.f;
|
||||
float nearZ = 0.f;
|
||||
float farZ = 0.f;
|
||||
zeus::CColor color;
|
||||
};
|
||||
|
||||
struct GXState {
|
||||
zeus::CMatrix4f mv;
|
||||
zeus::CMatrix4f mvInv;
|
||||
zeus::CMatrix4f proj;
|
||||
metaforce::CFogState fogState;
|
||||
FogState fog;
|
||||
GX::CullMode cullMode = GX::CULL_BACK;
|
||||
GX::BlendMode blendMode = GX::BM_NONE;
|
||||
GX::BlendFactor blendFacSrc = GX::BL_SRCALPHA;
|
||||
|
@ -114,6 +122,7 @@ void shutdown() noexcept;
|
|||
const TextureBind& get_texture(GX::TexMapID id) noexcept;
|
||||
|
||||
struct ShaderConfig {
|
||||
GX::FogType fogType;
|
||||
std::array<std::optional<TevStage>, MaxTevStages> tevStages;
|
||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannels;
|
||||
std::array<TcgConfig, MaxTexCoord> tcgs;
|
||||
|
@ -155,6 +164,7 @@ struct ShaderInfo {
|
|||
u32 uniformSize = 0;
|
||||
bool usesVtxColor : 1 = false;
|
||||
bool usesNormal : 1 = false;
|
||||
bool usesFog : 1 = false;
|
||||
};
|
||||
struct BindGroupRanges {
|
||||
Range vtxDataRange;
|
||||
|
@ -247,7 +257,9 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input)
|
|||
if (input.alphaDiscard) {
|
||||
XXH3_64bits_update(&state, &*input.alphaDiscard, sizeof(float));
|
||||
}
|
||||
XXH3_64bits_update(&state, &input.denormalizedVertexAttributes, sizeof(bool));
|
||||
XXH3_64bits_update(&state, &input.denormalizedHasNrm, sizeof(bool));
|
||||
XXH3_64bits_update(&state, &input.denormalizedVertexAttributes,
|
||||
sizeof(gfx::gx::ShaderConfig::denormalizedVertexAttributes));
|
||||
XXH3_64bits_update(&state, &input.denormalizedHasNrm, sizeof(gfx::gx::ShaderConfig::denormalizedHasNrm));
|
||||
XXH3_64bits_update(&state, &input.fogType, sizeof(gfx::gx::ShaderConfig::fogType));
|
||||
}
|
||||
} // namespace aurora
|
||||
|
|
|
@ -400,6 +400,7 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
|||
}
|
||||
Log.report(logvisor::Info, FMT_STRING(" alphaDiscard: {}"), config.alphaDiscard.value_or(0.f));
|
||||
Log.report(logvisor::Info, FMT_STRING(" denormalizedVertexAttributes: {}"), config.denormalizedVertexAttributes);
|
||||
Log.report(logvisor::Info, FMT_STRING(" fogType: {}"), config.fogType);
|
||||
}
|
||||
|
||||
std::string uniformPre;
|
||||
|
@ -684,6 +685,49 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
uniBufAttrs += fmt::format(FMT_STRING("\n postmtx{}: mat4x3<f32>;"), i);
|
||||
info.uniformSize += 64;
|
||||
}
|
||||
if (config.fogType != GX::FOG_NONE) {
|
||||
info.usesFog = true;
|
||||
|
||||
uniformPre += "\n"
|
||||
"struct Fog {\n"
|
||||
" color: vec4<f32>;\n"
|
||||
" a: f32;\n"
|
||||
" b: f32;\n"
|
||||
" c: f32;\n"
|
||||
" pad: f32;\n"
|
||||
"}";
|
||||
uniBufAttrs += "\n fog: Fog;";
|
||||
info.uniformSize += 32;
|
||||
|
||||
fragmentFn += "\n var fogF = clamp((ubuf.fog.a / (ubuf.fog.b - in.pos.z)) - ubuf.fog.c, 0.0, 1.0);";
|
||||
switch (config.fogType) {
|
||||
case GX::FOG_PERSP_LIN:
|
||||
case GX::FOG_ORTHO_LIN:
|
||||
fragmentFn += "\n var fogZ = fogF;";
|
||||
break;
|
||||
case GX::FOG_PERSP_EXP:
|
||||
case GX::FOG_ORTHO_EXP:
|
||||
fragmentFn += "\n var fogZ = 1.0 - exp2(-8.0 * fogF);";
|
||||
break;
|
||||
case GX::FOG_PERSP_EXP2:
|
||||
case GX::FOG_ORTHO_EXP2:
|
||||
fragmentFn += "\n var fogZ = 1.0 - exp2(-8.0 * fogF * fogF);";
|
||||
break;
|
||||
case GX::FOG_PERSP_REVEXP:
|
||||
case GX::FOG_ORTHO_REVEXP:
|
||||
fragmentFn += "\n var fogZ = exp2(-8.0 * (1.0 - fogF));";
|
||||
break;
|
||||
case GX::FOG_PERSP_REVEXP2:
|
||||
case GX::FOG_ORTHO_REVEXP2:
|
||||
fragmentFn += "\n fogF = 1.0 - fogF;"
|
||||
"\n var fogZ = exp2(-8.0 * fogF * fogF);";
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid fog type {}"), config.fogType);
|
||||
unreachable();
|
||||
}
|
||||
fragmentFn += "\n prev = vec4<f32>(mix(prev.rgb, ubuf.fog.color.rgb, clamp(fogZ, 0.0, 1.0)), prev.a);";
|
||||
}
|
||||
for (int i = 0; i < info.sampledTextures.size(); ++i) {
|
||||
if (!info.sampledTextures.test(i)) {
|
||||
continue;
|
||||
|
|
Loading…
Reference in New Issue