/// <summary> /// Executes a SAS script block /// </summary> /// <param name="script">A list of script commands</param> /// <param name="render">The render delegate (is called once for every shader pass); <c>null</c> for global script</param> /// <param name="sceneSize">The size of the scene on the screen - leave empty for fullscreen</param> /// <param name="sceneMap">A texture containing the rendered scene for <see cref="PostShader"/>), <c>null</c> if the shader doesn't need it</param> /// <param name="passScipt">Is this a pass script?</param> protected void ExecuteScript(IEnumerable <SasScriptCommand> script, Action render, Size sceneSize, RenderTarget sceneMap, bool passScipt) { if (script == null) { throw new ArgumentNullException(nameof(script)); } #region State variables //Color clearColor = Color.Black; //float clearDepth = 1.0f; //int clearStencil = 0; #endregion foreach (SasScriptCommand commandObject in script) { commandObject.Update(); switch (commandObject.Command) { #region Clear //case SasScriptCommand.CommandType.Clear: // using (new ProfilerEvent("SAS script: clear")) // { // SasScriptClear clear = (SasScriptClear)commandObject; // switch (clear.ClearOption) // { // case SasScriptClear.ClearType.Color: // engine.Device.Clear(ClearFlags.Target, clearColor, clearDepth, clearStencil); // break; // case SasScriptClear.ClearType.Depth: // engine.Device.Clear(ClearFlags.ZBuffer, clearColor, clearDepth, clearStencil); // break; // case SasScriptClear.ClearType.Stencil: // engine.Device.Clear(ClearFlags.Stencil, clearColor, clearDepth, clearStencil); // break; // default: // break; // } // } // break; //case SasScriptCommand.CommandType.ClearSetColor: // SasScriptClearSetColor clearSetColor = (SasScriptClearSetColor)commandObject; // clearColor = ColorHelper.Vector4ToColor(clearSetColor.Color); // break; //case SasScriptCommand.CommandType.ClearSetDepth: // SasScriptClearSetDepth clearSetDepth = (SasScriptClearSetDepth)commandObject; // clearDepth = clearSetDepth.Depth; // break; //case SasScriptCommand.CommandType.ClearSetStencil: // SasScriptClearSetStencil clearSetStencil = (SasScriptClearSetStencil)commandObject; // clearStencil = clearSetStencil.Stencil; // break; #endregion #region Render color target case SasScriptCommand.CommandType.RenderColorTarget: var renderColorTarget = (SasScriptRenderColorTarget)commandObject; if (renderColorTarget.TextureHandle == null) { Profiler.AddEvent("SAS script: restore original output target"); _activeRenderTarget = null; } else { if (passScipt) { using (new ProfilerEvent("SAS script: link new render target as output target")) { _activeRenderTarget = null; // Try to reuse an existing RenderTarget _availableRenderTargets.RemoveFirst(renderTarget => { if (renderTarget.Size == sceneSize) { // Found suitable RenderTarget _activeRenderTarget = renderTarget; _usedRenderTargets.Add(renderTarget); return(true); // Stop looking, remove from the pool } return(false); // Continue looking, keep in the pool }); // Create new RenderTargets if necessary if (_activeRenderTarget == null) { _activeRenderTarget = new RenderTarget(Engine, sceneSize); _usedRenderTargets.Add(_activeRenderTarget); } Effect.SetTexture(renderColorTarget.TextureHandle, _activeRenderTarget); } } else { using (new ProfilerEvent("SAS script: link existing render target to input variable")) Effect.SetTexture(renderColorTarget.TextureHandle, sceneMap); } } break; #endregion #region Render depth stencil target //case SasScriptCommand.CommandType.RenderDepthStencilTarget: // SasScriptRenderDepthStencilTarget renderDepthTarget = // (SasScriptRenderDepthStencilTarget)commandObject; // SasTexture tex = mat.GetTexture(renderDepthTarget.TextureHandle); // if (tex != null) // renderer.SetDepthTarget(tex.DepthSurface); // else // renderer.SetDepthTarget(null); // break; #endregion #region Technique case SasScriptCommand.CommandType.Technique: using (new ProfilerEvent("SAS script: set technique")) { var tech = (SasScriptTechnique)commandObject; if (tech.Handle != null) { Effect.Technique = tech.Handle; } } break; #endregion #region Pass case SasScriptCommand.CommandType.Pass: if (render != null && !passScipt) { var pass = (SasScriptPass)commandObject; using (new ProfilerEvent(() => "SAS script: pass " + pass.PassNum)) { ExecuteScript(Passes[Effect.GetPass(Effect.Technique, pass.PassNum)], render, sceneSize, sceneMap, true); Effect.BeginPass(pass.PassNum); if (_activeRenderTarget == null) { render(); } else { _activeRenderTarget.RenderTo(Engine.DrawQuadShader); } Effect.EndPass(); } } break; #endregion } } }