Skip to content

Commit

Permalink
Merge pull request #72 from andy840119/implement-repeat-moving-backgr…
Browse files Browse the repository at this point in the history
…ound-shader

Implement repeat moving background effect
  • Loading branch information
andy840119 authored Oct 24, 2021
2 parents 2526e2e + 8037fcb commit b94000b
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 0 deletions.
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);
}
}
}
35 changes: 35 additions & 0 deletions osu.Framework.Font/Resources/Shaders/sh_RepeatMovingBackground.fs
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);
}

0 comments on commit b94000b

Please sign in to comment.