|
|
@@ -21,91 +21,82 @@ void Sm::init(const RendererInitializer& initializer)
|
|
|
pcfEnabled = initializer.is.sm.pcfEnabled;
|
|
|
bilinearEnabled = initializer.is.sm.bilinearEnabled;
|
|
|
resolution = initializer.is.sm.resolution;
|
|
|
- level0Distance = initializer.is.sm.level0Distance;
|
|
|
|
|
|
- // Init the levels
|
|
|
- initLevel(resolution, level0Distance, bilinearEnabled, levels[0]);
|
|
|
- for(uint32_t i = 1; i < levels.size(); i++)
|
|
|
+ // Init the shadowmaps
|
|
|
+ for(Shadowmap& sm : sms)
|
|
|
{
|
|
|
- initLevel(levels[i - 1].resolution / 2,
|
|
|
- levels[i - 1].distance * 2.0,
|
|
|
- bilinearEnabled,
|
|
|
- levels[i]);
|
|
|
+ Renderer::createFai(resolution, resolution,
|
|
|
+ GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT, sm.tex);
|
|
|
+
|
|
|
+ if(bilinearEnabled)
|
|
|
+ {
|
|
|
+ sm.tex.setFiltering(Texture::TFT_LINEAR);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ sm.tex.setFiltering(Texture::TFT_NEAREST);
|
|
|
+ }
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
|
|
|
+ GL_COMPARE_R_TO_TEXTURE);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
|
|
+
|
|
|
+ sm.fbo.create();
|
|
|
+ sm.fbo.setOtherAttachment(GL_DEPTH_ATTACHMENT, sm.tex);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
-void Sm::initLevel(uint32_t resolution, float distance, bool bilinear,
|
|
|
- Level& level)
|
|
|
+Sm::Shadowmap& Sm::findBestCandidate(Light& light)
|
|
|
{
|
|
|
- level.resolution = resolution;
|
|
|
- level.distance = distance;
|
|
|
- level.bilinear = bilinear;
|
|
|
+ uint32_t crntFrame = r->getFramesCount();
|
|
|
+ uint32_t minFrame = crntFrame;
|
|
|
+ Shadowmap* best = nullptr;
|
|
|
+ Shadowmap* secondBest = nullptr;
|
|
|
|
|
|
- try
|
|
|
+ // Check if already in list
|
|
|
+ for(Shadowmap& sm : sms)
|
|
|
{
|
|
|
- // Init texture
|
|
|
- Renderer::createFai(level.resolution, level.resolution,
|
|
|
- GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT, level.shadowMap);
|
|
|
+ uint32_t fr;
|
|
|
|
|
|
- if(level.bilinear)
|
|
|
+ if(sm.light == &light)
|
|
|
{
|
|
|
- level.shadowMap.setFiltering(Texture::TFT_LINEAR);
|
|
|
+ return sm;
|
|
|
}
|
|
|
- else
|
|
|
+ else if(sm.light == nullptr)
|
|
|
{
|
|
|
- level.shadowMap.setFiltering(Texture::TFT_NEAREST);
|
|
|
+ best = &sm;
|
|
|
+ }
|
|
|
+ else if((fr = sm.light->getLastUpdateFrame()) < minFrame)
|
|
|
+ {
|
|
|
+ secondBest = &sm;
|
|
|
+ minFrame = fr;
|
|
|
}
|
|
|
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
|
|
|
- GL_COMPARE_R_TO_TEXTURE);
|
|
|
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
|
|
- /*If you dont want to use the FFP for comparing the shadowmap
|
|
|
- (the above two lines) then you can make the comparison
|
|
|
- inside the glsl shader. The GL_LEQUAL means that:
|
|
|
- shadow = (R <= Dt) ? 1.0 : 0.0; . The R is given by:
|
|
|
- R = _tex_coord2.z/_tex_coord2.w; and the
|
|
|
- Dt = shadow2D(shadow_depth_map, _shadow_uv).r (see lp_generic.frag).
|
|
|
- Hardware filters like GL_LINEAR cannot be applied.*/
|
|
|
-
|
|
|
- // create FBO
|
|
|
- level.fbo.create();
|
|
|
- level.fbo.setOtherAttachment(GL_DEPTH_ATTACHMENT, level.shadowMap);
|
|
|
- }
|
|
|
- catch(std::exception& e)
|
|
|
- {
|
|
|
- throw ANKI_EXCEPTION("Cannot create shadowmapping FBO") << e;
|
|
|
}
|
|
|
+
|
|
|
+ ANKI_ASSERT(best != nullptr || secondBest != nullptr);
|
|
|
+
|
|
|
+ return (best) ? *best : *secondBest;
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
-void Sm::run(Light& light, float distance)
|
|
|
+Texture* Sm::run(Light& light, float distance)
|
|
|
{
|
|
|
if(!enabled || !light.getShadowEnabled()
|
|
|
|| light.getLightType() == Light::LT_POINT)
|
|
|
{
|
|
|
- return;
|
|
|
+ return nullptr;
|
|
|
}
|
|
|
|
|
|
- // Determine the level
|
|
|
- //
|
|
|
- for(Level& level : levels)
|
|
|
- {
|
|
|
- crntLevel = &level;
|
|
|
- if(distance < level.distance)
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ Shadowmap& sm = findBestCandidate(light);
|
|
|
|
|
|
// Render
|
|
|
//
|
|
|
|
|
|
// FBO
|
|
|
- crntLevel->fbo.bind();
|
|
|
+ sm.fbo.bind();
|
|
|
|
|
|
// set GL
|
|
|
- GlStateSingleton::get().setViewport(0, 0,
|
|
|
- crntLevel->resolution, crntLevel->resolution);
|
|
|
+ GlStateSingleton::get().setViewport(0, 0, resolution, resolution);
|
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
// disable color & blend & enable depth test
|
|
|
@@ -117,12 +108,12 @@ void Sm::run(Light& light, float distance)
|
|
|
glPolygonOffset(2.0, 2.0); // keep the values as low as possible!!!!
|
|
|
GlStateSingleton::get().enable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
|
|
- // Visibility tests
|
|
|
- SpotLight& slight = static_cast<SpotLight&>(light);
|
|
|
+ Frustumable* fr = light.getFrustumable();
|
|
|
+ ANKI_ASSERT(fr);
|
|
|
|
|
|
// render all
|
|
|
- for(auto it = slight.getVisibilityInfo().getRenderablesBegin();
|
|
|
- it != slight.getVisibilityInfo().getRenderablesEnd(); ++it)
|
|
|
+ for(auto it = fr->getVisibilityInfo().getRenderablesBegin();
|
|
|
+ it != fr->getVisibilityInfo().getRenderablesEnd(); ++it)
|
|
|
{
|
|
|
r->getSceneDrawer().render(r->getScene().getActiveCamera(), 1, *(*it));
|
|
|
}
|
|
|
@@ -130,6 +121,8 @@ void Sm::run(Light& light, float distance)
|
|
|
// restore GL
|
|
|
GlStateSingleton::get().disable(GL_POLYGON_OFFSET_FILL);
|
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
|
+
|
|
|
+ return &sm.tex;
|
|
|
}
|
|
|
|
|
|
|