From d4b030f46c3a643e813cf31e3faa2b4f3662a160 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 3 Oct 2021 13:57:19 +0300 Subject: [PATCH] Support multiple lights in a single pass 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 | 10 +++++++--- shaderlib/cooktorrance.glsl | 12 ++++++++---- shaderlib/msp_interface.glsl | 5 +++-- shaderlib/phong.glsl | 11 +++++++---- shaderlib/shadow.glsl | 2 +- source/materials/lighting.cpp | 11 +++++++++++ 6 files changed, 37 insertions(+), 14 deletions(-) diff --git a/shaderlib/common.glsl b/shaderlib/common.glsl index dd8ac11f..b393b2a0 100644 --- a/shaderlib/common.glsl +++ b/shaderlib/common.glsl @@ -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); diff --git a/shaderlib/cooktorrance.glsl b/shaderlib/cooktorrance.glsl index 4b0c4dc8..7eefbf60 100644 --- a/shaderlib/cooktorrance.glsl +++ b/shaderlib/cooktorrance.glsl @@ -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; i1 || 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); diff --git a/source/materials/lighting.cpp b/source/materials/lighting.cpp index 20c812fe..cd04d1b4 100644 --- a/source/materials/lighting.cpp +++ b/source/materials/lighting.cpp @@ -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 -- 2.43.0