///<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; } } }