From 58c12b85ef5205e5d68cedfab191445512a4bfda Mon Sep 17 00:00:00 2001 From: Alexander Kavon Date: Thu, 21 Dec 2023 23:22:06 -0500 Subject: [PATCH 01/14] search for Qt6 then Qt5 --- cmake/QskFindMacros.cmake | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cmake/QskFindMacros.cmake b/cmake/QskFindMacros.cmake index 035e95143..40915c6f4 100644 --- a/cmake/QskFindMacros.cmake +++ b/cmake/QskFindMacros.cmake @@ -5,12 +5,11 @@ macro(qsk_setup_Qt) - # Often users have several Qt installations on their system and - # need to be able to explicitly the one to be used. Let's see if - # standard cmake features are good enough or if we need to introduce - # something sort of additional option. TODO ... - - find_package(QT "5.15" NAMES Qt6 Qt5 REQUIRED COMPONENTS Quick) + # Define a package QT, attempt Qt6, if not fallback to Qt5 + find_package(QT NAMES Qt6 REQUIRED COMPONENTS Quick) + if (NOT QT_FOUND) + find_package(QT "5.15" NAMES Qt5 REQUIRED COMPONENTS Quick) + endif() if ( QT_FOUND ) From 68a3ad3cd8e29fbf05d9fb8fcac473d551ae0bab Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 22 Dec 2023 15:14:03 +0100 Subject: [PATCH 02/14] disable integration test ( fails with Qt5 Ubuntu ) --- .github/workflows/cmake.yml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 84656396d..5662b48d5 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -431,22 +431,22 @@ jobs: killall iotdashboard killall Xvfb - - name: Configure ( CMake Integration Test ) - shell: bash - run: | - mkdir qskinny_build_test - cmake \ - -S qskinny_source/examples/iotdashboard_smoketest \ - -B qskinny_build_test \ - -G "${{ matrix.config.generators }}" \ - -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \ - -DCMAKE_PREFIX_PATH:PATH="${{ matrix.config.cmake.qtprefixpath }}" \ - -D${{ matrix.config.cmake.qtdirkey }}:PATH="${{ matrix.config.cmake.qtdirvalue }}" \ - -DQSkinny_DIR:PATH=$GITHUB_WORKSPACE/qskinny_install/lib/cmake/QSkinny - - - name: Build ( CMake Integration Test ) - shell: bash - run: cmake --build qskinny_build_test --config ${{ matrix.config.build_type }} + #- name: Configure ( CMake Integration Test ) + # shell: bash + # run: | + # mkdir qskinny_build_test + # cmake \ + # -S qskinny_source/examples/iotdashboard_smoketest \ + # -B qskinny_build_test \ + # -G "${{ matrix.config.generators }}" \ + # -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \ + # -DCMAKE_PREFIX_PATH:PATH="${{ matrix.config.cmake.qtprefixpath }}" \ + # -D${{ matrix.config.cmake.qtdirkey }}:PATH="${{ matrix.config.cmake.qtdirvalue }}" \ + # -DQSkinny_DIR:PATH=$GITHUB_WORKSPACE/qskinny_install/lib/cmake/QSkinny +# + #- name: Build ( CMake Integration Test ) + # shell: bash + # run: cmake --build qskinny_build_test --config ${{ matrix.config.build_type }} # - name: Pack # shell: bash From 3b60780cb67e25efa57771a33cc179a616b0c591 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 22 Dec 2023 15:25:59 +0100 Subject: [PATCH 03/14] Revert "disable integration test ( fails with Qt5 Ubuntu )" This reverts commit 68a3ad3cd8e29fbf05d9fb8fcac473d551ae0bab. --- .github/workflows/cmake.yml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 5662b48d5..84656396d 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -431,22 +431,22 @@ jobs: killall iotdashboard killall Xvfb - #- name: Configure ( CMake Integration Test ) - # shell: bash - # run: | - # mkdir qskinny_build_test - # cmake \ - # -S qskinny_source/examples/iotdashboard_smoketest \ - # -B qskinny_build_test \ - # -G "${{ matrix.config.generators }}" \ - # -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \ - # -DCMAKE_PREFIX_PATH:PATH="${{ matrix.config.cmake.qtprefixpath }}" \ - # -D${{ matrix.config.cmake.qtdirkey }}:PATH="${{ matrix.config.cmake.qtdirvalue }}" \ - # -DQSkinny_DIR:PATH=$GITHUB_WORKSPACE/qskinny_install/lib/cmake/QSkinny -# - #- name: Build ( CMake Integration Test ) - # shell: bash - # run: cmake --build qskinny_build_test --config ${{ matrix.config.build_type }} + - name: Configure ( CMake Integration Test ) + shell: bash + run: | + mkdir qskinny_build_test + cmake \ + -S qskinny_source/examples/iotdashboard_smoketest \ + -B qskinny_build_test \ + -G "${{ matrix.config.generators }}" \ + -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \ + -DCMAKE_PREFIX_PATH:PATH="${{ matrix.config.cmake.qtprefixpath }}" \ + -D${{ matrix.config.cmake.qtdirkey }}:PATH="${{ matrix.config.cmake.qtdirvalue }}" \ + -DQSkinny_DIR:PATH=$GITHUB_WORKSPACE/qskinny_install/lib/cmake/QSkinny + + - name: Build ( CMake Integration Test ) + shell: bash + run: cmake --build qskinny_build_test --config ${{ matrix.config.build_type }} # - name: Pack # shell: bash From 69090a6079f4d80ef9bd0ce8e07bbb0eeecbd36d Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 22 Dec 2023 15:26:58 +0100 Subject: [PATCH 04/14] disable Ninja multi config --- .github/workflows/cmake.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 84656396d..005be2b57 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -104,7 +104,8 @@ jobs: cc: "gcc", cxx: "g++", archiver: "7z a", - generators: "Ninja Multi-Config", + # generators: "Ninja Multi-Config", + generators: "Ninja", env: { DISPLAY: ":1" }, cmake: { From 67f0df44afce35bbed688dd52320ee0ab17f98f6 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 27 Dec 2023 08:47:57 +0100 Subject: [PATCH 05/14] Qt 6.7 incompatibilities fixed --- src/common/QskMetaFunction.hpp | 19 ++++++++++--------- src/nodes/QskPlainTextRenderer.cpp | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/common/QskMetaFunction.hpp b/src/common/QskMetaFunction.hpp index e8905ab55..26af08602 100644 --- a/src/common/QskMetaFunction.hpp +++ b/src/common/QskMetaFunction.hpp @@ -47,11 +47,8 @@ class QskMetaFunction::FunctionCall : public QtPrivate::QSlotObjectBase namespace QskMetaFunctionCall { - using FunctionCall = QskMetaFunction::FunctionCall; - using namespace QtPrivate; - template< typename Function, typename Args, typename R > - class StaticFunctionCall : public FunctionCall + class StaticFunctionCall : public QskMetaFunction::FunctionCall { using MetaCall = StaticFunctionCall< Function, Args, R >; @@ -74,7 +71,7 @@ namespace QskMetaFunctionCall } case Call: { - typedef FunctionPointer< Function > FuncType; + using FuncType = QtPrivate::FunctionPointer< Function >; FuncType::template call< Args, R >( static_cast< MetaCall* >( functionCall )->m_function, object, args ); @@ -100,7 +97,7 @@ namespace QskMetaFunctionCall }; template< typename Function, typename Args, typename R > - class MemberFunctionCall : public FunctionCall + class MemberFunctionCall : public QskMetaFunction::FunctionCall { using MetaCall = MemberFunctionCall< Function, Args, R >; @@ -123,7 +120,7 @@ namespace QskMetaFunctionCall } case Call: { - typedef FunctionPointer< Function > FuncType; + using FuncType = QtPrivate::FunctionPointer< Function >; FuncType::template call< Args, R >( static_cast< MetaCall* >( functionCall )->m_function, @@ -144,7 +141,7 @@ namespace QskMetaFunctionCall }; template< typename Function, int N, typename Args, typename R > - class FunctorFunctionCall : public FunctionCall + class FunctorFunctionCall : public QskMetaFunction::FunctionCall { using MetaCall = FunctorFunctionCall< Function, N, Args, R >; @@ -167,7 +164,11 @@ namespace QskMetaFunctionCall } case Call: { - typedef Functor< Function, N > FuncType; +#if QT_VERSION < QT_VERSION_CHECK( 6, 7, 0 ) + using FuncType = QtPrivate::Functor< Function, N >; +#else + using FuncType = QtPrivate::Callable< Function, Args >; +#endif FuncType::template call< Args, R >( static_cast< MetaCall* >( functionCall )->m_function, object, args ); diff --git a/src/nodes/QskPlainTextRenderer.cpp b/src/nodes/QskPlainTextRenderer.cpp index 7b5d5a435..77d13684e 100644 --- a/src/nodes/QskPlainTextRenderer.cpp +++ b/src/nodes/QskPlainTextRenderer.cpp @@ -127,16 +127,26 @@ static void qskRenderText( if ( glyphNode == nullptr ) { const bool preferNativeGlyphNode = false; // QskTextOptions? - -#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) constexpr int renderQuality = -1; // QQuickText::DefaultRenderTypeQuality + +#if QT_VERSION >= QT_VERSION_CHECK( 6, 7, 0 ) + const auto renderType = preferNativeGlyphNode + ? QSGTextNode::QtRendering : QSGTextNode::NativeRendering; + glyphNode = sgContext->createGlyphNode( + renderContext, renderType, renderQuality ); +#elif QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) glyphNode = sgContext->createGlyphNode( renderContext, preferNativeGlyphNode, renderQuality ); #else + Q_UNUSED( renderQuality ); glyphNode = sgContext->createGlyphNode( renderContext, preferNativeGlyphNode ); #endif + +#if QT_VERSION < QT_VERSION_CHECK( 6, 7, 0 ) glyphNode->setOwnerElement( item ); +#endif + glyphNode->setFlags( QSGNode::OwnedByParent | GlyphFlag ); } From ff10fc6fc13edcb6151a5ebc8b031bc75ebe7960 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 27 Dec 2023 08:51:12 +0100 Subject: [PATCH 06/14] missing initialization added --- src/nodes/QskSceneTexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nodes/QskSceneTexture.cpp b/src/nodes/QskSceneTexture.cpp index e4d78d787..0b733b747 100644 --- a/src/nodes/QskSceneTexture.cpp +++ b/src/nodes/QskSceneTexture.cpp @@ -75,7 +75,7 @@ namespace QskSceneTexture* m_texture = nullptr; #if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) - QOpenGLFramebufferObject* m_fbo; + QOpenGLFramebufferObject* m_fbo = nullptr; #endif #if QT_VERSION < QT_VERSION_CHECK( 6, 4, 0 ) From 1bc7cc3097f60d28bc29a76177699b82028b89e5 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 28 Dec 2023 17:02:30 +0100 Subject: [PATCH 07/14] finally working for RHI and the Qt5 OpenGL legacy backends --- src/nodes/QskSceneTexture.cpp | 126 ++++++++++++++++++++++++---------- src/nodes/QskSceneTexture.h | 7 -- 2 files changed, 91 insertions(+), 42 deletions(-) diff --git a/src/nodes/QskSceneTexture.cpp b/src/nodes/QskSceneTexture.cpp index 0b733b747..4ec935752 100644 --- a/src/nodes/QskSceneTexture.cpp +++ b/src/nodes/QskSceneTexture.cpp @@ -29,6 +29,26 @@ QSK_QT_PRIVATE_END #include #endif +static int qskRenderOrderCompare( const QSGNode* rootNode, + const QSGNode* node1, const QSGNode* node2 ) +{ + if ( rootNode == node1 ) + return 1; + + if ( rootNode == node2 ) + return -1; + + for ( auto node = rootNode->firstChild(); + node != nullptr; node = node->nextSibling() ) + { + const auto ret = qskRenderOrderCompare( node, node1, node2 ); + if ( ret ) + return ret; + } + + return 0; +} + namespace { #if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) @@ -51,7 +71,20 @@ namespace #if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) inline int textureId() const { return m_fbo ? m_fbo->texture() : 0; } - inline void renderScene() { Inherited::renderScene( textureId() ); } + + inline void renderScene() + { + class Bindable : public QSGBindable + { + public: + Bindable( QOpenGLFramebufferObject* fbo ) : m_fbo( fbo ) {} + void bind() const override { m_fbo->bind(); } + private: + QOpenGLFramebufferObject* m_fbo; + }; + + Inherited::renderScene( Bindable( m_fbo ) ); + } #endif inline QRhiTexture* rhiTexture() const { return m_rhiTexture; } @@ -62,6 +95,7 @@ namespace void setProjection( const QRectF& ); void setTextureSize( const QSize& ); + QSize textureSize() const; protected: void nodeChanged( QSGNode*, QSGNode::DirtyState ) override; @@ -70,6 +104,7 @@ namespace private: void createTarget( const QSize& ); void clearTarget(); + void markDirty(); QSGTransformNode* m_finalNode = nullptr; QskSceneTexture* m_texture = nullptr; @@ -100,6 +135,9 @@ namespace , m_texture( texture ) { setClearColor( Qt::transparent ); + + connect( this, &QSGRenderer::sceneGraphChanged, + this, &Renderer::markDirty ); } Renderer::~Renderer() @@ -112,6 +150,7 @@ namespace if ( node != m_finalNode ) { m_finalNode = node; + markDirty(); } } @@ -169,6 +208,11 @@ namespace setViewportRect( r ); } + QSize Renderer::textureSize() const + { + return m_fbo ? m_fbo->size() : QSize(); + } + void Renderer::render() { m_dirty = false; @@ -186,16 +230,25 @@ namespace void Renderer::nodeChanged( QSGNode* node, QSGNode::DirtyState state ) { - Inherited::nodeChanged( node, state ); - /* - We want to limit updates to nodes, that are actually rendered. TODO ... + No need to update the texture for changes of nodes behind + the final node. - In any case we need to block update requests, when the textureNode reports - that it has been updated by us to the renderer of the window. + Unfortunately QQuickWindow does not update the scene graph in + rendering order and we might be called for relevant nodes after + the texture has already been updated. In these situations we + update the texture twice. Not so good ... */ - if ( ( state != QSGNode::DirtyMaterial ) - || ( node != m_texture->textureNode() ) ) + if ( qskRenderOrderCompare( rootNode(), node, m_finalNode ) > 0 ) + { + // triggering QSGRenderer::sceneGraphChanged signals + Inherited::nodeChanged( node, state ); + } + } + + void Renderer::markDirty() + { + if ( !m_dirty ) { m_dirty = true; Q_EMIT m_texture->updateRequested(); @@ -295,19 +348,44 @@ class QskSceneTexturePrivate final : public QSGTexturePrivate #if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) int comparisonKey() const override - { return int( qintptr( rhiTexture() ) ); } + { + if ( renderer ) + { + if ( renderer->textureId() ) + return renderer->textureId(); + + if ( renderer->rhiTexture() ) + return int( qintptr( renderer->rhiTexture() ) ); + } + + return int( qintptr( this ) ); + } QRhiTexture *rhiTexture() const override { return renderer ? renderer->rhiTexture() : nullptr; } #endif + QSize pixelSize() const + { + QSize size( qCeil( rect.width() ), qCeil( rect.height() ) ); + size *= devicePixelRatio; + + const QSize minSize = context->sceneGraphContext()->minimumFBOSize(); + + while ( size.width() < minSize.width() ) + size.rwidth() *= 2; + + while ( size.height() < minSize.height() ) + size.rheight() *= 2; + + return size; + } + QRectF rect; const qreal devicePixelRatio; Renderer* renderer = nullptr; QSGDefaultRenderContext* context = nullptr; - - const QSGGeometryNode* textureNode = nullptr; }; QskSceneTexture::QskSceneTexture( const QQuickWindow* window ) @@ -321,32 +399,10 @@ QskSceneTexture::~QskSceneTexture() delete d_func()->renderer; } -void QskSceneTexture::setTextureNode( const QSGGeometryNode* node ) -{ - d_func()->textureNode = node; -} - -const QSGGeometryNode* QskSceneTexture::textureNode() const -{ - return d_func()->textureNode; -} - QSize QskSceneTexture::textureSize() const { Q_D( const QskSceneTexture ); - - QSize size( qCeil( d->rect.width() ), qCeil( d->rect.height() ) ); - size *= d->devicePixelRatio; - - const QSize minSize = d->context->sceneGraphContext()->minimumFBOSize(); - - while ( size.width() < minSize.width() ) - size.rwidth() *= 2; - - while ( size.height() < minSize.height() ) - size.rheight() *= 2; - - return size; + return d->renderer ? d->renderer->textureSize() : QSize(); } void QskSceneTexture::render( const QSGRootNode* rootNode, @@ -366,7 +422,7 @@ void QskSceneTexture::render( const QSGRootNode* rootNode, d->renderer->setFinalNode( const_cast< QSGTransformNode* >( finalNode ) ); d->renderer->setProjection( d->rect ); - d->renderer->setTextureSize( textureSize() ); + d->renderer->setTextureSize( d->pixelSize() ); d->renderer->renderScene(); } diff --git a/src/nodes/QskSceneTexture.h b/src/nodes/QskSceneTexture.h index 56acdb3ef..eff6727f1 100644 --- a/src/nodes/QskSceneTexture.h +++ b/src/nodes/QskSceneTexture.h @@ -13,7 +13,6 @@ class QskSceneTexturePrivate; class QSGRootNode; class QSGTransformNode; -class QSGGeometryNode; class QQuickWindow; class QSK_EXPORT QskSceneTexture : public QSGTexture @@ -26,12 +25,6 @@ class QSK_EXPORT QskSceneTexture : public QSGTexture QskSceneTexture( const QQuickWindow* ); ~QskSceneTexture(); -#if 1 - // to avoid recursive update - need to find a better solution TODO - void setTextureNode( const QSGGeometryNode* ); - const QSGGeometryNode* textureNode() const; -#endif - void render( const QSGRootNode*, const QSGTransformNode*, const QRectF& ); QSize textureSize() const override; From b3b4ca6aefa013c6d60ba6603964eb90d3401b18 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 28 Dec 2023 17:18:34 +0100 Subject: [PATCH 08/14] Qt6 incompatibility fixed --- src/nodes/QskSceneTexture.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/nodes/QskSceneTexture.cpp b/src/nodes/QskSceneTexture.cpp index 4ec935752..0274391a2 100644 --- a/src/nodes/QskSceneTexture.cpp +++ b/src/nodes/QskSceneTexture.cpp @@ -210,7 +210,12 @@ namespace QSize Renderer::textureSize() const { - return m_fbo ? m_fbo->size() : QSize(); +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + if ( m_fbo ) return m_fbo->size(); +#else + if( m_rt.rt ) return m_rt.rt->pixelSize(); +#endif + return QSize(); } void Renderer::render() From faf2ecd3c8fafea7ac627d88421d87a69666fd32 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 28 Dec 2023 17:26:24 +0100 Subject: [PATCH 09/14] docs updated --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fe3abc946..070079fed 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,12 @@ But so far only Linux is actively tested. It might support all versions Qt >= 5.15, but you can rely on: - Qt 5.15 -- current long term supported ( LTS ) version of Qt +- current long term supported ( LTS ) version of Qt ( at the moment Qt 6.5.x ) - current version of Qt -On debian bullseye these packages need to be installed: `build-essential -qt-qmake qtbase5-dev qtbase5-private-dev qtdeclarative5-dev -qtdeclarative5-private-dev libqt5svg5-dev`. +On debian bullseye these packages need to be installed for Qt5: `build-essential +qtbase5-dev qtbase5-private-dev qtdeclarative5-dev qtdeclarative5-private-dev libqt5svg5-dev`. +For Qt6 you need the corresponding ones. > Optional: When enabling the `hunspell` feature the following package needs to be installed: `libhunspell-dev` From 8149094c919847a638e857e93a9e9ad041789561 Mon Sep 17 00:00:00 2001 From: Alexander Kavon Date: Thu, 28 Dec 2023 14:01:32 -0500 Subject: [PATCH 10/14] check for any qt package greater than 5.15 otherwise automatically fallback --- cmake/QskFindMacros.cmake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cmake/QskFindMacros.cmake b/cmake/QskFindMacros.cmake index 40915c6f4..2dbe7d002 100644 --- a/cmake/QskFindMacros.cmake +++ b/cmake/QskFindMacros.cmake @@ -5,11 +5,15 @@ macro(qsk_setup_Qt) - # Define a package QT, attempt Qt6, if not fallback to Qt5 - find_package(QT NAMES Qt6 REQUIRED COMPONENTS Quick) - if (NOT QT_FOUND) - find_package(QT "5.15" NAMES Qt5 REQUIRED COMPONENTS Quick) + # Use QSK_QT_VERSION specified with baseline 5.15 + # otherwise fallback to latest known supported Qt version gte 5.15 + # set vars for correct alpha descending sort order and direction (ex. Qt6, Qt5) + if ( NOT QSK_QT_VERSION ) # QSK_QT_VERSION=Qt5 + set(QSK_QT_VERSION Qt6 Qt5) + set(CMAKE_FIND_PACKAGE_SORT_ORDER NAME) + set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC) endif() + find_package(QT "5.15" NAMES ${QSK_QT_VERSION} REQUIRED COMPONENTS Quick) if ( QT_FOUND ) From a420407a56fe509affd0740baeb8b2b7df43affe Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sat, 6 Jan 2024 15:00:23 +0100 Subject: [PATCH 11/14] qskInterpolatedColor added --- src/common/QskGradientStop.cpp | 20 +++++++++++++++++++- src/common/QskGradientStop.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/common/QskGradientStop.cpp b/src/common/QskGradientStop.cpp index ab255c678..a2a73d953 100644 --- a/src/common/QskGradientStop.cpp +++ b/src/common/QskGradientStop.cpp @@ -273,6 +273,25 @@ QskGradientStops qskInterpolatedGradientStops( return qskInterpolatedStops( from, to, ratio ); } +QColor qskInterpolatedColorAt( const QskGradientStops& stops, qreal pos ) noexcept +{ + if ( stops.isEmpty() ) + return QColor(); + + pos = qBound( 0.0, pos, 1.0 ); + + if ( pos <= stops.first().position() ) + return stops.first().color(); + + for ( int i = 1; i < stops.count(); i++ ) + { + if ( pos <= stops[i].position() ) + return qskInterpolatedColor( stops, i - 1, i, pos ); + } + + return stops.last().color(); +} + QskGradientStops qskExtractedGradientStops( const QskGradientStops& stops, qreal from, qreal to ) { @@ -421,4 +440,3 @@ QGradientStops qskToQGradientStops( const QskGradientStops& stops ) return qStops; } - diff --git a/src/common/QskGradientStop.h b/src/common/QskGradientStop.h index 2b265d66f..d115be625 100644 --- a/src/common/QskGradientStop.h +++ b/src/common/QskGradientStop.h @@ -120,6 +120,8 @@ QSK_EXPORT QDebug operator<<( QDebug, const QskGradientStop& ); typedef QVector< QskGradientStop > QskGradientStops; +QSK_EXPORT QColor qskInterpolatedColorAt( const QskGradientStops&, qreal pos ) noexcept; + QSK_EXPORT bool qskIsMonochrome( const QskGradientStops& ) noexcept; QSK_EXPORT bool qskIsVisible( const QskGradientStops& ) noexcept; From e63b064f5aa829161ffccd6df78fbe947614e083 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sat, 6 Jan 2024 15:05:30 +0100 Subject: [PATCH 12/14] QskArcShadowNode introduced ( kudos to Rick ) --- playground/shadows/ArcPage.cpp | 109 +++++++ playground/shadows/ArcPage.h | 14 + playground/shadows/BoxPage.cpp | 73 +++++ playground/shadows/BoxPage.h | 19 ++ playground/shadows/CMakeLists.txt | 5 +- playground/shadows/ShadowedArc.cpp | 269 +++++++++++++++++ playground/shadows/ShadowedArc.h | 64 +++++ playground/shadows/ShadowedBox.cpp | 13 +- playground/shadows/Slider.cpp | 47 +++ playground/shadows/Slider.h | 37 +++ playground/shadows/main.cpp | 132 ++------- src/CMakeLists.txt | 2 + src/controls/QskSkinlet.cpp | 8 +- src/nodes/QskArcNode.cpp | 94 ++++-- src/nodes/QskArcNode.h | 6 + src/nodes/QskArcShadowNode.cpp | 368 ++++++++++++++++++++++++ src/nodes/QskArcShadowNode.h | 32 +++ src/nodes/QskBoxShadowNode.cpp | 24 +- src/nodes/shaders.qrc | 5 + src/nodes/shaders/arcshadow-vulkan.frag | 46 +++ src/nodes/shaders/arcshadow-vulkan.vert | 21 ++ src/nodes/shaders/arcshadow.frag | 37 +++ src/nodes/shaders/arcshadow.frag.qsb | Bin 0 -> 2282 bytes src/nodes/shaders/arcshadow.vert | 12 + src/nodes/shaders/arcshadow.vert.qsb | Bin 0 -> 1585 bytes src/nodes/shaders/arcshadow2qsb.sh | 10 + src/nodes/shaders/boxshadow-vulkan.frag | 26 +- src/nodes/shaders/boxshadow-vulkan.vert | 2 +- src/nodes/shaders/boxshadow.frag | 26 +- src/nodes/shaders/boxshadow.frag.qsb | Bin 2656 -> 2606 bytes src/nodes/shaders/boxshadow.vert.qsb | Bin 1559 -> 1576 bytes src/nodes/shaders/vulkan2qsb.sh | 3 + 32 files changed, 1310 insertions(+), 194 deletions(-) create mode 100644 playground/shadows/ArcPage.cpp create mode 100644 playground/shadows/ArcPage.h create mode 100644 playground/shadows/BoxPage.cpp create mode 100644 playground/shadows/BoxPage.h create mode 100644 playground/shadows/ShadowedArc.cpp create mode 100644 playground/shadows/ShadowedArc.h create mode 100644 playground/shadows/Slider.cpp create mode 100644 playground/shadows/Slider.h create mode 100644 src/nodes/QskArcShadowNode.cpp create mode 100644 src/nodes/QskArcShadowNode.h create mode 100644 src/nodes/shaders/arcshadow-vulkan.frag create mode 100644 src/nodes/shaders/arcshadow-vulkan.vert create mode 100644 src/nodes/shaders/arcshadow.frag create mode 100644 src/nodes/shaders/arcshadow.frag.qsb create mode 100644 src/nodes/shaders/arcshadow.vert create mode 100644 src/nodes/shaders/arcshadow.vert.qsb create mode 100755 src/nodes/shaders/arcshadow2qsb.sh diff --git a/playground/shadows/ArcPage.cpp b/playground/shadows/ArcPage.cpp new file mode 100644 index 000000000..7ee255327 --- /dev/null +++ b/playground/shadows/ArcPage.cpp @@ -0,0 +1,109 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "ArcPage.h" +#include "ShadowedArc.h" +#include "Slider.h" + +#include + +namespace +{ + class ControlPanel : public QskGridBox + { + Q_OBJECT + + public: + ControlPanel( ShadowedArc* arc, QQuickItem* parent = nullptr ) + : QskGridBox( parent ) + { + setMargins( 5 ); + setSpacing( 10 ); + + { + auto slider = new Slider( "Start", 0, 360, 10, arc->startAngle() ); + connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setStartAngle ); + + addItem( slider, 0, 0 ); + } + { + auto slider = new Slider( "Span", -360, 360, 10, arc->spanAngle() ); + connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setSpanAngle ); + + addItem( slider, 0, 1 ); + } + { + auto slider = new Slider( "Extent", 0, 100, 1, arc->thickness() ); + connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setThickness ); + + addItem( slider, 1, 0 ); + } + { + auto slider = new Slider( "Border", 0, 10, 1, arc->borderWidth() ); + connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setBorderWidth ); + + addItem( slider, 1, 1); + } + { + auto slider = new Slider( "Spread Radius", -10, 50, 1, arc->spreadRadius() ); + connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setSpreadRadius ); + + addItem( slider, 2, 0 ); + } + { + auto slider = new Slider( "Blur Radius", 0, 50, 1, arc->blurRadius() ); + connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setBlurRadius ); + + addItem( slider, 2, 1 ); + } + { + auto slider = new Slider( "Offset X", -50, 50, 1, arc->offsetX() ); + connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setOffsetX ); + + addItem( slider, 3, 0 ); + + } + { + auto slider = new Slider( "Offset Y", -50, 50, 1, arc->offsetY() ); + connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setOffsetY ); + + addItem( slider, 3, 1 ); + } + } + }; +} + +ArcPage::ArcPage( QQuickItem* parent ) + : QskLinearBox( Qt::Vertical, parent ) +{ + auto arc = new ShadowedArc(); + arc->setMargins( 40 ); // some extra space for testing the offsets + + { + // initial settings + arc->setStartAngle( 45.0 ); + arc->setSpanAngle( 270.0 ); + arc->setThickness( 10.0 ); + + arc->setFillColor( Qt::darkRed ); + + arc->setBorderWidth( 0 ); + arc->setBorderColor( Qt::darkYellow ); + + arc->setShadowColor( Qt::black ); + arc->setSpreadRadius( 0.0 ); + arc->setBlurRadius( 4.0 ); + arc->setOffsetX( 2.0 ); + arc->setOffsetY( 2.0 ); + } + + auto panel = new ControlPanel( arc ); + panel->setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed ); + + addItem( panel ); + addItem( arc ); +} + +#include "ArcPage.moc" diff --git a/playground/shadows/ArcPage.h b/playground/shadows/ArcPage.h new file mode 100644 index 000000000..eeb620668 --- /dev/null +++ b/playground/shadows/ArcPage.h @@ -0,0 +1,14 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#pragma once + +#include + +class ArcPage : public QskLinearBox +{ + public: + ArcPage( QQuickItem* parent = nullptr ); +}; diff --git a/playground/shadows/BoxPage.cpp b/playground/shadows/BoxPage.cpp new file mode 100644 index 000000000..860c2c0f2 --- /dev/null +++ b/playground/shadows/BoxPage.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "BoxPage.h" +#include "ShadowedBox.h" +#include "Slider.h" + +#include +#include + +namespace +{ + class ControlPanel : public QskLinearBox + { + public: + ControlPanel( ShadowedBox* box, QQuickItem* parent = nullptr ) + : QskLinearBox( Qt::Vertical, parent ) + { + { + auto slider = new Slider( "Offset X", -50, 50, 1, box->offsetX() ); + connect( slider, &Slider::valueChanged, box, &ShadowedBox::setOffsetX ); + + addItem( slider ); + } + { + auto slider = new Slider( "Offset Y", -50, 50, 1, box->offsetY() ); + connect( slider, &Slider::valueChanged, box, &ShadowedBox::setOffsetY ); + + addItem( slider ); + } + { + auto slider = new Slider( "Spread Radius", -10, 50, 1, box->spreadRadius() ); + connect( slider, &Slider::valueChanged, box, &ShadowedBox::setSpreadRadius ); + + addItem( slider ); + } + { + auto slider = new Slider( "Blur Radius", 0, 50, 1, box->blurRadius() ); + connect( slider, &Slider::valueChanged, box, &ShadowedBox::setBlurRadius ); + + addItem( slider ); + } + { + auto slider = new Slider( "Opacity", 0, 1, 0.01, box->opacity() ); + connect( slider, &Slider::valueChanged, box, &ShadowedBox::setOpacity ); + + addItem( slider ); + } + } + }; +} + +BoxPage::BoxPage( QQuickItem* parent ) + : QskLinearBox( Qt::Vertical, parent ) +{ + auto box = new ShadowedBox(); + box->setMargins( 40 ); // some extra space for testing the offsets + + { + box->setOffsetX( 10 ); + box->setOffsetY( 10 ); + box->setSpreadRadius( 0 ); + box->setBlurRadius( 5 ); + } + + auto panel = new ControlPanel( box ); + panel->setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed ); + + addItem( panel ); + addItem( box ); +} diff --git a/playground/shadows/BoxPage.h b/playground/shadows/BoxPage.h new file mode 100644 index 000000000..d5dc15aa8 --- /dev/null +++ b/playground/shadows/BoxPage.h @@ -0,0 +1,19 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#pragma once + +#include + +class QskSlider; + +class BoxPage : public QskLinearBox +{ + public: + BoxPage( QQuickItem* parent = nullptr ); + + private: + void addSlider( int row, const QString&, QskSlider* ); +}; diff --git a/playground/shadows/CMakeLists.txt b/playground/shadows/CMakeLists.txt index 0d3466d70..f65ac3161 100644 --- a/playground/shadows/CMakeLists.txt +++ b/playground/shadows/CMakeLists.txt @@ -3,4 +3,7 @@ # SPDX-License-Identifier: BSD-3-Clause ############################################################################ -qsk_add_example(shadows ShadowedBox.h ShadowedBox.cpp main.cpp) +qsk_add_example(shadows + BoxPage.h BoxPage.cpp ShadowedBox.h ShadowedBox.cpp + ArcPage.h ArcPage.cpp ShadowedArc.h ShadowedArc.cpp + Slider.h Slider.cpp main.cpp) diff --git a/playground/shadows/ShadowedArc.cpp b/playground/shadows/ShadowedArc.cpp new file mode 100644 index 000000000..0ba49ad51 --- /dev/null +++ b/playground/shadows/ShadowedArc.cpp @@ -0,0 +1,269 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "ShadowedArc.h" + +#include +#include +#include +#include + +#include +#include + +QSK_SUBCONTROL( ShadowedArc, Arc ) + +namespace +{ + class Skinlet : public QskSkinlet + { + using Inherited = QskSkinlet; + + public: + enum NodeRoles { ArcRole }; + + Skinlet( QskSkin* skin = nullptr ); + + QRectF subControlRect( const QskSkinnable*, + const QRectF&, QskAspect::Subcontrol ) const override; + + QSGNode* updateSubNode( const QskSkinnable*, + quint8 nodeRole, QSGNode* ) const override; + + private: + QSGNode* updateArcNode( const ShadowedArc*, QSGNode* node ) const; + }; + + Skinlet::Skinlet( QskSkin* skin ) + : QskSkinlet( skin ) + { + setNodeRoles( { ArcRole } ); + } + + QRectF Skinlet::subControlRect( const QskSkinnable* skinnable, + const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const + { + if ( subControl == ShadowedArc::Arc ) + return contentsRect; + + return Inherited::subControlRect( skinnable, contentsRect, subControl ); + } + + QSGNode* Skinlet::updateSubNode( + const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const + { + if ( nodeRole == ArcRole ) + { + auto arc = static_cast< const ShadowedArc* >( skinnable ); + return updateArcNode( arc, node ); + } + + return Inherited::updateSubNode( skinnable, nodeRole, node ); + } + + QSGNode* Skinlet::updateArcNode( const ShadowedArc* arc, QSGNode* node ) const + { + using Q = ShadowedArc; + + const auto rect = arc->subControlRect( Q::Arc ); + if ( rect.isEmpty() ) + return nullptr; + + auto arcNode = QskSGNode::ensureNode< QskArcNode >( node ); + + const auto metrics = arc->arcMetricsHint( Q::Arc ); + const auto fillGradient = arc->gradientHint( Q::Arc ); + + const auto borderColor = arc->color( Q::Arc | QskAspect::Border ); + const auto borderWidth = arc->metric( Q::Arc | QskAspect::Border ); + + const auto shadowColor = arc->shadowColorHint( Q::Arc ); + const auto shadowMetrics = arc->shadowMetricsHint( Q::Arc ); + + arcNode->setArcData( rect, metrics, borderWidth, borderColor, + fillGradient, shadowColor, shadowMetrics); + + return arcNode; + } +} + +ShadowedArc::ShadowedArc( QQuickItem* parent ) + : Inherited( parent ) +{ + auto skinlet = new Skinlet(); + skinlet->setOwnedBySkinnable( true ); + + setSkinlet( skinlet ); + + // initial settings + + setArcMetrics( { 0.0, 360.0, 1.0, Qt::RelativeSize } ); + + setFillColor( Qt::darkRed ); + + setBorderWidth( 0 ); + setBorderColor( Qt::gray ); + + setShadowColor( Qt::black ); + setShadowMetrics( { 0, 0, QPointF( 0, 0 ), Qt::AbsoluteSize } ); +} + +ShadowedArc::~ShadowedArc() +{ +} + +void ShadowedArc::setThickness( qreal thickness ) +{ + auto metrics = arcMetrics(); + metrics.setThickness( thickness ); + + setArcMetrics( metrics ); +} + +qreal ShadowedArc::thickness() const +{ + return arcMetrics().thickness(); +} + +void ShadowedArc::setBorderWidth( qreal width ) +{ + width = std::max( width, 0.0 ); + setMetric( Arc | QskAspect::Border, width ); +} + +qreal ShadowedArc::borderWidth() const +{ + return metric( Arc | QskAspect::Border ); +} + +void ShadowedArc::setStartAngle( qreal degrees ) +{ + auto metrics = arcMetrics(); + metrics.setStartAngle( degrees ); + + setArcMetrics( metrics ); +} + +qreal ShadowedArc::startAngle() const +{ + return arcMetrics().startAngle(); +} + +void ShadowedArc::setSpanAngle( qreal degrees ) +{ + auto metrics = arcMetrics(); + metrics.setSpanAngle( degrees ); + + setArcMetrics( metrics ); +} + +qreal ShadowedArc::spanAngle() const +{ + return arcMetrics().spanAngle(); +} + +void ShadowedArc::setOffsetX( qreal dx ) +{ + auto metrics = shadowMetrics(); + metrics.setOffsetX( dx ); + + setShadowMetrics( metrics ); +} + +qreal ShadowedArc::offsetX() const +{ + return shadowMetrics().offset().x(); +} + +void ShadowedArc::setOffsetY( qreal dy ) +{ + auto metrics = shadowMetrics(); + metrics.setOffsetY( dy ); + + setShadowMetrics( metrics ); +} + +qreal ShadowedArc::offsetY() const +{ + return shadowMetrics().offset().y(); +} + +void ShadowedArc::setSpreadRadius( qreal radius ) +{ + auto metrics = shadowMetrics(); + metrics.setSpreadRadius( radius ); + + setShadowMetrics( metrics ); +} + +qreal ShadowedArc::spreadRadius() const +{ + return shadowMetrics().spreadRadius(); +} + +void ShadowedArc::setBlurRadius( qreal radius ) +{ + auto metrics = shadowMetrics(); + metrics.setBlurRadius( radius ); + + setShadowMetrics( metrics ); +} + +qreal ShadowedArc::blurRadius() const +{ + return shadowMetrics().blurRadius(); +} + +void ShadowedArc::setFillColor( const QColor& color ) +{ + setColor( Arc, color ); +} + +QColor ShadowedArc::fillColor() const +{ + return color( Arc ); +} + +void ShadowedArc::setShadowColor( const QColor& color ) +{ + setShadowColorHint( Arc, color ); +} + +QColor ShadowedArc::shadowColor() const +{ + return shadowColorHint( Arc ); +} + +void ShadowedArc::setBorderColor( const QColor& color ) +{ + setColor( Arc | QskAspect::Border, color ); +} + +QColor ShadowedArc::borderColor() const +{ + return color( Arc | QskAspect::Border ); +} + +QskShadowMetrics ShadowedArc::shadowMetrics() const +{ + return shadowMetricsHint( Arc ); +} + +void ShadowedArc::setShadowMetrics( const QskShadowMetrics& metrics ) +{ + setShadowMetricsHint( Arc, metrics ); +} + +QskArcMetrics ShadowedArc::arcMetrics() const +{ + return arcMetricsHint( Arc ); +} + +void ShadowedArc::setArcMetrics( const QskArcMetrics& metrics ) +{ + setArcMetricsHint( Arc, metrics ); +} + +#include "moc_ShadowedArc.cpp" diff --git a/playground/shadows/ShadowedArc.h b/playground/shadows/ShadowedArc.h new file mode 100644 index 000000000..a4179adef --- /dev/null +++ b/playground/shadows/ShadowedArc.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#pragma once + +#include + +class QskShadowMetrics; +class QskArcMetrics; + +class ShadowedArc : public QskControl +{ + Q_OBJECT + + using Inherited = QskControl; + + public: + QSK_SUBCONTROLS( Arc ) + + ShadowedArc( QQuickItem* parent = nullptr ); + ~ShadowedArc() override; + + qreal thickness() const; + qreal borderWidth() const; + + qreal startAngle() const; + qreal spanAngle() const; + + qreal offsetX() const; + qreal offsetY() const; + + qreal spreadRadius() const; + qreal blurRadius() const; + + QColor borderColor() const; + QColor fillColor() const; + QColor shadowColor() const; + + public Q_SLOTS: + void setThickness( qreal ); + void setBorderWidth( qreal ); + + void setStartAngle( qreal ); + void setSpanAngle( qreal ); + + void setOffsetX( qreal ); + void setOffsetY( qreal ); + + void setSpreadRadius( qreal ); + void setBlurRadius( qreal ); + + void setBorderColor( const QColor& ); + void setFillColor( const QColor& ); + void setShadowColor( const QColor& ); + + private: + QskShadowMetrics shadowMetrics() const; + void setShadowMetrics( const QskShadowMetrics& ); + + QskArcMetrics arcMetrics() const; + void setArcMetrics( const QskArcMetrics& ); +}; diff --git a/playground/shadows/ShadowedBox.cpp b/playground/shadows/ShadowedBox.cpp index 2431e80e3..cad0fd225 100644 --- a/playground/shadows/ShadowedBox.cpp +++ b/playground/shadows/ShadowedBox.cpp @@ -14,21 +14,10 @@ ShadowedBox::ShadowedBox( QQuickItem* parentItem ) : QskBox( true, parentItem ) { - QColor c( Qt::darkRed ); -#if 0 - c.setAlpha( 100 ); -#endif - - setGradientHint( Panel, c ); + setGradientHint( Panel, Qt::darkRed ); setBoxShapeHint( Panel, QskBoxShapeMetrics( 40, 0, 15, 0 ) ); setBoxBorderMetricsHint( Panel, 0 ); - -#if 0 - setBoxBorderMetricsHint( Panel, 10 ); - setBoxBorderColorsHint( Panel, Qt::blue ); -#endif - setShadowColorHint( Panel, Qt::black ); } diff --git a/playground/shadows/Slider.cpp b/playground/shadows/Slider.cpp new file mode 100644 index 000000000..0a08201a9 --- /dev/null +++ b/playground/shadows/Slider.cpp @@ -0,0 +1,47 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "Slider.h" + +#include +#include + +#include + +Slider::Slider( const QString& text, qreal min, qreal max, + qreal step, qreal value, QQuickItem* parent ) + : QskLinearBox( Qt::Horizontal, parent ) +{ + m_label = new QskTextLabel( text, this ); + m_label->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed ); + + m_slider = new QskSlider( this ); + m_slider->setBoundaries( min, max ); + m_slider->setStepSize( step ); + m_slider->setSnap( true ); + m_slider->setValue( value ); + + m_valueLabel = new QskTextLabel( this ); + m_valueLabel->setAlignment( Qt::AlignLeft | Qt::AlignVCenter ); + updateLabel( value ); + + const QFontMetricsF fm( m_valueLabel->font() ); + m_valueLabel->setFixedWidth( fm.horizontalAdvance( "-100" ) ); + + connect( m_slider, &QskSlider::valueChanged, this, &Slider::updateLabel ); + connect( m_slider, &QskSlider::valueChanged, this, &Slider::valueChanged ); +} + +void Slider::updateLabel( qreal value ) +{ + m_valueLabel->setText( QString::number( value ) ); +} + +void Slider::setValue( qreal value ) +{ + m_slider->setValue( value ); +} + +#include "moc_Slider.cpp" diff --git a/playground/shadows/Slider.h b/playground/shadows/Slider.h new file mode 100644 index 000000000..c62fa1602 --- /dev/null +++ b/playground/shadows/Slider.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#pragma once + +#include + +class QskSlider; +class QskTextLabel; + +class Slider : public QskLinearBox +{ + Q_OBJECT + + using Inherited = QskLinearBox; + + public: + Slider( const QString&, qreal min, qreal max, qreal step, + qreal value, QQuickItem* parent = nullptr ); + + qreal value() const; + + Q_SIGNALS: + void valueChanged( qreal ); + + public Q_SLOTS: + void setValue( qreal ); + + private: + void updateLabel( qreal ); + + QskTextLabel* m_label = nullptr; + QskSlider* m_slider = nullptr; + QskTextLabel* m_valueLabel = nullptr; +}; diff --git a/playground/shadows/main.cpp b/playground/shadows/main.cpp index 2d6d6de9f..c4e2cedae 100644 --- a/playground/shadows/main.cpp +++ b/playground/shadows/main.cpp @@ -3,129 +3,31 @@ * SPDX-License-Identifier: BSD-3-Clause *****************************************************************************/ -#include "ShadowedBox.h" +#include "BoxPage.h" +#include "ArcPage.h" #include #include -#include -#include -#include -#include +#include +#include #include #include -#include -class BoxPanel : public QskBox +namespace { - public: - BoxPanel( QQuickItem* parent = nullptr ) - : QskBox( parent ) + class TabView : public QskTabView { - setAutoLayoutChildren( true ); - setPadding( 60 ); - - setPanel( true ); - setGradientHint( QskBox::Panel, QGradient::SnowAgain ); - } -}; - -class Slider : public QskSlider -{ - public: - Slider( qreal min, qreal max, qreal step, qreal value, QQuickItem* parent = nullptr ) - : QskSlider( parent ) - { - setBoundaries( min, max ); - setStepSize( step ); - setSnap( true ); - setValue( value ); - } -}; - -class ValueLabel : public QskTextLabel -{ - public: - ValueLabel( QQuickItem* parent = nullptr ) - : QskTextLabel( parent ) - { - setFixedWidth( QFontMetrics( font() ).horizontalAdvance( "-100" ) ); - setAlignment( Qt::AlignLeft | Qt::AlignVCenter ); - } - - void setValue( qreal value ) - { - setText( QString::number( value ) ); - } -}; - -class GridBox : public QskGridBox -{ - public: - GridBox( QQuickItem* parent = nullptr ) - : QskGridBox( parent ) - { - setPanel( true ); - setPadding( 5 ); - setColumnStretchFactor( 1, 1 ); - - auto sliderX = new Slider( -50, 50, 1, 10 ); - auto sliderY = new Slider( -50, 50, 1, 10 ); - auto sliderSpread = new Slider( 0, 50, 1, 0 ); - auto sliderBlur = new Slider( 0, 50, 1, 10 ); - auto sliderOpacity = new Slider( 0, 1, 0.01, 1 ); - - auto panel = new BoxPanel(); - - int row = 0; - - addSlider( row++, "Offset X", sliderX ); - addSlider( row++, "Offset Y", sliderY ); - addSlider( row++, "Spread Radius", sliderSpread ); - addSlider( row++, "Blur Radius", sliderBlur ); - addSlider( row++, "Opacity", sliderOpacity ); - - addItem( panel, row, 0, -1, -1 ); - - auto box = new ShadowedBox( panel ); - - box->setOffsetX( sliderX->value() ); - box->setOffsetY( sliderY->value() ); - box->setSpreadRadius( sliderSpread->value() ); - box->setBlurRadius( sliderBlur->value() ); - box->setOpacity( sliderOpacity->value() ); - - connect( sliderX, &QskSlider::valueChanged, - box, &ShadowedBox::setOffsetX ); - - connect( sliderY, &QskSlider::valueChanged, - box, &ShadowedBox::setOffsetY ); - - connect( sliderSpread, &QskSlider::valueChanged, - box, &ShadowedBox::setSpreadRadius ); - - connect( sliderBlur, &QskSlider::valueChanged, - box, &ShadowedBox::setBlurRadius ); - - connect( sliderOpacity, &QskSlider::valueChanged, - box, &ShadowedBox::setOpacity ); - } - - private: - void addSlider( int row, const QString& text, QskSlider* slider ) - { - addItem( new QskTextLabel( text ), row, 0 ); - addItem( slider, row, 1 ); - - auto label = new ValueLabel(); - label->setValue( slider->value() ); - - addItem( label, row, 2 ); - - connect( slider, &QskSlider::valueChanged, - label, [label]( qreal value ) { label->setText( QString::number( value ) ); } ); - } -}; + public: + TabView() + { + //setTabBarEdge( Qt::LeftEdge ); + + addTab( "Arc Shadow", new ArcPage() ); + addTab( "Box Shadow", new BoxPage() ); + } + }; +} int main( int argc, char* argv[] ) { @@ -138,7 +40,7 @@ int main( int argc, char* argv[] ) SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts ); QskWindow window; - window.addItem( new GridBox() ); + window.addItem( new TabView() ); window.resize( 600, 600 ); window.show(); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3906ad948..3c6b49705 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -99,6 +99,7 @@ list(APPEND SOURCES list(APPEND HEADERS nodes/QskArcNode.h + nodes/QskArcShadowNode.h nodes/QskBasicLinesNode.h nodes/QskBoxNode.h nodes/QskBoxClipNode.h @@ -138,6 +139,7 @@ list(APPEND PRIVATE_HEADERS list(APPEND SOURCES nodes/QskArcNode.cpp + nodes/QskArcShadowNode.cpp nodes/QskBasicLinesNode.cpp nodes/QskBoxNode.cpp nodes/QskBoxClipNode.cpp diff --git a/src/controls/QskSkinlet.cpp b/src/controls/QskSkinlet.cpp index e63515192..1924339e5 100644 --- a/src/controls/QskSkinlet.cpp +++ b/src/controls/QskSkinlet.cpp @@ -231,7 +231,7 @@ static inline QSGNode* qskUpdateArcNode( return nullptr; auto arcNode = QskSGNode::ensureNode< QskArcNode >( node ); - arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient ); + arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient, {}, {} ); return arcNode; } @@ -547,11 +547,11 @@ QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, } QSGNode* QskSkinlet::updateArcNode( - const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect, + const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect, qreal borderWidth, const QColor& borderColor, const QskGradient& fillGradient, const QskArcMetrics& metrics ) { - return qskUpdateArcNode( skinnable, node, rect, + return qskUpdateArcNode( skinnable, node, rect, borderWidth, borderColor, fillGradient, metrics ); } @@ -594,7 +594,7 @@ QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, } QSGNode* QskSkinlet::updateLineNode( const QskSkinnable* skinnable, - QSGNode* node, const QLineF& line, QskAspect::Subcontrol subControl ) + QSGNode* node, const QLineF& line, QskAspect::Subcontrol subControl ) { auto lineStipple = skinnable->stippleMetricsHint( subControl ); if ( !lineStipple.isValid() ) diff --git a/src/nodes/QskArcNode.cpp b/src/nodes/QskArcNode.cpp index a58a72df4..ad280879a 100644 --- a/src/nodes/QskArcNode.cpp +++ b/src/nodes/QskArcNode.cpp @@ -5,15 +5,27 @@ #include "QskArcNode.h" #include "QskArcMetrics.h" +#include "QskArcShadowNode.h" #include "QskMargins.h" #include "QskGradient.h" #include "QskShapeNode.h" #include "QskStrokeNode.h" #include "QskSGNode.h" +#include "QskShadowMetrics.h" #include #include +namespace +{ + enum NodeRole + { + ShadowRole, + FillRole, + BorderRole + }; +} + static inline QskGradient qskEffectiveGradient( const QskGradient& gradient, const QskArcMetrics& metrics ) { @@ -54,6 +66,14 @@ static inline QRectF qskEffectiveRect( return qskValidOrEmptyInnerRect( rect, QskMargins( 0.5 * borderWidth ) ); } +static void qskUpdateChildren( QSGNode* parentNode, quint8 role, QSGNode* node ) +{ + static const QVector< quint8 > roles = { ShadowRole, FillRole, BorderRole }; + + auto oldNode = QskSGNode::findChildNode( parentNode, role ); + QskSGNode::replaceChildNode( roles, role, parentNode, oldNode, node ); +} + QskArcNode::QskArcNode() { } @@ -65,20 +85,24 @@ QskArcNode::~QskArcNode() void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics, const QskGradient& fillGradient ) { - setArcData( rect, arcMetrics, 0.0, QColor(), fillGradient ); + setArcData( rect, arcMetrics, 0.0, QColor(), fillGradient, {}, {} ); } void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics, - qreal borderWidth, const QColor& borderColor, const QskGradient& fillGradient ) + const qreal borderWidth, const QColor& borderColor, const QskGradient& fillGradient ) { - enum NodeRole - { - FillRole, - BorderRole - }; + setArcData( rect, arcMetrics, borderWidth, borderColor, fillGradient, {}, {} ); +} + +void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics, + const qreal borderWidth, const QColor& borderColor, const QskGradient& fillGradient, + const QColor& shadowColor, const QskShadowMetrics& shadowMetrics ) +{ + const auto metricsArc = qskEffectiveMetrics( arcMetrics, rect ); + const auto gradient = qskEffectiveGradient( fillGradient, metricsArc ); - const auto metrics = qskEffectiveMetrics( arcMetrics, rect ); - const auto gradient = qskEffectiveGradient( fillGradient, metrics ); + auto shadowNode = static_cast< QskArcShadowNode* >( + QskSGNode::findChildNode( this, ShadowRole ) ); auto fillNode = static_cast< QskShapeNode* >( QskSGNode::findChildNode( this, FillRole ) ); @@ -89,22 +113,52 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics const auto arcRect = qskEffectiveRect( rect, borderWidth ); if ( arcRect.isEmpty() ) { + delete shadowNode; delete fillNode; delete borderNode; - return; } - const auto path = metrics.painterPath( arcRect ); + const auto isFillNodeVisible = gradient.isVisible() && !metricsArc.isNull(); + const auto isStrokeNodeVisible = borderWidth > 0.0 && borderColor.alpha() > 0; + const auto isShadowNodeVisible = shadowColor.alpha() > 0.0 && isFillNodeVisible; - if ( gradient.isVisible() && !metrics.isNull() ) + const auto path = metricsArc.painterPath( arcRect ); + + if ( isShadowNodeVisible ) + { + if ( shadowNode == nullptr ) + { + shadowNode = new QskArcShadowNode; + QskSGNode::setNodeRole( shadowNode, ShadowRole ); + } + + /* + The shader of the shadow node is for circular arcs and we have some + unwanted scaling issues for the spread/blur values when having ellipsoid + arcs. We might also want to add the spread value to the ends of the arc + and not only to its radius. TODO ... + */ + + const auto sm = shadowMetrics.toAbsolute( arcRect.size() ); + const auto shadowRect = sm.shadowRect( arcRect ); + const auto spreadRadius = sm.spreadRadius() + 0.5 * metricsArc.thickness(); + + shadowNode->setShadowData( shadowRect, spreadRadius, sm.blurRadius(), + metricsArc.startAngle(), metricsArc.spanAngle(), shadowColor ); + } + else + { + delete shadowNode; + shadowNode = nullptr; + } + + if ( isFillNodeVisible ) { if ( fillNode == nullptr ) { fillNode = new QskShapeNode; QskSGNode::setNodeRole( fillNode, FillRole ); - - prependChildNode( fillNode ); } fillNode->updateNode( path, QTransform(), arcRect, gradient ); @@ -112,25 +166,29 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics else { delete fillNode; + fillNode = nullptr; } - if ( borderWidth > 0.0 && borderColor.alpha() > 0 ) + if ( isStrokeNodeVisible ) { if ( borderNode == nullptr ) { borderNode = new QskStrokeNode; QskSGNode::setNodeRole( borderNode, BorderRole ); - - appendChildNode( borderNode ); } QPen pen( borderColor, borderWidth ); pen.setCapStyle( Qt::FlatCap ); - + borderNode->updateNode( path, QTransform(), pen ); } else { delete borderNode; + borderNode = nullptr; } + + qskUpdateChildren(this, ShadowRole, shadowNode); + qskUpdateChildren(this, FillRole, fillNode); + qskUpdateChildren(this, BorderRole, borderNode); } diff --git a/src/nodes/QskArcNode.h b/src/nodes/QskArcNode.h index 1e3e44d1c..16784f2aa 100644 --- a/src/nodes/QskArcNode.h +++ b/src/nodes/QskArcNode.h @@ -10,6 +10,7 @@ class QskArcMetrics; class QskGradient; +class QskShadowMetrics; /* For the moment a QPainterPath/QskShapeNode. @@ -23,8 +24,13 @@ class QSK_EXPORT QskArcNode : public QskShapeNode ~QskArcNode() override; void setArcData( const QRectF&, const QskArcMetrics&, const QskGradient& ); + void setArcData( const QRectF&, const QskArcMetrics&, qreal borderWidth, const QColor& borderColor, const QskGradient& ); + + void setArcData( const QRectF&, const QskArcMetrics&, + qreal borderWidth, const QColor& borderColor, const QskGradient&, + const QColor& shadowColor, const QskShadowMetrics&); }; #endif diff --git a/src/nodes/QskArcShadowNode.cpp b/src/nodes/QskArcShadowNode.cpp new file mode 100644 index 000000000..8ced5062d --- /dev/null +++ b/src/nodes/QskArcShadowNode.cpp @@ -0,0 +1,368 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "QskArcShadowNode.h" + +#include +#include +#include +#include + +#include + +QSK_QT_PRIVATE_BEGIN +#include +QSK_QT_PRIVATE_END + +// QSGMaterialRhiShader became QSGMaterialShader in Qt6 + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) +#include +using RhiShader = QSGMaterialRhiShader; +#else +using RhiShader = QSGMaterialShader; +#endif + +namespace +{ + class Material final : public QSGMaterial + { + public: + Material(); + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + QSGMaterialShader* createShader() const override; +#else + QSGMaterialShader* createShader( QSGRendererInterface::RenderMode ) const override; +#endif + + QSGMaterialType* type() const override; + int compare( const QSGMaterial* other ) const override; + + QVector4D m_color { 0, 0, 0, 1 }; + QVector4D m_arc = {}; + + float m_spreadRadius = 0.0f; + float m_blurRadius = 0.0f; + }; +} + +namespace +{ + class ShaderRhi final : public RhiShader + { + public: + ShaderRhi() + { + const QString root( ":/qskinny/shaders/" ); + setShaderFileName( VertexStage, root + "arcshadow.vert.qsb" ); + setShaderFileName( FragmentStage, root + "arcshadow.frag.qsb" ); + } + + bool updateUniformData( RenderState& state, + QSGMaterial* const newMaterial, QSGMaterial* const oldMaterial ) override + { + const auto matOld = static_cast< Material* >( oldMaterial ); + const auto matNew = static_cast< Material* >( newMaterial ); + + Q_ASSERT( state.uniformData()->size() == 108 ); + + auto data = state.uniformData()->data(); + bool changed = false; + + if ( state.isMatrixDirty() ) + { + const auto matrix = state.combinedMatrix(); + memcpy( data + 0, matrix.constData(), 64 ); + + changed = true; + } + + if ( matOld == nullptr || matNew->m_color != matOld->m_color ) + { + memcpy( data + 64, &matNew->m_color, 16 ); + changed = true; + } + + if ( matOld == nullptr || matNew->m_arc != matOld->m_arc ) + { + memcpy( data + 80, &matNew->m_arc, 16 ); + changed = true; + } + + if ( matOld == nullptr || matNew->m_spreadRadius != matOld->m_spreadRadius ) + { + memcpy( data + 96, &matNew->m_spreadRadius, 4 ); + changed = true; + } + + if ( matOld == nullptr || matNew->m_blurRadius != matOld->m_blurRadius ) + { + memcpy( data + 100, &matNew->m_blurRadius, 4 ); + changed = true; + } + + if ( state.isOpacityDirty() ) + { + const float opacity = state.opacity(); + memcpy( data + 104, &opacity, 4 ); + + changed = true; + } + + return changed; + } + }; +} + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + +namespace +{ + // the old type of shader - specific for OpenGL + + class ShaderGL final : public QSGMaterialShader + { + struct Uniforms + { + int matrix = -1; + int color = -1; + int arc = -1; + int spreadRadius = -1; + int blurRadius = -1; + int opacity = -1; + }; + + public: + ShaderGL() + { + const QString root( ":/qskinny/shaders/" ); + setShaderSourceFile( QOpenGLShader::Vertex, root + "arcshadow.vert" ); + setShaderSourceFile( QOpenGLShader::Fragment, root + "arcshadow.frag" ); + } + + char const* const* attributeNames() const override + { + static char const* const names[] = { "in_vertex", "in_coord", nullptr }; + return names; + } + + void initialize() override + { + QSGMaterialShader::initialize(); + + const auto* const p = program(); + + id.matrix = p->uniformLocation( "matrix" ); + id.color = p->uniformLocation( "color" ); + id.arc = p->uniformLocation( "arc" ); + id.spreadRadius = p->uniformLocation( "spreadRadius" ); + id.blurRadius = p->uniformLocation( "blurRadius" ); + id.opacity = p->uniformLocation( "opacity" ); + } + + void updateState( const QSGMaterialShader::RenderState& state, + QSGMaterial* const newMaterial, QSGMaterial* const oldMaterial ) override + { + auto* const p = program(); + + if ( state.isMatrixDirty() ) + { + p->setUniformValue( id.matrix, state.combinedMatrix() ); + } + + if ( state.isOpacityDirty() ) + { + p->setUniformValue( id.opacity, state.opacity() ); + } + + auto updateMaterial = ( oldMaterial == nullptr ) || + ( newMaterial->compare( oldMaterial ) != 0 ); + + updateMaterial |= state.isCachedMaterialDataDirty(); + + if ( updateMaterial ) + { + const auto* const material = static_cast< const Material* >( newMaterial ); + + p->setUniformValue( id.color, material->m_color ); + p->setUniformValue( id.arc, material->m_arc ); + p->setUniformValue( id.spreadRadius, material->m_spreadRadius ); + p->setUniformValue( id.blurRadius, material->m_blurRadius ); + } + } + + private: + Uniforms id; + }; +} + +#endif + +namespace +{ + Material::Material() + { + setFlag( QSGMaterial::Blending, true ); +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + setFlag( QSGMaterial::SupportsRhiShader, true ); +#endif + } + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + + QSGMaterialShader* Material::createShader() const + { + if ( !( flags() & QSGMaterial::RhiShaderWanted ) ) + return new ShaderGL(); + + return new ShaderRhi(); + } + +#else + + QSGMaterialShader* Material::createShader( QSGRendererInterface::RenderMode ) const + { + return new ShaderRhi(); + } + +#endif + + QSGMaterialType* Material::type() const + { + static QSGMaterialType staticType; + return &staticType; + } + + int Material::compare( const QSGMaterial* const other ) const + { + auto material = static_cast< const Material* >( other ); + + if ( ( material->m_color == m_color ) + && ( material->m_arc == m_arc ) + && qFuzzyCompare( material->m_spreadRadius, m_spreadRadius ) + && qFuzzyCompare( material->m_blurRadius, m_blurRadius ) ) + { + return 0; + } + + return QSGMaterial::compare( other ); + } +} + +class QskArcShadowNodePrivate final : public QSGGeometryNodePrivate +{ + public: + QskArcShadowNodePrivate() + : geometry( QSGGeometry::defaultAttributes_TexturedPoint2D(), 4 ) + { + } + + QSGGeometry geometry; + Material material; + QRectF rect; +}; + +QskArcShadowNode::QskArcShadowNode() + : QSGGeometryNode( *new QskArcShadowNodePrivate ) +{ + Q_D( QskArcShadowNode ); + + setGeometry( &d->geometry ); + setMaterial( &d->material ); + + d->geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip ); + d->material.setFlag( QSGMaterial::Blending ); +} + +QskArcShadowNode::~QskArcShadowNode() = default; + +void QskArcShadowNode::setShadowData( + const QRectF& rect, qreal spreadRadius, qreal blurRadius, + qreal startAngle, qreal spanAngle, const QColor& color ) +{ + if ( qFuzzyIsNull( spanAngle ) || color.alpha() == 0 ) + { + setBoundingRectangle( {} ); + return; + } + + Q_D( QskArcShadowNode ); + + if ( d->rect != rect ) + { + setBoundingRectangle( rect ); // bounding rectangle includig spread/blur + } + + const auto size = qMin( rect.width(), rect.height() ); + + { +#if 1 + const auto a = color.alphaF(); + const QVector4D c( color.redF() * a, color.greenF() * a, color.blueF() * a, a ); +#else + const QVector4D c( color.redF(), color.greenF(), color.blueF(), color.alphaF() ); +#endif + + if ( d->material.m_color != c ) + { + d->material.m_color = c; + markDirty( QSGNode::DirtyMaterial ); + } + } + + { + const float r = spreadRadius / size; + + if ( d->material.m_spreadRadius != r ) + { + d->material.m_spreadRadius = r; + markDirty( QSGNode::DirtyMaterial ); + } + } + + { + const float r = blurRadius / size; + + if ( d->material.m_blurRadius != r ) + { + d->material.m_blurRadius = r; + markDirty( QSGNode::DirtyMaterial ); + } + } + + { + QVector4D arc( 0.0, 0.0, 1.0, 0.0 ); + + { + const auto a1 = qDegreesToRadians( startAngle + 0.5 * spanAngle ); + const auto a2 = qDegreesToRadians( 0.5 * qAbs( spanAngle ) ); + + arc = QVector4D( ::cos( a1 ), ::sin( a1 ), ::cos( a2 ), ::sin( a2 ) ); + } + + if ( d->material.m_arc != arc ) + { + d->material.m_arc = arc; + markDirty( QSGNode::DirtyMaterial ); + } + } +} + +void QskArcShadowNode::setBoundingRectangle( const QRectF& rect ) +{ + Q_D( QskArcShadowNode ); + + if ( d->rect == rect ) + return; + + d->rect = rect; + + QSGGeometry::updateTexturedRectGeometry( + &d->geometry, d->rect, { -0.5, -0.5, 1.0, 1.0 } ); + d->geometry.markVertexDataDirty(); + + markDirty( QSGNode::DirtyGeometry ); +} diff --git a/src/nodes/QskArcShadowNode.h b/src/nodes/QskArcShadowNode.h new file mode 100644 index 000000000..5d76b9bf8 --- /dev/null +++ b/src/nodes/QskArcShadowNode.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_ARC_SHADOW_NODE_H +#define QSK_ARC_SHADOW_NODE_H + +#include "QskGlobal.h" +#include + +class QskArcMetrics; +class QskShadowMetrics; + +class QskArcShadowNodePrivate; + +class QskArcShadowNode : public QSGGeometryNode +{ + public: + QskArcShadowNode(); + ~QskArcShadowNode() override; + + void setShadowData( const QRectF&, qreal spreadRadius, qreal blurRadius, + qreal startAngle, qreal spanAngle, const QColor& ); + + private: + void setBoundingRectangle( const QRectF& ); + + Q_DECLARE_PRIVATE( QskArcShadowNode ) +}; + +#endif diff --git a/src/nodes/QskBoxShadowNode.cpp b/src/nodes/QskBoxShadowNode.cpp index d94d8ad36..6f730ceb7 100644 --- a/src/nodes/QskBoxShadowNode.cpp +++ b/src/nodes/QskBoxShadowNode.cpp @@ -40,7 +40,7 @@ namespace int compare( const QSGMaterial* other ) const override; - QVector2D m_aspect = QVector2D{ 1, 1 }; + QVector2D m_aspectRatio = QVector2D{ 1, 1 }; QVector4D m_radius = QVector4D{ 0, 0, 0, 0 }; QVector4D m_color = QVector4D{ 0, 0, 0, 1 }; float m_blurExtent = 0.0; @@ -91,9 +91,9 @@ namespace changed = true; } - if ( matOld == nullptr || matNew->m_aspect != matOld->m_aspect ) + if ( matOld == nullptr || matNew->m_aspectRatio != matOld->m_aspectRatio ) { - memcpy( data + 96, &matNew->m_aspect, 8 ); + memcpy( data + 96, &matNew->m_aspectRatio, 8 ); changed = true; } @@ -146,7 +146,7 @@ namespace auto p = program(); m_matrixId = p->uniformLocation( "matrix" ); - m_aspectId = p->uniformLocation( "aspect" ); + m_aspectRatioId = p->uniformLocation( "aspectRatio" ); m_opacityId = p->uniformLocation( "opacity" ); m_blurExtentId = p->uniformLocation( "blurExtent" ); m_radiusId = p->uniformLocation( "radius" ); @@ -173,7 +173,7 @@ namespace { auto material = static_cast< const Material* >( newMaterial ); - p->setUniformValue( m_aspectId, material->m_aspect ); + p->setUniformValue( m_aspectRatioId, material->m_aspectRatio ); p->setUniformValue( m_blurExtentId, material->m_blurExtent); p->setUniformValue( m_radiusId, material->m_radius ); p->setUniformValue( m_colorId, material->m_color ); @@ -183,7 +183,7 @@ namespace private: int m_matrixId = -1; int m_opacityId = -1; - int m_aspectId = -1; + int m_aspectRatioId = -1; int m_blurExtentId = -1; int m_radiusId = -1; int m_colorId = -1; @@ -231,7 +231,7 @@ int Material::compare( const QSGMaterial* other ) const auto material = static_cast< const Material* >( other ); if ( ( material->m_color == m_color ) - && ( material->m_aspect == m_aspect ) + && ( material->m_aspectRatio == m_aspectRatio ) && qFuzzyCompare(material->m_blurExtent, m_blurExtent) && qFuzzyCompare(material->m_radius, m_radius) ) { @@ -284,16 +284,16 @@ void QskBoxShadowNode::setShadowData( d->geometry.markVertexDataDirty(); markDirty( QSGNode::DirtyGeometry ); - QVector2D aspect( 1.0, 1.0 ); + QVector2D aspectRatio( 1.0, 1.0 ); if ( rect.width() >= rect.height() ) - aspect.setX( rect.width() / rect.height() ); + aspectRatio.setX( rect.width() / rect.height() ); else - aspect.setY( rect.height() / rect.width() ); + aspectRatio.setY( rect.height() / rect.width() ); - if ( d->material.m_aspect != aspect ) + if ( d->material.m_aspectRatio != aspectRatio ) { - d->material.m_aspect = aspect; + d->material.m_aspectRatio = aspectRatio; markDirty( QSGNode::DirtyMaterial ); } } diff --git a/src/nodes/shaders.qrc b/src/nodes/shaders.qrc index 82a427483..7d2d15a42 100644 --- a/src/nodes/shaders.qrc +++ b/src/nodes/shaders.qrc @@ -2,6 +2,11 @@ + shaders/arcshadow.frag + shaders/arcshadow.vert + shaders/arcshadow.frag.qsb + shaders/arcshadow.vert.qsb + shaders/boxshadow.vert.qsb shaders/boxshadow.frag.qsb shaders/boxshadow.vert diff --git a/src/nodes/shaders/arcshadow-vulkan.frag b/src/nodes/shaders/arcshadow-vulkan.frag new file mode 100644 index 000000000..49646de34 --- /dev/null +++ b/src/nodes/shaders/arcshadow-vulkan.frag @@ -0,0 +1,46 @@ +#version 440 + +layout( location = 0 ) in vec2 coord; +layout( location = 0 ) out vec4 fragColor; + +layout( std140, binding = 0 ) uniform buf +{ + mat4 matrix; + vec4 color; + + /* + arc.xy: cos/sin of the angle of the midpoint + arc.zw: cos/sin of the angle between midpoint/endpoint + */ + vec4 arc; + + float spreadRadius; + float blurRadius; + + float opacity; +} ubuf; + +mat2 rotation( vec2 v ) { return mat2( v.x, -v.y, v.y, v.x ); } + +void main() +{ + float radius = 0.5 - ubuf.blurRadius - ubuf.spreadRadius; + + float dist = abs( length( coord ) - radius ) - ubuf.spreadRadius; + + if ( ( ubuf.arc.z ) < 1.0 && ( dist < 1.0 ) ) + { + vec2 v = coord * rotation( ubuf.arc.xy ); // x-axial symmetric + v.y = abs( v.y ); + + v *= rotation ( ubuf.arc.wz ); // end point to 90° + if ( v.x < 0.0 ) + { + v.y = max( 0.0, abs( v.y - radius ) - ubuf.spreadRadius ); + dist = max( dist, length( v ) ); + } + } + + float a = 1.0 - smoothstep( 0.0, ubuf.blurRadius, dist ); + fragColor = ubuf.color * a * ubuf.opacity; +} diff --git a/src/nodes/shaders/arcshadow-vulkan.vert b/src/nodes/shaders/arcshadow-vulkan.vert new file mode 100644 index 000000000..4899db18d --- /dev/null +++ b/src/nodes/shaders/arcshadow-vulkan.vert @@ -0,0 +1,21 @@ +#version 440 + +layout( location = 0 ) in vec4 in_vertex; +layout( location = 1 ) in vec2 in_coord; +layout( location = 0 ) out vec2 coord; + +layout( std140, binding = 0 ) uniform buf +{ + mat4 matrix; + vec4 color; + vec4 arc; + float spreadRadius; + float blurRadius; + float opacity; +} ubuf; + +void main() +{ + coord = in_coord; + gl_Position = ubuf.matrix * in_vertex; +} diff --git a/src/nodes/shaders/arcshadow.frag b/src/nodes/shaders/arcshadow.frag new file mode 100644 index 000000000..738b0ed49 --- /dev/null +++ b/src/nodes/shaders/arcshadow.frag @@ -0,0 +1,37 @@ +varying lowp vec2 coord; + +uniform lowp vec4 color; +uniform lowp float spreadRadius; +uniform lowp float blurRadius; +uniform lowp float opacity; + +/* + arc.xy: cos/sin of the angle of the midpoint + arc.zw: cos/sin of the angle between midpoint/endpoint + */ +uniform lowp vec4 arc; + +mat2 rotation( vec2 v ) { return mat2( v.x, -v.y, v.y, v.x ); } + +void main() +{ + float radius = 0.5 - blurRadius - spreadRadius; + + float dist = abs( length( coord ) - radius ) - spreadRadius; + + if ( ( arc.z < 1.0 ) && ( dist < 1.0 ) ) + { + vec2 v = coord * rotation( arc.xy ); // x-axial symmetric + v.y = abs( v.y ); + + v *= rotation( arc.wz ); // end point at 90° + if ( v.x < 0.0 ) + { + v.y = max( 0.0, abs( v.y - radius ) - spreadRadius ); + dist = max( dist, length( v ) ); + } + } + + float a = 1.0 - smoothstep( 0.0, blurRadius, dist ); + gl_FragColor = color * a * opacity; +} diff --git a/src/nodes/shaders/arcshadow.frag.qsb b/src/nodes/shaders/arcshadow.frag.qsb new file mode 100644 index 0000000000000000000000000000000000000000..1c90703303dc33dbd0af723f231835b235812372 GIT binary patch literal 2282 zcmVPk-Q+D~di zY>OsH3h@Gbo98;?nt=O=2tacR8hz0Q`Y?@MWqdE02kka@;3^;H*92&dfnBq$?ZtLd zB%%R~9TO%ZZ(XO)GtXN9%8R7PtSZB_(|f2)tN>drBT{xc*$wYn)1U^ zy;=6;rNB$wx|5{ky1#vy;fWuV&*4X*cG8xxShn&gSnig)wSm&Bmu;t&`xU@D;Nlql&nq5R*uZaUfPU9 zX~b;(V7ChGyqswjI=Q^;LY=$>JeLEvEDIwIypYX=ezHw`;4s7k&R0F4wzl%x1vgY# zoR&@a1P1u5czT+QPnkx%m*vA8bN;a3VLp~@BOw)iG#qP{=I+v^=}qr`wrjS};sVHiT1zaJq07QRYI$ zP1421z->c9ih1MF{&UGJ;YB&gG$D|el%H0PvF}>hr%tE~k}&6BCJCY_ttF|~(600? zjl8l$x?pJ)vTB9Zq?lFB!mPVF_)ti<_*u1ptf~QQjcTz9{Zlu`TISa!y|Qt!%SDi^ zf^Asn+r@6_MLSO5ehK!vy$mfnx}kv#SiT=sDv6icrDCq9pD9M|Y%kyZ5I)F#AJ+os z(o8%%ecTrYxwA>_=k2aV#!YiL!1^GkJDh28ycaI@fUL7-opfXE=K7|y5=Tkm+zcDN zz1XzWMS17_&sJ{VUcX-KX~SIjb~A14-N_f_#-?+}jjLWtDh8XZsonp%t+pb+tZX~D zuwD*c_W@?Bb=vrp>_nsvLc=jC-OpSJfo zgS~H<8EAiyh`m~1W&a*X-LJBD`*WV${+_b&RR%g=CEvd?dRpH=+j9omo|C=vSk_>v zsGn$ip#G%!wTEZ3a&;9h^PvJ2xbcOSx(0?A)1r|gG!sX9x;X0+tPFb<>|);@Lz~pA z%URpD{x&)?HHmM}7HlqlN9fDY-SK_;FuWY&_v)>UTLpNNEzBB1bHW!M}Qmo-=TSWkH(DNi!={L@4Li% zk;yKS>==z3KbMC1d5LhNZ<*vTk)P)Yy9T4E<0|R6Ol!jExkh7u1wH8V3Sn(Kd1S_SaDr`#Qa>Qn*5mX+aNKi zzBTqS**HWoe@J8Rf-dYMYeFA)ApR%7Q1%yObB$zf5{CA1ZLJHv9*?p3HwZU*y2J9c z!DK&SvZ(tL;x(~-IwZEw2sg3)k}$kYUqxM;G-hJ^oMPK#b9tBSn^?af>~j|D7tG%+ z;y=n_{T1OR*A8KCQeIt_R~)+sw@Z1w$8>KGna2|0hQ{A1UK1Yil-XQY*j#%etBI-@ ztce=oMxRgeHKlJ-VPBFyn_}{r&-eTCcc1u;emsgi&*nQIe&cH>vf2-r&4}5o6Q8M3 z9Q!BCotZ}-ux{g!wsX>@ovmLV8 z7TKD8K)A8_Q0SigN07ns-w@A3=KF6+&n}aDM7WWAOtO#2mmR|X4G~;~`vR?fbA*ZS z3-16Q{ze?8`T8Nt=gWli_5BLrhUYl(@OAns;g5(uL70(wZHUZC!VS-lhS+|c@HMK> zACo^P7Wt5)?1i0<%?&lPH|6V*$yKNZh z*@Y7@xCejI_WPNfJpR9r9o0nad+4aA3Pzv$yfL%!TuvLG#W~~iIbr;-P8aoQBCpam ztJ23=mCk)ntF-0D9sJV`FV%yxJSfZWU0GJ^&IeGL*WJ{;TiklO+APyI*5+Tb+AJ0= z2(siWs^(W~4ejaD0PKh9us>=Z)bT+bAJp;lsbg~(#r~gzscHScPsG3<^?Jwu1J}Sl EP`UJ}DgXcg literal 0 HcmV?d00001 diff --git a/src/nodes/shaders/arcshadow.vert b/src/nodes/shaders/arcshadow.vert new file mode 100644 index 000000000..018500396 --- /dev/null +++ b/src/nodes/shaders/arcshadow.vert @@ -0,0 +1,12 @@ +uniform highp mat4 matrix; + +attribute highp vec4 in_vertex; +attribute mediump vec2 in_coord; + +varying mediump vec2 coord; + +void main() +{ + coord = in_coord; + gl_Position = matrix * in_vertex; +} diff --git a/src/nodes/shaders/arcshadow.vert.qsb b/src/nodes/shaders/arcshadow.vert.qsb new file mode 100644 index 0000000000000000000000000000000000000000..ae08a617e90ce04b542051094ed46eb879ef228c GIT binary patch literal 1585 zcmV-12G02a03r-{ob6iOZWBio9@|MsHVGtYAkYF`NSfLqbxjnYN(chcsvsc|B^9cK zqGe;R!?yOW*&j$ixoq!y(!m1&Y5q{|IX|T z2qA`rx=L_Q30HW+5_RFjUmzO5E5cp)hc1!6W(faMIDn4exeweS?CLwh5-$L0k$fBn z^5H(!X9V^cIg9$qNA!r;6|rbSYZQKUyTwo=a8HP~u)&f5d_b$msqZesP3eX*pe0RE z4&LS6{2BqN0l*b(vmfld2t@~g4!|2?OFmsNH6$mVk$~Ja3m&xq81xv_=r`yzSl$76 z9pI5TAo%ls@T0B?8Z?oxiuSzg)mw4HF>kk>$ZlC-)M&Z8cZ`G|y6wi7_^3X=V;FJh zdV8j4x1F$K*Bw)iS~rX^3gUWX?#4~yjbXyoZ25Myy1#0+?I>{f*BR5S`z=36aqOVZ zXfx~tj@{U@8*UtO{%$J{@?0M*aifEE<1jI#ZM$C0^5ck`vjUp^pkY3J8i!6$Zuxbu zR@vD}S+du%HvQ0zT;Bs+hnfh=Nq4=Jucqr+FP$KA_F>DvnM=DhCW&eGTBQI)L)NS2{&Qs9&fVdL_xw(6hQK zBpH%5$nBmRMo?F~HEnC)zp~o)4}Orm@o1VwrmdL};2-^FGjyVIy;e!RYZ55anZd30 zz(JZbs2d!mKs@;w^vygvDTyq$dXPs`spO!qE2?^+e(lJu_n1i5Q(fIUN;8vWr{%EJ z@{Uvq(VMfq`EcurbwBXK(0b@~(vu&bpVrLpzWM(CM0(vDl@uK&xtL@WR0mC3uQ-r!sYOg&RW zTie@>@&@nCOuR|5awz_$CuXK$tUA<0*$tXv^l(58_a&h~oRe7vQq`TqYWJ8wv@E2R z9P+sbSBGDdZTABF1&A}k zkZt@V*E+_8+Rl6g_hq;jPzE5zh!#YT6OD2nz(#PI`t(*v^9sb{xFYdNQdX(UdjN9h zX#6nYH9gPdY92T*H%OXSAlzNXD-v&$@k+#d#&|=-YcSq0@t%{NS|0j;0e-Ktcp!a+ z(U&vvS|IwAjBQcMxdJjvB=a1!aBFG8JqLKijZmKn^eEYl{B@$oh==_K`LFv87I&04 zN%GLov+z7ky70P2^clim1bT|_XQbUKZ(7C_>6{_`)1-4osJbbUj#<)CARV)kudeez zpCg$=Qpc!_ujXl8`bK@{DIRmA59tdmMjv-$spw0jdy?>%L{hWZe}!zFBzj)xLjZ+G zdV$%GFa1&xy6v-YLaen~^Yifh?J3%?R1HEHJ-vb2t@d^2Mmhk6f zUKD?W^7$$G^9zibq*z}hKFUG=u2N3UlAf!CLm6oIXXN8OpwOQ(!!I&ih5CL1xkxY3 z*a{oF%*I|LeanRX8>0A?S`zep#!mvEqxk#DNx&eT1oZmm=BQi8=DZ*?LVkP$ihqA+ zA+O%*q(P*=f{yt~!~6XT;^zZ6ul{jzJ}^M%1Mm49;6vZ$57NH44rnzuoD;m~0<)I&g9_@c&K*PEG;_?<8Q* jckX?5(wTo(*Qc-Qe>;fWZadeX`K~^)KR5ngN?pPF4kaH6 literal 0 HcmV?d00001 diff --git a/src/nodes/shaders/arcshadow2qsb.sh b/src/nodes/shaders/arcshadow2qsb.sh new file mode 100755 index 000000000..d78eed3bf --- /dev/null +++ b/src/nodes/shaders/arcshadow2qsb.sh @@ -0,0 +1,10 @@ +#! /bin/sh + +function qsbcompile { + qsbfile=`echo $1 | sed 's/-vulkan//'` + qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o ${qsbfile}.qsb $1 + # qsb --qt6 -b -o ${qsbfile}.qsb $1 +} + +qsbcompile arcshadow-vulkan.vert +qsbcompile arcshadow-vulkan.frag diff --git a/src/nodes/shaders/boxshadow-vulkan.frag b/src/nodes/shaders/boxshadow-vulkan.frag index a5d5451e9..58d79062b 100644 --- a/src/nodes/shaders/boxshadow-vulkan.frag +++ b/src/nodes/shaders/boxshadow-vulkan.frag @@ -8,7 +8,7 @@ layout( std140, binding = 0 ) uniform buf mat4 matrix; vec4 color; vec4 radius; - vec2 aspect; + vec2 aspectRatio; float blurExtent; float opacity; } ubuf; @@ -25,25 +25,21 @@ void main() { vec4 col = vec4(0.0); - if ( ubuf.opacity > 0.0 ) - { - const float minRadius = 0.05; + float e2 = 0.5 * ubuf.blurExtent; + float r = 2.0 * effectiveRadius( ubuf.radius, coord ); - float e2 = 0.5 * ubuf.blurExtent; - float r = 2.0 * effectiveRadius( ubuf.radius, coord ); + const float minRadius = 0.05; + float f = minRadius / max( r, minRadius ); - float f = minRadius / max( r, minRadius ); + r += e2 * f; - r += e2 * f; + vec2 d = r + ubuf.blurExtent - ubuf.aspectRatio * ( 1.0 - abs( 2.0 * coord ) ); + float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) ); - vec2 d = r + ubuf.blurExtent - ubuf.aspect * ( 1.0 - abs( 2.0 * coord ) ); - float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) ); + float shadow = l - r; - float shadow = l - r; - - float v = smoothstep( -e2, e2, shadow ); - col = mix( ubuf.color, vec4(0.0), v ) * ubuf.opacity; - } + float v = smoothstep( -e2, e2, shadow ); + col = mix( ubuf.color, vec4(0.0), v ) * ubuf.opacity; fragColor = col; } diff --git a/src/nodes/shaders/boxshadow-vulkan.vert b/src/nodes/shaders/boxshadow-vulkan.vert index 3a3080602..0fe63bd99 100644 --- a/src/nodes/shaders/boxshadow-vulkan.vert +++ b/src/nodes/shaders/boxshadow-vulkan.vert @@ -10,7 +10,7 @@ layout( std140, binding = 0 ) uniform buf mat4 matrix; vec4 color; vec4 radius; - vec2 aspect; + vec2 aspectRatio; float blurExtent; float opacity; } ubuf; diff --git a/src/nodes/shaders/boxshadow.frag b/src/nodes/shaders/boxshadow.frag index b24ff1856..61b857f7f 100644 --- a/src/nodes/shaders/boxshadow.frag +++ b/src/nodes/shaders/boxshadow.frag @@ -2,7 +2,7 @@ uniform lowp float opacity; uniform lowp float blurExtent; uniform lowp vec4 radius; uniform lowp vec4 color; -uniform lowp vec2 aspect; +uniform lowp vec2 aspectRatio; varying lowp vec2 coord; @@ -18,25 +18,19 @@ void main() { lowp vec4 col = vec4(0.0); - if ( opacity > 0.0 ) - { - const lowp float minRadius = 0.05; + lowp float e2 = 0.5 * blurExtent; + lowp float r = 2.0 * effectiveRadius( radius, coord ); - lowp float e2 = 0.5 * blurExtent; - lowp float r = 2.0 * effectiveRadius( radius, coord ); + const lowp float minRadius = 0.05; + r += e2 * ( minRadius / max( r, minRadius ) ); - lowp float f = minRadius / max( r, minRadius ); + lowp vec2 d = r + blurExtent - aspectRatio * ( 1.0 - abs( 2.0 * coord ) ); + lowp float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) ); - r += e2 * f; + lowp float shadow = l - r; - lowp vec2 d = r + blurExtent - aspect * ( 1.0 - abs( 2.0 * coord ) ); - lowp float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) ); - - lowp float shadow = l - r; - - lowp float v = smoothstep( -e2, e2, shadow ); - col = mix( color, vec4(0.0), v ) * opacity; - } + lowp float v = smoothstep( -e2, e2, shadow ); + col = mix( color, vec4(0.0), v ) * opacity; gl_FragColor = col; } diff --git a/src/nodes/shaders/boxshadow.frag.qsb b/src/nodes/shaders/boxshadow.frag.qsb index 8ecfc828aa472382eb72816fe916e075d05238ff..3792962e6c2f61324ba37ef9878831e4e61edc89 100644 GIT binary patch literal 2606 zcmV+}3eoid04rs9ob6hBcNURmUiV$rCqVRvgM?1Qv#(xNeP_8IeZm91AGephJSgS17+skx!PGtHV!Q%oa6Ob zY3DbOJ9qBv%wDa95JN(UK{%g+Gbbt{guh5sff|5Qd`gGN9w@z6cp&MBnm7+Sb)~0m zZKgFWmP89Qh1dz-=DNwGhT$9)4X~VmMPIamewuh^ncOqxLc7f!ILq1m7*!ru!D>sy zBs{;7@O}`D!8I4`Ct^W4e(-w2z4J{2D?od zp#mc$VvWS>8;Ngr43p9*gMK^KjGS7-k(Ig=)MV9nYC#w$ent9l5xG@)aQtS&k7GZm zjW?q(36r&^8z0Q&#{8gCZ&h7+s^KP1-HwxL-CsJ*@YruukKspg`E)MVLK8A@8gATl zDy~#ov$Vs)AB0b|b4ERsyc)s9*+GE%A zV0!+FyP&3SCCicPRAG=HPRP~6DlC3M_VUVyWi#}HBu_5-p0pHDY|GQKR4nBcteI(; z?Bk``4wUMwahLoNx{;f-q9FB5b2=7#W-vMVpUhx# zvg5_w$DIMwUEOR3#wG>lEwvWfYd^43|EtAzK~{@vc{PtbI8b+kTC&VV3dX-ukJ)(HsfMdy zyADq9QYu#fj2mH?EXRr4w8q_XLE@=3$cWC7hTqmxRAsQhbEZSAhx zReRe_1JjnbniaQ_X*7!FsSLnpX)>+A_rj=wE~xMTwBkf-*d3K+x+^xQ_8o7ax-0SR zYW^fw^OexAs=8~LB{Jy+#_;m73$4=Mu*~X|=oHy6u)==E+NvC{>YzMcT~!LKs%~CV zv6yaJMyY@*t6xz0?BoGmZd5vJb^A4_oEMzLxm8*;wNuy1K}<5*ft1+;{+}!QK|qz8 z8A#Ha5B^2gQpqG_6t3D0=MEI(&XYF|ZR?r{I^e=Pq36YJVpTG^N`h(@U2>Cs6x+70`<6V=>=O!RLOY;WY7 zX8~#VbP7AuD!eWB3OiG3z5mN@vDG>JZ~6r;xSeSlnJ0AgxY&lHU)%7ga@bpVK({x2 zK;Ni$c%OIk@V44Lye&PNcbW$aK_22|`iI@sKPGfId%K6X<@VwA_77U5|3deuyHV3h z3vVIK2WTJa+jI{*(>;0~x*^?qOOJk7>8WSZ>^I@sB&8139A{;=bZHiApwD1hHB^Ka z;z(wnz^X30d$I=Bc_+lp!f(<}IQXY@(=b(fLN@}iwdZ>P+@`BhdCS?}7i{kfw)X|w z`-06YJ1c~Oem$XM^wf@lu@S6~Ik8jxn$SJ4bHIxEv=~<3m#$p9QjC*o5f)3ohuERy zkhfcms22%%nlavh^O3+8COZ@k1Bln*>NMFOQuI)V9;0uLjR^h1#b8g7+*yVV5H`=S z9faLx*dSrc3>zX0-=16oEo1KzNaGj>$qz%n%xIk7i;RB6=x4#ofRf*#e8KDeaD^{i zB%IHKJkHI$fRXUIljb`@{9VK!AbyT`yOiA_^`Z;;sE54gK;{{;kH=A>_YjRX_L7ZZ z;twl5ee8pg_A|W~DBgxXM!p#OIK{aD7SZMm+2W@es|b}yZFs6`rR)2KGCPa+mnt3vVmh=B^>3i5Islt*mr1skvC8D zNf-&oS`b+0bWG-%57#J%7D(?BVaDeh6xUH09qF62z83K?Up^vRZxVfzY+WbJ*!mu= znW5jJH88&1BAK_C%=c;h4@hQ_uv^UEMJ8{Pyjh3aeb&Jt+}K!|&nAl(NfgJaz%zPaCjLOJ)LNbmQL2sieBDsp`nzk@vT4p6S)*aw*Huaa$kAAF5)WBcob8QYTCM&3(8KaZj9mzeFB zY3|(bgM?!YUnKf(peIRxjOl-a^to?`2siqNy7VQJJxsCvC*X&PZ!!D%K65`pxS9J= z!pz)@Z0^V#7y5U4v^~yjm&o^H%=QG~=zD=^^u0*>Wu`w#`p2366yZjHs!PAfWTz>Q zaPHH@$DH_-@>OJiU}=laG5E*y2bS`a`UA`Mo7U}LRJMOn+5Sc4b9&R-_3xDCA5`=| Qx{98+v047V0QH^A6f>|mNdN!< literal 2656 zcmV-m3ZL}=04+Lrob6hTb{o|ZzBsX+2)855zs3E$=7q~?4#pp*xg^-S@iqoW1mwL+9 zW?Ca+S+qz~h+XulpPL41gzhoXAj>gX^hBHJhao#<;P&VT<+ka-DN}4-W76X?S#603 z;DwFB4uP7&CHpY~azi>k;MzxXsgu=EoF$KAQu3t|&$*`KlDxi6J~wHU5;+u$HNfi| z!8f}`;9$PX8l5REw<;AkwCKY+X@zdpi()rSFXu9;TPcgKFjy@%oVSC}s?-A~F0>0) zi@?N-L$6IbO{eruP^m<2oG#@uvrDX2Gh2PW3cT zcb4H{i@dzDaN+W`;^{DmqT&U=*@_WX(+rJy_3ZW2mo8mClT(8YP`=cP6WYdjWZ}xS z;#DWCx-m?sskyYcrPy0>FU#nrp~$iJvf7DaGw}RaFSu8+(u!lZt$8bF=PDT~P~vXb zipO%Z9hRZB)}z&{$rtHabIJv~-LbXPZ`=! zuH%KN+|-HO)Xelu{@989iOD=o;i%Pc+UYR+WkADtXdRie(iDZmRwX%R-YV0eX@Vp} zlc8{169_X3(_t$;sTP7H&T^DioBXhxZzj_>Azrx#Eh)QPw%b{&Y_DaqYN=?%y6act znv!Pq68Bq)YEC&=B~x`8HB3rZNDwuGAg)n)Z>A^QeAePyX&J^;BGuinneJBaY&WyA z){6Yh=rloYnY*o9mU!{&vz)&DrOc9f+*cnhDydbs=<%~oauvWiQ)C-iW$X&Y7%-Sp z4J4sJCdW2iHmbO>8+#3`r?><2nCQr5e9|@i=J<*mMqc1slet`~8M-A;QZ=tyYpMmA z?PGhq&vfCZz+&nR-fybcDtA`glHBgvJxQB;kQjMOrJ~v7lG|BvJFCYnqvd;*AZ*C* z0=%}wT5-ZP&#x+@2>AxBrQ--S776d`Dm_hQi#?^M9RFW-l&#I+{`8ZcR-!YDjPYZd z-R*58c26VOypNzh*n`@L9La1VcCv}61lm#yxfdN|s}1DK`-hxJS%oy;=^#c_GP-@( z-S#1|)I&1;4dg5JkN)-{E$0TB`9>Q^!)vQap?`D|3Xdxp-9YRC4WwExo}(gs#)+N9 z+>+5n5=HlJ_kS|O$Gb&$D)-wRB>GJ^m(Dbtg&GUQOpzj*=V`ODW;&(`2`1uKX;x}^^-A@vp=QaYr zEc&|(^BskJx9GmfV|fa)-O}!`d=JWU)??Y@gxLf8d>sM37c|>=6gEa6ACY?M+D9Wj zVdy=Dcx(D7e9`nV#5qeA+2%>uGVlF_oyC|tWqfwY7;B!M&j@bzaSr1soTBH!<2gQ$ zIcndYM?MTg{{>*pIliQ(_`JqnfInLPs*<15@=HeC7ckat_`~#T;IaG)u%m{(MY{j? z*Nb!7o`+a5{%zoQ8~BDC{&vT|PYwHjfbJ;9XZkL9(=_WL(S1eCynhmB7+B7Y8AF%X z|9pae#h@8~*`PVEt|jnqCFJFVd?i7@pP)YiJx|`wAa7nEk9pl*#9H%u&LK9Z!T$?k zI6u#T$NBXSvT+V`|2N@Tc9!mQh{IXK_77qEf?@k*@INFB(-)B|FT=m{;IR!}=c}-B z2{w2huXp%6Wb9stjMw)KvgCM zScfY3+GY)URp{}ac?Wu)5#Kuan)VUz&q#;q0K8XayhbFiiFoaVd;!>>2(=ISz5`we zeiJcaUW9Q&LpO%cHAA-reuTJ`!Q=VxK3ElM@9Z_=&<0;))_{4+z}y61um3G${o9ah z*-s%m2;AdFtkz*$&*5jHTen%CdG8vw*MS*B{@#Y{Md0+>y@zpcW8N#^Y5(sCRU# zNTtR-zf^CPUF*4q8$0!46qoDX^1Q*1yhiyb|FLWHR3_PkZ_) z$v5@nAtTSPd%kNGi%v|_U2es0v6xOf^;KsrDk@efo?9GWeq;q*2zNkl-9XL$wIlL&r2*VW!3UJzT7{DWMv?LI{YV7G}HM)q%HD2 zXWd#)?khebA&Gm~!3G>O>g!>B2aP=6z7LJ8;zaSuliyG~Gmaan$E~(BppB-cqp@jU zgY(qgy3^RO#~BcPcJO}mIwScy#OD1jNSyGI?atU-fjZK|?QdA-zfkXD6Q^bM0UvdG OxxYvD%Krzc77pV!&2d2h diff --git a/src/nodes/shaders/boxshadow.vert.qsb b/src/nodes/shaders/boxshadow.vert.qsb index d9831605a22608de23815ce59e348623f0add7e8..2e1e841bb5032bd922c2ab832e10089227db998c 100644 GIT binary patch literal 1576 zcmV+@2G{uj03mXCob6g|Pa8)NUTj{Ew*&&TB~30NO>BrX)jY`=!6AKcPRSU#fOych0wWwy98yf8jObFI~q46)F8ZLtj=`s#Df^n>rs+zNVpr(KsaD?7es&? zvRHn`0HTAR7TEO(yxk2v3s4_iGeLjAcDO?pSP?OsZ;8R3@ zL^j)=3DDaB3kFyS*eSv7Zt(M-F`8VZZ+QEDSvWR5-*O#wxmZ*bKkz~$P!GbI@?KHl zsp~-rKRl~h=8R+0D5-{PyPiaQdesX37Gp)#{f21-J9=Qbf?Km)9rW6vx7iF#Cy=>r zLpQA8w5*(!6(w}6n(Nik1vP{ZU>)n;spT9B&4%lG)v}@o;L<@Dn1X9LS|>pX1rT6h zHf4!0tGx|0m|}Wp!nLXprsd@F6gXF>RwT{HJ+!rL*S7*pScUsn5Xn&&Wm73=;T?cm z<^U?oP9SbY!SzJ@w60_Es%5GRmSfmq)l|Q(n}Kd?eo(cogLNh5`&PaBC4Ll+)**#H zX3Np*rVp7lRX(fSVR3mLO3mZ~3#Pop#E}=7v;NC6lP?%@QFFsU_J|f)-P;R&)63be z;S}@x`w3^{h1lC`&=5gw+ASv$ZoEz~v9%|1DGTwIN}!hWkqJ`K3P6lKsr4C5Bb&s0DRUUL^Pgn{o*2x_*T^SXTmL@3h|~aB=;o>&)=Jc)b{ku zAoLuZ8126SZkf)8-)Q&Y8R5id#A>ge5tu9ae1P<)4hF$VoCv_`?W2IvX-zB9U(IF~ zhH$7rg;^rOO{hA!WTQ|Z@%x)syRQmxMife`MNvVrkpec!6h6i?CbBWYL>a|WHxKVU z)ByhAm#E48V^eHJo)qlc14E8_b9~u2^`!j6 zM~Hp~h&i4w5$hD;F~(1cU!irnP4WE-bCCX=FtHNzwcAb&w#>s z9!mHJ67CVneg?fr=VzFgqZsL|25rouV?qg$)_W{@+A`9w|UKwdUdxKan4C?_f4 zYCciIIZ!GyDfAN=Ex>W{Nn;D|+R;>$+Mp+SQKz6(f?1=(ou!-*wW?N<8P}Vn9;v!S z#dvr7<<4vEx##-6_R?u2?^E)XXHETX^ZVypTRSg`oo_oaU^#J@k}Yh7L8J4Pt+V>% zb!|=EeJv&8EULNap?2ZITMzAAE4;_@X3O(x+U~a~?rj-UqstnMBL`YpsmRjQ-78LR z8%n+eNZ|=a2hYTGmlFacb5b|F#CB@KMt)0<(v>f1bs(d^R{QtcU-P>+RZszyvw!6pL?l`9S*CL~yUYX`RHG`iJfRYc1H00z$Z9S4p zSGBFb+;f7lxF^Ru@lSG3t`hfRJ^2V9pVyOL_v0}w_v6?7_vQ89z1|=HOTUVLUuInQ ztG(5)%7Vld`*Qo(PB(`b@btrPbT8gg^h{qIyP1SZyW>M_pINduyXx)p<@aW(e-@1z aVDWznSX=+rCQtoc=DG5=`TqbWmBfNrpA;Mb literal 1559 zcmV+y2I%RM|3>IH3$Szi-bf(DpV;- zjpOqLw?6yuBMG2LRi%D_{?o71kI=8vf2ww7clJEC??6GN3N#z}ygT#Td9HmkNrVvN zLXAKt5at zhU`F|QL<>5d_+%(b&-k=%nrg`&wC6t0oSzX3L7kmzz4K?igNILBVg!^4 zDBzj{a4Inc;B^jMP(YQi0`LY0DqNPvBDVgjjHdLKpj$PSaX4>w;yK!67X4O^)z5vN znB^`nhh>U0OzTBr0o;Y7t55pM^1~-jt@}|J$JWE3mnM{b<8kQgWPqE>`vE3APLqNSkMbht*7N3P$tt1raX?sRW*){)hkB3o zgQf@r98lXsxlkZZspsRFJKZI$c8~cJxk(xY1tmND%_Ha=QoniHqm{V>I5pr~{R%OT z!V3yt`%_Sg;Qi}IE05}N(ylkJH`KTGs1_g&3q#KF`&#Rm6slmsqT)1M=TQbAkbahQ z;ChPIDCZj}^$rnls*f3!w2I`9L5ZQpIN|krj_#axfb?tH2;uHBT7_uKj5bQNXN)#R zwC9XAPBfqF)bh};lW@Pl{5(l9(CgEMIGm?7+I$S8R3v^>+Jf_wFvFtIgzFUG5jR0R z6V?aGZlt$pJxMg=8|1&{8x-Rak~c&0#-tr8<}eIOSChYq{usHGRg>5EU^NNv&|D?y1;r9l zQU1f)af}WPjfyqr1&*J#UGuB1o7lbuFKXXgzhh+d*z2~x#E<&(JK$!F^>JW#-59)g zO}VQzAol%AlgFQm2$lh&@ElMb@=jSGGtk=xeuoVzZB|#)7|LTmbb>~0ZEa|Iv%1=& zDS}GUyY~0~z{D@)!U> zH3U+5t^X`&iFhrVuXmJLAu9&Fpitt3rK+NM&WhCz6%nDT9q{OlOU)wRU&A%>^Z%m1 z&N$_!;9q{!cV8rn!JT>`J0EeU{-I=t_xxBJ{ITEj@0p(eJ@@t>dh5QIdhrjf$;L}<^&?EQxN{Wa8kz2SXJ1BykG_YpRrK-$~25bt3j36Yu#;un6$^G1GY J|3AYhu2G@K4xRu2 diff --git a/src/nodes/shaders/vulkan2qsb.sh b/src/nodes/shaders/vulkan2qsb.sh index 765f51272..27639dd4b 100755 --- a/src/nodes/shaders/vulkan2qsb.sh +++ b/src/nodes/shaders/vulkan2qsb.sh @@ -6,6 +6,9 @@ function qsbcompile { # qsb --qt6 -b -o ${qsbfile}.qsb $1 } +qsbcompile arcshadow-vulkan.vert +qsbcompile arcshadow-vulkan.frag + qsbcompile boxshadow-vulkan.vert qsbcompile boxshadow-vulkan.frag From f9c08c34fb2cc64546bbe6ce9d359f416e934961 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sun, 7 Jan 2024 15:43:34 +0100 Subject: [PATCH 13/14] FUNDING.yml added --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..9dbb23913 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [uwerat] From 81cecb6ec458e1a90dff2a27d1c6f5263acad93b Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 8 Jan 2024 16:06:43 +0100 Subject: [PATCH 14/14] supoort of experimental Qt5/RHI dropped ( use Qt6 for RHI ). Building the qsb files from the makefiles. See https://github.com/uwerat/qskinny/issues/356 --- README.md | 8 ++-- cmake/QskFindMacros.cmake | 5 +++ src/CMakeLists.txt | 47 +++++++++++++++++++++- src/controls/QskWindow.cpp | 14 +++++++ src/nodes/shaders.qrc | 14 +------ src/nodes/shaders/arcshadow.frag.qsb | Bin 2282 -> 0 bytes src/nodes/shaders/arcshadow.vert.qsb | Bin 1585 -> 0 bytes src/nodes/shaders/arcshadow2qsb.sh | 10 ----- src/nodes/shaders/boxshadow.frag.qsb | Bin 2606 -> 0 bytes src/nodes/shaders/boxshadow.vert.qsb | Bin 1576 -> 0 bytes src/nodes/shaders/crisplines.frag.qsb | Bin 872 -> 0 bytes src/nodes/shaders/crisplines.vert.qsb | Bin 1871 -> 0 bytes src/nodes/shaders/gradientconic.frag.qsb | Bin 1826 -> 0 bytes src/nodes/shaders/gradientconic.vert.qsb | Bin 1624 -> 0 bytes src/nodes/shaders/gradientlinear.frag.qsb | Bin 1444 -> 0 bytes src/nodes/shaders/gradientlinear.vert.qsb | Bin 1582 -> 0 bytes src/nodes/shaders/gradientradial.frag.qsb | Bin 1550 -> 0 bytes src/nodes/shaders/gradientradial.vert.qsb | Bin 1479 -> 0 bytes 18 files changed, 71 insertions(+), 27 deletions(-) delete mode 100644 src/nodes/shaders/arcshadow.frag.qsb delete mode 100644 src/nodes/shaders/arcshadow.vert.qsb delete mode 100755 src/nodes/shaders/arcshadow2qsb.sh delete mode 100644 src/nodes/shaders/boxshadow.frag.qsb delete mode 100644 src/nodes/shaders/boxshadow.vert.qsb delete mode 100644 src/nodes/shaders/crisplines.frag.qsb delete mode 100644 src/nodes/shaders/crisplines.vert.qsb delete mode 100644 src/nodes/shaders/gradientconic.frag.qsb delete mode 100644 src/nodes/shaders/gradientconic.vert.qsb delete mode 100644 src/nodes/shaders/gradientlinear.frag.qsb delete mode 100644 src/nodes/shaders/gradientlinear.vert.qsb delete mode 100644 src/nodes/shaders/gradientradial.frag.qsb delete mode 100644 src/nodes/shaders/gradientradial.vert.qsb diff --git a/README.md b/README.md index 070079fed..2b21d3c0f 100644 --- a/README.md +++ b/README.md @@ -35,9 +35,11 @@ It might support all versions Qt >= 5.15, but you can rely on: - current long term supported ( LTS ) version of Qt ( at the moment Qt 6.5.x ) - current version of Qt -On debian bullseye these packages need to be installed for Qt5: `build-essential -qtbase5-dev qtbase5-private-dev qtdeclarative5-dev qtdeclarative5-private-dev libqt5svg5-dev`. -For Qt6 you need the corresponding ones. +On Debian these packages need to be installed for Qt6: `build-essential cmake +qtbase6-dev qtbase6-private-dev qtdeclarative6-dev qtdeclarative6-private-dev libqt6svg-dev qt6-shadertools` +For Qt5 you need: `build-essential cmake +qtbase5-dev qtbase5-private-dev qtdeclarative5-dev qtdeclarative5-private-dev libqt5svg-dev`. + > Optional: When enabling the `hunspell` feature the following package needs to be installed: `libhunspell-dev` diff --git a/cmake/QskFindMacros.cmake b/cmake/QskFindMacros.cmake index 2dbe7d002..0c9d8583f 100644 --- a/cmake/QskFindMacros.cmake +++ b/cmake/QskFindMacros.cmake @@ -15,6 +15,11 @@ macro(qsk_setup_Qt) endif() find_package(QT "5.15" NAMES ${QSK_QT_VERSION} REQUIRED COMPONENTS Quick) + if(QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6) + # we need the qsb tool for Qt6 + find_package(Qt6 REQUIRED COMPONENTS ShaderTools) + endif() + if ( QT_FOUND ) # Would like to have a status message about where the Qt installation diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3c6b49705..99386af73 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -173,7 +173,9 @@ list(APPEND SOURCES nodes/QskVertex.cpp ) -qt_add_resources(SOURCES nodes/shaders.qrc) +if (QT_VERSION_MAJOR VERSION_LESS 6) + qt_add_resources(SOURCES nodes/shaders.qrc) +endif() list(APPEND HEADERS controls/QskAbstractButton.h @@ -473,6 +475,49 @@ if(BUILD_QSKDLL) set_target_properties(${target} PROPERTIES DEFINE_SYMBOL QSK_MAKEDLL) endif() +if (QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6) + + qt6_add_shaders(${target} "qskshaders" + + BATCHABLE + PRECOMPILE + + #OPTIMIZED + QUIET + + PREFIX + "/qskinny/shaders" + + FILES + nodes/shaders/arcshadow-vulkan.vert + nodes/shaders/arcshadow-vulkan.frag + nodes/shaders/boxshadow-vulkan.vert + nodes/shaders/boxshadow-vulkan.frag + nodes/shaders/crisplines-vulkan.vert + nodes/shaders/crisplines-vulkan.frag + nodes/shaders/gradientconic-vulkan.vert + nodes/shaders/gradientconic-vulkan.frag + nodes/shaders/gradientlinear-vulkan.vert + nodes/shaders/gradientlinear-vulkan.frag + nodes/shaders/gradientradial-vulkan.vert + nodes/shaders/gradientradial-vulkan.frag + + OUTPUTS + arcshadow.vert.qsb + arcshadow.frag.qsb + boxshadow.vert.qsb + boxshadow.frag.qsb + crisplines.vert.qsb + crisplines.frag.qsb + gradientconic.vert.qsb + gradientconic.frag.qsb + gradientlinear.vert.qsb + gradientlinear.frag.qsb + gradientradial.vert.qsb + gradientradial.frag.qsb + ) +endif() + target_include_directories(${target} PUBLIC $ $ diff --git a/src/controls/QskWindow.cpp b/src/controls/QskWindow.cpp index f46c6da51..7955320a5 100644 --- a/src/controls/QskWindow.cpp +++ b/src/controls/QskWindow.cpp @@ -416,6 +416,20 @@ void QskWindow::keyReleaseEvent( QKeyEvent* event ) void QskWindow::exposeEvent( QExposeEvent* event ) { +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + if ( qskRenderingHardwareInterface( this ) ) + { + /* + Actually our code supports Qt5 RHI ( f9c08c34fb2cc64546bbe6ce9d359f416e934961 ), + but Qt5 does not come with the qsb tool out of the box. Then we run into + problems with compiling the shader code from the makefiles. + But why should anyone use the experimental Qt5 RHI implementations + instead of using Qt6 ... + */ + qFatal( "the experimental Qt5 RHI implementation is not supported:\n" + "\tuse Qt6 or run the default OpenGL backend." ); + } +#endif ensureFocus( Qt::OtherFocusReason ); layoutItems(); diff --git a/src/nodes/shaders.qrc b/src/nodes/shaders.qrc index 7d2d15a42..3919b702e 100644 --- a/src/nodes/shaders.qrc +++ b/src/nodes/shaders.qrc @@ -2,33 +2,21 @@ - shaders/arcshadow.frag shaders/arcshadow.vert - shaders/arcshadow.frag.qsb - shaders/arcshadow.vert.qsb + shaders/arcshadow.frag - 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 - shaders/crisplines.vert.qsb - shaders/crisplines.frag.qsb shaders/crisplines.vert diff --git a/src/nodes/shaders/arcshadow.frag.qsb b/src/nodes/shaders/arcshadow.frag.qsb deleted file mode 100644 index 1c90703303dc33dbd0af723f231835b235812372..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2282 zcmVPk-Q+D~di zY>OsH3h@Gbo98;?nt=O=2tacR8hz0Q`Y?@MWqdE02kka@;3^;H*92&dfnBq$?ZtLd zB%%R~9TO%ZZ(XO)GtXN9%8R7PtSZB_(|f2)tN>drBT{xc*$wYn)1U^ zy;=6;rNB$wx|5{ky1#vy;fWuV&*4X*cG8xxShn&gSnig)wSm&Bmu;t&`xU@D;Nlql&nq5R*uZaUfPU9 zX~b;(V7ChGyqswjI=Q^;LY=$>JeLEvEDIwIypYX=ezHw`;4s7k&R0F4wzl%x1vgY# zoR&@a1P1u5czT+QPnkx%m*vA8bN;a3VLp~@BOw)iG#qP{=I+v^=}qr`wrjS};sVHiT1zaJq07QRYI$ zP1421z->c9ih1MF{&UGJ;YB&gG$D|el%H0PvF}>hr%tE~k}&6BCJCY_ttF|~(600? zjl8l$x?pJ)vTB9Zq?lFB!mPVF_)ti<_*u1ptf~QQjcTz9{Zlu`TISa!y|Qt!%SDi^ zf^Asn+r@6_MLSO5ehK!vy$mfnx}kv#SiT=sDv6icrDCq9pD9M|Y%kyZ5I)F#AJ+os z(o8%%ecTrYxwA>_=k2aV#!YiL!1^GkJDh28ycaI@fUL7-opfXE=K7|y5=Tkm+zcDN zz1XzWMS17_&sJ{VUcX-KX~SIjb~A14-N_f_#-?+}jjLWtDh8XZsonp%t+pb+tZX~D zuwD*c_W@?Bb=vrp>_nsvLc=jC-OpSJfo zgS~H<8EAiyh`m~1W&a*X-LJBD`*WV${+_b&RR%g=CEvd?dRpH=+j9omo|C=vSk_>v zsGn$ip#G%!wTEZ3a&;9h^PvJ2xbcOSx(0?A)1r|gG!sX9x;X0+tPFb<>|);@Lz~pA z%URpD{x&)?HHmM}7HlqlN9fDY-SK_;FuWY&_v)>UTLpNNEzBB1bHW!M}Qmo-=TSWkH(DNi!={L@4Li% zk;yKS>==z3KbMC1d5LhNZ<*vTk)P)Yy9T4E<0|R6Ol!jExkh7u1wH8V3Sn(Kd1S_SaDr`#Qa>Qn*5mX+aNKi zzBTqS**HWoe@J8Rf-dYMYeFA)ApR%7Q1%yObB$zf5{CA1ZLJHv9*?p3HwZU*y2J9c z!DK&SvZ(tL;x(~-IwZEw2sg3)k}$kYUqxM;G-hJ^oMPK#b9tBSn^?af>~j|D7tG%+ z;y=n_{T1OR*A8KCQeIt_R~)+sw@Z1w$8>KGna2|0hQ{A1UK1Yil-XQY*j#%etBI-@ ztce=oMxRgeHKlJ-VPBFyn_}{r&-eTCcc1u;emsgi&*nQIe&cH>vf2-r&4}5o6Q8M3 z9Q!BCotZ}-ux{g!wsX>@ovmLV8 z7TKD8K)A8_Q0SigN07ns-w@A3=KF6+&n}aDM7WWAOtO#2mmR|X4G~;~`vR?fbA*ZS z3-16Q{ze?8`T8Nt=gWli_5BLrhUYl(@OAns;g5(uL70(wZHUZC!VS-lhS+|c@HMK> zACo^P7Wt5)?1i0<%?&lPH|6V*$yKNZh z*@Y7@xCejI_WPNfJpR9r9o0nad+4aA3Pzv$yfL%!TuvLG#W~~iIbr;-P8aoQBCpam ztJ23=mCk)ntF-0D9sJV`FV%yxJSfZWU0GJ^&IeGL*WJ{;TiklO+APyI*5+Tb+AJ0= z2(siWs^(W~4ejaD0PKh9us>=Z)bT+bAJp;lsbg~(#r~gzscHScPsG3<^?Jwu1J}Sl EP`UJ}DgXcg diff --git a/src/nodes/shaders/arcshadow.vert.qsb b/src/nodes/shaders/arcshadow.vert.qsb deleted file mode 100644 index ae08a617e90ce04b542051094ed46eb879ef228c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1585 zcmV-12G02a03r-{ob6iOZWBio9@|MsHVGtYAkYF`NSfLqbxjnYN(chcsvsc|B^9cK zqGe;R!?yOW*&j$ixoq!y(!m1&Y5q{|IX|T z2qA`rx=L_Q30HW+5_RFjUmzO5E5cp)hc1!6W(faMIDn4exeweS?CLwh5-$L0k$fBn z^5H(!X9V^cIg9$qNA!r;6|rbSYZQKUyTwo=a8HP~u)&f5d_b$msqZesP3eX*pe0RE z4&LS6{2BqN0l*b(vmfld2t@~g4!|2?OFmsNH6$mVk$~Ja3m&xq81xv_=r`yzSl$76 z9pI5TAo%ls@T0B?8Z?oxiuSzg)mw4HF>kk>$ZlC-)M&Z8cZ`G|y6wi7_^3X=V;FJh zdV8j4x1F$K*Bw)iS~rX^3gUWX?#4~yjbXyoZ25Myy1#0+?I>{f*BR5S`z=36aqOVZ zXfx~tj@{U@8*UtO{%$J{@?0M*aifEE<1jI#ZM$C0^5ck`vjUp^pkY3J8i!6$Zuxbu zR@vD}S+du%HvQ0zT;Bs+hnfh=Nq4=Jucqr+FP$KA_F>DvnM=DhCW&eGTBQI)L)NS2{&Qs9&fVdL_xw(6hQK zBpH%5$nBmRMo?F~HEnC)zp~o)4}Orm@o1VwrmdL};2-^FGjyVIy;e!RYZ55anZd30 zz(JZbs2d!mKs@;w^vygvDTyq$dXPs`spO!qE2?^+e(lJu_n1i5Q(fIUN;8vWr{%EJ z@{Uvq(VMfq`EcurbwBXK(0b@~(vu&bpVrLpzWM(CM0(vDl@uK&xtL@WR0mC3uQ-r!sYOg&RW zTie@>@&@nCOuR|5awz_$CuXK$tUA<0*$tXv^l(58_a&h~oRe7vQq`TqYWJ8wv@E2R z9P+sbSBGDdZTABF1&A}k zkZt@V*E+_8+Rl6g_hq;jPzE5zh!#YT6OD2nz(#PI`t(*v^9sb{xFYdNQdX(UdjN9h zX#6nYH9gPdY92T*H%OXSAlzNXD-v&$@k+#d#&|=-YcSq0@t%{NS|0j;0e-Ktcp!a+ z(U&vvS|IwAjBQcMxdJjvB=a1!aBFG8JqLKijZmKn^eEYl{B@$oh==_K`LFv87I&04 zN%GLov+z7ky70P2^clim1bT|_XQbUKZ(7C_>6{_`)1-4osJbbUj#<)CARV)kudeez zpCg$=Qpc!_ujXl8`bK@{DIRmA59tdmMjv-$spw0jdy?>%L{hWZe}!zFBzj)xLjZ+G zdV$%GFa1&xy6v-YLaen~^Yifh?J3%?R1HEHJ-vb2t@d^2Mmhk6f zUKD?W^7$$G^9zibq*z}hKFUG=u2N3UlAf!CLm6oIXXN8OpwOQ(!!I&ih5CL1xkxY3 z*a{oF%*I|LeanRX8>0A?S`zep#!mvEqxk#DNx&eT1oZmm=BQi8=DZ*?LVkP$ihqA+ zA+O%*q(P*=f{yt~!~6XT;^zZ6ul{jzJ}^M%1Mm49;6vZ$57NH44rnzuoD;m~0<)I&g9_@c&K*PEG;_?<8Q* jckX?5(wTo(*Qc-Qe>;fWZadeX`K~^)KR5ngN?pPF4kaH6 diff --git a/src/nodes/shaders/arcshadow2qsb.sh b/src/nodes/shaders/arcshadow2qsb.sh deleted file mode 100755 index d78eed3bf..000000000 --- a/src/nodes/shaders/arcshadow2qsb.sh +++ /dev/null @@ -1,10 +0,0 @@ -#! /bin/sh - -function qsbcompile { - qsbfile=`echo $1 | sed 's/-vulkan//'` - qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o ${qsbfile}.qsb $1 - # qsb --qt6 -b -o ${qsbfile}.qsb $1 -} - -qsbcompile arcshadow-vulkan.vert -qsbcompile arcshadow-vulkan.frag diff --git a/src/nodes/shaders/boxshadow.frag.qsb b/src/nodes/shaders/boxshadow.frag.qsb deleted file mode 100644 index 3792962e6c2f61324ba37ef9878831e4e61edc89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2606 zcmV+}3eoid04rs9ob6hBcNURmUiV$rCqVRvgM?1Qv#(xNeP_8IeZm91AGephJSgS17+skx!PGtHV!Q%oa6Ob zY3DbOJ9qBv%wDa95JN(UK{%g+Gbbt{guh5sff|5Qd`gGN9w@z6cp&MBnm7+Sb)~0m zZKgFWmP89Qh1dz-=DNwGhT$9)4X~VmMPIamewuh^ncOqxLc7f!ILq1m7*!ru!D>sy zBs{;7@O}`D!8I4`Ct^W4e(-w2z4J{2D?od zp#mc$VvWS>8;Ngr43p9*gMK^KjGS7-k(Ig=)MV9nYC#w$ent9l5xG@)aQtS&k7GZm zjW?q(36r&^8z0Q&#{8gCZ&h7+s^KP1-HwxL-CsJ*@YruukKspg`E)MVLK8A@8gATl zDy~#ov$Vs)AB0b|b4ERsyc)s9*+GE%A zV0!+FyP&3SCCicPRAG=HPRP~6DlC3M_VUVyWi#}HBu_5-p0pHDY|GQKR4nBcteI(; z?Bk``4wUMwahLoNx{;f-q9FB5b2=7#W-vMVpUhx# zvg5_w$DIMwUEOR3#wG>lEwvWfYd^43|EtAzK~{@vc{PtbI8b+kTC&VV3dX-ukJ)(HsfMdy zyADq9QYu#fj2mH?EXRr4w8q_XLE@=3$cWC7hTqmxRAsQhbEZSAhx zReRe_1JjnbniaQ_X*7!FsSLnpX)>+A_rj=wE~xMTwBkf-*d3K+x+^xQ_8o7ax-0SR zYW^fw^OexAs=8~LB{Jy+#_;m73$4=Mu*~X|=oHy6u)==E+NvC{>YzMcT~!LKs%~CV zv6yaJMyY@*t6xz0?BoGmZd5vJb^A4_oEMzLxm8*;wNuy1K}<5*ft1+;{+}!QK|qz8 z8A#Ha5B^2gQpqG_6t3D0=MEI(&XYF|ZR?r{I^e=Pq36YJVpTG^N`h(@U2>Cs6x+70`<6V=>=O!RLOY;WY7 zX8~#VbP7AuD!eWB3OiG3z5mN@vDG>JZ~6r;xSeSlnJ0AgxY&lHU)%7ga@bpVK({x2 zK;Ni$c%OIk@V44Lye&PNcbW$aK_22|`iI@sKPGfId%K6X<@VwA_77U5|3deuyHV3h z3vVIK2WTJa+jI{*(>;0~x*^?qOOJk7>8WSZ>^I@sB&8139A{;=bZHiApwD1hHB^Ka z;z(wnz^X30d$I=Bc_+lp!f(<}IQXY@(=b(fLN@}iwdZ>P+@`BhdCS?}7i{kfw)X|w z`-06YJ1c~Oem$XM^wf@lu@S6~Ik8jxn$SJ4bHIxEv=~<3m#$p9QjC*o5f)3ohuERy zkhfcms22%%nlavh^O3+8COZ@k1Bln*>NMFOQuI)V9;0uLjR^h1#b8g7+*yVV5H`=S z9faLx*dSrc3>zX0-=16oEo1KzNaGj>$qz%n%xIk7i;RB6=x4#ofRf*#e8KDeaD^{i zB%IHKJkHI$fRXUIljb`@{9VK!AbyT`yOiA_^`Z;;sE54gK;{{;kH=A>_YjRX_L7ZZ z;twl5ee8pg_A|W~DBgxXM!p#OIK{aD7SZMm+2W@es|b}yZFs6`rR)2KGCPa+mnt3vVmh=B^>3i5Islt*mr1skvC8D zNf-&oS`b+0bWG-%57#J%7D(?BVaDeh6xUH09qF62z83K?Up^vRZxVfzY+WbJ*!mu= znW5jJH88&1BAK_C%=c;h4@hQ_uv^UEMJ8{Pyjh3aeb&Jt+}K!|&nAl(NfgJaz%zPaCjLOJ)LNbmQL2sieBDsp`nzk@vT4p6S)*aw*Huaa$kAAF5)WBcob8QYTCM&3(8KaZj9mzeFB zY3|(bgM?!YUnKf(peIRxjOl-a^to?`2siqNy7VQJJxsCvC*X&PZ!!D%K65`pxS9J= z!pz)@Z0^V#7y5U4v^~yjm&o^H%=QG~=zD=^^u0*>Wu`w#`p2366yZjHs!PAfWTz>Q zaPHH@$DH_-@>OJiU}=laG5E*y2bS`a`UA`Mo7U}LRJMOn+5Sc4b9&R-_3xDCA5`=| Qx{98+v047V0QH^A6f>|mNdN!< diff --git a/src/nodes/shaders/boxshadow.vert.qsb b/src/nodes/shaders/boxshadow.vert.qsb deleted file mode 100644 index 2e1e841bb5032bd922c2ab832e10089227db998c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1576 zcmV+@2G{uj03mXCob6g|Pa8)NUTj{Ew*&&TB~30NO>BrX)jY`=!6AKcPRSU#fOych0wWwy98yf8jObFI~q46)F8ZLtj=`s#Df^n>rs+zNVpr(KsaD?7es&? zvRHn`0HTAR7TEO(yxk2v3s4_iGeLjAcDO?pSP?OsZ;8R3@ zL^j)=3DDaB3kFyS*eSv7Zt(M-F`8VZZ+QEDSvWR5-*O#wxmZ*bKkz~$P!GbI@?KHl zsp~-rKRl~h=8R+0D5-{PyPiaQdesX37Gp)#{f21-J9=Qbf?Km)9rW6vx7iF#Cy=>r zLpQA8w5*(!6(w}6n(Nik1vP{ZU>)n;spT9B&4%lG)v}@o;L<@Dn1X9LS|>pX1rT6h zHf4!0tGx|0m|}Wp!nLXprsd@F6gXF>RwT{HJ+!rL*S7*pScUsn5Xn&&Wm73=;T?cm z<^U?oP9SbY!SzJ@w60_Es%5GRmSfmq)l|Q(n}Kd?eo(cogLNh5`&PaBC4Ll+)**#H zX3Np*rVp7lRX(fSVR3mLO3mZ~3#Pop#E}=7v;NC6lP?%@QFFsU_J|f)-P;R&)63be z;S}@x`w3^{h1lC`&=5gw+ASv$ZoEz~v9%|1DGTwIN}!hWkqJ`K3P6lKsr4C5Bb&s0DRUUL^Pgn{o*2x_*T^SXTmL@3h|~aB=;o>&)=Jc)b{ku zAoLuZ8126SZkf)8-)Q&Y8R5id#A>ge5tu9ae1P<)4hF$VoCv_`?W2IvX-zB9U(IF~ zhH$7rg;^rOO{hA!WTQ|Z@%x)syRQmxMife`MNvVrkpec!6h6i?CbBWYL>a|WHxKVU z)ByhAm#E48V^eHJo)qlc14E8_b9~u2^`!j6 zM~Hp~h&i4w5$hD;F~(1cU!irnP4WE-bCCX=FtHNzwcAb&w#>s z9!mHJ67CVneg?fr=VzFgqZsL|25rouV?qg$)_W{@+A`9w|UKwdUdxKan4C?_f4 zYCciIIZ!GyDfAN=Ex>W{Nn;D|+R;>$+Mp+SQKz6(f?1=(ou!-*wW?N<8P}Vn9;v!S z#dvr7<<4vEx##-6_R?u2?^E)XXHETX^ZVypTRSg`oo_oaU^#J@k}Yh7L8J4Pt+V>% zb!|=EeJv&8EULNap?2ZITMzAAE4;_@X3O(x+U~a~?rj-UqstnMBL`YpsmRjQ-78LR z8%n+eNZ|=a2hYTGmlFacb5b|F#CB@KMt)0<(v>f1bs(d^R{QtcU-P>+RZszyvw!6pL?l`9S*CL~yUYX`RHG`iJfRYc1H00z$Z9S4p zSGBFb+;f7lxF^Ru@lSG3t`hfRJ^2V9pVyOL_v0}w_v6?7_vQ89z1|=HOTUVLUuInQ ztG(5)%7Vld`*Qo(PB(`b@btrPbT8gg^h{qIyP1SZyW>M_pINduyXx)p<@aW(e-@1z aVDWznSX=+rCQtoc=DG5=`TqbWmBfNrpA;Mb diff --git a/src/nodes/shaders/crisplines.frag.qsb b/src/nodes/shaders/crisplines.frag.qsb deleted file mode 100644 index 274f8d5544268d1261e03ef12bbadf8984a5f083..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 872 zcmV-u1DE^&00~8SoXu9-Zqq;z-P{`Lrgv^n$Pfu7LJB5I5u&6jD&itlqM}eCRh8v9 zw!0A9(b_JNs{BSjfe+!C58?&E?Cdz%CiH;^Bvx8`XLjc7oU`kd8Dka3SedC-fWEc$cVT}SZSitwI{looM zlJ;AjElbX?AYY};D#VnDLg;W=AX`K#CG=HgK8&RA4&lEByGG**+Lei2pTtakRgxz6 z6)0|3^A*W=fa{eeKDqV^yzdcKZr>$)6QYV}mynel--MAA%Y=Rl;;STH8GU6`zC?9x zlf6j3+h7|sSEl?W$}ge@s@^2-#9l+XrYsKj(tDz(uQj_ z6%Q4v0S?fDR*;VAL#BWe!0qr2XEdT*?S^R68mkI4zrX9 z%%;E!he!5%M+9DKDRh)n2H2N$ou+g(Dk$mvYUW%jfhnecNB~NKXUAx$Al=i_SJ(LB zo_J{{q8Wg(zRzX)*z$e;Q0I|5$oii7Ec8-mV8ews;JqDV>Q8vse<&ZV(;YZ?36BCZ zazZbG{qRi8`qP=7oC^J1ljhpVrk&Q$HbKdXEy?1l{W?BIoQBmrIZ>H%F7zTTSB)BO z9Dyhi)^{KG46@Y;$MojpL(KDJ@0#ahRb@P*yZ#|*!pBN)DR>2;=)M?D6=xUId!udr ymv@1z_(H4r>$Kvne^#;78}sx}c%H^pn=pTy&D>~{dz;bk&dir^dHy#x?c~a-3$$qf diff --git a/src/nodes/shaders/crisplines.vert.qsb b/src/nodes/shaders/crisplines.vert.qsb deleted file mode 100644 index 674b357c8947d6cf75ecaa2cc7866f718001bcd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1871 zcmV-V2e9}605F?)ob6kCZxcrlUz`_QQr=Md0FIu{*Pqy}clW z=n(3P!F^CH3tM=?ho38ALb&kH6M5jYBjj(oMDW@xGU6e~WC)EKgxCgmR}%?A{7$hT zs-gg`?eNs?yA0I^caJEEEa>-y16~QyO}uf2+pQah$blP0>56iDoU{4WBSDT>gu6^L zFfD!A;MGII!*x=7dv2jxDA=9}5A&Sq*^5rax4rm6GGRP6Ot?JvQKppr!u8BT(ariJ zD&@mw;Il0piqfH}7a!a>{!#|p6=~IRqR9;9ANs zjEbN2ot##@Sj8mrhGZUU$sbsE}m#RJu zu2BZ;-@1HvVrpvUQc{_YP%%~Y8+0(2K*#KD<{)ZWcAdPm0~6UH{Cv?_7&Gehic`uD;t%WdF~g``RLPZUb(+*Q;+-}h zucaF61BzQzcaMXu#uU=)%?g%>XQ>W)wOJb}4(rqgD^wezN`nBgkx{8*r`%eoZOAVAm5*zbma8}b_bs^Z!F>fddhK?|en+j}M^8=zXXK7U z)3yA7g#=?Fh3wL+$PwrcKhczI%j6zxDw&CiS(+ z8Bp84Hkc(LOt@bMJmNZOK1}$zon-Mo1bu_r?S$_pd`#L=aXGU!uOgp!tnk>s$Ht7d z=9v6v)b3>b2QOX#LEucoV-8#QT{~`jCYiH-;w=OB#ZPXL_1CNerEGb$fq-e z`vc;ml#u<3!hUdy!~74?bw( z*97r&9$X^%31;&$vx#$XxrS5x4>^I!4*lSUyjpe&u2+(02)LI5Qf>3Bq=PTz@?ALa8Z1Fko7@+? z!-eg(>(ylB<~t61$HZpe?$-TYUEl8w?R}$Pi9_j?r)Ma=lCAV=rPqIuUO!Xmf_BWV zr`PCnOD}khZ_Fzo%8{FyhkgbqwzsKs?NxnQZ}Otf$ktcDs09(+b2b^vlwYQGiH@-|?)X99^iy)A#53O-C9pFQ`YWtyefUghm zqe>7*oo*fTztTI0ryTQ#Sh6&M7G9mgkVhN(Kmb?QFZ=_6{_BE`eIV$P?Whj~TlwQa z>tn#y{20(Wyl)-ew+`=Hhxc3c@P3`cbUcpw{$(Gg*Lhp%aH@3>`n->=__2H_QD4rn zd@E5~iP|ht^#MOzvEG+!U-$D6zFLI-rd@xDRR0k`G@Rf!@I!y|`c!^{ J{6F~|#be=Rv#|gG diff --git a/src/nodes/shaders/gradientconic.frag.qsb b/src/nodes/shaders/gradientconic.frag.qsb deleted file mode 100644 index 8a7e83b9bcffeeb2ad77d625c4ed24b4511852ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1826 zcmV+-2i^Dp02lyxob6a!Zxcrpo;VIk&8<+Nr8IO%3ar6djB$d&Nl5B&laPp#2#})4 z+N{@RTYJ~q9h;;G^`WZNr#|*S^*8j7^re?`X3ng~mvE^>)mB}!@t!l^xqmwz!x)=j zjHTfogFC}q7Q(-X)j&$Y&HkW^^E=zXPc$;QB$pV-OaBE+in>KEbyRg6m67!A-i4HMGDH zV-|IP>~-dJ9iq>gp;{bI%}%0u28y^(+7r-Eba)s{@bmto%|~`DYIboxuc{bN(mKv2 zW$t*l93MNtF2Y@6IJj}CpF|(C@CrGDQrn8zbC` zp-YkOfuS2G-6KPnCf&NBn;_km%ym5Rhj~vA)G{s_FJBz|1xg3o8* z35UbwotCvt(!f3jd5WIX(k{(DV2bI8ISbNJS|22Vmd}CzWAJ&D{2wPh>dGYRm+UIY zhh(1W!uY4iKj!)g$e&XDw5)4N_6BttXWkg^GqOEL@lc*7-D!}|Q|)6EALY-p}T4t)sog^cK}y&kfX%ME~XZ&nr5g0#n>U`5qVf@~lzQ4B29x zS?bMY!}bd4za{x9>9oxp+2jlxoAgH@GnB7Uyt8DF>py@!u3e|~yivmqs-a-`ERy~^ zvYRJc)PGO91*#3#mZ5uRNvD0>q8zk*n`GUWGUYi%YdY2<*_MqQmqzq?ne^J<9rBl^ zHC^)x`Mg7Uu9EH+tYhpinfh{DHR7#NyowR;F6nOJ39cF|y@`(zpMhG0@9NgM*spS*vdHU^)2N^)36DCi;G63YH=a~0Q5eV7he5j| zXl$k%h_!Y1S>^HLjkUZgWQ6hKju@~u;(>?FC)F({YIuTN5JVQXDlFB-uG8#z33EJX zR?usaty*FYHzP;sTGBqp^LD7+VeQJA1vYCN(kJ^`h7h1Ae`bPbdf-p>kSC zC$+1n5M9p&0{3h%DBKDBdKk6j-iM9DyIwxZ}S=my?0oN$DDLzkly6{o9J%$)BT;;uE}oy1+v=)*&EI3J)p%JB(R;| zIf(JL$@l?+{A3X1XpbQC|5AeZK_55Zz2K4_=EnVQeEAQt<&9h8>xfcg$?v4p%^p$m z`Aj?VTwhAh{l@dQ%B(!3_5)G=r;|!$`v2bZ{`a1={Hf482Vay-KGOguK7+Q z2xB~YLCs<0)%eWZ)0Q8{FoL;u6pB#nx4n2KlbQ7cx7n$Ae6i&TrwQkWTGQWMHuSOI zs$IiB_VZ1@Cr*SFHlUnlGIFxT+Sj*}-$CcpiC9 z4a6W8D%2%Tq^2cJ{+c?p8)xi3%LdhRu~0aAa1DCp?wFrr$Juxzp`>KyT2;xAv7 z-*PX2W49mJ$$pSL{~cRGIB;a`+Yxf++y_QHv{@Jf57ogIH;)O~7Wx%E@Jm|CL;t%= Q|LZ%j+Z>Gj6C?0OCtn__e*gdg diff --git a/src/nodes/shaders/gradientconic.vert.qsb b/src/nodes/shaders/gradientconic.vert.qsb deleted file mode 100644 index f807bce7b1287f7efd47d412f9699dabc4694044..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1624 zcmV-e2B-M|03<4Sob6g)PuxZjU+#{7hJ=I!+O$dIgcR<8m1_kiY0+$!n0A>;=e}ghmaFb->+yf&|WK z%vSVgPSKC(F1E`WtOBDRc*^mXg6e|1pVgQJmITZN`x)z_xyK6biX04s0S@!Hvq8ey z42krxHrFt$5VAT5*&w>k*KA!F()v9fW(V z@G`_(R(M(Btth-4@zxYxC-FA9t=XnNw0jVqcNIU7zN6T9kH&pXOqTPce3AS{AFcs6 z!{xKwHgP<&e4FcVe*}2MbE8{Zq#>`Y`H@EkRBx75YX4icGN#X^mU?9eu%K$%KQz*zfWk~Mfz@$K1TRk z6hEo&Hu>Jg`6AXD&3#UD_sCYHM~Nrb9wXg|&(qoiMBgW@)HlUsp%VI#E-JpFZPSW= zq-ROzEbNU8i%%_L{s0c{wMEL?CCbezLtvyD1G3MjMm+_dOc>Dx1NKX=Gg7jd149e*ktz!^Q+WLTU^aLoh>k9=xt>8*D zCw-bB*^(kVr^wFIdUJ&R6SDJ=XNcvf4kGb$oVt!*M)sW`bbU{MFjLgDFbW!Wr0+H= z+AB?mt7b(d{0ZE{1}lP0yvPZbd_O1)Zl&s5k#2=`$Bx#m$n{lr7+FD-VAL&7 zrTw~PyV22tcD$fz4bQFkK@Dxt8}I`xzY)>8Vnx?OvIIXt_~sEr zHFUi_-Lq;A1mAXaF164m;XH<=!(`Gq^S@0y8G`;6O-Q(E4kcdS-fo0Wkgxi-S1j!8 zD7s3CJZx{*X^5bdcGpYzs-_7N@^pzK@05uOLNs5JB5rna1=I+8358G2<ZU~m-cZ<^Sz&|i+*0+8TA9Y;Kq}Aqih~0O7r4l+(-Yymr1%Lw;-&)Wm6)nJu zpRHiyWg5;in*tuR0Yb)Ga5HHX?SodJaa0gn1GXnvX1A#!3yG=bCQ0HGc~Pel?;tt? z8*9(jpPNg8ABN^Lub!-M$s#nbZ+^YCw7R*ep|$VxkPt_4Z}7z4~Mc zo!2*>E5SIHX8_GK-~1q$uR93lYYsxKQOzrwC)K@L_$M#bbcn>cPNhee^&H01S2anC zDj;1lV=IzCWoJl@6i>luW1kTBIUztQr=^%D_HYU-lVzuBdvcLuwZ>p+KUBUMe~nB0 z^tmbV@!a|SiexNqv>^LOwb3#~+_!7Ah*s4}jh2fhi;%x)s=Pl{)a9gLRG+w;@G z_z*sC)m{j`xPQCoh5S#wkbm3r_>fx~@32SlzBM0MvcG(Onh$5G1gAd>TmJD$w)(~Y Wn@N8UnGI3up;#U diff --git a/src/nodes/shaders/gradientlinear.frag.qsb b/src/nodes/shaders/gradientlinear.frag.qsb deleted file mode 100644 index be5fa92c530aaab819c11b1cd8d79624d60c7e02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1444 zcmV;V1zY+601;7moaI+pZyPrdrX^q9I7ySbX>)I^CS9eDsv1t3R;DBzC`8YC2A)(mYV^e%^6jJ1&fft7ZI2W7$d42w~hDek@kTqh2V|rFAz*!X(`S5~PPb zJ(h8ou(V_&Zi^!np+C)eqC6u%awDzLgY&7e2 z2oDew*@h*_*efs$Y>%fra#sf2qqH0P-=@5~&K2Kn?iC6UjW(#ecl8<@{R}t`?k9Sn zg#T(Ke6OGI`~O|SlUy0#4y8Qc#CYX2^A zFR+T%w_!Y9h%uH9GC3~c=5D(>7S#dTPInvjN_c72e*-q*` zGWjfc(}b}={%#S*0_7Wd9|HXe*-TK(NZ+<%yhC%udjLKvtbZb4oWBESim)+{*D0SX zwEi0u^D1axC;BU}z!+~bbAloN3GmR@rxf393&SJ+FJxCITaR$B5bqCI#Y1==kX~^* z;y!-~dKi~OG0zb`?%f62x5D2=(%S@_d7UT2!@Yb#*q6u-Wq$%5(htp>Qq(!7YKfJj z$^&Q$9g*s0_%-yWuFRB3z5Qm{vXWPR#D9X8qFc}M(XwtNzUjJP0}bV6(&=PEc|o&o zbzM?4-FQfG*;X`q)R~49@7GP!-YJf(M+SSf-=Xce6-Kaay7;!@O1OTh=TmpL^)u9m zbA>Az6j57U-WCjYdOC`>H#fGP`)g^EW&TFo%hf=e?puJ*oo{|zd-iN=y=fLS2H;t) zh7hb^0Ac&Nzr)k6Py|6L?>=wJ6f{g~ywRjA8i)27)UgjCjKe?8lgPJEqR}jvQ*R`_ zF6>BG_!8$uAXb)FY!yHm6}P%X&|&Tn_@gu@717QFB)Dy{z>B zBI0fka=6d6CGW;bhA*6iNh;dz!o3%f%rdy`-Rq@^O4M;rWDAZ{lW`E{ZQ(wOgyNwO zhj1wOS1o=fqxR?c(>Pd#`wc?4F^@zBSr@LhYK^&2l{Ic(s^~p?$F+*EaIH;T|4Hxh z?ylY!uUX&Q8)GTslS*iJH_xDC!z74pTV0_t4rL6*?sElk@8?SRzUT4q6+g~=Bdphl z3q~EJg13Q;GiBV}aq0CZQE^djo33Luol?bE7peQ+yhy}W za?Q*uQU>dX^c3&@-rk}Ki^qCz@92U91=H(w<`>_xHqb0?s77`C>d>PRXtjEICof{e zXT^Q}rZuKt$athYlcD+=Xd8=m>W8vCa<{c|o|r1cGMv(p(Y>P0$~)A=&;75AX4C1V yB9NLoklllxiMutzma!UFK&SmhVx0Z&J_IYHcNI;Ke7VyX{ZMN?S@&;Z&k$F4LC^C5 diff --git a/src/nodes/shaders/gradientlinear.vert.qsb b/src/nodes/shaders/gradientlinear.vert.qsb deleted file mode 100644 index 4a4a0b36b8119e3e992b7dadc3315511c0600028..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1582 zcmV+}2GRKd03$1Sob6g|Zxcrl-o$nSCcHzTl#+uKutP8=BtT<=K%r_QAteHYDxv7) z*yr?G`!3v_i37@~s#3pJs@ndA{-XYseyQ4--DiD!X9ox^Rnq#R^X<$$Gdnvow`&gw zA#y@p!*qWjUI<47BBIZZSP(w_1)@%pEJOapC6d=MVTJ*^@T6V`vh8MK*@##bZPB37K6>i$69bi@drY)Mm3#_>E3F=Y?4E%;q6cGg*)@Xu z()BEWM?|0N5P{aoc8x4YViR61>lp3i8pE?5FE7{33{Q;mFi-2d1HnEbV!s@-H?6Ac>50baF4BF2^-0RSbFlvf(R#5tN$0xsL>CkD zMiCs%8v^d0!5ao|S2wmCQZksD2) z0X>gg9Yj8sh|By#;2nfb_Uk@bJSl5I#r=e#e+qo9e;T|~hW@vt&$16;pD}mI+x_5a z`ychOe-?ag|6}mZA_f`QIs@4}YShBoHGLjy|B>e6*k1tVyn&ejM$@09bS?tJ{O`fL z1X~y3$2fSrCa#4ktZ5QY4t^jVrmq20f*r1*>q6DtB<8se9NS<&W>81> ziQ;;`W#DfbxZ99@2me2X?rlT2V(89cz6!8^P)2X7lO~HjGArW!n6t7m;d-@ZyY5(b zT254L+O*v^-PODKm>;^W`ZfM2eRVgVZ-=h8W_i_?6RuZljwQ7!`Ft1!?OJ55wj23Z zd5f+_)2~J|of)fDjRLn*F__j1rxy8v!LocZ=0=;9{8ns>T`t>xJ2EX=HNWWxi(cL7 zSkIodLnkOS{hC)UuB;@cSZmtLe&|N7?-6btLk9KC;Ccy{$-5wOIt#uZ)Je4(k^8Id z$SJ5fSY07v2i2&c%~>wb8AjDLhp3g6DRSB)(v$JIWVPv&0QA`)_t|U_9>f;;p0{3Y z8H<{>Xc@$Gy^`T#sk3Qal_pCnti(ttQJy@~G7&E~6oMux8S$LA>V8z9Nv5Py(YhuX zJO(FLGvf>6D$&+t%0ZDSL#9RK*uW`Jm-)FqLZ&IJIzo-VAys`9#KGsq)`*~!OiWBVltfauDmjv&w zj=-jDBb`J(Pp9J~X2)u3JCOmOqt|WC4I|oJR?9jxfxlt5s$cs-yfw3PHk_NYD1G1f zjYjB1g<83o*i9u+g(d}@F@Xw)I!FO$i>ffFzN(R1>$6W+Qldn#Oi`jf5(2Y0P{)s# z7au*f7Xm*F?L}`rd730Q`#I~$XJ0NXEj@ZrHWwA=BnI3{oFnEOOYLZV`y;FW6v^Xi z&U*aR2+Ec&bavHFRD0rB=v(jh8_xv$pRV{;yIC-NnKG-aSK%$HzBjt+o$tx4rH@=1 z#~VVN-+2?zdql-vB!NazX^TjMV)XG(sr!;pAd{0iJQJ@#4>pkxv+#{mH96f@db6+N z$qzf;?901vv)|)8dUA^vBJO!G`xmq4q4(~c^*r_|OQL_zbEAP?&3*U(E0)3n%i~s-t diff --git a/src/nodes/shaders/gradientradial.frag.qsb b/src/nodes/shaders/gradientradial.frag.qsb deleted file mode 100644 index 9759ed4ca97712fe980d5f9c73e0008e5ed69221..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1550 zcmV+p2J!g-01~};oaI>SZ`4K*-{kV3CP1M;%cHO)E%m{1xTipAk3`U%KX7q>q9WUoU~L_haa#i#xa{S*78kD1-Ey?40-p-QMyw=(CM{mpy5GYw;GnlUy7 z&jdUc^H~D_r7Qqy5+3$9EjG9ieTH=a>9HQ z9P5E*2^vFo0Q7O%dtl(+FJ8`r+k(Xa7a*`Q6v6{#YQ&mT-UnbIXBmOl#(__Q&OX3> zfJ=5r!K@bnk6SuVewm*QP|*WLjMJ^#m~)5(OieW%`5LJHc_Kwre5 zaV1I8UV56@GWU}xNjJP+ z-;7hD$D6>6M7k+GDY#qW+)VRLe1>={17zq^LUznUao;=xDb#x#jgrDScNZN1$G;BU~x4g6~B&i^X3hbe@ zbq@EvC>Lds1tcr3QqPZL{V@h08#eN{^Lro!=NJys~*TEnFEtl4}m7=?XW*_rf#n#FDwyq?#3; zP$-%)!k89K6rn*Tr)dUb91|nug9=_+com>c`lf#~E`gsH_C=b7Nz6aL zu*mwe)F$?Y567zd{0y#6x%o|1S%njm$6+T)d+JueoEt1U2d&lWw7@O|fQkn`hA<`% z=rd6JZ$5-lf4O$4zM<3@2hKciZ+Fz1Z+Fz1=20^$gDa>iGqqKlT$sgzS#a$;#61m{ zEtc>&T)g=E-Q&&2%}fT(#XFAf1-0^WKgDKM2f(MWaS@)&3>#EU@n=y7ykWzdCmRKQ zjr1Uma#xJ~%Lcs$^i_JFR`hg9FO-;yH_LQ`EO--ydtmS;iMM9(YQ$StKGaGa`g3i_ z|7+wwt`7h;spy*0f$!(x4OE{24gK+h;Y^+Nk+S=Cxm{sP5+jO3BNNIcxXM7Gb;KGK(o_Yu%n zNOnrqZARtp3gHV|sE3oytE7ih9+7tr=y}T71o=HrH7Wf3gx=2@`!@|g8?=x1?m}HB zSv92~<`3XZlWoj(opQcJIr*64dI%`A^(pzcU|_Bj{};d@{Taz2e-138ZJT2Fn)a8$ zdY$-Rf*j`R2Ghe`o$R6Sx5(a2vWL2w#Q&A#Zj)@2^j;+1pJ4GGJa-9K432oVz5pD? zX;BX5NI#yJ({xq}duIr@PVt>19-g0Pr29O{;oe`M59xdQbQbrGo@L8bd$rJqtE=a6 zKl0)(4??dSCmBv2A-tp_;Pbbh^};L*R_C+>tSqow8M|mLl{hp9s zUd}XykN7O{7cbl6JAD{8$2a?AXdD}8_zklbLuo%U3m8R6^w5T%__T7B?y7*5{bl0! zYHV{HtDg!#RMcMB-RtW>+DF)7EJuB1?`Fi)E{q=Z_Pz8FuY`Xw*|k>R!ED!!+;5@U ztDf|>ot?KG@UV6V)rC8;U)8YnUmLyu9~GHA+6MKXmT-;uBgoJnI>uxF0b*xQr^ZJO A)c^nh diff --git a/src/nodes/shaders/gradientradial.vert.qsb b/src/nodes/shaders/gradientradial.vert.qsb deleted file mode 100644 index b530364f68a2e9ebd650e4f25df4534996a192b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1479 zcmV;&1vvTu03O76ob6d{Pa8)NUTpJrkU&UCo02rwI3zYN7ned))ip}wR3%a*P>7;P z7P5}>nOvRXejg=i9rpLr^0U2#4(3nSEyV+1Z)n1{h<5 zOk5fGTxEOAWG?gJyThu?fghJOU?zuOCP{LKl zAZU31;mPI`&GQ@D@=8f?%5ogeO%QEl)7C8;$D_2^4BEmB%Ab>Ol*c7`4dgJOgIpf$ z%K0uP(g9gM4s`>Bdm!mDq+648S<-EA4%sda`Aot6mc$R`FQm1v(Ri$j$#NaqUxx1t z$7lH(q6o4OImT4@d;OKW|g648O zu0wop6XZW!8~t1&4wK{uxdXAH1`?tzec`Mo*`Z6 z>pH~`@i)lV1j)Aui~hcbm}gj&;i&%`G?*V1iq8d#!8))(J{L)MfozcTL$H|U=OOla zh3toUoQ3`uzzp*^3LmIng%w9hhdypFk*`y?DslQ9Y!oJP=qBmW5AHEf zak){mbnp!E(xGv+TgM3IBp|>UhaW* z^@bIANuc&hh62>!3B=GOpnUhOcgJJbwDTUUePMt3S4P1D`^d_6200egC4mzW(%4N#0P` zsRXz$Hqv8_^}tUoLc8eWKDK?pY(AHQfotqJR)f>5W11AgqZd9a@&>fdfx4JFSFx77 zNJVW2t%78@AZJZ6WuUzRlPC&vvAKO2B2_z<{-05`4{YXv zwTH`nxl-z;7Mu%3sg1cJjwsxu0jZTdXs#87Dkm`&q)4g2wwjLH=Fb&8c~AjGawuF` zHj0T_17*6-cz(WpYHCNMCdbh8Yfeoi!12;j3U`i0FGTpP{VH$SMk{ET>UV9^*IRXX z-)ULft4gHztajrberZ3hLeM>_$z&8tG4gP@Qh=`mR z6+(Bag=>bzy0x_cd~FbI9ABs&mQps7i_Lgbpq>4J8 zYH?4oDt1KiVmb|SQdGVjseH|-e3wqXeD`$s0Mk=0;qF=WsN`tw)D|=zK!fghn~4sf z^x+@C2}U^{HpZfc5JH#p<%aMcO&qTw9OdJF4dE<1`%NL@XK6pk?Yv2R_e~B0}6U zf1J07@1RAD_(rexGV1=v&`2h1c&7t6x!FlV_K($qvUmq{3R=+jR_1c!nCRS3LF0G^ hI`>@qwJ+@A#eZ~J>VF}r`NW^|-Z-DK{|~_h0=*k1+@$~j