|
|
@@ -22,6 +22,7 @@ void Sm::init(const RendererInitializer& initializer)
|
|
|
resolution = initializer.is.sm.resolution;
|
|
|
|
|
|
// Init the shadowmaps
|
|
|
+ sms.resize(initializer.is.sm.maxLights);
|
|
|
for(Shadowmap& sm : sms)
|
|
|
{
|
|
|
Renderer::createFai(resolution, resolution,
|
|
|
@@ -35,9 +36,9 @@ void Sm::init(const RendererInitializer& initializer)
|
|
|
{
|
|
|
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.tex.setParameter(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
|
|
+ sm.tex.setParameter(GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
|
|
|
|
|
sm.fbo.create();
|
|
|
sm.fbo.setOtherAttachment(GL_DEPTH_ATTACHMENT, sm.tex);
|
|
|
@@ -45,84 +46,129 @@ void Sm::init(const RendererInitializer& initializer)
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
-Sm::Shadowmap& Sm::findBestCandidate(Light& light)
|
|
|
+void Sm::prepareDraw()
|
|
|
{
|
|
|
- uint32_t crntFrame = r->getFramesCount();
|
|
|
- uint32_t minFrame = crntFrame;
|
|
|
- Shadowmap* best = nullptr;
|
|
|
- Shadowmap* secondBest = nullptr;
|
|
|
-
|
|
|
- // Check if already in list
|
|
|
- for(Shadowmap& sm : sms)
|
|
|
- {
|
|
|
- uint32_t fr;
|
|
|
+ // set GL
|
|
|
+ GlStateSingleton::get().setViewport(0, 0, resolution, resolution);
|
|
|
|
|
|
- if(sm.light == &light)
|
|
|
- {
|
|
|
- return sm;
|
|
|
- }
|
|
|
- else if(sm.light == nullptr)
|
|
|
- {
|
|
|
- best = &sm;
|
|
|
- }
|
|
|
- else if((fr = sm.light->getLastUpdateFrame()) < minFrame)
|
|
|
- {
|
|
|
- secondBest = &sm;
|
|
|
- minFrame = fr;
|
|
|
- }
|
|
|
- }
|
|
|
+ // disable color & blend & enable depth test
|
|
|
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
|
|
+ GlStateSingleton::get().enable(GL_DEPTH_TEST);
|
|
|
+ GlStateSingleton::get().disable(GL_BLEND);
|
|
|
|
|
|
- ANKI_ASSERT(best != nullptr || secondBest != nullptr);
|
|
|
+ // for artifacts
|
|
|
+ glPolygonOffset(2.0, 2.0); // keep the values as low as possible!!!!
|
|
|
+ GlStateSingleton::get().enable(GL_POLYGON_OFFSET_FILL);
|
|
|
+}
|
|
|
|
|
|
- return (best) ? *best : *secondBest;
|
|
|
+//==============================================================================
|
|
|
+void Sm::afterDraw()
|
|
|
+{
|
|
|
+ GlStateSingleton::get().disable(GL_POLYGON_OFFSET_FILL);
|
|
|
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
-Texture* Sm::run(Light& light, float distance)
|
|
|
+void Sm::run()
|
|
|
{
|
|
|
- if(!enabled || !light.getShadowEnabled()
|
|
|
- || light.getLightType() == Light::LT_POINT)
|
|
|
- {
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
+ ANKI_ASSERT(enabled);
|
|
|
|
|
|
- Shadowmap& sm = findBestCandidate(light);
|
|
|
+ Camera& cam = r->getScene().getActiveCamera();
|
|
|
+ VisibilityInfo& vi = cam.getFrustumable()->getVisibilityInfo();
|
|
|
|
|
|
- // Render
|
|
|
- //
|
|
|
+ prepareDraw();
|
|
|
|
|
|
- // FBO
|
|
|
- sm.fbo.bind();
|
|
|
+ // Get the shadow casters
|
|
|
+ //
|
|
|
+ const U MAX_SHADOW_CASTERS = 256;
|
|
|
+ ANKI_ASSERT(getMaxLightsCount() > MAX_SHADOW_CASTERS);
|
|
|
+ Array<Light*, MAX_SHADOW_CASTERS> casters;
|
|
|
+ U32 castersCount = 0;
|
|
|
|
|
|
- // set GL
|
|
|
- GlStateSingleton::get().setViewport(0, 0, resolution, resolution);
|
|
|
- glClear(GL_DEPTH_BUFFER_BIT);
|
|
|
+ for(auto it = vi.getLightsBegin(); it != vi.getLightsEnd(); ++it)
|
|
|
+ {
|
|
|
+ Light* light = (*it);
|
|
|
|
|
|
- // disable color & blend & enable depth test
|
|
|
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
|
|
- GlStateSingleton::get().enable(GL_DEPTH_TEST);
|
|
|
- GlStateSingleton::get().disable(GL_BLEND);
|
|
|
+ if(light->getShadowEnabled())
|
|
|
+ {
|
|
|
+ casters[castersCount % getMaxLightsCount()] = light;
|
|
|
+ ++castersCount;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // for artifacts
|
|
|
- glPolygonOffset(2.0, 2.0); // keep the values as low as possible!!!!
|
|
|
- GlStateSingleton::get().enable(GL_POLYGON_OFFSET_FILL);
|
|
|
+#if 1
|
|
|
+ if(castersCount > getMaxLightsCount())
|
|
|
+ {
|
|
|
+ ANKI_LOGW("Too many shadow casters: " << castersCount);
|
|
|
+ }
|
|
|
+#endif
|
|
|
|
|
|
- Frustumable* fr = light.getFrustumable();
|
|
|
- ANKI_ASSERT(fr);
|
|
|
+ castersCount = castersCount % getMaxLightsCount();
|
|
|
|
|
|
// render all
|
|
|
- for(auto it = fr->getVisibilityInfo().getRenderablesBegin();
|
|
|
+ /*for(auto it = fr->getVisibilityInfo().getRenderablesBegin();
|
|
|
it != fr->getVisibilityInfo().getRenderablesEnd(); ++it)
|
|
|
{
|
|
|
r->getSceneDrawer().render(r->getScene().getActiveCamera(), 1, *(*it));
|
|
|
+ }*/
|
|
|
+
|
|
|
+ afterDraw();
|
|
|
+}
|
|
|
+
|
|
|
+//==============================================================================
|
|
|
+Sm::Shadowmap& Sm::bestCandidate(Light& light)
|
|
|
+{
|
|
|
+ // Allready there
|
|
|
+ for(Shadowmap& sm : sms)
|
|
|
+ {
|
|
|
+ if(&light == sm.light)
|
|
|
+ {
|
|
|
+ return sm;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // restore GL
|
|
|
- GlStateSingleton::get().disable(GL_POLYGON_OFFSET_FILL);
|
|
|
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
|
+ // Find a null
|
|
|
+ for(Shadowmap& sm : sms)
|
|
|
+ {
|
|
|
+ if(sm.light == nullptr)
|
|
|
+ {
|
|
|
+ sm.light = &light;
|
|
|
+ sm.timestamp = 0;
|
|
|
+ return sm;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return &sm.tex;
|
|
|
+ // Find an old
|
|
|
+ Shadowmap* sm = &sms[0];
|
|
|
+ for(U i = 1; i < sms.size(); i++)
|
|
|
+ {
|
|
|
+ if(sms[i].timestamp < sm->timestamp)
|
|
|
+ {
|
|
|
+ sm = &sms[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ sm->light = &light;
|
|
|
+ sm->timestamp = 0;
|
|
|
+ return *sm;
|
|
|
}
|
|
|
|
|
|
+//==============================================================================
|
|
|
+void Sm::doLight(Light& light)
|
|
|
+{
|
|
|
+ /// XXX Set FBO
|
|
|
+ Shadowmap& sm = bestCandidate(light);
|
|
|
+
|
|
|
+ Frustumable* fr = light.getFrustumable();
|
|
|
+ ANKI_ASSERT(fr != nullptr);
|
|
|
+ Movable* mov = &light;
|
|
|
+
|
|
|
+ U32 lightLastUpdateTimestamp = light.getMovableTimestamp();
|
|
|
+ lightLastUpdateTimestamp = std::max(lightLastUpdateTimestamp,
|
|
|
+ light.getFrustumable()->getFrustumableTimestamp());
|
|
|
+
|
|
|
+ //for()
|
|
|
+
|
|
|
+}
|
|
|
|
|
|
-} // end namespace
|
|
|
+} // end namespace anki
|