Skip to content

Commit

Permalink
QskBasicLinesNode ( crisplines shaders ) introduced
Browse files Browse the repository at this point in the history
  • Loading branch information
uwerat committed Nov 23, 2023
1 parent 16754b4 commit dc64f21
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
190 changes: 190 additions & 0 deletions src/nodes/QskBasicLinesNode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/

#include "QskBasicLinesNode.h"

#include <qsgmaterial.h>
#include <qsggeometry.h>
#include <QTransform>

QSK_QT_PRIVATE_BEGIN
#include <private/qsgnode_p.h>
QSK_QT_PRIVATE_END

namespace
{
class Material final : public QSGMaterial
{
public:
Material();

QSGMaterialShader* createShader( QSGRendererInterface::RenderMode ) const override;

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 QSGMaterialShader
{
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 ) )
{
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;
}
};
}

Material::Material()
{
}

QSGMaterialShader* Material::createShader( QSGRendererInterface::RenderMode ) const
{
return new ShaderRhi();
}

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 )
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();
}

42 changes: 42 additions & 0 deletions src/nodes/QskBasicLinesNode.h
Original file line number Diff line number Diff line change
@@ -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 <qsgnode.h>
#include <qnamespace.h>

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
3 changes: 3 additions & 0 deletions src/nodes/shaders.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@
<file>shaders/gradientlinear.vert</file>
<file>shaders/gradientlinear.frag</file>

<file>shaders/crisplines.vert.qsb</file>
<file>shaders/crisplines.frag.qsb</file>

</qresource>
</RCC>
15 changes: 15 additions & 0 deletions src/nodes/shaders/crisplines-vulkan.frag
Original file line number Diff line number Diff line change
@@ -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;
}
41 changes: 41 additions & 0 deletions src/nodes/shaders/crisplines-vulkan.vert
Original file line number Diff line number Diff line change
@@ -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 );
}
}
Binary file added src/nodes/shaders/crisplines.frag.qsb
Binary file not shown.
Binary file added src/nodes/shaders/crisplines.vert.qsb
Binary file not shown.
3 changes: 3 additions & 0 deletions src/nodes/shaders/vulkan2qsb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ qsbcompile gradientradial-vulkan.frag

qsbcompile gradientlinear-vulkan.vert
qsbcompile gradientlinear-vulkan.frag

qsbcompile crisplines-vulkan.vert
qsbcompile crisplines-vulkan.frag

0 comments on commit dc64f21

Please sign in to comment.