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