Add glass pipeline for WMO windows with Fresnel-based transparency

Dedicated Vulkan pipeline with alpha blending AND depth writes so
windows look transparent at oblique angles without see-through artifacts.
Fresnel alpha ranges from 0.4 (grazing) to 0.95 (head-on) with sun
glint, reflections, and silver-lining specular.
This commit is contained in:
Kelsi 2026-02-23 00:43:14 -08:00
parent fb4ff46fe3
commit 1b16bcf71f
4 changed files with 99 additions and 16 deletions

View file

@ -21,6 +21,7 @@ layout(set = 1, binding = 1) uniform WMOMaterial {
int unlit;
int isInterior;
float specularIntensity;
int isWindow;
};
layout(set = 0, binding = 1) uniform sampler2DShadow uShadowMap;
@ -78,5 +79,44 @@ void main() {
float fogFactor = clamp((fogParams.y - dist) / (fogParams.y - fogParams.x), 0.0, 1.0);
result = mix(fogColor.rgb, result, fogFactor);
outColor = vec4(result, texColor.a);
float alpha = texColor.a;
// Window glass: opaque but simulates dark tinted glass with reflections.
// No real alpha blending — we darken the base texture and add reflection
// on top so it reads as glass without needing the transparent pipeline.
if (isWindow != 0) {
vec3 viewDir = normalize(viewPos.xyz - FragPos);
float NdotV = abs(dot(norm, viewDir));
// Fresnel: strong reflection at grazing angles
float fresnel = 0.08 + 0.92 * pow(1.0 - NdotV, 4.0);
// Glass darkness depends on view angle — bright when sun glints off,
// darker when looking straight on with no sun reflection.
vec3 ldir = normalize(-lightDir.xyz);
vec3 reflectDir = reflect(-viewDir, norm);
float sunGlint = pow(max(dot(reflectDir, ldir), 0.0), 32.0);
// Base ranges from dark (0.3) to bright (0.9) based on sun reflection
float baseBrightness = mix(0.3, 0.9, sunGlint);
vec3 glass = result * baseBrightness;
// Reflection: blend sky/ambient color based on Fresnel
vec3 reflectTint = mix(ambientColor.rgb * 1.2, vec3(0.6, 0.75, 1.0), 0.6);
glass = mix(glass, reflectTint, fresnel * 0.8);
// Sharp sun glint on glass
vec3 halfDir = normalize(ldir + viewDir);
float spec = pow(max(dot(norm, halfDir), 0.0), 256.0);
glass += spec * lightColor.rgb * 0.8;
// Broad warm sheen when sun is nearby
float specBroad = pow(max(dot(norm, halfDir), 0.0), 12.0);
glass += specBroad * lightColor.rgb * 0.12;
result = glass;
// Fresnel-based transparency: more transparent at oblique angles
alpha = mix(0.4, 0.95, NdotV);
}
outColor = vec4(result, alpha);
}

Binary file not shown.