QskArcShadowNode introduced ( kudos to Rick )
This commit is contained in:
parent
a420407a56
commit
e63b064f5a
109
playground/shadows/ArcPage.cpp
Normal file
109
playground/shadows/ArcPage.cpp
Normal file
@ -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 <QskGridBox.h>
|
||||
|
||||
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"
|
14
playground/shadows/ArcPage.h
Normal file
14
playground/shadows/ArcPage.h
Normal file
@ -0,0 +1,14 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QskLinearBox.h>
|
||||
|
||||
class ArcPage : public QskLinearBox
|
||||
{
|
||||
public:
|
||||
ArcPage( QQuickItem* parent = nullptr );
|
||||
};
|
73
playground/shadows/BoxPage.cpp
Normal file
73
playground/shadows/BoxPage.cpp
Normal file
@ -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 <QskRgbValue.h>
|
||||
#include <QFontMetrics>
|
||||
|
||||
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 );
|
||||
}
|
19
playground/shadows/BoxPage.h
Normal file
19
playground/shadows/BoxPage.h
Normal file
@ -0,0 +1,19 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QskLinearBox.h>
|
||||
|
||||
class QskSlider;
|
||||
|
||||
class BoxPage : public QskLinearBox
|
||||
{
|
||||
public:
|
||||
BoxPage( QQuickItem* parent = nullptr );
|
||||
|
||||
private:
|
||||
void addSlider( int row, const QString&, QskSlider* );
|
||||
};
|
@ -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)
|
||||
|
269
playground/shadows/ShadowedArc.cpp
Normal file
269
playground/shadows/ShadowedArc.cpp
Normal file
@ -0,0 +1,269 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ShadowedArc.h"
|
||||
|
||||
#include <QskSkinlet.h>
|
||||
#include <QskArcNode.h>
|
||||
#include <QskArcMetrics.h>
|
||||
#include <QskShadowMetrics.h>
|
||||
|
||||
#include <QskArcNode.h>
|
||||
#include <QskSGNode.h>
|
||||
|
||||
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"
|
64
playground/shadows/ShadowedArc.h
Normal file
64
playground/shadows/ShadowedArc.h
Normal file
@ -0,0 +1,64 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QskControl.h>
|
||||
|
||||
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& );
|
||||
};
|
@ -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 );
|
||||
}
|
||||
|
||||
|
47
playground/shadows/Slider.cpp
Normal file
47
playground/shadows/Slider.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "Slider.h"
|
||||
|
||||
#include <QskSlider.h>
|
||||
#include <QskTextLabel.h>
|
||||
|
||||
#include <qfontmetrics.h>
|
||||
|
||||
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"
|
37
playground/shadows/Slider.h
Normal file
37
playground/shadows/Slider.h
Normal file
@ -0,0 +1,37 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QskLinearBox.h>
|
||||
|
||||
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;
|
||||
};
|
@ -3,129 +3,31 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ShadowedBox.h"
|
||||
#include "BoxPage.h"
|
||||
#include "ArcPage.h"
|
||||
|
||||
#include <QskObjectCounter.h>
|
||||
#include <QskWindow.h>
|
||||
#include <QskGridBox.h>
|
||||
#include <QskSlider.h>
|
||||
#include <QskTextLabel.h>
|
||||
#include <QskRgbValue.h>
|
||||
#include <QskTabView.h>
|
||||
#include <QskTabBar.h>
|
||||
|
||||
#include <SkinnyShortcut.h>
|
||||
#include <QGuiApplication>
|
||||
#include <QFontMetrics>
|
||||
|
||||
class BoxPanel : public QskBox
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
BoxPanel( QQuickItem* parent = nullptr )
|
||||
: QskBox( parent )
|
||||
class TabView : public QskTabView
|
||||
{
|
||||
setAutoLayoutChildren( true );
|
||||
setPadding( 60 );
|
||||
public:
|
||||
TabView()
|
||||
{
|
||||
//setTabBarEdge( Qt::LeftEdge );
|
||||
|
||||
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 ) ); } );
|
||||
}
|
||||
};
|
||||
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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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() )
|
||||
|
@ -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 <qpen.h>
|
||||
#include <qpainterpath.h>
|
||||
|
||||
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, {}, {} );
|
||||
}
|
||||
|
||||
const auto metrics = qskEffectiveMetrics( arcMetrics, rect );
|
||||
const auto gradient = qskEffectiveGradient( fillGradient, metrics );
|
||||
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 );
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
368
src/nodes/QskArcShadowNode.cpp
Normal file
368
src/nodes/QskArcShadowNode.cpp
Normal file
@ -0,0 +1,368 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskArcShadowNode.h"
|
||||
|
||||
#include <qcolor.h>
|
||||
#include <qsgmaterial.h>
|
||||
#include <qsgmaterialshader.h>
|
||||
#include <qmath.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qsgnode_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
// QSGMaterialRhiShader became QSGMaterialShader in Qt6
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||
#include <QSGMaterialRhiShader>
|
||||
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 );
|
||||
}
|
32
src/nodes/QskArcShadowNode.h
Normal file
32
src/nodes/QskArcShadowNode.h
Normal file
@ -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 <qsgnode.h>
|
||||
|
||||
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
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,11 @@
|
||||
<RCC version="1.0">
|
||||
<qresource prefix="/qskinny/">
|
||||
|
||||
<file>shaders/arcshadow.frag</file>
|
||||
<file>shaders/arcshadow.vert</file>
|
||||
<file>shaders/arcshadow.frag.qsb</file>
|
||||
<file>shaders/arcshadow.vert.qsb</file>
|
||||
|
||||
<file>shaders/boxshadow.vert.qsb</file>
|
||||
<file>shaders/boxshadow.frag.qsb</file>
|
||||
<file>shaders/boxshadow.vert</file>
|
||||
|
46
src/nodes/shaders/arcshadow-vulkan.frag
Normal file
46
src/nodes/shaders/arcshadow-vulkan.frag
Normal file
@ -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;
|
||||
}
|
21
src/nodes/shaders/arcshadow-vulkan.vert
Normal file
21
src/nodes/shaders/arcshadow-vulkan.vert
Normal file
@ -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;
|
||||
}
|
37
src/nodes/shaders/arcshadow.frag
Normal file
37
src/nodes/shaders/arcshadow.frag
Normal file
@ -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;
|
||||
}
|
BIN
src/nodes/shaders/arcshadow.frag.qsb
Normal file
BIN
src/nodes/shaders/arcshadow.frag.qsb
Normal file
Binary file not shown.
12
src/nodes/shaders/arcshadow.vert
Normal file
12
src/nodes/shaders/arcshadow.vert
Normal file
@ -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;
|
||||
}
|
BIN
src/nodes/shaders/arcshadow.vert.qsb
Normal file
BIN
src/nodes/shaders/arcshadow.vert.qsb
Normal file
Binary file not shown.
10
src/nodes/shaders/arcshadow2qsb.sh
Executable file
10
src/nodes/shaders/arcshadow2qsb.sh
Executable file
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user