////////////////////////////////////////////////
// UNIFORMS
////////////////////////////////////////////////
// the main texture (diffuse color)
uniform sampler2D texture;
// the normal map texture
uniform sampler2D normal_map;
// material specular
uniform float specular = 1.0f;
// ambient light
uniform vec3 light_ambient_color = vec3(0,0,0);
// factor to multiply light distance so that no matter what the screen size is lights will be at the same size
uniform float lights_size_factor = 1.0f;
// create a light uniform with unique index
uniform vec3 light_0_position = vec3(0,0,0);
uniform vec4 light_0_color = vec4(0,0,0,0);
uniform float light_0_glow = 1.0f;
uniform vec3 light_1_position = vec3(0,0,0);
uniform vec4 light_1_color = vec4(0,0,0,0);
uniform float light_1_glow = 1.0f;
uniform vec3 light_2_position = vec3(0,0,0);
uniform vec4 light_2_color = vec4(0,0,0,0);
uniform float light_2_glow = 1.0f;
uniform vec3 light_3_position = vec3(0,0,0);
uniform vec4 light_3_color = vec4(0,0,0,0);
uniform float light_3_glow = 1.0f;
uniform vec3 light_4_position = vec3(0,0,0);
uniform vec4 light_4_color = vec4(0,0,0,0);
uniform float light_4_glow = 1.0f;
uniform vec3 light_5_position = vec3(0,0,0);
uniform vec4 light_5_color = vec4(0,0,0,0);
uniform float light_5_glow = 1.0f;
uniform vec3 light_6_position = vec3(0,0,0);
uniform vec4 light_6_color = vec4(0,0,0,0);
uniform float light_6_glow = 1.0f;
uniform vec3 light_7_position = vec3(0,0,0);
uniform vec4 light_7_color = vec4(0,0,0,0);
uniform float light_7_glow = 1.0f;
uniform vec3 light_8_position = vec3(0,0,0);
uniform vec4 light_8_color = vec4(0,0,0,0);
uniform float light_8_glow = 1.0f;
uniform vec3 light_9_position = vec3(0,0,0);
uniform vec4 light_9_color = vec4(0,0,0,0);
uniform float light_9_glow = 1.0f;
// will store the 3d position of the fragment
vec3 frag_pos;
// calc the strength of a light for a given pixel
vec3 calc_light(vec3 light_pos, vec4 light_color, vec4 normal, float light_glow)
{
// get vector from light source to frag
vec3 positionToLightSource = light_pos - frag_pos;
float distance_fac = length(positionToLightSource);
// calc distance factor
float str = (light_color.a * 10000.0) / (pow(distance_fac, 2) * pow(lights_size_factor, 2)) / (100.0f * light_color.a);
// wrap value and calc normal map factor
positionToLightSource.y *= -1.0;
positionToLightSource = normalize(positionToLightSource).xyz * (specular * light_glow);
str = min(1, str) * (max(dot(normal.xyz, positionToLightSource.xyz), 0.0));
// return light strength on fragment
return light_color.rgb * str;
}
////////////////////////////////////////////////
// main loop
////////////////////////////////////////////////
void main()
{
// get fragment texture and normal
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
// if invisible stop here
if (pixel.a * gl_Color.a == 0.0f)
{
gl_FragColor = vec4(0.0f, 0.0f, 0.0f, 0.0f);
return;
}
vec4 normal = texture2D(normal_map, gl_TexCoord[0].xy);
// get the 3d position of the current fragment
// IMPORTANT NOTICE: X AND Y THE POSITION, Z IS HEIGHT ABOVE THE FLOOR
frag_pos = vec3(gl_FragCoord.x, gl_FragCoord.y, 0);
frag_pos.z = (normal.a - 0.5f) * 50.0;
// fix normal
normal = normalize(normal - 0.5);
// calculate light on this fragment
vec4 light_str = vec4(0,0,0,1);
if (light_0_color.a > 0) light_str.rgb += calc_light(light_0_position, light_0_color, normal, light_0_glow);
if (light_1_color.a > 0) light_str.rgb += calc_light(light_1_position, light_1_color, normal, light_1_glow);
if (light_2_color.a > 0) light_str.rgb += calc_light(light_2_position, light_2_color, normal, light_2_glow);
if (light_3_color.a > 0) light_str.rgb += calc_light(light_3_position, light_3_color, normal, light_3_glow);
if (light_4_color.a > 0) light_str.rgb += calc_light(light_4_position, light_4_color, normal, light_4_glow);
if (light_5_color.a > 0) light_str.rgb += calc_light(light_5_position, light_5_color, normal, light_5_glow);
if (light_6_color.a > 0) light_str.rgb += calc_light(light_6_position, light_6_color, normal, light_6_glow);
if (light_7_color.a > 0) light_str.rgb += calc_light(light_7_position, light_7_color, normal, light_7_glow);
if (light_8_color.a > 0) light_str.rgb += calc_light(light_8_position, light_8_color, normal, light_8_glow);
if (light_9_color.a > 0) light_str.rgb += calc_light(light_9_position, light_9_color, normal, light_9_glow);
light_str.rgb += light_ambient_color;
light_str = (floor(light_str * 3.5f) / 3.5f);
light_str.a = 1.0f; // so we won't effect opacity due to lighting
// calculate the output color: vertex color * texture * light
gl_FragColor = gl_Color * pixel * light_str;
}
excuse those ugly copy-pastas, its because (as far as I know) sfml can't set array of uniforms or structs.
anyway in the cpp side I do something like this to set a light:
void Graphics::add_light(const SLight& light, unsigned int index)
{
// fix light position
sf::Vector2f pos(light.position.x, light.position.y);
pos = (sf::Vector2f)m_window.mapCoordsToPixel(pos, m_view);
sf::Vector3f pos_convert(pos.x, get_window_size().y - pos.y, light.position.z);
// set light params
m_shader.setParameter("light_" + std::to_string((long long)index) + "_position", pos_convert);
m_shader.setParameter("light_" + std::to_string((long long)index) + "_glow", light.glow);
m_shader.setParameter("light_" + std::to_string((long long)index) + "_color", light.color);
}