#version 450 core layout(location=0) out vec4 oColor; layout(std140, binding=0) uniform PerFrame { mat4 uView; mat4 uProj; vec4 uLightDir; }; layout(std140, binding=2) uniform Material { vec4 uAlbedo; }; layout(location=0) in VS_OUT { vec3 wPos; vec2 uv; } v; // geometric normal from screen-space derivatives of the *world* position vec3 normal_from_worldpos(vec3 w){ vec3 dx = dFdx(w), dy = dFdy(w); vec3 n = cross(dx,dy); float l2 = dot(n,n); return (l2 < 1e-12) ? vec3(0,0,1) : normalize(n); } void main(){ vec3 N = normal_from_worldpos(v.wPos); vec3 L = normalize(-uLightDir.xyz); float ndl = max(dot(N,L), 0.0); // cheap color: height-based gradient + slight darkening by slope float h = v.wPos.z; // world height float h01 = clamp(h * 0.1 + 0.5, 0.0, 1.0); // remap height to 0..1 vec3 low = vec3(0.35, 0.38, 0.40); // rock/soil vec3 high = vec3(0.65, 0.75, 0.60); // grass vec3 base = mix(low, high, h01); float slope = 1.0 - abs(N.z); // 0 = flat up, 1 = vertical base *= mix(1.0, 0.8, slope); // darker on steep slopes vec3 ambient = vec3(0.08); vec3 color = ambient + base * (uAlbedo.rgb * ndl); oColor = vec4(color, 1.0); }