diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 710dde2fde..cd94e7063b 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -951,11 +951,57 @@ SceneOpenGL2::~SceneOpenGL2() { } +QMatrix4x4 SceneOpenGL2::createProjectionMatrix() const +{ + // Create a perspective projection with a 60° field-of-view, + // and an aspect ratio of 1.0. + const float fovY = 60.0f; + const float aspect = 1.0f; + const float zNear = 0.1f; + const float zFar = 100.0f; + + const float yMax = zNear * std::tan(fovY * M_PI / 360.0f); + const float yMin = -yMax; + const float xMin = yMin * aspect; + const float xMax = yMax * aspect; + + QMatrix4x4 projection; + projection.frustum(xMin, xMax, yMin, yMax, zNear, zFar); + + // Create a second matrix that transforms screen coordinates + // to world coordinates. + const float scaleFactor = 1.1 * std::tan(fovY * M_PI / 360.0f) / yMax; + const QSize size = screens()->size(); + + QMatrix4x4 matrix; + matrix.translate(xMin * scaleFactor, yMax * scaleFactor, -1.1); + matrix.scale( (xMax - xMin) * scaleFactor / size.width(), + -(yMax - yMin) * scaleFactor / size.height(), + 0.001); + + // Combine the matrices + return projection * matrix; +} + +void SceneOpenGL2::paintSimpleScreen(int mask, QRegion region) +{ + m_projectionMatrix = createProjectionMatrix(); + m_screenProjectionMatrix = m_projectionMatrix; + + Scene::paintSimpleScreen(mask, region); +} + void SceneOpenGL2::paintGenericScreen(int mask, ScreenPaintData data) { - ShaderBinder binder(ShaderManager::GenericShader); + const QMatrix4x4 screenMatrix = transformation(mask, data); + const QMatrix4x4 pMatrix = createProjectionMatrix(); - binder.shader()->setUniform(GLShader::ScreenTransformation, transformation(mask, data)); + m_projectionMatrix = pMatrix; + m_screenProjectionMatrix = pMatrix * screenMatrix; + + // ### Remove the following two lines when there are no more users of the old shader API + ShaderBinder binder(ShaderManager::GenericShader); + binder.shader()->setUniform(GLShader::ScreenTransformation, screenMatrix); Scene::paintGenericScreen(mask, data); } @@ -1337,21 +1383,36 @@ void SceneOpenGL2Window::performPaint(int mask, QRegion region, WindowPaintData if (!beginRenderWindow(mask, region, data)) return; + SceneOpenGL2 *scene = static_cast(m_scene); + + const QMatrix4x4 windowMatrix = transformation(mask, data); + QMatrix4x4 mvpMatrix; + + if (mask & Scene::PAINT_SCREEN_TRANSFORMED) + mvpMatrix = scene->screenModelViewProjectionMatrix() * windowMatrix; + else + mvpMatrix = scene->modelViewProjectionMatrix() * windowMatrix; + GLShader *shader = data.shader; if (!shader) { - if ((mask & Scene::PAINT_WINDOW_TRANSFORMED) || (mask & Scene::PAINT_SCREEN_TRANSFORMED)) { - shader = ShaderManager::instance()->pushShader(ShaderManager::GenericShader); - } else { - shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); - shader->setUniform(GLShader::Offset, QVector2D(x(), y())); - } + ShaderTraits traits = ShaderTrait::MapTexture; + + if (data.opacity() != 1.0 || data.brightness() != 1.0) + traits |= ShaderTrait::Modulate; + + if (data.saturation() != 1.0) + traits |= ShaderTrait::AdjustSaturation; + + shader = ShaderManager::instance()->pushShader(traits); + shader->setUniform(GLShader::ModelViewProjectionMatrix, mvpMatrix); } - if (ColorCorrection *cc = static_cast(m_scene)->colorCorrection()) { + if (ColorCorrection *cc = scene->colorCorrection()) { cc->setupForOutput(data.screen()); } - shader->setUniform(GLShader::WindowTransformation, transformation(mask, data)); + // ### Remove the following line when there are no more users of the old shader API + shader->setUniform(GLShader::WindowTransformation, windowMatrix); shader->setUniform(GLShader::Saturation, data.saturation()); const GLenum filter = (mask & (Effect::PAINT_WINDOW_TRANSFORMED | Effect::PAINT_SCREEN_TRANSFORMED)) diff --git a/scene_opengl.h b/scene_opengl.h index 886b2976bf..59d2b34d66 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -124,8 +124,11 @@ public: static bool supported(OpenGLBackend *backend); ColorCorrection *colorCorrection(); + QMatrix4x4 projectionMatrix() const { return m_projectionMatrix; } + QMatrix4x4 screenProjectionMatrix() const { return m_screenProjectionMatrix; } protected: + virtual void paintSimpleScreen(int mask, QRegion region); virtual void paintGenericScreen(int mask, ScreenPaintData data); virtual void doPaintBackground(const QVector< float >& vertices); virtual Scene::Window *createWindow(Toplevel *t); @@ -138,10 +141,13 @@ private Q_SLOTS: private: void performPaintWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data); + QMatrix4x4 createProjectionMatrix() const; private: LanczosFilter *m_lanczosFilter; QScopedPointer m_colorCorrection; + QMatrix4x4 m_projectionMatrix; + QMatrix4x4 m_screenProjectionMatrix; GLuint vao; };