Light direction is now computed in fragment shader because interface
variable locations can't use specialization constants.
Shadow map currently only affects the first light but will be improved
soon.
mat4 vertex_tf = get_vertex_transform();
mat3 normal_tf = get_normal_transform();
mat4 vertex_tf = get_vertex_transform();
mat3 normal_tf = get_normal_transform();
- vec4 world_vertex = vertex_tf*get_vertex_position();
+ out vec4 world_vertex = vertex_tf*get_vertex_position();
vec4 eye_vertex = eye_world_matrix*world_vertex;
gl_Position = clip_eye_matrix*eye_vertex;
vec4 eye_vertex = eye_world_matrix*world_vertex;
gl_Position = clip_eye_matrix*eye_vertex;
vec3 eye_pos = (inverse(eye_world_matrix)*vec4(0.0, 0.0, 0.0, 1.0)).xyz;
out vec3 world_look_dir = normalize(world_vertex.xyz-eye_pos);
vec3 eye_pos = (inverse(eye_world_matrix)*vec4(0.0, 0.0, 0.0, 1.0)).xyz;
out vec3 world_look_dir = normalize(world_vertex.xyz-eye_pos);
- out vec3 world_light_dir = light_sources[0].position.xyz-world_vertex.xyz*light_sources[0].position.w;
-
out float fog_coord = eye_vertex.z;
if(use_clipping)
out float fog_coord = eye_vertex.z;
if(use_clipping)
return normalize(world_normal);
}
return normalize(world_normal);
}
+virtual vec3 get_light_direction(int index)
+{
+ vec4 light_pos = light_sources[index].position;
+ return normalize(light_pos.xyz-world_vertex.xyz*light_pos.w);
+}
+
virtual vec3 get_environment_sample(vec3 direction, float roughness)
{
float lod = (2-roughness)*roughness*(textureQueryLevels(environment_map)-1);
virtual vec3 get_environment_sample(vec3 direction, float roughness)
{
float lod = (2-roughness)*roughness*(textureQueryLevels(environment_map)-1);
vec3 cooktorrance_lighting(vec3 normal, vec3 look, vec3 base_color, float metalness, float roughness)
{
vec3 cooktorrance_lighting(vec3 normal, vec3 look, vec3 base_color, float metalness, float roughness)
{
- vec3 light = normalize(world_light_dir);
-
- float shadow = get_shadow_factor(0);
- vec3 color = cooktorrance_one_light_direct(normal, look, light, light_sources[0].color, base_color, metalness, roughness)*shadow;
+ vec3 color = vec3(0.0);
+ for(int i=0; i<max_lights; ++i)
+ if(light_sources[i].enabled!=0)
+ {
+ vec3 light = get_light_direction(i);
+ float shadow = get_shadow_factor(i);
+ color += cooktorrance_one_light_direct(normal, look, light, light_sources[i].color, base_color, metalness, roughness)*shadow;
+ }
color += cooktorrance_environment(normal, look, base_color, metalness, roughness);
color += cooktorrance_environment(normal, look, base_color, metalness, roughness);
{
vec4 position;
vec3 color;
{
vec4 position;
vec3 color;
+layout(constant_id=auto) const int max_lights = 4;
- // Declared as an array for compatibility reasons
- LightSourceParameters light_sources[1];
+ LightSourceParameters light_sources[max_lights];
vec4 ambient_color;
vec4 fog_color;
float fog_density;
vec4 ambient_color;
vec4 fog_color;
float fog_density;
vec3 phong_lighting(vec3 normal, vec3 look, vec3 surface_diffuse, vec3 surface_specular, float shininess)
{
vec3 phong_lighting(vec3 normal, vec3 look, vec3 surface_diffuse, vec3 surface_specular, float shininess)
{
- vec3 light = normalize(world_light_dir);
-
vec3 color = phong_ambient(surface_diffuse);
vec3 color = phong_ambient(surface_diffuse);
- float shadow = get_shadow_factor(0);
- color += phong_one_light(light, normal, look, light_sources[0].color, surface_diffuse, surface_specular, shininess)*shadow;
+ for(int i=0; i<max_lights; ++i)
+ if(light_sources[i].enabled!=0)
+ {
+ vec3 light = get_light_direction(i);
+ float shadow = get_shadow_factor(i);
+ color += phong_one_light(light, normal, look, light_sources[i].color, surface_diffuse, surface_specular, shininess)*shadow;
+ }
if(use_emission)
color += get_emission_color();
if(use_emission)
color += get_emission_color();
- if(shadow_coord.x<0 || shadow_coord.x>1 || shadow_coord.y<0 || shadow_coord.y>1)
+ if(index>0 || shadow_coord.x<0 || shadow_coord.x>1 || shadow_coord.y<0 || shadow_coord.y>1)
return 1.0;
float shadow_sample = texture(shadow_map, shadow_coord);
return mix(1.0, shadow_sample, shadow_darkness);
return 1.0;
float shadow_sample = texture(shadow_map, shadow_coord);
return mix(1.0, shadow_sample, shadow_darkness);
set_ambient(0.2f);
set_fog_color(Color(0.0f, 0.0f, 0.0f, 0.0f));
set_fog_density(0.0f);
set_ambient(0.2f);
set_fog_color(Color(0.0f, 0.0f, 0.0f, 0.0f));
set_fog_density(0.0f);
+
+ for(unsigned i=0; i<8; ++i)
+ {
+ string base = format("light_sources[%d]", i);
+ shdata.uniform(base+".position", Vector4(0, 0, 1, 0));
+ shdata.uniform(base+".color", 0.0f, 0.0f, 0.0f);
+ shdata.uniform(base+".enabled", 0);
+ }
}
void Lighting::set_ambient(const Color &a)
}
void Lighting::set_ambient(const Color &a)
{
auto i = find_member(lights, &l, &AttachedLight::light);
if(i!=lights.end())
{
auto i = find_member(lights, &l, &AttachedLight::light);
if(i!=lights.end())
+ shdata.uniform(format("light_sources[%d].enabled", lights.size()), 0);
+ }
}
const ProgramData &Lighting::get_shader_data() const
}
const ProgramData &Lighting::get_shader_data() const