diff --git a/src/nodes/QskBasicLinesNode.cpp b/src/nodes/QskBasicLinesNode.cpp index a9f85d4d..93414295 100644 --- a/src/nodes/QskBasicLinesNode.cpp +++ b/src/nodes/QskBasicLinesNode.cpp @@ -13,6 +13,21 @@ QSK_QT_PRIVATE_BEGIN #include 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 ) #include using RhiShader = QSGMaterialRhiShader; @@ -37,7 +52,7 @@ namespace 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; }; @@ -72,27 +87,28 @@ namespace 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 ... - memcpy( data + 64, &matNew->m_color, 16 ); + const auto v4 = qskColorVector( matNew->m_color, state.opacity() ); + memcpy( data + 64, &v4, 16 ); changed = true; } if ( state.isMatrixDirty() || ( matOld == nullptr ) || ( 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 ) - size.setX( r.width() ); - - if ( matNew->m_pixelAlignment & Qt::Vertical ) - size.setY( r.height() ); - - memcpy( data + 80, &size, 8 ); + memcpy( data + 80, &origin, 8 ); changed = true; } @@ -135,7 +151,7 @@ namespace m_matrixId = p->uniformLocation( "matrix" ); m_colorId = p->uniformLocation( "color" ); - m_sizeId = p->uniformLocation( "size" ); + m_originId = p->uniformLocation( "origin" ); } void updateState( const QSGMaterialShader::RenderState& state, @@ -157,26 +173,19 @@ namespace { 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(); - - QVector2D size; - - 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 ); + const auto origin = qskOrigin( + state.viewportRect(), material->m_pixelAlignment );; + p->setUniformValue( m_originId, origin ); } } private: int m_matrixId = -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 ); - const auto a = color.alphaF(); - - const QVector4D c( color.redF() * a, color.greenF() * a, color.blueF() * a, a ); - + const auto c = color.toRgb(); if ( c != d->material.m_color ) { 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 ) { Q_D( QskBasicLinesNode ); diff --git a/src/nodes/QskBasicLinesNode.h b/src/nodes/QskBasicLinesNode.h index 607c9cc5..cbbe02a2 100644 --- a/src/nodes/QskBasicLinesNode.h +++ b/src/nodes/QskBasicLinesNode.h @@ -31,6 +31,7 @@ class QSK_EXPORT QskBasicLinesNode : public QSGGeometryNode Qt::Orientations pixelAlignment() const; void setColor( const QColor& ); + QColor color() const; void setLineWidth( float ); float lineWidth() const; diff --git a/src/nodes/shaders/crisplines-vulkan.frag b/src/nodes/shaders/crisplines-vulkan.frag index a4618fe9..6c6cf664 100644 --- a/src/nodes/shaders/crisplines-vulkan.frag +++ b/src/nodes/shaders/crisplines-vulkan.frag @@ -6,7 +6,7 @@ layout( std140, binding = 0 ) uniform buf { mat4 matrix; vec4 color; - vec2 size; + vec2 origin; } ubuf; void main() diff --git a/src/nodes/shaders/crisplines-vulkan.vert b/src/nodes/shaders/crisplines-vulkan.vert index e572cda7..b4e140c4 100644 --- a/src/nodes/shaders/crisplines-vulkan.vert +++ b/src/nodes/shaders/crisplines-vulkan.vert @@ -6,36 +6,28 @@ layout( std140, binding = 0 ) uniform buf { mat4 matrix; vec4 color; - vec2 size; + vec2 origin; } ubuf; 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() { - 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 ); - gl_Position.x = round( gl_Position.x ) + 0.5; - gl_Position.x = normalized( gl_Position.x, gl_Position.w, ubuf.size.x ); + pos.x = ( pos.x + 1.0 ) * ubuf.origin.x; + pos.x = round( pos.x ) + 0.5; + 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 ); - gl_Position.y = round( gl_Position.y ) + 0.5; - gl_Position.y = normalized( gl_Position.y, gl_Position.w, ubuf.size.y ); + pos.y = ( pos.y + 1.0 ) * ubuf.origin.y; + pos.y = round( pos.y ) + 0.5; + pos.y = pos.y / ubuf.origin.y - 1.0; } + + gl_Position = pos; } diff --git a/src/nodes/shaders/crisplines.frag.qsb b/src/nodes/shaders/crisplines.frag.qsb index 9a0addc5..fb01e7de 100644 Binary files a/src/nodes/shaders/crisplines.frag.qsb and b/src/nodes/shaders/crisplines.frag.qsb differ diff --git a/src/nodes/shaders/crisplines.vert b/src/nodes/shaders/crisplines.vert index 41d01bac..2a1e26af 100644 --- a/src/nodes/shaders/crisplines.vert +++ b/src/nodes/shaders/crisplines.vert @@ -1,17 +1,7 @@ attribute highp vec4 in_vertex; uniform highp mat4 matrix; -uniform lowp vec2 size; - -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; -} +uniform lowp vec2 origin; float round( in float v ) { @@ -20,19 +10,21 @@ float round( in float v ) 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 ); - gl_Position.x = round( gl_Position.x ) + 0.5; - gl_Position.x = normalized( gl_Position.x, gl_Position.w, size.x ); + pos.x = ( pos.x + 1.0 ) * origin.x; + pos.x = round( pos.x ) + 0.5; + 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 ); - gl_Position.y = round( gl_Position.y ) + 0.5; - gl_Position.y = normalized( gl_Position.y, gl_Position.w, size.y ); + pos.y = ( pos.y + 1.0 ) * origin.y; + pos.y = round( pos.y ) + 0.5; + pos.y = pos.y / origin.y - 1.0; } + + gl_Position = pos; } diff --git a/src/nodes/shaders/crisplines.vert.qsb b/src/nodes/shaders/crisplines.vert.qsb index 27f5213f..c25564dc 100644 Binary files a/src/nodes/shaders/crisplines.vert.qsb and b/src/nodes/shaders/crisplines.vert.qsb differ