///<summary> /// Compile the final (output) operation. This is done seperately because this /// is combined with the input in chained filters. ///</summary> public void CompileOutputOperation( CompositeTargetOperation finalState ) { // Final target var tpass = this.technique.OutputTarget; // Logical-and together the visibilityMask, and multiply the lodBias finalState.VisibilityMask &= tpass.VisibilityMask; finalState.LodBias *= tpass.LodBias; if ( tpass.InputMode == CompositorInputMode.Previous ) { // Collect target state for previous compositor // The TargetOperation for the final target is collected seperately as it is merged // with later operations this.previousInstance.CompileOutputOperation( finalState ); } // Collect passes CollectPasses( finalState, tpass ); }
///<summary> /// Queue a render system operation. ///</summary> ///<returns>destination pass</returns> protected void QueueRenderSystemOp( CompositeTargetOperation finalState, CompositeRenderSystemOperation op ) { // Store operation for current QueueGroup ID finalState.RenderSystemOperations.Add( new QueueIDAndOperation( finalState.CurrentQueueGroupId, op ) ); // Save a pointer, so that it will be freed on recompile this.chain.RenderSystemOperations.Add( op ); }
///<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; } } }
///<summary> /// Recursively collect target states (except for final Pass). ///</summary> ///<param name="compiledState">This vector will contain a list of TargetOperation objects</param> public void CompileTargetOperations( List<CompositeTargetOperation> compiledState ) { // Collect targets of previous state if ( this.previousInstance != null ) { this.previousInstance.CompileTargetOperations( compiledState ); } // Texture targets foreach ( var target in this.technique.TargetPasses ) { var ts = new CompositeTargetOperation( GetTextureInstance( target.OutputName ).GetBuffer().GetRenderTarget() ); // Set "only initial" flag, visibilityMask and lodBias according to CompositionTargetPass. ts.OnlyInitial = target.OnlyInitial; ts.VisibilityMask = target.VisibilityMask; ts.LodBias = target.LodBias; ts.ShadowsEnabled = target.ShadowsEnabled; // Check for input mode previous if ( target.InputMode == CompositorInputMode.Previous && this.previousInstance != null ) { // Collect target state for previous compositor // The TargetOperation for the final target is collected seperately as it is merged // with later operations this.previousInstance.CompileOutputOperation( ts ); } // Collect passes of our own target CollectPasses( ts, target ); compiledState.Add( ts ); } }
///<summary> /// Set current operation and target */ ///</summary> public void SetOperation( CompositeTargetOperation op, SceneManager sm, RenderSystem rs ) { this.operation = op; this.sceneManager = sm; this.renderSystem = rs; this.currentOp = 0; this.lastOp = op.RenderSystemOperations.Count; }
protected void ClearCompiledState() { this.renderSystemOperations.Clear(); this.compiledState.Clear(); this.outputOperation = new CompositeTargetOperation( null ); }
///<summary> /// Restore a viewport, the camera and the scene after a rendering operation ///</summary> protected void PostTargetOperation( CompositeTargetOperation op, Viewport vp, Camera cam ) { if ( cam != null ) { var sm = cam.SceneManager; // Unregister our listener sm.QueueStarted -= this.listener.OnRenderQueueStarted; sm.QueueEnded -= this.listener.OnRenderQueueEnded; // Restore default scene and camera settings sm.VisibilityMask = this.oldVisibilityMask; sm.FindVisibleObjectsBool = this.oldFindVisibleObjects; cam.LodBias = this.oldLodBias; } vp.MaterialScheme = this.oldMaterialScheme; vp.ShowShadows = this.oldShowShadows; }
///<summary> /// Prepare a viewport, the camera and the scene for a rendering operation ///</summary> protected void PreTargetOperation( CompositeTargetOperation op, Viewport vp, Camera cam ) { if ( cam != null ) { var sm = cam.SceneManager; // Set up render target listener this.listener.SetOperation( op, sm, sm.TargetRenderSystem ); this.listener.Viewport = vp; // Register it sm.QueueStarted += this.listener.OnRenderQueueStarted; sm.QueueEnded += this.listener.OnRenderQueueEnded; // Set visiblity mask this.oldVisibilityMask = sm.VisibilityMask; sm.VisibilityMask = op.VisibilityMask; // Set whether we find visibles this.oldFindVisibleObjects = sm.FindVisibleObjectsBool; sm.FindVisibleObjectsBool = op.FindVisibleObjects; // Set LOD bias level this.oldLodBias = cam.LodBias; cam.LodBias = cam.LodBias*op.LodBias; } // Set material scheme this.oldMaterialScheme = vp.MaterialScheme; vp.MaterialScheme = op.MaterialScheme; // Set Shadows Enabled this.oldShowShadows = vp.ShowShadows; vp.ShowShadows = op.ShadowsEnabled; //vp.ClearEveryFrame = true; //vp.ShowOverlays = false; //vp.BackgroundColor = op.ClearColor; }
public CompositorChain( Viewport vp ) { this.viewport = vp; this.originalScene = null; this.instances = new List<CompositorInstance>(); this.dirty = true; this.anyCompositorsEnabled = false; this.compiledState = new List<CompositeTargetOperation>(); this.outputOperation = null; this.oldClearEveryFrameBuffers = this.viewport.ClearBuffers; this.renderSystemOperations = new List<CompositeRenderSystemOperation>(); CreateOriginalScene(); this.listener = new RQListener(); Debug.Assert( this.viewport != null ); this.viewport.Target.BeforeUpdate += BeforeRenderTargetUpdate; this.viewport.Target.AfterUpdate += AfterRenderTargetUpdate; this.viewport.Target.BeforeViewportUpdate += BeforeViewportUpdate; this.viewport.Target.AfterViewportUpdate += AfterViewportUpdate; }