protected virtual Pass DeriveShadowCasterPass( Pass pass )
{
if ( this.IsShadowTechniqueTextureBased )
{
Pass retPass;
if ( pass.Parent.ShadowCasterMaterial != null )
{
retPass = pass.Parent.ShadowCasterMaterial.GetBestTechnique().GetPass( 0 );
}
else
{
retPass = ( this.shadowTextureCustomCasterPass != null ? this.shadowTextureCustomCasterPass : this.shadowCasterPlainBlackPass );
}
// Special case alpha-blended passes
if ( ( pass.SourceBlendFactor == SceneBlendFactor.SourceAlpha &&
pass.DestinationBlendFactor == SceneBlendFactor.OneMinusSourceAlpha )
|| pass.AlphaRejectFunction != CompareFunction.AlwaysPass )
{
// Alpha blended passes must retain their transparency
retPass.SetAlphaRejectSettings( pass.AlphaRejectFunction, pass.AlphaRejectValue );
retPass.SetSceneBlending( pass.SourceBlendFactor, pass.DestinationBlendFactor );
retPass.Parent.Parent.TransparencyCastsShadows = true;
// So we allow the texture units, but override the color functions
// Copy texture state, shift up one since 0 is shadow texture
int origPassTUCount = pass.TextureUnitStageCount;
for ( int t = 0; t < origPassTUCount; ++t )
{
TextureUnitState tex;
if ( retPass.TextureUnitStageCount <= t )
{
tex = retPass.CreateTextureUnitState();
}
else
{
tex = retPass.GetTextureUnitState( t );
}
// copy base state
pass.GetTextureUnitState( t ).CopyTo( tex );
// override colour function
tex.SetColorOperationEx( LayerBlendOperationEx.Source1, LayerBlendSource.Manual, LayerBlendSource.Current, this.IsShadowTechniqueAdditive ? ColorEx.Black : shadowColor );
}
// Remove any extras
while ( retPass.TextureUnitStageCount > origPassTUCount )
{
retPass.RemoveTextureUnitState( origPassTUCount );
}
}
else
{
// reset
retPass.SetSceneBlending( SceneBlendType.Replace );
retPass.AlphaRejectFunction = CompareFunction.AlwaysPass;
while ( retPass.TextureUnitStageCount > 0 )
{
retPass.RemoveTextureUnitState( 0 );
}
}
// Propogate culling modes
retPass.CullingMode = pass.CullingMode;
retPass.ManualCullingMode = pass.ManualCullingMode;
// Does incoming pass have a custom shadow caster program?
if ( pass.ShadowCasterVertexProgramName != "" )
{
retPass.SetVertexProgram( pass.ShadowCasterVertexProgramName, false );
GpuProgram prg = retPass.VertexProgram;
// Load this program if not done already
if ( !prg.IsLoaded )
{
prg.Load();
}
// Copy params
retPass.VertexProgramParameters = pass.ShadowCasterVertexProgramParameters;
// Also have to hack the light autoparams, that is done later
}
else
{
// reset vp?
if ( retPass == this.shadowTextureCustomCasterPass )
{
if ( retPass.VertexProgramName != this.shadowTextureCustomCasterVertexProgram )
{
this.shadowTextureCustomCasterPass.SetVertexProgram( this.shadowTextureCustomCasterVertexProgram );
if ( retPass.HasVertexProgram )
{
retPass.VertexProgramParameters = this.shadowTextureCustomCasterVPParams;
}
}
}
else
{
// Standard shadow caster pass, reset to no vp
retPass.SetVertexProgram( "" );
}
}
return retPass;
}
else
{
return pass;
}
}