#version 460 core in vec3 FragPos; in vec2 TexCoords; in vec3 Normal; out vec4 FragColor; uniform vec3 cameraPos; uniform vec3 lightPos; // Material constants const vec3 waterShallowColor = vec3(0.0, 0.6, 0.7); const vec3 waterDeepColor = vec3(0.05, 0.15, 0.3); const vec3 sunColor = vec3(1.0, 0.95, 0.8); void main() { // Normalize vectors vec3 n = normalize(Normal); vec3 viewDir = normalize(cameraPos - FragPos); vec3 lightDir = normalize(lightPos - FragPos); // 1. Ambient Lighting vec3 ambient = 0.3 * waterShallowColor; // 2. Diffuse Shading float diff = max(dot(n, lightDir), 0.0); vec3 diffuse = diff * sunColor * 0.4; // 3. Specular Highlights (Blinn-Phong) vec3 halfwayDir = normalize(lightDir + viewDir); float spec = pow(max(dot(n, halfwayDir), 0.0), 64.0); // High shininess for water glaze vec3 specular = spec * sunColor * 0.8; // 4. Fresnel Approximation (Schlick's approximation) // Water has a base reflectivity of roughly 0.02 at a perpendicular view angle float F0 = 0.02; float fresnel = F0 + (1.0 - F0) * pow(1.0 - max(dot(n, viewDir), 0.0), 5.0); // Mix deep and shallow water colors based on the normal angle vec3 baseWaterColor = mix(waterShallowColor, waterDeepColor, max(dot(n, vec3(0.0, 1.0, 0.0)), 0.0)); // Combine lighting results vec3 lightingResult = ambient + diffuse + specular; // Blend final look with Fresnel reflection dominance vec3 finalColor = mix(baseWaterColor + specular, lightingResult + vec3(fresnel * 0.5), fresnel); // Output final color with subtle translucency opacity FragColor = vec4(finalColor, 0.85); }