Skip to content

Commit 3a0187a

Browse files
committed
Implement the mosaic effect
1 parent fc4b640 commit 3a0187a

File tree

6 files changed

+78
-9
lines changed

6 files changed

+78
-9
lines changed

src/shadermanager.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ static const char *TEXTURE_UNIT_UNIFORM = "u_skin";
3636
static const char *SKIN_SIZE_UNIFORM = "u_skinSize";
3737

3838
static const std::unordered_map<ShaderManager::Effect, const char *> EFFECT_TO_NAME = {
39-
{ ShaderManager::Effect::Color, "color" }, { ShaderManager::Effect::Brightness, "brightness" }, { ShaderManager::Effect::Ghost, "ghost" },
40-
{ ShaderManager::Effect::Fisheye, "fisheye" }, { ShaderManager::Effect::Whirl, "whirl" }, { ShaderManager::Effect::Pixelate, "pixelate" }
39+
{ ShaderManager::Effect::Color, "color" }, { ShaderManager::Effect::Brightness, "brightness" }, { ShaderManager::Effect::Ghost, "ghost" }, { ShaderManager::Effect::Fisheye, "fisheye" },
40+
{ ShaderManager::Effect::Whirl, "whirl" }, { ShaderManager::Effect::Pixelate, "pixelate" }, { ShaderManager::Effect::Mosaic, "mosaic" }
4141
};
4242

4343
static const std::unordered_map<ShaderManager::Effect, const char *> EFFECT_UNIFORM_NAME = {
44-
{ ShaderManager::Effect::Color, "u_color" }, { ShaderManager::Effect::Brightness, "u_brightness" }, { ShaderManager::Effect::Ghost, "u_ghost" },
45-
{ ShaderManager::Effect::Fisheye, "u_fisheye" }, { ShaderManager::Effect::Whirl, "u_whirl" }, { ShaderManager::Effect::Pixelate, "u_pixelate" }
44+
{ ShaderManager::Effect::Color, "u_color" }, { ShaderManager::Effect::Brightness, "u_brightness" }, { ShaderManager::Effect::Ghost, "u_ghost" }, { ShaderManager::Effect::Fisheye, "u_fisheye" },
45+
{ ShaderManager::Effect::Whirl, "u_whirl" }, { ShaderManager::Effect::Pixelate, "u_pixelate" }, { ShaderManager::Effect::Mosaic, "u_mosaic" }
4646
};
4747

4848
static const std::unordered_map<ShaderManager::Effect, ConverterFunc> EFFECT_CONVERTER = {
@@ -51,12 +51,13 @@ static const std::unordered_map<ShaderManager::Effect, ConverterFunc> EFFECT_CON
5151
{ ShaderManager::Effect::Ghost, [](float x) { return 1 - std::clamp(x, 0.0f, 100.0f) / 100.0f; } },
5252
{ ShaderManager::Effect::Fisheye, [](float x) { return std::max(0.0f, (x + 100.0f) / 100.0f); } },
5353
{ ShaderManager::Effect::Whirl, [](float x) { return x * (float)pi / 180.0f; } },
54-
{ ShaderManager::Effect::Pixelate, [](float x) { return std::abs(x) / 10.0f; } }
54+
{ ShaderManager::Effect::Pixelate, [](float x) { return std::abs(x) / 10.0f; } },
55+
{ ShaderManager::Effect::Mosaic, [](float x) { return std::max(1.0f, std::min(std::round((std::abs(x) + 10.0f) / 10.0f), 512.0f)); } }
5556
};
5657

5758
static const std::unordered_map<ShaderManager::Effect, bool> EFFECT_SHAPE_CHANGES = {
58-
{ ShaderManager::Effect::Color, false }, { ShaderManager::Effect::Brightness, false }, { ShaderManager::Effect::Ghost, false },
59-
{ ShaderManager::Effect::Fisheye, true }, { ShaderManager::Effect::Whirl, true }, { ShaderManager::Effect::Pixelate, true }
59+
{ ShaderManager::Effect::Color, false }, { ShaderManager::Effect::Brightness, false }, { ShaderManager::Effect::Ghost, false }, { ShaderManager::Effect::Fisheye, true },
60+
{ ShaderManager::Effect::Whirl, true }, { ShaderManager::Effect::Pixelate, true }, { ShaderManager::Effect::Mosaic, true }
6061
};
6162

6263
Q_GLOBAL_STATIC(ShaderManager, globalInstance)

src/shadermanager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ class ShaderManager : public QObject
2121
Ghost = 1 << 2,
2222
Fisheye = 1 << 3,
2323
Whirl = 1 << 4,
24-
Pixelate = 1 << 5
24+
Pixelate = 1 << 5,
25+
Mosaic = 1 << 6
2526
};
2627

2728
explicit ShaderManager(QObject *parent = nullptr);

src/shaders/sprite.frag

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ uniform float u_pixelate;
3131
uniform vec2 u_skinSize;
3232
#endif // ENABLE_pixelate
3333

34+
#ifdef ENABLE_mosaic
35+
uniform float u_mosaic;
36+
#endif // ENABLE_mosaic
37+
3438
varying vec2 v_texCoord;
3539
uniform sampler2D u_skin;
3640

@@ -102,6 +106,10 @@ void main()
102106
{
103107
vec2 texcoord0 = v_texCoord;
104108

109+
#ifdef ENABLE_mosaic
110+
texcoord0 = fract(u_mosaic * texcoord0);
111+
#endif // ENABLE_mosaic
112+
105113
#ifdef ENABLE_pixelate
106114
{
107115
// TODO: clean up "pixel" edges

test/shadermanager/shadermanager_test.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,3 +388,62 @@ TEST_F(ShaderManagerTest, PixelateEffectValue)
388388

389389
program->release();
390390
}
391+
392+
TEST_F(ShaderManagerTest, MosaicEffectValue)
393+
{
394+
static const QString effectName = "mosaic";
395+
static const QString uniformName = "u_" + effectName;
396+
static const ShaderManager::Effect effect = ShaderManager::Effect::Mosaic;
397+
398+
std::unordered_map<ShaderManager::Effect, float> values;
399+
400+
QOpenGLFunctions glF(&m_context);
401+
glF.initializeOpenGLFunctions();
402+
ShaderManager manager;
403+
404+
// In range
405+
std::unordered_map<ShaderManager::Effect, double> effects = { { effect, 58.5 } };
406+
QOpenGLShaderProgram *program = manager.getShaderProgram(effects);
407+
program->bind();
408+
manager.setUniforms(program, 0, QSize(), effects);
409+
manager.getUniformValuesForEffects(effects, values);
410+
411+
GLfloat value = 0.0f;
412+
glF.glGetUniformfv(program->programId(), program->uniformLocation(uniformName), &value);
413+
ASSERT_EQ(value, 7.0f);
414+
ASSERT_EQ(values.at(effect), value);
415+
416+
effects[effect] = -21.8;
417+
program->bind();
418+
manager.setUniforms(program, 0, QSize(), effects);
419+
manager.getUniformValuesForEffects(effects, values);
420+
421+
value = 0.0f;
422+
glF.glGetUniformfv(program->programId(), program->uniformLocation(uniformName), &value);
423+
ASSERT_EQ(value, 3.0f);
424+
ASSERT_EQ(values.at(effect), value);
425+
426+
// Below the minimum
427+
effects[effect] = 4;
428+
program->bind();
429+
manager.setUniforms(program, 0, QSize(), effects);
430+
manager.getUniformValuesForEffects(effects, values);
431+
432+
value = 0.0f;
433+
glF.glGetUniformfv(program->programId(), program->uniformLocation(uniformName), &value);
434+
ASSERT_EQ(value, 1.0f);
435+
ASSERT_EQ(values.at(effect), value);
436+
437+
// Above the maximum
438+
effects[effect] = 5120;
439+
program->bind();
440+
manager.setUniforms(program, 0, QSize(), effects);
441+
manager.getUniformValuesForEffects(effects, values);
442+
443+
value = 0.0f;
444+
glF.glGetUniformfv(program->programId(), program->uniformLocation(uniformName), &value);
445+
ASSERT_EQ(value, 512.0f);
446+
ASSERT_EQ(values.at(effect), value);
447+
448+
program->release();
449+
}

test/shape_changing_effects.png

20 Bytes
Loading

test/targetpainter/targetpainter_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ TEST_F(TargetPainterTest, Paint)
112112
effects[ShaderManager::Effect::Fisheye] = 46;
113113
effects[ShaderManager::Effect::Whirl] = 50;
114114
effects[ShaderManager::Effect::Pixelate] = 25;
115-
// effects[ShaderManager::Effect::Mosaic] = 30;
115+
effects[ShaderManager::Effect::Mosaic] = 30;
116116
EXPECT_CALL(target, texture()).WillOnce(Return(texture));
117117
EXPECT_CALL(target, cpuTexture()).WillOnce(ReturnRef(texture));
118118
EXPECT_CALL(target, graphicEffects()).WillOnce(ReturnRef(effects));

0 commit comments

Comments
 (0)