I try to implement depth shadow mapping for a small video game. I have to use GLSL shaders. The goal is to get a fair shadow quality with self shadows, keeping good perfomances if possible.
I copied the materials from the Ogre Shadow Sample (Ogre/DepthShadowmap/Caster/Float & Ogre/DepthShadowmap/Receiver/Float) with their corresponding GLSL shaders. With some very minor changes (for transparency textures), I managed to make it work using the SHADOW_TYPE_TEXTURE_ADDITIVE mode.
=> My problem was that I cannot keep a fair shadow quality (and shadow distance) withtout having a huge drop in fps
So I switched in SHADOW_TYPE_TEXTURE_ADDITIVE_INTEGRATED mode. My goal : gain fps by using a minimum number of passes and use the PSSMCameraSetup to manage long distance shadows. I modified my shadow receiver shaders so it also makes the shading stuff (normaly done by some default material throught the ambient/lighting/decal passes if I well understood). The shading works, but my shadows wether disappear (default CameraSetup) or are totaly wrong and uncomprehensive (using LiSPSMShadowCameraSetup).
My cpp :
Code: Select all
mSceneMgr->setShadowTexturePixelFormat(Ogre::PF_FLOAT16_R);
mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
mSceneMgr->setShadowTextureSelfShadow(true);
mSceneMgr->setShadowTextureSize(2048);
mSceneMgr->setShadowFarDistance(100);
mSceneMgr->setShadowTextureCasterMaterial("Ogre/DepthShadowmap/Caster/Float");
Code: Select all
vertex_program Ogre/DepthShadowmap/ReceiverIntegratedVP_GLSL glsl
{
source DepthShadowmapReceiverIntegratedVp.glsl
default_params
{
param_named_auto world world_matrix
param_named_auto worldIT inverse_transpose_world_matrix
param_named_auto worldViewProj worldviewproj_matrix
param_named_auto texViewProj texture_viewproj_matrix
param_named_auto lightPosition light_position 0
param_named_auto lightColour light_diffuse_colour 0
}
}
fragment_program Ogre/DepthShadowmap/ReceiverIntegratedFP_GLSL glsl
{
source DepthShadowmapReceiverIntegratedFp.glsl
preprocessor_defines PCF=0
default_params
{
param_named shadowMap int 0
param_named inverseShadowmapSize float 0.0009765625
param_named fixedDepthBias float 0.0005
param_named gradientClamp float 0.0098
param_named gradientScaleBias float 0
param_named_auto ambientColour ambient_light_colour
}
}
vertex_program Ogre/DepthShadowmap/ReceiverIntegratedVP unified
{
delegate Ogre/DepthShadowmap/ReceiverIntegratedVP_GLSL
}
fragment_program Ogre/DepthShadowmap/ReceiverIntegratedFP unified
{
delegate Ogre/DepthShadowmap/ReceiverIntegratedFP_GLSL
}
material Ogre/DepthShadowmap/ReceiverIntegrated/Float
{
technique
{
pass
{
vertex_program_ref Ogre/DepthShadowmap/ReceiverIntegratedVP
{
}
fragment_program_ref Ogre/DepthShadowmap/ReceiverIntegratedFP
{
}
texture_unit 0
{
texture 1stCharacter.dds
}
texture_unit 1
{
content_type shadow
}
}
}
}
Code: Select all
uniform mat4 world;
uniform mat4 worldIT;
uniform mat4 worldViewProj;
uniform mat4 texViewProj;
uniform vec4 lightPosition;
uniform vec4 lightColour;
uniform vec4 shadowDepthRange;
in vec2 uv0;
void main()
{
gl_Position = ftransform();
vec4 worldPos = world * gl_Vertex;
vec3 worldNorm = (worldIT * vec4(gl_Normal, 1)).xyz;
// calculate lighting (simple vertex lighting)
vec3 lightDir = normalize(
lightPosition.xyz - (worldPos.xyz * lightPosition.w));
gl_FrontColor = lightColour * max(dot(lightDir, worldNorm), 0.0);
gl_TexCoord[0] = vec4(uv0, 0, 0);
// calculate shadow map coords
gl_TexCoord[1] = texViewProj * worldPos;
#if LINEAR_RANGE
// adjust by fixed depth bias, rescale into range
gl_TexCoord[1].z = (gl_TexCoord[1].z - shadowDepthRange.x) * shadowDepthRange.w;
#endif
}
Code: Select all
uniform float inverseShadowmapSize;
uniform float fixedDepthBias;
uniform float gradientClamp;
uniform float gradientScaleBias;
uniform float shadowFuzzyWidth;
uniform vec4 ambientColour;
uniform sampler2D texMap;
uniform sampler2D shadowMap;
void main()
{
vec4 texColor = texture2D(texMap, gl_TexCoord[0].xy);
vec4 shadowUV = gl_TexCoord[1];
// point on shadowmap
#if LINEAR_RANGE
shadowUV.xy = shadowUV.xy / shadowUV.w;
#else
shadowUV = shadowUV / shadowUV.w;
#endif
float centerdepth = texture2D(shadowMap, shadowUV.xy).x;
// gradient calculation
float pixeloffset = inverseShadowmapSize;
vec4 depths = vec4(
texture2D(shadowMap, shadowUV.xy + vec2(-pixeloffset, 0)).x,
texture2D(shadowMap, shadowUV.xy + vec2(+pixeloffset, 0)).x,
texture2D(shadowMap, shadowUV.xy + vec2(0, -pixeloffset)).x,
texture2D(shadowMap, shadowUV.xy + vec2(0, +pixeloffset)).x);
vec2 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;
gl_FragColor = ambientColour;
if (finalCenterDepth > shadowUV.z)
{
gl_FragColor.xyz += gl_Color.xyz;
}
gl_FragColor *= texColor;
}