QskBasicLinesNode completed

This commit is contained in:
Uwe Rathmann 2023-11-24 13:07:53 +01:00
parent f3a1de5b00
commit 534ffb41e1
7 changed files with 68 additions and 72 deletions

View File

@ -13,6 +13,21 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qsgnode_p.h> #include <private/qsgnode_p.h>
QSK_QT_PRIVATE_END QSK_QT_PRIVATE_END
static inline QVector4D qskColorVector( const QColor& c, qreal opacity)
{
const auto a = c.alphaF() * opacity;
return QVector4D( c.redF() * a, c.greenF() * a, c.blueF() * a, a );
}
static inline QVector2D qskOrigin(
const QRect& rect, Qt::Orientations orientations )
{
return QVector2D(
( orientations & Qt::Horizontal ) ? 0.5 * rect.width() : 0.0,
( orientations & Qt::Vertical ) ? 0.5 * rect.height() : 0.0
);
}
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) #if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
#include <QSGMaterialRhiShader> #include <QSGMaterialRhiShader>
using RhiShader = QSGMaterialRhiShader; using RhiShader = QSGMaterialRhiShader;
@ -37,7 +52,7 @@ namespace
int compare( const QSGMaterial* other ) const override; int compare( const QSGMaterial* other ) const override;
QVector4D m_color = QVector4D{ 0, 0, 0, 1 }; QColor m_color = QColor( 255, 255, 255 );
Qt::Orientations m_pixelAlignment; Qt::Orientations m_pixelAlignment;
}; };
@ -72,27 +87,28 @@ namespace
changed = true; changed = true;
} }
if ( ( matOld == nullptr ) || ( matNew->m_color != matOld->m_color ) ) if ( ( matOld == nullptr ) || ( matNew->m_color != matOld->m_color )
|| state.isOpacityDirty() )
{ {
// state.opacity() TODO ... const auto v4 = qskColorVector( matNew->m_color, state.opacity() );
memcpy( data + 64, &matNew->m_color, 16 ); memcpy( data + 64, &v4, 16 );
changed = true; changed = true;
} }
if ( state.isMatrixDirty() || ( matOld == nullptr ) if ( state.isMatrixDirty() || ( matOld == nullptr )
|| ( matNew->m_pixelAlignment != matOld->m_pixelAlignment ) ) || ( matNew->m_pixelAlignment != matOld->m_pixelAlignment ) )
{ {
const auto r = state.viewportRect(); /*
The shaders work with coordinates in the range[-1,1]. When knowing
the device coordinates corresponding to [0.0] we can scale a vertex
into device coordinates.
QVector2D size; coordinates <= 0.0 indicate, that no rounding should be done.
*/
const auto origin = qskOrigin(
state.viewportRect(), matNew->m_pixelAlignment );
if ( matNew->m_pixelAlignment & Qt::Horizontal ) memcpy( data + 80, &origin, 8 );
size.setX( r.width() );
if ( matNew->m_pixelAlignment & Qt::Vertical )
size.setY( r.height() );
memcpy( data + 80, &size, 8 );
changed = true; changed = true;
} }
@ -135,7 +151,7 @@ namespace
m_matrixId = p->uniformLocation( "matrix" ); m_matrixId = p->uniformLocation( "matrix" );
m_colorId = p->uniformLocation( "color" ); m_colorId = p->uniformLocation( "color" );
m_sizeId = p->uniformLocation( "size" ); m_originId = p->uniformLocation( "origin" );
} }
void updateState( const QSGMaterialShader::RenderState& state, void updateState( const QSGMaterialShader::RenderState& state,
@ -157,26 +173,19 @@ namespace
{ {
auto material = static_cast< const Material* >( newMaterial ); auto material = static_cast< const Material* >( newMaterial );
p->setUniformValue( m_colorId, material->m_color ); p->setUniformValue( m_colorId,
qskColorVector( material->m_color, state.opacity() ) );
const auto r = state.viewportRect(); const auto origin = qskOrigin(
state.viewportRect(), material->m_pixelAlignment );;
QVector2D size; p->setUniformValue( m_originId, origin );
if ( material->m_pixelAlignment & Qt::Horizontal )
size.setX( r.width() );
if ( material->m_pixelAlignment & Qt::Vertical )
size.setY( r.height() );
p->setUniformValue( m_sizeId, size );
} }
} }
private: private:
int m_matrixId = -1; int m_matrixId = -1;
int m_colorId = -1; int m_colorId = -1;
int m_sizeId = -1; int m_originId = -1;
}; };
} }
@ -273,10 +282,7 @@ void QskBasicLinesNode::setColor( const QColor& color )
{ {
Q_D( QskBasicLinesNode ); Q_D( QskBasicLinesNode );
const auto a = color.alphaF(); const auto c = color.toRgb();
const QVector4D c( color.redF() * a, color.greenF() * a, color.blueF() * a, a );
if ( c != d->material.m_color ) if ( c != d->material.m_color )
{ {
d->material.m_color = c; d->material.m_color = c;
@ -284,6 +290,11 @@ void QskBasicLinesNode::setColor( const QColor& color )
} }
} }
QColor QskBasicLinesNode::color() const
{
return d_func()->material.m_color;
}
void QskBasicLinesNode::setLineWidth( float lineWidth ) void QskBasicLinesNode::setLineWidth( float lineWidth )
{ {
Q_D( QskBasicLinesNode ); Q_D( QskBasicLinesNode );

View File

@ -31,6 +31,7 @@ class QSK_EXPORT QskBasicLinesNode : public QSGGeometryNode
Qt::Orientations pixelAlignment() const; Qt::Orientations pixelAlignment() const;
void setColor( const QColor& ); void setColor( const QColor& );
QColor color() const;
void setLineWidth( float ); void setLineWidth( float );
float lineWidth() const; float lineWidth() const;

View File

@ -6,7 +6,7 @@ layout( std140, binding = 0 ) uniform buf
{ {
mat4 matrix; mat4 matrix;
vec4 color; vec4 color;
vec2 size; vec2 origin;
} ubuf; } ubuf;
void main() void main()

View File

@ -6,36 +6,28 @@ layout( std140, binding = 0 ) uniform buf
{ {
mat4 matrix; mat4 matrix;
vec4 color; vec4 color;
vec2 size; vec2 origin;
} ubuf; } ubuf;
out gl_PerVertex { vec4 gl_Position; }; out gl_PerVertex { vec4 gl_Position; };
float normalized( in float pos, in float scale, in float size )
{
return ( ( pos / size - 0.5 ) / 0.5 ) * scale;
}
float denormalized( in float pos, in float scale, in float size )
{
return ( ( pos / scale ) * 0.5 + 0.5 ) * size;
}
void main() void main()
{ {
gl_Position = ubuf.matrix * vertexCoord; vec4 pos = ubuf.matrix * vertexCoord;
if ( ubuf.size.x > 0.0 ) if ( ubuf.origin.x > 0.0 )
{ {
gl_Position.x = denormalized( gl_Position.x, gl_Position.w, ubuf.size.x ); pos.x = ( pos.x + 1.0 ) * ubuf.origin.x;
gl_Position.x = round( gl_Position.x ) + 0.5; pos.x = round( pos.x ) + 0.5;
gl_Position.x = normalized( gl_Position.x, gl_Position.w, ubuf.size.x ); pos.x = pos.x / ubuf.origin.x - 1.0;
} }
if ( ubuf.size.y > 0.0 ) if ( ubuf.origin.y > 0.0 )
{ {
gl_Position.y = denormalized( gl_Position.y, gl_Position.w, ubuf.size.y ); pos.y = ( pos.y + 1.0 ) * ubuf.origin.y;
gl_Position.y = round( gl_Position.y ) + 0.5; pos.y = round( pos.y ) + 0.5;
gl_Position.y = normalized( gl_Position.y, gl_Position.w, ubuf.size.y ); pos.y = pos.y / ubuf.origin.y - 1.0;
} }
gl_Position = pos;
} }

View File

@ -1,17 +1,7 @@
attribute highp vec4 in_vertex; attribute highp vec4 in_vertex;
uniform highp mat4 matrix; uniform highp mat4 matrix;
uniform lowp vec2 size; uniform lowp vec2 origin;
float normalized( in float pos, in float scale, in float size )
{
return ( ( pos / size - 0.5 ) / 0.5 ) * scale;
}
float denormalized( in float pos, in float scale, in float size )
{
return ( ( pos / scale ) * 0.5 + 0.5 ) * size;
}
float round( in float v ) float round( in float v )
{ {
@ -20,19 +10,21 @@ float round( in float v )
void main() void main()
{ {
gl_Position = matrix * in_vertex; vec4 pos = matrix * in_vertex;
if ( size.x > 0.0 ) if ( origin.x > 0.0 )
{ {
gl_Position.x = denormalized( gl_Position.x, gl_Position.w, size.x ); pos.x = ( pos.x + 1.0 ) * origin.x;
gl_Position.x = round( gl_Position.x ) + 0.5; pos.x = round( pos.x ) + 0.5;
gl_Position.x = normalized( gl_Position.x, gl_Position.w, size.x ); pos.x = pos.x / origin.x - 1.0;
} }
if ( size.y > 0.0 ) if ( origin.y > 0.0 )
{ {
gl_Position.y = denormalized( gl_Position.y, gl_Position.w, size.y ); pos.y = ( pos.y + 1.0 ) * origin.y;
gl_Position.y = round( gl_Position.y ) + 0.5; pos.y = round( pos.y ) + 0.5;
gl_Position.y = normalized( gl_Position.y, gl_Position.w, size.y ); pos.y = pos.y / origin.y - 1.0;
} }
gl_Position = pos;
} }