Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement repeat moving background effect #72

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@
// See the LICENCE file in the repository root for full licence text.

using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Font.Tests.Helper;
using osu.Framework.Graphics.Shaders;
using osu.Framework.Graphics.Textures;
using osuTK;

namespace osu.Framework.Font.Tests.Visual.Shaders
{
public class CustomizedShaderTestScene : ShaderTestScene
{
[Resolved]
private TextureStore textures { get; set; }

[TestCase(0, "#FF0000")]
[TestCase(10, "#00FF00")]
[TestCase(20, "#0000FF")]
Expand Down Expand Up @@ -90,5 +95,85 @@ public void TestPixelShader(float x, float y)
};
});
}

[TestCase("sample-texture", 10, 10)]
[TestCase("sample-texture", 30, 30)]
[TestCase("sample-texture", 5, 20)]
public void TestRepeatMovingBackgroundShaderDisplaySize(string textureName, float width, float height)
{
AddStep("Apply shader", () =>
{
ShaderContainer.Shaders = new[]
{
GetShaderByType<RepeatMovingBackgroundShader>().With(s =>
{
s.Texture = textures.Get(textureName);
s.TextureDisplaySize = new Vector2(width, height);
})
};
});
}

[TestCase("sample-texture", 0, 0)]
[TestCase("sample-texture", 10, 10)]
[TestCase("sample-texture", 5, 20)]
[TestCase("sample-texture", 30, 30)]
public void TestRepeatMovingBackgroundShaderBorder(string textureName, float width, float height)
{
AddStep("Apply shader", () =>
{
ShaderContainer.Shaders = new[]
{
GetShaderByType<RepeatMovingBackgroundShader>().With(s =>
{
s.Texture = textures.Get(textureName);
s.TextureDisplaySize = new Vector2(30);
s.TextureDisplayBorder = new Vector2(width, height);
})
};
});
}

[TestCase(0, 0)]
[TestCase(1, 1)]
[TestCase(0.1f, 0.1f)]
[TestCase(5, 2)]
public void TestRepeatMovingBackgroundShaderSpeed(float xSpeed, float ySpeed)
{
AddStep("Apply shader", () =>
{
ShaderContainer.Shaders = new[]
{
GetShaderByType<RepeatMovingBackgroundShader>().With(s =>
{
s.Texture = textures.Get("sample-texture");
s.TextureDisplaySize = new Vector2(30);
s.Speed = new Vector2(xSpeed, ySpeed);
})
};
});
}

[TestCase(0)]
[TestCase(0.5f)]
[TestCase(1f)]
[TestCase(-1)] // invalid
[TestCase(3)] // invalid
public void TestRepeatMovingBackgroundShaderMix(float mix)
{
AddStep("Apply shader", () =>
{
ShaderContainer.Shaders = new[]
{
GetShaderByType<RepeatMovingBackgroundShader>().With(s =>
{
s.Texture = textures.Get("sample-texture");
s.TextureDisplaySize = new Vector2(30);
s.Speed = new Vector2(1);
s.Mix = mix;
})
};
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using osu.Framework.Graphics.OpenGL.Buffers;
using osu.Framework.Graphics.Textures;
using osuTK;
using osuTK.Graphics.ES30;

namespace osu.Framework.Graphics.Shaders
{
public class RepeatMovingBackgroundShader : InternalShader, IApplicableToCurrentTime
{
public override string ShaderName => "RepeatMovingBackground";

public Texture Texture { get; set; }

public Vector2 TextureDisplaySize { get; set; } = new Vector2(10);

public Vector2 TextureDisplayBorder { get; set; }

public Vector2 Speed { get; set; }

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

public RepeatMovingBackgroundShader(IShader originShader)
: base(originShader)
{
}

public override void ApplyValue(FrameBuffer current)
{
if (Texture == null)
return;

var size = current.Size;
GetUniform<Vector2>(@"g_TexSize").UpdateValue(ref size);

Texture.TextureGL.Bind(TextureUnit.Texture1);

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);

var textureSize = Texture.GetTextureRect().Size;
GetUniform<Vector2>(@"g_RepeatSampleSize").UpdateValue(ref textureSize);

var textureDisplaySize = TextureDisplaySize;
GetUniform<Vector2>("g_DisplaySize").UpdateValue(ref textureDisplaySize);

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

var speed = Speed;
GetUniform<Vector2>("g_Speed").UpdateValue(ref speed);

var mix = Math.Clamp(Mix, 0, 1);
GetUniform<float>(@"g_Mix").UpdateValue(ref mix);
}

public void ApplyCurrentTime(float currentTime)
{
GetUniform<float>("g_Time").UpdateValue(ref currentTime);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// see : https://github.com/kiwipxl/GLSL-shaders/blob/master/repeat.glsl

varying vec2 v_TexCoord;
varying vec4 v_Colour;
varying mediump vec4 v_TexRect;

uniform lowp sampler2D m_Sampler;

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;

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

// get the repeat texture cooldinate.
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);
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 = mix(texColor, repeatSampleColor, g_Mix);
}