QGIS API Documentation 3.99.0-Master (21b3aa880ba)
Loading...
Searching...
No Matches
qgsmetalroughmaterial.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmetalroughmaterial.cpp
3 --------------------------------------
4 Date : December 2023
5 Copyright : (C) 2023 by Nyall Dawson
6 Email : nyall dot dawson 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 "qgs3dutils.h"
19
20#include <Qt3DRender/QAbstractTexture>
21#include <Qt3DRender/QGraphicsApiFilter>
22#include <Qt3DRender/QParameter>
23#include <Qt3DRender/QRenderPass>
24#include <Qt3DRender/QShaderProgramBuilder>
25#include <Qt3DRender/QTechnique>
26#include <Qt3DRender/QTexture>
27
28#include "moc_qgsmetalroughmaterial.cpp"
29
31QgsMetalRoughMaterial::QgsMetalRoughMaterial( QNode *parent )
32 : QgsMaterial( parent )
33 , mBaseColorParameter( new Qt3DRender::QParameter( QStringLiteral( "baseColor" ), QColor( "grey" ), this ) )
34 , mMetalnessParameter( new Qt3DRender::QParameter( QStringLiteral( "metalness" ), 0.0f, this ) )
35 , mRoughnessParameter( new Qt3DRender::QParameter( QStringLiteral( "roughness" ), 0.0f, this ) )
36 , mBaseColorMapParameter( new Qt3DRender::QParameter( QStringLiteral( "baseColorMap" ), QVariant(), this ) )
37 , mMetalnessMapParameter( new Qt3DRender::QParameter( QStringLiteral( "metalnessMap" ), QVariant(), this ) )
38 , mRoughnessMapParameter( new Qt3DRender::QParameter( QStringLiteral( "roughnessMap" ), QVariant(), this ) )
39 , mAmbientOcclusionMapParameter( new Qt3DRender::QParameter( QStringLiteral( "ambientOcclusionMap" ), QVariant(), this ) )
40 , mNormalMapParameter( new Qt3DRender::QParameter( QStringLiteral( "normalMap" ), QVariant(), this ) )
41 , mTextureScaleParameter( new Qt3DRender::QParameter( QStringLiteral( "texCoordScale" ), 1.0f, this ) )
42 , mMetalRoughEffect( new Qt3DRender::QEffect( this ) )
43 , mMetalRoughGL3Technique( new Qt3DRender::QTechnique( this ) )
44 , mMetalRoughGL3RenderPass( new Qt3DRender::QRenderPass( this ) )
45 , mMetalRoughGL3Shader( new Qt3DRender::QShaderProgram( this ) )
46 , mFilterKey( new Qt3DRender::QFilterKey( this ) )
47{
48 init();
49}
50
51QgsMetalRoughMaterial::~QgsMetalRoughMaterial() = default;
52
53QVariant QgsMetalRoughMaterial::baseColor() const
54{
55 return mBaseColorParameter->value();
56}
57
58QVariant QgsMetalRoughMaterial::metalness() const
59{
60 return mMetalnessParameter->value();
61}
62
63QVariant QgsMetalRoughMaterial::roughness() const
64{
65 return mRoughnessParameter->value();
66}
67
68QVariant QgsMetalRoughMaterial::ambientOcclusion() const
69{
70 return mAmbientOcclusionMapParameter->value();
71}
72
73QVariant QgsMetalRoughMaterial::normal() const
74{
75 return mNormalMapParameter->value();
76}
77
78float QgsMetalRoughMaterial::textureScale() const
79{
80 return mTextureScaleParameter->value().toFloat();
81}
82
83void QgsMetalRoughMaterial::setBaseColor( const QVariant &baseColor )
84{
85 mBaseColorParameter->setValue( baseColor );
86 mBaseColorMapParameter->setValue( baseColor );
87 bool oldUsingBaseColorMap = mUsingBaseColorMap;
88
89 if ( baseColor.value<Qt3DRender::QAbstractTexture *>() )
90 {
91 mUsingBaseColorMap = true;
92 mMetalRoughEffect->addParameter( mBaseColorMapParameter );
93 if ( mMetalRoughEffect->parameters().contains( mBaseColorParameter ) )
94 mMetalRoughEffect->removeParameter( mBaseColorParameter );
95 }
96 else
97 {
98 mUsingBaseColorMap = false;
99 if ( mMetalRoughEffect->parameters().contains( mBaseColorMapParameter ) )
100 mMetalRoughEffect->removeParameter( mBaseColorMapParameter );
101 mMetalRoughEffect->addParameter( mBaseColorParameter );
102 }
103
104 if ( oldUsingBaseColorMap != mUsingBaseColorMap )
105 updateFragmentShader();
106}
107
108void QgsMetalRoughMaterial::setMetalness( const QVariant &metalness )
109{
110 mMetalnessParameter->setValue( metalness );
111 mMetalnessMapParameter->setValue( metalness );
112 bool oldUsingMetalnessMap = mUsingMetalnessMap;
113
114 if ( metalness.value<Qt3DRender::QAbstractTexture *>() )
115 {
116 mUsingMetalnessMap = true;
117 mMetalRoughEffect->addParameter( mMetalnessMapParameter );
118 if ( mMetalRoughEffect->parameters().contains( mMetalnessParameter ) )
119 mMetalRoughEffect->removeParameter( mMetalnessParameter );
120 }
121 else
122 {
123 mUsingMetalnessMap = false;
124 if ( mMetalRoughEffect->parameters().contains( mMetalnessMapParameter ) )
125 mMetalRoughEffect->removeParameter( mMetalnessMapParameter );
126 mMetalRoughEffect->addParameter( mMetalnessParameter );
127 }
128
129 if ( oldUsingMetalnessMap != mUsingMetalnessMap )
130 updateFragmentShader();
131}
132
133void QgsMetalRoughMaterial::setRoughness( const QVariant &roughness )
134{
135 mRoughnessParameter->setValue( roughness );
136 mRoughnessMapParameter->setValue( roughness );
137 bool oldUsingRoughnessMap = mUsingRoughnessMap;
138
139 if ( roughness.value<Qt3DRender::QAbstractTexture *>() )
140 {
141 mUsingRoughnessMap = true;
142 mMetalRoughEffect->addParameter( mRoughnessMapParameter );
143 if ( mMetalRoughEffect->parameters().contains( mRoughnessParameter ) )
144 mMetalRoughEffect->removeParameter( mRoughnessParameter );
145 }
146 else
147 {
148 mUsingRoughnessMap = false;
149 if ( mMetalRoughEffect->parameters().contains( mRoughnessMapParameter ) )
150 mMetalRoughEffect->removeParameter( mRoughnessMapParameter );
151 mMetalRoughEffect->addParameter( mRoughnessParameter );
152 }
153
154 if ( oldUsingRoughnessMap != mUsingRoughnessMap )
155 updateFragmentShader();
156}
157
158void QgsMetalRoughMaterial::setAmbientOcclusion( const QVariant &ambientOcclusion )
159{
160 mAmbientOcclusionMapParameter->setValue( ambientOcclusion );
161 bool oldUsingAmbientOcclusionMap = mUsingAmbientOcclusionMap;
162
163 if ( ambientOcclusion.value<Qt3DRender::QAbstractTexture *>() )
164 {
165 mUsingAmbientOcclusionMap = true;
166 mMetalRoughEffect->addParameter( mAmbientOcclusionMapParameter );
167 }
168 else
169 {
170 mUsingAmbientOcclusionMap = false;
171 if ( mMetalRoughEffect->parameters().contains( mAmbientOcclusionMapParameter ) )
172 mMetalRoughEffect->removeParameter( mAmbientOcclusionMapParameter );
173 }
174
175 if ( oldUsingAmbientOcclusionMap != mUsingAmbientOcclusionMap )
176 updateFragmentShader();
177}
178
179void QgsMetalRoughMaterial::setNormal( const QVariant &normal )
180{
181 mNormalMapParameter->setValue( normal );
182 bool oldUsingNormalMap = mUsingNormalMap;
183
184 if ( normal.value<Qt3DRender::QAbstractTexture *>() )
185 {
186 mUsingNormalMap = true;
187 mMetalRoughEffect->addParameter( mNormalMapParameter );
188 }
189 else
190 {
191 mUsingNormalMap = false;
192 if ( mMetalRoughEffect->parameters().contains( mNormalMapParameter ) )
193 mMetalRoughEffect->removeParameter( mNormalMapParameter );
194 }
195
196 if ( oldUsingNormalMap != mUsingNormalMap )
197 updateFragmentShader();
198}
199
200void QgsMetalRoughMaterial::setTextureScale( float textureScale )
201{
202 mTextureScaleParameter->setValue( textureScale );
203}
204
205void QgsMetalRoughMaterial::init()
206{
207 QObject::connect( mBaseColorParameter, &Qt3DRender::QParameter::valueChanged, this, &QgsMetalRoughMaterial::baseColorChanged );
208 QObject::connect( mMetalnessParameter, &Qt3DRender::QParameter::valueChanged, this, &QgsMetalRoughMaterial::metalnessChanged );
209 QObject::connect( mRoughnessParameter, &Qt3DRender::QParameter::valueChanged, this, &QgsMetalRoughMaterial::roughnessChanged );
210 QObject::connect( mAmbientOcclusionMapParameter, &Qt3DRender::QParameter::valueChanged, this, &QgsMetalRoughMaterial::ambientOcclusionChanged );
211 QObject::connect( mNormalMapParameter, &Qt3DRender::QParameter::valueChanged, this, &QgsMetalRoughMaterial::normalChanged );
212 connect( mTextureScaleParameter, &Qt3DRender::QParameter::valueChanged, this, &QgsMetalRoughMaterial::handleTextureScaleChanged );
213
214 mMetalRoughGL3Shader->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/default.vert" ) ) ) );
215
216 updateFragmentShader();
217
218 mMetalRoughGL3Technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
219 mMetalRoughGL3Technique->graphicsApiFilter()->setMajorVersion( 3 );
220 mMetalRoughGL3Technique->graphicsApiFilter()->setMinorVersion( 1 );
221 mMetalRoughGL3Technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
222
223 mFilterKey->setParent( this );
224 mFilterKey->setName( QStringLiteral( "renderingStyle" ) );
225 mFilterKey->setValue( QStringLiteral( "forward" ) );
226
227 mMetalRoughGL3Technique->addFilterKey( mFilterKey );
228 mMetalRoughGL3RenderPass->setShaderProgram( mMetalRoughGL3Shader );
229 mMetalRoughGL3Technique->addRenderPass( mMetalRoughGL3RenderPass );
230 mMetalRoughEffect->addTechnique( mMetalRoughGL3Technique );
231
232 // Given parameters a parent
233 mBaseColorMapParameter->setParent( mMetalRoughEffect );
234 mMetalnessMapParameter->setParent( mMetalRoughEffect );
235 mRoughnessMapParameter->setParent( mMetalRoughEffect );
236
237 mMetalRoughEffect->addParameter( mBaseColorParameter );
238 mMetalRoughEffect->addParameter( mMetalnessParameter );
239 mMetalRoughEffect->addParameter( mRoughnessParameter );
240 mMetalRoughEffect->addParameter( mTextureScaleParameter );
241
242 setEffect( mMetalRoughEffect );
243}
244
245void QgsMetalRoughMaterial::updateFragmentShader()
246{
247 // pre-process fragment shader and add #defines based on whether using maps for some properties
248 QByteArray fragmentShaderCode = Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/metalrough.frag" ) ) );
249 QStringList defines;
250 if ( mUsingBaseColorMap )
251 defines += "BASE_COLOR_MAP";
252 if ( mUsingMetalnessMap )
253 defines += "METALNESS_MAP";
254 if ( mUsingRoughnessMap )
255 defines += "ROUGHNESS_MAP";
256 if ( mUsingAmbientOcclusionMap )
257 defines += "AMBIENT_OCCLUSION_MAP";
258 if ( mUsingNormalMap )
259 defines += "NORMAL_MAP";
260
261 if ( mFlatShading )
262 defines += "FLAT_SHADING";
263
264 QByteArray finalShaderCode = Qgs3DUtils::addDefinesToShaderCode( fragmentShaderCode, defines );
265 mMetalRoughGL3Shader->setFragmentShaderCode( finalShaderCode );
266}
267
268void QgsMetalRoughMaterial::handleTextureScaleChanged( const QVariant &var )
269{
270 emit textureScaleChanged( var.toFloat() );
271}
272
273bool QgsMetalRoughMaterial::flatShadingEnabled() const
274{
275 return mFlatShading;
276}
277
278void QgsMetalRoughMaterial::setFlatShadingEnabled( bool enabled )
279{
280 if ( enabled != mFlatShading )
281 {
282 mFlatShading = enabled;
283 updateFragmentShader();
284 }
285}
286
static QByteArray addDefinesToShaderCode(const QByteArray &shaderCode, const QStringList &defines)
Inserts some define macros into a shader source code.
Base class for all materials used within QGIS 3D views.
Definition qgsmaterial.h:39