| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- //-----------------------------------------------------------------------------
- // RenderToTexture.cs
- //
- // Microsoft XNA Community Game Platform
- // Copyright (C) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- using Microsoft.Xna.Framework.Graphics;
- using System;
- using System.Collections;
- using System.Text;
- using RacingGame.Graphics;
- using RacingGame.Helpers;
- using Texture = RacingGame.Graphics.Texture;
- using Model = RacingGame.Graphics.Model;
- using XnaTexture = Microsoft.Xna.Framework.Graphics.Texture2D;
- using Microsoft.Xna.Framework;
- using RacingGame.GameLogic;
- using Microsoft.Xna.Framework.Input;
- namespace RacingGame.Shaders
- {
- /// <summary>
- /// Render to texture helper class based on the Texture class.
- /// This class allows to render stuff onto textures, if thats not
- /// supported, it will just not work and report an engine log message.
- /// This class is required for most PostScreenShaders.
- /// </summary>
- public class RenderToTexture : Texture
- {
- /// <summary>
- /// Our render target we are going to render to. Much easier than in MDX
- /// where you have to use Surfaces, etc. Also supports the Xbox360 model
- /// of resolving the render target texture before we can use it, otherwise
- /// the RenderToTexture class would not work on the Xbox360.
- /// </summary>
- RenderTarget2D renderTarget = null;
- /*
- /// <summary>
- /// Z buffer surface for shadow mapping render targets that do not
- /// fit in our resolution. Usually unused!
- /// </summary>
- DepthStencilBuffer zBufferSurface = null;
- /// <summary>
- /// ZBuffer surface
- /// </summary>
- /// <returns>Surface</returns>
- public DepthStencilBuffer ZBufferSurface
- {
- get
- {
- return zBufferSurface;
- }
- }
- */
- /// <summary>
- /// Posible size types for creating a RenderToTexture object.
- /// </summary>
- public enum SizeType
- {
- /// <summary>
- /// Uses the full screen size for this texture
- /// </summary>
- FullScreen,
- /// <summary>
- /// Uses half the full screen size, e.g. 800x600 becomes 400x300
- /// </summary>
- HalfScreen,
- /// <summary>
- /// Uses a quarter of the full screen size, e.g. 800x600 becomes 200x150
- /// </summary>
- QuarterScreen,
- /// <summary>
- /// Shadow map texture, usually 1024x1024, but can also be better
- /// like 2048x2048 or 4096x4096.
- /// </summary>
- ShadowMap,
- }
- /// <summary>
- /// Size type
- /// </summary>
- private SizeType sizeType;
- /// <summary>
- /// Calc size
- /// </summary>
- private void CalcSize()
- {
- switch (sizeType)
- {
- case SizeType.FullScreen:
- texWidth = BaseGame.Width;
- texHeight = BaseGame.Height;
- break;
- case SizeType.HalfScreen:
- texWidth = BaseGame.Width / 2;
- texHeight = BaseGame.Height / 2;
- break;
- case SizeType.QuarterScreen:
- texWidth = BaseGame.Width / 4;
- texHeight = BaseGame.Height / 4;
- break;
- case SizeType.ShadowMap:
- // Use a larger texture for high detail
- if (BaseGame.HighDetail)
- {
- texWidth = 2048;
- texHeight = 2048;
- }
- else
- {
- texWidth = 1024;
- texHeight = 1024;
- }
- break;
- }
- CalcHalfPixelSize();
- }
- /// <summary>
- /// Does this texture use some high percision format? Better than 8 bit color?
- /// </summary>
- private bool usesHighPercisionFormat = false;
- /// <summary>
- /// Render target
- /// </summary>
- /// <returns>Render target 2D</returns>
- public RenderTarget2D RenderTarget
- {
- get
- {
- return renderTarget;
- }
- }
- /// <summary>
- /// Override how to get XnaTexture, we have to resolve the render target
- /// for supporting the Xbox, which requires calling Resolve first!
- /// After that you can call this property to get the current texture.
- /// </summary>
- /// <returns>XnaTexture</returns>
- public override XnaTexture XnaTexture
- {
- get
- {
- if (alreadyResolved)
- internalXnaTexture = renderTarget;
- return internalXnaTexture;
- }
- }
- /// <summary>
- /// Does this texture use some high percision format? Better than 8 bit color?
- /// </summary>
- public bool UsesHighPercisionFormat
- {
- get
- {
- return usesHighPercisionFormat;
- }
- }
- /// <summary>
- /// Id for each created RenderToTexture for the generated filename.
- /// </summary>
- private static int RenderToTextureGlobalInstanceId = 0;
- /// <summary>
- /// Creates an offscreen texture with the specified size which
- /// can be used for render to texture.
- /// </summary>
- public RenderToTexture(SizeType setSizeType)
- {
- sizeType = setSizeType;
- CalcSize();
- texFilename = "RenderToTexture instance " +
- RenderToTextureGlobalInstanceId++;
- Create();
- BaseGame.AddRemRenderToTexture(this);
- }
- /// <summary>
- /// Handle the DeviceReset event, we have to re-create all our render targets.
- /// </summary>
- public void HandleDeviceReset()
- {
- // Respond to resolution changes
- CalcSize();
- // Clear resolved texture
- alreadyResolved = false;
- internalXnaTexture = null;
- // Re-create
- Create();
- }
- /// <summary>
- /// Create
- /// </summary>
- private void Create()
- {
- SurfaceFormat outSF;
- DepthFormat outDF;
- int outMSC;
- int MultisampleCount = 2;
- if (BaseGame.Device.PresentationParameters.BackBufferHeight == 720)
- {
- MultisampleCount = 4;
- }
- // UWP COMMENT OUT
- //if (sizeType == SizeType.ShadowMap ||
- // BaseGame.CurrentPlatform == PlatformID.Win32NT)
- //{
- // MultisampleCount = 0;
- //}
- // Rgba64 is a HiDef-only format and is not available on Android or iOS.
- // Android also does not reliably support MSAA on render targets.
- outSF = OperatingSystem.IsAndroid() || OperatingSystem.IsIOS() ? SurfaceFormat.Color : SurfaceFormat.Rgba64;
- outDF = BaseGame.BackBufferDepthFormat;
- outMSC = OperatingSystem.IsAndroid() || OperatingSystem.IsIOS() ? 0 : MultisampleCount;
- if (sizeType == SizeType.ShadowMap)
- outMSC = 0;
- // Create render target of specified size.
- renderTarget = new RenderTarget2D (
- BaseGame.Device,
- texWidth, texHeight, false,
- outSF, outDF, outMSC, RenderTargetUsage.DiscardContents);
- if (outSF != SurfaceFormat.Color)
- usesHighPercisionFormat = true;
- loaded = true;
- }
- /// <summary>
- /// Clear render target (call SetRenderTarget first)
- /// </summary>
- public void Clear(Color clearColor)
- {
- if (loaded == false ||
- renderTarget == null)
- return;
- BaseGame.Device.Clear(
- ClearOptions.Target | ClearOptions.DepthBuffer,
- clearColor, 1.0f, 0);
- }
- /// <summary>
- /// Set render target to this texture to render stuff on it.
- /// </summary>
- public bool SetRenderTarget()
- {
- if (loaded == false ||
- renderTarget == null)
- return false;
- BaseGame.SetRenderTarget(renderTarget, false);
- return true;
- }
- /// <summary>
- /// Make sure we don't call XnaTexture before resolving for the first time!
- /// </summary>
- bool alreadyResolved = false;
- /// <summary>
- /// Resolve render target. For windows developers this method may seem
- /// strange, why not just use the rendertarget's texture? Well, this is
- /// just for the Xbox360 support. The Xbox requires that you call Resolve
- /// first before using the rendertarget texture. The reason for that is
- /// copying the data over from the EPRAM to the video memory, for more
- /// details read the XNA docs.
- /// Note: This method will only work if the render target was set before
- /// with SetRenderTarget, else an exception will be thrown to ensure
- /// correct calling order.
- /// </summary>
- public void Resolve()
- {
- // Make sure this render target is currently set!
- if (BaseGame.CurrentRenderTarget != renderTarget)
- throw new InvalidOperationException(
- "You can't call Resolve without first setting the render target!");
- alreadyResolved = true;
- // fix
- //BaseGame.Device.ResolveRenderTarget(0);
- BaseGame.Device.SetRenderTarget(null);
- }
- }
- }
|