From 51a7e4e589d152db18215051089024f2dcb5a717 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 13 Oct 2022 19:39:57 +0200 Subject: [PATCH] Using our own gradient shaders ( no dependencies from quickshapes anymore ). shapes/Gradient has not yet been merged into QskGradient and we still have some stupid conversions to QGradient in the way. --- playground/shapes/Gradient.cpp | 34 +- playground/shapes/Gradient.h | 118 ++---- playground/shapes/ShapeItem.cpp | 39 +- playground/shapes/main.cpp | 165 ++++++-- src/nodes/QskGradientMaterial.cpp | 420 +++++++++---------- src/nodes/QskGradientMaterial.h | 2 +- src/nodes/QskShapeNode.cpp | 7 +- src/nodes/QskShapeNode.h | 7 +- src/nodes/shaders.qrc | 17 + src/nodes/shaders/boxshadow-vulkan.frag | 6 +- src/nodes/shaders/boxshadow-vulkan.vert | 8 +- src/nodes/shaders/boxshadow.frag.qsb | Bin 2652 -> 2633 bytes src/nodes/shaders/boxshadow.vert.qsb | Bin 1570 -> 1565 bytes src/nodes/shaders/gradientconic-vulkan.frag | 32 ++ src/nodes/shaders/gradientconic-vulkan.vert | 21 + src/nodes/shaders/gradientconic.frag | 24 ++ src/nodes/shaders/gradientconic.frag.qsb | Bin 0 -> 1794 bytes src/nodes/shaders/gradientconic.vert | 12 + src/nodes/shaders/gradientconic.vert.qsb | Bin 0 -> 1505 bytes src/nodes/shaders/gradientlinear-vulkan.frag | 23 + src/nodes/shaders/gradientlinear-vulkan.vert | 22 + src/nodes/shaders/gradientlinear.frag | 14 + src/nodes/shaders/gradientlinear.frag.qsb | Bin 0 -> 1432 bytes src/nodes/shaders/gradientlinear.vert | 15 + src/nodes/shaders/gradientlinear.vert.qsb | Bin 0 -> 1595 bytes src/nodes/shaders/gradientradial-vulkan.frag | 24 ++ src/nodes/shaders/gradientradial-vulkan.vert | 20 + src/nodes/shaders/gradientradial.frag | 16 + src/nodes/shaders/gradientradial.frag.qsb | Bin 0 -> 1537 bytes src/nodes/shaders/gradientradial.vert | 12 + src/nodes/shaders/gradientradial.vert.qsb | Bin 0 -> 1478 bytes src/nodes/shaders/vulkan2qsb.sh | 18 +- src/src.pro | 6 - 33 files changed, 684 insertions(+), 398 deletions(-) create mode 100644 src/nodes/shaders/gradientconic-vulkan.frag create mode 100644 src/nodes/shaders/gradientconic-vulkan.vert create mode 100644 src/nodes/shaders/gradientconic.frag create mode 100644 src/nodes/shaders/gradientconic.frag.qsb create mode 100644 src/nodes/shaders/gradientconic.vert create mode 100644 src/nodes/shaders/gradientconic.vert.qsb create mode 100644 src/nodes/shaders/gradientlinear-vulkan.frag create mode 100644 src/nodes/shaders/gradientlinear-vulkan.vert create mode 100644 src/nodes/shaders/gradientlinear.frag create mode 100644 src/nodes/shaders/gradientlinear.frag.qsb create mode 100644 src/nodes/shaders/gradientlinear.vert create mode 100644 src/nodes/shaders/gradientlinear.vert.qsb create mode 100644 src/nodes/shaders/gradientradial-vulkan.frag create mode 100644 src/nodes/shaders/gradientradial-vulkan.vert create mode 100644 src/nodes/shaders/gradientradial.frag create mode 100644 src/nodes/shaders/gradientradial.frag.qsb create mode 100644 src/nodes/shaders/gradientradial.vert create mode 100644 src/nodes/shaders/gradientradial.vert.qsb 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 088e7513075afd383e6a572ca77e100fa3da6ee4..110de80036d7ec7d6d4645ea142b6dd377f41841 100644 GIT binary patch literal 2633 zcmV-P3byqC04+v%ob6f*cN5nUzVQKSg0{Rn*GEqZxi!X7B?u(@#6CO!Aq9RU`PEG15TbpT( zi51ZzO(AyBw|;IKQtZ(#Q76kWS@cDl=!d~OVaPqIAC%js11C(jdF_%Om&s~NL=axu zSlA(Y`027T9{A15nAQhr$a!p~3A6DQxI`zewi7s<<1yG61Ak2FscR3d^rWHp zH1e(K!|+AZN08?%S!A1Yuw~wRNp>D!D%kU7?vj%N%v`?!F0l$@d$fpLt-5u^6) zIO<^(`Y%A%jPWHE;&Cm14*qEVtBQX@^Dh{AU&2~D;SbZV0b~9p$c`KKuF?J1znovt z_I%`u<==+x@1Z-6^_jj4Y=)v95=l2;>>q@TLY8Y|*3jksKifmU zV$dvq(V)4muJp*i)x$6M@K<~2_j~A%KrfQFv#6UF$Yb8O7qQp8p9{#%N#K7b8LrP$ zz_`BtPBzXU_J5H)^G?%!26;Gb*#04GpEGQ~4E#fqVfs93_>L zwaqH@D$wJ1<{jwyMt*C+HQhkIKPMfg17NSpe2q!0iF}QKzXaKz2=yNFeFs>|Mk5I%IaCes6>KBINYmy@z#gBkomT+W$L3^$1OWfcm%t z{SP7Y0rcMorsY2ts%GB>{RuG5|5S9>^v{LrLA$8CG5rhpJq6uQA;W8Z1ipUXe~Fs= zOeF97=fJi7UkTOImM{l@4a~fGZRY(3Yv*8R4)Xfl_^s&ge_sISnr0ingPku#(nA^h zC-pns_s$sp{z0f2z_NEi|C_uxM)wSI&V7h4{!MX|=8o~L3i88+F8hvwO)eR#*XjoJEe5x6`C0|lizfx^lUM+Cq z`99ch5SWVMuvLn!m6n&fm9prnJMlDsgnoNo0;_Im+A0OLAT;REDf_Lc0~9PLYPzLZ z0dhfWrPc~hw_~@_g$7NhZ)?l|ISm3T9tm@aHHB+Zsk1x`) z7S!6gcA~%Dd2(x!y9M2~LAs$Ex57r^nc{RT_C+u~{dFRkp6+;Y^Ijt`bZ=}Hf%a@Y zwN5)5_+^U=IIXuxR~8xL$27Y;-`PAah#bmgvmJB`q@T|ft%I_La=mreS*huSPMu_> zlv%)#C@2YgieylE-7AH}DCF|AP;V(p#jMuP^eTGN!+bHXuA|e%eDPSmI6E_2IC89T zY^qSS4pVB{=`i~ha)#;9I<#P=Df)w!m+1+ltWsJ?lTdF~GS(!LtKM1CPfOV;$}sVq zl_)L4Ck92E$@GQ88&;=%WRJ_acGfEA)-uxb3@ul489sni{-RCB0dm3^nu2%^|8Sw204ZrR#5`9|H3 zB5G%o%`k|Ac&+J1`%~EW*RDw)()rBt z@&HZ0VJf2elTs^k!*neuHB3E6=DAVx8?I&BPE6shv|`t`(`l!6!&!@L#mrI71|>-FpDD&M3YPvH85CO3o#X8RO1)xrndF z->9sA95&j?{2QH24jqO3_CaF1*KZ#rAhCUr*gi;Xa*!CpUqIm+pDn3h9kP4PQO#F; z@-$4Z@9dhKI!1E$EPM37);}?Szl(F>4O%IS$#oQxU zGzAMv5If#2IAaPbxujZpWpg+CrS(hNE6TgXZC?NIH%|!jU7&H^NX{3Rmd;(gVxJ6y zD6-Ern%yT9ebAV*E}y=7^1_9Sr}ABg6I1y@D{gLlzL~QwU9m4aVa1JMV(_>zj$gk1 z*x4Xtq*GYgq&b8_49zb^20NP+T^#tp^4>7({))?x}qHTbcS9)z=>_eNLulUF0f(3nt4vTpDkM z0tPImR0ByUArt93kQiOucpJM7teZoXPbYVc)5+1~bW;2Vo=*Hm*TIDUW?WoSh;V9l|eJ2=bX~>j~@D8oYntg?mx@)@x^}uKEV#;H3?5T literal 2652 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 Kr~Kb$xenv86?=35 diff --git a/src/nodes/shaders/boxshadow.vert.qsb b/src/nodes/shaders/boxshadow.vert.qsb index ae721f89d4deb12b516f3d2c5fedd3c81e252f39..3c7c09cc86779b1b3e02952e607eeffe7858b56c 100644 GIT binary patch literal 1565 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 UuEfppGn>e<{M`6I0rl6eQ3;9`g#Z8m 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 0000000000000000000000000000000000000000..a9ce184249272f62c896a99482b3e961db50eb26 GIT binary patch literal 1794 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..49a2402a5ebb806685591ebda53d684bae6a77ef GIT binary patch literal 1505 zcmV<71s?hU03Yvoob6f7Pa8)RAAf*hAt50lZJMN+#v!!>I4**wf`Wo*RU#pQLKIbs z&}vz)>9+Q+vmam*ajJUjrI+4&>z|lQ)xJ0L);qhlDX26pfwk72_vZIL=k3hwm@ziU z1iZMMo>_;{=aJ$Z!uNf%3A<4k9-Kt?AtYG5n_ccG62_G!#i^k
  • -~V2!88I*@H=1!1mEljKh8Bu!lN-OyHd0rvk}%T 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 mVWLKTXT9CD7*qeNmYot6 z!q=tFqVT0&3$mR&v20kZiKeL0*#Y|1=T8h&mi9xUA<7g}C_HI(6tZ~(cTArgAec+x z#2DzjDKxhu6zvAtt&r7NY$2j$ou9w69fFZ6erX^0Wqi{OBQNmno5iAKMRC}y#P(XV zX1%m*+8X6}nh&AZDoMtsTbZ^)w-PI|Ru9Ut9c+{S2ik zE;>OoHtm^dU0G>HZkVeF6~CBYT}?SKlex08fl~%`dGP#Hz-F#VwOu~B4j)F!P1K#d zcB1Sg!%$~A?bP--vM4UEyF{(7PSVhPB7K>|E3yCxK*t&llAY(R@%DBl! z6_rbQOPM9jbuWr3wQEJ4*f4nRG|FEEVN$ysyMx$gZK~3*gIXBK=)N+BuX)QI93J%NhpxX>9|l+ zwbq4A<;|=x<2p>c+cqCOyjEx>m*c?a$(mtmzpWYG(1k(zNzV!Y$w>HTNy2AdU&86B z)}3j7PQ9gB7FY^n8~iz&86V-~TeM2okDuf8FyiSLrDlMCKY950VSyG}h3T21TBc|9 zf=nDGJ%NRq_Q4CbG1~L2OA@9p!1kv^>$U%oq=(w{cpH=OC^&hpc>}=B8@vp7%hF%A z&12su==TzAY5Jl;kELQ85?66P+QwuhkL{hLV@B#{Wd>ABmz6D^P5T+L$MFtBW)pn? zV;F(lf_xD2QH+WCCD6KOIZO0W$OdJcYP^~^3>(Mc?-*<_eFD7GM4v=_Z1WoEQ=nP@ zG_V$E&PNvZOQ6TVyMTOXY!3XZz~(UTS;N-^a>@8>@O2b)5m>f&o5q(BNwdfN--t5= z+nmdT$fc&wfu2Kd4{26e+GQ5e-^wmhWFDnwjoqlt- z$L6j>;T7Jz{a3wU5=9zl6w{m8GV0gNBHc3XyVuNbMKfczjQn2z`~B83614vo9}`qf zCTgf|cAfVi*jv|mP@eD9b>0$hSLez2TflQ%{Z91tcA`vA3H?D-*<<<^cs!OFj77jc z)3*(OOwYnczq9Rkwrqprm_{8vAd2hxj)A{z;O;{9E#m(Wx_1rTlA${beg@h9OE!cc*ACV~I} literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ccd2540194f95492c6682bc1a027fa5cbc3beeb4 GIT binary patch literal 1537 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