QGIS API Documentation 3.36.0-Maidenhead (09951dc0acf)
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
28#include "qgssymbollayerutils.h"
29#include "qgs3dmapsettings.h"
30#include "qgsmarkersymbol.h"
31
33 : mSize( new Qt3DRender::QParameter( "BB_SIZE", QSizeF( 100, 100 ), this ) )
34 , mViewportSize( new Qt3DRender::QParameter( "WIN_SCALE", QSizeF( 800, 600 ), this ) )
35{
36 addParameter( mSize );
37 addParameter( mViewportSize );
38
39 // Initialize with empty parameter.
40 mTexture2D = new Qt3DRender::QParameter( "tex0", QVariant(), this );
41 addParameter( mTexture2D );
42
43 // Blending for handling transparency
44 Qt3DRender::QBlendEquationArguments *blendState = new Qt3DRender::QBlendEquationArguments;
45 blendState->setSourceRgb( Qt3DRender::QBlendEquationArguments::SourceAlpha );
46 blendState->setDestinationRgb( Qt3DRender::QBlendEquationArguments::OneMinusSourceAlpha );
47
48 Qt3DRender::QBlendEquation *blendEquation = new Qt3DRender::QBlendEquation;
49 blendEquation->setBlendFunction( Qt3DRender::QBlendEquation::Add );
50
51 // Shader program
52 Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram( this );
53 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/billboards.vert" ) ) ) );
54 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/billboards.frag" ) ) ) );
55 shaderProgram->setGeometryShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/billboards.geom" ) ) ) );
56
57 // Render Pass
58 Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass( this );
59 renderPass->setShaderProgram( shaderProgram );
60 renderPass->addRenderState( blendState );
61 renderPass->addRenderState( blendEquation );
62
63 // without this filter the default forward renderer would not render this
64 Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey;
65 filterKey->setName( QStringLiteral( "renderingStyle" ) );
66 filterKey->setValue( "forward" );
67
68 // Technique
69 Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
70 technique->addRenderPass( renderPass );
71 technique->addFilterKey( filterKey );
72 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
73 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
74 technique->graphicsApiFilter()->setMajorVersion( 3 );
75 technique->graphicsApiFilter()->setMinorVersion( 1 );
76
77 // Effect
78 Qt3DRender::QEffect *effect = new Qt3DRender::QEffect( this );
79 effect->addTechnique( technique );
80
81 setEffect( effect );
82}
83
85
86void QgsPoint3DBillboardMaterial::setSize( const QSizeF size )
87{
88 mSize->setValue( size );
89}
90
92{
93 return mSize->value().value<QSizeF>();
94}
95
97{
98 mViewportSize->setValue( size );
99}
100
102{
103 return mViewportSize->value().value<QSizeF>();
104}
105
106void QgsPoint3DBillboardMaterial::setTexture2DFromImage( QImage image, double size )
107{
108 // Create texture image
109 const QgsRectangle randomExtent = QgsRectangle( rand(), rand(), rand(), rand() );
110 QgsTerrainTextureImage *billboardTextureImage = new QgsTerrainTextureImage( image, randomExtent, QStringLiteral( "billboard material." ) );
111
112 setTexture2DFromTextureImage( billboardTextureImage );
113 setSize( QSizeF( size + size, size + size ) );
114}
115
117{
118 // Default texture
119 const std::unique_ptr< QgsMarkerSymbol> defaultSymbol( static_cast<QgsMarkerSymbol *>( QgsSymbol::defaultSymbol( Qgis::GeometryType::Point ) ) );
120 setTexture2DFromSymbol( defaultSymbol.get(), map, selected );
121}
122
124{
125 QgsRenderContext context;
126 context.setSelectionColor( map.selectionColor() );
127 context.setScaleFactor( map.outputDpi() / 25.4 );
130 const double pixelSize = context.convertToPainterUnits( markerSymbol->size( context ), markerSymbol->sizeUnit() );
131
132 // This number is an max estimation ratio between stroke width and symbol size.
133 const double strokeRatio = 0.5;
134 // Minimum extra width, just in case the size is small, but the stroke is quite big.
135 // 10 mm is quite big based on Raymond's experiece.
136 // 10 mm has around 37 pixel in 96 dpi, round up become 40.
137 const double minimumExtraSize = 40;
138 const double extraPixel = minimumExtraSize > pixelSize * strokeRatio ? minimumExtraSize : pixelSize * strokeRatio;
139 const int pixelWithExtra = std::ceil( pixelSize + extraPixel );
140 const QPixmap symbolPixmap = QgsSymbolLayerUtils::symbolPreviewPixmap( markerSymbol, QSize( pixelWithExtra, pixelWithExtra ), 0, &context, selected );
141 const QImage symbolImage = symbolPixmap.toImage();
142 const QImage flippedSymbolImage = symbolImage.mirrored();
143 setTexture2DFromImage( flippedSymbolImage, pixelWithExtra );
144}
145
146void QgsPoint3DBillboardMaterial::setTexture2DFromTextureImage( Qt3DRender::QAbstractTextureImage *textureImage )
147{
148 // Texture2D
149 Qt3DRender::QTexture2D *texture2D = new Qt3DRender::QTexture2D( this );
150 texture2D->setGenerateMipMaps( false );
151 texture2D->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
152 texture2D->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
153
154 // The textureImage gets parented to texture2D here
155 texture2D->addTextureImage( textureImage );
156
157 mTexture2D->setValue( QVariant::fromValue( texture2D ) );
158}
@ Antialiasing
Use antialiasing while drawing.
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
double outputDpi() const
Returns DPI used for conversion between real world units (e.g.
QColor selectionColor() const
Returns color used for selected features.
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).
QSizeF windowSize() const
Returns the size of the view port.
~QgsPoint3DBillboardMaterial() override
QSizeF size() const
Returns the billboard size.
void useDefaultSymbol(const Qgs3DMapSettings &map, bool selected=false)
Set default symbol for the texture with map and selected parameter for rendering.
void setViewportSize(const QSizeF size)
Set the size of the view port.
void setSize(const QSizeF size)
Set the billboard size.
void setTexture2DFromSymbol(QgsMarkerSymbol *markerSymbol, const Qgs3DMapSettings &map, bool selected=false)
Set markerSymbol for the texture with map and selected parameter for rendering.
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.