Implement fog

This commit is contained in:
Luke Street 2022-03-14 19:12:18 -04:00
parent 9062e54c76
commit ec5f188063
6 changed files with 87 additions and 23 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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;