#version 460 core layout(location = 0) out vec4 color; in vec4 vColor; in vec3 vNormal; in vec3 vPosition; void main() { vec3 lightDirection = normalize(vec3(0.8, -0.5, 0.6)); // ambient component float ambientStrength = 0.1; vec3 ambient = ambientStrength * vColor.rgb; // terrain bump mapping with multi‐octave noise based on world position float bumpStrength = 0.4; float n1 = fract(sin(dot(vPosition.xz, vec2(12.9898, 78.233))) * 43758.5453); float n2 = fract(sin(dot(vPosition.xz * 0.5, vec2(93.9898, 67.345))) * 24634.6345); float noiseVal = mix(n1, n2, 0.5); vec3 bumpNormal = normalize(vNormal + bumpStrength * (noiseVal - 0.5) * vec3(1.0)); // diffuse component (Lambert) with bump float lambert = max(0.0, dot(normalize(bumpNormal), -lightDirection)); vec3 diffuse = vColor.rgb * lambert; // combine ambient and diffuse vec3 result = ambient + diffuse; // specular component (Phong) float shininess = 32.0; vec3 viewDir = vec3(0.0, 0.0, 1.0); vec3 reflectDir = reflect(-lightDirection, bumpNormal); float spec = pow(max(dot(reflectDir, viewDir), 0.0), shininess); float specStrength = 0.5; vec3 specular = specStrength * spec * vec3(1.0); result += specular; color = vec4(result, vColor.a); }