]> git.tdb.fi Git - libs/gl.git/commitdiff
Support multiple lights in a single pass
authorMikko Rasa <tdb@tdb.fi>
Sun, 3 Oct 2021 10:57:19 +0000 (13:57 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 3 Oct 2021 16:29:55 +0000 (19:29 +0300)
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.

shaderlib/common.glsl
shaderlib/cooktorrance.glsl
shaderlib/msp_interface.glsl
shaderlib/phong.glsl
shaderlib/shadow.glsl
source/materials/lighting.cpp

index dd8ac11f2564642078f9360aef97317e79b07497..b393b2a0daf2d7e0398a348b60eb4d9753ad2f47 100644 (file)
@@ -38,7 +38,7 @@ void standard_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;
 
@@ -50,8 +50,6 @@ void standard_transform()
        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)
@@ -83,6 +81,12 @@ virtual vec3 get_fragment_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);
index 4b0c4dc814ca5b16e903d7003f1371b96b3c6503..7eefbf60eb52e96a9ab320e6c9c42e1ccc4d1e40 100644 (file)
@@ -151,10 +151,14 @@ vec3 cooktorrance_environment(vec3 normal, vec3 look, vec3 base_color, float met
 
 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);
 
index 6c229da0f32da92fc9bd76db74241a5542fba478..23c612051248281c9a3bc9795cf11163e2b2f5d1 100644 (file)
@@ -2,6 +2,7 @@ struct LightSourceParameters
 {
        vec4 position;
        vec3 color;
+       int enabled;
 };
 
 struct ClipPlane
@@ -19,10 +20,10 @@ uniform CameraTransform
        mat4 eye_clip_matrix;
 };
 
+layout(constant_id=auto) const int max_lights = 4;
 uniform Lighting
 {
-       // 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;
index 7d8dc295bc93ad95f26ef3d01143c63ec7d3ecb7..87eba5eadf38bce9ba1c6873a4dd18b2dcb2f841 100644 (file)
@@ -94,11 +94,14 @@ vec3 phong_one_light(vec3 light, vec3 normal, vec3 look, vec3 light_color, vec3
 
 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);
-       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();
index 04cf6832dcffd19a6a4949c1049b98e0f2b64a40..65b003f43bcdef2295678d88624d45a5ed7089d2 100644 (file)
@@ -21,7 +21,7 @@ virtual float get_shadow_factor(int index)
 {
        if(use_shadow_map)
        {
-               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);
index 20c812fe58cfd3e6ee7434bef5f10707db67f01c..cd04d1b4af153a981973c75e7eb8ff642d8f7545 100644 (file)
@@ -17,6 +17,14 @@ Lighting::Lighting()
        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)
@@ -55,7 +63,10 @@ void Lighting::detach(const Light &l)
 {
        auto i = find_member(lights, &l, &AttachedLight::light);
        if(i!=lights.end())
+       {
                lights.erase(i);
+               shdata.uniform(format("light_sources[%d].enabled", lights.size()), 0);
+       }
 }
 
 const ProgramData &Lighting::get_shader_data() const