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; }
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; }
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; }
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; }