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

@ -155,6 +155,52 @@ void main() {
float time = fogParams.z;
float basicType = push.liquidBasicType;
// ============================================================
// Magma / Slime — self-luminous flowing surfaces, skip water path
// ============================================================
if (basicType > 1.5) {
float dist = length(viewPos.xyz - FragPos);
vec2 flowUV = FragPos.xy;
bool isMagma = basicType < 2.5;
// Multi-octave flowing noise for organic lava look
float n1 = fbmNoise(flowUV * 0.06 + vec2(time * 0.02, time * 0.03), time * 0.4);
float n2 = fbmNoise(flowUV * 0.10 + vec2(-time * 0.015, time * 0.025), time * 0.3);
float n3 = noiseValue(flowUV * 0.25 + vec2(time * 0.04, -time * 0.02));
float flow = n1 * 0.45 + n2 * 0.35 + n3 * 0.20;
// Dark crust vs bright molten core
vec3 crustColor, hotColor, coreColor;
if (isMagma) {
crustColor = vec3(0.15, 0.04, 0.01); // dark cooled rock
hotColor = vec3(1.0, 0.45, 0.05); // orange molten
coreColor = vec3(1.0, 0.85, 0.3); // bright yellow-white core
} else {
crustColor = vec3(0.05, 0.15, 0.02);
hotColor = vec3(0.3, 0.8, 0.15);
coreColor = vec3(0.5, 1.0, 0.3);
}
// Three-tier color: crust → molten → hot core
float crustMask = smoothstep(0.25, 0.50, flow);
float coreMask = smoothstep(0.60, 0.80, flow);
vec3 color = mix(crustColor, hotColor, crustMask);
color = mix(color, coreColor, coreMask);
// Subtle pulsing emissive glow
float pulse = 1.0 + 0.15 * sin(time * 1.5 + flow * 6.0);
color *= pulse;
// Emissive brightening for hot areas
color *= 1.0 + coreMask * 0.6;
float fogFactor = clamp((fogParams.y - dist) / (fogParams.y - fogParams.x), 0.0, 1.0);
color = mix(fogColor.rgb, color, fogFactor);
outColor = vec4(color, 0.97);
return;
}
vec2 screenUV = gl_FragCoord.xy / vec2(textureSize(SceneColor, 0));
// --- Normal computation ---

Binary file not shown.

View file

@ -28,6 +28,7 @@ layout(set = 1, binding = 1) uniform WMOMaterial {
int pomMaxSamples;
float heightMapVariance;
float normalMapStrength;
int isLava;
};
layout(set = 1, binding = 2) uniform sampler2D uNormalHeightMap;
@ -120,6 +121,14 @@ void main() {
// Compute final UV (with POM if enabled)
vec2 finalUV = TexCoord;
// Lava/magma: scroll UVs for flowing effect
if (isLava != 0) {
float time = fogParams.z;
// Scroll both axes — pools get horizontal flow, waterfalls get vertical flow
// (UV orientation depends on mesh, so animate both)
finalUV += vec2(time * 0.04, time * 0.06);
}
// Build TBN matrix
vec3 T = normalize(Tangent);
vec3 B = normalize(Bitangent);
@ -170,7 +179,10 @@ void main() {
shadow = mix(1.0, shadow, shadowParams.y);
}
if (unlit != 0) {
if (isLava != 0) {
// Lava is self-luminous — bright emissive, no shadows
result = texColor.rgb * 1.5;
} else if (unlit != 0) {
result = texColor.rgb * shadow;
} else if (isInterior != 0) {
vec3 mocv = max(VertColor.rgb, vec3(0.5));

Binary file not shown.