]> git.tdb.fi Git - libs/gl.git/commitdiff
Suppoer per-light shadow casters in ShadowMap
authorMikko Rasa <tdb@tdb.fi>
Mon, 11 Oct 2021 12:40:22 +0000 (15:40 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 11 Oct 2021 12:40:22 +0000 (15:40 +0300)
Different types of lights may require different shaders for rendering
shadow maps, or it may be desirable to use different occluder geometry
for far away lights than close ones.

source/effects/shadowmap.cpp
source/effects/shadowmap.h

index bfb053421440d98bdd3164a6e16d092e1479aa47..74dad5e78b74fb6d32505008ca2ecf15d262600b 100644 (file)
@@ -11,12 +11,11 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
-ShadowMap::ShadowMap(unsigned w, unsigned h, Renderable &r, const Lighting *l, Renderable &c):
+ShadowMap::ShadowMap(unsigned w, unsigned h, Renderable &r, const Lighting *l):
        Effect(r),
        width(w),
        height(h),
        lighting(l),
-       shadow_caster(c),
        sampler(Resources::get_global().get<Sampler>("_linear_clamp_shadow.samp"))
 {
        depth_buf.storage(DEPTH_COMPONENT32F, width, height, 1);
@@ -35,16 +34,16 @@ ShadowMap::ShadowMap(unsigned w, unsigned h, Renderable &r, const Lighting *l, R
 }
 
 ShadowMap::ShadowMap(unsigned s, Renderable &r, const DirectionalLight &l, Renderable &c):
-       ShadowMap(s, s, r, 0, c)
+       ShadowMap(s, s, r, 0)
 {
-       add_light(l, s);
+       add_light(l, s, c);
 }
 
-ShadowMap::ShadowMap(unsigned w, unsigned h, Renderable &r, const Lighting &l, Renderable &c):
-       ShadowMap(w, h, r, &l, c)
+ShadowMap::ShadowMap(unsigned w, unsigned h, Renderable &r, const Lighting &l):
+       ShadowMap(w, h, r, &l)
 { }
 
-void ShadowMap::add_light(const DirectionalLight &light, unsigned s)
+void ShadowMap::add_light(const DirectionalLight &light, unsigned s, Renderable &c)
 {
        if(!lighting && !lights.empty())
                throw invalid_operation("ShadowMap::add_light");
@@ -90,6 +89,7 @@ void ShadowMap::add_light(const DirectionalLight &light, unsigned s)
        sl.light = &light;
        sl.index = index;
        sl.region = region;
+       sl.shadow_caster = &c;
 
        string base = format("shadows[%d]", index);
        shdata.uniform(base+".enabled", 1);
@@ -138,7 +138,8 @@ void ShadowMap::setup_frame(Renderer &renderer)
 
        rendered = true;
        renderable.setup_frame(renderer);
-       shadow_caster.setup_frame(renderer);
+       for(const ShadowedLight &l: lights)
+               l.shadow_caster->setup_frame(renderer);
 
        for(ShadowedLight &l: lights)
        {
@@ -163,7 +164,7 @@ void ShadowMap::setup_frame(Renderer &renderer)
                renderer.set_scissor(&l.region);
                renderer.set_camera(l.shadow_camera);
 
-               renderer.render(shadow_caster);
+               renderer.render(*light.shadow_caster);
        }
 }
 
index 611f56f51040a2204055e29f37d0e67a68d48b7c..6c4e1e501713d84aa393652b8eefb32912a3a0ec 100644 (file)
@@ -30,13 +30,13 @@ private:
                unsigned index;
                Rect region;
                Camera shadow_camera;
+               Renderable *shadow_caster;
        };
 
        unsigned width;
        unsigned height;
        const Lighting *lighting;
        std::vector<ShadowedLight> lights;
-       Renderable &shadow_caster;
        Framebuffer fbo;
        Texture2D depth_buf;
        const Sampler &sampler;
@@ -48,12 +48,12 @@ private:
        bool rendered = false;
        std::string debug_name;
 
-       ShadowMap(unsigned, unsigned, Renderable &, const Lighting *, Renderable &);
+       ShadowMap(unsigned, unsigned, Renderable &, const Lighting *);
 public:
        ShadowMap(unsigned, Renderable &, const DirectionalLight &, Renderable &);
-       ShadowMap(unsigned, unsigned, Renderable &, const Lighting &, Renderable &);
+       ShadowMap(unsigned, unsigned, Renderable &, const Lighting &);
 
-       void add_light(const DirectionalLight &, unsigned);
+       void add_light(const DirectionalLight &, unsigned, Renderable &);
 
        /** Sets the ShadowMap target point and radius.  The transformation matrix is
        computed so that a sphere with the specified parameters will be completely