Files
Vibe-HD-2D/assets/shaders/mesh.frag
Gabrieal Jimmy 2c99305fb0 init
2026-10-02 12:42:00 -05:00

84 lines
3.4 KiB
GLSL

#version 450 core
#include "common.glsl"
// High-resolution 3D scenery (trees, bushes, rocks). Foliage uses wrap
// lighting on its rounded custom normals plus sun translucency.
in VS {
vec3 worldPos;
vec3 normal;
vec2 uv;
vec3 color;
float height;
} v;
layout(binding = 0) uniform sampler2D uTex;
uniform vec4 uBaseColor;
uniform int uAlphaMask;
uniform float uCutoff;
uniform int uFoliage;
uniform int uOccluderFade; // 1 in the main view: dither away scenery hiding the player
uniform vec3 uEmissive; // linear HDR; multiplied by the emissive texture (unit 1)
layout(binding = 1) uniform sampler2D uEmissiveTex;
layout(location = 0) out vec4 fragColor;
void main() {
vec4 tex = texture(uTex, v.uv);
if (uAlphaMask == 1) {
// Sharpen alpha by its screen-space rate of change: keeps leaf coverage
// stable through the mip chain instead of thinning out with distance.
float a = (tex.a - uCutoff) / max(fwidth(tex.a), 1e-4) + 0.5;
if (a < 0.5) discard;
}
if (uOccluderFade == 1 && uBlob.w > 0.0) {
vec4 pc = uViewProj * vec4(uBlob.xyz + vec3(0.0, 0.6, 0.0), 1.0);
vec2 ps = pc.xy / pc.w * 0.5 + 0.5;
vec2 d = (gl_FragCoord.xy * uScreen.zw - ps) * vec2(uScreen.x * uScreen.w, 1.0);
float fragDepth = (uViewProj * vec4(v.worldPos, 1.0)).w;
float fade = (1.0 - smoothstep(0.07, 0.15, length(d))) * step(fragDepth, pc.w - 1.0);
if (ign(gl_FragCoord.xy) < fade * 0.85) discard;
}
vec3 wp = v.worldPos;
vec3 n = normalize(v.normal);
if (uFoliage == 0 && !gl_FrontFacing) n = -n;
vec3 L = uSunDir.xyz;
vec3 V = normalize(uCamPos.xyz - wp);
vec3 albedo = tex.rgb * uBaseColor.rgb * v.color;
float gao = groundAO(wp, v.height);
float ndl = dot(n, L);
float diffuse = uFoliage == 1 ? clamp((ndl + 0.45) / 1.45, 0.0, 1.0) : max(ndl, 0.0);
// Offset along the normal and toward the sun to avoid acne on thin cards.
float vis = sunShadow(wp + n * 0.06 + L * 0.08) * canopyCookie(wp);
if (uFoliage == 1) vis = mix(0.3, 1.0, vis); // light scatters through leaves: soft self-shadowing
vec3 sunRad = uSunColor.rgb * uSunDir.w;
vec3 toCam = cross(uBillboardRight.xyz, vec3(0.0, 1.0, 0.0));
vec3 amb = hemiAmbient(n) + uSkyHorizon.rgb * uSkyHorizon.w * max(dot(n, toCam), 0.0);
vec3 light = sunRad * diffuse * vis * mix(1.0, gao, 0.7) + amb * gao + pointLights(wp, n);
if (uFoliage == 1) {
// Backlit leaves glow; sunlit rims pick up a warm sheen.
float back = pow(max(dot(-V, L), 0.0), 4.0);
light += sunRad * back * vis * 0.35 * vec3(1.0, 1.05, 0.7);
float rim = pow(1.0 - max(dot(n, V), 0.0), 3.0) * max(ndl, 0.0);
light += sunRad * rim * vis * 0.25;
} else {
// Subtle sheen on rocks and bark.
vec3 H = normalize(L + V);
light += sunRad * pow(max(dot(n, H), 0.0), 24.0) * 0.06 * vis;
}
vec3 sheen = vec3(0.0);
if (uWeather.y > 0.0) albedo = wetSurface(albedo, n, V, vis, sheen);
vec3 col = albedo * light + sheen * gao;
col += texture(uEmissiveTex, v.uv).rgb * uEmissive;
if (uBlob.w > 0.0) { // player's contact shadow
float d = length(wp.xz - uBlob.xz) / uBlob.w;
float near = 1.0 - smoothstep(0.0, 0.6, abs(wp.y - uBlob.y));
col *= 1.0 - 0.4 * (1.0 - smoothstep(0.3, 1.0, d)) * near;
}
fragColor = vec4(col, 1.0);
}