QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsphongmaterialsettings.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsphongmaterialsettings.cpp
3  --------------------------------------
4  Date : July 2017
5  Copyright : (C) 2017 by Martin Dobias
6  Email : wonder dot sk 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 
17 
18 #include "qgssymbollayerutils.h"
19 #include "qgsapplication.h"
20 #include "qgsimagecache.h"
21 #include <Qt3DExtras/QDiffuseMapMaterial>
22 #include <Qt3DExtras/QPhongMaterial>
23 #include <Qt3DRender/QAttribute>
24 #include <Qt3DRender/QBuffer>
25 #include <Qt3DRender/QGeometry>
26 #include <Qt3DRender/QParameter>
27 #include <Qt3DRender/QEffect>
28 #include <Qt3DRender/QTechnique>
29 #include <Qt3DRender/QGraphicsApiFilter>
30 #include <QMap>
31 
32 
34 {
35  return QStringLiteral( "phong" );
36 }
37 
39 {
40  switch ( technique )
41  {
48  return true;
49 
51  return false;
52  }
53  return false;
54 }
55 
57 {
58  return new QgsPhongMaterialSettings();
59 }
60 
62 {
63  return new QgsPhongMaterialSettings( *this );
64 }
65 
66 void QgsPhongMaterialSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
67 {
68  mAmbient = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "ambient" ), QStringLiteral( "25,25,25" ) ) );
69  mDiffuse = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "diffuse" ), QStringLiteral( "178,178,178" ) ) );
70  mSpecular = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "specular" ), QStringLiteral( "255,255,255" ) ) );
71  mShininess = elem.attribute( QStringLiteral( "shininess" ) ).toFloat();
72 
73  QgsAbstractMaterialSettings::readXml( elem, context );
74 }
75 
76 void QgsPhongMaterialSettings::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
77 {
78  elem.setAttribute( QStringLiteral( "ambient" ), QgsSymbolLayerUtils::encodeColor( mAmbient ) );
79  elem.setAttribute( QStringLiteral( "diffuse" ), QgsSymbolLayerUtils::encodeColor( mDiffuse ) );
80  elem.setAttribute( QStringLiteral( "specular" ), QgsSymbolLayerUtils::encodeColor( mSpecular ) );
81  elem.setAttribute( QStringLiteral( "shininess" ), mShininess );
82 
84 }
85 
86 
88 {
89  switch ( technique )
90  {
97  {
98  if ( dataDefinedProperties().hasActiveProperties() )
99  return dataDefinedMaterial();
100 
101  Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial;
102  material->setDiffuse( mDiffuse );
103  material->setAmbient( mAmbient );
104  material->setSpecular( mSpecular );
105  material->setShininess( mShininess );
106 
107  if ( context.isSelected() )
108  {
109  // update the material with selection colors
110  material->setDiffuse( context.selectionColor() );
111  material->setAmbient( context.selectionColor().darker() );
112  }
113  return material;
114  }
115 
117  return nullptr;
118  }
119  return nullptr;
120 }
121 
122 QMap<QString, QString> QgsPhongMaterialSettings::toExportParameters() const
123 {
124  QMap<QString, QString> parameters;
125  parameters[ QStringLiteral( "Kd" ) ] = QStringLiteral( "%1 %2 %3" ).arg( mDiffuse.redF() ).arg( mDiffuse.greenF() ).arg( mDiffuse.blueF() );
126  parameters[ QStringLiteral( "Ka" ) ] = QStringLiteral( "%1 %2 %3" ).arg( mAmbient.redF() ).arg( mAmbient.greenF() ).arg( mAmbient.blueF() );
127  parameters[ QStringLiteral( "Ks" ) ] = QStringLiteral( "%1 %2 %3" ).arg( mSpecular.redF() ).arg( mSpecular.greenF() ).arg( mSpecular.blueF() );
128  parameters[ QStringLiteral( "Ns" ) ] = QString::number( mShininess );
129  return parameters;
130 }
131 
132 void QgsPhongMaterialSettings::addParametersToEffect( Qt3DRender::QEffect *effect ) const
133 {
134  Qt3DRender::QParameter *ambientParameter = new Qt3DRender::QParameter( QStringLiteral( "ka" ), QColor::fromRgbF( 0.05f, 0.05f, 0.05f, 1.0f ) );
135  Qt3DRender::QParameter *diffuseParameter = new Qt3DRender::QParameter( QStringLiteral( "kd" ), QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) );
136  Qt3DRender::QParameter *specularParameter = new Qt3DRender::QParameter( QStringLiteral( "ks" ), QColor::fromRgbF( 0.01f, 0.01f, 0.01f, 1.0f ) );
137  Qt3DRender::QParameter *shininessParameter = new Qt3DRender::QParameter( QStringLiteral( "shininess" ), 150.0f );
138 
139  diffuseParameter->setValue( mDiffuse );
140  ambientParameter->setValue( mAmbient );
141  specularParameter->setValue( mSpecular );
142  shininessParameter->setValue( mShininess );
143 
144  effect->addParameter( ambientParameter );
145  effect->addParameter( diffuseParameter );
146  effect->addParameter( specularParameter );
147  effect->addParameter( shininessParameter );
148 }
149 
151 {
152  QColor ambient = dataDefinedProperties().valueAsColor( Ambient, expressionContext, mAmbient );
153  QColor diffuse = dataDefinedProperties().valueAsColor( Diffuse, expressionContext, mDiffuse );
154  QColor specular = dataDefinedProperties().valueAsColor( Specular, expressionContext, mSpecular );
155 
156  QByteArray array;
157  array.resize( sizeof( unsigned char ) * 9 );
158  unsigned char *fptr = reinterpret_cast<unsigned char *>( array.data() );
159 
160  *fptr++ = static_cast<unsigned char>( diffuse.red() );
161  *fptr++ = static_cast<unsigned char>( diffuse.green() );
162  *fptr++ = static_cast<unsigned char>( diffuse.blue() );
163 
164  *fptr++ = static_cast<unsigned char>( ambient.red() );
165  *fptr++ = static_cast<unsigned char>( ambient.green() );
166  *fptr++ = static_cast<unsigned char>( ambient.blue() );
167 
168  *fptr++ = static_cast<unsigned char>( specular.red() );
169  *fptr++ = static_cast<unsigned char>( specular.green() );
170  *fptr++ = static_cast<unsigned char>( specular.blue() );
171 
172  return array;
173 }
174 
175 int QgsPhongMaterialSettings::dataDefinedByteStride() const {return 9 * sizeof( unsigned char );}
176 
177 void QgsPhongMaterialSettings::applyDataDefinedToGeometry( Qt3DRender::QGeometry *geometry, int vertexCount, const QByteArray &data ) const
178 {
179  Qt3DRender::QBuffer *dataBuffer = new Qt3DRender::QBuffer( geometry );
180 
181  Qt3DRender::QAttribute *diffuseAttribute = new Qt3DRender::QAttribute( geometry );
182  diffuseAttribute->setName( QStringLiteral( "dataDefinedDiffuseColor" ) );
183  diffuseAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
184  diffuseAttribute->setVertexSize( 3 );
185  diffuseAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
186  diffuseAttribute->setBuffer( dataBuffer );
187  diffuseAttribute->setByteStride( 9 * sizeof( unsigned char ) );
188  diffuseAttribute->setByteOffset( 0 );
189  diffuseAttribute->setCount( vertexCount );
190  geometry->addAttribute( diffuseAttribute );
191 
192  Qt3DRender::QAttribute *ambientAttribute = new Qt3DRender::QAttribute( geometry );
193  ambientAttribute->setName( QStringLiteral( "dataDefinedAmbiantColor" ) );
194  ambientAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
195  ambientAttribute->setVertexSize( 3 );
196  ambientAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
197  ambientAttribute->setBuffer( dataBuffer );
198  ambientAttribute->setByteStride( 9 * sizeof( unsigned char ) );
199  ambientAttribute->setByteOffset( 3 * sizeof( unsigned char ) );
200  ambientAttribute->setCount( vertexCount );
201  geometry->addAttribute( ambientAttribute );
202 
203  Qt3DRender::QAttribute *specularAttribute = new Qt3DRender::QAttribute( geometry );
204  specularAttribute->setName( QStringLiteral( "dataDefinedSpecularColor" ) );
205  specularAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
206  specularAttribute->setVertexSize( 3 );
207  specularAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
208  specularAttribute->setBuffer( dataBuffer );
209  specularAttribute->setByteStride( 9 * sizeof( unsigned char ) );
210  specularAttribute->setByteOffset( 6 * sizeof( unsigned char ) );
211  specularAttribute->setCount( vertexCount );
212  geometry->addAttribute( specularAttribute );
213 
214  dataBuffer->setData( data );
215 }
216 
217 Qt3DRender::QMaterial *QgsPhongMaterialSettings::dataDefinedMaterial() const
218 {
219  Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
220 
221  Qt3DRender::QEffect *eff = new Qt3DRender::QEffect( material );
222 
223  Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
224  technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
225  technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
226  technique->graphicsApiFilter()->setMajorVersion( 3 );
227  technique->graphicsApiFilter()->setMinorVersion( 3 );
228  Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey();
229  filterKey->setName( QStringLiteral( "renderingStyle" ) );
230  filterKey->setValue( QStringLiteral( "forward" ) );
231  technique->addFilterKey( filterKey );
232 
233  Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass();
234  Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram();
235 
236  //Load shader programs
237  QUrl urlVert( QStringLiteral( "qrc:/shaders/phongDataDefined.vert" ) );
238  shaderProgram->setShaderCode( Qt3DRender::QShaderProgram::Vertex, shaderProgram->loadSource( urlVert ) );
239  QUrl urlFrag( QStringLiteral( "qrc:/shaders/phongDataDefined.frag" ) );
240  shaderProgram->setShaderCode( Qt3DRender::QShaderProgram::Fragment, shaderProgram->loadSource( urlFrag ) );
241 
242  renderPass->setShaderProgram( shaderProgram );
243  technique->addRenderPass( renderPass );
244 
245  technique->addParameter( new Qt3DRender::QParameter( QStringLiteral( "shininess" ), mShininess ) );
246 
247  eff->addTechnique( technique );
248  material->setEffect( eff );
249 
250  return material;
251 }
virtual void writeXml(QDomElement &element, const QgsReadWriteContext &) const
Writes settings to a DOM element.
virtual void readXml(const QDomElement &element, const QgsReadWriteContext &)
Reads settings from a DOM element.
@ Ambient
Ambient color (phong material)
QgsPropertyCollection dataDefinedProperties() const
Returns the symbol material property collection, used for data defined overrides.
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QColor selectionColor() const
Returns the color for representing materials in a selected state.
bool isSelected() const
Returns true if the material should represent a selected state.
int dataDefinedByteStride() const override
Returns byte stride of the data defined colors,used to fill the vertex colors data defined buffer for...
Qt3DRender::QMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const override
Creates a new QMaterial object representing the material settings.
void addParametersToEffect(Qt3DRender::QEffect *effect) const override
Adds parameters from the material to a destination effect.
QString type() const override
Returns the unique type name for the material.
QColor diffuse() const
Returns diffuse color component.
QMap< QString, QString > toExportParameters() const override
Returns the parameters to be exported to .mtl file.
QColor specular() const
Returns specular color component.
QColor ambient() const
Returns ambient color component.
static QgsAbstractMaterialSettings * create()
Returns a new instance of QgsPhongMaterialSettings.
static bool supportsTechnique(QgsMaterialSettingsRenderingTechnique technique)
Returns true if the specified technique is supported by the Phong material.
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const override
Writes settings to a DOM element.
QgsPhongMaterialSettings * clone() const override
Clones the material settings.
QgsPhongMaterialSettings()=default
Constructor for QgsPhongMaterialSettings.
void applyDataDefinedToGeometry(Qt3DRender::QGeometry *geometry, int vertexCount, const QByteArray &data) const override
Applies the data defined bytes, dataDefinedBytes, on the geometry by filling a specific vertex buffer...
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads settings from a DOM element.
QByteArray dataDefinedVertexColorsAsByte(const QgsExpressionContext &expressionContext) const override
Returns byte array corresponding to the data defined colors depending of the expressionContext,...
The class is used as a container of context for various read/write operations on other objects.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
QgsMaterialSettingsRenderingTechnique
Material rendering techniques 3.
@ Points
Point based rendering, requires point data.
@ Triangles
Triangle based rendering (default)
@ TrianglesFromModel
Triangle based rendering, using a model object source.
@ Lines
Line based rendering, requires line data.
@ TrianglesDataDefined
Triangle based rendering with possibility of datadefined color.
@ InstancedPoints
Instanced based rendering, requiring triangles and point data.
@ TrianglesWithFixedTexture
Triangle based rendering, using a fixed, non-user-configurable texture (e.g. for terrain rendering)