/// <summary> /// Applies a bloom effect to the specified render target, writes the result /// to the specified render target. /// </summary> /// <param name="source">The render target to use as the source</param> /// <param name="result">The render target to use as the result</param> public void Bloom(RenderTarget2D source, RenderTarget2D result, float threshold, float bloom_intensity, float base_intensity, float bloom_saturation, float base_saturation) { float sigma = 2.5f; int scale = 1; IntermediateTexture downscaleTexture = GetIntermediateTexture(source.Width / scale, source.Height / scale, SurfaceFormat.Color); extractEffect.CurrentTechnique = extractEffect.Techniques["BloomExtract"]; extractEffect.Parameters["BloomThreshold"].SetValue(threshold); PostProcess(source, downscaleTexture.RenderTarget, extractEffect); Blur(downscaleTexture.RenderTarget, downscaleTexture.RenderTarget, sigma); bloomEffect.CurrentTechnique = bloomEffect.Techniques["BloomCombine"]; bloomEffect.Parameters["BloomIntensity"].SetValue(bloom_intensity); bloomEffect.Parameters["BaseIntensity"].SetValue(base_intensity); bloomEffect.Parameters["BloomSaturation"].SetValue(bloom_saturation); bloomEffect.Parameters["BaseSaturation"].SetValue(base_saturation); RenderTarget2D[] sources = new RenderTarget2D[2]; sources[0] = downscaleTexture.RenderTarget; sources[1] = source; PostProcess(sources, result, bloomEffect); downscaleTexture.InUse = false; }
/// <summary> /// Downscales the source to 1/16th size, using software(shader) filtering /// </summary> /// <param name="source">The source to be downscaled</param> /// <param name="result">The RT in which to store the result</param> private void GenerateDownscaleTargetSW(RenderTarget2D source, RenderTarget2D result) { String techniqueName = "Downscale4"; IntermediateTexture downscale1 = GetIntermediateTexture(source.Width / 4, source.Height / 4, source.Format); scalingEffect.CurrentTechnique = scalingEffect.Techniques[techniqueName]; PostProcess(source, downscale1.RenderTarget, scalingEffect); scalingEffect.CurrentTechnique = scalingEffect.Techniques[techniqueName]; PostProcess(downscale1.RenderTarget, result, scalingEffect); downscale1.InUse = false; }
protected IntermediateTexture GetIntermediateTexture( int width, int height, SurfaceFormat format, MultiSampleType msType, int msQuality) { width = Math.Max(1, width); height = Math.Max(1, height); // Look for a matching rendertarget in the cache var match = _intermediateTextures.FirstOrDefault( t => !t.InUse && height == t.RenderTarget.Height && format == t.RenderTarget.Format && width == t.RenderTarget.Width && msType == t.RenderTarget.MultiSampleType && msQuality == t.RenderTarget.MultiSampleQuality); if (match != null) { match.InUse = true; return(match); } // We didn't find one, let's make one var newTexture = new IntermediateTexture { RenderTarget = new RenderTarget2D( _graphicsDevice, width, height, 1, format, msType, msQuality, RenderTargetUsage.DiscardContents) }; _intermediateTextures.Add(newTexture); newTexture.InUse = true; return(newTexture); }
/// <summary> /// Applies a blur to the specified render target, writes the result /// to the specified render target. /// </summary> /// <param name="source">The render target to use as the source</param> /// <param name="result">The render target to use as the result</param> /// <param name="sigma">The standard deviation used for gaussian weights</param> public void Blur(RenderTarget2D source, RenderTarget2D result, float sigma) { IntermediateTexture blurH = GetIntermediateTexture(source.Width, source.Height, source.Format, source.MultiSampleCount); string baseTechniqueName = "GaussianBlur"; // Do horizontal pass first blurEffect.CurrentTechnique = blurEffect.Techniques[baseTechniqueName + "H"]; blurEffect.Parameters["g_fSigma"].SetValue(sigma); PostProcess(source, blurH.RenderTarget, blurEffect); // Now the vertical pass blurEffect.CurrentTechnique = blurEffect.Techniques[baseTechniqueName + "V"]; PostProcess(blurH.RenderTarget, result, blurEffect); blurH.InUse = false; }
/// <summary> /// Downscales the source to 1/16th size, using hardware filtering /// </summary> /// <param name="source">The source to be downscaled</param> /// <param name="result">The RT in which to store the result</param> private void GenerateDownscaleTargetHW(RenderTarget2D source, RenderTarget2D result) { IntermediateTexture downscale1 = GetIntermediateTexture(source.Width / 2, source.Height / 2, source.Format); scalingEffect.CurrentTechnique = scalingEffect.Techniques["ScaleHW"]; PostProcess(source, downscale1.RenderTarget, scalingEffect); IntermediateTexture downscale2 = GetIntermediateTexture(source.Width / 2, source.Height / 2, source.Format); scalingEffect.CurrentTechnique = scalingEffect.Techniques["ScaleHW"]; PostProcess(downscale1.RenderTarget, downscale2.RenderTarget, scalingEffect); downscale1.InUse = false; IntermediateTexture downscale3 = GetIntermediateTexture(source.Width / 2, source.Height / 2, source.Format); scalingEffect.CurrentTechnique = scalingEffect.Techniques["ScaleHW"]; PostProcess(downscale2.RenderTarget, downscale3.RenderTarget, scalingEffect); downscale2.InUse = false; scalingEffect.CurrentTechnique = scalingEffect.Techniques["ScaleHW"]; PostProcess(downscale3.RenderTarget, result, scalingEffect); downscale3.InUse = false; }
private IntermediateTexture GetIntermediateTexture(int width, int height, SurfaceFormat format, int msQuality) { // Look for a matching rendertarget in the cache for (int i = 0; i < intermediateTextures.Count; i++) { if (intermediateTextures[i].InUse == false && height == intermediateTextures[i].RenderTarget.Height && format == intermediateTextures[i].RenderTarget.Format && width == intermediateTextures[i].RenderTarget.Width && msQuality == intermediateTextures[i].RenderTarget.MultiSampleCount) { intermediateTextures[i].InUse = true; return(intermediateTextures[i]); } } // We didn't find one, let's make one IntermediateTexture newTexture = new IntermediateTexture(); newTexture.RenderTarget = new RenderTarget2D(device, width, height, false, format, DepthFormat.None, msQuality, RenderTargetUsage.DiscardContents); intermediateTextures.Add(newTexture); newTexture.InUse = true; return(newTexture); }
private IntermediateTexture GetIntermediateTexture(int width, int height, SurfaceFormat format, int msQuality) { // Look for a matching rendertarget in the cache for (int i = 0; i < intermediateTextures.Count; i++) { if (intermediateTextures[i].InUse == false && height == intermediateTextures[i].RenderTarget.Height && format == intermediateTextures[i].RenderTarget.Format && width == intermediateTextures[i].RenderTarget.Width && msQuality == intermediateTextures[i].RenderTarget.MultiSampleCount) { intermediateTextures[i].InUse = true; return intermediateTextures[i]; } } // We didn't find one, let's make one IntermediateTexture newTexture = new IntermediateTexture(); newTexture.RenderTarget = new RenderTarget2D(device, width, height, false, format, DepthFormat.None, msQuality, RenderTargetUsage.DiscardContents); intermediateTextures.Add(newTexture); newTexture.InUse = true; return newTexture; }
/// <summary> /// Performs tone mapping on the specified render target /// </summary> /// <param name="source">The source render target</param> /// <param name="result">The render target to which the result will be output</param> /// <param name="depthTexture">The render target containing scene depth</param> /// <param name="camera">The camera used to render the scene</param> /// <param name="dofType">The type of DOF effect to apply</param> /// <param name="focalDistance">The distance to the camera focal point</param> /// <param name="focalWidth">The width of the camera focal point</param> public void DepthOfField(RenderTarget2D source, RenderTarget2D result, RenderTarget2D depthTexture, Camera camera, DepthOfFieldType dofType, float focalDistance, float focalWidth, float time) { if (dofType == DepthOfFieldType.DiscBlur) { // Scale tap offsets based on render target size float dx = 0.5f / (float)source.Width; float dy = 0.5f / (float)source.Height; // Generate the texture coordinate offsets for our disc Vector2[] discOffsets = new Vector2[12]; discOffsets[0] = new Vector2(-0.326212f * dx, -0.40581f * dy); discOffsets[1] = new Vector2(-0.840144f * dx, -0.07358f * dy); discOffsets[2] = new Vector2(-0.840144f * dx, 0.457137f * dy); discOffsets[3] = new Vector2(-0.203345f * dx, 0.620716f * dy); discOffsets[4] = new Vector2(0.96234f * dx, -0.194983f * dy); discOffsets[5] = new Vector2(0.473434f * dx, -0.480026f * dy); discOffsets[6] = new Vector2(0.519456f * dx, 0.767022f * dy); discOffsets[7] = new Vector2(0.185461f * dx, -0.893124f * dy); discOffsets[8] = new Vector2(0.507431f * dx, 0.064425f * dy); discOffsets[9] = new Vector2(0.89642f * dx, 0.412458f * dy); discOffsets[10] = new Vector2(-0.32194f * dx, -0.932615f * dy); discOffsets[11] = new Vector2(-0.791559f * dx, -0.59771f * dy); // Set array of offsets dofEffect.Parameters["g_vFilterTaps"].SetValue(discOffsets); dofEffect.CurrentTechnique = dofEffect.Techniques["DOFDiscBlur"]; dofEffect.Parameters["g_fFocalDistance"].SetValue(focalDistance); dofEffect.Parameters["g_fFocalWidth"].SetValue(focalWidth / 2.0f); dofEffect.Parameters["g_fFarClip"].SetValue(camera.far); dofEffect.Parameters["g_fAttenuation"].SetValue(1); dofEffect.Parameters["time"].SetValue(time); //wave effect RenderTarget2D[] sources = doubleSourceArray; sources[0] = source; sources[1] = depthTexture; PostProcess(sources, result, dofEffect); } else { // Downscale to 1/16th size and blur IntermediateTexture downscaleTexture = GetIntermediateTexture(source.Width / 4, source.Height / 4, SurfaceFormat.Color); GenerateDownscaleTargetSW(source, downscaleTexture.RenderTarget); // For the "dumb" DOF type just do a blur, otherwise use a special blur // that takes depth into account if (dofType == DepthOfFieldType.BlurBuffer) { Blur(downscaleTexture.RenderTarget, downscaleTexture.RenderTarget, 2.5f); } else if (dofType == DepthOfFieldType.BlurBufferDepthCorrection) { DepthBlur(downscaleTexture.RenderTarget, downscaleTexture.RenderTarget, depthTexture, 2.5f); } dofEffect.CurrentTechnique = dofEffect.Techniques["DOFBlurBuffer"]; dofEffect.Parameters["g_fFocalDistance"].SetValue(focalDistance); dofEffect.Parameters["g_fFocalWidth"].SetValue(focalWidth / 2.0f); dofEffect.Parameters["g_fFarClip"].SetValue(camera.far); dofEffect.Parameters["g_fAttenuation"].SetValue(1.0f); RenderTarget2D[] sources = tripleSourceArray; sources[0] = source; sources[1] = downscaleTexture.RenderTarget; sources[2] = depthTexture; PostProcess(sources, result, dofEffect); downscaleTexture.InUse = false; } }