Beispiel #1
0
 /// <summary>
 /// Allows to swap render target in a simple manner.
 /// Note that the returned object is disposable and on calling Dispose the original rendertarget binding is restored.
 /// Recommend way of usage: using statement (all rendering within the using block).
 /// </summary>
 /// <param name="renderContext"></param>
 /// <param name="renderTarget">The rendertarget to write to. Use null if you want to render to the actuall backbuffer.</param>
 /// <param name="usage"></param>
 /// <returns></returns>
 public static IDisposable RenderTo(this IRenderContext renderContext, RenderTarget2D renderTarget, BackBufferSwapUsage usage = BackBufferSwapUsage.WpfSupport)
 {
     return(new RenderTargetHelper(renderContext, renderTarget, usage));
 }
        /// <summary>
        /// When invoked will insert the renderTargets as the currently active one and save itself a reference back to the original one.
        /// On <see cref="Dispose"/> the rendertarget is detached and the original one is swapped back in.
        /// </summary>
        /// <param name="renderContext"></param>
        /// <param name="renderTarget">The rendertarget to be used.</param>
        /// <param name="usage"></param>
        public RenderTargetHelper(IRenderContext renderContext, RenderTarget2D renderTarget, BackBufferSwapUsage usage)
        {
            _renderContext = renderContext;

            // check if there is an existing rendertarget bound to the graphicsdevice
            // there are 4 possible options. existing rendertarget and target rendertarget can both be null or some rendertarget so we need to check which state it is for us
            // the 4 options: null & null, null & rt, rt & null, rt & rt
            _originalRenderTarget = renderContext.GraphicsDevice.RenderTargetCount > 0
                ? renderContext.GraphicsDevice.GetRenderTargets()[0]
                : (RenderTargetBinding?)null;

            // user requested backbuffer when he only provided one RT which he set to null
            var backBufferRequested = renderTarget == null;

            if (backBufferRequested)
            {
                if (_originalRenderTarget == null)
                {
                    // 1. option, rendertarget is null and user wants to draw to backbuffer -> no need for swapping
                    _resetToBackBuffer = true;
                    return;
                }
                // 3. option: user wants to draw to the back buffer, but a rendertarget already exists

                // user wants to render directly to backbuffer, however someone has already set a rendertarget
                // this is the case e.g. for the WPF interop: https://github.com/MarcStan/MonoGame.Framework.WpfInterop
                // which doesn't write to the normal backbuffer but writes to a 3D11 image host instead (which in turn can be displayed in WPF)
                // so we can't actually render to backbuffer as it won't be visible then
                // instead user selected WpfSupport, so don't set to null but keep the rendertarget that is set
                _resetToBackBuffer = usage != BackBufferSwapUsage.WpfSupport;
            }
            else
            {
                // 2. and 4. option
                // we set a rendertarget and then later reset to the original rendertarget (which is either null or an existing one)
                _resetToBackBuffer = true;
            }

            // only set the target rt if we are actually going to swap back to source
            // otherwise source = target
            if (_resetToBackBuffer)
            {
                renderContext.GraphicsDevice.SetRenderTarget(renderTarget);
            }
        }