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
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);
receiving material, shadow obtained
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;
}
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
}
}
}
}