// Project: XnaGraphicEngine, File: PostScreenMenu.cs // Namespace: XnaGraphicEngine.Shaders, Class: PostScreenMenu // Path: C:\code\XnaGraphicEngine\Shaders, Author: Abi // Code lines: 369, Size of file: 10,70 KB // Creation date: 27.09.2006 03:46 // Last modified: 15.10.2006 19:59 // Generated with Commenter by abi.exDream.com #region Using directives using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System; using System.Collections; using System.IO; using System.Text; using XnaGraphicEngine.Game; using XnaGraphicEngine.Graphics; using XnaGraphicEngine.Helpers; using Texture = XnaGraphicEngine.Graphics.Texture; using Model = XnaGraphicEngine.Graphics.Model; #endregion namespace XnaGraphicEngine.Shaders { /// /// Post screen glow shader based on PostScreenMenu.fx /// /// Shader effect public class PostScreenDarkenBorder : ShaderEffect { #region Variables /// /// The shader effect filename for this shader. /// private const string Filename = "PostScreenDarkenBorder.fx"; /// /// Effect handles for window size and scene map. /// protected EffectParameter windowSize, sceneMap, screenBorderFadeoutMap; /// /// Links to the passTextures, easier to write code this way. /// This are just reference copies. Static to load them only once /// (used for both PostScreenMenu and PostScreenGlow). /// protected static RenderToTexture sceneMapTexture; /// /// Helper texture for the screen border (darken the borders). /// private Texture screenBorderFadeoutMapTexture = null; /// /// Is this post screen shader started? /// Else don't execute Show if it is called. /// protected static bool started = false; /// /// Started /// /// Bool public bool Started { get { return started; } // get } // Started #endregion #region Constructor /// /// Create post screen menu. Also used for the constructor of /// PostScreenGlow (same RenderToTextures used there). /// protected PostScreenDarkenBorder(string shaderFilename) : base(shaderFilename) { Load(); } // PostScreenDarkenBorder() /// /// Create post screen menu /// public PostScreenDarkenBorder() : this(Filename) { } // PostScreenDarkenBorder() #endregion #region Dispose /// /// Dispose /// public override void Dispose() { base.Dispose(); if (sceneMapTexture != null) sceneMapTexture.Dispose(); sceneMapTexture = null; } // Dispose() #endregion #region Load /// /// Load in case the device got lost. /// public override void Load() { base.Load(); // Scene map texture if (sceneMapTexture == null) sceneMapTexture = new RenderToTexture( RenderToTexture.SizeType.FullScreen); } // Load() #endregion #region Get parameters /// /// Reload /// protected override void GetParameters() { // Can't get parameters if loading failed! if (effect == null) return; windowSize = effect.Parameters["windowSize"]; sceneMap = effect.Parameters["sceneMap"]; // We need both windowSize and sceneMap. if (windowSize == null || sceneMap == null) throw new NotSupportedException("windowSize and sceneMap must be " + "valid in PostScreenShader=" + Filename); // Load screen border texture screenBorderFadeoutMap = effect.Parameters["screenBorderFadeoutMap"]; screenBorderFadeoutMapTexture = new Texture("ScreenBorderFadeout.dds"); // Set texture screenBorderFadeoutMap.SetValue( screenBorderFadeoutMapTexture.XnaTexture); } // GetParameters() #endregion #region Start /// /// Start this post screen shader, will just call SetRenderTarget. /// All render calls will now be drawn on the sceneMapTexture. /// Make sure you don't reset the RenderTarget until you call Show()! /// public void Start() { // Only apply post screen shader if texture is valid and effect is valid if (sceneMapTexture == null || effect == null || started == true || // Also skip if we don't use post screen shaders at all! BaseGame.UsePostScreenShaders == false) return; BaseGame.SetRenderTarget(sceneMapTexture.RenderTarget, true); started = true; } // Start() #endregion #region Show /// /// Execute shaders and show result on screen, Start(..) must have been /// called before and the scene should be rendered to sceneMapTexture. /// public virtual void Show() { // Only apply post screen glow if texture is valid and effect is valid if (sceneMapTexture == null || Valid == false || started == false) return; started = false; // Resolve sceneMapTexture render target for Xbox360 support sceneMapTexture.Resolve(); try { // Don't use or write to the z buffer BaseGame.Device.RenderState.DepthBufferEnable = false; BaseGame.Device.RenderState.DepthBufferWriteEnable = false; // Also don't use any kind of blending. BaseGame.Device.RenderState.AlphaBlendEnable = false; //unused: BaseGame.Device.RenderState.Lighting = false; if (windowSize != null) windowSize.SetValue(new float[] { sceneMapTexture.Width, sceneMapTexture.Height }); if (sceneMap != null) sceneMap.SetValue(sceneMapTexture.XnaTexture); effect.CurrentTechnique = effect.Techniques["ScreenDarkenBorder"]; // We must have exactly 1 pass! if (effect.CurrentTechnique.Passes.Count != 1) throw new Exception("This shader should have exactly 1 pass!"); effect.Begin(); for (int pass = 0; pass < effect.CurrentTechnique.Passes.Count; pass++) { if (pass == 0) // Do a full reset back to the back buffer BaseGame.ResetRenderTarget(true); EffectPass effectPass = effect.CurrentTechnique.Passes[pass]; effectPass.Begin(); //tst for last pass? VBScreenHelper.Render10x10Grid(); VBScreenHelper.Render(); effectPass.End(); } // for (pass, <, ++) } // try catch (Exception ex) { // Make effect invalid, continue rendering without this // post screen shader. effect = null; BaseGame.ResetRenderTarget(true); #if DEBUG throw ex; #else Log.Write("Failed to render post screen shader "+Filename+": "+ ex.ToString()); #endif } // catch finally { effect.End(); // Restore z buffer state BaseGame.Device.RenderState.DepthBufferEnable = true; BaseGame.Device.RenderState.DepthBufferWriteEnable = true; } // finally } // Show() #endregion #region Unit Testing #if DEBUG /// /// Test PostScreenDarkenBorder /// //[Test] public static void TestPostScreenDarkenBorder() { PreScreenSkyCubeMapping skyCube = null; Model testModel = null; PostScreenDarkenBorder postScreenShader = null; TestGame.Start("TestPostScreenDarkenBorder", delegate { skyCube = new PreScreenSkyCubeMapping(); testModel = new Model("Asteroid4"); postScreenShader = new PostScreenDarkenBorder(); }, delegate { // Start post screen shader to render everything to our sceneMap if (Input.Keyboard[Keys.Space] == KeyState.Up && Input.GamePadBPressed == false) postScreenShader.Start(); // Draw background sky cube skyCube.RenderSky(); // And our testModel (the asteroid) testModel.Render(Matrix.CreateScale(10)); // And finally show post screen shader if (Input.Keyboard[Keys.Space] == KeyState.Up && Input.GamePadBPressed == false) postScreenShader.Show(); TextureFont.WriteText(2, 30, "Press space or B to disable post screen shader"); TextureFont.WriteText(2, 60, "Press A to show sceneMap of post screen shader"); TextureFont.WriteText(2, 90, "Speed Mode"); if (Input.Keyboard.IsKeyDown(Keys.A) || Input.GamePadAPressed) { sceneMapTexture.RenderOnScreen( new Rectangle(10, 10, 256, 256)); } // if (Input.Keyboard.IsKeyDown) //*/ }); } // TestPostScreenMenu() #endif #endregion } // class PostScreenDarkenBorder } // namespace XnaGraphicEngine.Shaders