Axiom.Core.SceneManager.DeriveShadowReceiverPass C# (CSharp) Method

DeriveShadowReceiverPass() protected method

Internal method for turning a regular pass into a shadow receiver pass.
This is only used for texture shadows, basically we're trying to ensure that objects are rendered with a projective texture. This method will usually return a standard single-texture pass for all fixed function passes, but will merge in a vertex program for passes with vertex programs.
protected DeriveShadowReceiverPass ( Pass pass ) : Pass
pass Axiom.Graphics.Pass
return Axiom.Graphics.Pass
		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;
			}
		}
SceneManager