Пример #1
0
        protected override void OnProcess(RenderContext context)
        {
            context.ThrowIfCameraMissing();
            context.ThrowIfGBuffer0Missing();

            var graphicsDevice   = GraphicsService.GraphicsDevice;
            var cameraNode       = context.CameraNode;
            var renderTargetPool = GraphicsService.RenderTargetPool;

            var source   = context.SourceTexture;
            var target   = context.RenderTarget;
            var viewport = context.Viewport;

            var sourceSize        = new Vector2F(source.Width, source.Height);
            int width             = (int)sourceSize.X;
            int height            = (int)sourceSize.Y;
            int downsampledWidth  = Math.Max(1, width / DownsampleFactor);
            int downsampledHeight = Math.Max(1, height / DownsampleFactor);

            if (TextureHelper.IsFloatingPointFormat(source.Format))
            {
                graphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
                InitializeGaussianBlur(new Vector2F(downsampledWidth, downsampledHeight), false);
            }
            else
            {
                graphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;
                InitializeGaussianBlur(new Vector2F(downsampledWidth, downsampledHeight), true);
            }

            // Get temporary render targets.
            var            downsampleFormat = new RenderTargetFormat(downsampledWidth, downsampledHeight, false, source.Format, DepthFormat.None);
            RenderTarget2D blurredScene0    = renderTargetPool.Obtain2D(downsampleFormat);
            RenderTarget2D blurredScene1    = renderTargetPool.Obtain2D(downsampleFormat);

            var            blurredDepthFormat = new RenderTargetFormat(downsampledWidth, downsampledHeight, false, context.GBuffer0.Format, DepthFormat.None);
            RenderTarget2D blurredDepth0      = renderTargetPool.Obtain2D(blurredDepthFormat);

            var            cocFormat = new RenderTargetFormat(width, height, false, SurfaceFormat.Single, DepthFormat.None);
            RenderTarget2D cocImage  = renderTargetPool.Obtain2D(cocFormat);

            var            downSampledCocFormat = new RenderTargetFormat(downsampledWidth, downsampledHeight, false, cocFormat.SurfaceFormat, DepthFormat.None);
            RenderTarget2D cocImageBlurred      = renderTargetPool.Obtain2D(downSampledCocFormat);

            // ----- Create CoC map.
            _effect.CurrentTechnique = _effect.Techniques[0];
            graphicsDevice.SetRenderTarget(cocImage);
            _screenSizeParameter.SetValue(new Vector2(cocImage.Width, cocImage.Height));
            _depthTextureParameter.SetValue(context.GBuffer0);
            _nearBlurDistanceParameter.SetValue(NearBlurDistance);
            _nearFocusDistanceParameter.SetValue(NearFocusDistance);
            _farFocusDistanceParameter.SetValue(FarFocusDistance);
            _farBlurDistanceParameter.SetValue(FarBlurDistance);
            _farParameter.SetValue(cameraNode.Camera.Projection.Far);
            _circleOfConfusionPass.Apply();
            graphicsDevice.DrawFullScreenQuad();

            // ----- Downsample cocImage to cocImageBlurred.
            context.SourceTexture = cocImage;
            context.RenderTarget  = cocImageBlurred;
            context.Viewport      = new Viewport(0, 0, cocImageBlurred.Width, cocImageBlurred.Height);
            _downsampleFilter.Process(context);

            renderTargetPool.Recycle(cocImage);

            // ----- Downsample source to blurredScene0.
            context.SourceTexture = source;
            context.RenderTarget  = blurredScene0;
            context.Viewport      = new Viewport(0, 0, blurredScene0.Width, blurredScene0.Height);
            _downsampleFilter.Process(context);

            // ----- Downsample depth texture to blurredDepth0.
            context.SourceTexture = context.GBuffer0;
            context.RenderTarget  = blurredDepth0;
            context.Viewport      = new Viewport(0, 0, blurredDepth0.Width, blurredDepth0.Height);
            _downsampleFilter.Process(context);

            // ----- Blur scene.
            // Horizontal blur
            graphicsDevice.SetRenderTarget(blurredScene1);
            _screenSizeParameter.SetValue(new Vector2(blurredScene0.Width, blurredScene0.Height));
            _blurTextureParameter.SetValue(blurredScene0);
            _downsampledDepthTextureParameter.SetValue(blurredDepth0);
            _downsampledCocTextureParameter.SetValue(cocImageBlurred);
            _offsetsParameter.SetValue(_horizontalOffsets);
            _weightsParameter.SetValue(_weights);
            _blurPass.Apply();
            graphicsDevice.DrawFullScreenQuad();

            // Vertical blur.
            graphicsDevice.SetRenderTarget(blurredScene0);
            _blurTextureParameter.SetValue(blurredScene1);
            _offsetsParameter.SetValue(_verticalOffsets);
            _blurPass.Apply();
            graphicsDevice.DrawFullScreenQuad();

            renderTargetPool.Recycle(blurredScene1);

            // ----- Blur cocImageBlurred.
            context.SourceTexture = cocImageBlurred;
            context.RenderTarget  = cocImageBlurred;
            context.Viewport      = new Viewport(0, 0, cocImageBlurred.Width, cocImageBlurred.Height);
            _cocBlur.Process(context); // We make a two pass blur, so context.SourceTexture can be equal to context.RenderTarget.

            // ----- Blur depth.
            context.SourceTexture = blurredDepth0;
            context.RenderTarget  = blurredDepth0;
            context.Viewport      = new Viewport(0, 0, blurredDepth0.Width, blurredDepth0.Height);
            _cocBlur.Process(context);

            // ----- Create final DoF image.
            _effect.CurrentTechnique = _effect.Techniques[0];
            graphicsDevice.SetRenderTarget(target);
            graphicsDevice.Viewport = viewport;
            _screenSizeParameter.SetValue(new Vector2(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height));
            _sceneTextureParameter.SetValue(source);
            _blurTextureParameter.SetValue(blurredScene0);
            _depthTextureParameter.SetValue(context.GBuffer0);
            _downsampledDepthTextureParameter.SetValue(blurredDepth0);
            _downsampledCocTextureParameter.SetValue(cocImageBlurred);
            _depthOfFieldPass.Apply();
            graphicsDevice.DrawFullScreenQuad();

            // ----- Clean-up
            _depthTextureParameter.SetValue((Texture2D)null);
            _blurTextureParameter.SetValue((Texture2D)null);
            _downsampledDepthTextureParameter.SetValue((Texture2D)null);
            _downsampledCocTextureParameter.SetValue((Texture2D)null);
            _sceneTextureParameter.SetValue((Texture2D)null);
            renderTargetPool.Recycle(blurredScene0);
            renderTargetPool.Recycle(blurredDepth0);
            renderTargetPool.Recycle(cocImageBlurred);
            context.SourceTexture = source;
            context.RenderTarget  = target;
            context.Viewport      = viewport;
        }
Пример #2
0
        protected override void OnProcess(RenderContext context)
        {
            context.ThrowIfCameraMissing();

            var graphicsDevice   = GraphicsService.GraphicsDevice;
            var renderTargetPool = GraphicsService.RenderTargetPool;
            var cameraNode       = context.CameraNode;

            var source   = context.SourceTexture;
            var target   = context.RenderTarget;
            var viewport = context.Viewport;

            if (Quality == 0)
            {
                // No ambient occlusion.
                if (!CombineWithSource)
                {
                    // CombineWithSource is not set. --> Simply clear the render target to white.
                    graphicsDevice.SetRenderTarget(target);
                    graphicsDevice.Viewport = viewport;
                    graphicsDevice.Clear(Color.White);
                }
                else
                {
                    // Copy source image to target.
                    _copyFilter.Process(context);
                }
                return;
            }

            // Try to get downsampled depth buffer from render context.
            // If we cannot find it in the render context, we downsample it manually.
            Texture2D      downsampledDepthTexture = null;
            RenderTarget2D downsampledDepthTarget  = null;

            if (DownsampleFactor == 2)
            {
                object dummy;
                if (context.Data.TryGetValue(RenderContextKeys.DepthBufferHalf, out dummy))
                {
                    downsampledDepthTexture = dummy as Texture2D;
                }
            }

            if (downsampledDepthTexture == null)
            {
                context.ThrowIfGBuffer0Missing();

                if (DownsampleFactor == 1)
                {
                    downsampledDepthTexture = context.GBuffer0;
                }
                else
                {
                    // Downsample manually.
                    // If we do not downsample the depth target, we get artifacts (strange horizontal and vertical
                    // lines). TODO: Check what causes the artifacts and try to remove the downsampling.
                    downsampledDepthTarget = renderTargetPool.Obtain2D(new RenderTargetFormat(
                                                                           context.GBuffer0.Width / DownsampleFactor,
                                                                           context.GBuffer0.Height / DownsampleFactor,
                                                                           false,
                                                                           context.GBuffer0.Format,
                                                                           DepthFormat.None));
                    context.SourceTexture = context.GBuffer0;
                    context.RenderTarget  = downsampledDepthTarget;
                    context.Viewport      = new Viewport(0, 0, downsampledDepthTarget.Width, downsampledDepthTarget.Height);
                    _downsampleFilter.Process(context);
                    downsampledDepthTexture = downsampledDepthTarget;
                }
            }

            // We use two temporary render targets.
            // We do not use a floating point format because float textures cannot use hardware filtering.

            RenderTarget2D temp0;

            if (!CombineWithSource && target != null &&
                target.Width == context.GBuffer0.Width / DownsampleFactor &&
                target.Height == context.GBuffer0.Height / DownsampleFactor &&
                Strength < 1)
            {
                // If we do not have to combine the AO result with the source image, and if the target
                // image has the half resolution, then we can use the target image directly and do not
                // need a temporary render target.
                // Also, a Strength > 1 is always applied in a separate pass because applying a Strength
                // > 1 before the blur has no effect.

                temp0 = target;
            }
            else
            {
                temp0 = renderTargetPool.Obtain2D(new RenderTargetFormat(
                                                      context.GBuffer0.Width / DownsampleFactor,
                                                      context.GBuffer0.Height / DownsampleFactor,
                                                      false,
                                                      SurfaceFormat.Color,
                                                      DepthFormat.None));
            }

            // Create SSAO.
            graphicsDevice.SetRenderTarget(temp0);
            _viewportSizeParameter.SetValue(new Vector2(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height));
            _farParameter.SetValue(cameraNode.Camera.Projection.Far);
            _radiusParameter.SetValue((Vector2)Radii);
            _maxDistancesParameter.SetValue((Vector2)MaxDistances);
            _strengthParameter.SetValue(Strength < 1 ? Strength : 1);
            _gBuffer0Parameter.SetValue(downsampledDepthTexture);
            if (Quality == 1)
            {
                _createLinesAPass.Apply();
            }
            else
            {
                _createLinesBPass.Apply();
            }

            graphicsDevice.DrawFullScreenQuad();

            if (UseEdgeAwareBlur)
            {
                RenderTarget2D temp1 = renderTargetPool.Obtain2D(new RenderTargetFormat(
                                                                     context.GBuffer0.Width / DownsampleFactor,
                                                                     context.GBuffer0.Height / DownsampleFactor,
                                                                     false,
                                                                     SurfaceFormat.Color,
                                                                     DepthFormat.None));

                for (int i = 0; i < NumberOfBlurPasses; i++)
                {
                    // Blur horizontally.
                    // Note: We use a bilateral filter which is not separable - but the results are still ok
                    // if we use separate the horizontal and vertical blur.
                    graphicsDevice.SetRenderTarget(temp1);
                    _occlusionTextureParameter.SetValue(temp0);
                    _blurHorizontalPass.Apply();
                    graphicsDevice.DrawFullScreenQuad();

                    // Blur vertically.
                    graphicsDevice.SetRenderTarget(temp0);
                    _occlusionTextureParameter.SetValue(temp1);
                    _blurVerticalPass.Apply();
                    graphicsDevice.DrawFullScreenQuad();
                }

                // A few render targets are not needed anymore.
                renderTargetPool.Recycle(downsampledDepthTarget);
                renderTargetPool.Recycle(temp1);
            }
            else
            {
                // A few render targets are not needed anymore.
                renderTargetPool.Recycle(downsampledDepthTarget);

                context.SourceTexture = temp0;
                context.RenderTarget  = temp0;
                context.Viewport      = new Viewport(0, 0, temp0.Width, temp0.Height);
                for (int i = 0; i < NumberOfBlurPasses; i++)
                {
                    _blur.Process(context);
                }
            }

            _strengthParameter.SetValue(Strength > 1 ? Strength : 1);

            if (CombineWithSource)
            {
                if (TextureHelper.IsFloatingPointFormat(source.Format))
                {
                    graphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
                }
                else
                {
                    graphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;
                }

                // Combine with scene.
                graphicsDevice.SetRenderTarget(target);
                graphicsDevice.Viewport = viewport;
                _viewportSizeParameter.SetValue(new Vector2(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height));
                _occlusionTextureParameter.SetValue(temp0);
                _sourceTextureParameter.SetValue(source);
                _combinePass.Apply();
                graphicsDevice.DrawFullScreenQuad();
            }
            else
            {
                if (temp0 != target)
                {
                    graphicsDevice.SetRenderTarget(target);
                    graphicsDevice.Viewport = viewport;
                    _viewportSizeParameter.SetValue(new Vector2(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height));
                    _occlusionTextureParameter.SetValue(temp0);
                    _copyPass.Apply();
                    graphicsDevice.DrawFullScreenQuad();
                }
            }

            // Clean-up
            if (temp0 != target)
            {
                renderTargetPool.Recycle(temp0);
            }

            _sourceTextureParameter.SetValue((Texture2D)null);
            _gBuffer0Parameter.SetValue((Texture2D)null);
            _occlusionTextureParameter.SetValue((Texture2D)null);
            context.SourceTexture = source;
            context.RenderTarget  = target;
            context.Viewport      = viewport;
        }
Пример #3
0
        protected override void OnProcess(RenderContext context)
        {
            var graphicsDevice   = GraphicsService.GraphicsDevice;
            var renderTargetPool = GraphicsService.RenderTargetPool;

            var source   = context.SourceTexture;
            var target   = context.RenderTarget;
            var viewport = context.Viewport;

            int downsampledWidth  = Math.Max(1, source.Width / DownsampleFactor);
            int downsampledHeight = Math.Max(1, source.Height / DownsampleFactor);

            // ----- Get temporary render targets.
            var sourceDownsampled = renderTargetPool.Obtain2D(new RenderTargetFormat(
                                                                  downsampledWidth,
                                                                  downsampledHeight,
                                                                  false,
                                                                  source.Format,
                                                                  DepthFormat.None));
            var bloom = renderTargetPool.Obtain2D(new RenderTargetFormat(
                                                      downsampledWidth,
                                                      downsampledHeight,
                                                      false,
                                                      SurfaceFormat.Color,
                                                      DepthFormat.None));

            // ----- Downsample scene.
            context.RenderTarget = sourceDownsampled;
            context.Viewport     = new Viewport(0, 0, sourceDownsampled.Width, sourceDownsampled.Height);
            _downsampleFilter.Process(context);

            // ----- Compute luminance.
            context.SourceTexture = sourceDownsampled;
            context.RenderTarget  = _luminanceTarget;
            context.Viewport      = new Viewport(0, 0, _luminanceTarget.Width, _luminanceTarget.Height);
            _luminance.Process(context);

            // ----- Create bloom image.
            graphicsDevice.SetRenderTarget(bloom);
            _viewportSizeParameter.SetValue(new Vector2(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height));
            _bloomThresholdParameter.SetValue(BloomThreshold);
            _middleGrayParameter.SetValue(MiddleGray);
            _minExposureParameter.SetValue(MinExposure);
            _maxExposureParameter.SetValue(MaxExposure);
            _bloomIntensityParameter.SetValue(BloomIntensity);
            _sceneTextureParameter.SetValue(sourceDownsampled);
            _luminanceTextureParameter.SetValue(_luminanceTarget);
            _brightnessPass.Apply();
            graphicsDevice.DrawFullScreenQuad();

            // sourceDownsampled is not needed anymore.
            renderTargetPool.Recycle(sourceDownsampled);

            // We make a two-pass blur, so source can be equal to target.
            context.SourceTexture = bloom;
            context.RenderTarget  = bloom;
            context.Viewport      = new Viewport(0, 0, bloom.Width, bloom.Height);
            _blur.Process(context);

            // ----- Combine scene and bloom.
            graphicsDevice.SetRenderTarget(target);
            graphicsDevice.Viewport = viewport;
            _viewportSizeParameter.SetValue(new Vector2(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height));
            _sceneTextureParameter.SetValue(source);
            _bloomTextureParameter.SetValue(bloom);
            _luminanceTextureParameter.SetValue(_luminanceTarget);
            _middleGrayParameter.SetValue(MiddleGray);

            if (EnableBlueShift)
            {
                _blueShiftColorParameter.SetValue((Vector3)BlueShiftColor);
                _blueShiftParameter.SetValue(new Vector2(1 / BlueShiftCenter, 1 / BlueShiftRange));
                _combineWithBlueShiftPass.Apply();
            }
            else
            {
                _combinePass.Apply();
            }

            graphicsDevice.DrawFullScreenQuad();

            // ----- Clean-up
            _sceneTextureParameter.SetValue((Texture2D)null);
            _luminanceTextureParameter.SetValue((Texture2D)null);
            _bloomTextureParameter.SetValue((Texture2D)null);
            renderTargetPool.Recycle(bloom);
            context.SourceTexture = source;
            context.RenderTarget  = target;
            context.Viewport      = viewport;
        }
Пример #4
0
        protected override void OnProcess(RenderContext context)
        {
            if (TextureHelper.IsFloatingPointFormat(context.SourceTexture.Format))
            {
                throw new GraphicsException("Source texture format must not be a floating-point format.");
            }

            var graphicsDevice   = GraphicsService.GraphicsDevice;
            var renderTargetPool = GraphicsService.RenderTargetPool;

            var source   = context.SourceTexture;
            var target   = context.RenderTarget;
            var viewport = context.Viewport;

            int downsampledWidth  = Math.Max(1, source.Width / DownsampleFactor);
            int downsampledHeight = Math.Max(1, source.Height / DownsampleFactor);

            // ----- Get temporary render targets.
            var            bloomFormat = new RenderTargetFormat(downsampledWidth, downsampledHeight, false, SurfaceFormat.Color, DepthFormat.None);
            RenderTarget2D bloom0      = renderTargetPool.Obtain2D(bloomFormat);
            RenderTarget2D bloom1      = renderTargetPool.Obtain2D(bloomFormat);

            // ----- Downsample scene to bloom0.
            context.RenderTarget = bloom0;
            context.Viewport     = new Viewport(0, 0, bloom0.Width, bloom0.Height);
            _downsampleFilter.Process(context);

            // ----- Create bloom image
            graphicsDevice.SetRenderTarget(bloom1);
            _viewportSizeParameter.SetValue(new Vector2(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height));
            _bloomThresholdParameter.SetValue(Threshold);
            _bloomIntensityParameter.SetValue(Intensity);
            _bloomSaturationParameter.SetValue(Saturation);
            _sceneTextureParameter.SetValue(bloom0);
            _brightnessPass.Apply();
            graphicsDevice.DrawFullScreenQuad();

            // bloom0 is not needed anymore.
            renderTargetPool.Recycle(bloom0);

            // We make a two-pass blur, so source can be equal to target.
            context.SourceTexture = bloom1;
            context.RenderTarget  = bloom1;
            _blur.Process(context);

            // ----- Combine scene and bloom.
            graphicsDevice.SetRenderTarget(target);
            graphicsDevice.Viewport = viewport;
            _viewportSizeParameter.SetValue(new Vector2(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height));
            _sceneTextureParameter.SetValue(source);
            _bloomTextureParameter.SetValue(bloom1);
            _combinePass.Apply();
            graphicsDevice.DrawFullScreenQuad();

            // ----- Clean-up
            _sceneTextureParameter.SetValue((Texture2D)null);
            _bloomTextureParameter.SetValue((Texture2D)null);
            renderTargetPool.Recycle(bloom1);

            // Restore original context.
            context.SourceTexture = source;
            context.RenderTarget  = target;
            context.Viewport      = viewport;
        }