diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b626e406..a6ff444a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -97,6 +97,7 @@ list(APPEND SOURCES list(APPEND HEADERS nodes/QskArcNode.h + nodes/QskBasicLinesNode.h nodes/QskBoxNode.h nodes/QskBoxClipNode.h nodes/QskBoxFillNode.h @@ -133,6 +134,7 @@ list(APPEND PRIVATE_HEADERS list(APPEND SOURCES nodes/QskArcNode.cpp + nodes/QskBasicLinesNode.cpp nodes/QskBoxNode.cpp nodes/QskBoxClipNode.cpp nodes/QskBoxFillNode.cpp diff --git a/src/nodes/QskBasicLinesNode.cpp b/src/nodes/QskBasicLinesNode.cpp new file mode 100644 index 00000000..202b82c3 --- /dev/null +++ b/src/nodes/QskBasicLinesNode.cpp @@ -0,0 +1,301 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "QskBasicLinesNode.h" + +#include +#include +#include + +QSK_QT_PRIVATE_BEGIN +#include +QSK_QT_PRIVATE_END + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + #include + 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 = QVector4D{ 0, 0, 0, 1 }; + Qt::Orientations m_pixelAlignment; + }; + + class ShaderRhi final : public RhiShader + { + public: + + ShaderRhi() + { + const QString root( ":/qskinny/shaders/" ); + + setShaderFileName( VertexStage, root + "crisplines.vert.qsb" ); + setShaderFileName( FragmentStage, root + "crisplines.frag.qsb" ); + } + + bool updateUniformData( RenderState& state, + QSGMaterial* newMaterial, QSGMaterial* oldMaterial ) override + { + auto matOld = static_cast< Material* >( oldMaterial ); + auto matNew = static_cast< Material* >( newMaterial ); + + Q_ASSERT( state.uniformData()->size() >= 88 ); + + auto data = state.uniformData()->data(); + bool changed = false; + + const auto matrix = state.combinedMatrix(); + + if ( state.isMatrixDirty() ) + { + memcpy( data + 0, matrix.constData(), 64 ); + changed = true; + } + + if ( ( matOld == nullptr ) || ( matNew->m_color != matOld->m_color ) ) + { + // state.opacity() TODO ... + memcpy( data + 64, &matNew->m_color, 16 ); + changed = true; + } + + if ( state.isMatrixDirty() || ( matOld == nullptr ) + || ( matNew->m_pixelAlignment != matOld->m_pixelAlignment ) ) + { + /* + We do not need to upload the size as it is available + from the matrix. But the shader needs to know wether to + round or not TODO ... + */ + QVector2D size; + + if ( matNew->m_pixelAlignment & Qt::Horizontal ) + size.setX( 2.0 / matrix( 0, 0 ) ); + + if ( matNew->m_pixelAlignment & Qt::Vertical ) + size.setY( -2.0 / matrix( 1, 1 ) ); + + memcpy( data + 80, &size, 8 ); + changed = true; + } + + return changed; + } + }; +} + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + +namespace +{ + // the old type of shader - spcific for OpenGL + + class ShaderGL final : public QSGMaterialShader + { + public: + ShaderGL() + { + const QString root( ":/qskinny/shaders/" ); + + setShaderSourceFile( QOpenGLShader::Vertex, + ":/qskinny/shaders/crisplines.vert" ); + + setShaderSourceFile( QOpenGLShader::Fragment, + ":/qt-project.org/scenegraph/shaders/flatcolor.frag" ); + } + + char const* const* attributeNames() const override + { + static char const* const names[] = { "in_vertex", nullptr }; + return names; + } + + void initialize() override + { + QSGMaterialShader::initialize(); + + auto p = program(); + + m_matrixId = p->uniformLocation( "matrix" ); + m_colorId = p->uniformLocation( "color" ); + m_sizeId = p->uniformLocation( "size" ); + } + + void updateState( const QSGMaterialShader::RenderState& state, + QSGMaterial* newMaterial, QSGMaterial* oldMaterial) override + { + auto p = program(); + + const auto matrix = state.combinedMatrix(); + + if ( state.isMatrixDirty() ) + p->setUniformValue( m_matrixId, matrix ); + + bool updateMaterial = ( oldMaterial == nullptr ) + || newMaterial->compare( oldMaterial ) != 0; + + updateMaterial |= state.isCachedMaterialDataDirty(); + + if ( updateMaterial ) + { + auto material = static_cast< const Material* >( newMaterial ); + + p->setUniformValue( m_colorId, material->m_color ); + + QVector2D size; + + if ( material->m_pixelAlignment & Qt::Horizontal ) + size.setX( 2.0 / matrix( 0, 0 ) ); + + if ( material->m_pixelAlignment & Qt::Vertical ) + size.setY( -2.0 / matrix( 1, 1 ) ); + + p->setUniformValue( m_sizeId, size ); + } + } + + private: + int m_matrixId = -1; + int m_colorId = -1; + int m_sizeId = -1; + }; +} + +#endif + +Material::Material() +{ +#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* other ) const +{ + auto material = static_cast< const Material* >( other ); + + if ( ( material->m_color == m_color ) + && ( material->m_pixelAlignment == m_pixelAlignment ) ) + { + return 0; + } + + return QSGMaterial::compare( other ); +} + +class QskBasicLinesNodePrivate final : public QSGGeometryNodePrivate +{ + public: + QskBasicLinesNodePrivate() + : geometry( QSGGeometry::defaultAttributes_Point2D(), 0 ) + { + geometry.setDrawingMode( QSGGeometry::DrawLines ); + } + + QSGGeometry geometry; + Material material; +}; + +QskBasicLinesNode::QskBasicLinesNode() + : QSGGeometryNode( *new QskBasicLinesNodePrivate ) +{ + Q_D( QskBasicLinesNode ); + + setGeometry( &d->geometry ); + setMaterial( &d->material ); +} + +QskBasicLinesNode::~QskBasicLinesNode() +{ +} + +void QskBasicLinesNode::setPixelAlignment( Qt::Orientations orientations ) +{ + Q_D( QskBasicLinesNode ); + + if ( orientations != d->material.m_pixelAlignment ) + { + d->material.m_pixelAlignment = orientations; + markDirty( QSGNode::DirtyMaterial ); + } +} + +Qt::Orientations QskBasicLinesNode::pixelAlignment() const +{ + return d_func()->material.m_pixelAlignment; +} + +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 ); + + if ( c != d->material.m_color ) + { + d->material.m_color = c; + markDirty( QSGNode::DirtyMaterial ); + } +} + +void QskBasicLinesNode::setLineWidth( float lineWidth ) +{ + Q_D( QskBasicLinesNode ); + + lineWidth = std::max( lineWidth, 0.0f ); + if( lineWidth != d->geometry.lineWidth() ) + d->geometry.setLineWidth( lineWidth ); +} + +float QskBasicLinesNode::lineWidth() const +{ + return d_func()->geometry.lineWidth(); +} + diff --git a/src/nodes/QskBasicLinesNode.h b/src/nodes/QskBasicLinesNode.h new file mode 100644 index 00000000..607c9cc5 --- /dev/null +++ b/src/nodes/QskBasicLinesNode.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_BASIC_LINES_NODE_H +#define QSK_BASIC_LINES_NODE_H + +#include "QskGlobal.h" + +#include +#include + +class QColor; + +class QskBasicLinesNodePrivate; + +/* + A node for stippled or solid lines. + For the moment limited to horizontal/vertical lines: TODO + */ +class QSK_EXPORT QskBasicLinesNode : public QSGGeometryNode +{ + using Inherited = QSGGeometryNode; + + public: + QskBasicLinesNode(); + ~QskBasicLinesNode() override; + + void setPixelAlignment( Qt::Orientations ); + Qt::Orientations pixelAlignment() const; + + void setColor( const QColor& ); + + void setLineWidth( float ); + float lineWidth() const; + + private: + Q_DECLARE_PRIVATE( QskBasicLinesNode ) +}; + +#endif diff --git a/src/nodes/QskLinesNode.cpp b/src/nodes/QskLinesNode.cpp index 7f1e50dd..1d89715e 100644 --- a/src/nodes/QskLinesNode.cpp +++ b/src/nodes/QskLinesNode.cpp @@ -9,17 +9,9 @@ #include "QskStippledLineRenderer.h" #include "QskSGNode.h" -#include -#include #include -#include -#include #include -QSK_QT_PRIVATE_BEGIN -#include -QSK_QT_PRIVATE_END - namespace { inline qreal mapX( const QTransform& t, qreal x ) @@ -114,115 +106,14 @@ static QSGGeometry::Point2D* qskAddLines( const QTransform& transform, return reinterpret_cast< QSGGeometry::Point2D* >( vlines ); } -class QskLinesNodePrivate final : public QSGGeometryNodePrivate -{ - public: - QskLinesNodePrivate() - : geometry( QSGGeometry::defaultAttributes_Point2D(), 0 ) - { - geometry.setDrawingMode( QSGGeometry::DrawLines ); - } - - inline qreal round( bool isHorizontal, qreal v ) const - { - if ( !doRound ) - return v; - - const auto r2 = 2.0 * devicePixelRatio; - const qreal v0 = isHorizontal ? p0.x() : p0.y(); - - const int d = qRound( r2 * ( v + v0 ) ); - const auto f = ( d % 2 ? d : d - 1 ) / r2; - - return f / devicePixelRatio - v0; - } - - inline void setLineAttributes( QskLinesNode* node, - const QColor& color, float lineWidth ) - { - if ( color != material.color() ) - { - material.setColor( color ); - node->markDirty( QSGNode::DirtyMaterial ); - } - - if( lineWidth != geometry.lineWidth() ) - geometry.setLineWidth( lineWidth ); - } - - QSGGeometry geometry; - QSGFlatColorMaterial material; - - // position of [0,0] in device coordinates - QPointF p0; - qreal devicePixelRatio = 1.0; - - QskHashValue hash = 0.0; - - bool dirty = true; - bool doRound = false; -}; - QskLinesNode::QskLinesNode() - : QSGGeometryNode( *new QskLinesNodePrivate ) { - Q_D( QskLinesNode ); - - setGeometry( &d->geometry ); - setMaterial( &d->material ); } QskLinesNode::~QskLinesNode() { } -void QskLinesNode::setGlobalPosition( const QQuickItem* item ) -{ - QPointF p0; - qreal devicePixelRatio = 1.0; - - if ( item ) - { - p0 = item->mapToGlobal( QPointF() ); - - if ( auto w = item->window() ) - devicePixelRatio = w->devicePixelRatio(); - } - - setGlobalPosition( p0, devicePixelRatio ); -} - -void QskLinesNode::setGlobalPosition( - const QPointF& pos, qreal devicePixelRatio ) -{ - Q_D( QskLinesNode ); - - if ( d->doRound == false ) - { - d->doRound = true; - d->dirty = true; - } - - if ( pos != d->p0 || devicePixelRatio != d->devicePixelRatio ) - { - d->p0 = pos; - d->devicePixelRatio = devicePixelRatio; - - d->dirty = true; - } -} - -void QskLinesNode::resetGlobalPosition() -{ - Q_D( QskLinesNode ); - - if ( d->doRound == true ) - { - d->doRound = false; - d->dirty = true; - } -} - void QskLinesNode::updateRect( const QColor& color, qreal lineWidth, const QskStippleMetrics& stippleMetrics, const QTransform& transform, const QRectF& rect ) @@ -272,8 +163,6 @@ void QskLinesNode::updateLines( const QColor& color, qreal lineWidth, const QskStippleMetrics& stippleMetrics, const QTransform& transform, int count, const QLineF* lines ) { - Q_D( QskLinesNode ); - if ( !stippleMetrics.isValid() || !color.isValid() || color.alpha() == 0 || count == 0 ) { @@ -287,22 +176,18 @@ void QskLinesNode::updateLines( const QColor& color, hash = qHash( transform, hash ); hash = qHashBits( lines, count * sizeof( QLineF ) ); - if ( hash != d->hash ) + if ( hash != m_hash ) { - d->dirty = true; - d->hash = hash; - } + m_hash = hash; - if( d->dirty ) - { updateGeometry( stippleMetrics, transform, count, lines ); - d->geometry.markVertexDataDirty(); + geometry()->markVertexDataDirty(); markDirty( QSGNode::DirtyGeometry ); - d->dirty = false; } - d->setLineAttributes( this, color, lineWidth ); + setLineWidth( lineWidth ); + setColor( color ); } void QskLinesNode::updateGrid( const QColor& color, @@ -310,8 +195,6 @@ void QskLinesNode::updateGrid( const QColor& color, const QTransform& transform, const QRectF& rect, const QVector< qreal >& xValues, const QVector< qreal >& yValues ) { - Q_D( QskLinesNode ); - if ( !stippleMetrics.isValid() || !color.isValid() || color.alpha() == 0 ) { QskSGNode::resetGeometry( this ); @@ -326,30 +209,24 @@ void QskLinesNode::updateGrid( const QColor& color, hash = qHash( xValues, hash ); hash = qHash( yValues, hash ); - if ( hash != d->hash ) + if ( hash != m_hash ) { - d->dirty = true; - d->hash = hash; - } + m_hash = hash; - if( d->dirty ) - { updateGeometry( stippleMetrics, transform, rect, xValues, yValues ); - d->geometry.markVertexDataDirty(); + geometry()->markVertexDataDirty(); markDirty( QSGNode::DirtyGeometry ); - d->dirty = false; } - d->setLineAttributes( this, color, lineWidth ); + setLineWidth( lineWidth ); + setColor( color ); } void QskLinesNode::updateGeometry( const QskStippleMetrics& stippleMetrics, const QTransform& transform, int count, const QLineF* lines ) { - Q_D( QskLinesNode ); - - auto& geom = d->geometry; + auto& geom = *geometry(); QSGGeometry::Point2D* points = nullptr; @@ -382,8 +259,8 @@ void QskLinesNode::updateGeometry( const QskStippleMetrics& stippleMetrics, lineCount += renderer.dashCount( p1, p2 ); } - d->geometry.allocate( 2 * lineCount ); - points = d->geometry.vertexDataAsPoint2D(); + geometry()->allocate( 2 * lineCount ); + points = geometry()->vertexDataAsPoint2D(); points = qskAddDashes( transform, count, lines, stippleMetrics, points ); @@ -397,9 +274,7 @@ void QskLinesNode::updateGeometry( const QTransform& transform, const QRectF& rect, const QVector< qreal >& xValues, const QVector< qreal >& yValues ) { - Q_D( QskLinesNode ); - - auto& geom = d->geometry; + auto& geom = *geometry(); const auto y1 = mapY( transform, rect.top() ); const auto y2 = mapY( transform, rect.bottom() ); @@ -430,8 +305,8 @@ void QskLinesNode::updateGeometry( const auto countY = renderer.dashCount( x1, 0.0, x2, 0.0 ); const auto count = xValues.count() * countX + yValues.count() * countY; - d->geometry.allocate( 2 * count ); - points = d->geometry.vertexDataAsPoint2D(); + geometry()->allocate( 2 * count ); + points = geometry()->vertexDataAsPoint2D(); points = setStippledLines( Qt::Vertical, y1, y2, transform, xValues.count(), xValues.constData(), @@ -450,8 +325,6 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines( const QTransform& transform, int count, const qreal* values, const QskStippleMetrics& stippleMetrics, QSGGeometry::Point2D* points ) const { - Q_D( const QskLinesNode ); - if ( count <= 0 ) return points; @@ -464,16 +337,14 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines( if ( orientation == Qt::Vertical ) { - auto x = mapX( transform, values[0] ); - x = d->round( true, x ); + const auto x = mapX( transform, values[0] ); points = renderer.addDashes( points, x, v1, x, v2 ); dashCount = points - line0; } else { - auto y = mapY( transform, values[0] ); - y = d->round( false, y ); + const auto y = mapY( transform, values[0] ); points = renderer.addDashes( points, v1, y, v2, y ); dashCount = points - line0; @@ -485,8 +356,7 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines( { for ( int i = 1; i < count; i++ ) { - auto x = mapX( transform, values[i] ); - x = d->round( true, x ); + const auto x = mapX( transform, values[i] ); for ( int j = 0; j < dashCount; j++ ) points++->set( x, line0[j].y ); @@ -496,8 +366,7 @@ QSGGeometry::Point2D* QskLinesNode::setStippledLines( { for ( int i = 1; i < count; i++ ) { - auto y = mapY( transform, values[i] ); - y = d->round( false, y ); + const auto y = mapY( transform, values[i] ); for ( int j = 0; j < dashCount; j++ ) points++->set( line0[j].x, y ); @@ -512,8 +381,6 @@ QSGGeometry::Point2D* QskLinesNode::setSolidLines( const QTransform& transform, int count, const qreal* values, QSGGeometry::Point2D* points ) const { - Q_D( const QskLinesNode ); - if ( count <= 0 ) return points; @@ -523,9 +390,7 @@ QSGGeometry::Point2D* QskLinesNode::setSolidLines( { for ( int i = 0; i < count; i++ ) { - auto x = mapX( transform, values[i] ); - x = d->round( true, x ); - + const auto x = mapX( transform, values[i] ); lines++->setVLine( x, v1, v2 ); } } @@ -533,9 +398,7 @@ QSGGeometry::Point2D* QskLinesNode::setSolidLines( { for ( int i = 0; i < count; i++ ) { - auto y = mapY( transform, values[i] ); - y = d->round( false, y ); - + const auto y = mapY( transform, values[i] ); lines++->setHLine( v1, v2, y ); } } @@ -552,13 +415,11 @@ void QskLinesNode::updatePolygon( const QColor& color, qreal lineWidth, return; } - Q_D( QskLinesNode ); - if ( true ) // for the moment we always update the geometry. TODO ... { - d->geometry.allocate( polygon.count() + 1 ); + geometry()->allocate( polygon.count() + 1 ); - auto points = d->geometry.vertexDataAsPoint2D(); + auto points = geometry()->vertexDataAsPoint2D(); if ( transform.isIdentity() ) { @@ -579,9 +440,10 @@ void QskLinesNode::updatePolygon( const QColor& color, qreal lineWidth, points[ polygon.count() ] = points[0]; - d->geometry.markVertexDataDirty(); + geometry()->markVertexDataDirty(); markDirty( QSGNode::DirtyGeometry ); } - d->setLineAttributes( this, color, lineWidth ); + setLineWidth( lineWidth ); + setColor( color ); } diff --git a/src/nodes/QskLinesNode.h b/src/nodes/QskLinesNode.h index 54e25b9c..4a1271a6 100644 --- a/src/nodes/QskLinesNode.h +++ b/src/nodes/QskLinesNode.h @@ -6,9 +6,7 @@ #ifndef QSK_LINES_NODE_H #define QSK_LINES_NODE_H -#include "QskGlobal.h" - -#include +#include "QskBasicLinesNode.h" #include class QskIntervalF; @@ -17,26 +15,19 @@ class QTransform; class QPointF; class QLineF; class QPolygonF; -class QQuickItem; - -class QskLinesNodePrivate; /* A node for stippled or solid lines. For the moment limited to horizontal/vertical lines: TODO */ -class QSK_EXPORT QskLinesNode : public QSGGeometryNode +class QSK_EXPORT QskLinesNode : public QskBasicLinesNode { - using Inherited = QSGGeometryNode; + using Inherited = QskBasicLinesNode; public: QskLinesNode(); ~QskLinesNode() override; - void setGlobalPosition( const QPointF&, qreal devicePixelRatio ); - void setGlobalPosition( const QQuickItem* ); - void resetGlobalPosition(); - void updateGrid( const QColor&, qreal lineWidth, const QskStippleMetrics&, const QTransform&, const QRectF&, const QVector< qreal >&, const QVector< qreal >& ); @@ -80,7 +71,7 @@ class QSK_EXPORT QskLinesNode : public QSGGeometryNode const QTransform&, int count, const qreal* values, const QskStippleMetrics&, QSGGeometry::Point2D* ) const; - Q_DECLARE_PRIVATE( QskLinesNode ) + QskHashValue m_hash = 0.0; }; #endif diff --git a/src/nodes/shaders.qrc b/src/nodes/shaders.qrc index 0301b991..82a42748 100644 --- a/src/nodes/shaders.qrc +++ b/src/nodes/shaders.qrc @@ -22,5 +22,9 @@ shaders/gradientlinear.vert shaders/gradientlinear.frag + shaders/crisplines.vert.qsb + shaders/crisplines.frag.qsb + shaders/crisplines.vert + diff --git a/src/nodes/shaders/boxshadow.frag.qsb b/src/nodes/shaders/boxshadow.frag.qsb index 67bd10ec..9a799078 100644 Binary files a/src/nodes/shaders/boxshadow.frag.qsb and b/src/nodes/shaders/boxshadow.frag.qsb differ diff --git a/src/nodes/shaders/boxshadow.vert.qsb b/src/nodes/shaders/boxshadow.vert.qsb index 3f9a0c90..4d371492 100644 Binary files a/src/nodes/shaders/boxshadow.vert.qsb and b/src/nodes/shaders/boxshadow.vert.qsb differ diff --git a/src/nodes/shaders/crisplines-vulkan.frag b/src/nodes/shaders/crisplines-vulkan.frag new file mode 100644 index 00000000..a4618fe9 --- /dev/null +++ b/src/nodes/shaders/crisplines-vulkan.frag @@ -0,0 +1,15 @@ +#version 440 + +layout( location = 0 ) out vec4 fragColor; + +layout( std140, binding = 0 ) uniform buf +{ + mat4 matrix; + vec4 color; + vec2 size; +} ubuf; + +void main() +{ + fragColor = ubuf.color; +} diff --git a/src/nodes/shaders/crisplines-vulkan.vert b/src/nodes/shaders/crisplines-vulkan.vert new file mode 100644 index 00000000..e572cda7 --- /dev/null +++ b/src/nodes/shaders/crisplines-vulkan.vert @@ -0,0 +1,41 @@ +#version 440 + +layout( location = 0 ) in vec4 vertexCoord; + +layout( std140, binding = 0 ) uniform buf +{ + mat4 matrix; + vec4 color; + vec2 size; +} 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; + + if ( ubuf.size.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 ); + } + + if ( ubuf.size.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 ); + } +} diff --git a/src/nodes/shaders/crisplines.frag.qsb b/src/nodes/shaders/crisplines.frag.qsb new file mode 100644 index 00000000..9a0addc5 Binary files /dev/null and b/src/nodes/shaders/crisplines.frag.qsb differ diff --git a/src/nodes/shaders/crisplines.vert b/src/nodes/shaders/crisplines.vert new file mode 100644 index 00000000..41d01bac --- /dev/null +++ b/src/nodes/shaders/crisplines.vert @@ -0,0 +1,38 @@ +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; +} + +float round( in float v ) +{ + return floor( v + 0.5 ); +} + +void main() +{ + gl_Position = matrix * in_vertex; + + if ( size.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 ); + } + + if ( size.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 ); + } +} diff --git a/src/nodes/shaders/crisplines.vert.qsb b/src/nodes/shaders/crisplines.vert.qsb new file mode 100644 index 00000000..27f5213f Binary files /dev/null and b/src/nodes/shaders/crisplines.vert.qsb differ diff --git a/src/nodes/shaders/gradientconic.frag.qsb b/src/nodes/shaders/gradientconic.frag.qsb index 517fbf52..c2a0848e 100644 Binary files a/src/nodes/shaders/gradientconic.frag.qsb and b/src/nodes/shaders/gradientconic.frag.qsb differ diff --git a/src/nodes/shaders/gradientconic.vert.qsb b/src/nodes/shaders/gradientconic.vert.qsb index 6d5b2293..e1b0505c 100644 Binary files a/src/nodes/shaders/gradientconic.vert.qsb and b/src/nodes/shaders/gradientconic.vert.qsb differ diff --git a/src/nodes/shaders/gradientlinear.frag.qsb b/src/nodes/shaders/gradientlinear.frag.qsb index 87c773bd..0d042678 100644 Binary files a/src/nodes/shaders/gradientlinear.frag.qsb and b/src/nodes/shaders/gradientlinear.frag.qsb differ diff --git a/src/nodes/shaders/gradientlinear.vert.qsb b/src/nodes/shaders/gradientlinear.vert.qsb index ef94ce40..55c4d629 100644 Binary files a/src/nodes/shaders/gradientlinear.vert.qsb and b/src/nodes/shaders/gradientlinear.vert.qsb differ diff --git a/src/nodes/shaders/gradientradial.frag.qsb b/src/nodes/shaders/gradientradial.frag.qsb index c0b5aea2..5af5a391 100644 Binary files a/src/nodes/shaders/gradientradial.frag.qsb and b/src/nodes/shaders/gradientradial.frag.qsb differ diff --git a/src/nodes/shaders/gradientradial.vert.qsb b/src/nodes/shaders/gradientradial.vert.qsb index 99fa7614..c81c721d 100644 Binary files a/src/nodes/shaders/gradientradial.vert.qsb and b/src/nodes/shaders/gradientradial.vert.qsb differ diff --git a/src/nodes/shaders/vulkan2qsb.sh b/src/nodes/shaders/vulkan2qsb.sh index 84f7f389..22e28e10 100755 --- a/src/nodes/shaders/vulkan2qsb.sh +++ b/src/nodes/shaders/vulkan2qsb.sh @@ -16,3 +16,6 @@ qsbcompile gradientradial-vulkan.frag qsbcompile gradientlinear-vulkan.vert qsbcompile gradientlinear-vulkan.frag + +qsbcompile crisplines-vulkan.vert +qsbcompile crisplines-vulkan.frag