QGIS API Documentation 3.41.0-Master (45a0abf3bec)
Loading...
Searching...
No Matches
qgspoint3dbillboardmaterial.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspoint3dbillboardmaterial.h
3 --------------------------------------
4 Date : Jul 2019
5 Copyright : (C) 2019 by Ismail Sunni
6 Email : imajimatika at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15#include <Qt3DRender/QParameter>
16#include <Qt3DRender/QShaderProgram>
17#include <Qt3DRender/QRenderPass>
18#include <Qt3DRender/QTechnique>
19#include <Qt3DRender/QGraphicsApiFilter>
20#include <Qt3DRender/QEffect>
21#include <Qt3DRender/QBlendEquationArguments>
22#include <Qt3DRender/QBlendEquation>
23#include <Qt3DRender/QNoDepthMask>
24#include <QUrl>
25
27#include "moc_qgspoint3dbillboardmaterial.cpp"
29#include "qgssymbollayerutils.h"
30#include "qgsmarkersymbol.h"
31#include "qgs3drendercontext.h"
32
34 : mSize( new Qt3DRender::QParameter( "BB_SIZE", QSizeF( 100, 100 ), this ) )
35 , mViewportSize( new Qt3DRender::QParameter( "WIN_SCALE", QSizeF( 800, 600 ), this ) )
36{
37 addParameter( mSize );
38 addParameter( mViewportSize );
39
40 // Initialize with empty parameter.
41 mTexture2D = new Qt3DRender::QParameter( "tex0", QVariant(), this );
42 addParameter( mTexture2D );
43
44 // Blending for handling transparency
45 Qt3DRender::QBlendEquationArguments *blendState = new Qt3DRender::QBlendEquationArguments;
46 blendState->setSourceRgb( Qt3DRender::QBlendEquationArguments::SourceAlpha );
47 blendState->setDestinationRgb( Qt3DRender::QBlendEquationArguments::OneMinusSourceAlpha );
48
49 Qt3DRender::QBlendEquation *blendEquation = new Qt3DRender::QBlendEquation;
50 blendEquation->setBlendFunction( Qt3DRender::QBlendEquation::Add );
51
52 // Shader program
53 Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram( this );
54 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/billboards.vert" ) ) ) );
55 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/billboards.frag" ) ) ) );
56 shaderProgram->setGeometryShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/billboards.geom" ) ) ) );
57
58 // Render Pass
59 Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass( this );
60 renderPass->setShaderProgram( shaderProgram );
61 renderPass->addRenderState( blendState );
62 renderPass->addRenderState( blendEquation );
63
64 // without this filter the default forward renderer would not render this
65 Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey;
66 filterKey->setName( QStringLiteral( "renderingStyle" ) );
67 filterKey->setValue( "forward" );
68
69 // Technique
70 Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
71 technique->addRenderPass( renderPass );
72 technique->addFilterKey( filterKey );
73 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
74 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
75 technique->graphicsApiFilter()->setMajorVersion( 3 );
76 technique->graphicsApiFilter()->setMinorVersion( 1 );
77
78 // Effect
79 Qt3DRender::QEffect *effect = new Qt3DRender::QEffect( this );
80 effect->addTechnique( technique );
81
82 setEffect( effect );
83}
84
86
87void QgsPoint3DBillboardMaterial::setSize( const QSizeF size )
88{
89 mSize->setValue( size );
90}
91
93{
94 return mSize->value().value<QSizeF>();
95}
96
98{
99 mViewportSize->setValue( size );
100}
101
103{
104 return mViewportSize->value().value<QSizeF>();
105}
106
107void QgsPoint3DBillboardMaterial::setTexture2DFromImage( QImage image, double size )
108{
109 // Create texture image
110 const QgsRectangle randomExtent = QgsRectangle( rand(), rand(), rand(), rand() );
111 QgsTerrainTextureImage *billboardTextureImage = new QgsTerrainTextureImage( image, randomExtent, QStringLiteral( "billboard material." ) );
112
113 setTexture2DFromTextureImage( billboardTextureImage );
114 setSize( QSizeF( size + size, size + size ) );
115}
116
118{
119 // Default texture
120 const std::unique_ptr< QgsMarkerSymbol> defaultSymbol( static_cast<QgsMarkerSymbol *>( QgsSymbol::defaultSymbol( Qgis::GeometryType::Point ) ) );
121 setTexture2DFromSymbol( defaultSymbol.get(), context, selected );
122}
123
125{
126 QgsRenderContext context2D;
127 context2D.setSelectionColor( context.selectionColor() );
128 context2D.setScaleFactor( context.outputDpi() / 25.4 );
131 const double pixelSize = context2D.convertToPainterUnits( markerSymbol->size( context2D ), markerSymbol->sizeUnit() );
132
133 // This number is an max estimation ratio between stroke width and symbol size.
134 const double strokeRatio = 0.5;
135 // Minimum extra width, just in case the size is small, but the stroke is quite big.
136 // 10 mm is quite big based on Raymond's experiece.
137 // 10 mm has around 37 pixel in 96 dpi, round up become 40.
138 const double minimumExtraSize = 40;
139 const double extraPixel = minimumExtraSize > pixelSize * strokeRatio ? minimumExtraSize : pixelSize * strokeRatio;
140 const int pixelWithExtra = std::ceil( pixelSize + extraPixel );
141 const QPixmap symbolPixmap = QgsSymbolLayerUtils::symbolPreviewPixmap( markerSymbol, QSize( pixelWithExtra, pixelWithExtra ), 0, &context2D, selected );
142 const QImage symbolImage = symbolPixmap.toImage();
143 const QImage flippedSymbolImage = symbolImage.mirrored();
144 setTexture2DFromImage( flippedSymbolImage, pixelWithExtra );
145}
146
147void QgsPoint3DBillboardMaterial::setTexture2DFromTextureImage( Qt3DRender::QAbstractTextureImage *textureImage )
148{
149 // Texture2D
150 Qt3DRender::QTexture2D *texture2D = new Qt3DRender::QTexture2D( this );
151 texture2D->setGenerateMipMaps( false );
152 texture2D->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
153 texture2D->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
154
155 // The textureImage gets parented to texture2D here
156 texture2D->addTextureImage( textureImage );
157
158 mTexture2D->setValue( QVariant::fromValue( texture2D ) );
159}
@ Antialiasing
Use antialiasing while drawing.
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
QColor selectionColor() const
Returns color used for selected features.
double outputDpi() const
Returns DPI used for conversion between real world units (e.g.
A marker symbol type, for rendering Point and MultiPoint geometries.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
Qgis::RenderUnit sizeUnit() const
Returns the size units for the whole symbol (including all symbol layers).
void useDefaultSymbol(const Qgs3DRenderContext &context, bool selected=false)
Set default symbol for the texture with context and selected parameter for rendering.
QSizeF windowSize() const
Returns the size of the view port.
~QgsPoint3DBillboardMaterial() override
void setTexture2DFromSymbol(QgsMarkerSymbol *markerSymbol, const Qgs3DRenderContext &context, bool selected=false)
Set markerSymbol for the texture with context and selected parameter for rendering.
QSizeF size() const
Returns the billboard size.
void setViewportSize(const QSizeF size)
Set the size of the view port.
void setSize(const QSizeF size)
Set the billboard size.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void setSelectionColor(const QColor &color)
Sets the color to use when rendering selected features.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a color ramp.
static QgsSymbol * defaultSymbol(Qgis::GeometryType geomType)
Returns a new default symbol for the specified geometry type.