]> git.tdb.fi Git - libs/gl.git/blob - source/effects/shadowmap.cpp
Some more cleanup of includes and forward declarations
[libs/gl.git] / source / effects / shadowmap.cpp
1 #include "light.h"
2 #include "renderer.h"
3 #include "resources.h"
4 #include "shadowmap.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10
11 ShadowMap::ShadowMap(unsigned s, Renderable &r, const Light &l, Renderable &c):
12         Effect(r),
13         size(s),
14         light(l),
15         shadow_caster(c),
16         sampler(Resources::get_global().get<Sampler>("_linear_clamp_shadow.samp")),
17         radius(1),
18         depth_bias(4),
19         rendered(false)
20 {
21         depth_buf.storage(DEPTH_COMPONENT32F, size, size, 1);
22         fbo.set_format((DEPTH_ATTACHMENT,DEPTH_COMPONENT32F));
23         fbo.attach(DEPTH_ATTACHMENT, depth_buf, 0);
24
25         depth_test.enabled = true;
26         depth_test.compare = LEQUAL;
27
28         set_darkness(1.0f);
29         shdata.uniform("shd_world_matrix", Matrix());
30 }
31
32 void ShadowMap::set_target(const Vector3 &t, float r)
33 {
34         target = t;
35         radius = r;
36 }
37
38 void ShadowMap::set_darkness(float d)
39 {
40         if(d<0.0f || d>1.0f)
41                 throw invalid_argument("ShadowMap::set_darkness");
42
43         shdata.uniform("shadow_darkness", d);
44 }
45
46 void ShadowMap::set_depth_bias(float b)
47 {
48         if(b<0.0f)
49                 throw invalid_argument("ShadowMap::set_depth_bias");
50
51         depth_bias = b;
52 }
53
54 void ShadowMap::setup_frame(Renderer &renderer)
55 {
56         if(rendered)
57                 return;
58
59         rendered = true;
60         renderable.setup_frame(renderer);
61         shadow_caster.setup_frame(renderer);
62
63         shadow_camera.set_object_matrix(*light.get_matrix());
64         shadow_camera.set_position(target);
65         // TODO support point and spot lights with a frustum projection.
66         // Omnidirectional lights also need a cube shadow map.
67         shadow_camera.set_orthographic(radius*2, radius*2);
68         shadow_camera.set_depth_clip(-radius, radius);
69
70         shadow_matrix = shadow_camera.get_object_matrix();
71         shadow_matrix.scale(radius*2, radius*2, -radius*2);
72         shadow_matrix.translate(-0.5, -0.5, depth_bias/size-0.5);
73         shadow_matrix.invert();
74
75         shdata.uniform("shd_world_matrix", shadow_matrix);
76
77         Renderer::Push push(renderer);
78         renderer.set_framebuffer(&fbo);
79         renderer.set_camera(shadow_camera);
80         renderer.set_depth_test(&depth_test);
81
82         renderer.render(shadow_caster);
83 }
84
85 void ShadowMap::finish_frame()
86 {
87         if(rendered)
88         {
89                 rendered = false;
90                 renderable.finish_frame();
91         }
92 }
93
94 void ShadowMap::render(Renderer &renderer, Tag tag) const
95 {
96         if(!enabled_passes.count(tag))
97                 return renderer.render(renderable, tag);
98
99         Renderer::Push _push_rend(renderer);
100
101         renderer.set_texture("shadow_map", &depth_buf, &sampler);
102         renderer.add_shader_data(shdata);
103         renderer.render(renderable, tag);
104 }
105
106 void ShadowMap::set_debug_name(const string &name)
107 {
108 #ifdef DEBUG
109         fbo.set_debug_name(name+" [FBO]");
110         shadow_camera.set_debug_name(name+".camera");
111         depth_buf.set_debug_name(name+"/depth.tex2d");
112         shdata.set_debug_name(name+" [UBO]");
113 #else
114         (void)name;
115 #endif
116 }
117
118 } // namespace GL
119 } // namespace Msp