///<summary> /// Prepare a viewport, the camera and the scene for a rendering operation ///</summary> protected void PreTargetOperation(CompositorTargetOperation op, Viewport vp, Camera cam) { SceneManager sm = cam.SceneManager; /// Set up render target listener listener.SetOperation(op, sm, sm.TargetRenderSystem); listener.NotifyViewport(vp); /// Register it sm.QueueStarted += listener.OnRenderQueueStarted; sm.QueueEnded += listener.OnRenderQueueEnded; /// Set visiblity mask oldVisibilityMask = sm.VisibilityMask; sm.VisibilityMask = op.VisibilityMask; /// Set whether we find visibles oldFindVisibleObjects = sm.FindVisibleObjectsBool; sm.FindVisibleObjectsBool = op.FindVisibleObjects; /// Set LOD bias level oldLodBias = cam.LodBias; cam.LodBias = cam.LodBias * op.LodBias; /// Set material scheme oldMaterialScheme = vp.MaterialScheme; vp.MaterialScheme = op.MaterialScheme; /// XXX TODO //vp->setClearEveryFrame( true ); //vp->setOverlaysEnabled( false ); //vp->setBackgroundColour( op.clearColour ); }
///<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 <CompositorTargetOperation> compiledState) { /// Collect targets of previous state if (previousInstance != null) { previousInstance.CompileTargetOperations(compiledState); } /// Texture targets foreach (CompositionTargetPass target in technique.TargetPasses) { CompositorTargetOperation ts = new CompositorTargetOperation(GetTargetForTex(target.OutputName)); /// Set "only initial" flag, visibilityMask and lodBias according to CompositionTargetPass. ts.OnlyInitial = target.OnlyInitial; ts.VisibilityMask = target.VisibilityMask; ts.LodBias = target.LodBias; /// Check for input mode previous if (target.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 previousInstance.CompileOutputOperation(ts); } /// Collect passes of our own target CollectPasses(ts, target); compiledState.Add(ts); } }
///<summary> /// Queue a render system operation. ///</summary> ///<returns>destination pass</return> protected void QueueRenderSystemOp(CompositorTargetOperation finalState, CompositorRenderSystemOperation 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 chain.RenderSystemOperations.Add(op); }
///<summary> /// Set current operation and target */ ///</summary> public void SetOperation(CompositorTargetOperation op, SceneManager sm, RenderSystem rs) { operation = op; sceneManager = sm; renderSystem = rs; currentOp = 0; lastOp = op.RenderSystemOperations.Count; }
public CompositorChain(Viewport vp) { this.viewport = vp; originalScene = null; instances = new List <CompositorInstance>(); dirty = true; anyCompositorsEnabled = false; compiledState = new List <CompositorTargetOperation>(); outputOperation = null; oldClearEveryFrameBuffers = viewport.ClearBuffers; renderSystemOperations = new List <CompositorRenderSystemOperation>(); listener = new RQListener(); Debug.Assert(viewport != null); }
///<summary> /// Restore a viewport, the camera and the scene after a rendering operation ///</summary> protected void PostTargetOperation(CompositorTargetOperation op, Viewport vp, Camera cam) { SceneManager sm = cam.SceneManager; /// Unregister our listener sm.QueueStarted -= listener.OnRenderQueueStarted; sm.QueueEnded -= listener.OnRenderQueueEnded; /// Flush remaing operations listener.FlushUpTo(RenderQueueGroupID.Count); /// Restore default scene and camera settings sm.VisibilityMask = oldVisibilityMask; sm.FindVisibleObjectsBool = oldFindVisibleObjects; cam.LodBias = oldLodBias; vp.MaterialScheme = oldMaterialScheme; }
///<summary> /// Compile the final (output) operation. This is done seperately because this /// is combined with the input in chained filters. ///</summary> public void CompileOutputOperation(CompositorTargetOperation finalState) { /// Final target CompositionTargetPass tpass = 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 previousInstance.CompileOutputOperation(finalState); } /// Collect passes CollectPasses(finalState, tpass); }
///<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<CompositorTargetOperation> compiledState) { /// Collect targets of previous state if(previousInstance != null) previousInstance.CompileTargetOperations(compiledState); /// Texture targets foreach (CompositionTargetPass target in technique.TargetPasses) { CompositorTargetOperation ts = new CompositorTargetOperation(GetTargetForTex(target.OutputName)); /// Set "only initial" flag, visibilityMask and lodBias according to CompositionTargetPass. ts.OnlyInitial = target.OnlyInitial; ts.VisibilityMask = target.VisibilityMask; ts.LodBias = target.LodBias; /// Check for input mode previous if(target.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 previousInstance.CompileOutputOperation(ts); } /// Collect passes of our own target CollectPasses(ts, target); compiledState.Add(ts); } }
///<summary> /// Compile the final (output) operation. This is done seperately because this /// is combined with the input in chained filters. ///</summary> public void CompileOutputOperation(CompositorTargetOperation finalState) { /// Final target CompositionTargetPass tpass = 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 previousInstance.CompileOutputOperation(finalState); } /// Collect passes CollectPasses(finalState, tpass); }
protected void ClearCompiledState() { renderSystemOperations.Clear(); compiledState.Clear(); outputOperation = new CompositorTargetOperation(null); }
///<summary> /// Collect rendering passes. Here, passes are converted into render target operations /// and queued with queueRenderSystemOp. ///</summary> protected void CollectPasses(CompositorTargetOperation finalState, CompositionTargetPass target) { /// Here, passes are converted into render target operations Pass targetpass; Technique srctech; Material srcmat; foreach (CompositionPass 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 ((int)pass.FirstRenderQueue < (int)finalState.CurrentQueueGroupID) { /// Mismatch -- warn user /// XXX We could support repeating the last queue, with some effort LogManager.Instance.Write("Warning in compilation of Compositor " + compositor.Name + ": Attempt to render queue " + pass.FirstRenderQueue + " before " + finalState.CurrentQueueGroupID); } /// Add render queues for (RenderQueueGroupID x = pass.FirstRenderQueue; x <= pass.LastRenderQueue; ++x) { Debug.Assert(x >= 0); finalState.RenderQueues[(int)x] = true; } finalState.CurrentQueueGroupID = (RenderQueueGroupID)((int)pass.LastRenderQueue + 1); finalState.FindVisibleObjects = true; finalState.MaterialScheme = target.MaterialScheme; break; case CompositorPassType.RenderQuad: srcmat = pass.Material; if (srcmat == null) { /// No material -- warn user LogManager.Instance.Write("Warning in compilation of Compositor " + compositor.Name + ": No material defined for composition pass"); break; } srcmat.Load(); if (srcmat.SupportedTechniques.Count == 0) { /// No supported techniques -- warn user LogManager.Instance.Write("Warning in compilation of Compositor " + compositor.Name + ": material " + srcmat.Name + " has no supported techniques"); break; } srctech = srcmat.GetBestTechnique(0); /// Create local material Material localMat = CreateLocalMaterial(); /// Copy and adapt passes from source material for (int i = 0; i < srctech.NumPasses; i++) { Pass srcpass = srctech.GetPass(i); /// Create new target pass targetpass = localMat.GetTechnique(0).CreatePass(); srcpass.CopyTo(targetpass); /// Set up inputs int numInputs = pass.GetNumInputs(); for (int x = 0; x < numInputs; x++) { string inp = pass.Inputs[x]; if (inp != string.Empty) { if (x < targetpass.NumTextureUnitStages) { targetpass.GetTextureUnitState(x).SetTextureName(GetSourceForTex(inp)); } else { /// Texture unit not there LogManager.Instance.Write("Warning in compilation of Compositor " + compositor.Name + ": material " + srcmat.Name + " texture unit " + x + " out of bounds"); } } } } QueueRenderSystemOp(finalState, new RSQuadOperation(this, pass.Identifier, localMat)); break; } } }
///<summary> /// Collect rendering passes. Here, passes are converted into render target operations /// and queued with queueRenderSystemOp. ///</summary> protected void CollectPasses(CompositorTargetOperation finalState, CompositionTargetPass target) { /// Here, passes are converted into render target operations Pass targetpass; Technique srctech; Material srcmat; foreach (CompositionPass 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((int)pass.FirstRenderQueue < (int)finalState.CurrentQueueGroupID) { /// Mismatch -- warn user /// XXX We could support repeating the last queue, with some effort LogManager.Instance.Write("Warning in compilation of Compositor " + compositor.Name + ": Attempt to render queue " + pass.FirstRenderQueue + " before "+ finalState.CurrentQueueGroupID); } /// Add render queues for(RenderQueueGroupID x=pass.FirstRenderQueue; x<=pass.LastRenderQueue; ++x) { Debug.Assert(x>=0); finalState.RenderQueues[(int)x] = true; } finalState.CurrentQueueGroupID = (RenderQueueGroupID)((int)pass.LastRenderQueue + 1); finalState.FindVisibleObjects = true; finalState.MaterialScheme = target.MaterialScheme; break; case CompositorPassType.RenderQuad: srcmat = pass.Material; if(srcmat == null) { /// No material -- warn user LogManager.Instance.Write("Warning in compilation of Compositor " + compositor.Name + ": No material defined for composition pass"); break; } srcmat.Load(); if(srcmat.SupportedTechniques.Count == 0) { /// No supported techniques -- warn user LogManager.Instance.Write("Warning in compilation of Compositor " + compositor.Name + ": material " + srcmat.Name + " has no supported techniques"); break; } srctech = srcmat.GetBestTechnique(0); /// Create local material Material localMat = CreateLocalMaterial(); /// Copy and adapt passes from source material for (int i=0; i<srctech.NumPasses; i++) { Pass srcpass = srctech.GetPass(i); /// Create new target pass targetpass = localMat.GetTechnique(0).CreatePass(); srcpass.CopyTo(targetpass); /// Set up inputs int numInputs = pass.GetNumInputs(); for (int x = 0; x < numInputs; x++) { string inp = pass.Inputs[x]; if (inp != string.Empty) { if (x < targetpass.NumTextureUnitStages) targetpass.GetTextureUnitState(x).SetTextureName(GetSourceForTex(inp)); else { /// Texture unit not there LogManager.Instance.Write("Warning in compilation of Compositor " + compositor.Name + ": material " + srcmat.Name + " texture unit " + x + " out of bounds"); } } } } QueueRenderSystemOp(finalState, new RSQuadOperation(this, pass.Identifier, localMat)); break; } } }
public CompositorChain(Viewport vp) { this.viewport = vp; originalScene = null; instances = new List<CompositorInstance>(); dirty = true; anyCompositorsEnabled = false; compiledState = new List<CompositorTargetOperation>(); outputOperation = null; oldClearEveryFrameBuffers = viewport.ClearBuffers; renderSystemOperations = new List<CompositorRenderSystemOperation>(); listener = new RQListener(); Debug.Assert(viewport != null); }