[2.2] Self Shadowing errors
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
[2.2] Self Shadowing errors
When an object casts a shadow onto another, the shadows are black and correct.
However, when an object self shadows it produces a really acne'd shadow which doesn't look good in worlds.
I believe the acne is caused by the depth issues on casting onto itself, but adjusting the shadow depth bias improves the acne with depth issues either coming forwards on an object or you get the peter panning effect and is not ideal.
I have a couple screenshots taken of the PBS materials sample with only the directional light in the scene.
In the shader i am simply outputting fShadow to the outPs_colour variable.
Here is what i get.
Is there anyway of improving the self shadows to be full black on the shadowed side of a self shadow as they should be rather than the ugly acne and light bleed it causes on the backsides of objects in the world.
Acne is of course affected by the PCF filtering, blurring the acne makes the shadow lighter and more noticeable that something is not shadowed.
I would use ESM as it looks great, but it doesn't cast shadows on point lights and i'm getting some issues running shadow nodes with more complex setups and larger textures( ESM second PSSM split 1 has projection issues). and also receiving curves at the edge of buildings... but still trying to work these issues out myself in case there is an implementation issue.
-
- OGRE Contributor
- Posts: 267
- Joined: Wed Apr 23, 2014 3:49 pm
- Location: Bologna, Italy
- x 75
Re: [2.2] Self Shadowing errors
Don't know if you've seen it (or if is in some way useful to your specific case), but there's has been some work concerning shadows (see: viewtopic.php?p=547572#p547572).
In addition, @xrgo and some other users also have discovered some bugs (see here and here).
I'm super-interested in this topic since it's a problem quite noticeable which I have (since forever I guess ) on some particular objects (e.g. flags and guard rails).
Senior programmer at 505 Games; former senior engine programmer at Sandbox Games
Worked on: Racecraft Esport — Racecraft Coin-Op, Victory: The Age of Racing
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
Why would the other engines be able to not bother with this, surely they would experience the same problems as the rest of gfx development regarding shadows, unless they know something we don't
Possibly going to look into CSSM instead of PSSM as those shadows are more used across the engine board.
Im possibly looking at adding a compute shader at the end of the compositor node for the shadows to attempt a sort of denoise or de acne based on reading blocks of data and finding if the texel should be shadow or light. This way in theory you would not have to use a bias as you could sort of post process the shadow image data to make it either black or white rather than a plane of acne.
This would only work though if the acne is in the shadow texture otherwise its in the pixel shader and my approach would not work.
Just a thought anyway.
Will continue to look into this to see if there is any improvements that can be made
Edit: Turning Off the backface culling for shadows did improve the quality and adding a slight constant bias in the shadowmapping piece for the depth does get rid of most of the lit area acne and get strong shadows/non acne shadows in the self shadow. Of course having a thin object though is not going to get self shadows because of the bias and the way it works. Better than no shadows and just acne though.
Downside is that backface culling is also faster.
Edit2: Yeah, this is much better than it was.. (Screenshot from inside our engine rather than ogre demo.)
As you can see self shadowing is working quite well, the odd bit of acne. The white box is not emissive, its just to thin to get the shadow on it with the bias.
Speaking of bias, probably the wrong place but at the moment i have added a hardcoded bias into the shader at:
ShadowMapping_piece_ps.any
Line 155:
instead of:
Code: Select all
float fDepth = psPosLN.z / psPosLN.w;
Code: Select all
float fDepth = psPosLN.z+0.0007 / psPosLN.w;
-
- OGRE Team Member
- Posts: 5446
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1348
Re: [2.2] Self Shadowing errors
Please note ESM does work with point lights.SolarPortal wrote: ↑Tue Jun 09, 2020 2:02 pm I would use ESM as it looks great, but it doesn't cast shadows on point lights
Please note it should be (psPosLN.z+0.0007) / psPosLN.wfloat fDepth = psPosLN.z+0.0007 / psPosLN.w;
It's missing a parenthesis, otherwise it won't work with spot and point lights.
Btw there's one more thing to try I didn't invest time into: slope bias.
The slope bias must be set from a macroblock level via HlmsMacroblock::mDepthBiasSlopeScale and should only be set to the shadow caster's macroblock.
We currently don't touch this value in HlmsDatablock::setMacroblock, but it is worth looking into this (a lot).
SlopeScale bias is known to alleviate self shadowing issues as it allows large values that only affect triangles nearly parallel to the light direction, while applying 0 or near-0 bias to triangles perpendicular to the light direction.
Update: We don't implement "normal offset bias", PRs are welcomed:
https://mynameismjp.wordpress.com/2013/ ... adow-maps/ (look for "The normal-based offset, called Offset Scale...")
http://c0de517e.blogspot.com/2011/05/sh ... notes.html
https://ndotl.wordpress.com/2014/12/19/ ... adow-bias/
There are two ways:
1. Displace during the caster pass
```
triangle.xyz += normal.xyz * ( 1.0f - abs( dot( normal, lightdir ) ) ) * normal_bias;
```
I'm not sure if that's the exact formula, MJP has a demo with code.
Requires access to normals in the vertex shader for the caster pass, thus make sure that the shadow map optimization is turned off (because it strips everything except position data). msOptimizeForShadowMapping should be set to false and hasIndependentShadowMappingVaos should be returning false.
Once the PR is done we can modify VertexShadowMapHelper::optimizeForShadowMapping to keep normals in a lightweight manner (probably 8bpp per component is enough?, adding only 4 bytes per vertex)
2. Displace during the normal rendering pass by the geometric normal, before sampling the shadow map. This should be more accurate.
This is what MJP demo does:
Code: Select all
float3 GetShadowPosOffset(in float nDotL, in float3 normal)
{
float2 shadowMapSize;
float numSlices;
ShadowMap.GetDimensions(shadowMapSize.x, shadowMapSize.y, numSlices);
float texelSize = 2.0f / shadowMapSize.x;
float nmlOffsetScale = saturate(1.0f - nDotL);
return texelSize * OffsetScale * nmlOffsetScale * normal;
}
float3 offset = GetShadowPosOffset(nDotL, normal) / abs(CascadeScales[cascadeIdx].z);
// Project into shadow space
float3 samplePos = positionWS + offset;
...
It divides the offset by the shadow map size in order to apply the offset in texels, making this effect account shadow map resolution.
Also: made a Github ticket.
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
-
- OGRE Team Member
- Posts: 5446
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1348
Re: [2.2] Self Shadowing errors
Btw looking at the problem, it appears normal offset depth is only a couple lines of code to change (specially option 2, in the pixel shader) so it looks like it's way easier to implement than I originally thought so.
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
You may say its easy, but the shadow code in ogre is quite complex to other sources out there and having to work out which variables are which and where to put this normal offset. I think i have a location in the ShadowMapper_os file under the getShadow function.
So making a little bit of progress but not much so far will keep working on it.. but the extra bit of information could help
-
- OGRE Team Member
- Posts: 5446
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1348
Re: [2.2] Self Shadowing errors
The releases page has it already compiled.SolarPortal wrote: ↑Wed Jun 10, 2020 12:17 am @dark_sylinc, do you have a compiled version of that MJP demo as mine does not seem to compile and would be useful while testing to see what it happening.
Oops sorry.SolarPortal wrote: ↑Wed Jun 10, 2020 12:17 amYou may say its easy, but the shadow code in ogre is quite complex to other sources out there and having to work out which variables are which and where to put this normal offset. I think i have a location in the ShadowMapper_os file under the getShadow function.
You can modify psPosLN.xyz by the offset normal in getShadow/getShadowPoint around line 151 from ShadowMapping_piece_ps.any
You have the geometric normal in pixelData.geomNormal (you will have to modify getShadow so that it accepts PixelData as input argument)
I wonder if this can be done at vertex shader level, in ShadowMapping_piece_vs.any by offsetting outVs.posL@n, but I'm not sure if that's correct.
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
However, the one thing i do notice is that self shadows on thicker objects even with back face culling are producing a solid black shadow whereas in ogre it does not. So i will have to compare the shadow casters also i think.
As for the normal offset, i need to get hold of the light direction, what is the best way of grabbing this information for use in the getshadow() that you would recommend. or even getting NDOTL
Edit: It also appears in the demo that shadows are rendered with no culling:
Code: Select all
D3D11_RASTERIZER_DESC rsDesc = RasterizerStates::NoCullDesc();
rsDesc.DepthClipEnable = FALSE;
DXCall(device->CreateRasterizerState(&rsDesc, &shadowRSState));
Edit2: Sort of have the normal offset working but doesnt take the light into account yet.
placed in top the get shadow function (not the full code.)
Code: Select all
@property( hlms_normal || hlms_qtangent )
//normal = normalize(normal);
//float3 lightDir = lightPos.xyz - posVS;
//float nDotL = saturate(dot(normal, lightPos));
float3 normalBias = GetShadowPosOffset(shadowMap, 0, pixelData.geomNormal.xyz, 1.8);
//float3 samplePos = posVS.xyz + normalBias;
//float3 shadowoffset = mul(float4(normalBias, 1.0f), passBuf.shadowRcv[0].texViewProj).xyz;
//uv += shadowoffset.xy;
//uv += normalBias;
//uv = lightPos.xy;
@property( @m == 0 || @m == 1 )psPosLN.xyz -= normalBias;@end
@end
Code: Select all
INLINE float3 GetShadowPosOffset(@insertpiece( TEXTURE2DSHADOW ) shadowMap, float nDotL, float3 normal, float offsetScale)
{
float2 shadowMapSize;
shadowMap.GetDimensions(shadowMapSize.x, shadowMapSize.y);
float texelSize = 2.0f / shadowMapSize.x;
float nmlOffsetScale = saturate(1.0f - nDotL);
return texelSize * offsetScale * nmlOffsetScale * normal;
}
Still just working things through, but wanted to keep you all updated in case someone has an "ahh.. if you did this" moment
Still have yet to try thisI wonder if this can be done at vertex shader level, in ShadowMapping_piece_vs.any by offsetting outVs.posL@n, but I'm not sure if that's correct.
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
In the getShadow() code at the top of the function i have this:
Code: Select all
float3 lightPos = light.position.xyz;
float2 uv;
@property( @m < 2 ) -- the other side of the condition is the point light
@property( hlms_normal || hlms_qtangent )
float3 lightDir = mul(light.position, (float3x3)passBuf.invView);
float nDotL = saturate(dot(pixelData.worldNorm, lightDir));
float3 offset = GetShadowPosOffset(shadowMap, nDotL, pixelData.worldNorm, 4) / passBuf.pssmSplitPoints0;//abs(CascadeScales[cascadeIdx].z);
float4 shadowPosition = mul(float4(pixelData.worldPos+offset, 1.0f), passBuf.shadowRcv[shadowMapIdx].texViewProj);
@property( !hlms_shadowmap@n_is_directional_light && hlms_no_reverse_depth )
shadowPosition.z = shadowPosition.z * passBuf.shadowRcv[shadowMapIdx].shadowDepthRange.y;@end
@property( hlms_no_reverse_depth && (syntax == glsl || syntax == glsles) )shadowPosition.z = (shadowPosition.z * 0.5) + 0.5;@end
psPosLN = shadowPosition;
float constantBias = 0.0002;
//psPosLN.z -= constantBias;
@end
It seems to function and works for both front face and back face culling. Both have their own little artifacts that need adjustments for.
There is a constant bias but currently commented out.
I can get black shadows on both thick and thin objects in either culling mode and it does do a nice job at removing acne but the backface culling adds a gap of light where the offset is. I would say it works better with front face, but it does an alright job with backface culling.
Also with complete bias'ing turned off.
You may also notice that I redid the shadow map position in the pixel shader
BACK FACE EXAMPLES - Normal offset value: 4
This is the error i was talking about with the light gap
Thin object from front with shadow recieve
Really thin object from behind first split
Note the lines in the edges
This is a PCF6x6 on second split on the really thin object
FRONT FACE EXAMPLES - Normal offset value: 7
Note the line under the square box
Thin object split 1 all black
The sphere shadows comes out front a bit
Thick objects with correct rendering.
Note: The ground plane in front face culling has depth issues, simply turning off cast shadows on the plane works, not necessary in backface.
Note2: Applying a slight constant bias in the front face helps remove more acne but in these shots it is not used.
All that is rendered is the variable fShadow only. It only proceeds to look better with proper shading and ambience.
-
- OGRE Team Member
- Posts: 5446
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1348
Re: [2.2] Self Shadowing errors
After some experimentation I arrived to this experimental tweaks:
Code: Select all
diff --git a/OgreMain/src/OgreHlmsDatablock.cpp b/OgreMain/src/OgreHlmsDatablock.cpp
index ae5e73810..6e41076dd 100644
--- a/OgreMain/src/OgreHlmsDatablock.cpp
+++ b/OgreMain/src/OgreHlmsDatablock.cpp
@@ -115,7 +115,7 @@ namespace Ogre
mAlphaTestCmp( CMPF_ALWAYS_PASS ),
mAlphaTestShadowCasterOnly( false ),
mAlphaTestThreshold( 0.5f ),
- mShadowConstantBias( 0.01f )
+ mShadowConstantBias( 0.05f )
{
mMacroblockHash[0] = mMacroblockHash[1] = 0;
mMacroblock[0] = mMacroblock[1] = 0;
diff --git a/OgreMain/src/OgreHlmsManager.cpp b/OgreMain/src/OgreHlmsManager.cpp
index 4292409f0..99c3787ff 100644
--- a/OgreMain/src/OgreHlmsManager.cpp
+++ b/OgreMain/src/OgreHlmsManager.cpp
@@ -44,7 +44,7 @@ namespace Ogre
HlmsManager::HlmsManager() :
mComputeHlms( 0 ),
mRenderSystem( 0 ),
- mShadowMappingUseBackFaces( true ),
+ mShadowMappingUseBackFaces( false ),
mDefaultHlmsType( HLMS_PBS )
#if !OGRE_NO_JSON
, mJsonListener( 0 )
diff --git a/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp b/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp
index a2415e108..057d414b9 100644
--- a/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp
+++ b/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp
@@ -97,7 +97,7 @@ namespace Demo
createChildSceneNode( Ogre::SCENE_DYNAMIC );
mSceneNode[idx]->setPosition( (i - 1.5f) * armsLength,
- 2.0f,
+ 0.0f,
(j - 1.5f) * armsLength );
mSceneNode[idx]->setScale( 0.65f, 0.65f, 0.65f );
@@ -123,7 +123,7 @@ namespace Demo
lightNode->attachObject( light );
light->setDiffuseColour( 0.8f, 0.4f, 0.2f ); //Warm
light->setSpecularColour( 0.8f, 0.4f, 0.2f );
- light->setPowerScale( Ogre::Math::PI );
+ light->setPowerScale( Ogre::Math::PI * 0 );
light->setType( Ogre::Light::LT_SPOTLIGHT );
lightNode->setPosition( -10.0f, 10.0f, 10.0f );
light->setDirection( Ogre::Vector3( 1, -1, -1 ).normalisedCopy() );
@@ -136,7 +136,7 @@ namespace Demo
lightNode->attachObject( light );
light->setDiffuseColour( 0.2f, 0.4f, 0.8f ); //Cold
light->setSpecularColour( 0.2f, 0.4f, 0.8f );
- light->setPowerScale( Ogre::Math::PI );
+ light->setPowerScale( Ogre::Math::PI * 0 );
light->setType( Ogre::Light::LT_SPOTLIGHT );
lightNode->setPosition( 10.0f, 10.0f, -10.0f );
light->setDirection( Ogre::Vector3( -1, -1, 1 ).normalisedCopy() );
@@ -175,6 +175,14 @@ namespace Demo
gaussianDeviationFactor, K );
#endif
+ {
+ Ogre::Root *root = mGraphicsSystem->getRoot();
+ Ogre::Hlms *hlms = root->getHlmsManager()->getHlms( Ogre::HLMS_PBS );
+ assert( dynamic_cast<Ogre::HlmsPbs*>( hlms ) );
+ Ogre::HlmsPbs *pbs = static_cast<Ogre::HlmsPbs*>( hlms );
+ pbs->getHlmsManager()->setShadowMappingUseBackFaces( false );
+ }
+
TutorialGameState::createScene01();
}
//-----------------------------------------------------------------------------------
@@ -450,10 +458,10 @@ namespace Demo
}
#endif
- if( nextFilter == Ogre::HlmsPbs::ExponentialShadowMaps )
+ //if( nextFilter == Ogre::HlmsPbs::ExponentialShadowMaps )
pbs->getHlmsManager()->setShadowMappingUseBackFaces( false );
- else
- pbs->getHlmsManager()->setShadowMappingUseBackFaces( true );
+// else
+// pbs->getHlmsManager()->setShadowMappingUseBackFaces( true );
pbs->setShadowSettings( nextFilter );
diff --git a/Samples/Media/Hlms/Common/Any/ShadowCaster_piece_vs.any b/Samples/Media/Hlms/Common/Any/ShadowCaster_piece_vs.any
index d4e0a668a..7a66574f5 100644
--- a/Samples/Media/Hlms/Common/Any/ShadowCaster_piece_vs.any
+++ b/Samples/Media/Hlms/Common/Any/ShadowCaster_piece_vs.any
@@ -3,14 +3,22 @@
@property( hlms_shadowcaster )
@piece( DoShadowCasterVS )
- float shadowConstantBias = uintBitsToFloat( worldMaterialIdx[inVs_drawId].y );
+ @property( hlms_no_reverse_depth )
+ float shadowConstantBias = uintBitsToFloat( worldMaterialIdx[inVs_drawId].y );
+ @else
+ //float shadowConstantBias = -uintBitsToFloat( worldMaterialIdx[inVs_drawId].y );
+ //float shadowConstantBias = -0.5 / passBuf.depthRange.y * 0.1f;
+ //float shadowConstantBias = -4.5 / passBuf.depthRange.y * 0.1f;
+ float shadowConstantBias = -0.015 / passBuf.depthRange.y /passBuf.depthRange.y * 0.1f;
+ //float shadowConstantBias = 0.65 / passBuf.depthRange.y * 0.1f;
+ @end
@property( !hlms_shadow_uses_depth_texture && !hlms_shadowcaster_point && !exponential_shadow_maps )
//Linear depth
@property( hlms_shadowcaster_directional || !hlms_no_reverse_depth )
- outVs.depth = outVs_Position.z + shadowConstantBias * passBuf.depthRange.y * passBuf.depthRange.y;
+ outVs.depth = outVs_Position.z + shadowConstantBias * passBuf.depthRange.y * passBuf.depthRange.y;
@else
- outVs.depth = (outVs_Position.z + shadowConstantBias * passBuf.depthRange.y) * passBuf.depthRange.y;
+ outVs.depth = (outVs_Position.z + shadowConstantBias * passBuf.depthRange.y) * passBuf.depthRange.y;
@end
@property( hlms_no_reverse_depth && (syntax == glsl || syntax == glsles) )outVs.depth = (outVs.depth * 0.5) + 0.5;@end
@end
@@ -27,7 +35,7 @@
//however we can use a cheap approximation ("pseudo linear depth")
//see http://www.yosoygames.com.ar/wp/2014/01/linear-depth-buffer-my-ass/
@property( hlms_shadowcaster_directional || !hlms_no_reverse_depth )
- outVs_Position.z = outVs_Position.z + shadowConstantBias * passBuf.depthRange.y * passBuf.depthRange.y;
+ outVs_Position.z = outVs_Position.z + shadowConstantBias * passBuf.depthRange.y * passBuf.depthRange.y;
@else
outVs_Position.z = (outVs_Position.z + shadowConstantBias * passBuf.depthRange.y) * passBuf.depthRange.y * outVs_Position.w;
@end
diff --git a/Samples/Media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any b/Samples/Media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any
index 58b8b7e01..89c59b438 100644
--- a/Samples/Media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any
+++ b/Samples/Media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any
@@ -1,4 +1,4 @@
-
+
//#include "SyntaxHighlightingMisc.h"
@property( hlms_num_shadow_map_lights )
@@ -134,10 +134,10 @@
@foreach( 4, m )
@property( @m == 0 )
INLINE float getShadow( @insertpiece( TEXTURE2DSHADOW ) shadowMap, @insertpiece( SamplerShadow )
- float4 psPosLN, float4 invShadowMapSize )
+ float4 psPosLN, float4 invShadowMapSize, float2 invDepthRange, PixelData pixelData, float f )
@end @property( @m == 1 )
INLINE float getShadow( @insertpiece( TEXTURE2DSHADOW ) shadowMap, @insertpiece( SamplerShadow )
- float4 psPosLN, float4 invShadowMapSize, float2 minUV, float2 maxUV )
+ float4 psPosLN, float4 invShadowMapSize, float2 invDepthRange, PixelData pixelData, float f, float2 minUV, float2 maxUV )
@end @property( @m == 2 )
INLINE float getShadowPoint( @insertpiece( TEXTURE2DSHADOW ) shadowMap, @insertpiece( SamplerShadow )
float3 posVS, float3 lightPos, float4 invShadowMapSize, float2 invDepthRange
@@ -150,6 +150,17 @@
@end
{
@property( @m < 2 )
+ float tmpNDotL = saturate( dot( passBuf.lights[0].position.xyz, pixelData.geomNormal.xyz ) );
+ @property( @m == 0 )
+ psPosLN.xy -= ((1.0f - tmpNDotL) * 3.5f * pixelData.geomNormal.xy * 0.000488281f * invDepthRange.y) * psPosLN.w;
+ @else
+ float regionSize = (maxUV.x - minUV.x) / invShadowMapSize.x;
+ regionSize = 1.0f / regionSize;
+ psPosLN.xyz -= ((1.0f - tmpNDotL) * 0.75f * pixelData.geomNormal.xyz *
+ float3(regionSize,regionSize, -1.0f * invDepthRange.y)) * psPosLN.w;
+// psPosLN.xyz -= ((1.0f - tmpNDotL) * 0.5f * pixelData.geomNormal.xyz * regionSize * (f+1)) * psPosLN.w;
+// psPosLN.z += (f) * psPosLN.w * 0.005f;
+ @end
//Spot and directional lights
@property( !exponential_shadow_maps && !hlms_no_reverse_depth )
float fDepth = psPosLN.z / psPosLN.w;
@@ -328,14 +339,18 @@
{
fShadow = getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL0,
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@counter(CurrentShadowMap)_uv_param );
@property( hlms_pssm_blend )
if( inPs.depth > passBuf.pssmBlendPoints@value(CurrentShadowMapBlend) )
{
fShadowBlend = getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL1,
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@value(CurrentShadowMap)_uv_param );
fShadow = lerp( fShadow, fShadowBlend,
(inPs.depth - passBuf.pssmBlendPoints@value(CurrentShadowMapBlend)) /
@@ -351,14 +366,18 @@
{
fShadow = getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL@n,
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@counter(CurrentShadowMap)_uv_param );
@property( hlms_pssm_blend && @n < hlms_pssm_splits_minus_one )
if( inPs.depth > passBuf.pssmBlendPoints@value(CurrentShadowMapBlend) )
{
fShadowBlend = getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL@value(CurrentShadowMap),
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@value(CurrentShadowMap)_uv_param );
fShadow = lerp( fShadow, fShadowBlend,
(inPs.depth - passBuf.pssmBlendPoints@value(CurrentShadowMapBlend)) /
@@ -387,7 +406,9 @@
@property( receive_shadows )
float fShadow = getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL0,
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@counter(CurrentShadowMap)_uv_param );
@end @property( !receive_shadows )
float fShadow = 1.0;
@@ -400,7 +421,9 @@
@piece( DarkenWithShadow )
* getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL@value(CurrentShadowMap),
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@counter(CurrentShadowMap)_uv_param )
@end
This looks almost perfect (minor artifacts here and there) with some exceptions.
A couple things to notice:
- The "0.75f" in "(1.0f - tmpNDotL) * 0.75f * pixelData.geomNormal.xyz..." is the arbitrary normal offset
- The spheres from PbsMaterial benefit from a value much smaller than 0.75, else they show artifacts
- The -0.015 in "float shadowConstantBias = -0.015 / passBuf.depthRange.y /passBuf.depthRange.y * 0.1f;" is the arbitrary constant offset. The value from HlmsDatablock is not being respected in this patch
- The caster "/ passBuf.depthRange.y /passBuf.depthRange.y" can be done much more efficiently (mostly because a few lines later we multiply against passBuf.depthRange.y; this was a quick way of undoing that from the root)
- I tested Forward3D sample (which has a large scene), a modified version of ShadowMapDebugging, and PbsMaterials
- ESM could be broken
- It's quite clear with this technique that two factors are needed: One global (per scene) and one per object. I'm not sure yet if we can identify what element from a scene can be used to automatically calculate that global factor
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
Heres some comparison shots:
First with some ambience, notice all the white streaks because of the broken self shadowing. without(left) and normal offset(right)
No ambience to show what it looks like without(left) and normal offset(right)
Brighter comparison: before(left) and new normal offset(right)
-
- OGRE Team Member
- Posts: 5446
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1348
Re: [2.2] Self Shadowing errors
Code: Select all
diff --git a/OgreMain/src/OgreHlmsDatablock.cpp b/OgreMain/src/OgreHlmsDatablock.cpp
index ae5e73810..6e41076dd 100644
--- a/OgreMain/src/OgreHlmsDatablock.cpp
+++ b/OgreMain/src/OgreHlmsDatablock.cpp
@@ -115,7 +115,7 @@ namespace Ogre
mAlphaTestCmp( CMPF_ALWAYS_PASS ),
mAlphaTestShadowCasterOnly( false ),
mAlphaTestThreshold( 0.5f ),
- mShadowConstantBias( 0.01f )
+ mShadowConstantBias( 0.05f )
{
mMacroblockHash[0] = mMacroblockHash[1] = 0;
mMacroblock[0] = mMacroblock[1] = 0;
diff --git a/OgreMain/src/OgreHlmsManager.cpp b/OgreMain/src/OgreHlmsManager.cpp
index 4292409f0..99c3787ff 100644
--- a/OgreMain/src/OgreHlmsManager.cpp
+++ b/OgreMain/src/OgreHlmsManager.cpp
@@ -44,7 +44,7 @@ namespace Ogre
HlmsManager::HlmsManager() :
mComputeHlms( 0 ),
mRenderSystem( 0 ),
- mShadowMappingUseBackFaces( true ),
+ mShadowMappingUseBackFaces( false ),
mDefaultHlmsType( HLMS_PBS )
#if !OGRE_NO_JSON
, mJsonListener( 0 )
diff --git a/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp b/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp
index a2415e108..057d414b9 100644
--- a/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp
+++ b/Samples/2.0/ApiUsage/ShadowMapDebugging/ShadowMapDebuggingGameState.cpp
@@ -97,7 +97,7 @@ namespace Demo
createChildSceneNode( Ogre::SCENE_DYNAMIC );
mSceneNode[idx]->setPosition( (i - 1.5f) * armsLength,
- 2.0f,
+ 0.0f,
(j - 1.5f) * armsLength );
mSceneNode[idx]->setScale( 0.65f, 0.65f, 0.65f );
@@ -123,7 +123,7 @@ namespace Demo
lightNode->attachObject( light );
light->setDiffuseColour( 0.8f, 0.4f, 0.2f ); //Warm
light->setSpecularColour( 0.8f, 0.4f, 0.2f );
- light->setPowerScale( Ogre::Math::PI );
+ light->setPowerScale( Ogre::Math::PI * 0 );
light->setType( Ogre::Light::LT_SPOTLIGHT );
lightNode->setPosition( -10.0f, 10.0f, 10.0f );
light->setDirection( Ogre::Vector3( 1, -1, -1 ).normalisedCopy() );
@@ -136,7 +136,7 @@ namespace Demo
lightNode->attachObject( light );
light->setDiffuseColour( 0.2f, 0.4f, 0.8f ); //Cold
light->setSpecularColour( 0.2f, 0.4f, 0.8f );
- light->setPowerScale( Ogre::Math::PI );
+ light->setPowerScale( Ogre::Math::PI * 0 );
light->setType( Ogre::Light::LT_SPOTLIGHT );
lightNode->setPosition( 10.0f, 10.0f, -10.0f );
light->setDirection( Ogre::Vector3( -1, -1, 1 ).normalisedCopy() );
@@ -175,6 +175,14 @@ namespace Demo
gaussianDeviationFactor, K );
#endif
+ {
+ Ogre::Root *root = mGraphicsSystem->getRoot();
+ Ogre::Hlms *hlms = root->getHlmsManager()->getHlms( Ogre::HLMS_PBS );
+ assert( dynamic_cast<Ogre::HlmsPbs*>( hlms ) );
+ Ogre::HlmsPbs *pbs = static_cast<Ogre::HlmsPbs*>( hlms );
+ pbs->getHlmsManager()->setShadowMappingUseBackFaces( false );
+ }
+
TutorialGameState::createScene01();
}
//-----------------------------------------------------------------------------------
@@ -450,10 +458,10 @@ namespace Demo
}
#endif
- if( nextFilter == Ogre::HlmsPbs::ExponentialShadowMaps )
+ //if( nextFilter == Ogre::HlmsPbs::ExponentialShadowMaps )
pbs->getHlmsManager()->setShadowMappingUseBackFaces( false );
- else
- pbs->getHlmsManager()->setShadowMappingUseBackFaces( true );
+// else
+// pbs->getHlmsManager()->setShadowMappingUseBackFaces( true );
pbs->setShadowSettings( nextFilter );
diff --git a/Samples/Media/Hlms/Common/Any/ShadowCaster_piece_vs.any b/Samples/Media/Hlms/Common/Any/ShadowCaster_piece_vs.any
index d4e0a668a..7a66574f5 100644
--- a/Samples/Media/Hlms/Common/Any/ShadowCaster_piece_vs.any
+++ b/Samples/Media/Hlms/Common/Any/ShadowCaster_piece_vs.any
@@ -3,14 +3,22 @@
@property( hlms_shadowcaster )
@piece( DoShadowCasterVS )
- float shadowConstantBias = uintBitsToFloat( worldMaterialIdx[inVs_drawId].y );
+ @property( hlms_no_reverse_depth )
+ float shadowConstantBias = uintBitsToFloat( worldMaterialIdx[inVs_drawId].y );
+ @else
+ //float shadowConstantBias = -uintBitsToFloat( worldMaterialIdx[inVs_drawId].y );
+ //float shadowConstantBias = -0.5 / passBuf.depthRange.y * 0.1f;
+ //float shadowConstantBias = -4.5 / passBuf.depthRange.y * 0.1f;
+ float shadowConstantBias = -0.015 / passBuf.depthRange.y /passBuf.depthRange.y * 0.1f;
+ //float shadowConstantBias = 0.65 / passBuf.depthRange.y * 0.1f;
+ @end
@property( !hlms_shadow_uses_depth_texture && !hlms_shadowcaster_point && !exponential_shadow_maps )
//Linear depth
@property( hlms_shadowcaster_directional || !hlms_no_reverse_depth )
- outVs.depth = outVs_Position.z + shadowConstantBias * passBuf.depthRange.y * passBuf.depthRange.y;
+ outVs.depth = outVs_Position.z + shadowConstantBias * passBuf.depthRange.y * passBuf.depthRange.y;
@else
- outVs.depth = (outVs_Position.z + shadowConstantBias * passBuf.depthRange.y) * passBuf.depthRange.y;
+ outVs.depth = (outVs_Position.z + shadowConstantBias * passBuf.depthRange.y) * passBuf.depthRange.y;
@end
@property( hlms_no_reverse_depth && (syntax == glsl || syntax == glsles) )outVs.depth = (outVs.depth * 0.5) + 0.5;@end
@end
@@ -27,7 +35,7 @@
//however we can use a cheap approximation ("pseudo linear depth")
//see http://www.yosoygames.com.ar/wp/2014/01/linear-depth-buffer-my-ass/
@property( hlms_shadowcaster_directional || !hlms_no_reverse_depth )
- outVs_Position.z = outVs_Position.z + shadowConstantBias * passBuf.depthRange.y * passBuf.depthRange.y;
+ outVs_Position.z = outVs_Position.z + shadowConstantBias * passBuf.depthRange.y * passBuf.depthRange.y;
@else
outVs_Position.z = (outVs_Position.z + shadowConstantBias * passBuf.depthRange.y) * passBuf.depthRange.y * outVs_Position.w;
@end
diff --git a/Samples/Media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any b/Samples/Media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any
index 58b8b7e01..8b843eeb5 100644
--- a/Samples/Media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any
+++ b/Samples/Media/Hlms/Pbs/Any/ShadowMapping_piece_ps.any
@@ -1,4 +1,4 @@
-
+
//#include "SyntaxHighlightingMisc.h"
@property( hlms_num_shadow_map_lights )
@@ -134,10 +134,10 @@
@foreach( 4, m )
@property( @m == 0 )
INLINE float getShadow( @insertpiece( TEXTURE2DSHADOW ) shadowMap, @insertpiece( SamplerShadow )
- float4 psPosLN, float4 invShadowMapSize )
+ float4 psPosLN, float4 invShadowMapSize, float2 invDepthRange, PixelData pixelData, float f )
@end @property( @m == 1 )
INLINE float getShadow( @insertpiece( TEXTURE2DSHADOW ) shadowMap, @insertpiece( SamplerShadow )
- float4 psPosLN, float4 invShadowMapSize, float2 minUV, float2 maxUV )
+ float4 psPosLN, float4 invShadowMapSize, float2 invDepthRange, PixelData pixelData, float f, float2 minUV, float2 maxUV )
@end @property( @m == 2 )
INLINE float getShadowPoint( @insertpiece( TEXTURE2DSHADOW ) shadowMap, @insertpiece( SamplerShadow )
float3 posVS, float3 lightPos, float4 invShadowMapSize, float2 invDepthRange
@@ -150,6 +150,21 @@
@end
{
@property( @m < 2 )
+ float tmpNDotL = saturate( dot( passBuf.lights[0].position.xyz, pixelData.geomNormal.xyz ) );
+ @property( @m == 0 )
+ psPosLN.xy -= ((1.0f - tmpNDotL) * 3.5f * pixelData.geomNormal.xy * 0.000488281f * invDepthRange.y) * psPosLN.w;
+ @else
+ float regionSize = (maxUV.x - minUV.x) / invShadowMapSize.x;
+ regionSize = 1.0f / regionSize;
+ float dff = max( abs(OGRE_ddx( psPosLN.z )), abs(OGRE_ddy( psPosLN.z )) );
+ dff = 1.0f + pow( dff, 0.1 ) * 16.0;
+ //float dff = max( 1.0f - 4.0 * pow( max( abs(OGRE_ddx( psPosLN.z )), abs(OGRE_ddy( psPosLN.z )) ), 0.05 ), 0 );
+ //float dff = 1.0;
+ psPosLN.xyz -= ((1.0f - tmpNDotL) * (0.75f) * pixelData.geomNormal.xyz *
+ float3(regionSize,regionSize, -1.0f * invDepthRange.y / dff)) * psPosLN.w;
+// psPosLN.xyz -= ((1.0f - tmpNDotL) * 0.5f * pixelData.geomNormal.xyz * regionSize * (f+1)) * psPosLN.w;
+// psPosLN.z += (f) * psPosLN.w * 0.005f;
+ @end
//Spot and directional lights
@property( !exponential_shadow_maps && !hlms_no_reverse_depth )
float fDepth = psPosLN.z / psPosLN.w;
@@ -328,14 +343,18 @@
{
fShadow = getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL0,
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@counter(CurrentShadowMap)_uv_param );
@property( hlms_pssm_blend )
if( inPs.depth > passBuf.pssmBlendPoints@value(CurrentShadowMapBlend) )
{
fShadowBlend = getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL1,
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@value(CurrentShadowMap)_uv_param );
fShadow = lerp( fShadow, fShadowBlend,
(inPs.depth - passBuf.pssmBlendPoints@value(CurrentShadowMapBlend)) /
@@ -351,14 +370,18 @@
{
fShadow = getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL@n,
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@counter(CurrentShadowMap)_uv_param );
@property( hlms_pssm_blend && @n < hlms_pssm_splits_minus_one )
if( inPs.depth > passBuf.pssmBlendPoints@value(CurrentShadowMapBlend) )
{
fShadowBlend = getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL@value(CurrentShadowMap),
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@value(CurrentShadowMap)_uv_param );
fShadow = lerp( fShadow, fShadowBlend,
(inPs.depth - passBuf.pssmBlendPoints@value(CurrentShadowMapBlend)) /
@@ -387,7 +410,9 @@
@property( receive_shadows )
float fShadow = getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL0,
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@counter(CurrentShadowMap)_uv_param );
@end @property( !receive_shadows )
float fShadow = 1.0;
@@ -400,7 +425,9 @@
@piece( DarkenWithShadow )
* getShadow( hlms_shadowmap@value(CurrentShadowMap), @insertpiece( UseSamplerShadow )
inPs.posL@value(CurrentShadowMap),
- passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
+ passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize,
+ passBuf.shadowRcv[@value(CurrentShadowMap)].shadowDepthRange.xy,
+ pixelData, @value(CurrentShadowMap)
hlms_shadowmap@counter(CurrentShadowMap)_uv_param )
@end
-
- OGRE Team Member
- Posts: 5446
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1348
Re: [2.2] Self Shadowing errors
Also I found the original paper in Godot's github. The technique works from vertex shader too!
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
How would the light affect the offset in the vertex shader, would it have the same quality.
And yeah that original paper was useful for me too, I should have posted a link to it. sorry
Edit: Be careful with front face culling and point lights: (as my version does not support point lights and normal offsets yet)
The point lights need a bias at all times from what it seems. Its also good that we are solving this as having blacker areas with no light bleed or acne means the GI solutions will have better quality.
-
- Goblin
- Posts: 272
- Joined: Thu Jun 10, 2004 4:19 am
- x 26
Re: [2.2] Self Shadowing errors
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
-
- OGRE Team Member
- Posts: 5446
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1348
Re: [2.2] Self Shadowing errors
I didn't want to risk breaking master, it needs more testing (but so far it looks damn good!).
The commit explains the changes.
I removed the back face method. This method is far superior.
This version supports all light types: directional, spot & point lights.
Cheers!
-
- Gnoll
- Posts: 659
- Joined: Mon Aug 06, 2007 12:53 pm
- Location: Saarland, Germany
- x 63
Re: [2.2] Self Shadowing errors
thanks! I will test it.
Best Regards
Lax
http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62
-
- Gnoll
- Posts: 659
- Joined: Mon Aug 06, 2007 12:53 pm
- Location: Saarland, Germany
- x 63
Re: [2.2] Self Shadowing errors
I cannot load a scene anymore using the 'shadow_bias_improve'. I updated all hlms/compositor resource and cleared also the shader cache.
But I'm getting the following shader compile errors:
Code: Select all
13:56:49: OGRE EXCEPTION(-2147467259:RenderingAPIException): Cannot compile D3D11 high-level shader 700000000VertexShader_vs Errors:
(438,45-53): error X3004: undeclared identifier 'worldNorm'
in D3D11HLSLProgram::compileMicrocode at ..\Ogre2.2SDK\RenderSystems\Direct3D11\src\OgreD3D11HLSLProgram.cpp (line 549)
13:56:49: High-level program 700000000VertexShader_vs encountered an error during loading and is thus not supported.
Lax
http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
@Lax, i shall see if i get this too and let you know.
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
I am also running in DX11.
However, so far i am experiencing the odd strange shadow artefact that i didn't get with mine happening at the moment which i am investigating.
-
- OGRE Team Member
- Posts: 5446
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1348
Re: [2.2] Self Shadowing errors
Thanks for the report. Fixed it.Lax wrote: ↑Fri Jun 12, 2020 12:58 pm Hi,
I cannot load a scene anymore using the 'shadow_bias_improve'. I updated all hlms/compositor resource and cleared also the shader cache.
But I'm getting the following shader compile errors:
Best RegardsCode: Select all
13:56:49: OGRE EXCEPTION(-2147467259:RenderingAPIException): Cannot compile D3D11 high-level shader 700000000VertexShader_vs Errors: (438,45-53): error X3004: undeclared identifier 'worldNorm' in D3D11HLSLProgram::compileMicrocode at ..\Ogre2.2SDK\RenderSystems\Direct3D11\src\OgreD3D11HLSLProgram.cpp (line 549) 13:56:49: High-level program 700000000VertexShader_vs encountered an error during loading and is thus not supported.
Lax
Gosh, I really should work on that "unit test mode" for the samples so that these bugs can be spot immediately and automatically.
-
- OGRE Contributor
- Posts: 203
- Joined: Sat Jul 16, 2011 8:29 pm
- Location: UK
- x 51
Re: [2.2] Self Shadowing errors
Quick question and not sure if i'm wrong, but is the worldnormal of the object multiplied by the transform of the node? Or does the normal that comes into the vertex already have the multiplication against the node transform. Could be having a ditsy moment haha
Because i'm just looking at the animated boxes in the ShadowmapDebugging and keep getting black on top of the boxes at certain rotations.
Also some shadow acne on the stable splits in that demo too.
-
- OGRE Team Member
- Posts: 5446
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1348
Re: [2.2] Self Shadowing errors
The normals are in object space, hence need to be multiplied against the worldMatrix to be in world space.SolarPortal wrote: ↑Fri Jun 12, 2020 7:24 pm Quick question and not sure if i'm wrong, but is the worldnormal of the object multiplied by the transform of the node? Or does the normal that comes into the vertex already have the multiplication against the node transform. Could be having a ditsy moment haha
I can't see such thing, perhaps GL3+ vs D3D11 thing? (I only tried GL).Because i'm just looking at the animated boxes in the ShadowmapDebugging and keep getting black on top of the boxes at certain rotations.
Also I tried to apply the lowest bias as possible
I see it too once stable splits > 1; which is why I added the ability to globally control the bias per cascade.SolarPortal wrote: ↑Fri Jun 12, 2020 7:24 pm Also some shadow acne on the stable splits in that demo too.
Once stable splits > 2, the quality degradation on the higher splits is rather big; thus it's no longer just a matter of a "small bias issue" (but it can be solved with larger biases).
I agree the shadow map debugging sample should automatically adjust these biases to show how it's done.