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