[update] Implemented a glitch effect for TextProgram.
This commit is contained in:
parent
d5039cc431
commit
70f150f820
@ -3,6 +3,7 @@ module sj.SelectScene;
|
|||||||
|
|
||||||
import std.conv,
|
import std.conv,
|
||||||
std.math,
|
std.math,
|
||||||
|
std.random,
|
||||||
std.variant;
|
std.variant;
|
||||||
|
|
||||||
import derelict.sfml2.audio;
|
import derelict.sfml2.audio;
|
||||||
@ -113,6 +114,13 @@ private abstract class AbstractSceneState {
|
|||||||
enum LoadingCubeRotationSpeed = vec3(0, PI/5, PI/10);
|
enum LoadingCubeRotationSpeed = vec3(0, PI/5, PI/10);
|
||||||
enum LoadingCubeInterval = 0.06;
|
enum LoadingCubeInterval = 0.06;
|
||||||
|
|
||||||
|
enum TitleTextSize = 40;
|
||||||
|
enum TitleTextScale = vec3(-0.002, 0.002, 0.002);
|
||||||
|
enum TitleTextTranslation = vec3(0, -0.4, 0);
|
||||||
|
|
||||||
|
enum TitleTextRandomTranslationRange = 0.02;
|
||||||
|
enum TitleTextRandomScaleRange = 0.0003;
|
||||||
|
|
||||||
this(SelectScene owner) {
|
this(SelectScene owner) {
|
||||||
owner_ = owner;
|
owner_ = owner;
|
||||||
}
|
}
|
||||||
@ -212,14 +220,23 @@ private class SongAppearState : AbstractSceneState {
|
|||||||
const song = owner.songs_[song_index_];
|
const song = owner.songs_[song_index_];
|
||||||
with (owner.text_) {
|
with (owner.text_) {
|
||||||
const w = LoadGlyphs(vec2i(256, 64),
|
const w = LoadGlyphs(vec2i(256, 64),
|
||||||
song.name.to!dstring, vec2i(40, 0), owner.fonts_.gothic);
|
song.name.to!dstring, vec2i(TitleTextSize, 0), owner.fonts_.gothic);
|
||||||
matrix.scale = vec3(-0.002, 0.002, 0.002);
|
matrix.scale = TitleTextScale;
|
||||||
matrix.translation = vec3(-w/2*matrix.scale.x, -0.4, 0);
|
matrix.translation = TitleTextTranslation + vec3(-w/2*matrix.scale.x, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override UpdateResult Update(KeyInput input) {
|
override UpdateResult Update(KeyInput input) {
|
||||||
const ratio = anime_.Update();
|
const ratio = anime_.Update();
|
||||||
|
|
||||||
|
if (owner.text_.frame++%10 > 7) {
|
||||||
|
alias RT = TitleTextRandomTranslationRange;
|
||||||
|
owner.text_.matrix.translation += vec3(
|
||||||
|
uniform(-RT, RT), uniform(-RT, RT), uniform(-RT, RT));
|
||||||
|
alias RS = TitleTextRandomScaleRange;
|
||||||
|
owner.text_.matrix.scale += vec3(
|
||||||
|
uniform(-RS, RS), uniform(-RS, RS), 0);
|
||||||
|
}
|
||||||
|
|
||||||
with (owner.lobby_) {
|
with (owner.lobby_) {
|
||||||
cube_matrix.rotation += cube_rota_speed_ease_.Calculate(ratio);
|
cube_matrix.rotation += cube_rota_speed_ease_.Calculate(ratio);
|
||||||
cube_interval = cube_interval_ease_.Calculate(ratio);
|
cube_interval = cube_interval_ease_.Calculate(ratio);
|
||||||
@ -260,10 +277,35 @@ private class SongWaitState : AbstractSceneState {
|
|||||||
|
|
||||||
auto song = owner.songs_[song_index_];
|
auto song = owner.songs_[song_index_];
|
||||||
song.PlayForPreview();
|
song.PlayForPreview();
|
||||||
|
|
||||||
|
with (owner.text_) {
|
||||||
|
matrix.scale = TitleTextScale;
|
||||||
|
matrix.translation =
|
||||||
|
TitleTextTranslation + vec3(-modelWidth/2*matrix.scale.x, 0, 0);
|
||||||
|
frame = 0;
|
||||||
|
}
|
||||||
|
frame_ = 0;
|
||||||
}
|
}
|
||||||
override UpdateResult Update(KeyInput input) {
|
override UpdateResult Update(KeyInput input) {
|
||||||
owner.lobby_.cube_matrix.rotation += CubeRotationSpeed;
|
owner.lobby_.cube_matrix.rotation += CubeRotationSpeed;
|
||||||
|
|
||||||
|
if (frame_%10 == 0) with (owner.text_) {
|
||||||
|
++frame;
|
||||||
|
|
||||||
|
if (frame_%100 == 0) {
|
||||||
|
matrix.scale = TitleTextScale;
|
||||||
|
matrix.translation =
|
||||||
|
TitleTextTranslation + vec3(-modelWidth/2*matrix.scale.x, 0, 0);
|
||||||
|
|
||||||
|
} else if (frame_%20 == 0) {
|
||||||
|
alias RT = TitleTextRandomTranslationRange;
|
||||||
|
matrix.translation += vec3(uniform(-RT, RT), uniform(-RT, RT), uniform(-RT, RT));
|
||||||
|
|
||||||
|
alias RS = TitleTextRandomScaleRange;
|
||||||
|
matrix.scale += vec3(uniform(-RS, RS), uniform(-RS, RS), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (input.right) {
|
if (input.right) {
|
||||||
song.StopPlaying();
|
song.StopPlaying();
|
||||||
song_appear_state_.Initialize(++song_index_%owner.songs_.length);
|
song_appear_state_.Initialize(++song_index_%owner.songs_.length);
|
||||||
@ -274,6 +316,8 @@ private class SongWaitState : AbstractSceneState {
|
|||||||
owner.title_scene_.Initialize();
|
owner.title_scene_.Initialize();
|
||||||
return CreateResult(owner.title_scene_);
|
return CreateResult(owner.title_scene_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++frame_;
|
||||||
return CreateResult(this);
|
return CreateResult(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,4 +329,6 @@ private class SongWaitState : AbstractSceneState {
|
|||||||
SongAppearState song_appear_state_;
|
SongAppearState song_appear_state_;
|
||||||
|
|
||||||
size_t song_index_;
|
size_t song_index_;
|
||||||
|
|
||||||
|
int frame_;
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,8 @@ class Text {
|
|||||||
gloader.pxHeight = charsz.y;
|
gloader.pxHeight = charsz.y;
|
||||||
gloader.flags = FT_LOAD_DEFAULT | FT_LOAD_RENDER;
|
gloader.flags = FT_LOAD_DEFAULT | FT_LOAD_RENDER;
|
||||||
|
|
||||||
|
model_width_ = 0;
|
||||||
int bmp_width;
|
int bmp_width;
|
||||||
float text_width = 0;
|
|
||||||
foreach (c; text) {
|
foreach (c; text) {
|
||||||
with (gloader) {
|
with (gloader) {
|
||||||
character = c;
|
character = c;
|
||||||
@ -60,7 +60,7 @@ class Text {
|
|||||||
const bearing_y = m.horiBearingY*1f / m.height * srcsz.y;
|
const bearing_y = m.horiBearingY*1f / m.height * srcsz.y;
|
||||||
const advance = m.horiAdvance *1f / m.width * srcsz.x;
|
const advance = m.horiAdvance *1f / m.width * srcsz.x;
|
||||||
|
|
||||||
const posleft = text_width + bearing_x;
|
const posleft = model_width_ + bearing_x;
|
||||||
const posright = posleft + srcsz.x;
|
const posright = posleft + srcsz.x;
|
||||||
const postop = bearing_y;
|
const postop = bearing_y;
|
||||||
const posbottom = postop - srcsz.y;
|
const posbottom = postop - srcsz.y;
|
||||||
@ -95,7 +95,7 @@ class Text {
|
|||||||
*vertices_ptr++ = uvbottom;
|
*vertices_ptr++ = uvbottom;
|
||||||
|
|
||||||
bmp_width += srcsz.x;
|
bmp_width += srcsz.x;
|
||||||
text_width += advance;
|
model_width_ += advance;
|
||||||
}
|
}
|
||||||
|
|
||||||
texture_.Bind();
|
texture_.Bind();
|
||||||
@ -133,7 +133,7 @@ class Text {
|
|||||||
}
|
}
|
||||||
index_count_ = indices_ptr - indices_data.entity;
|
index_count_ = indices_ptr - indices_data.entity;
|
||||||
|
|
||||||
return text_width;
|
return model_width_;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -145,17 +145,25 @@ class Text {
|
|||||||
void Draw(mat4 proj, mat4 view) {
|
void Draw(mat4 proj, mat4 view) {
|
||||||
if (index_count_ == 0) return;
|
if (index_count_ == 0) return;
|
||||||
|
|
||||||
program_.Use(proj, view, matrix.Create(), texture_, color);
|
program_.Use(proj, view,
|
||||||
|
matrix.Create(), texture_, color, frame, model_width_);
|
||||||
|
|
||||||
vao_.Bind();
|
vao_.Bind();
|
||||||
indices_.Bind();
|
indices_.Bind();
|
||||||
gl.DrawElements(GL_TRIANGLE_STRIP, index_count_.to!int, GL_UNSIGNED_SHORT, null);
|
gl.DrawElements(GL_TRIANGLE_STRIP, index_count_.to!int, GL_UNSIGNED_SHORT, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@property float modelWidth() const {
|
||||||
|
return model_width_;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
ModelMatrixFactory!4 matrix;
|
ModelMatrixFactory!4 matrix;
|
||||||
///
|
///
|
||||||
vec4 color = vec4(0, 0, 0, 1);
|
vec4 color = vec4(0, 0, 0, 1);
|
||||||
|
///
|
||||||
|
int frame;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void CopyRawPixels(in ubyte* src, vec2i srcsz, ubyte* dst, vec2i dstsz, vec2i offset) {
|
static void CopyRawPixels(in ubyte* src, vec2i srcsz, ubyte* dst, vec2i dstsz, vec2i offset) {
|
||||||
@ -179,4 +187,6 @@ class Text {
|
|||||||
ElementArrayBufferRef indices_;
|
ElementArrayBufferRef indices_;
|
||||||
|
|
||||||
size_t index_count_;
|
size_t index_count_;
|
||||||
|
|
||||||
|
float model_width_;
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,11 @@ class TextProgram {
|
|||||||
layout(location = 0) in vec3 vert;
|
layout(location = 0) in vec3 vert;
|
||||||
layout(location = 1) in vec2 uv;
|
layout(location = 1) in vec2 uv;
|
||||||
|
|
||||||
|
out vec3 vert_;
|
||||||
out vec2 uv_;
|
out vec2 uv_;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
vert_ = vert;
|
||||||
uv_ = uv;
|
uv_ = uv;
|
||||||
gl_Position = P * V * M * vec4(vert, 1);
|
gl_Position = P * V * M * vec4(vert, 1);
|
||||||
}
|
}
|
||||||
@ -39,14 +41,44 @@ class TextProgram {
|
|||||||
enum FragmentShaderSrc = ShaderHeader ~ q{
|
enum FragmentShaderSrc = ShaderHeader ~ q{
|
||||||
layout(location = 3) uniform sampler2D tex;
|
layout(location = 3) uniform sampler2D tex;
|
||||||
layout(location = 4) uniform vec4 color;
|
layout(location = 4) uniform vec4 color;
|
||||||
|
layout(location = 5) uniform int frame;
|
||||||
|
layout(location = 6) uniform float model_width;
|
||||||
|
|
||||||
|
in vec3 vert_;
|
||||||
in vec2 uv_;
|
in vec2 uv_;
|
||||||
|
|
||||||
out vec4 pixel_;
|
out vec4 pixel_;
|
||||||
|
|
||||||
|
float choose(int a, int b, float a_big, float b_big) {
|
||||||
|
float condition = step(float(a), float(b));
|
||||||
|
return condition * b_big + (1-condition) * a_big;
|
||||||
|
}
|
||||||
|
float choose(float a, float b, float c, float hit, float other) {
|
||||||
|
float condition = step(a, b) * step(b, c);
|
||||||
|
return condition * hit + (1-condition) * other;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
float vx = vert_.x / model_width;
|
||||||
|
vec2 uv = uv_;
|
||||||
|
|
||||||
|
uv.y = choose(15, frame%18, uv.y,
|
||||||
|
choose(0.1, vx, 0.2, clamp(uv.y, 0, 0.6), uv.y));
|
||||||
|
uv.y = choose(8, frame%14, uv.y,
|
||||||
|
choose(0.1, vx, 0.6, clamp(uv.y, 0, 0.8), uv.y));
|
||||||
|
uv.y = choose(21, frame%29, uv.y,
|
||||||
|
choose(0.2, vx, 0.3, clamp(uv.y, 0.1, 1), uv.y));
|
||||||
|
uv.y = choose(20, frame%23, uv.y,
|
||||||
|
choose(0.4, vx, 0.6, clamp(uv.y, 0.4, 1), uv.y));
|
||||||
|
uv.y = choose(5, frame%6, uv.y,
|
||||||
|
choose(0.5, vx, 0.8, clamp(uv.y, 0, 0.7), uv.y));
|
||||||
|
uv.y = choose(15, frame%17, uv.y,
|
||||||
|
choose(0.6, vx, 0.7, clamp(uv.y, 0.5, 1), uv.y));
|
||||||
|
uv.y = choose(7, frame%9, uv.y,
|
||||||
|
choose(0.6, vx, 0.9, clamp(uv.y, 0.3, 1), uv.y));
|
||||||
|
|
||||||
pixel_ = color;
|
pixel_ = color;
|
||||||
pixel_.a *= texture(tex, uv_).r;
|
pixel_.a *= texture(tex, uv).r;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -89,7 +121,8 @@ class TextProgram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
void Use(mat4 proj, mat4 view, mat4 model, ref Texture2DRef tex, vec4 color) {
|
void Use(mat4 proj, mat4 view, mat4 model,
|
||||||
|
ref Texture2DRef tex, vec4 color, int frame, float model_width) {
|
||||||
tex.BindToUnit(GL_TEXTURE0);
|
tex.BindToUnit(GL_TEXTURE0);
|
||||||
sampler_.Bind(0);
|
sampler_.Bind(0);
|
||||||
|
|
||||||
@ -99,6 +132,8 @@ class TextProgram {
|
|||||||
program_.uniform!2 = model;
|
program_.uniform!2 = model;
|
||||||
program_.uniform!3 = 0;
|
program_.uniform!3 = 0;
|
||||||
program_.uniform!4 = color;
|
program_.uniform!4 = color;
|
||||||
|
program_.uniform!5 = frame;
|
||||||
|
program_.uniform!6 = model_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user