for(unsigned i=0; i<4; ++i)
{
string base = format("shadows[%d]", i);
- shdata.uniform(base+".enabled", 0);
+ shdata.uniform(base+".type", 0);
shdata.uniform(base+".darkness", 1.0f);
- shdata.uniform(base+".shd_world_matrix", Matrix());
+ shdata.uniform(base+".matrix_index", 0);
shdata.uniform(base+".region", Vector4(0.0f, 0.0f, 1.0f, 1.0f));
}
+
+ Matrix dummy_matrix;
+ shdata.uniform_array("shd_world_matrix", 1, &dummy_matrix);
}
ShadowMap::ShadowMap(unsigned s, Renderable &r, const DirectionalLight &l, Renderable &c):
{ }
void ShadowMap::add_light(const DirectionalLight &light, unsigned s, Renderable &c)
+{
+ add_light(light, s, DIRECTIONAL, c);
+}
+
+void ShadowMap::add_light(const Light &light, unsigned s, ShadowType type, Renderable &c)
{
if(!lighting && !lights.empty())
throw invalid_operation("ShadowMap::add_light");
sl.light = &light;
sl.index = index;
sl.region = region;
+ sl.type = type;
+ sl.view_index = views.size();
sl.shadow_caster = &c;
+ views.emplace_back();
+ ShadowView &view = views[sl.view_index];
+ view.light_index = lights.size()-1;
+ view.face = 0;
+
string base = format("shadows[%d]", index);
- shdata.uniform(base+".enabled", 1);
+ shdata.uniform(base+".type", static_cast<int>(type));
shdata.uniform(base+".darkness", darkness);
+ shdata.uniform(base+".matrix_index", static_cast<int>(sl.view_index));
float xf = static_cast<float>(region.left)/width;
float yf = static_cast<float>(region.bottom)/height;
#ifdef DEBUG
if(!debug_name.empty())
- sl.shadow_camera.set_debug_name(format("%s/light%d.camera", debug_name, lights.size()-1));
+ {
+ for(unsigned i=sl.view_index; i<views.size(); ++i)
+ views[i].camera.set_debug_name(format("%s/view%d.camera", debug_name, i));
+ }
#endif
}
for(const ShadowedLight &l: lights)
l.shadow_caster->setup_frame(renderer);
- for(ShadowedLight &l: lights)
+ vector<Matrix> shadow_matrices;
+ shadow_matrices.reserve(views.size());
+ for(ShadowView &v: views)
{
- l.shadow_camera.set_object_matrix(*l.light->get_matrix());
- l.shadow_camera.set_position(target);
- // TODO support point and spot lights with a frustum projection.
- // Omnidirectional lights also need a cube shadow map.
- l.shadow_camera.set_orthographic(radius*2, radius*2);
- l.shadow_camera.set_depth_clip(-radius, radius);
+ const ShadowedLight &light = lights[v.light_index];
- Matrix to_texcoord = Matrix().translate(Vector3(0.5f, 0.5f, 0.5f-depth_bias/l.region.width)).scale(0.5f);
- Matrix shadow_matrix = to_texcoord*l.shadow_camera.get_projection_matrix()*l.shadow_camera.get_view_matrix();
+ if(light.type==DIRECTIONAL)
+ {
+ v.camera.set_object_matrix(*light.light->get_matrix());
+ v.camera.set_position(target);
+ v.camera.set_orthographic(radius*2, radius*2);
+ v.camera.set_depth_clip(-radius, radius);
+ }
- shdata.uniform(format("shadows[%d].shd_world_matrix", l.index), shadow_matrix);
+ Matrix to_texcoord = Matrix().translate(Vector3(0.5f, 0.5f, 0.5f-depth_bias/light.region.width)).scale(0.5f);
+ shadow_matrices.push_back(to_texcoord*v.camera.get_projection_matrix()*v.camera.get_view_matrix());
}
- for(ShadowedLight &l: lights)
+ shdata.uniform_array("shd_world_matrix", shadow_matrices.size(), shadow_matrices.data());
+
+ for(const ShadowView &v: views)
{
+ const ShadowedLight &light = lights[v.light_index];
+
Renderer::Push push(renderer);
renderer.set_framebuffer(&fbo);
- renderer.set_viewport(&l.region);
- renderer.set_scissor(&l.region);
- renderer.set_camera(l.shadow_camera);
+ renderer.set_viewport(&light.region);
+ renderer.set_scissor(&light.region);
+ renderer.set_camera(v.camera);
- renderer.render(*light.shadow_caster);
+ renderer.render(*light.shadow_caster, (v.face>0 ? "noclear" : ""));
}
}
{
#ifdef DEBUG
fbo.set_debug_name(name+" [FBO]");
- for(unsigned i=0; i<lights.size(); ++i)
- lights[i].shadow_camera.set_debug_name(format("%s/light%d.camera", name, i));
+ for(unsigned i=0; i<views.size(); ++i)
+ views[i].camera.set_debug_name(format("%s/view%d.camera", name, i));
depth_buf.set_debug_name(name+"/depth.tex");
shdata.set_debug_name(name+" [UBO]");
#else