1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 21:27:24 +08:00

Improve quality of beatmap background blurs

This commit is contained in:
Dan Balasescu 2022-01-11 21:22:16 +09:00
parent 01a3cf3849
commit 906e700b60

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Diagnostics;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@ -17,8 +18,6 @@ namespace osu.Game.Graphics.Backgrounds
/// </summary>
public class Background : CompositeDrawable, IEquatable<Background>
{
private const float blur_scale = 0.5f;
public readonly Sprite Sprite;
private readonly string textureName;
@ -46,7 +45,7 @@ namespace osu.Game.Graphics.Backgrounds
Sprite.Texture = textures.Get(textureName);
}
public Vector2 BlurSigma => bufferedContainer?.BlurSigma / blur_scale ?? Vector2.Zero;
public Vector2 BlurSigma => Vector2.Divide(bufferedContainer?.BlurSigma ?? Vector2.Zero, blurScale);
/// <summary>
/// Smoothly adjusts <see cref="IBufferedContainer.BlurSigma"/> over time.
@ -67,9 +66,48 @@ namespace osu.Game.Graphics.Backgrounds
}
if (bufferedContainer != null)
bufferedContainer.FrameBufferScale = newBlurSigma == Vector2.Zero ? Vector2.One : new Vector2(blur_scale);
transformBlurSigma(newBlurSigma, duration, easing);
}
bufferedContainer?.BlurTo(newBlurSigma * blur_scale, duration, easing);
private void transformBlurSigma(Vector2 newBlurSigma, double duration, Easing easing)
=> this.TransformTo(nameof(blurSigma), newBlurSigma, duration, easing);
private Vector2 blurSigmaBacking = Vector2.Zero;
private Vector2 blurScale = Vector2.One;
private Vector2 blurSigma
{
get => blurSigmaBacking;
set
{
Debug.Assert(bufferedContainer != null);
blurSigmaBacking = value;
blurScale = new Vector2(calculateBlurDownscale(value.X), calculateBlurDownscale(value.Y));
bufferedContainer.FrameBufferScale = blurScale;
bufferedContainer.BlurSigma = value * blurScale; // If the image is scaled down, the blur radius also needs to be reduced to cover the same pixel block.
}
}
/// <summary>
/// Determines a factor to downscale the background based on a given blur sigma, in order to reduce the computational complexity of blurs.
/// </summary>
/// <param name="sigma">The blur sigma.</param>
/// <returns>The scale-down factor.</returns>
private float calculateBlurDownscale(float sigma)
{
// If we're blurring within one pixel, scaling down will always result in an undesirable loss of quality.
// The algorithm below would also cause this value to go above 1, which is likewise undesirable.
if (sigma <= 1)
return 1;
// A good value is one where the loss in quality as a result of downscaling the image is not easily perceivable.
// The constants here have been experimentally chosen to yield nice transitions by approximating a log curve through the points {{ 1, 1 }, { 4, 0.75 }, { 16, 0.5 }, { 32, 0.25 }}.
float scale = -0.18f * MathF.Log(0.004f * sigma);
// To reduce shimmering, the scaling transitions are limited to happen only in increments of 0.2.
return MathF.Round(scale / 0.2f, MidpointRounding.AwayFromZero) * 0.2f;
}
public virtual bool Equals(Background other)