Ironforge Great Forge lava, magma water rendering, LavaSteam particle effects

- Add magma/slime rendering path to water shader (fbm noise, crust/molten/core coloring)
- Fix WMO liquid height filter rejecting high-altitude zones like Ironforge (Z>300)
- Allow interior WMO magma/slime MLIQ groups to load (skip only water/ocean)
- Mark LAVASTEAM.m2 as spell effect for proper additive blend, hide emission mesh
- Add isLavaModel flag for M2 ForgeLava/LavaPots UV scroll fallback
- Add isLava material detection in WMO renderer for lava texture UV animation
- Fix WMO material UBO colors for magma (was blue, now orange-red)
This commit is contained in:
Kelsi 2026-03-07 00:48:04 -08:00
parent 2c5b7cd368
commit a24fe4cc45
10 changed files with 158 additions and 12 deletions

View file

@ -596,20 +596,26 @@ bool WMORenderer::loadModel(const pipeline::WMOModel& model, uint32_t id) {
// so we additionally check for "window" or "glass" in the texture path to
// distinguish actual glass from lamp post geometry.
bool isWindow = false;
bool isLava = false;
if (batch.materialId < modelData.materialTextureIndices.size()) {
uint32_t ti = modelData.materialTextureIndices[batch.materialId];
if (ti < modelData.textureNames.size()) {
const auto& texName = modelData.textureNames[ti];
// Case-insensitive search for "window" or "glass"
// Case-insensitive search for material types
std::string texNameLower = texName;
std::transform(texNameLower.begin(), texNameLower.end(), texNameLower.begin(), ::tolower);
isWindow = (texNameLower.find("window") != std::string::npos ||
texNameLower.find("glass") != std::string::npos);
isLava = (texNameLower.find("lava") != std::string::npos ||
texNameLower.find("molten") != std::string::npos ||
texNameLower.find("magma") != std::string::npos);
if (isLava) {
LOG_WARNING("WMO LAVA BATCH: tex='", texName, "' matId=", batch.materialId,
" blend=", blendMode, " flags=0x", std::hex, matFlags, std::dec);
}
}
}
BatchKey key{ reinterpret_cast<uintptr_t>(tex), alphaTest, unlit, isWindow };
auto& mb = batchMap[key];
if (mb.draws.empty()) {
@ -619,6 +625,7 @@ bool WMORenderer::loadModel(const pipeline::WMOModel& model, uint32_t id) {
mb.unlit = unlit;
mb.isTransparent = (blendMode >= 2);
mb.isWindow = isWindow;
mb.isLava = isLava;
// Look up normal/height map from texture cache
if (hasTexture && tex != whiteTexture_.get()) {
for (const auto& [cacheKey, cacheEntry] : textureCache) {
@ -668,6 +675,7 @@ bool WMORenderer::loadModel(const pipeline::WMOModel& model, uint32_t id) {
}
matData.heightMapVariance = mb.heightMapVariance;
matData.normalMapStrength = normalMapStrength_;
matData.isLava = mb.isLava ? 1 : 0;
if (matBuf.info.pMappedData) {
memcpy(matBuf.info.pMappedData, &matData, sizeof(matData));
}
@ -789,6 +797,7 @@ bool WMORenderer::loadModel(const pipeline::WMOModel& model, uint32_t id) {
doodadTemplate.m2Path = m2Path;
doodadTemplate.localTransform = localTransform;
modelData.doodadTemplates.push_back(doodadTemplate);
}
if (!modelData.doodadTemplates.empty()) {