Skip to content

Commit

Permalink
Fix the repeat moving background shader.
Browse files Browse the repository at this point in the history
Co-authored-by: WebFreak001 <[email protected]>
  • Loading branch information
andy840119 and WebFreak001 committed Mar 19, 2023
1 parent 173718d commit d5d0c3c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 40 deletions.
49 changes: 30 additions & 19 deletions osu.Framework.Font/Graphics/Shaders/RepeatMovingBackgroundShader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Runtime.InteropServices;
using osu.Framework.Graphics.Rendering;
using osu.Framework.Graphics.Shaders.Types;
using osu.Framework.Graphics.Textures;
using osuTK;
using osuTK.Graphics.ES30;

namespace osu.Framework.Graphics.Shaders;

Expand All @@ -23,32 +24,42 @@ public class RepeatMovingBackgroundShader : InternalShader, IHasCurrentTime, IHa

public float Mix { get; set; } = 1f;

private IUniformBuffer<RepeatParameters>? repeatParametersBuffer;

public override void ApplyValue(IRenderer renderer)
{
if (Texture == null)
return;

Texture.Bind(1);

var unitId = TextureUnit.Texture1 - TextureUnit.Texture0;
GetUniform<int>(@"g_RepeatSample").UpdateValue(ref unitId);

var textureCoord = Texture.GetTextureRect().TopLeft;
GetUniform<Vector2>(@"g_RepeatSampleCoord").UpdateValue(ref textureCoord);
// todo: think about how to upload the texture.
// Texture.Bind(1);
// var unitId = TextureUnit.Texture1 - TextureUnit.Texture0;
// GetUniform<int>(@"g_RepeatSample").UpdateValue(ref unitId);

var textureSize = Texture.GetTextureRect().Size;
GetUniform<Vector2>(@"g_RepeatSampleSize").UpdateValue(ref textureSize);
repeatParametersBuffer ??= renderer.CreateUniformBuffer<RepeatParameters>();

var textureDisplaySize = TextureDisplaySize;
GetUniform<Vector2>("g_DisplaySize").UpdateValue(ref textureDisplaySize);
repeatParametersBuffer.Data = new RepeatParameters
{
RepeatSampleCoord = Texture.GetTextureRect().TopLeft,
RepeatSampleSize = Texture.GetTextureRect().Size,
DisplaySize = TextureDisplaySize,
DisplayBorder = TextureDisplayBorder,
Speed = Speed,
Mix = Math.Clamp(Mix, 0, 1)
};

var textureDisplayBorder = TextureDisplayBorder;
GetUniform<Vector2>("g_DisplayBorder").UpdateValue(ref textureDisplayBorder);

var speed = Speed;
GetUniform<Vector2>("g_Speed").UpdateValue(ref speed);
BindUniformBlock("m_RepeatMovingBackgroundParameters", repeatParametersBuffer);
}

var mix = Math.Clamp(Mix, 0, 1);
GetUniform<float>(@"g_Mix").UpdateValue(ref mix);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private record struct RepeatParameters
{
public UniformVector2 RepeatSampleCoord;
public UniformVector2 RepeatSampleSize;
public UniformVector2 DisplaySize;
public UniformVector2 DisplayBorder;
public UniformVector2 Speed;
public UniformFloat Mix;
private UniformPadding4 pad1;
}
}
45 changes: 24 additions & 21 deletions osu.Framework.Font/Resources/Shaders/sh_RepeatMovingBackground.fs
Original file line number Diff line number Diff line change
@@ -1,40 +1,43 @@
// see : https://github.com/kiwipxl/GLSL-shaders/blob/master/repeat.glsl
#include "sh_CustomizedShaderGlobalUniforms.h"
#include "sh_Utils.h"

varying vec2 v_TexCoord;
varying vec4 v_Colour;
varying mediump vec4 v_TexRect;
layout(location = 1) in lowp vec4 v_Colour;
layout(location = 2) in highp vec2 v_TexCoord;
layout(location = 3) in highp vec4 v_TexRect;

uniform lowp sampler2D m_Sampler;
layout(set = 2, binding = 0) uniform lowp texture2D m_RepeatTexture;
layout(set = 2, binding = 1) uniform lowp sampler m_RepeatSampler;

uniform mediump vec2 g_TexSize;
uniform lowp sampler2D g_RepeatSample;
uniform vec2 g_RepeatSampleCoord;
uniform vec2 g_RepeatSampleSize;
uniform vec2 g_DisplaySize;
uniform vec2 g_DisplayBorder;
uniform vec2 g_Speed;
uniform float g_Time;
uniform float g_Mix;
layout(std140, set = 3, binding = 0) uniform m_RepeatMovingBackgroundParameters
{
mediump vec2 g_RepeatSampleCoord;
mediump vec2 g_RepeatSampleSize;
mediump vec2 g_DisplaySize;
mediump vec2 g_DisplayBorder;
mediump vec2 g_Speed;
mediump float g_Mix;
};

float mod(float a, int b) {
return a - (float(b) * floor(a/float(b)));
}
layout(set = 1, binding = 0) uniform lowp texture2D m_Texture;
layout(set = 1, binding = 1) uniform lowp sampler m_Sampler;

layout(location = 0) out vec4 o_Colour;

void main(void) {
// calculate how many times texture should be repeated.
vec2 repeat = g_TexSize / (g_DisplaySize + g_DisplayBorder);

// get the repeat texture coordinate.
float repeatTexCoordX = mod(v_TexCoord.x * repeat.x + g_Speed.x * g_Time, 1);
float repeatTexCoordY = mod(v_TexCoord.y * repeat.y + g_Speed.y * g_Time, 1);
float repeatTexCoordX = mod(v_TexCoord.x * repeat.x + g_Speed.x * g_Time, 1.0);
float repeatTexCoordY = mod(v_TexCoord.y * repeat.y + g_Speed.y * g_Time, 1.0);
vec2 repeatTexCoord = vec2(repeatTexCoordX, repeatTexCoordY) / g_DisplaySize * (g_DisplaySize + g_DisplayBorder);

// because repeat texture will be the size of 1024*1024, so should make a conversion to get the target area of the texture.
vec2 fixedTexCoord = repeatTexCoord * g_RepeatSampleSize + g_RepeatSampleCoord;

// get point colour from sample.
vec4 texColor = texture2D(m_Sampler, v_TexCoord);
vec4 repeatSampleColor = v_Colour * vec4(texture2D(g_RepeatSample, fixedTexCoord).xyz, texColor.a);
gl_FragColor = toSRGB(mix(texColor, repeatSampleColor, g_Mix));
vec4 texColor = texture(sampler2D(m_Texture, m_Sampler), v_TexCoord);
vec4 repeatSampleColor = v_Colour * vec4(texture(sampler2D(m_RepeatTexture, m_RepeatSampler), fixedTexCoord).xyz, texColor.a);
o_Colour = toSRGB(mix(texColor, repeatSampleColor, g_Mix));
}

0 comments on commit d5d0c3c

Please sign in to comment.