protected virtual Pass DeriveShadowReceiverPass( Pass pass )
{
if ( this.IsShadowTechniqueTextureBased )
{
Pass retPass;
if ( pass.Parent.ShadowReceiverMaterial != null )
{
retPass = pass.Parent.ShadowReceiverMaterial.GetBestTechnique().GetPass( 0 );
}
else
{
retPass = ( this.shadowTextureCustomReceiverPass != null ? this.shadowTextureCustomReceiverPass : this.shadowReceiverPass );
}
// Does incoming pass have a custom shadow receiver program?
if ( pass.ShadowReceiverVertexProgramName != "" )
{
retPass.SetVertexProgram( pass.ShadowReceiverVertexProgramName );
GpuProgram prg = retPass.VertexProgram;
// Load this program if not done already
if ( !prg.IsLoaded )
{
prg.Load();
}
// Copy params
retPass.VertexProgramParameters = pass.ShadowReceiverVertexProgramParameters;
// Also have to hack the light autoparams, that is done later
}
else
{
if ( retPass == this.shadowTextureCustomReceiverPass )
{
if ( this.shadowTextureCustomReceiverPass.VertexProgramName != this.shadowTextureCustomReceiverVertexProgram )
{
this.shadowTextureCustomReceiverPass.SetVertexProgram( this.shadowTextureCustomReceiverVertexProgram );
if ( retPass.HasVertexProgram )
{
retPass.VertexProgramParameters = this.shadowTextureCustomReceiverVPParams;
}
}
}
else
{
retPass.SetVertexProgram( "" );
}
}
int keepTUCount;
// If additive, need lighting parameters & standard programs
if ( this.IsShadowTechniqueAdditive )
{
keepTUCount = 1;
retPass.LightingEnabled = true;
retPass.Ambient = pass.Ambient;
retPass.SelfIllumination = pass.SelfIllumination;
retPass.Diffuse = pass.Diffuse;
retPass.Specular = pass.Specular;
retPass.Shininess = pass.Shininess;
retPass.SetRunOncePerLight( pass.IteratePerLight,
pass.RunOnlyOncePerLightType,
pass.OnlyLightType );
// We need to keep alpha rejection settings
retPass.SetAlphaRejectSettings( pass.AlphaRejectFunction, pass.AlphaRejectValue );
// Copy texture state, shift up one since 0 is shadow texture
int origPassTUCount = pass.TextureUnitStageCount;
for ( int t = 0; t < origPassTUCount; ++t )
{
int targetIndex = t + 1;
TextureUnitState tex = ( retPass.TextureUnitStageCount <= targetIndex
?
retPass.CreateTextureUnitState()
:
retPass.GetTextureUnitState( targetIndex ) );
pass.GetTextureUnitState( t ).CopyTo( tex );
// If programmable, have to adjust the texcoord sets too
// D3D insists that texcoordsets match tex unit in programmable mode
if ( retPass.HasVertexProgram )
tex.TextureCoordSet = targetIndex;
}
keepTUCount = origPassTUCount + 1;
}
else
{
// need to keep spotlight fade etc
keepTUCount = retPass.TextureUnitStageCount;
}
// Will also need fragment programs since this is a complex light setup
if ( pass.ShadowReceiverFragmentProgramName != "" )
{
// Have to merge the shadow receiver vertex program in
retPass.SetFragmentProgram( pass.ShadowReceiverFragmentProgramName );
GpuProgram prg = retPass.FragmentProgram;
// Load this program if not done already
if ( !prg.IsLoaded )
{
prg.Load();
}
// Copy params
retPass.FragmentProgramParameters = pass.ShadowReceiverFragmentProgramParameters;
// Did we bind a shadow vertex program?
if ( pass.HasVertexProgram && !retPass.HasVertexProgram )
{
// We didn't bind a receiver-specific program, so bind the original
retPass.SetVertexProgram( pass.VertexProgramName );
prg = retPass.VertexProgram;
// Load this program if required
if ( !prg.IsLoaded )
{
prg.Load();
}
// Copy params
retPass.VertexProgramParameters = pass.VertexProgramParameters;
}
}
else
{
// Reset any merged fragment programs from last time
if ( retPass == this.shadowTextureCustomReceiverPass )
{
// reset fp?
if ( retPass.FragmentProgramName != this.shadowTextureCustomReceiverFragmentProgram )
{
retPass.SetFragmentProgram( this.shadowTextureCustomReceiverFragmentProgram );
if ( retPass.HasFragmentProgram )
{
retPass.FragmentProgramParameters = this.shadowTextureCustomReceiverFPParams;
}
}
}
else
{
// Standard shadow receiver pass, reset to no fp
retPass.SetFragmentProgram( "" );
}
}
// Remove any extra texture units
while ( retPass.TextureUnitStageCount > keepTUCount )
{
retPass.RemoveTextureUnitState( keepTUCount );
}
retPass.Load();
return retPass;
}
else
{
return pass;
}
}