- fixed 1-section long walls being impossible to fix after their body has been destroyed - better looking blur (small lights aren't "skewed")
98 lines
3.4 KiB
C#
98 lines
3.4 KiB
C#
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);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Computes sample weightings and texture coordinate offsets
|
|
/// for one pass of a separable gaussian blur filter.
|
|
/// </summary>
|
|
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);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Evaluates a single point on the gaussian falloff curve.
|
|
/// Used for setting up the blur filter weightings.
|
|
/// </summary>
|
|
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)));
|
|
}
|
|
|
|
}
|
|
}
|