diff --git a/krita/data/shaders/shaders.qrc b/krita/data/shaders/shaders.qrc --- a/krita/data/shaders/shaders.qrc +++ b/krita/data/shaders/shaders.qrc @@ -1,13 +1,8 @@ - - - + + bilinear_gradient.frag conical_gradient.frag conical_symetric_gradient.frag - cursor_legacy.frag - cursor_legacy.vert - cursor.frag - cursor.vert highq_downscale.frag linear_gradient.frag matrix_transform.vert @@ -16,5 +11,7 @@ square_gradient.frag matrix_transform_legacy.vert simple_texture_legacy.frag + solid_color.frag + solid_color_legacy.frag diff --git a/krita/data/shaders/solid_color.frag b/krita/data/shaders/solid_color.frag --- a/krita/data/shaders/solid_color.frag +++ b/krita/data/shaders/solid_color.frag @@ -0,0 +1,8 @@ +uniform vec4 fragColor; + +out vec4 resultFragmentColor; + +void main(void) +{ + resultFragmentColor = vec4(fragColor.x, fragColor.y, fragColor.z, fragColor.w); +} diff --git a/krita/data/shaders/solid_color_legacy.frag b/krita/data/shaders/solid_color_legacy.frag --- a/krita/data/shaders/solid_color_legacy.frag +++ b/krita/data/shaders/solid_color_legacy.frag @@ -0,0 +1,6 @@ +uniform vec4 fragColor; + +void main(void) +{ + gl_FragColor = vec4(fragColor.x, fragColor.y, fragColor.z, fragColor.w); +} diff --git a/libs/ui/kis_config.h b/libs/ui/kis_config.h --- a/libs/ui/kis_config.h +++ b/libs/ui/kis_config.h @@ -103,6 +103,9 @@ CursorStyle newCursorStyle(bool defaultValue = false) const; void setNewCursorStyle(CursorStyle style); + QColor getCursorMainColor(bool defaultValue = false) const; + void setCursorMainColor(const QColor& v) const; + OutlineStyle newOutlineStyle(bool defaultValue = false) const; void setNewOutlineStyle(OutlineStyle style); @@ -189,6 +192,12 @@ QColor getGridSubdivisionColor(bool defaultValue = false) const; void setGridSubdivisionColor(const QColor & v) const; + QColor getOpenGLGridColor(bool defaultValue = false) const; + void setOpenGLGridColor(const QColor & v) const; + + qreal getOpenGLGridDrawingThreshold(bool defaultValue = false) const; + void setOpenGLGridDrawingThreshold(qreal v) const; + quint32 guidesLineStyle(bool defaultValue = false) const; void setGuidesLineStyle(quint32 v) const; QColor guidesColor(bool defaultValue = false) const; diff --git a/libs/ui/kis_config.cc b/libs/ui/kis_config.cc --- a/libs/ui/kis_config.cc +++ b/libs/ui/kis_config.cc @@ -279,6 +279,18 @@ m_cfg.writeEntry("newCursorStyle", (int)style); } +QColor KisConfig::getCursorMainColor(bool defaultValue) const +{ + QColor col; + col.setRgbF(0.501961, 1.0, 0.501961); + return (defaultValue ? col : m_cfg.readEntry("cursormaincolor", col)); +} + +void KisConfig::setCursorMainColor(const QColor &v) const +{ + m_cfg.writeEntry("cursormaincolor", v); +} + OutlineStyle KisConfig::newOutlineStyle(bool defaultValue) const { if (defaultValue) { @@ -721,6 +733,28 @@ m_cfg.writeEntry("gridsubdivisioncolor", v); } +QColor KisConfig::getOpenGLGridColor(bool defaultValue) const +{ + QColor col(255, 255, 255); + return (defaultValue ? col : m_cfg.readEntry("openglgridcolor", col)); +} + +void KisConfig::setOpenGLGridColor(const QColor & v) const +{ + m_cfg.writeEntry("openglgridcolor", v); +} + +qreal KisConfig::getOpenGLGridDrawingThreshold(bool defaultValue) const +{ + qreal border = 8.0f; + return (defaultValue ? border : m_cfg.readEntry("griddrawingborder", border)); +} + +void KisConfig::setOpenGLGridDrawingThreshold(qreal v) const +{ + m_cfg.writeEntry("griddrawingborder", v); +} + quint32 KisConfig::guidesLineStyle(bool defaultValue) const { int v = m_cfg.readEntry("guidesLineStyle", 0); diff --git a/libs/ui/opengl/kis_opengl_canvas2.h b/libs/ui/opengl/kis_opengl_canvas2.h --- a/libs/ui/opengl/kis_opengl_canvas2.h +++ b/libs/ui/opengl/kis_opengl_canvas2.h @@ -110,6 +110,7 @@ void reportFailedShaderCompilation(const QString &context); void drawImage(); void drawCheckers(); + void drawGrid(); private: diff --git a/libs/ui/opengl/kis_opengl_canvas2.cpp b/libs/ui/opengl/kis_opengl_canvas2.cpp --- a/libs/ui/opengl/kis_opengl_canvas2.cpp +++ b/libs/ui/opengl/kis_opengl_canvas2.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #define NEAR_VAL -1000.0 #define FAR_VAL 1000.0 @@ -62,7 +63,7 @@ ~Private() { delete displayShader; delete checkerShader; - delete cursorShader; + delete solidColorShader; Sync::deleteSync(glSyncObject); } @@ -73,7 +74,7 @@ KisOpenGLShaderLoader shaderLoader; KisShaderProgram *displayShader{0}; KisShaderProgram *checkerShader{0}; - KisShaderProgram *cursorShader{0}; + KisShaderProgram *solidColorShader{0}; GLfloat checkSizeScale; bool scrollCheckers; @@ -292,11 +293,11 @@ if (!d->canvasInitialized) { delete d->displayShader; delete d->checkerShader; - delete d->cursorShader; + delete d->solidColorShader; try { d->displayShader = d->shaderLoader.loadDisplayShader(d->displayFilter, useHiQualityFiltering); d->checkerShader = d->shaderLoader.loadCheckerShader(); - d->cursorShader = d->shaderLoader.loadCursorShader(); + d->solidColorShader = d->shaderLoader.loadSolidColorShader(); } catch (const ShaderLoaderException &e) { reportFailedShaderCompilation(e.what()); } @@ -359,26 +360,32 @@ void KisOpenGLCanvas2::paintToolOutline(const QPainterPath &path) { - d->cursorShader->bind(); + if (!d->solidColorShader->bind()) { + return; + } // setup the mvp transformation - KisCoordinatesConverter *converter = coordinatesConverter(); - QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices - QMatrix4x4 modelMatrix(converter->flakeToWidgetTransform()); + QMatrix4x4 modelMatrix(coordinatesConverter()->flakeToWidgetTransform()); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; - d->cursorShader->setUniformValue(d->cursorShader->location(Uniform::ModelViewProjection), modelMatrix); + d->solidColorShader->setUniformValue(d->solidColorShader->location(Uniform::ModelViewProjection), modelMatrix); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_COLOR_LOGIC_OP); glLogicOp(GL_XOR); + KisConfig cfg; + QColor cursorColor = cfg.getCursorMainColor(); + d->solidColorShader->setUniformValue( + d->solidColorShader->location(Uniform::FragmentColor), + QVector4D(cursorColor.redF(), cursorColor.greenF(), cursorColor.blueF(), 1.0f)); + // Paint the tool outline if (KisOpenGL::hasOpenGL3()) { d->outlineVAO.bind(); @@ -392,6 +399,7 @@ QVector vertices; vertices.resize(polygon.count()); + for (int j = 0; j < polygon.count(); j++) { QPointF p = polygon.at(j); vertices[j].setX(p.x()); @@ -401,8 +409,8 @@ d->lineBuffer.allocate(vertices.constData(), 3 * vertices.size() * sizeof(float)); } else { - d->cursorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); - d->cursorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, vertices.constData()); + d->solidColorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); + d->solidColorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, vertices.constData()); } glDrawArrays(GL_LINE_STRIP, 0, vertices.size()); @@ -415,7 +423,7 @@ glDisable(GL_COLOR_LOGIC_OP); - d->cursorShader->release(); + d->solidColorShader->release(); } bool KisOpenGLCanvas2::isBusy() const @@ -469,7 +477,6 @@ //Setup the geometry for rendering if (KisOpenGL::hasOpenGL3()) { rectToVertices(d->vertices, modelRect); - d->quadBuffers[0].bind(); d->quadBuffers[0].write(0, d->vertices, 3 * 6 * sizeof(float)); @@ -498,6 +505,75 @@ glBindBuffer(GL_ARRAY_BUFFER, 0); } +void KisOpenGLCanvas2::drawGrid() +{ + if (!d->solidColorShader->bind()) { + return; + } + + QMatrix4x4 projectionMatrix; + projectionMatrix.setToIdentity(); + projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); + + // Set view/projection matrices + QMatrix4x4 modelMatrix(coordinatesConverter()->imageToWidgetTransform()); + modelMatrix.optimize(); + modelMatrix = projectionMatrix * modelMatrix; + d->solidColorShader->setUniformValue(d->solidColorShader->location(Uniform::ModelViewProjection), modelMatrix); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + KisConfig cfg; + QColor gridColor = cfg.getOpenGLGridColor(); + d->solidColorShader->setUniformValue( + d->solidColorShader->location(Uniform::FragmentColor), + QVector4D(gridColor.redF(), gridColor.greenF(), gridColor.blueF(), 0.5f)); + + if (KisOpenGL::hasOpenGL3()) { + d->outlineVAO.bind(); + d->lineBuffer.bind(); + } + + QRectF widgetRect(0,0, width(), height()); + QRectF widgetRectInImagePixels = coordinatesConverter()->documentToImage(coordinatesConverter()->widgetToDocument(widgetRect)); + QRect wr = widgetRectInImagePixels.toAlignedRect(); + + if (!d->wrapAroundMode) { + wr &= d->openGLImageTextures->storedImageBounds(); + } + + QPoint topLeftCorner = wr.topLeft(); + QPoint bottomRightCorner = wr.bottomRight() + QPoint(1, 1); + QVector grid; + + for (int i = topLeftCorner.x(); i <= bottomRightCorner.x(); ++i) { + grid.append(QVector3D(i, topLeftCorner.y(), 0)); + grid.append(QVector3D(i, bottomRightCorner.y(), 0)); + } + for (int i = topLeftCorner.y(); i <= bottomRightCorner.y(); ++i) { + grid.append(QVector3D(topLeftCorner.x(), i, 0)); + grid.append(QVector3D(bottomRightCorner.x(), i, 0)); + } + + if (KisOpenGL::hasOpenGL3()) { + d->lineBuffer.allocate(grid.constData(), 3 * grid.size() * sizeof(float)); + } + else { + d->solidColorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); + d->solidColorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, grid.constData()); + } + + glDrawArrays(GL_LINES, 0, grid.size()); + + if (KisOpenGL::hasOpenGL3()) { + d->lineBuffer.release(); + d->outlineVAO.release(); + } + + d->solidColorShader->release(); +} + void KisOpenGLCanvas2::drawImage() { if (!d->displayShader) { @@ -516,7 +592,7 @@ projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices - QMatrix4x4 modelMatrix(coordinatesConverter()->imageToWidgetTransform()); + QMatrix4x4 modelMatrix(converter->imageToWidgetTransform()); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->displayShader->setUniformValue(d->displayShader->location(Uniform::ModelViewProjection), modelMatrix); @@ -595,7 +671,6 @@ //Setup the geometry for rendering if (KisOpenGL::hasOpenGL3()) { rectToVertices(d->vertices, modelRect); - d->quadBuffers[0].bind(); d->quadBuffers[0].write(0, d->vertices, 3 * 6 * sizeof(float)); @@ -703,8 +778,13 @@ if (KisOpenGL::hasOpenGL3()) { d->quadVAO.bind(); } + drawCheckers(); drawImage(); + KisConfig cfg; + if (coordinatesConverter()->effectiveZoom() > cfg.getOpenGLGridDrawingThreshold() - 0.00001) { + drawGrid(); + } if (KisOpenGL::hasOpenGL3()) { d->quadVAO.release(); } diff --git a/libs/ui/opengl/kis_opengl_shader_loader.h b/libs/ui/opengl/kis_opengl_shader_loader.h --- a/libs/ui/opengl/kis_opengl_shader_loader.h +++ b/libs/ui/opengl/kis_opengl_shader_loader.h @@ -32,7 +32,7 @@ * An enum for storing all uniform names used in shaders */ enum Uniform { ModelViewProjection, TextureMatrix, ViewportScale, - TexelSize, Texture0, Texture1, FixedLodLevel }; + TexelSize, Texture0, Texture1, FixedLodLevel, FragmentColor }; /** * A wrapper class over Qt's QOpenGLShaderProgram to @@ -84,7 +84,7 @@ public: KisShaderProgram *loadDisplayShader(QSharedPointer displayFilter, bool useHiQualityFiltering); KisShaderProgram *loadCheckerShader(); - KisShaderProgram *loadCursorShader(); + KisShaderProgram *loadSolidColorShader(); private: KisShaderProgram *loadShader(QString vertPath, QString fragPath, QByteArray vertHeader, QByteArray fragHeader); diff --git a/libs/ui/opengl/kis_opengl_shader_loader.cpp b/libs/ui/opengl/kis_opengl_shader_loader.cpp --- a/libs/ui/opengl/kis_opengl_shader_loader.cpp +++ b/libs/ui/opengl/kis_opengl_shader_loader.cpp @@ -36,7 +36,8 @@ {TexelSize, "texelSize"}, {Texture0, "texture0"}, {Texture1, "texture1"}, - {FixedLodLevel, "fixedLodLevel"} + {FixedLodLevel, "fixedLodLevel"}, + {FragmentColor, "fragColor"} }; /** @@ -168,19 +169,19 @@ } /** - * Specific cursor shader loading function. It picks the appropriate shader + * Specific uniform shader loading function. It picks the appropriate shader * files depending on the availability of OpenGL3 on the target machine. */ -KisShaderProgram *KisOpenGLShaderLoader::loadCursorShader() +KisShaderProgram *KisOpenGLShaderLoader::loadSolidColorShader() { QString vertPath, fragPath; // Select appropriate shader files if (KisOpenGL::supportsLoD()) { - vertPath = "cursor.vert"; - fragPath = "cursor.frag"; + vertPath = "matrix_transform.vert"; + fragPath = "solid_color.frag"; } else { - vertPath = "cursor_legacy.vert"; - fragPath = "cursor_legacy.frag"; + vertPath = "matrix_transform_legacy.vert"; + fragPath = "solid_color_legacy.frag"; } KisShaderProgram *shader = loadShader(vertPath, fragPath, QByteArray(), QByteArray());