///<summary>
/// Collect rendering passes. Here, passes are converted into render target operations
/// and queued with queueRenderSystemOp.
///</summary>
protected void CollectPasses( CompositeTargetOperation finalState, CompositionTargetPass target )
{
// Here, passes are converted into render target operations
Pass targetPass = null;
Technique srctech = null;
Material mat = null, srcmat = null;
foreach ( var pass in target.Passes )
{
switch ( pass.Type )
{
case CompositorPassType.Clear:
{
QueueRenderSystemOp( finalState,
new RSClearOperation( pass.ClearBuffers, pass.ClearColor, pass.ClearDepth, pass.ClearStencil ) );
}
break;
case CompositorPassType.Stencil:
{
QueueRenderSystemOp( finalState,
new RSStencilOperation( pass.StencilCheck, pass.StencilFunc, pass.StencilRefValue,
pass.StencilMask, pass.StencilFailOp, pass.StencilDepthFailOp,
pass.StencilPassOp, pass.StencilTwoSidedOperation ) );
}
break;
case CompositorPassType.RenderScene:
{
if ( pass.FirstRenderQueue < finalState.CurrentQueueGroupId )
{
// Mismatch -- warn user
// XXX We could support repeating the last queue, with some effort
LogManager.Instance.Write( "Warning in compilation of Compositor {0}: Attempt to render queue {1} before {2}.",
this.compositor.Name, pass.FirstRenderQueue, finalState.CurrentQueueGroupId );
}
RSSetSchemeOperation setSchemeOperation = null;
if ( pass.MaterialScheme != string.Empty )
{
//Add the triggers that will set the scheme and restore it each frame
finalState.CurrentQueueGroupId = pass.FirstRenderQueue;
setSchemeOperation = new RSSetSchemeOperation( pass.MaterialScheme );
QueueRenderSystemOp( finalState, setSchemeOperation );
}
// Add render queues
for ( var x = (int)pass.FirstRenderQueue; x < (int)pass.LastRenderQueue; x++ )
{
Debug.Assert( x >= 0 );
finalState.RenderQueues.Set( x, true );
}
finalState.CurrentQueueGroupId = pass.LastRenderQueue + 1;
if ( setSchemeOperation != null )
{
//Restoring the scheme after the queues have been rendered
QueueRenderSystemOp( finalState, new RSRestoreSchemeOperation( setSchemeOperation ) );
}
finalState.FindVisibleObjects = true;
finalState.MaterialScheme = target.MaterialScheme;
finalState.ShadowsEnabled = target.ShadowsEnabled;
}
break;
case CompositorPassType.RenderQuad:
{
srcmat = pass.Material;
if ( srcmat == null )
{
// No material -- warn user
LogManager.Instance.Write(
"Warning in compilation of Compositor {0}: No material defined for composition pass.", this.compositor.Name );
break;
}
srcmat.Load();
if ( srcmat.SupportedTechniques.Count == 0 )
{
// No supported techniques -- warn user
LogManager.Instance.Write(
"Warning in compilation of Compositor {0}: material {1} has no supported techniques.", this.compositor.Name,
srcmat.Name );
break;
}
srctech = srcmat.GetBestTechnique( 0 );
// Create local material
mat = CreateLocalMaterial( srcmat.Name );
// Copy and adapt passes from source material
for ( var i = 0; i < srctech.PassCount; i++ )
{
var srcpass = srctech.GetPass( i );
// Create new target pass
targetPass = mat.GetTechnique( 0 ).CreatePass();
srcpass.CopyTo( targetPass );
// Set up inputs
for ( var x = 0; x < pass.InputsCount; x++ )
{
var inp = pass.GetInput( x );
if ( !string.IsNullOrEmpty( inp.Name ) )
{
if ( x < targetPass.TextureUnitStatesCount )
{
targetPass.GetTextureUnitState( x ).SetTextureName( GetTextureInstance( inp.Name, inp.MrtIndex ).Name );
}
else
{
// Texture unit not there
LogManager.Instance.Write(
"Warning in compilation of Compositor {0}: material {1} texture unit {2} out of bounds.",
this.compositor.Name,
srcmat.Name, x );
}
}
} //end for inputs.length
} //end for passcount
var rsQuadOperation = new RSQuadOperation( this, pass.Identifier, mat );
float left, top, right, bottom;
if ( pass.GetQuadCorners( out left, out top, out right, out bottom ) )
{
rsQuadOperation.SetQuadCorners( left, top, right, bottom );
}
rsQuadOperation.SetQuadFarCorners( pass.QuadFarCorners, pass.QuadFarCornersViewSpace );
QueueRenderSystemOp( finalState, rsQuadOperation );
}
break;
case CompositorPassType.RenderCustom:
{
var customOperation = CompositorManager.Instance.CustomCompositionPasses[ pass.CustomType ].CreateOperation(
this, pass );
QueueRenderSystemOp( finalState, customOperation );
}
break;
}
}
}