Esempio n. 1
0
        /// <summary>
        /// Function called to render the effect.
        /// </summary>
        /// <param name="renderMethod">The method used to render the scene that will be used in the effect.</param>
        /// <param name="output">The render target that will receive the results of rendering the effect.</param>
        /// <param name="blendStateOverride">[Optional] An override for the current blending state.</param>
        /// <param name="depthStencilStateOverride">[Optional] An override for the current depth/stencil state.</param>
        /// <param name="rasterStateOverride">[Optional] An override for the current raster state.</param>
        /// <param name="camera">[Optional] The camera to use when rendering.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="renderMethod"/>, or the <paramref name="output"/> parameter is <b>null</b>.</exception>
        /// <remarks>
        /// <para>
        /// The <paramref name="renderMethod"/> is a callback to a method with 3 parameters:
        /// <list type="number">
        ///     <item>
        ///         <description>The current pass index.</description>
        ///     </item>
        ///     <item>
        ///         <description>The total number of passes.</description>
        ///     </item>
        ///     <item>
        ///         <description>The size of the current render target.</description>
        ///     </item>
        /// </list>
        /// Users should pass a method that will render the items they want to use with this effect.
        /// </para>
        /// <para>
        /// <para>
        /// If the <paramref name="blendStateOverride"/>, parameter is omitted, then the <see cref="GorgonBlendState.Default"/> is used. When provided, this will override the current blending state.
        /// </para>
        /// <para>
        /// If the <paramref name="depthStencilStateOverride"/> parameter is omitted, then the <see cref="GorgonDepthStencilState.Default"/> is used. When provided, this will override the current
        /// depth/stencil state.
        /// </para>
        /// <para>
        /// If the <paramref name="rasterStateOverride"/> parameter is omitted, then the <see cref="GorgonRasterState.Default"/> is used. When provided, this will override the current raster state.
        /// </para>
        /// <para>
        /// The <paramref name="camera"/> parameter is used to render the texture using a different view, and optionally, a different coordinate set.
        /// </para>
        /// <para>
        /// <note type="important">
        /// <para>
        /// For performance reasons, any exceptions thrown by this method will only be thrown when Gorgon is compiled as DEBUG.
        /// </para>
        /// </note>
        /// </para>
        /// </para>
        /// </remarks>
        public void Render(Action <int, int, DX.Size2> renderMethod,
                           GorgonRenderTargetView output,
                           GorgonBlendState blendStateOverride = null,
                           GorgonDepthStencilState depthStencilStateOverride = null,
                           GorgonRasterState rasterStateOverride             = null,
                           IGorgon2DCamera camera = null)
        {
            renderMethod.ValidateObject(nameof(renderMethod));
            output.ValidateObject(nameof(output));

            bool stateChanged = SetupStates(blendStateOverride, depthStencilStateOverride, rasterStateOverride, output, camera);

            for (int i = 0; i < PassCount; ++i)
            {
                // Batch state should be cached on the implementation side, otherwise the GC could be impacted by a lot of dead objects per frame.
                Gorgon2DBatchState batchState = OnGetBatchState(i, stateChanged);

                switch (OnBeforeRenderPass(i, output, camera))
                {
                case PassContinuationState.Continue:
                    Renderer.Begin(batchState, camera);
                    OnRenderPass(i, renderMethod, output);
                    Renderer.End();

                    OnAfterRenderPass(i, output);
                    break;

                case PassContinuationState.Skip:
                    continue;

                default:
                    OnAfterRender(output);
                    return;
                }
            }

            OnAfterRender(output);
        }
Esempio n. 2
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);
        }