#version 330 core in vec3 v_normal; in vec2 v_tex; in vec3 v_position; out vec4 frag_color; uniform vec3 u_light; // direction TO the light (normalized) uniform sampler2D tex; uniform vec3 color; // base colour factor (acts as solid colour when no texture) void main() { // Combine base texture (or constant white) with colour factor supplied by CPU. vec3 base_col = texture(tex, v_tex).rgb * color; vec3 N = normalize(v_normal); vec3 L = normalize(u_light); // Classic Blinn-Phong lighting // Ambient: always present vec3 ambient = base_col * 0.15; // Diffuse: N dot L, clamped float NdotL = max(dot(N, L), 0.0); vec3 diffuse = base_col * NdotL * 0.7; // Specular: only on surfaces facing the light (NdotL > 0) float specular = 0.0; if (NdotL > 0.0) { vec3 V = normalize(-v_position); // view direction (camera at origin in view space) vec3 H = normalize(L + V); // half-vector float NdotH = max(dot(N, H), 0.0); specular = pow(NdotH, 32.0) * 0.5; // tighter highlight, moderated intensity } vec3 result = ambient + diffuse + vec3(specular); // Convert from linear to sRGB for display (approximate gamma correction) result = pow(result, vec3(1.0 / 2.2)); frag_color = vec4(result, 1.0); }