Esempio n. 1
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();
        }
Esempio n. 2
0
 /// <summary>
 /// Function to retrieve a draw indexed call from the pool and,  initialize it.
 /// </summary>
 /// <param name="renderable">The renderable to evaluate.</param>
 /// <param name="batchState">The current global state for the batch.</param>
 /// <param name="indexBuffer">The index buffer to use when creating the draw call.</param>
 /// <param name="vertexBuffer">The vertex buffer binding to use when creating the draw call.</param>
 /// <param name="layout">The vertex input layout.</param>
 /// <returns>The draw call.</returns>
 public GorgonDrawIndexCall GetDrawIndexCall(BatchRenderable renderable, Gorgon2DBatchState batchState, GorgonIndexBuffer indexBuffer, GorgonVertexBufferBinding vertexBuffer, GorgonInputLayout layout)
 {
     SetCommonStates(_drawIndexBuilder, renderable, batchState, null);
     return(_drawIndexBuilder.VertexBuffer(layout, vertexBuffer)
            .IndexBuffer(indexBuffer)
            .Build(_drawIndexAllocator));
 }
        /// <summary>
        /// Function called to build a new (or return an existing) 2D batch state.
        /// </summary>
        /// <param name="passIndex">The index of the current rendering pass.</param>
        /// <param name="statesChanged"><b>true</b> if the blend, raster, or depth/stencil state was changed. <b>false</b> if not.</param>
        /// <returns>The 2D batch state.</returns>
        protected override Gorgon2DBatchState OnGetBatchState(int passIndex, bool statesChanged)
        {
            if (statesChanged)
            {
                _batchState = BatchStateBuilder.Build();
            }

            return(_batchState);
        }
Esempio n. 4
0
        /// <summary>
        /// Function to build up the render targets.
        /// </summary>
        /// <param name="width">The width of the render targets.</param>
        /// <param name="height">The height of the render targets.</param>
        /// <param name="format">The format of the buffer.</param>
        private void BuildRenderTargets(int width, int height, BufferFormat format)
        {
            // For the lighting effect, we use a deferred rendering technique where we have 3 render targets for diffuse, specularity, and normal mapping.
            // These targets are sub resources of the same texture resource (array indices).

            // Diffuse.
            _rtvInfo.Width      = width;
            _rtvInfo.Height     = height;
            _rtvInfo.Format     = format;
            _rtvInfo.ArrayCount = 2;

            _gbufferTargets[0] = Graphics.TemporaryTargets.Rent(_rtvInfo, "Gorgon 2D GBuffer - Diffuse/Specular", false);
            _gbufferTargets[0].Clear(GorgonColor.Black);
            // Specular.
            _gbufferTargets[1] = _gbufferTargets[0].Texture.GetRenderTargetView(arrayIndex: 1, arrayCount: 1);

            _rtvInfo.Format     = BufferFormat.R8G8B8A8_UNorm;
            _rtvInfo.ArrayCount = 1;

            // Normals.
            // We'll clear it before the pass, the default color is insufficient.
            _gbufferTargets[2] = Graphics.TemporaryTargets.Rent(_rtvInfo, "Gorgon 2D Buffer - Normals", false);
            GorgonTexture2DView normalSrv = _gbufferTargets[2].GetShaderResourceView();

            if ((_pixelLitShaderState.ShaderResources[1] != normalSrv) ||
                (_diffuseFilter != DiffuseFiltering) ||
                (_normalFilter != NormalFiltering) ||
                (_specularFilter != SpecularFiltering))
            {
                _diffuseFilter  = DiffuseFiltering ?? GorgonSamplerState.Default;
                _normalFilter   = NormalFiltering ?? GorgonSamplerState.PointFiltering;
                _specularFilter = SpecularFiltering ?? GorgonSamplerState.Default;

                _pixelDeferShaderState = PixelShaderBuilder.ResetTo(_pixelDeferShaderState)
                                         .SamplerState(_diffuseFilter, 0)
                                         .SamplerState(_normalFilter, 1)
                                         .SamplerState(_specularFilter, 2)
                                         .Build();

                _pixelLitShaderState = PixelShaderBuilder
                                       .ResetTo(_pixelLitShaderState)
                                       .ShaderResource(normalSrv, 1)
                                       .SamplerState(_diffuseFilter, 0)
                                       .SamplerState(_normalFilter, 1)
                                       .SamplerState(_specularFilter, 2)
                                       .Build();

                _lightingState = BatchStateBuilder
                                 .ResetTo(_lightingState)
                                 .PixelShaderState(_pixelLitShaderState)
                                 .Build();
            }


            _gbufferTexture = _gbufferTargets[0].Texture.GetShaderResourceView();
        }
Esempio n. 5
0
 /// <summary>
 /// Function to clear the effects from the compositor.
 /// </summary>
 /// <returns>The fluent interface for the effects processor.</returns>
 public Gorgon2DCompositor Clear()
 {
     _batchState = Gorgon2DBatchState.NoBlend;
     _batchStateBuilder.Clear();
     _batchStateBuilder.BlendState(GorgonBlendState.NoBlending);
     _effectList.Clear();
     _effects.Clear();
     _hasBatchStateChanged = false;
     return(this);
 }
        /// <summary>
        /// Function called when the effect is being initialized.
        /// </summary>
        /// <remarks>
        /// Use this method to set up the effect upon its creation.  For example, this method could be used to create the required shaders for the effect.
        /// </remarks>
        protected override void OnInitialize()
        {
            // Compile our blur shader.
            _grayScaleShader = CompileShader <GorgonPixelShader>(Resources.BasicSprite, "GorgonPixelShaderGrayScale");
            _grayScaleState  = PixelShaderBuilder
                               .Shader(_grayScaleShader)
                               .Build();

            _batchState = BatchStateBuilder
                          .PixelShaderState(_grayScaleState)
                          .Build();
        }
Esempio n. 7
0
        /// <summary>
        /// Function called to initialize the effect.
        /// </summary>
        /// <remarks>Applications must implement this method to ensure that any required resources are created, and configured for the effect.</remarks>
        protected override void OnInitialize()
        {
            var globalData = new GlobalEffectData
            {
                CameraPosition = DX.Vector3.Zero,
                FlipYNormal    = 0
            };

            _globalData = GorgonConstantBufferView.CreateConstantBuffer(Graphics, ref globalData, "Global deferred light effect data.", ResourceUsage.Default);

            _lightData = GorgonConstantBufferView.CreateConstantBuffer(Graphics,
                                                                       new GorgonConstantBufferInfo("Deferred Lighting Light Data Buffer")
            {
                SizeInBytes = Unsafe.SizeOf <PointLightData>(),
                Usage       = ResourceUsage.Dynamic
            });

            Macros.Add(new GorgonShaderMacro("DEFERRED_LIGHTING"));
            _vertexDeferShader      = CompileShader <GorgonVertexShader>(Resources.Lighting, "GorgonVertexLightingShader");
            _vertexDeferShaderState = VertexShaderBuilder.Shader(_vertexDeferShader)
                                      .Build();

            _pixelDeferShader      = CompileShader <GorgonPixelShader>(Resources.Lighting, "GorgonPixelShaderDeferred");
            _pixelDeferShaderState = PixelShaderBuilder.Shader(_pixelDeferShader)
                                     .SamplerState(_diffuseFilter, 0)
                                     .SamplerState(_normalFilter, 1)
                                     .SamplerState(_specularFilter, 2)
                                     .Build();

            Macros.Clear();
            Macros.Add(new GorgonShaderMacro("LIGHTS"));
            _vertexLitShader      = CompileShader <GorgonVertexShader>(Resources.Lighting, "GorgonVertexLitShader");
            _vertexLitShaderState = VertexShaderBuilder.Shader(_vertexLitShader)
                                    .Build();

            _pixelLitShader      = CompileShader <GorgonPixelShader>(Resources.Lighting, "GorgonPixelShaderLighting");
            _pixelLitShaderState = PixelShaderBuilder.Shader(_pixelLitShader)
                                   .ConstantBuffer(_lightData, 1)
                                   .ConstantBuffer(_globalData, 2)
                                   .SamplerState(_diffuseFilter, 0)
                                   .SamplerState(_normalFilter, 1)
                                   .SamplerState(_specularFilter, 2)
                                   .Build();

            // Rebuild our states for the new pixel shaders.
            _lightingState = BatchStateBuilder.PixelShaderState(_pixelLitShaderState)
                             .VertexShaderState(_vertexLitShaderState)
                             .BlendState(GorgonBlendState.Additive)
                             .Build();
        }
Esempio n. 8
0
        /// <summary>
        /// Function called to build a new (or return an existing) 2D batch state.
        /// </summary>
        /// <param name="passIndex">The index of the current rendering pass.</param>
        /// <param name="statesChanged"><b>true</b> if the blend, raster, or depth/stencil state was changed. <b>false</b> if not.</param>
        /// <returns>The 2D batch state.</returns>
        protected override Gorgon2DBatchState OnGetBatchState(int passIndex, bool statesChanged)
        {
            switch (passIndex)
            {
            case 0:
                if ((statesChanged) || (_deferredState == null))
                {
                    _deferredState = BatchStateBuilder
                                     .PixelShaderState(_pixelDeferShaderState)
                                     .VertexShaderState(_vertexDeferShaderState)
                                     .BlendState(GorgonBlendState.NoBlending)
                                     .Build();
                }

                return(_deferredState);

            default:
                return(_lightingState);
            }
        }
Esempio n. 9
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);
        }
        /// <summary>Function called to build a new (or return an existing) 2D batch state.</summary>
        /// <param name="passIndex">The index of the current rendering pass.</param>
        /// <param name="statesChanged">
        ///   <b>true</b> if the blend, raster, or depth/stencil state was changed. <b>false</b> if not.</param>
        /// <returns>The 2D batch state.</returns>
        protected override Gorgon2DBatchState OnGetBatchState(int passIndex, bool statesChanged)
        {
            if ((_useSimple != FullScreen) ||
                ((LookupTexture == null) && (_currentLut != _defaultLut)) ||
                ((LookupTexture != null) && (LookupTexture != _currentLut)))
            {
                GorgonPixelShader current = FullScreen ? _simpleChromeAbShader : _chromeAbShader;
                _currentLut = LookupTexture ?? _defaultLut;

                _chromeAbBatchState = BatchStateBuilder.Clear()
                                      .BlendState(GorgonBlendState.NoBlending)
                                      .PixelShaderState(_shaderStateBuilder
                                                        .Clear()
                                                        .Shader(current)
                                                        .ShaderResource(!FullScreen ? _currentLut : null, 1)
                                                        .SamplerState(!FullScreen ? GorgonSamplerState.Default : null, 1)
                                                        .ConstantBuffer(_settings, 1))
                                      .Build();

                _useSimple = FullScreen;
            }

            return(_chromeAbBatchState);
        }
Esempio n. 11
0
        /// <summary>
        /// Function to set up common states for a draw call type.
        /// </summary>
        /// <typeparam name="TB">The type of draw call builder.</typeparam>
        /// <typeparam name="TD">The type of draw call to return.</typeparam>
        /// <param name="builder">The builder to pass in.</param>
        /// <param name="renderable">The renderable being rendered.</param>
        /// <param name="batchState">The current batch level state.</param>
        /// <param name="renderer">The renderer used to send renderable data to the GPU.</param>
        private void SetCommonStates <TB, TD>(GorgonDrawCallBuilderCommon <TB, TD> builder, BatchRenderable renderable, Gorgon2DBatchState batchState, ObjectRenderer renderer)
            where TB : GorgonDrawCallBuilderCommon <TB, TD>
            where TD : GorgonDrawCallCommon
        {
            // If we haven't specified values for our first texture and sampler, then do so now.
            batchState.PixelShaderState.RwSrvs[0]     = renderable.Texture ?? _defaultTexture;
            batchState.PixelShaderState.RwSamplers[0] = renderable.TextureSampler ?? GorgonSamplerState.Default;

            builder.ConstantBuffers(ShaderType.Vertex, batchState.VertexShaderState.RwConstantBuffers)
            .ConstantBuffers(ShaderType.Pixel, batchState.PixelShaderState.RwConstantBuffers)
            .ShaderResources(ShaderType.Vertex, batchState.VertexShaderState.RwSrvs)
            .ShaderResources(ShaderType.Pixel, batchState.PixelShaderState.RwSrvs)
            .SamplerStates(ShaderType.Vertex, batchState.VertexShaderState.RwSamplers)
            .SamplerStates(ShaderType.Pixel, batchState.PixelShaderState.RwSamplers)
            .PipelineState(_stateBuilder.PixelShader(batchState.PixelShaderState.Shader)
                           .VertexShader(batchState.VertexShaderState.Shader)
                           .DepthStencilState(batchState.DepthStencilState)
                           .RasterState(batchState.RasterState)
                           .BlendState(batchState.BlendState)
                           .PrimitiveType(renderable.PrimitiveType));

            // If we don't supply a renderer type, then don't assign a vertex buffer.
            if (renderer == null)
            {
                return;
            }

            builder.VertexBuffer(_inputLayout, renderer.VertexBuffer);
        }
Esempio n. 12
0
 /// <summary>
 /// Function to retrieve a draw indexed call from the pool and,  initialize it.
 /// </summary>
 /// <param name="renderable">The renderable to evaluate.</param>
 /// <param name="batchState">The current global state for the batch.</param>
 /// <param name="renderer">The renderer that will be </param>
 /// <returns>The draw call.</returns>
 public GorgonDrawIndexCall GetDrawIndexCall(BatchRenderable renderable, Gorgon2DBatchState batchState, ObjectRenderer renderer)
 {
     SetCommonStates(_drawIndexBuilder, renderable, batchState, renderer);
     return(_drawIndexBuilder.IndexBuffer(renderer.IndexBuffer)
            .Build(_drawIndexAllocator));
 }
Esempio n. 13
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);
        }