Spotlight issue when using depth shadow mapping

Anything and everything that's related to OGRE or the wider graphics field that doesn't fit into the other forums.
Post Reply
nickygs
Gnoblar
Posts: 15
Joined: Wed Jul 20, 2016 7:55 pm

Spotlight issue when using depth shadow mapping

Post by nickygs »

So I used the following link http://www.ogre3d.org/tikiwiki/Depth+Shadow+Mapping in the wiki to get Depth shadow mapping to work, or that's what I thought.
I've read http://www.ogre3d.org/docs/manual/manual_72.html and know that point lights must be out of camera view and above the frustrum to work correctly.

The problem is, spot lights and directional light should work out of the box unlike point lights but spotlights are giving me an issue. I played with the biases until I got the shadow I expected. The spotlights are illuminating a much larger area than they should be. I have seen other posts but most of them have broken links, images which are now down or reference to use projects which can no longer be downloaded. As far as I know this issue has not really been encountered.

spot light using Stencil shadows and non depth shadow mapping materials

Code: Select all

	mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);//Stencil shadow technique which renders each light as a separate additive pass to the scene
Image


spot light using

Code: Select all

mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
	// Allow self shadowing (note: this only works in conjunction with the shaders defined above)
	mSceneMgr->setShadowTextureSelfShadow(true);
	// Set the caster material which uses the shaders defined above
	mSceneMgr->setShadowTextureCasterMaterial("Ogre/DepthShadowmap/Caster/Float");
	// Set the pixel format to floating point
	mSceneMgr->setShadowTexturePixelFormat(Ogre::PF_FLOAT32_R);
	mSceneMgr->setShadowTextureCount(1);

	mSceneMgr->setShadowTextureSize(2048);
	// You can switch this on or off, I suggest you try both and see which works best for you
	mSceneMgr->setShadowCasterRenderBackFaces(true);
no receiving material, so no shadow
Image

receiving material, shadow obtained
Image

So it is quite clear that the receiving material template has something wrong with it.

Shaders from above link

Code: Select all

/* This file implements standard programs for depth shadow mapping. 
   These particular ones are suitable for additive lighting models, and
   include 3 techniques to reduce depth fighting on self-shadowed surfaces,
   constant bias, gradient (slope-scale) bias, and a fuzzy shadow map comparison*/
 
// Shadow caster vertex program.
void casterVP(
    float4 position            : POSITION,
    out float4 outPos        : POSITION,
    out float2 outDepth        : TEXCOORD0,
 
    uniform float4x4 worldViewProj,
    uniform float4 texelOffsets,
    uniform float4 depthRange
    )
{
    outPos = mul(worldViewProj, position);
 
    // fix pixel / texel alignment
    outPos.xy += texelOffsets.zw * outPos.w;
    // linear depth storage
    // offset / scale range output
#if LINEAR_RANGE
    outDepth.x = (outPos.z - depthRange.x) * depthRange.w;
#else
    outDepth.x = outPos.z;
#endif
    outDepth.y = outPos.w;
}
 
// Shadow caster fragment program for high-precision single-channel textures    
void casterFP(
    float2 depth            : TEXCOORD0,
    out float4 result        : COLOR)
 
{
#if LINEAR_RANGE
    float finalDepth = depth.x;
#else
    float finalDepth = depth.x / depth.y;
#endif
    // just smear across all components 
    // therefore this one needs high individual channel precision
    result = float4(finalDepth, finalDepth, finalDepth, 1);
}
 
void receiverVP(
    float4 position        : POSITION,
    float4 normal        : NORMAL,
 
    out float4 outPos            : POSITION,
    out float4 outColour        : COLOR,
    out float4 outShadowUV        : TEXCOORD0,
 
    uniform float4x4 world,
    uniform float4x4 worldIT,
    uniform float4x4 worldViewProj,
    uniform float4x4 texViewProj,
    uniform float4 lightPosition,
    uniform float4 lightColour,
    uniform float4 shadowDepthRange
    )
{
    float4 worldPos = mul(world, position);
    outPos = mul(worldViewProj, position);
 
    float3 worldNorm = mul(worldIT, normal).xyz;
 
    // calculate lighting (simple vertex lighting)
    float3 lightDir = normalize(
        lightPosition.xyz -  (worldPos.xyz * lightPosition.w));
 
    outColour = lightColour * max(dot(lightDir, worldNorm), 0.0);
 
    // calculate shadow map coords
    outShadowUV = mul(texViewProj, worldPos);
#if LINEAR_RANGE
    // adjust by fixed depth bias, rescale into range
    outShadowUV.z = (outShadowUV.z - shadowDepthRange.x) * shadowDepthRange.w;
#endif
}
 
void receiverFP(
    float4 position            : POSITION,
    float4 shadowUV            : TEXCOORD0,
    float4 vertexColour        : COLOR,
 
    uniform sampler2D shadowMap : register(s0),
    uniform float inverseShadowmapSize,
    uniform float fixedDepthBias,
    uniform float gradientClamp,
    uniform float gradientScaleBias,
    uniform float shadowFuzzyWidth,
 
    out float4 result        : COLOR)
{
    // point on shadowmap
#if LINEAR_RANGE
    shadowUV.xy = shadowUV.xy / shadowUV.w;
#else
    shadowUV = shadowUV / shadowUV.w;
#endif
    float centerdepth = tex2D(shadowMap, shadowUV.xy).x;
 
    // gradient calculation
      float pixeloffset = inverseShadowmapSize;
    float4 depths = float4(
        tex2D(shadowMap, shadowUV.xy + float2(-pixeloffset, 0)).x,
        tex2D(shadowMap, shadowUV.xy + float2(+pixeloffset, 0)).x,
        tex2D(shadowMap, shadowUV.xy + float2(0, -pixeloffset)).x,
        tex2D(shadowMap, shadowUV.xy + float2(0, +pixeloffset)).x);
 
    float2 differences = abs( depths.yw - depths.xz );
    float gradient = min(gradientClamp, max(differences.x, differences.y));
    float gradientFactor = gradient * gradientScaleBias;
 
    // visibility function
    float depthAdjust = gradientFactor + (fixedDepthBias * centerdepth);
    float finalCenterDepth = centerdepth + depthAdjust;
 
    // shadowUV.z contains lightspace position of current object
 
#if FUZZY_TEST
    // fuzzy test - introduces some ghosting in result and doesn't appear to be needed?
    //float visibility = saturate(1 + delta_z / (gradient * shadowFuzzyWidth));
    float visibility = saturate(1 + (finalCenterDepth - shadowUV.z) * shadowFuzzyWidth * shadowUV.w);
 
    result = vertexColour * visibility;
#else
    // hard test
#if PCF
    // use depths from prev, calculate diff
    depths += depthAdjust.xxxx;
    float final = (finalCenterDepth > shadowUV.z) ? 1.0f : 0.0f;
    final += (depths.x > shadowUV.z) ? 1.0f : 0.0f;
    final += (depths.y > shadowUV.z) ? 1.0f : 0.0f;
    final += (depths.z > shadowUV.z) ? 1.0f : 0.0f;
    final += (depths.w > shadowUV.z) ? 1.0f : 0.0f;
 
    final *= 0.2f;
 
    result = float4(vertexColour.xyz * final, 1);
 
#else
    result = (finalCenterDepth > shadowUV.z) ? vertexColour : float4(0,0,0,1);
#endif
 
#endif
}
 
/*
  Basic ambient lighting vertex program
*/
void ambientOneTexture_vp(float4 position : POSITION,
                          float2 uv          : TEXCOORD0,
 
                          out float4 oPosition : POSITION,
                          out float2 oUv       : TEXCOORD0,
                          out float4 colour    : COLOR,
 
                          uniform float4x4 worldViewProj,
                          uniform float4 ambient)
{
    oPosition = mul(worldViewProj, position);
    oUv = uv;
    colour = ambient;
}
Receiving Material Template

Code: Select all

// Basic materials which support shadows as a seperate scheme
material Ogre/DepthShadowmap/BasicTemplateMaterial
{
    // This technique supports dynamic shadows
    technique
    {
        // Base ambient pass
        pass Ambient
        {
            // base colours, not needed for rendering, but as information
            // to lighting pass categorisation routine
            ambient 1 1 1
            diffuse 0 0 0 
            specular 0 0 0 0 
            // Really basic vertex program
            vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTexture
            {
            }
        }
        // Now do the lighting pass
        // NB we don't do decal texture here because this is repeated per light
        pass Lighting
        {
            // base colours, not needed for rendering, but as information
            // to lighting pass categorisation routine
            ambient 0 0 0 
 
            // do this for each light
            iteration once_per_light
 
            scene_blend add//changing this gave some better results
 
            // Vertex program reference
            vertex_program_ref Ogre/DepthShadowmap/ReceiverVP
            {
            }
 
            // Fragment program
            fragment_program_ref Ogre/DepthShadowmap/ReceiverFP
            {
            }
 
            texture_unit
            {
                content_type shadow
                tex_address_mode clamp
                filtering none
            }
        }
 
        // Decal pass
        pass Decal
        {
            // base colours, not needed for rendering, but as information
            // to lighting pass categorisation routine
            lighting off
            // Really basic vertex program
            vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTexture
            {
                param_named ambient float4 1 1 1 1
            }
            scene_blend modulate
 
            texture_unit
            {
                texture_alias MainTexture
                tex_address_mode clamp//changed to wrap in my version
            }
        }
    }
}
User avatar
tod
Troll
Posts: 1394
Joined: Wed Aug 02, 2006 9:41 am
Location: Bucharest
x 94
Contact:

Re: Spotlight issue when using depth shadow mapping

Post by tod »

Your light seems to cover a lot of ground in the second picture, so not sure if shadow related. If you disable shadow on that light, does the light look the same?
Post Reply