diff --git a/playground/shapes/Gradient.cpp b/playground/shapes/Gradient.cpp index c03b9b42..70b701d6 100644 --- a/playground/shapes/Gradient.cpp +++ b/playground/shapes/Gradient.cpp @@ -8,8 +8,8 @@ Gradient::Gradient( const Gradient& other ) noexcept : m_stops( other.m_stops ) - , m_values{ other.m_values[0], other.m_values[1], other.m_values[2], - other.m_values[3], other.m_values[4], other.m_values[5] } + , m_values{ other.m_values[0], other.m_values[1], + other.m_values[2], other.m_values[3], } , m_type( other.m_type ) , m_spread( other.m_spread ) { @@ -25,8 +25,6 @@ Gradient& Gradient::operator=( const Gradient& other ) noexcept m_values[1] = other.m_values[1]; m_values[2] = other.m_values[2]; m_values[3] = other.m_values[3]; - m_values[4] = other.m_values[4]; - m_values[5] = other.m_values[5]; return *this; } @@ -46,8 +44,6 @@ bool Gradient::operator==( const Gradient& other ) const noexcept && ( m_values[1] == other.m_values[1] ) && ( m_values[2] == other.m_values[2] ) && ( m_values[3] == other.m_values[3] ) - && ( m_values[4] == other.m_values[4] ) - && ( m_values[5] == other.m_values[5] ) && ( m_stops == other.m_stops ); } @@ -223,28 +219,11 @@ void RadialGradient::setCenter( qreal x, qreal y ) noexcept m_values[1] = y; } -void RadialGradient::setFocalPoint( const QPointF& focalPoint ) noexcept -{ - m_values[3] = focalPoint.x(); - m_values[4] = focalPoint.y(); -} - -void RadialGradient::setFocalPoint( qreal x, qreal y ) noexcept -{ - m_values[3] = x; - m_values[4] = y; -} - -void RadialGradient::setCenterRadius( qreal radius ) noexcept +void RadialGradient::setRadius( qreal radius ) noexcept { m_values[2] = radius; } -void RadialGradient::setFocalRadius( qreal radius ) noexcept -{ - m_values[5] = radius; -} - void ConicGradient::setCenter( const QPointF& center ) noexcept { m_values[0] = center.x(); @@ -257,7 +236,12 @@ void ConicGradient::setCenter( qreal x, qreal y ) noexcept m_values[1] = y; } -void ConicGradient::setDegrees( qreal degrees ) noexcept +void ConicGradient::setStartAngle( qreal degrees ) noexcept { m_values[2] = degrees; } + +void ConicGradient::setSpanAngle( qreal degrees ) noexcept +{ + m_values[3] = qBound( -360.0, degrees, 360.0 ); +} diff --git a/playground/shapes/Gradient.h b/playground/shapes/Gradient.h index ea25992c..3b1d40f7 100644 --- a/playground/shapes/Gradient.h +++ b/playground/shapes/Gradient.h @@ -37,8 +37,8 @@ class Gradient bool isMonochrome() const; bool isVisible() const; - void setStops( const QVector< QskGradientStop >& ); - const QVector< QskGradientStop >& stops() const noexcept; + void setStops( const QskGradientStops& ); + const QskGradientStops& stops() const noexcept; void setStops( QGradient::Preset ); void setStops( const QGradientStops& ); @@ -63,22 +63,28 @@ class Gradient friend class ConicGradient; Gradient( QGradient::Type ) noexcept; - Gradient( QGradient::Type, - qreal, qreal, qreal, qreal, qreal, qreal ) noexcept; + Gradient( QGradient::Type, qreal, qreal, qreal, qreal ) noexcept; - QVector< QskGradientStop > m_stops; + QskGradientStops m_stops; /* - Linear: x1, y1, x2, y2, n/a, n/a - Radial: centerX, centerY, centerRadius, focalX, focalY, focalRadius - Conic: centerX, centerY, degrees, n/a, n/a, n/a + Linear: x1, y1, x2, y2 + Radial: centerX, centerY, radius, n/a + Conic: centerX, centerY, startAngle, spanAngle */ - qreal m_values[6] = {}; + qreal m_values[4] = {}; QGradient::Type m_type = QGradient::NoGradient; QGradient::Spread m_spread = QGradient::PadSpread; }; +#ifndef QT_NO_DEBUG_STREAM + +class QDebug; +QDebug operator<<( QDebug, const QskGradient& ); + +#endif + class LinearGradient : public Gradient { public: @@ -96,13 +102,6 @@ class LinearGradient : public Gradient QPointF stop() const noexcept; }; -#ifndef QT_NO_DEBUG_STREAM - -class QDebug; -QDebug operator<<( QDebug, const Gradient& ); - -#endif - class RadialGradient : public Gradient { public: @@ -111,40 +110,34 @@ class RadialGradient : public Gradient RadialGradient( const QPointF& center, qreal radius ) noexcept; RadialGradient( qreal cx, qreal cy, qreal radius ) noexcept; - RadialGradient( const QPointF& center, qreal centerRadius, - const QPointF& focalPoint, qreal focalRadius = 0.0 ) noexcept; - - RadialGradient(qreal cx, qreal cy, qreal centerRadius, - qreal fx, qreal fy, qreal focalRadius = 0.0 ) noexcept; - QPointF center() const noexcept; void setCenter(const QPointF& center) noexcept; void setCenter(qreal x, qreal y) noexcept; - QPointF focalPoint() const noexcept; - void setFocalPoint( const QPointF& focalPoint ) noexcept; - void setFocalPoint( qreal x, qreal y ) noexcept; - - qreal centerRadius() const noexcept; - void setCenterRadius( qreal radius ) noexcept; - - qreal focalRadius() const noexcept; - void setFocalRadius( qreal radius ) noexcept; + qreal radius() const noexcept; + void setRadius( qreal radius ) noexcept; }; class ConicGradient : public Gradient { public: ConicGradient() noexcept; - ConicGradient( const QPointF&, qreal degrees ) noexcept; - ConicGradient( qreal cx, qreal cy, qreal degrees ) noexcept; + + ConicGradient( const QPointF&, + qreal startAngle = 0.0, qreal spanAngle = 360.0 ) noexcept; + + ConicGradient( qreal cx, qreal cy, + qreal startAngle = 0.0, qreal spanAngle = 360.0 ) noexcept; QPointF center() const noexcept; void setCenter(const QPointF& center) noexcept; void setCenter(qreal x, qreal y) noexcept; - qreal degrees() const noexcept; - void setDegrees(qreal ) noexcept; + qreal startAngle() const noexcept; + void setStartAngle( qreal ) noexcept; + + qreal spanAngle() const noexcept; + void setSpanAngle( qreal ) noexcept; }; inline Gradient::Gradient( QGradient::Type type ) noexcept @@ -153,9 +146,8 @@ inline Gradient::Gradient( QGradient::Type type ) noexcept } inline Gradient::Gradient( QGradient::Type type, - qreal v1, qreal v2, qreal v3, - qreal v4 = 0.0, qreal v5 = 0.0, qreal v6 = 0.0 ) noexcept - : m_values{ v1, v2, v3, v4, v5, v6 } + qreal v1, qreal v2, qreal v3, qreal v4 ) noexcept + : m_values{ v1, v2, v3, v4 } , m_type( type ) { } @@ -175,7 +167,7 @@ inline bool Gradient::isValid() const noexcept return m_type != QGradient::NoGradient; } -inline const QVector< QskGradientStop >& Gradient::stops() const noexcept +inline const QskGradientStops& Gradient::stops() const noexcept { return m_stops; } @@ -213,15 +205,7 @@ inline QPointF LinearGradient::stop() const noexcept } inline RadialGradient::RadialGradient() noexcept - : Gradient( QGradient::RadialGradient, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 ) -{ -} - -inline RadialGradient::RadialGradient( - const QPointF& center, qreal radius, - const QPointF& focalPoint, qreal focalRadius ) noexcept - : RadialGradient( center.x(), center.y(), radius, - focalPoint.x(), focalPoint.y(), focalRadius ) + : Gradient( QGradient::RadialGradient, 0.5, 0.5, 0.5, 0.0 ) { } @@ -233,14 +217,7 @@ inline RadialGradient::RadialGradient( inline RadialGradient::RadialGradient( qreal cx, qreal cy, qreal radius ) noexcept - : RadialGradient( cx, cy, radius, cx, cy, 0.0 ) -{ -} - -inline RadialGradient::RadialGradient( - qreal cx, qreal cy, qreal radius, - qreal fx, qreal fy, qreal focalRadius ) noexcept - : Gradient( QGradient::RadialGradient, cx, cy, radius, fx, fy, focalRadius ) + : Gradient( QGradient::RadialGradient, cx, cy, radius, 0.0 ) { } @@ -249,35 +226,25 @@ inline QPointF RadialGradient::center() const noexcept return QPointF( m_values[0], m_values[1] ); } -inline qreal RadialGradient::centerRadius() const noexcept +inline qreal RadialGradient::radius() const noexcept { return m_values[2]; } -inline QPointF RadialGradient::focalPoint() const noexcept -{ - return QPointF( m_values[3], m_values[4] ); -} - -inline qreal RadialGradient::focalRadius() const noexcept -{ - return m_values[5]; -} - inline ConicGradient::ConicGradient() noexcept - : Gradient( QGradient::ConicalGradient, 0.0, 0.0, 0.0 ) + : Gradient( QGradient::ConicalGradient, 0.0, 0.0, 0.0, 0.0 ) { } inline ConicGradient::ConicGradient( - const QPointF& center, qreal degrees ) noexcept - : ConicGradient( center.x(), center.y(), degrees ) + const QPointF& center, qreal startAngle, qreal spanAngle ) noexcept + : ConicGradient( center.x(), center.y(), startAngle, spanAngle ) { } inline ConicGradient::ConicGradient( - qreal cx, qreal cy, qreal degrees ) noexcept - : Gradient( QGradient::ConicalGradient, cx, cy, degrees ) + qreal cx, qreal cy, qreal startAngle, qreal spanAngle ) noexcept + : Gradient( QGradient::ConicalGradient, cx, cy, startAngle, spanAngle ) { } @@ -286,7 +253,12 @@ inline QPointF ConicGradient::center() const noexcept return QPointF( m_values[0], m_values[1] ); } -inline qreal ConicGradient::degrees() const noexcept +inline qreal ConicGradient::startAngle() const noexcept { return m_values[2]; } + +inline qreal ConicGradient::spanAngle() const noexcept +{ + return m_values[3]; +} diff --git a/playground/shapes/ShapeItem.cpp b/playground/shapes/ShapeItem.cpp index c5d7bd73..1d3d6209 100644 --- a/playground/shapes/ShapeItem.cpp +++ b/playground/shapes/ShapeItem.cpp @@ -67,20 +67,11 @@ namespace { const auto& g = gradient.asLinearGradient(); - const qreal x1 = rect.left() + g.start().x() * rect.width(); - const qreal y1 = rect.top() + g.start().y() * rect.height(); - - const qreal x2 = rect.left() + g.stop().x() * rect.width(); - const qreal y2 = rect.top() + g.stop().y() * rect.height(); - -#if 0 - QTransform t2( rect.width(), 0, 0, rect.height(), rect.x(), rect.y()); -#endif - QLinearGradient qgradient( x1, y1, x2, y2 ); + QLinearGradient qgradient( g.start(), g.stop() ); qgradient.setSpread( g.spread() ); qgradient.setStops( g.qtStops() ); - updateNode( path, transform, &qgradient ); + updateNode( path, transform, rect, &qgradient ); break; } @@ -88,19 +79,11 @@ namespace { const auto& g = gradient.asRadialGradient(); - const qreal x = rect.left() + g.center().x() * rect.width(); - const qreal y = rect.top() + g.center().y() * rect.height(); - const qreal r = g.centerRadius() * qMin( rect.width(), rect.height() ); - - const qreal fx = rect.left() + g.focalPoint().x() * rect.width(); - const qreal fy = rect.top() + g.focalPoint().y() * rect.height(); - const qreal fr = g.focalRadius() * qMin( rect.width(), rect.height() ); - - QRadialGradient qgradient( x, y, r, fx, fy, fr ); + QRadialGradient qgradient( g.center(), g.radius() ); qgradient.setSpread( g.spread() ); qgradient.setStops( g.qtStops() ); - updateNode( path, transform, &qgradient ); + updateNode( path, transform, rect, &qgradient ); break; } @@ -108,14 +91,16 @@ namespace { const auto& g = gradient.asConicGradient(); - const qreal x = rect.left() + g.center().x() * rect.width(); - const qreal y = rect.top() + g.center().y() * rect.height(); - - QConicalGradient qgradient( x, y, g.degrees() ); - //qgradient.setSpread( g.spread() ); + QConicalGradient qgradient( g.center(), g.startAngle() ); + qgradient.setSpread( g.spread() ); qgradient.setStops( g.qtStops() ); - updateNode( path, transform, &qgradient ); + /* + Once ConicGradient has become QskConicGradient we do not + need QConicalGradient anymore and passing the spanAngle + as extra parameter can go away. + */ + updateNode( path, transform, rect, &qgradient, g.spanAngle() ); break; } diff --git a/playground/shapes/main.cpp b/playground/shapes/main.cpp index 5311d74c..302a2074 100644 --- a/playground/shapes/main.cpp +++ b/playground/shapes/main.cpp @@ -4,57 +4,64 @@ *****************************************************************************/ #include "ShapeItem.h" +#include "Gradient.h" #include #include #include #include +#include #include #include #include +#include namespace { - QPainterPath path( SkinnyShapeFactory::Shape shape ) - { - return SkinnyShapeFactory::shapePath( shape, QSizeF( 50, 50 ) ); - } - - class Pen : public QPen + class Page : public QskLinearBox { public: - Pen( const QColor& color ) - : QPen( color ) + Page( QQuickItem* parent = nullptr ) + : QskLinearBox( Qt::Horizontal, 2, parent ) { - //setCosmetic( true ); - setWidth( isCosmetic() ? 8 : 2 ); - - setJoinStyle( Qt::MiterJoin ); - - //setStyle( Qt::NoPen ); - //setStyle( Qt::DashLine ); - - //setAlpha( 100 ); } - void setAlpha( int alpha ) + protected: + static QPen pen( const QColor& color ) { - setColor( QskRgb::toTransparent( color(), alpha ) ); + QPen p( color ); +#if 0 + p.setCosmetic( true ); +#endif + + p.setWidth( p.isCosmetic() ? 8 : 2 ); + p.setJoinStyle( Qt::MiterJoin ); + +#if 0 + p.setStyle( Qt::DashLine ); + p.setColor( QskRgb::toTransparent( color(), alpha ) ); +#endif + return p; + } + + static QPainterPath path( SkinnyShapeFactory::Shape shape ) + { + return SkinnyShapeFactory::shapePath( shape, QSizeF( 50, 50 ) ); } }; - class Box : public QskLinearBox + class LinearGradientPage : public Page { public: - Box( QQuickItem* parent = nullptr ) - : QskLinearBox( Qt::Horizontal, 2, parent ) + LinearGradientPage( QQuickItem* parent = nullptr ) + : Page( parent ) { { auto shapeItem = new ShapeItem( this ); shapeItem->setPath( path( SkinnyShapeFactory::Hexagon ) ); - shapeItem->setPen( Pen( QColorConstants::Svg::indigo ) ); + shapeItem->setPen( pen( QColorConstants::Svg::indigo ) ); LinearGradient gradient( 0.0, 0.0, 0.2, 0.5 ); gradient.setSpread( QGradient::ReflectSpread ); @@ -62,14 +69,36 @@ namespace shapeItem->setGradient( gradient ); } + } + }; + class RadialGradientPage : public Page + { + public: + RadialGradientPage( QQuickItem* parent = nullptr ) + : Page( parent ) + { + { + auto shapeItem = new ShapeItem( this ); + + shapeItem->setPath( path( SkinnyShapeFactory::Rectangle ) ); + shapeItem->setPen( pen( QColorConstants::Svg::indigo ) ); + + RadialGradient gradient( 0.5, 0.5, 0.5 ); + + gradient.setSpread( QGradient::PadSpread ); + gradient.setStops( QColorConstants::Svg::lightyellow, + QColorConstants::Svg::midnightblue ); + + shapeItem->setGradient( gradient ); + } { auto shapeItem = new ShapeItem( this ); shapeItem->setPath( path( SkinnyShapeFactory::Ellipse ) ); RadialGradient gradient( 0.5, 0.5, 0.5 ); - gradient.setSpread( QGradient::RepeatSpread ); + gradient.setSpread( QGradient::PadSpread ); QVector< QskGradientStop > stops; @@ -88,29 +117,101 @@ namespace shapeItem->setGradient( gradient ); } - { auto shapeItem = new ShapeItem( this ); - shapeItem->setPath( path( SkinnyShapeFactory::Arc ) ); + shapeItem->setPath( path( SkinnyShapeFactory::Rectangle ) ); + shapeItem->setPen( pen( QColorConstants::Svg::indigo ) ); - ConicGradient gradient( 0.5, 0.5, -60.0 ); - gradient.setStops( QGradient::BurningSpring ); + RadialGradient gradient( 0.5, 0.5, 0.25 ); + gradient.setCenter( 0.5, 0.7 ); + + gradient.setSpread( QGradient::RepeatSpread ); + gradient.setStops( QGradient::LilyMeadow ); shapeItem->setGradient( gradient ); } + { + auto shapeItem = new ShapeItem( this ); + shapeItem->setPath( path( SkinnyShapeFactory::Rectangle ) ); + shapeItem->setPen( pen( QColorConstants::Svg::indigo ) ); + + RadialGradient gradient( 0.6, 0.4, 0.1 ); + + gradient.setSpread( QGradient::ReflectSpread ); + gradient.setStops( Qt::red, Qt::blue ); + + shapeItem->setGradient( gradient ); + } + } + }; + + class ConicGradientPage : public Page + { + public: + ConicGradientPage( QQuickItem* parent = nullptr ) + : Page( parent ) + { { auto shapeItem = new ShapeItem( this ); shapeItem->setPath( path( SkinnyShapeFactory::Ellipse ) ); - RadialGradient gradient( 0.5, 0.5, 0.5 ); - gradient.setSpread( QGradient::RepeatSpread ); - gradient.setStops( QGradient::DirtyBeauty ); + ConicGradient gradient( 0.5, 0.5, 30.0, 60.0 ); + gradient.setSpread( QGradient::ReflectSpread ); + gradient.setStops( QGradient::JuicyPeach ); shapeItem->setGradient( gradient ); } + { + auto shapeItem = new ShapeItem( this ); + + shapeItem->setPath( path( SkinnyShapeFactory::TriangleUp ) ); + + ConicGradient gradient( 0.5, 0.5, 30.0, 60.0 ); + gradient.setSpread( QGradient::RepeatSpread ); + gradient.setStops( QGradient::WinterNeva ); + + shapeItem->setGradient( gradient ); + } + { + auto shapeItem = new ShapeItem( this ); + + shapeItem->setPath( path( SkinnyShapeFactory::Arc ) ); + + ConicGradient gradient( 0.5, 0.5, 300.0, -240.0 ); + gradient.setStops( QGradient::SpikyNaga ); + + shapeItem->setGradient( gradient ); + } + { + auto shapeItem = new ShapeItem( this ); + + shapeItem->setPath( path( SkinnyShapeFactory::Diamond ) ); + + ConicGradient gradient( 0.5, 0.5, 45.0, 180.0 ); + gradient.setStops( QGradient::FabledSunset ); + gradient.setSpread( QGradient::ReflectSpread ); + + shapeItem->setGradient( gradient ); + } + } + }; + + class TabView : public QskTabView + { + public: + TabView( QQuickItem* parentItem = nullptr ) + : QskTabView( parentItem ) + { + setMargins( 10 ); + setAutoFitTabs( true ); + setTabBarEdge( Qt::TopEdge ); + + addTab( "Radial Gradients", new RadialGradientPage() ); + addTab( "Conic Gradients", new ConicGradientPage() ); + addTab( "Linear Gradients", new LinearGradientPage() ); } }; } @@ -127,7 +228,7 @@ int main( int argc, char* argv[] ) QskWindow window; window.setColor( Qt::gray ); - window.addItem( new Box() ); + window.addItem( new TabView() ); window.resize( 800, 600 ); window.show(); diff --git a/src/nodes/QskGradientMaterial.cpp b/src/nodes/QskGradientMaterial.cpp index f9a4da8c..8f423cc6 100644 --- a/src/nodes/QskGradientMaterial.cpp +++ b/src/nodes/QskGradientMaterial.cpp @@ -1,13 +1,22 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + #include "QskGradientMaterial.h" #include "QskFunctions.h" #include "QskRgbValue.h" +#include + QSK_QT_PRIVATE_BEGIN #include #include #include QSK_QT_PRIVATE_END +#include + // RHI shaders are supported by Qt 5.15 and Qt 6.x #define SHADER_RHI @@ -23,106 +32,33 @@ QSK_QT_PRIVATE_END using RhiShader = QSGMaterialShader; #endif -/* - The shaders for the gradient are implemented in the quickshapes module - Beside them we do not need this module. - */ - -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) - - QSK_QT_PRIVATE_BEGIN - #ifndef signals - #define signals Q_SIGNALS - #endif - #include - QSK_QT_PRIVATE_END - - static void QQuickShapes_initializeModule() - { - QQuickShapesModule::defineModule(); - } - -#else - extern void QQuickShapes_initializeModule(); -#endif - -Q_CONSTRUCTOR_FUNCTION( QQuickShapes_initializeModule ) - namespace { - /* - Qt offers QGradient compatible shaders in the quickshapes module. - So why reimplementing the wheel ... - - Those shaders ( f.e lineargradient.frag ) want to have a lookup table - with the interpolated colors, being uploaded as a texture. - A 1 dimensional 256x1 texture is how Chrome, Firefox, and Android render - gradients - so let's do the same. - */ - class GradientImage : public QImage - { - public: - GradientImage( const QGradientStops& stops ) - : QImage( 256, 1, QImage::Format_RGBA8888_Premultiplied ) - { - constexpr int numColors = 256; - auto colorTable = reinterpret_cast< uint* >( bits() ); - - int index1, index2; - QRgb rgb1, rgb2; - - index1 = index2 = qRound( stops[0].first * numColors ); - rgb1 = rgb2 = stops[0].second.rgba(); - - if ( index1 > 0 ) - { - const auto v = value( rgb1 ); - - for ( int i = 0; i < index1; i++ ) - colorTable[i] = v; - } - - for ( int i = 1; i < stops.count(); i++ ) - { - const auto& stop = stops[i]; - - index2 = qRound( stop.first * numColors ); - rgb2 = stop.second.rgba(); - - const auto n = index2 - index1; - - for ( int j = 0; j < n; j++ ) - { - const auto rgb = QskRgb::interpolated( rgb1, rgb2, qreal( j ) / n ); - colorTable[ index1 + j] = value( rgb ); - } - - index1 = index2; - rgb1 = rgb2; - } - - if ( index1 < numColors - 1 ) - { - const auto v = value( rgb1 ); - - for ( int i = index1; i < numColors ; i++ ) - colorTable[i] = v; - } - } - - private: - inline uint value( const QRgb rgb ) const - { - return ARGB2RGBA( qPremultiply( rgb ) ); - } - }; - class GradientTexture : public QSGPlainTexture { public: GradientTexture( const QGradientStops& stops, QGradient::Spread spread ) { - setImage( GradientImage( stops ) ); +#if 1 + /* + Once we got rid of QGradient we will have QskGradientStops + ( like in the gradients branch ). For the moment we have to copy + */ + + QskGradientStops qskStops; + qskStops.reserve( stops.size() ); + + for ( const auto& s : stops ) + qskStops += QskGradientStop( s.first, s.second ); +#endif + /* + Qt creates tables of 1024 colors, while Chrome, Firefox, and Android + seem to use 256 colors only ( according to maybe outdated sources + from the internet ), + */ + + + setImage( QskRgb::colorTable( 256, qskStops ) ); const auto wrapMode = this->wrapMode( spread ); @@ -183,10 +119,9 @@ namespace s_instance = new TextureCache(); /* - For OpenGL we coud fiddle around with QOpenGLSharedResource - while with RHI we would have QRhi::addCleanupCallback - - But let's keep things simple for the moment. TODO ... + For RHI we have QRhi::addCleanupCallback, but with + OpenGL we have to fiddle around with QOpenGLSharedResource + So let's keep things simple for the moment. TODO ... */ qAddPostRoutine( cleanup ); } @@ -209,6 +144,17 @@ namespace { texture = new GradientTexture( stops, spread ); m_hashTable[ key ] = texture; + + if ( rhi != nullptr ) + { + auto myrhi = ( QRhi* )rhi; + + if ( !m_rhiTable.contains( myrhi ) ) + { + myrhi->addCleanupCallback( TextureCache::cleanupRhi ); + m_rhiTable += myrhi; + } + } } return texture; @@ -220,7 +166,29 @@ namespace delete instance(); } + static void cleanupRhi( const QRhi *rhi ) + { + auto cache = instance(); + + auto& table = cache->m_hashTable; + for ( auto it = table.begin(); it != table.end(); ) + { + if ( it.key().rhi == rhi ) + { + delete it.value(); + it = table.erase( it ); + } + else + { + ++it; + } + } + + cache->m_rhiTable.removeAll( rhi ); + } + QHash< TextureHashKey, GradientTexture* > m_hashTable; + QVector< const QRhi* > m_rhiTable; }; } @@ -269,7 +237,7 @@ namespace public: void setShaderFiles( const char* name ) { - static const QString root( ":/qt-project.org/shapes/shaders/" ); + static const QString root( ":/qskinny/shaders/" ); setShaderSourceFile( QOpenGLShader::Vertex, root + name + ".vert" ); setShaderSourceFile( QOpenGLShader::Fragment, root + name + ".frag" ); @@ -320,7 +288,7 @@ namespace public: void setShaderFiles( const char* name ) { - static const QString root( ":/qt-project.org/shapes/shaders_ng/" ); + static const QString root( ":/qskinny/shaders/" ); setShaderFileName( VertexStage, root + name + ".vert.qsb" ); setShaderFileName( FragmentStage, root + name + ".frag.qsb" ); @@ -359,29 +327,35 @@ namespace { } - bool setGradient( const QLinearGradient* gradient ) + bool setGradient( const QRectF& rect, const QLinearGradient& gradient ) { bool changed = false; - if ( gradient->stops() != stops() ) + if ( gradient.stops() != stops() ) { - setStops( gradient->stops() ); + setStops( gradient.stops() ); changed = true; } - if ( gradient->spread() != spread() ) + if ( gradient.spread() != spread() ) { - setSpread( gradient->spread() ); + setSpread( gradient.spread() ); changed = true; } - const QVector2D start( gradient->start() ); - const QVector2D stop( gradient->finalStop() ); +#if 0 + QTransform transform( rect.width(), 0, 0, rect.height(), rect.x(), rect.y()); +#endif - if ( m_start != start || m_stop != stop ) + const QVector4D gradientRect( + rect.left() + gradient.start().x() * rect.width(), + rect.top() + gradient.start().y() * rect.height(), + gradient.finalStop().x() * rect.width(), + gradient.finalStop().y() * rect.height() ); + + if ( m_gradientRect != gradientRect ) { - m_start = start; - m_stop = stop; + m_gradientRect = gradientRect; changed = true; } @@ -398,7 +372,7 @@ namespace { const auto mat = static_cast< const LinearMaterial* >( other ); - if ( ( m_start != mat->m_start ) || ( m_stop != mat->m_stop ) ) + if ( m_gradientRect != mat->m_gradientRect ) return QSGMaterial::compare( other ); else return GradientMaterial::compare( other ); @@ -406,8 +380,7 @@ namespace QSGMaterialShader* createShader() const override; - QVector2D m_start; - QVector2D m_stop; + QVector4D m_gradientRect; }; #ifdef SHADER_GL @@ -416,28 +389,23 @@ namespace public: LinearShaderGL() { - setShaderFiles( "lineargradient" ); + setShaderFiles( "gradientlinear" ); } void initialize() override { GradientShaderGL::initialize(); - - m_startId = program()->uniformLocation( "gradStart" ); - m_stopId = program()->uniformLocation( "gradEnd" ); + m_rectId = program()->uniformLocation( "rect" ); } void updateUniformValues( const GradientMaterial* newMaterial ) override { auto material = static_cast< const LinearMaterial* >( newMaterial ); - - program()->setUniformValue( m_startId, material->m_start ); - program()->setUniformValue( m_stopId, material->m_stop ); + program()->setUniformValue( m_rectId, material->m_gradientRect ); } private: - int m_startId = -1; - int m_stopId = -1; + int m_rectId = -1; }; #endif @@ -447,7 +415,7 @@ namespace public: LinearShaderRhi() { - setShaderFiles( "lineargradient" ); + setShaderFiles( "gradientlinear" ); } bool updateUniformData( RenderState& state, @@ -469,15 +437,9 @@ namespace changed = true; } - if ( matOld == nullptr || matNew->m_start != matOld->m_start ) + if ( matOld == nullptr || matNew->m_gradientRect != matOld->m_gradientRect ) { - memcpy( data + 64, &matNew->m_start, 8 ); - changed = true; - } - - if ( matOld == nullptr || matNew->m_stop != matOld->m_stop ) - { - memcpy( data + 72, &matNew->m_stop, 8 ); + memcpy( data + 64, &matNew->m_gradientRect, 16 ); changed = true; } @@ -520,40 +482,35 @@ namespace return &type; } - bool setGradient( const QRadialGradient* gradient ) + bool setGradient( const QRectF& rect, const QRadialGradient& gradient ) { bool changed = false; - if ( gradient->stops() != stops() ) + if ( gradient.stops() != stops() ) { - setStops( gradient->stops() ); + setStops( gradient.stops() ); changed = true; } - if ( gradient->spread() != spread() ) + if ( gradient.spread() != spread() ) { - setSpread( gradient->spread() ); + setSpread( gradient.spread() ); changed = true; } - const QVector2D focalToCenter( gradient->center() - gradient->focalPoint() ); - const float centerRadius = gradient->centerRadius(); + const auto& center = gradient.center(); + const auto r = gradient.radius(); - const QVector2D focalPoint( gradient->focalPoint() ); - const float focalRadius = gradient->focalRadius(); + const QVector2D pos( + rect.left() + center.x() * rect.width(), + rect.top() + center.y() * rect.height() ); - if ( ( focalPoint != m_focalPoint ) || ( focalRadius != m_focalRadius ) ) + const QVector2D radius( r * rect.width(), r * rect.height() ); + + if ( ( pos != m_center ) || ( m_radius != radius ) ) { - m_focalPoint = focalPoint; - m_focalRadius = focalRadius; - - changed = true; - } - - if ( ( focalToCenter != m_focalToCenter ) || ( m_centerRadius != centerRadius ) ) - { - m_focalToCenter = focalToCenter; - m_centerRadius = centerRadius; + m_center = pos; + m_radius = radius; changed = true; } @@ -565,10 +522,7 @@ namespace { const auto mat = static_cast< const RadialMaterial* >( other ); - if ( ( m_focalPoint != mat->m_focalPoint ) - || ( m_focalToCenter != mat->m_focalToCenter ) - || qskFuzzyCompare( m_centerRadius, mat->m_centerRadius ) - || qskFuzzyCompare( m_focalRadius, mat->m_focalRadius ) ) + if ( ( m_center != mat->m_center ) || ( m_radius != mat->m_radius ) ) { return QSGMaterial::compare( other ); } @@ -580,10 +534,8 @@ namespace QSGMaterialShader* createShader() const override; - QVector2D m_focalPoint; - QVector2D m_focalToCenter; - float m_centerRadius = 0.0; - float m_focalRadius = 0.0; + QVector2D m_center; + QVector2D m_radius; }; #ifdef SHADER_GL @@ -592,7 +544,7 @@ namespace public: RadialShaderGL() { - setShaderFiles( "radialgradient" ); + setShaderFiles( "gradientradial" ); } void initialize() override @@ -601,10 +553,8 @@ namespace auto p = program(); - m_focalPointId = p->uniformLocation( "translationPoint" ); - m_focalToCenterId = p->uniformLocation( "focalToCenter" ); - m_centerRadiusId = p->uniformLocation( "centerRadius" ); - m_focalRadiusId = p->uniformLocation( "focalRadius" ); + m_centerCoordId = p->uniformLocation( "centerCoord" ); + m_radiusId = p->uniformLocation( "radius" ); } void updateUniformValues( const GradientMaterial* newMaterial ) override @@ -613,17 +563,13 @@ namespace auto p = program(); - p->setUniformValue( m_focalToCenterId, material->m_focalToCenter ); - p->setUniformValue( m_centerRadiusId, material->m_centerRadius); - p->setUniformValue( m_focalRadiusId, material->m_focalRadius); - p->setUniformValue( m_focalPointId, material->m_focalPoint); + p->setUniformValue( m_centerCoordId, material->m_center ); + p->setUniformValue( m_radiusId, material->m_radius ); } private: - int m_focalToCenterId = -1; - int m_focalPointId = -1; - int m_centerRadiusId = -1; - int m_focalRadiusId = -1; + int m_centerCoordId = -1; + int m_radiusId = -1; }; #endif @@ -633,7 +579,7 @@ namespace public: RadialShaderRhi() { - setShaderFiles( "radialgradient" ); + setShaderFiles( "gradientradial" ); } bool updateUniformData( RenderState& state, @@ -642,7 +588,7 @@ namespace auto matNew = static_cast< RadialMaterial* >( newMaterial ); auto matOld = static_cast< RadialMaterial* >( oldMaterial ); - Q_ASSERT( state.uniformData()->size() >= 92 ); + Q_ASSERT( state.uniformData()->size() >= 84 ); auto data = state.uniformData()->data(); bool changed = false; @@ -655,34 +601,22 @@ namespace changed = true; } - if ( matOld == nullptr || matNew->m_focalPoint != matOld->m_focalPoint ) + if ( matOld == nullptr || matNew->m_center != matOld->m_center ) { - memcpy( data + 64, &matNew->m_focalPoint, 8 ); + memcpy( data + 64, &matNew->m_center, 8 ); changed = true; } - if ( matOld == nullptr || matNew->m_focalToCenter != matOld->m_focalToCenter ) + if ( matOld == nullptr || matNew->m_radius != matOld->m_radius ) { - memcpy( data + 72, &matNew->m_focalToCenter, 8 ); - changed = true; - } - - if ( matOld == nullptr || matNew->m_centerRadius != matOld->m_centerRadius ) - { - memcpy( data + 80, &matNew->m_centerRadius, 4); - changed = true; - } - - if ( matOld == nullptr || matNew->m_focalRadius != matOld->m_focalRadius ) - { - memcpy( data + 84, &matNew->m_focalRadius, 4 ); + memcpy( data + 72, &matNew->m_radius, 8 ); changed = true; } if ( state.isOpacityDirty() ) { const float opacity = state.opacity(); - memcpy( data + 88, &opacity, 4 ); + memcpy( data + 80, &opacity, 4 ); changed = true; } @@ -719,23 +653,44 @@ namespace return &type; } - bool setGradient( const QConicalGradient* gradient ) + bool setGradient( const QRectF& rect, const QConicalGradient& gradient, qreal spanAngle ) { bool changed = false; - if ( gradient->stops() != stops() ) + if ( gradient.stops() != stops() ) { - setStops( gradient->stops() ); + setStops( gradient.stops() ); changed = true; } - const QVector2D center( gradient->center() ); - const float radians = -qDegreesToRadians( gradient->angle() ); + if ( gradient.spread() != spread() ) + { + setSpread( gradient.spread() ); + changed = true; + } - if ( center != m_center || radians != m_radians ) + const QVector2D center( + rect.left() + gradient.center().x() * rect.width(), + rect.top() + gradient.center().y() * rect.height() ); + + // Angles as ratio of a rotation + + float start = fmod( gradient.angle(), 360.0 ) / 360.0; + if ( start < 0.0) + start += 1.0; + + const float span = fmod( spanAngle, 360.0 ) / 360.0; + + if ( center != m_center ) { m_center = center; - m_radians = radians; + changed = true; + } + + if ( ( start != m_start ) || ( span != m_span ) ) + { + m_start = start; + m_span = span; changed = true; } @@ -747,16 +702,21 @@ namespace { const auto mat = static_cast< const ConicMaterial* >( other ); - if ( ( m_center != mat->m_center ) || qskFuzzyCompare( m_radians, mat->m_radians ) ) + if ( ( m_center != mat->m_center ) + || qskFuzzyCompare( m_start, mat->m_start ) + || qskFuzzyCompare( m_span, mat->m_span ) ) + { return QSGMaterial::compare( other ); - else - return GradientMaterial::compare( other ); + } + + return GradientMaterial::compare( other ); } QSGMaterialShader* createShader() const override; QVector2D m_center; - float m_radians = 0.0; + float m_start = 0.0; + float m_span = 1.0; }; #ifdef SHADER_GL @@ -765,28 +725,31 @@ namespace public: ConicShaderGL() { - setShaderFiles( "conicalgradient" ); + setShaderFiles( "gradientconic" ); } void initialize() override { GradientShaderGL::initialize(); - m_radiansId = program()->uniformLocation( "angle" ); - m_centerPointId = program()->uniformLocation( "translationPoint" ); + m_centerCoordId = program()->uniformLocation( "centerCoord" ); + m_startId = program()->uniformLocation( "start" ); + m_spanId = program()->uniformLocation( "span" ); } void updateUniformValues( const GradientMaterial* newMaterial ) override { auto material = static_cast< const ConicMaterial* >( newMaterial ); - program()->setUniformValue( m_radiansId, material->m_radians ); - program()->setUniformValue( m_centerPointId, material->m_center ); + program()->setUniformValue( m_centerCoordId, material->m_center ); + program()->setUniformValue( m_startId, material->m_start ); + program()->setUniformValue( m_spanId, material->m_span ); } private: - int m_radiansId = -1; - int m_centerPointId = -1; + int m_centerCoordId = -1; + int m_startId = -1; + int m_spanId = -1; }; #endif @@ -796,7 +759,7 @@ namespace public: ConicShaderRhi() { - setShaderFiles( "conicalgradient" ); + setShaderFiles( "gradientconic" ); } bool updateUniformData( RenderState& state, @@ -805,7 +768,7 @@ namespace auto matNew = static_cast< ConicMaterial* >( newMaterial ); auto matOld = static_cast< ConicMaterial* >( oldMaterial ); - Q_ASSERT( state.uniformData()->size() >= 80 ); + Q_ASSERT( state.uniformData()->size() >= 84 ); auto data = state.uniformData()->data(); bool changed = false; @@ -824,16 +787,22 @@ namespace changed = true; } - if ( matOld == nullptr || matNew->m_radians != matOld->m_radians ) + if ( matOld == nullptr || matNew->m_start != matOld->m_start ) { - memcpy( data + 72, &matNew->m_radians, 4 ); + memcpy( data + 72, &matNew->m_start, 4 ); + changed = true; + } + + if ( matOld == nullptr || matNew->m_span != matOld->m_span ) + { + memcpy( data + 76, &matNew->m_span, 4 ); changed = true; } if ( state.isOpacityDirty() ) { const float opacity = state.opacity(); - memcpy( data + 76, &opacity, 4 ); + memcpy( data + 80, &opacity, 4 ); changed = true; } @@ -867,31 +836,42 @@ inline Material* qskEnsureMaterial( QskGradientMaterial* material ) return static_cast< Material* >( material ); } -bool QskGradientMaterial::updateGradient( const QGradient* gradient ) +bool QskGradientMaterial::updateGradient( + const QRectF& rect, const QGradient* g, qreal extraValue ) { - Q_ASSERT( gradient && gradient->type() == m_gradientType ); + Q_ASSERT( g ); - if ( gradient == nullptr || gradient->type() != m_gradientType ) + if ( g == nullptr ) return false; - switch ( static_cast< int >( gradient->type() ) ) + auto& gradient = *g; + + Q_ASSERT( gradient.type() == m_gradientType ); + + if ( gradient.type() != m_gradientType ) + return false; + + switch ( static_cast< int >( gradient.type() ) ) { case QGradient::LinearGradient: { auto material = static_cast< LinearMaterial* >( this ); - return material->setGradient( static_cast< const QLinearGradient* >( gradient ) ); + return material->setGradient( rect, + *reinterpret_cast< const QLinearGradient* >( g ) ); } case QGradient::RadialGradient: { auto material = static_cast< RadialMaterial* >( this ); - return material->setGradient( static_cast< const QRadialGradient* >( gradient ) ); + return material->setGradient( rect, + *reinterpret_cast< const QRadialGradient* >( g ) ); } case QGradient::ConicalGradient: { auto material = static_cast< ConicMaterial* >( this ); - return material->setGradient( static_cast< const QConicalGradient* >( gradient ) ); + return material->setGradient( rect, + *reinterpret_cast< const QConicalGradient* >( g ), extraValue ); } } diff --git a/src/nodes/QskGradientMaterial.h b/src/nodes/QskGradientMaterial.h index da485999..38ff3a53 100644 --- a/src/nodes/QskGradientMaterial.h +++ b/src/nodes/QskGradientMaterial.h @@ -15,7 +15,7 @@ class QSK_EXPORT QskGradientMaterial : public QSGMaterial public: static QskGradientMaterial* createMaterial( QGradient::Type ); - bool updateGradient( const QGradient* ); + bool updateGradient( const QRectF&, const QGradient*, qreal ); QGradient::Type gradientType() const; const QGradientStops& stops() const; diff --git a/src/nodes/QskShapeNode.cpp b/src/nodes/QskShapeNode.cpp index 0cd20cf0..d91ca665 100644 --- a/src/nodes/QskShapeNode.cpp +++ b/src/nodes/QskShapeNode.cpp @@ -71,7 +71,7 @@ static inline bool qskIsGradientVisible( const QGradient* gradient ) { if ( gradient && gradient->type() != QGradient::NoGradient ) { - for ( const auto stop : gradient->stops() ) + for ( const auto& stop : gradient->stops() ) { if ( stop.second.alpha() > 0 ) return true; @@ -166,7 +166,8 @@ void QskShapeNode::updateNode( const QPainterPath& path, } void QskShapeNode::updateNode( const QPainterPath& path, - const QTransform& transform, const QGradient* gradient ) + const QTransform& transform, const QRectF& rect, + const QGradient* gradient, qreal extraValue ) { Q_D( QskShapeNode ); @@ -200,7 +201,7 @@ void QskShapeNode::updateNode( const QPainterPath& path, } auto gradientMaterial = static_cast< QskGradientMaterial* >( material() ); - if ( gradientMaterial->updateGradient( gradient ) ) + if ( gradientMaterial->updateGradient( rect, gradient, extraValue ) ) markDirty( QSGNode::DirtyMaterial ); } diff --git a/src/nodes/QskShapeNode.h b/src/nodes/QskShapeNode.h index 793c3d77..19a96977 100644 --- a/src/nodes/QskShapeNode.h +++ b/src/nodes/QskShapeNode.h @@ -20,8 +20,11 @@ class QSK_EXPORT QskShapeNode : public QSGGeometryNode public: QskShapeNode(); - void updateNode( const QPainterPath&, const QTransform&, const QGradient* ); - void updateNode( const QPainterPath&, const QTransform&, const QColor& ); + void updateNode( const QPainterPath&, const QTransform&, + const QRectF&, const QGradient*, qreal = 0.0 ); + + void updateNode( const QPainterPath&, + const QTransform&, const QColor& ); private: Q_DECLARE_PRIVATE( QskShapeNode ) diff --git a/src/nodes/shaders.qrc b/src/nodes/shaders.qrc index dab52798..0301b991 100644 --- a/src/nodes/shaders.qrc +++ b/src/nodes/shaders.qrc @@ -1,9 +1,26 @@ + shaders/boxshadow.vert.qsb shaders/boxshadow.frag.qsb shaders/boxshadow.vert shaders/boxshadow.frag + + shaders/gradientconic.vert.qsb + shaders/gradientconic.frag.qsb + shaders/gradientconic.vert + shaders/gradientconic.frag + + shaders/gradientradial.vert.qsb + shaders/gradientradial.frag.qsb + shaders/gradientradial.vert + shaders/gradientradial.frag + + shaders/gradientlinear.vert.qsb + shaders/gradientlinear.frag.qsb + shaders/gradientlinear.vert + shaders/gradientlinear.frag + diff --git a/src/nodes/shaders/boxshadow-vulkan.frag b/src/nodes/shaders/boxshadow-vulkan.frag index 06a8df1a..a5d5451e 100644 --- a/src/nodes/shaders/boxshadow-vulkan.frag +++ b/src/nodes/shaders/boxshadow-vulkan.frag @@ -1,9 +1,9 @@ #version 440 -layout(location = 0) in vec2 coord; -layout(location = 0) out vec4 fragColor; +layout( location = 0 ) in vec2 coord; +layout( location = 0 ) out vec4 fragColor; -layout(std140, binding = 0) uniform buf +layout( std140, binding = 0 ) uniform buf { mat4 matrix; vec4 color; diff --git a/src/nodes/shaders/boxshadow-vulkan.vert b/src/nodes/shaders/boxshadow-vulkan.vert index 1d802d81..3a308060 100644 --- a/src/nodes/shaders/boxshadow-vulkan.vert +++ b/src/nodes/shaders/boxshadow-vulkan.vert @@ -1,11 +1,11 @@ #version 440 -layout(location = 0) in vec4 in_vertex; -layout(location = 1) in vec2 in_coord; +layout( location = 0 ) in vec4 in_vertex; +layout( location = 1 ) in vec2 in_coord; -layout(location = 0) out vec2 coord; +layout( location = 0 ) out vec2 coord; -layout(std140, binding = 0) uniform buf +layout( std140, binding = 0 ) uniform buf { mat4 matrix; vec4 color; diff --git a/src/nodes/shaders/boxshadow.frag.qsb b/src/nodes/shaders/boxshadow.frag.qsb index 088e7513..110de800 100644 Binary files a/src/nodes/shaders/boxshadow.frag.qsb and b/src/nodes/shaders/boxshadow.frag.qsb differ diff --git a/src/nodes/shaders/boxshadow.vert.qsb b/src/nodes/shaders/boxshadow.vert.qsb index ae721f89..3c7c09cc 100644 Binary files a/src/nodes/shaders/boxshadow.vert.qsb and b/src/nodes/shaders/boxshadow.vert.qsb differ diff --git a/src/nodes/shaders/gradientconic-vulkan.frag b/src/nodes/shaders/gradientconic-vulkan.frag new file mode 100644 index 00000000..681ac96c --- /dev/null +++ b/src/nodes/shaders/gradientconic-vulkan.frag @@ -0,0 +1,32 @@ +#version 440 + +layout( location = 0 ) in vec2 coord; +layout( location = 0 ) out vec4 fragColor; + +layout( std140, binding = 0 ) uniform buf +{ + mat4 matrix; + vec2 centerCoord; + float start; + float span; + float opacity; +} ubuf; + +layout( binding = 1 ) uniform sampler2D palette; + +vec4 colorAt( highp float value ) +{ + return texture( palette, vec2( value, 0.0 ) ); +} + +void main() +{ + /* + angles as ratio of a rotation: + start: [ 0.0, 1.0 [ + span: ] -1.0, 1.0 [ + */ + + float v = sign( ubuf.span ) * ( atan( -coord.y, coord.x ) / 6.2831853 - ubuf.start ); + fragColor = colorAt( ( v - floor( v ) ) / abs( ubuf.span ) ) * ubuf.opacity; +} diff --git a/src/nodes/shaders/gradientconic-vulkan.vert b/src/nodes/shaders/gradientconic-vulkan.vert new file mode 100644 index 00000000..c23fdebb --- /dev/null +++ b/src/nodes/shaders/gradientconic-vulkan.vert @@ -0,0 +1,21 @@ +#version 440 + +layout( location = 0 ) in vec4 vertexCoord; +layout( location = 0 ) out vec2 coord; + +layout( std140, binding = 0 ) uniform buf +{ + mat4 matrix; + vec2 centerCoord; + float start; + float span; + float opacity; +} ubuf; + +out gl_PerVertex { vec4 gl_Position; }; + +void main() +{ + coord = vertexCoord.xy - ubuf.centerCoord; + gl_Position = ubuf.matrix * vertexCoord; +} diff --git a/src/nodes/shaders/gradientconic.frag b/src/nodes/shaders/gradientconic.frag new file mode 100644 index 00000000..55de04e4 --- /dev/null +++ b/src/nodes/shaders/gradientconic.frag @@ -0,0 +1,24 @@ +uniform sampler2D palette; +uniform lowp float opacity; + +uniform highp float start; +uniform highp float span; + +varying highp vec2 coord; + +lowp vec4 colorAt( highp float value ) +{ + return texture2D( palette, vec2( value, 0.0 ) ); +} + +void main() +{ + /* + angles as ratio of a rotation: + start: [ 0.0, 1.0 [ + span: ] -1.0, 1.0 [ + */ + + highp float v = sign( span ) * ( atan( -coord.y, coord.x ) / 6.2831853 - start ); + gl_FragColor = colorAt( ( v - floor( v ) ) / abs( span ) ) * opacity; +} diff --git a/src/nodes/shaders/gradientconic.frag.qsb b/src/nodes/shaders/gradientconic.frag.qsb new file mode 100644 index 00000000..a9ce1842 Binary files /dev/null and b/src/nodes/shaders/gradientconic.frag.qsb differ diff --git a/src/nodes/shaders/gradientconic.vert b/src/nodes/shaders/gradientconic.vert new file mode 100644 index 00000000..53b3dbf4 --- /dev/null +++ b/src/nodes/shaders/gradientconic.vert @@ -0,0 +1,12 @@ +attribute vec4 vertexCoord; + +uniform mat4 matrix; +uniform vec2 centerCoord; + +varying vec2 coord; + +void main() +{ + coord = vertexCoord.xy - centerCoord; + gl_Position = matrix * vertexCoord; +} diff --git a/src/nodes/shaders/gradientconic.vert.qsb b/src/nodes/shaders/gradientconic.vert.qsb new file mode 100644 index 00000000..49a2402a Binary files /dev/null and b/src/nodes/shaders/gradientconic.vert.qsb differ diff --git a/src/nodes/shaders/gradientlinear-vulkan.frag b/src/nodes/shaders/gradientlinear-vulkan.frag new file mode 100644 index 00000000..ab809c25 --- /dev/null +++ b/src/nodes/shaders/gradientlinear-vulkan.frag @@ -0,0 +1,23 @@ +#version 440 + +layout( location = 0 ) in float colorIndex; +layout( location = 0 ) out vec4 fragColor; + +layout( std140, binding = 0 ) uniform buf +{ + mat4 matrix; + vec4 rect; + float opacity; +} ubuf; + +layout( binding = 1 ) uniform sampler2D palette; + +vec4 colorAt( float value ) +{ + return texture( palette, vec2( value, 0.0 ) ); +} + +void main() +{ + fragColor = colorAt( colorIndex ) * ubuf.opacity; +} diff --git a/src/nodes/shaders/gradientlinear-vulkan.vert b/src/nodes/shaders/gradientlinear-vulkan.vert new file mode 100644 index 00000000..890760f5 --- /dev/null +++ b/src/nodes/shaders/gradientlinear-vulkan.vert @@ -0,0 +1,22 @@ +#version 440 + +layout( location = 0 ) in vec4 vertexCoord; +layout( location = 0 ) out float colorIndex; + +layout( std140, binding = 0 ) uniform buf +{ + mat4 matrix; + vec4 rect; + float opacity; +} ubuf; + +out gl_PerVertex { vec4 gl_Position; }; + +void main() +{ + vec2 l = vertexCoord.xy - ubuf.rect.xy; + vec2 size = ubuf.rect.zw; + + colorIndex = dot( l, size ) / dot( size, size ); + gl_Position = ubuf.matrix * vertexCoord; +} diff --git a/src/nodes/shaders/gradientlinear.frag b/src/nodes/shaders/gradientlinear.frag new file mode 100644 index 00000000..dd0525b3 --- /dev/null +++ b/src/nodes/shaders/gradientlinear.frag @@ -0,0 +1,14 @@ +uniform sampler2D palette; +uniform highp float opacity; + +varying highp float colorIndex; + +lowp vec4 colorAt( float value ) +{ + return texture2D( palette, vec2( value, 0.0 ) ); +} + +void main() +{ + gl_FragColor = colorAt( colorIndex ) * opacity; +} diff --git a/src/nodes/shaders/gradientlinear.frag.qsb b/src/nodes/shaders/gradientlinear.frag.qsb new file mode 100644 index 00000000..693848c7 Binary files /dev/null and b/src/nodes/shaders/gradientlinear.frag.qsb differ diff --git a/src/nodes/shaders/gradientlinear.vert b/src/nodes/shaders/gradientlinear.vert new file mode 100644 index 00000000..cde28307 --- /dev/null +++ b/src/nodes/shaders/gradientlinear.vert @@ -0,0 +1,15 @@ +attribute vec4 vertexCoord; + +uniform mat4 matrix; +uniform vec4 rect; + +varying float colorIndex; + +void main() +{ + highp vec2 l = vertexCoord.xy - rect.xy; + highp vec2 size = rect.zw; + + colorIndex = dot( l, size ) / dot( size, size ); + gl_Position = matrix * vertexCoord; +} diff --git a/src/nodes/shaders/gradientlinear.vert.qsb b/src/nodes/shaders/gradientlinear.vert.qsb new file mode 100644 index 00000000..8981730a Binary files /dev/null and b/src/nodes/shaders/gradientlinear.vert.qsb differ diff --git a/src/nodes/shaders/gradientradial-vulkan.frag b/src/nodes/shaders/gradientradial-vulkan.frag new file mode 100644 index 00000000..248faa9e --- /dev/null +++ b/src/nodes/shaders/gradientradial-vulkan.frag @@ -0,0 +1,24 @@ +#version 440 + +layout( location = 0 ) in vec2 coord; +layout( location = 0 ) out vec4 fragColor; + +layout( std140, binding = 0 ) uniform buf +{ + mat4 matrix; + vec2 centerCoord; + vec2 radius; + float opacity; +} ubuf; + +layout( binding = 1 ) uniform sampler2D palette; + +vec4 colorAt( float value ) +{ + return texture( palette, vec2( value, 0.0 ) ); +} + +void main() +{ + fragColor = colorAt( length( coord / ubuf.radius ) ) * ubuf.opacity; +} diff --git a/src/nodes/shaders/gradientradial-vulkan.vert b/src/nodes/shaders/gradientradial-vulkan.vert new file mode 100644 index 00000000..71c1b2e2 --- /dev/null +++ b/src/nodes/shaders/gradientradial-vulkan.vert @@ -0,0 +1,20 @@ +#version 440 + +layout( location = 0 ) in vec4 vertexCoord; +layout( location = 0 ) out vec2 coord; + +layout( std140, binding = 0 ) uniform buf +{ + mat4 matrix; + vec2 centerCoord; + vec2 radius; + float opacity; +} ubuf; + +out gl_PerVertex { vec4 gl_Position; }; + +void main() +{ + coord = vertexCoord.xy - ubuf.centerCoord; + gl_Position = ubuf.matrix * vertexCoord; +} diff --git a/src/nodes/shaders/gradientradial.frag b/src/nodes/shaders/gradientradial.frag new file mode 100644 index 00000000..1297d3e6 --- /dev/null +++ b/src/nodes/shaders/gradientradial.frag @@ -0,0 +1,16 @@ +uniform sampler2D palette; +uniform lowp float opacity; + +uniform highp vec2 radius; + +varying highp vec2 coord; + +lowp vec4 colorAt( highp float value ) +{ + return texture2D( palette, vec2( value, 0.0 ) ); +} + +void main() +{ + gl_FragColor = colorAt( length( coord / radius ) ) * opacity; +} diff --git a/src/nodes/shaders/gradientradial.frag.qsb b/src/nodes/shaders/gradientradial.frag.qsb new file mode 100644 index 00000000..ccd25401 Binary files /dev/null and b/src/nodes/shaders/gradientradial.frag.qsb differ diff --git a/src/nodes/shaders/gradientradial.vert b/src/nodes/shaders/gradientradial.vert new file mode 100644 index 00000000..53b3dbf4 --- /dev/null +++ b/src/nodes/shaders/gradientradial.vert @@ -0,0 +1,12 @@ +attribute vec4 vertexCoord; + +uniform mat4 matrix; +uniform vec2 centerCoord; + +varying vec2 coord; + +void main() +{ + coord = vertexCoord.xy - centerCoord; + gl_Position = matrix * vertexCoord; +} diff --git a/src/nodes/shaders/gradientradial.vert.qsb b/src/nodes/shaders/gradientradial.vert.qsb new file mode 100644 index 00000000..be9e813b Binary files /dev/null and b/src/nodes/shaders/gradientradial.vert.qsb differ diff --git a/src/nodes/shaders/vulkan2qsb.sh b/src/nodes/shaders/vulkan2qsb.sh index 032a238d..84f7f389 100755 --- a/src/nodes/shaders/vulkan2qsb.sh +++ b/src/nodes/shaders/vulkan2qsb.sh @@ -1,4 +1,18 @@ #! /bin/sh -qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o boxshadow.vert.qsb boxshadow-vulkan.vert -qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o boxshadow.frag.qsb boxshadow-vulkan.frag +function qsbcompile { + qsbfile=`echo $1 | sed 's/-vulkan//'` + qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o ${qsbfile}.qsb $1 +} + +qsbcompile boxshadow-vulkan.vert +qsbcompile boxshadow-vulkan.frag + +qsbcompile gradientconic-vulkan.vert +qsbcompile gradientconic-vulkan.frag + +qsbcompile gradientradial-vulkan.vert +qsbcompile gradientradial-vulkan.frag + +qsbcompile gradientlinear-vulkan.vert +qsbcompile gradientlinear-vulkan.frag diff --git a/src/src.pro b/src/src.pro index 38773a7e..c5021646 100644 --- a/src/src.pro +++ b/src/src.pro @@ -3,12 +3,6 @@ TARGET = $$qskLibraryTarget(qskinny) QT += quick quick-private -# We need quickshapes for the shaders for the gradients only, -# As those shaders are more or less trivial # it might be better -# to implement our own shaders to get rid of this extra module dependency - -QT += quickshapes-private - greaterThan( QT_MAJOR_VERSION, 5 ) { QT += opengl-private }