Skip to content

Commit eb45629

Browse files
committed
Implement the fisheye effect
1 parent 56d9790 commit eb45629

File tree

6 files changed

+96
-6
lines changed

6 files changed

+96
-6
lines changed

src/shadermanager.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,25 @@ static const QString SHADER_PREFIX = "#version 140\n";
3232

3333
static const char *TEXTURE_UNIT_UNIFORM = "u_skin";
3434

35-
static const std::unordered_map<ShaderManager::Effect, const char *>
36-
EFFECT_TO_NAME = { { ShaderManager::Effect::Color, "color" }, { ShaderManager::Effect::Brightness, "brightness" }, { ShaderManager::Effect::Ghost, "ghost" } };
35+
static const std::unordered_map<ShaderManager::Effect, const char *> EFFECT_TO_NAME = {
36+
{ ShaderManager::Effect::Color, "color" },
37+
{ ShaderManager::Effect::Brightness, "brightness" },
38+
{ ShaderManager::Effect::Ghost, "ghost" },
39+
{ ShaderManager::Effect::Fisheye, "fisheye" }
40+
};
3741

38-
static const std::unordered_map<ShaderManager::Effect, const char *>
39-
EFFECT_UNIFORM_NAME = { { ShaderManager::Effect::Color, "u_color" }, { ShaderManager::Effect::Brightness, "u_brightness" }, { ShaderManager::Effect::Ghost, "u_ghost" } };
42+
static const std::unordered_map<ShaderManager::Effect, const char *> EFFECT_UNIFORM_NAME = {
43+
{ ShaderManager::Effect::Color, "u_color" },
44+
{ ShaderManager::Effect::Brightness, "u_brightness" },
45+
{ ShaderManager::Effect::Ghost, "u_ghost" },
46+
{ ShaderManager::Effect::Fisheye, "u_fisheye" }
47+
};
4048

4149
static const std::unordered_map<ShaderManager::Effect, ConverterFunc> EFFECT_CONVERTER = {
4250
{ ShaderManager::Effect::Color, [](float x) { return wrapClamp(x / 200.0f, 0.0f, 1.0f); } },
4351
{ ShaderManager::Effect::Brightness, [](float x) { return std::clamp(x, -100.0f, 100.0f) / 100.0f; } },
44-
{ ShaderManager::Effect::Ghost, [](float x) { return 1 - std::clamp(x, 0.0f, 100.0f) / 100.0f; } }
52+
{ 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); } }
4554
};
4655

4756
static const std::unordered_map<ShaderManager::Effect, bool>

src/shadermanager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ class ShaderManager : public QObject
1818
{
1919
Color = 1 << 0,
2020
Brightness = 1 << 1,
21-
Ghost = 1 << 2
21+
Ghost = 1 << 2,
22+
Fisheye = 1 << 3
2223
};
2324

2425
explicit ShaderManager(QObject *parent = nullptr);

src/shaders/sprite.frag

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ uniform float u_brightness;
1818
uniform float u_ghost;
1919
#endif // ENABLE_ghost
2020

21+
#ifdef ENABLE_fisheye
22+
uniform float u_fisheye;
23+
#endif // ENABLE_fisheye
24+
2125
varying vec2 v_texCoord;
2226
uniform sampler2D u_skin;
2327

@@ -89,6 +93,17 @@ void main()
8993
{
9094
vec2 texcoord0 = v_texCoord;
9195

96+
#ifdef ENABLE_fisheye
97+
{
98+
vec2 vec = (texcoord0 - kCenter) / kCenter;
99+
float vecLength = length(vec);
100+
float r = pow(min(vecLength, 1.0), u_fisheye) * max(1.0, vecLength);
101+
vec2 unit = vec / vecLength;
102+
103+
texcoord0 = kCenter + r * unit * kCenter;
104+
}
105+
#endif // ENABLE_fisheye
106+
92107
gl_FragColor = texture2D(u_skin, texcoord0);
93108

94109
#if defined(ENABLE_color) || defined(ENABLE_brightness)

test/shadermanager/shadermanager_test.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,51 @@ TEST_F(ShaderManagerTest, GhostEffectValue)
266266

267267
program->release();
268268
}
269+
270+
TEST_F(ShaderManagerTest, FisheyeEffectValue)
271+
{
272+
static const QString effectName = "fisheye";
273+
static const QString uniformName = "u_" + effectName;
274+
static const ShaderManager::Effect effect = ShaderManager::Effect::Fisheye;
275+
276+
std::unordered_map<ShaderManager::Effect, float> values;
277+
278+
QOpenGLFunctions glF(&m_context);
279+
glF.initializeOpenGLFunctions();
280+
ShaderManager manager;
281+
282+
// In range
283+
std::unordered_map<ShaderManager::Effect, double> effects = { { effect, 58.5 } };
284+
QOpenGLShaderProgram *program = manager.getShaderProgram(effects);
285+
program->bind();
286+
manager.setUniforms(program, 0, effects);
287+
manager.getUniformValuesForEffects(effects, values);
288+
289+
GLfloat value = 0.0f;
290+
glF.glGetUniformfv(program->programId(), program->uniformLocation(uniformName), &value);
291+
ASSERT_EQ(value, 1.585f);
292+
ASSERT_EQ(values.at(effect), value);
293+
294+
effects[effect] = -20.8;
295+
program->bind();
296+
manager.setUniforms(program, 0, effects);
297+
manager.getUniformValuesForEffects(effects, values);
298+
299+
value = 0.0f;
300+
glF.glGetUniformfv(program->programId(), program->uniformLocation(uniformName), &value);
301+
ASSERT_EQ(value, 0.792f);
302+
ASSERT_EQ(values.at(effect), value);
303+
304+
// Below the minimum
305+
effects[effect] = -101;
306+
program->bind();
307+
manager.setUniforms(program, 0, effects);
308+
manager.getUniformValuesForEffects(effects, values);
309+
310+
value = 0.0f;
311+
glF.glGetUniformfv(program->programId(), program->uniformLocation(uniformName), &value);
312+
ASSERT_EQ(value, 0.0f);
313+
ASSERT_EQ(values.at(effect), value);
314+
315+
program->release();
316+
}

test/shape_changing_effects.png

356 Bytes
Loading

test/targetpainter/targetpainter_test.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,23 @@ TEST_F(TargetPainterTest, Paint)
103103
// Compare with reference image
104104
ASSERT_LE(fuzzyCompareImages(fbo.toImage(), QImage("color_effects.png")), 0.04);
105105

106+
// Paint with shape changing effects
107+
glF.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
108+
glF.glClear(GL_COLOR_BUFFER_BIT);
109+
effects.clear();
110+
effects[ShaderManager::Effect::Fisheye] = 46;
111+
/*effects[ShaderManager::Effect::Whirl] = 50;
112+
effects[ShaderManager::Effect::Pixelate] = 25;
113+
effects[ShaderManager::Effect::Mosaic] = 30;*/
114+
EXPECT_CALL(target, texture()).WillOnce(Return(texture));
115+
EXPECT_CALL(target, graphicEffects()).WillOnce(ReturnRef(effects));
116+
targetPainter.paint(&painter);
117+
painter.endFrame();
118+
effects.clear();
119+
120+
// Compare with reference image
121+
ASSERT_LE(fuzzyCompareImages(fbo.toImage(), QImage("shape_changing_effects.png")), 0.04);
122+
106123
// Release
107124
fbo.release();
108125
refFbo.release();

0 commit comments

Comments
 (0)