Skip to content

Commit ca7ab44

Browse files
committed
Implement the whirl effect
1 parent f851fb9 commit ca7ab44

File tree

6 files changed

+78
-8
lines changed

6 files changed

+78
-8
lines changed

src/shadermanager.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ using namespace scratchcpprender;
1212

1313
using ConverterFunc = float (*)(float);
1414

15+
static const double pi = std::acos(-1); // TODO: Use std::numbers::pi in C++20
16+
1517
static float wrapClamp(float n, float min, float max)
1618
{
1719
// TODO: Move this to a separate class
@@ -36,25 +38,33 @@ static const std::unordered_map<ShaderManager::Effect, const char *> EFFECT_TO_N
3638
{ ShaderManager::Effect::Color, "color" },
3739
{ ShaderManager::Effect::Brightness, "brightness" },
3840
{ ShaderManager::Effect::Ghost, "ghost" },
39-
{ ShaderManager::Effect::Fisheye, "fisheye" }
41+
{ ShaderManager::Effect::Fisheye, "fisheye" },
42+
{ ShaderManager::Effect::Whirl, "whirl" }
4043
};
4144

4245
static const std::unordered_map<ShaderManager::Effect, const char *> EFFECT_UNIFORM_NAME = {
4346
{ ShaderManager::Effect::Color, "u_color" },
4447
{ ShaderManager::Effect::Brightness, "u_brightness" },
4548
{ ShaderManager::Effect::Ghost, "u_ghost" },
46-
{ ShaderManager::Effect::Fisheye, "u_fisheye" }
49+
{ ShaderManager::Effect::Fisheye, "u_fisheye" },
50+
{ ShaderManager::Effect::Whirl, "u_whirl" }
4751
};
4852

4953
static const std::unordered_map<ShaderManager::Effect, ConverterFunc> EFFECT_CONVERTER = {
5054
{ ShaderManager::Effect::Color, [](float x) { return wrapClamp(x / 200.0f, 0.0f, 1.0f); } },
5155
{ ShaderManager::Effect::Brightness, [](float x) { return std::clamp(x, -100.0f, 100.0f) / 100.0f; } },
5256
{ ShaderManager::Effect::Ghost, [](float x) { return 1 - std::clamp(x, 0.0f, 100.0f) / 100.0f; } },
53-
{ ShaderManager::Effect::Fisheye, [](float x) { return std::max(0.0f, (x + 100.0f) / 100.0f); } }
57+
{ ShaderManager::Effect::Fisheye, [](float x) { return std::max(0.0f, (x + 100.0f) / 100.0f); } },
58+
{ ShaderManager::Effect::Whirl, [](float x) { return x * (float)pi / 180.0f; } }
5459
};
5560

56-
static const std::unordered_map<ShaderManager::Effect, bool>
57-
EFFECT_SHAPE_CHANGES = { { ShaderManager::Effect::Color, false }, { ShaderManager::Effect::Brightness, false }, { ShaderManager::Effect::Ghost, false }, { ShaderManager::Effect::Fisheye, true } };
61+
static const std::unordered_map<ShaderManager::Effect, bool> EFFECT_SHAPE_CHANGES = {
62+
{ ShaderManager::Effect::Color, false },
63+
{ ShaderManager::Effect::Brightness, false },
64+
{ ShaderManager::Effect::Ghost, false },
65+
{ ShaderManager::Effect::Fisheye, true },
66+
{ ShaderManager::Effect::Whirl, true }
67+
};
5868

5969
Q_GLOBAL_STATIC(ShaderManager, globalInstance)
6070

src/shadermanager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ class ShaderManager : public QObject
1919
Color = 1 << 0,
2020
Brightness = 1 << 1,
2121
Ghost = 1 << 2,
22-
Fisheye = 1 << 3
22+
Fisheye = 1 << 3,
23+
Whirl = 1 << 4
2324
};
2425

2526
explicit ShaderManager(QObject *parent = nullptr);

src/shaders/sprite.frag

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ uniform float u_ghost;
2222
uniform float u_fisheye;
2323
#endif // ENABLE_fisheye
2424

25+
#ifdef ENABLE_whirl
26+
uniform float u_whirl;
27+
#endif // ENABLE_whirl
28+
2529
varying vec2 v_texCoord;
2630
uniform sampler2D u_skin;
2731

@@ -93,6 +97,24 @@ void main()
9397
{
9498
vec2 texcoord0 = v_texCoord;
9599

100+
#ifdef ENABLE_whirl
101+
{
102+
const float kRadius = 0.5;
103+
vec2 offset = texcoord0 - kCenter;
104+
float offsetMagnitude = length(offset);
105+
float whirlFactor = max(1.0 - (offsetMagnitude / kRadius), 0.0);
106+
float whirlActual = u_whirl * whirlFactor * whirlFactor;
107+
float sinWhirl = sin(whirlActual);
108+
float cosWhirl = cos(whirlActual);
109+
mat2 rotationMatrix = mat2(
110+
cosWhirl, -sinWhirl,
111+
sinWhirl, cosWhirl
112+
);
113+
114+
texcoord0 = rotationMatrix * offset + kCenter;
115+
}
116+
#endif // ENABLE_whirl
117+
96118
#ifdef ENABLE_fisheye
97119
{
98120
vec2 vec = (texcoord0 - kCenter) / kCenter;

test/shadermanager/shadermanager_test.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,40 @@ TEST_F(ShaderManagerTest, FisheyeEffectValue)
314314

315315
program->release();
316316
}
317+
318+
TEST_F(ShaderManagerTest, WhirlEffectValue)
319+
{
320+
static const QString effectName = "whirl";
321+
static const QString uniformName = "u_" + effectName;
322+
static const ShaderManager::Effect effect = ShaderManager::Effect::Whirl;
323+
324+
std::unordered_map<ShaderManager::Effect, float> values;
325+
326+
QOpenGLFunctions glF(&m_context);
327+
glF.initializeOpenGLFunctions();
328+
ShaderManager manager;
329+
330+
// In range
331+
std::unordered_map<ShaderManager::Effect, double> effects = { { effect, 58.5 } };
332+
QOpenGLShaderProgram *program = manager.getShaderProgram(effects);
333+
program->bind();
334+
manager.setUniforms(program, 0, effects);
335+
manager.getUniformValuesForEffects(effects, values);
336+
337+
GLfloat value = 0.0f;
338+
glF.glGetUniformfv(program->programId(), program->uniformLocation(uniformName), &value);
339+
ASSERT_EQ(std::round(value * 1000) / 1000, 1.021f);
340+
ASSERT_EQ(values.at(effect), value);
341+
342+
effects[effect] = -20.8;
343+
program->bind();
344+
manager.setUniforms(program, 0, effects);
345+
manager.getUniformValuesForEffects(effects, values);
346+
347+
value = 0.0f;
348+
glF.glGetUniformfv(program->programId(), program->uniformLocation(uniformName), &value);
349+
ASSERT_EQ(std::round(value * 1000) / 1000, -0.363f);
350+
ASSERT_EQ(values.at(effect), value);
351+
352+
program->release();
353+
}

test/shape_changing_effects.png

5 Bytes
Loading

test/targetpainter/targetpainter_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ TEST_F(TargetPainterTest, Paint)
108108
glF.glClear(GL_COLOR_BUFFER_BIT);
109109
effects.clear();
110110
effects[ShaderManager::Effect::Fisheye] = 46;
111-
/*effects[ShaderManager::Effect::Whirl] = 50;
112-
effects[ShaderManager::Effect::Pixelate] = 25;
111+
effects[ShaderManager::Effect::Whirl] = 50;
112+
/*effects[ShaderManager::Effect::Pixelate] = 25;
113113
effects[ShaderManager::Effect::Mosaic] = 30;*/
114114
EXPECT_CALL(target, texture()).WillOnce(Return(texture));
115115
EXPECT_CALL(target, graphicEffects()).WillOnce(ReturnRef(effects));

0 commit comments

Comments
 (0)