Ejemplo n.º 1
0
        /// <summary>
        /// Function to render a pass without applying any effect.
        /// </summary>
        /// <param name="name">A name for the pass.</param>
        /// <param name="renderMethod">The method used to render the scene.</param>
        /// <returns>The fluent interface for the effects processor.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="name"/>, or the <paramref name="renderMethod"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="name"/> parameter is empty.</exception>
        /// <remarks>
        /// <para>
        /// This allows an application to render a scene without applying any kind of effect.  The <paramref name="renderMethod"/> is a method that will take the following parameters:
        /// <list type="number">
        ///     <item>
        ///         <description>The last texture that was processed by a previous effect.</description>
        ///     </item>
        ///     <item>
        ///         <description>The current pass index being rendered.</description>
        ///     </item>
        ///     <item>
        ///         <description>Total number of passes in the effect.</description>
        ///     </item>
        ///     <item>
        ///         <description>The size of the current render target.</description>
        ///     </item>
        /// </list>
        /// </para>
        /// </remarks>
        public Gorgon2DCompositor RenderPass(string name, Action <GorgonTexture2DView, int, int, DX.Size2> renderMethod)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentEmptyException(nameof(name));
            }

            if (renderMethod == null)
            {
                throw new ArgumentNullException(nameof(renderMethod));
            }

            if (_effects.TryGetValue(name, out int prevIndex))
            {
                _effectList[prevIndex] = new Gorgon2DCompositionPass(name)
                {
                    RenderMethod = renderMethod
                };
            }
            else
            {
                _effects[name] = _effectList.Count;
                _effectList.Add(new Gorgon2DCompositionPass(name)
                {
                    RenderMethod = renderMethod
                });
            }

            return(this);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Function to render a scene that does not use an effect.
        /// </summary>
        /// <param name="pass">The current pass.</param>
        /// <param name="currentTarget">The currently active render target.</param>
        /// <param name="currentTexture">The texture for the previously active render target.</param>
        private void RenderNoEffectPass(Gorgon2DCompositionPass pass, GorgonRenderTargetView currentTarget, GorgonTexture2DView currentTexture)
        {
            if (pass.RenderMethod == null)
            {
                return;
            }

            // If we changed the states, then apply them now.
            if ((_noEffectBatchState.BlendState != pass.BlendOverride) ||
                (_noEffectBatchState.RasterState != pass.RasterOverride) ||
                (_noEffectBatchState.DepthStencilState != pass.DepthStencilOverride))
            {
                _noEffectBatchState = _noEffectBatchStateBuilder.BlendState(pass.BlendOverride)
                                      .DepthStencilState(pass.DepthStencilOverride)
                                      .RasterState(pass.RasterOverride)
                                      .Build();
            }

            if (Graphics.RenderTargets[0] != currentTarget)
            {
                Graphics.SetRenderTarget(currentTarget, Graphics.DepthStencilView);
            }

            Renderer.Begin(_noEffectBatchState, pass.Camera);
            pass.RenderMethod(currentTexture, 0, 0, new DX.Size2(currentTarget.Width, currentTarget.Height));
            Renderer.End();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Function to render a scene that does use an effect.
        /// </summary>
        /// <param name="pass">The current pass.</param>
        /// <param name="currentTarget">The currently active render target.</param>
        /// <param name="currentTexture">The texture for the previously active render target.</param>
        private void RenderEffectPass(Gorgon2DCompositionPass pass, GorgonRenderTargetView currentTarget, GorgonTexture2DView currentTexture)
        {
            // The callback method for rendering the effect.
            void RenderAction(int passIndex, int passCount, DX.Size2 size)
            {
                if (pass.RenderMethod != null)
                {
                    pass.RenderMethod(currentTexture, passIndex, passCount, size);
                }
                else
                {
                    DX.RectangleF destRegion = pass.DestinationRegion ?? new DX.RectangleF(0, 0, size.Width, size.Height);
                    DX.RectangleF srcCoords  = pass.SourceCoordinates ?? new DX.RectangleF(0, 0, 1, 1);

                    Renderer.DrawFilledRectangle(destRegion,
                                                 GorgonColor.White,
                                                 currentTexture,
                                                 srcCoords,
                                                 textureSampler: DefaultActionSampler);
                }
            }

            pass.Effect.Render(RenderAction,
                               currentTarget,
                               pass.BlendOverride ?? GorgonBlendState.NoBlending,
                               pass.DepthStencilOverride,
                               pass.RasterOverride,
                               pass.Camera);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Function to move the specified pass to a new location in the list.
        /// </summary>
        /// <param name="pass">The pass to move.</param>
        /// <param name="newPassIndex">The new index for the pass.</param>
        /// <returns>The fluent interface for the effects processor.</returns>
        public Gorgon2DCompositor MovePass(Gorgon2DCompositionPass pass, int newPassIndex)
        {
            if (pass == null)
            {
                return(this);
            }

            return(!_effects.TryGetValue(pass.Name, out int passIndex) ? this : MovePass(passIndex, newPassIndex));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Function to remove the first matching pass in the effect chain.
        /// </summary>
        /// <param name="index">The index of the pass to remove.</param>
        /// <returns>The fluent interface for the effects processor.</returns>
        public Gorgon2DCompositor RemovePass(int index)
        {
            if ((index < 0) || (index >= _effectList.Count))
            {
                return(this);
            }

            Gorgon2DCompositionPass pass = _effectList[index];

            _effectList.Remove(index);
            _effects.Remove(pass.Name);
            return(this);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Function to remove the first matching pass in the effect chain.
        /// </summary>
        /// <param name="pass">The pass to remove.</param>
        /// <returns>The fluent interface for the effects processor.</returns>
        public Gorgon2DCompositor RemovePass(Gorgon2DCompositionPass pass)
        {
            if (pass == null)
            {
                return(this);
            }

            if (!_effects.TryGetValue(pass.Name, out int index))
            {
                return(this);
            }

            _effectList.Remove(index);
            _effects.Remove(pass.Name);
            return(this);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Function to add an effect, and an optional rendering action to the compositor queue.
        /// </summary>
        /// <param name="pass">The effect pass to add.</param>
        /// <returns>The fluent interface for the effects processor.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="pass"/> parameter is <b>null</b>.</exception>
        /// <seealso cref="Gorgon2DCompositionPass"/>
        public Gorgon2DCompositor Pass(Gorgon2DCompositionPass pass)
        {
            if (pass == null)
            {
                throw new ArgumentNullException(nameof(pass));
            }

            if (_effects.TryGetValue(pass.Name, out int prevIndex))
            {
                _effectList[prevIndex] = pass;
            }
            else
            {
                _effects[pass.Name] = _effectList.Count;
                _effectList.Add(pass);
            }

            return(this);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Function to move the pass at the specified index to a new location in the list.
        /// </summary>
        /// <param name="passIndex">The index of the pass to move.</param>
        /// <param name="newPassIndex">The new index for the pass.</param>
        /// <returns>The fluent interface for the effects processor.</returns>
        public Gorgon2DCompositor MovePass(int passIndex, int newPassIndex)
        {
            passIndex    = passIndex.Max(0).Min(_effects.Count - 1);
            newPassIndex = newPassIndex.Max(0).Min(_effects.Count);

            if (newPassIndex == passIndex)
            {
                return(this);
            }

            Gorgon2DCompositionPass pass = _effectList[passIndex];

            _effectList[passIndex] = null;
            _effectList.Insert(newPassIndex, pass);
            _effectList.Remove((Gorgon2DCompositionPass)null);

            for (int i = 0; i < _effectList.Count; ++i)
            {
                pass = _effectList[i];
                _effects[pass.Name] = i;
            }

            return(this);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Function to render the scene for the compositor effects.
        /// </summary>
        /// <param name="output">The final output render target for the compositor.</param>
        /// <param name="renderMethod">The method used to render the initial scene.</param>
        /// <returns>The fluent interface for the effects processor.</returns>
        public Gorgon2DCompositor Render(GorgonRenderTargetView output,
                                         Action renderMethod)
        {
            output.ValidateObject(nameof(output));
            renderMethod.ValidateObject(nameof(renderMethod));

            // Create or update our resources
            if ((_final != output) || (NeedsResourceUpdate(output)))
            {
                FreeResources();
                CreateResources(output);
            }

            // Create the batch state that we'll use for our initial scene.
            if (_hasBatchStateChanged)
            {
                _batchState           = _batchStateBuilder.Build();
                _hasBatchStateChanged = false;
            }

            if (_hasFinalBatchStateChanged)
            {
                _finalBatchState           = _finalBatchStateBuilder.Build();
                _hasFinalBatchStateChanged = false;
            }

            RenderInitalScene(renderMethod);

            // If we have no effects, then, just output the scene to the render target as-is.
            if (_effects.Count == 0)
            {
                CopyToFinal(_originalTexture);
                return(this);
            }

            (GorgonRenderTargetView target, GorgonTexture2DView texture)current = (_pingTarget, _originalTexture);

            // Iterate through our items.
            for (int i = 0; i < _effectList.Count; ++i)
            {
                Gorgon2DCompositionPass pass = _effectList[i];

                if (!pass.Enabled)
                {
                    continue;
                }

                GorgonRenderTargetView   currentTarget  = current.target;
                GorgonTexture2DView      currentTexture = current.texture;
                GorgonTexture2DView      nextTexture    = ((currentTexture == _originalTexture) || (currentTexture == _pongTexture)) ? _pingTexture : _pongTexture;
                GorgonRenderTarget2DView nextTarget     = current.target == _pingTarget ? _pongTarget : _pingTarget;

                if (pass.ClearColor != null)
                {
                    currentTarget.Clear(pass.ClearColor.Value);
                }

                if (pass.Effect != null)
                {
                    RenderEffectPass(pass, currentTarget, currentTexture);
                }
                else
                {
                    RenderNoEffectPass(pass, currentTarget, currentTexture);
                }

                current = (nextTarget, nextTexture);
            }

            CopyToFinal(current.texture);

            return(this);
        }