Graphical errors in the Exponential Shadow Maps
Th3V1kt0r opened this issue · 4 comments
Ogre 2.3 (master)
There are some graphical errors in the Exponential Shadow Maps.
You can see it clearly in Sample_ShadowMapDebugging if you enable ESM. Once on the cubes (green). Or on the edges when you make the plate smaller (red).
It's even worse if you have multiple plates next to each other that have a gap.
Hi!
I can't reproduce your bug. Can you provide a diff to apply the same changes you're doing?
I'm doing:
diff --git a/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp b/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp
index 52db386537..044f17f20c 100644
--- a/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp
+++ b/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp
@@ -74,6 +74,7 @@ namespace Demo
Ogre::SceneNode *sceneNode = sceneManager->getRootSceneNode( Ogre::SCENE_DYNAMIC )
->createChildSceneNode( Ogre::SCENE_DYNAMIC );
sceneNode->setPosition( 0, -1, 0 );
+ sceneNode->setScale(Ogre::Vector3(0.1f));
sceneNode->attachObject( item );
}
@@ -169,6 +170,18 @@ namespace Demo
MiscUtils::setGaussianLogFilterParams( "ESM/GaussianLogFilterV", kernelRadius,
gaussianDeviationFactor, K );
#endif
+ {
+ Ogre::Hlms *hlms = mGraphicsSystem->getRoot()->getHlmsManager()->getHlms( Ogre::HLMS_PBS );
+
+ assert( dynamic_cast<Ogre::HlmsPbs *>( hlms ) );
+ Ogre::HlmsPbs *pbs = static_cast<Ogre::HlmsPbs *>( hlms );
+
+ Ogre::HlmsPbs::ShadowFilter nextFilter = Ogre::HlmsPbs::ExponentialShadowMaps;
+ pbs->setShadowSettings( nextFilter );
+
+ if( nextFilter == Ogre::HlmsPbs::ExponentialShadowMaps )
+ setupShadowNode( true );
+ }
TutorialGameState::createScene01();
}
Also please provide the following info:
- Operating System / Platform: ❔
- RenderSystem: ❔
- GPU: ❔
Cheers
Hi!
I created small plates and did not scale them.
I used F5 to switch to ESM mode.
Windows 7/10
OpenGL/DirectX
GeForce GTX 1060
diff --git a/ShadowMapDebuggingGameState - Kopie.cpp b/ShadowMapDebuggingGameState.cpp
index 52db386537..c3adb779fd 100644
--- a/ShadowMapDebuggingGameState - Kopie.cpp
+++ b/ShadowMapDebuggingGameState.cpp
@@ -61,7 +61,13 @@ namespace Demo
Ogre::v1::MeshPtr planeMeshV1 = Ogre::v1::MeshManager::getSingleton().createPlane(
"Plane v1", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
- Ogre::Plane( Ogre::Vector3::UNIT_Y, 1.0f ), 50.0f, 50.0f, 1, 1, true, 1, 4.0f, 4.0f,
+ Ogre::Plane( Ogre::Vector3::UNIT_Y, 1.0f ), 5.0f, 5.0f, 1, 1, true, 1, 4.0f, 4.0f,
+ Ogre::Vector3::UNIT_Z, Ogre::v1::HardwareBuffer::HBU_STATIC,
+ Ogre::v1::HardwareBuffer::HBU_STATIC );
+
+ Ogre::v1::MeshPtr planeMeshV2 = Ogre::v1::MeshManager::getSingleton().createPlane(
+ "Plane v2", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
+ Ogre::Plane( Ogre::Vector3::UNIT_Y, 1.0f ), 5.0f, 5.0f, 1, 1, true, 1, 4.0f, 4.0f,
Ogre::Vector3::UNIT_Z, Ogre::v1::HardwareBuffer::HBU_STATIC,
Ogre::v1::HardwareBuffer::HBU_STATIC );
@@ -77,6 +83,18 @@ namespace Demo
sceneNode->attachObject( item );
}
+ Ogre::MeshPtr planeMesh2 = Ogre::MeshManager::getSingleton().createByImportingV1(
+ "Plane2", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, planeMeshV1.get(), true,
+ true, true );
+
+ {
+ Ogre::Item *item = sceneManager->createItem( planeMesh, Ogre::SCENE_DYNAMIC );
+ Ogre::SceneNode *sceneNode = sceneManager->getRootSceneNode( Ogre::SCENE_DYNAMIC )
+ ->createChildSceneNode( Ogre::SCENE_DYNAMIC );
+ sceneNode->setPosition( 5.001, -1, 0 );
+ sceneNode->attachObject( item );
+ }
+
float armsLength = 2.5f;
for( int i = 0; i < 4; ++i )
Oh NOW I understand what's going on.
You've created two floor panels and there is a small gap between them:
This gap is triggering a limitation of ESM shadow maps: When there is a discontinuity.
From the shadow camera's POV we have:
- Pixel to the left: floor tile A
- Pixel in the center: an abyss far away you can't see the bottom of. It's almost an infinite depth.
- Pixel to the right: floor tile B
Because ESM works by blurring depth, the "abyss" starts leaking into the nearby pixels. The K setting (setEsmK) also plays an important role.
If you fix the gap you can fix the problem.
If you cannot fix the gap, you can workaround the problem by creating another floor at the same (or very similar) Y position as the floor panels, and set visibility flags so that the object cast shadows but isn't drawn in the main scene.
Like this:
{
Ogre::Item *item = sceneManager->createItem( planeMesh, Ogre::SCENE_DYNAMIC );
Ogre::SceneNode *sceneNode = sceneManager->getRootSceneNode( Ogre::SCENE_DYNAMIC )
->createChildSceneNode( Ogre::SCENE_DYNAMIC );
sceneNode->setPosition( 0, -2, 0 );
sceneNode->setScale( Ogre::Vector3( 10.0f, 1, 10.0f ) );
sceneNode->attachObject( item );
}
And if we add to that new fake floor:
item->setVisibilityFlags( 1u );
And change compositor script:
compositor_node ShadowMapDebuggingRenderingNode
{
in 0 rt_renderwindow
target rt_renderwindow
{
pass render_scene
{
load
{
all clear
clear_colour 0.2 0.4 0.6 1
}
store
{
colour store_or_resolve
depth dont_care
stencil dont_care
}
overlays on
shadows ShadowMapDebuggingShadowNode
visibility_mask 0xFFFFFFFE
profiling_id "Main Render"
}
}
}
Notice the visibility_mask 0xFFFFFFFE
is a new line. Then we get the desired output:
Since the fake floor is casting a shadow, but isn't shown on screen.
Again, this is a limitation of the ESM technique and there is not much that can be done other than hiding the artifact via workarounds or switching to a different technique.
MSM (Moment Shadow Mapping) fixes this problem with brute force by using all techniques (VSM, ESM, PCF) and then select per pixel which one to use (based on a heuristic of "which one has less artifacts"), but we don't implement it in OgreNext yet.
I'm closing the ticket because there is not much that can be done; this is why ESM is best fit for interiors rather than exteriors or open world maps.
Note that the workaround doesn't have to be a plane. You could encase your scene inside a sphere to achieve a similar result.