QskStrokeNode with colored matarial for better batching. option for
simple polygons added without line joining added
This commit is contained in:
parent
585f763542
commit
ffe4e11b21
@ -4,24 +4,77 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskStrokeNode.h"
|
#include "QskStrokeNode.h"
|
||||||
|
#include "QskVertex.h"
|
||||||
|
|
||||||
#include <qsgflatcolormaterial.h>
|
#include <qsgflatcolormaterial.h>
|
||||||
|
#include <qsgvertexcolormaterial.h>
|
||||||
|
#include <qpainterpath.h>
|
||||||
|
#include <qpolygon.h>
|
||||||
|
|
||||||
QSK_QT_PRIVATE_BEGIN
|
QSK_QT_PRIVATE_BEGIN
|
||||||
#include <private/qsgnode_p.h>
|
#include <private/qsgnode_p.h>
|
||||||
#include <private/qtriangulatingstroker_p.h>
|
#include <private/qtriangulatingstroker_p.h>
|
||||||
QSK_QT_PRIVATE_END
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
|
Q_GLOBAL_STATIC( QSGVertexColorMaterial, qskMaterialColorVertex )
|
||||||
|
|
||||||
|
static inline void qskMapPolygon( const QPolygonF& polygon,
|
||||||
|
const QTransform& transform, const QColor& color, QSGGeometry& geometry )
|
||||||
|
{
|
||||||
|
const QskVertex::Color c( color );
|
||||||
|
|
||||||
|
auto p = geometry.vertexDataAsColoredPoint2D();
|
||||||
|
|
||||||
|
if ( transform.isIdentity() )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < polygon.count(); i++ )
|
||||||
|
{
|
||||||
|
const auto& pos = polygon[i];
|
||||||
|
p[i].set( pos.x(), pos.y(), c.r, c.g, c.b, c.a );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < polygon.count(); i++ )
|
||||||
|
{
|
||||||
|
const auto pos = transform.map( polygon[i] );
|
||||||
|
p[i].set( pos.x(), pos.y(), c.r, c.g, c.b, c.a );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void qskMapPolygon( const QPolygonF& polygon,
|
||||||
|
const QTransform& transform, QSGGeometry& geometry )
|
||||||
|
{
|
||||||
|
auto p = geometry.vertexDataAsPoint2D();
|
||||||
|
|
||||||
|
if ( transform.isIdentity() )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < polygon.count(); i++ )
|
||||||
|
{
|
||||||
|
const auto& pos = polygon[i];
|
||||||
|
p[i].set( pos.x(), pos.y() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < polygon.count(); i++ )
|
||||||
|
{
|
||||||
|
const auto pos = transform.map( polygon[i] );
|
||||||
|
p[i].set( pos.x(), pos.y() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class QskStrokeNodePrivate final : public QSGGeometryNodePrivate
|
class QskStrokeNodePrivate final : public QSGGeometryNodePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QskStrokeNodePrivate()
|
QskStrokeNodePrivate()
|
||||||
: geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
|
: geometry( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 )
|
||||||
{
|
{
|
||||||
geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGGeometry geometry;
|
QSGGeometry geometry;
|
||||||
QSGFlatColorMaterial material;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QskStrokeNode::QskStrokeNode()
|
QskStrokeNode::QskStrokeNode()
|
||||||
@ -30,7 +83,41 @@ QskStrokeNode::QskStrokeNode()
|
|||||||
Q_D( QskStrokeNode );
|
Q_D( QskStrokeNode );
|
||||||
|
|
||||||
setGeometry( &d->geometry );
|
setGeometry( &d->geometry );
|
||||||
setMaterial( &d->material );
|
setMaterial( qskMaterialColorVertex );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskStrokeNode::setRenderHint( RenderHint renderHint )
|
||||||
|
{
|
||||||
|
Q_D( QskStrokeNode );
|
||||||
|
|
||||||
|
const auto material = this->material();
|
||||||
|
|
||||||
|
if ( renderHint == Colored )
|
||||||
|
{
|
||||||
|
if ( material != qskMaterialColorVertex )
|
||||||
|
{
|
||||||
|
setMaterial( qskMaterialColorVertex );
|
||||||
|
delete material;
|
||||||
|
|
||||||
|
const QSGGeometry g( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 );
|
||||||
|
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( material == qskMaterialColorVertex )
|
||||||
|
{
|
||||||
|
setMaterial( new QSGFlatColorMaterial() );
|
||||||
|
|
||||||
|
const QSGGeometry g( QSGGeometry::defaultAttributes_Point2D(), 0 );
|
||||||
|
memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QskStrokeNode::RenderHint QskStrokeNode::renderHint() const
|
||||||
|
{
|
||||||
|
return ( material() == qskMaterialColorVertex ) ? Colored : Flat;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskStrokeNode::updateNode(
|
void QskStrokeNode::updateNode(
|
||||||
@ -91,19 +178,92 @@ void QskStrokeNode::updateNode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2 vertices for each point
|
// 2 vertices for each point
|
||||||
|
d->geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
||||||
d->geometry.allocate( stroker.vertexCount() / 2 );
|
d->geometry.allocate( stroker.vertexCount() / 2 );
|
||||||
|
|
||||||
|
if ( material() == qskMaterialColorVertex )
|
||||||
|
{
|
||||||
|
const QskVertex::Color c( pen.color() );
|
||||||
|
|
||||||
|
const auto v = stroker.vertices();
|
||||||
|
auto points = d->geometry.vertexDataAsColoredPoint2D();
|
||||||
|
|
||||||
|
for ( int i = 0; i < d->geometry.vertexCount(); i++ )
|
||||||
|
{
|
||||||
|
const auto j = 2 * i;
|
||||||
|
points[i].set( v[j], v[j + 1], c.r, c.g, c.b, c.a );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
memcpy( d->geometry.vertexData(), stroker.vertices(),
|
memcpy( d->geometry.vertexData(), stroker.vertices(),
|
||||||
stroker.vertexCount() * sizeof( float ) );
|
stroker.vertexCount() * sizeof( float ) );
|
||||||
|
}
|
||||||
|
|
||||||
markDirty( QSGNode::DirtyGeometry );
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( material() != qskMaterialColorVertex )
|
||||||
|
{
|
||||||
const auto color = pen.color().toRgb();
|
const auto color = pen.color().toRgb();
|
||||||
|
|
||||||
if ( d->material.color() != color )
|
auto flatMaterial = static_cast< QSGFlatColorMaterial* >( material() );
|
||||||
|
if ( flatMaterial->color() != color )
|
||||||
{
|
{
|
||||||
d->material.setColor( color );
|
flatMaterial->setColor( color );
|
||||||
markDirty( QSGNode::DirtyMaterial );
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
For polygons with a small lineWidth ( < 2 ) or a line without
|
||||||
|
connections we might get away with a simple and fast implementation
|
||||||
|
using DrawLineStrip/DrawLineLoop
|
||||||
|
*/
|
||||||
|
void QskStrokeNode::updateNode( const QPolygonF& polygon,
|
||||||
|
const QTransform& transform, qreal lineWidth, const QColor& color )
|
||||||
|
{
|
||||||
|
Q_D( QskStrokeNode );
|
||||||
|
|
||||||
|
if ( polygon.isEmpty() || !color.isValid() || ( color.alpha() == 0 ) )
|
||||||
|
{
|
||||||
|
if ( d->geometry.vertexCount() > 0 )
|
||||||
|
{
|
||||||
|
d->geometry.allocate( 0 );
|
||||||
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->geometry.setDrawingMode( QSGGeometry::DrawLineStrip );
|
||||||
|
|
||||||
|
const float lineWidthF = lineWidth;
|
||||||
|
|
||||||
|
if( lineWidthF != d->geometry.lineWidth() )
|
||||||
|
d->geometry.setLineWidth( lineWidthF );
|
||||||
|
|
||||||
|
if ( true ) // TODO
|
||||||
|
{
|
||||||
|
d->geometry.allocate( polygon.count() );
|
||||||
|
|
||||||
|
if ( material() == qskMaterialColorVertex )
|
||||||
|
{
|
||||||
|
qskMapPolygon( polygon, transform, color, d->geometry );
|
||||||
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qskMapPolygon( polygon, transform, d->geometry );
|
||||||
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
|
||||||
|
auto flatMaterial = static_cast< QSGFlatColorMaterial* >( material() );
|
||||||
|
if ( flatMaterial->color() != color )
|
||||||
|
{
|
||||||
|
flatMaterial->setColor( color );
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
class QPen;
|
class QPen;
|
||||||
class QPainterPath;
|
class QPainterPath;
|
||||||
|
class QPolygonF;
|
||||||
|
|
||||||
class QskStrokeNodePrivate;
|
class QskStrokeNodePrivate;
|
||||||
|
|
||||||
@ -19,8 +20,26 @@ class QSK_EXPORT QskStrokeNode : public QSGGeometryNode
|
|||||||
public:
|
public:
|
||||||
QskStrokeNode();
|
QskStrokeNode();
|
||||||
|
|
||||||
|
/*
|
||||||
|
We only support monochrome pens ( QPen::color() ) and using a
|
||||||
|
QSGFlatColorMaterial is good enough. However QSGVertexColorMaterial
|
||||||
|
usually allows better batching. So Flat vs. Colored is a tradeoff
|
||||||
|
between memory and performance.
|
||||||
|
*/
|
||||||
|
enum RenderHint
|
||||||
|
{
|
||||||
|
Flat,
|
||||||
|
Colored
|
||||||
|
};
|
||||||
|
|
||||||
|
void setRenderHint( RenderHint );
|
||||||
|
RenderHint renderHint() const;
|
||||||
|
|
||||||
void updateNode( const QPainterPath&, const QTransform&, const QPen& );
|
void updateNode( const QPainterPath&, const QTransform&, const QPen& );
|
||||||
|
|
||||||
|
void updateNode( const QPolygonF&, const QTransform&,
|
||||||
|
qreal lineWidth, const QColor& );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DECLARE_PRIVATE( QskStrokeNode )
|
Q_DECLARE_PRIVATE( QskStrokeNode )
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user