Skip to content

Commit b7e88d5

Browse files
committed
Apply graphic effects in TargetPainter
1 parent f6aa3ea commit b7e88d5

File tree

3 files changed

+88
-24
lines changed

3 files changed

+88
-24
lines changed

src/targetpainter.cpp

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "irenderedtarget.h"
99
#include "spritemodel.h"
1010
#include "bitmapskin.h"
11+
#include "shadermanager.h"
1112

1213
using namespace scratchcpprender;
1314

@@ -59,15 +60,57 @@ void TargetPainter::paint(QNanoPainter *painter)
5960
return;
6061
}
6162

62-
// Blit the FBO to the Qt Quick FBO
63-
glF.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
64-
glF.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFbo->handle());
65-
glF.glBlitFramebuffer(0, 0, texture.width(), texture.height(), 0, 0, targetFbo->width(), targetFbo->height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
63+
// Get the shader program for the current set of effects
64+
ShaderManager *shaderManager = ShaderManager::instance();
65+
66+
const auto &effects = m_target->graphicEffects();
67+
QOpenGLShaderProgram *shaderProgram = shaderManager->getShaderProgram(effects);
68+
Q_ASSERT(shaderProgram);
69+
Q_ASSERT(shaderProgram->isLinked());
70+
71+
// Set up vertex data and buffers for a quad
72+
float vertices[] = {
73+
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
74+
};
75+
76+
GLuint VBO, VAO;
77+
glF.glGenVertexArrays(1, &VAO);
78+
glF.glGenBuffers(1, &VBO);
79+
80+
glF.glBindVertexArray(VAO);
81+
82+
glF.glBindBuffer(GL_ARRAY_BUFFER, VBO);
83+
glF.glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
84+
85+
// Position attribute
86+
glF.glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0);
87+
glF.glEnableVertexAttribArray(0);
88+
89+
// Texture coordinate attribute
90+
glF.glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)(2 * sizeof(float)));
91+
glF.glEnableVertexAttribArray(1);
92+
93+
// Render to the target framebuffer
6694
glF.glBindFramebuffer(GL_FRAMEBUFFER, targetFbo->handle());
95+
shaderProgram->bind();
96+
glF.glBindVertexArray(VAO);
97+
glF.glActiveTexture(GL_TEXTURE0);
98+
glF.glBindTexture(GL_TEXTURE_2D, texture.handle());
99+
shaderManager->setUniforms(shaderProgram, 0, effects); // set texture and effect uniforms
100+
glF.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
101+
102+
// Process the resulting texture
103+
// NOTE: This must happen now, not later, because the alpha channel can be used here
104+
m_target->updateHullPoints(targetFbo);
67105

106+
// Cleanup
107+
shaderProgram->release();
108+
glF.glBindFramebuffer(GL_FRAMEBUFFER, 0);
68109
glF.glDeleteFramebuffers(1, &fbo);
69110

70-
m_target->updateHullPoints(targetFbo);
111+
// Delete vertex array and buffer
112+
glF.glDeleteVertexArrays(1, &VAO);
113+
glF.glDeleteBuffers(1, &VBO);
71114
}
72115

73116
void TargetPainter::synchronize(QNanoQuickItem *item)

test/color_effects.png

589 Bytes
Loading

test/targetpainter/targetpainter_test.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,29 @@ using ::testing::ReturnRef;
1111
class TargetPainterTest : public testing::Test
1212
{
1313
public:
14-
void createContextAndSurface(QOpenGLContext *context, QOffscreenSurface *surface)
14+
void SetUp() override
1515
{
16-
QSurfaceFormat surfaceFormat;
17-
surfaceFormat.setMajorVersion(4);
18-
surfaceFormat.setMinorVersion(3);
16+
m_context.create();
17+
ASSERT_TRUE(m_context.isValid());
1918

20-
context->setFormat(surfaceFormat);
21-
context->create();
22-
ASSERT_TRUE(context->isValid());
23-
24-
surface->setFormat(surfaceFormat);
25-
surface->create();
26-
ASSERT_TRUE(surface->isValid());
19+
m_surface.setFormat(m_context.format());
20+
m_surface.create();
21+
Q_ASSERT(m_surface.isValid());
22+
m_context.makeCurrent(&m_surface);
23+
}
2724

28-
context->makeCurrent(surface);
29-
ASSERT_EQ(QOpenGLContext::currentContext(), context);
25+
void TearDown() override
26+
{
27+
ASSERT_EQ(m_context.surface(), &m_surface);
28+
m_context.doneCurrent();
3029
}
30+
31+
QOpenGLContext m_context;
32+
QOffscreenSurface m_surface;
3133
};
3234

3335
TEST_F(TargetPainterTest, Paint)
3436
{
35-
QOpenGLContext context;
36-
QOffscreenSurface surface;
37-
createContextAndSurface(&context, &surface);
38-
3937
QOpenGLFramebufferObjectFormat format;
4038
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
4139

@@ -48,8 +46,10 @@ TEST_F(TargetPainterTest, Paint)
4846
// Paint reference
4947
refPainter.setAntialias(0);
5048
refPainter.setStrokeStyle(QNanoColor(255, 0, 0, 128));
49+
refPainter.setFillStyle(QNanoColor(0, 255, 100, 150));
5150
refPainter.ellipse(refFbo.width() / 2, refFbo.height() / 2, refFbo.width() / 2, refFbo.height() / 2);
5251
refPainter.stroke();
52+
refPainter.fill();
5353
refPainter.endFrame();
5454

5555
// Begin painting
@@ -76,17 +76,38 @@ TEST_F(TargetPainterTest, Paint)
7676

7777
// Paint
7878
Texture texture(refFbo.texture(), refFbo.size());
79+
std::unordered_map<ShaderManager::Effect, double> effects;
7980
EXPECT_CALL(target, texture()).WillOnce(Return(texture));
81+
EXPECT_CALL(target, graphicEffects()).WillOnce(ReturnRef(effects));
8082
EXPECT_CALL(target, updateHullPoints(&fbo));
8183
targetPainter.paint(&painter);
8284
painter.endFrame();
8385

8486
// Compare resulting images
8587
ASSERT_EQ(fbo.toImage(), refFbo.toImage());
8688

89+
// Paint with color effects
90+
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
91+
glClear(GL_COLOR_BUFFER_BIT);
92+
effects[ShaderManager::Effect::Color] = 46.2;
93+
effects[ShaderManager::Effect::Brightness] = 20.4;
94+
effects[ShaderManager::Effect::Ghost] = 84.3;
95+
EXPECT_CALL(target, texture()).WillOnce(Return(texture));
96+
EXPECT_CALL(target, graphicEffects()).WillOnce(ReturnRef(effects));
97+
EXPECT_CALL(target, updateHullPoints(&fbo));
98+
targetPainter.paint(&painter);
99+
painter.endFrame();
100+
effects.clear();
101+
102+
// Compare with reference image
103+
QBuffer refBuffer1;
104+
fbo.toImage().save(&refBuffer1, "png");
105+
QFile ref1("color_effects.png");
106+
ref1.open(QFile::ReadOnly);
107+
refBuffer1.open(QBuffer::ReadOnly);
108+
ASSERT_EQ(ref1.readAll(), refBuffer1.readAll());
109+
87110
// Release
88111
fbo.release();
89112
refFbo.release();
90-
91-
context.doneCurrent();
92113
}

0 commit comments

Comments
 (0)