# Source code of the fragment shader
	fun fragment_shader_source: Text is abstract
					lib/gamnit/programs.nit:503,2--504,45
				
	redef var fragment_shader_source = """
		precision mediump float;
		// Does this object use a texture?
		uniform bool use_texture;
		// Texture to apply on this object
		uniform sampler2D texture0;
		// Texture to apply on this object
		uniform sampler2D animation;
		// Input from the vertex shader
		varying vec4 v_color;
		varying vec2 v_coord;
		varying float v_animated;
		void main()
		{
			if (v_animated > 0.5) {
				gl_FragColor = v_color * texture2D(animation, v_coord);
				if (gl_FragColor.a <= 0.01) discard;
			} else if (use_texture) {
				gl_FragColor = v_color * texture2D(texture0, v_coord);
				if (gl_FragColor.a <= 0.01) discard;
			} else {
				gl_FragColor = v_color;
			}
		}
		""" @ glsl_fragment_shader
					lib/gamnit/flat/flat_core.nit:722,2--751,28
				
	redef var fragment_shader_source = """
		precision mediump float;
		// Virtual screen texture / color attachment
		uniform sampler2D texture0;
		// Input from the vertex shader
		varying vec2 v_coord;
		// Ratio of the virtual screen to draw
		uniform float ratio;
		void main()
		{
			gl_FragColor = texture2D(texture0, v_coord*ratio);
		}
		""" @ glsl_fragment_shader
					lib/gamnit/dynamic_resolution.nit:325,2--341,28
				
	redef var fragment_shader_source = """
		precision mediump float;
		// Input from the vertex shader
		varying vec2 v_tex_coord;
		varying vec3 v_normal;
		varying vec4 v_to_light;
		varying vec4 v_to_camera;
		varying vec4 v_depth_pos;
		varying float v_alpha;
		// Colors
		uniform vec4 ambient_color;
		uniform vec4 diffuse_color;
		uniform vec4 specular_color;
		// Ambient map
		uniform bool use_map_ambient;
		uniform sampler2D map_ambient;
		// Diffuse map
		uniform bool use_map_diffuse;
		uniform sampler2D map_diffuse;
		// Specular map
		uniform bool use_map_specular;
		uniform sampler2D map_specular;
		// Bump map
		uniform bool use_map_bump;
		uniform sampler2D map_bump;
		// Normal map
		uniform bool use_map_normal;
		uniform sampler2D map_normal;
		// Shadow
		uniform lowp int light_kind;
		uniform bool use_shadows;
		uniform sampler2D depth_texture;
		uniform float depth_size;
		uniform int depth_taps;
		// Shadow effect on the diffuse colors of the fragment at offset `x, y`
		float shadow_lookup(vec2 depth_coord, float x, float y) {
			float tap_width = 1.0;
			float pixel_size = tap_width/depth_size;
			vec2 offset = vec2(x * pixel_size * v_depth_pos.w,
			                   y * pixel_size * v_depth_pos.w);
			depth_coord += offset;
			float depth = v_depth_pos.z/v_depth_pos.w;
			//vec2 depth_coord = v_depth_pos.xy/v_depth_pos.w;
			if (depth_coord.x < 0.0 || depth_coord.x > 1.0 || depth_coord.y < 0.0 || depth_coord.y > 1.0) {
				// Out of the shadow map texture
				//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // debug, red out of the light view
				return 1.0;
			}
			float shadow_depth = texture2D(depth_texture, depth_coord).r;
			float bias = 0.0001;
			if (shadow_depth == 1.0) {
				// Too far to be in depth texture
				return 1.0;
			} else if (shadow_depth <= depth - bias) {
				// In a shadow
				//gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0); // debug, blue shadows
				return 0.2; // TODO replace with a configurable ambient light
			}
			//gl_FragColor = vec4(0.0, 1.0-(shadow_depth-depth), 0.0, 1.0); // debug, green lit surfaces
			return 1.0;
		}
		// Shadow effect on the diffuse colors of the fragment
		float shadow() {
			if (!use_shadows) return 1.0;
			vec2 depth_coord = v_depth_pos.xy/v_depth_pos.w;
			float taps = float(depth_taps);
			float tap_step = 2.00/taps;
			float sum = 0.0;
			for (float x = -1.0; x <= 0.99; x += tap_step)
				for (float y = -1.0; y <= 0.99; y += tap_step)
					sum += shadow_lookup(depth_coord, x, y);
			return sum / taps / taps;
		}
		void main()
		{
			// Normal
			vec3 normal = v_normal;
			if (use_map_bump) {
				// TODO
				vec3 bump = 2.0 * texture2D(map_bump, v_tex_coord).rgb - 1.0;
			}
			// Ambient light
			vec4 ambient = ambient_color * v_alpha;
			if (use_map_ambient) ambient *= texture2D(map_ambient, v_tex_coord);
			if (light_kind == 0) {
				// No light, show diffuse and ambient
				vec4 diffuse = diffuse_color * v_alpha;
				if (use_map_diffuse) diffuse *= texture2D(map_diffuse, v_tex_coord);
				gl_FragColor = ambient + diffuse;
			} else {
				// Parallel light or point light (1 or 2)
				// Diffuse Lambert light
				vec3 to_light = v_to_light.xyz;
				float lambert = clamp(dot(normal, to_light), 0.0, 1.0);
				vec4 diffuse = lambert * diffuse_color;
				if (use_map_diffuse) diffuse *= texture2D(map_diffuse, v_tex_coord);
				// Specular Phong light
				float s = 0.0;
				if (lambert > 0.0) {
					// In light
					vec3 l = reflect(-to_light, normal);
					s = clamp(dot(l, v_to_camera.xyz), 0.0, 1.0);
					s = pow(s, 8.0); // TODO make this `shininess` a material attribute
					// Shadows
					diffuse *= shadow();
				}
				vec4 specular = s * specular_color * v_alpha;
				if (use_map_specular) specular *= texture2D(map_specular, v_tex_coord).x;
				gl_FragColor = ambient + diffuse + specular;
			}
			if (gl_FragColor.a < 0.01) discard;
			//gl_FragColor = vec4(normalize(normal).rgb, 1.0); // Debug normals
		}
		""" @ glsl_fragment_shader
					lib/gamnit/depth/more_materials.nit:392,2--534,28
				
	redef var fragment_shader_source = """
		precision mediump float;
		// Diffuse map
		uniform bool use_map_diffuse;
		uniform sampler2D map_diffuse;
		varying vec2 v_tex_coord;
		void main()
		{
			if (use_map_diffuse && texture2D(map_diffuse, v_tex_coord).a <= 0.01) {
				discard;
			}
		}
		""" @ glsl_fragment_shader
					lib/gamnit/depth/shadow.nit:383,2--398,28
				
	redef var fragment_shader_source = """
		precision mediump float;
		// Virtual screen texture / color attachment
		uniform sampler2D texture0;
		// Input from the vertex shader
		varying vec2 v_coord;
		void main()
		{
			gl_FragColor = texture2D(texture0, v_coord);
		}
		""" @ glsl_fragment_shader
					lib/gamnit/depth/shadow.nit:449,2--462,28
				
	redef var fragment_shader_source = """
		precision mediump float;
		// Input from the vertex shader
		varying vec4 v_color;
		// Does this particle use a texture?
		uniform bool use_texture;
		// Texture to apply on this particle
		uniform sampler2D texture0;
		void main()
		{
			if (use_texture) {
				gl_FragColor = texture2D(texture0, gl_PointCoord) * v_color;
			} else {
				gl_FragColor = v_color;
			}
		}
		""" @ glsl_fragment_shader
					lib/gamnit/depth/particles.nit:255,2--275,28
				
	#
	redef var fragment_shader_source = """
		precision highp float;
		varying vec2 v_tex_coord;
		// Map used as reference for opacity
		uniform sampler2D map_diffuse;
		// Should `map_diffuse` be used?
		uniform bool use_map_diffuse;
		// Color ID
		uniform vec4 color;
		void main()
		{
			gl_FragColor = vec4(color.rgb, 1.0);
			if (use_map_diffuse && texture2D(map_diffuse, v_tex_coord).a < 0.1) {
				gl_FragColor.a = 0.0;
			}
		}
		""" @ glsl_fragment_shader
					lib/gamnit/depth/selection.nit:270,2--293,28
				
	redef var fragment_shader_source = """
		precision mediump float;
		// Input from the vertex shader
		varying vec3 v_normal;
		void main()
		{
			gl_FragColor = vec4(v_normal*0.5 + 0.5, 1.0);
		}
		""" @ glsl_fragment_shader
					lib/gamnit/depth/more_materials.nit:648,2--658,28