using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Barotrauma { class BlurEffect { public readonly Effect Effect; public BlurEffect(Effect effect, float dx, float dy) { Effect = effect; SetParameters(dx, dy); } /// /// Computes sample weightings and texture coordinate offsets /// for one pass of a separable gaussian blur filter. /// public void SetParameters(float dx, float dy) { EffectParameter weightsParameter = Effect.Parameters["SampleWeights"]; EffectParameter offsetsParameter = Effect.Parameters["SampleOffsets"]; // Look up how many samples our gaussian blur effect supports. int sampleCount = weightsParameter.Elements.Count; // Create temporary arrays for computing our filter settings. float[] sampleWeights = new float[sampleCount]; Vector2[] sampleOffsets = new Vector2[sampleCount]; sampleWeights[0] = ComputeGaussian(0); sampleOffsets[0] = new Vector2(0); float totalWeights = sampleWeights[0]; // Add pairs of additional sample taps, positioned // along a line in both directions from the center. for (int i = 0; i < sampleCount / 2; i++) { // Store weights for the positive and negative taps. float weight = ComputeGaussian(i + 1); sampleWeights[i * 2 + 1] = weight; sampleWeights[i * 2 + 2] = weight; totalWeights += weight * 2; // To get the maximum amount of blurring from a limited number of // pixel shader samples, we take advantage of the bilinear filtering // hardware inside the texture fetch unit. If we position our texture // coordinates exactly halfway between two texels, the filtering unit // will average them for us, giving two samples for the price of one. // This allows us to step in units of two texels per sample, rather // than just one at a time. The 1.5 offset kicks things off by // positioning us nicely in between two texels. float sampleOffset = i * 2 + 1.5f; Vector2 delta = new Vector2(dx, dy) * sampleOffset; // Store texture coordinate offsets for the positive and negative taps. sampleOffsets[i * 2 + 1] = delta; sampleOffsets[i * 2 + 2] = -delta; } // Normalize the list of sample weightings, so they will always sum to one. for (int i = 0; i < sampleWeights.Length; i++) { sampleWeights[i] /= totalWeights; } weightsParameter.SetValue(sampleWeights); offsetsParameter.SetValue(sampleOffsets); } /// /// Evaluates a single point on the gaussian falloff curve. /// Used for setting up the blur filter weightings. /// float ComputeGaussian(float n) { float theta = 2.0f; return (float)((1.0 / Math.Sqrt(2 * Math.PI * theta)) * Math.Exp(-(n * n) / (2 * theta * theta))); } } }