in vec2 vs_tile_tex_coords; in vec3 frag_position; #ifdef USE_SHADOW in vec4 vs_pos_light_space; #endif // USE_SHADOW #ifdef USE_NOISE in vec3 vs_noise_tex_coords; #endif // USE_NOISE out vec4 frag_color; struct DirectionalLight { vec3 direction; vec3 ambient; vec3 diffuse; //vec3 specular; }; struct PositionalLight { vec3 position; float constant_attenuation; float linear_attenuation; float quadratic_attenuation; vec3 ambient; vec3 diffuse; // vec3 specular; }; // All water tiles are horizontally flat surfaces const vec3 normal = vec3(0.0, 0.0, 1.0); // gl_LightModel.ambient. Client never sets it, so use default value of: const vec3 lightmodel_ambient = vec3(0.2, 0.2, 0.2); // This is the value of glColor when the shader is called const vec4 white = vec4(1.0, 1.0, 1.0, 1.0); uniform sampler2D tile_texture; uniform DirectionalLight directional_light; uniform PositionalLight positional_lights[8]; uniform int nr_positional_lights; #ifdef USE_REFLECTION uniform sampler2D reflection_texture; uniform vec4 viewport; uniform float blend; #endif // USE_REFLECTION #ifdef USE_SHADOW uniform sampler2DShadow shadow_texture; #endif // USE_SHADOW #ifdef USE_NOISE uniform sampler3D noise_texture; uniform vec4 noise_scale; #endif // USE_NOISE #ifdef USE_CUBIC_FILTER uniform sampler1D hg_texture; uniform vec2 size; uniform vec2 texel_size_x; uniform vec2 texel_size_y; #endif // USE_CUBIC_FILTER #ifdef USE_FOG uniform float fog_density; uniform vec4 fog_color; #endif // USE_FOG void calc_directional_light(DirectionalLight light, vec3 normal, out vec3 ambient, out vec3 diffuse) { vec3 light_direction = normalize(-light.direction); float diff = max(dot(normal, light_direction), 0.0); ambient = light.ambient; diffuse = light.diffuse * diff; } void calc_positional_light(PositionalLight light, vec3 position, out vec3 ambient, out vec3 diffuse) { vec3 light_direction = normalize(light.position - position); float diff = max(dot(normal, light_direction), 0.0); float dist = length(light.position - position); float attenuation = 1.0 / (light.constant_attenuation + light.linear_attenuation * dist + light.quadratic_attenuation * dist * dist); ambient = light.ambient * attenuation; diffuse = light.diffuse * diff * attenuation; } void main (void) { vec3 ambient, diffuse; calc_directional_light(directional_light, normal, ambient, diffuse); for (int i = 0; i < nr_positional_lights; ++i) { vec3 p_ambient, p_diffuse; calc_positional_light(positional_lights[i], frag_position, p_ambient, p_diffuse); ambient += p_ambient; diffuse += p_diffuse; } ambient += lightmodel_ambient; vec4 light_color = vec4(ambient + diffuse, 1.0); vec2 tile_tex_coords = vs_tile_tex_coords; vec4 color, light; #ifdef USE_REFLECTION vec2 reflection_tex_coords = (gl_FragCoord.xy - viewport.xy) / viewport.zw; #endif // USE_REFLECTION #ifdef USE_NOISE vec2 noise_displacement = texture(noise_texture, vs_noise_tex_coords).ga * 2.0 - 1.0; #ifdef USE_REFLECTION reflection_tex_coords += noise_displacement * noise_scale.xy; #endif // USE_REFLECTION tile_tex_coords += noise_displacement * noise_scale.zw; #endif // USE_NOISE #ifdef USE_SHADOW vec4 shadow_color = vec4(ambient, 1.0); float shadow = textureProj(shadow_texture, vs_pos_light_space); light = mix(shadow_color, light_color, shadow); #else // USE_SHADOW light = light_color; #endif // USE_SHADOW vec4 tile_color = light * texture(tile_texture, tile_tex_coords); #ifdef USE_REFLECTION #ifdef USE_CUBIC_FILTER vec2 coord_hg = reflection_tex_coords * size - vec2(0.5, 0.5); vec3 hg_x = texture(hg_texture, coord_hg.x).xyz; vec3 hg_y = texture(hg_texture, coord_hg.y).xyz; vec2 reflection_tex_coord10 = reflection_tex_coords + hg_x.x * texel_size_x; vec2 reflection_tex_coord00 = reflection_tex_coords - hg_x.y * texel_size_x; vec2 reflection_tex_coord11 = reflection_tex_coords + hg_y.x * texel_size_y; vec2 reflection_tex_coord01 = reflection_tex_coords + hg_y.x * texel_size_y; reflection_tex_coord10 -= hg_y.y * texel_size_y; reflection_tex_coord00 -= hg_y.y * texel_size_y; vec4 color00 = texture(reflection_texture, reflection_tex_coord00); vec4 color10 = texture(reflection_texture, reflection_tex_coord10); vec4 color01 = texture(reflection_texture, reflection_tex_coord01); vec4 color11 = texture(reflection_texture, reflection_tex_coord11); color00 = mix(color00, color01, hg_y.z); color10 = mix(color10, color11, hg_y.z); color = mix(color00, color10, hg_x.z); #else // USE_CUBIC_FILTER color = texture(reflection_texture, reflection_tex_coords); #endif // USE_CUBIC_FILTER frag_color = mix(tile_color, color, blend); #else // USE_REFLECTION frag_color = tile_color; #endif // USE_REFLECTION #ifdef USE_FOG const float LOG2 = 1.442695; float fog = fog_density * gl_FragCoord.z / gl_FragCoord.w; fog = exp2(-fog*fog*LOG2); frag_color = mix(fog_color, frag_color, fog); #endif // USE_FOG }