QskArc rendering improved
This commit is contained in:
parent
b17cabaa83
commit
feabc1fd50
|
@ -10,7 +10,6 @@
|
|||
#include "QskArcRenderer.h"
|
||||
#include "QskMargins.h"
|
||||
#include "QskGradient.h"
|
||||
#include "QskShapeNode.h"
|
||||
#include "QskSGNode.h"
|
||||
#include "QskShadowMetrics.h"
|
||||
|
||||
|
@ -22,40 +21,38 @@ namespace
|
|||
{
|
||||
ShadowRole,
|
||||
|
||||
PathRole,
|
||||
ArcRole
|
||||
/*
|
||||
If possible border + filling will be displayed by ArcRole
|
||||
Otherwise ArcRole displays the border and FillRole the filling
|
||||
*/
|
||||
|
||||
ArcRole,
|
||||
FillRole
|
||||
};
|
||||
}
|
||||
|
||||
static inline QskGradient qskEffectiveGradient(
|
||||
const QskGradient& gradient, const QskArcMetrics& metrics )
|
||||
static void qskUpdateChildren( QSGNode* parentNode, quint8 role, QSGNode* node )
|
||||
{
|
||||
if ( !gradient.isMonochrome() )
|
||||
{
|
||||
if ( gradient.type() == QskGradient::Stops )
|
||||
{
|
||||
QskGradient g( gradient.stops() );
|
||||
g.setConicDirection( 0.5, 0.5, metrics.startAngle(), 360.0 );
|
||||
static const QVector< quint8 > roles = { ShadowRole, ArcRole, FillRole };
|
||||
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
return gradient;
|
||||
auto oldNode = QskSGNode::findChildNode( parentNode, role );
|
||||
QskSGNode::replaceChildNode( roles, role, parentNode, oldNode, node );
|
||||
}
|
||||
|
||||
template< typename Node >
|
||||
inline Node* qskInsertOrRemoveNode( QSGNode* parentNode, quint8 role, bool isValid )
|
||||
inline Node* qskNode( QSGNode* parentNode, quint8 role )
|
||||
{
|
||||
using namespace QskSGNode;
|
||||
|
||||
Node* oldNode = static_cast< Node* >( findChildNode( parentNode, role ) );
|
||||
Node* newNode = isValid ? ensureNode< Node >( oldNode ) : nullptr;
|
||||
auto node = static_cast< Node* > ( findChildNode( parentNode, role ) );
|
||||
|
||||
static const QVector< quint8 > roles = { ShadowRole, PathRole, ArcRole };
|
||||
replaceChildNode( roles, role, parentNode, oldNode, newNode );
|
||||
if ( node == nullptr )
|
||||
{
|
||||
node = new Node();
|
||||
setNodeRole( node, role );
|
||||
}
|
||||
|
||||
return newNode;
|
||||
return node;
|
||||
}
|
||||
|
||||
QskArcNode::QskArcNode()
|
||||
|
@ -82,28 +79,24 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
|
|||
const qreal borderWidth, const QColor& borderColor, const QskGradient& gradient,
|
||||
const QColor& shadowColor, const QskShadowMetrics& shadowMetrics )
|
||||
{
|
||||
const bool radial = false;
|
||||
using namespace QskSGNode;
|
||||
|
||||
const auto metricsArc = arcMetrics.toAbsolute( rect.size() );
|
||||
QskArcShadowNode* shadowNode = nullptr;
|
||||
QskArcRenderNode* arcNode = nullptr;
|
||||
QskArcRenderNode* fillNode = nullptr;
|
||||
|
||||
if ( metricsArc.isNull() || rect.isEmpty() )
|
||||
if ( !( rect.isEmpty() || arcMetrics.isNull() ) )
|
||||
{
|
||||
delete QskSGNode::findChildNode( this, ShadowRole );
|
||||
delete QskSGNode::findChildNode( this, PathRole );
|
||||
delete QskSGNode::findChildNode( this, ArcRole );
|
||||
|
||||
return;
|
||||
}
|
||||
const bool radial = false;
|
||||
const auto metricsArc = arcMetrics.toAbsolute( rect.size() );
|
||||
|
||||
const auto hasFilling = gradient.isVisible();
|
||||
const auto hasBorder = ( borderWidth > 0.0 )
|
||||
&& borderColor.isValid() && ( borderColor.alpha() > 0 );
|
||||
|
||||
const auto hasShadow = shadowColor.isValid() && ( shadowColor.alpha() > 0 );
|
||||
|
||||
auto shadowNode = qskInsertOrRemoveNode< QskArcShadowNode >(
|
||||
this, ShadowRole, hasFilling && hasShadow );
|
||||
|
||||
if ( shadowNode )
|
||||
if ( hasShadow && hasFilling )
|
||||
{
|
||||
/*
|
||||
The shader of the shadow node is for circular arcs and we have some
|
||||
|
@ -112,6 +105,8 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
|
|||
and not only to its radius. TODO ...
|
||||
*/
|
||||
|
||||
auto shadowNode = qskNode< QskArcShadowNode >( this, ShadowRole );
|
||||
|
||||
const auto sm = shadowMetrics.toAbsolute( rect.size() );
|
||||
const auto shadowRect = sm.shadowRect( rect );
|
||||
const auto spreadRadius = sm.spreadRadius() + 0.5 * metricsArc.thickness();
|
||||
|
@ -120,22 +115,32 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
|
|||
metricsArc.startAngle(), metricsArc.spanAngle(), shadowColor );
|
||||
}
|
||||
|
||||
auto pathNode = qskInsertOrRemoveNode< QskShapeNode >( this, PathRole,
|
||||
hasFilling && !QskArcRenderer::isGradientSupported( rect, metricsArc, gradient ) );
|
||||
|
||||
if ( pathNode )
|
||||
if ( hasBorder || hasFilling )
|
||||
{
|
||||
const auto path = metricsArc.painterPath( rect, radial );
|
||||
pathNode->updateNode( path, QTransform(), rect,
|
||||
qskEffectiveGradient( gradient, metricsArc ) );
|
||||
}
|
||||
arcNode = qskNode< QskArcRenderNode >( this, ArcRole );
|
||||
|
||||
auto arcNode = qskInsertOrRemoveNode< QskArcRenderNode >(
|
||||
this, ArcRole, hasBorder || ( hasFilling && !pathNode ) );
|
||||
|
||||
if ( arcNode )
|
||||
if ( hasBorder && hasFilling )
|
||||
{
|
||||
arcNode->updateArc( rect, metricsArc, radial,
|
||||
borderWidth, borderColor, pathNode ? QskGradient() : gradient );
|
||||
if ( !QskArcRenderer::isGradientSupported( rect, metricsArc, gradient ) )
|
||||
fillNode = qskNode< QskArcRenderNode >( this, FillRole );
|
||||
}
|
||||
|
||||
if ( fillNode )
|
||||
{
|
||||
arcNode->updateBorder( rect, metricsArc,
|
||||
radial, borderWidth, borderColor );
|
||||
|
||||
fillNode->updateFilling( rect, metricsArc, radial, borderWidth, gradient );
|
||||
}
|
||||
else
|
||||
{
|
||||
arcNode->updateArc( rect, metricsArc,
|
||||
radial, borderWidth, borderColor, gradient );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qskUpdateChildren( this, ShadowRole, shadowNode );
|
||||
qskUpdateChildren( this, ArcRole, arcNode );
|
||||
qskUpdateChildren( this, FillRole, fillNode );
|
||||
}
|
||||
|
|
|
@ -11,41 +11,61 @@
|
|||
#include "QskSGNode.h"
|
||||
#include "QskFillNodePrivate.h"
|
||||
|
||||
static inline bool qskHasBorder( qreal width, const QColor& color )
|
||||
{
|
||||
return ( width > 0.0 ) && color.isValid() && ( color.alpha() > 0 );
|
||||
}
|
||||
|
||||
class QskArcRenderNodePrivate final : public QskFillNodePrivate
|
||||
{
|
||||
public:
|
||||
inline void resetNode( QskArcRenderNode* node )
|
||||
{
|
||||
hash = 0;
|
||||
m_metricsHash = m_colorsHash = 0;
|
||||
node->resetGeometry();
|
||||
}
|
||||
|
||||
inline bool updateHash( const QRectF& rect, const QskArcMetrics& metrics,
|
||||
bool radial, qreal borderWidth, const QColor& borderColor,
|
||||
const QskGradient& gradient )
|
||||
inline bool updateMetrics( const QRectF& rect,
|
||||
const QskArcMetrics& metrics, bool radial, qreal borderWidth )
|
||||
{
|
||||
QskHashValue value = 3496;
|
||||
QskHashValue hash = 13000;
|
||||
|
||||
value = qHashBits( &rect, sizeof( QRectF ), value );
|
||||
value = metrics.hash( value );
|
||||
value = qHash( radial, value );
|
||||
value = qHash( borderWidth, value );
|
||||
value = qHashBits( &borderColor, sizeof( borderColor ), value );
|
||||
hash = qHashBits( &rect, sizeof( rect ), hash );
|
||||
hash = metrics.hash( hash );
|
||||
hash = qHash( radial, hash );
|
||||
hash = qHash( borderWidth, hash );
|
||||
|
||||
return updateHash( m_metricsHash, hash );
|
||||
}
|
||||
|
||||
inline bool updateColors( const QColor& borderColor, const QskGradient& gradient )
|
||||
{
|
||||
QskHashValue hash = 13000;
|
||||
|
||||
if ( borderColor.isValid() && ( borderColor.alpha() > 0 ) )
|
||||
hash = qHashBits( &borderColor, sizeof( borderColor ), hash );
|
||||
|
||||
if ( gradient.isVisible() )
|
||||
value = gradient.hash( value );
|
||||
hash = gradient.hash( hash );
|
||||
|
||||
if ( hash != value )
|
||||
return updateHash( m_colorsHash, hash );
|
||||
}
|
||||
|
||||
private:
|
||||
inline bool updateHash( QskHashValue& value, const QskHashValue newValue ) const
|
||||
{
|
||||
hash = value;
|
||||
if ( newValue != value )
|
||||
{
|
||||
value = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
QskHashValue hash = 0;
|
||||
public:
|
||||
QskHashValue m_metricsHash = 0;
|
||||
QskHashValue m_colorsHash = 0;
|
||||
};
|
||||
|
||||
QskArcRenderNode::QskArcRenderNode()
|
||||
|
@ -69,47 +89,103 @@ void QskArcRenderNode::updateFilling( const QRectF& rect,
|
|||
{
|
||||
Q_D( QskArcRenderNode );
|
||||
|
||||
if ( rect.isEmpty() || arcMetrics.isNull() || !gradient.isVisible() )
|
||||
{
|
||||
d->resetNode( this );
|
||||
return;
|
||||
}
|
||||
|
||||
const auto metrics = arcMetrics.toAbsolute( rect.size() );
|
||||
const auto borderMax = 0.5 * metrics.thickness();
|
||||
|
||||
const bool hasFill = gradient.isVisible() && ( borderWidth < borderMax );
|
||||
const bool hasBorder = false;
|
||||
|
||||
if ( rect.isEmpty() || metrics.isNull() || !( hasFill || hasBorder ) )
|
||||
if ( borderWidth >= 0.5 * metrics.thickness() )
|
||||
{
|
||||
d->resetNode( this );
|
||||
return;
|
||||
}
|
||||
|
||||
borderWidth = qMin( borderWidth, borderMax );
|
||||
|
||||
if ( !d->updateHash( rect, metrics, radial, borderWidth, QColor(), gradient ) )
|
||||
{
|
||||
d->resetNode( this );
|
||||
return;
|
||||
}
|
||||
|
||||
#if 1
|
||||
const bool coloredGeometry = hasHint( PreferColoredGeometry )
|
||||
&& QskArcRenderer::isGradientSupported( rect, metrics, gradient );
|
||||
Q_ASSERT( coloredGeometry ); // TODO ...
|
||||
#endif
|
||||
|
||||
auto& geometry = *this->geometry();
|
||||
bool dirtyGeometry = d->updateMetrics( rect, metrics, radial, borderWidth );
|
||||
bool dirtyMaterial = d->updateColors( QColor(), gradient );
|
||||
|
||||
if ( coloredGeometry != isGeometryColored() )
|
||||
dirtyGeometry = dirtyMaterial = true;
|
||||
|
||||
if ( dirtyGeometry || dirtyMaterial )
|
||||
{
|
||||
if ( coloredGeometry )
|
||||
{
|
||||
setColoring( QskFillNode::Polychrome );
|
||||
|
||||
QskArcRenderer::setColoredFillLines( rect, metrics, radial,
|
||||
borderWidth, gradient, geometry );
|
||||
borderWidth, gradient, *geometry() );
|
||||
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
else
|
||||
{
|
||||
setColoring( rect, gradient );
|
||||
|
||||
if ( dirtyGeometry )
|
||||
{
|
||||
QskArcRenderer::setFillLines( rect, metrics,
|
||||
radial, borderWidth, *geometry() );
|
||||
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QskArcRenderNode::updateBorder( const QRectF& rect,
|
||||
const QskArcMetrics& metrics, bool radial,
|
||||
const QskArcMetrics& arcMetrics, bool radial,
|
||||
qreal borderWidth, const QColor& borderColor )
|
||||
{
|
||||
updateArc( rect, metrics, radial, borderWidth, borderColor, QskGradient() );
|
||||
Q_D( QskArcRenderNode );
|
||||
|
||||
if ( rect.isEmpty() || arcMetrics.isNull()
|
||||
|| !qskHasBorder( borderWidth, borderColor ) )
|
||||
{
|
||||
d->resetNode( this );
|
||||
return;
|
||||
}
|
||||
|
||||
const bool coloredGeometry = hasHint( PreferColoredGeometry );
|
||||
|
||||
bool dirtyGeometry = d->updateMetrics( rect, arcMetrics, radial, borderWidth );
|
||||
bool dirtyMaterial = d->updateColors( borderColor, QskGradient() );
|
||||
|
||||
if ( coloredGeometry != isGeometryColored() )
|
||||
dirtyGeometry = dirtyMaterial = true;
|
||||
|
||||
if ( dirtyGeometry || dirtyMaterial )
|
||||
{
|
||||
const auto metrics = arcMetrics.toAbsolute( rect.size() );
|
||||
borderWidth = qMin( borderWidth, 0.5 * metrics.thickness() );
|
||||
|
||||
if ( coloredGeometry )
|
||||
{
|
||||
setColoring( QskFillNode::Polychrome );
|
||||
|
||||
QskArcRenderer::setColoredBorderLines( rect, metrics, radial,
|
||||
borderWidth, borderColor, *geometry() );
|
||||
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
else
|
||||
{
|
||||
setColoring( borderColor );
|
||||
|
||||
if ( dirtyGeometry )
|
||||
{
|
||||
QskArcRenderer::setBorderLines( rect, metrics, radial,
|
||||
borderWidth, *geometry() );
|
||||
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QskArcRenderNode::updateArc(
|
||||
|
@ -119,38 +195,50 @@ void QskArcRenderNode::updateArc(
|
|||
Q_D( QskArcRenderNode );
|
||||
|
||||
const auto metrics = arcMetrics.toAbsolute( rect.size() );
|
||||
if ( rect.isEmpty() || metrics.isNull() )
|
||||
{
|
||||
d->resetNode( this );
|
||||
return;
|
||||
}
|
||||
|
||||
const auto borderMax = 0.5 * metrics.thickness();
|
||||
|
||||
const bool hasFill = gradient.isVisible() && ( borderWidth < borderMax );
|
||||
const bool hasBorder = ( borderWidth > 0.0 )
|
||||
&& borderColor.isValid() && ( borderColor.alpha() > 0 );
|
||||
const bool hasBorder = qskHasBorder( borderWidth, borderColor );
|
||||
|
||||
if ( rect.isEmpty() || metrics.isNull() || !( hasFill || hasBorder ) )
|
||||
if ( hasBorder && hasFill )
|
||||
{
|
||||
d->resetNode( this );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
When having a monochrome gradient that has the same color as the
|
||||
border we might be able to use QskFillNode::Monochrome. For the
|
||||
moment this is not implemented
|
||||
*/
|
||||
borderWidth = qMin( borderWidth, borderMax );
|
||||
|
||||
if ( !d->updateHash( rect, metrics, radial, borderWidth, borderColor, gradient ) )
|
||||
const bool isDirty = d->updateMetrics( rect, arcMetrics, radial, borderWidth )
|
||||
|| d->updateColors( borderColor, gradient ) || !isGeometryColored();
|
||||
|
||||
if ( isDirty )
|
||||
{
|
||||
d->resetNode( this );
|
||||
return;
|
||||
}
|
||||
|
||||
#if 1
|
||||
const bool coloredGeometry = hasHint( PreferColoredGeometry )
|
||||
&& QskArcRenderer::isGradientSupported( rect, metrics, gradient );
|
||||
Q_ASSERT( coloredGeometry ); // TODO ...
|
||||
#endif
|
||||
|
||||
auto& geometry = *this->geometry();
|
||||
|
||||
setColoring( QskFillNode::Polychrome );
|
||||
|
||||
QskArcRenderer::setColoredBorderAndFillLines( rect, metrics, radial,
|
||||
borderWidth, borderColor, gradient, geometry );
|
||||
borderWidth, borderColor, gradient, *geometry() );
|
||||
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
}
|
||||
else if ( hasBorder )
|
||||
{
|
||||
updateBorder( rect, arcMetrics, radial, borderWidth, borderColor );
|
||||
}
|
||||
else if ( hasFill )
|
||||
{
|
||||
updateFilling( rect, arcMetrics, radial, borderWidth, gradient );
|
||||
}
|
||||
else
|
||||
{
|
||||
d->resetNode( this );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,8 @@ void QskBoxNode::updateNode( const QRectF& rect,
|
|||
QskBoxRectangleNode* rectNode = nullptr;
|
||||
QskBoxRectangleNode* fillNode = nullptr;
|
||||
|
||||
if ( !rect.isEmpty() )
|
||||
{
|
||||
if ( !shadowMetrics.isNull()
|
||||
&& shadowColor.isValid() && shadowColor.alpha() != 0 )
|
||||
{
|
||||
|
@ -94,6 +96,7 @@ void QskBoxNode::updateNode( const QRectF& rect,
|
|||
fillNode->updateFilling( rect, shape, borderMetrics, gradient );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qskUpdateChildren( this, ShadowRole, shadowNode );
|
||||
qskUpdateChildren( this, BoxRole, rectNode );
|
||||
|
|
|
@ -12,6 +12,12 @@
|
|||
#include "QskGradientDirection.h"
|
||||
#include "QskFillNodePrivate.h"
|
||||
|
||||
static inline bool qskHasBorder(
|
||||
const QskBoxBorderMetrics& metrics, const QskBoxBorderColors& colors )
|
||||
{
|
||||
return !metrics.isNull() && colors.isVisible();
|
||||
}
|
||||
|
||||
class QskBoxRectangleNodePrivate final : public QskFillNodePrivate
|
||||
{
|
||||
public:
|
||||
|
@ -30,7 +36,7 @@ class QskBoxRectangleNodePrivate final : public QskFillNodePrivate
|
|||
hash = shape.hash( hash );
|
||||
hash = borderMetrics.hash( hash );
|
||||
|
||||
return updateValue( m_metricsHash, hash );
|
||||
return updateHash( m_metricsHash, hash );
|
||||
}
|
||||
|
||||
inline bool updateColors(
|
||||
|
@ -44,11 +50,11 @@ class QskBoxRectangleNodePrivate final : public QskFillNodePrivate
|
|||
if ( gradient.isVisible() )
|
||||
hash = gradient.hash( hash );
|
||||
|
||||
return updateValue( m_colorsHash, hash );
|
||||
return updateHash( m_colorsHash, hash );
|
||||
}
|
||||
|
||||
private:
|
||||
inline bool updateValue( QskHashValue& value, const QskHashValue newValue ) const
|
||||
inline bool updateHash( QskHashValue& value, const QskHashValue newValue ) const
|
||||
{
|
||||
if ( newValue != value )
|
||||
{
|
||||
|
@ -105,7 +111,7 @@ void QskBoxRectangleNode::updateFilling( const QRectF& rect,
|
|||
|
||||
const bool dirtyMetrics = d->updateMetrics( rect, shape, borderMetrics );
|
||||
const bool dirtyColors = d->updateColors( QskBoxBorderColors(), fillGradient )
|
||||
&& ( coloredGeometry == isGeometryColored() );
|
||||
|| ( coloredGeometry != isGeometryColored() );
|
||||
|
||||
if ( dirtyMetrics || dirtyColors )
|
||||
{
|
||||
|
@ -148,29 +154,43 @@ void QskBoxRectangleNode::updateBorder( const QRectF& rect,
|
|||
{
|
||||
Q_D( QskBoxRectangleNode );
|
||||
|
||||
if ( rect.isEmpty() || borderMetrics.isNull() || !borderColors.isVisible() )
|
||||
if ( rect.isEmpty() || !qskHasBorder( borderMetrics, borderColors ) )
|
||||
{
|
||||
d->resetNode( this );
|
||||
return;
|
||||
}
|
||||
|
||||
const bool coloredGeometry = hasHint( PreferColoredGeometry )
|
||||
|| !borderColors.isMonochrome();
|
||||
|
||||
const bool dirtyMetrics = d->updateMetrics( rect, shape, borderMetrics );
|
||||
const bool dirtyColors = d->updateColors( borderColors, QskGradient() );
|
||||
const bool dirtyColors = d->updateColors( borderColors, QskGradient() )
|
||||
|| ( coloredGeometry != isGeometryColored() );
|
||||
|
||||
if ( dirtyMetrics || dirtyColors )
|
||||
{
|
||||
const auto coloring = QskFillNode::Polychrome;
|
||||
if ( coloredGeometry )
|
||||
{
|
||||
setColoring( QskFillNode::Polychrome );
|
||||
|
||||
if ( coloring == QskFillNode::Polychrome )
|
||||
setColoring( coloring );
|
||||
else
|
||||
setColoring( borderColors.left().rgbStart() );
|
||||
|
||||
QskBoxRenderer::setColoredBorderLines( rect, shape, borderMetrics,
|
||||
borderColors, *this->geometry() );
|
||||
QskBoxRenderer::setColoredBorderLines( rect, shape,
|
||||
borderMetrics, borderColors, *geometry() );
|
||||
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
else
|
||||
{
|
||||
setColoring( borderColors.left().rgbStart() );
|
||||
|
||||
if ( dirtyMetrics )
|
||||
{
|
||||
QskBoxRenderer::setBorderLines( rect, shape,
|
||||
borderMetrics, *geometry() );
|
||||
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QskBoxRectangleNode::updateBox( const QRectF& rect,
|
||||
|
@ -186,7 +206,7 @@ void QskBoxRectangleNode::updateBox( const QRectF& rect,
|
|||
}
|
||||
|
||||
const bool hasFill = gradient.isVisible();
|
||||
const bool hasBorder = !borderMetrics.isNull() && borderColors.isVisible();
|
||||
const bool hasBorder = qskHasBorder( borderMetrics, borderColors );
|
||||
|
||||
if ( hasFill && hasBorder )
|
||||
{
|
||||
|
|
|
@ -36,15 +36,15 @@ class QSK_EXPORT QskFillNode : public QSGGeometryNode
|
|||
Colors might be defined in the material ( QskGradientMaterial,
|
||||
QSGFlatColorMaterial ) or attached to each point ( QSGVertexColorMaterial ).
|
||||
|
||||
The main advantage of using colored points is, that the material becomes
|
||||
independent of the coloring and the scene graph is able to batch the nodes
|
||||
Having colored points makes the material independent of the coloring
|
||||
and the scene graph is able to batch the geometries
|
||||
( https://doc.qt.io/qt-6/qtquick-visualcanvas-scenegraph.html ).
|
||||
|
||||
However adding the color information for each point increases the memory
|
||||
footprint.
|
||||
Having the colors in the material needs less memory and avoids updates
|
||||
of the geometry only because of recoloring.
|
||||
|
||||
The default setting is to use colored points where possible. Note, that
|
||||
this is what is also done in the Qt/Quick code.
|
||||
this is what is also done in the Qt/Quick classes.
|
||||
*/
|
||||
PreferColoredGeometry = 1
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue