QGIS API Documentation 4.1.0-Master (376402f9aeb)
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, Qgs3DUtils::srgbToLinear( 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 , mHeightMapParameter( new Qt3DRender::QParameter( u"heightMap"_s, QVariant(), this ) )
45 , mParallaxScaleParameter( new Qt3DRender::QParameter( u"parallaxScale"_s, 0.1f, this ) )
46 , mEmissionMapParameter( new Qt3DRender::QParameter( u"emissionMap"_s, QVariant(), this ) )
47 , mEmissionFactorParameter( new Qt3DRender::QParameter( u"emissiveFactor"_s, 1.0f, this ) )
48 , mTextureScaleParameter( new Qt3DRender::QParameter( u"texCoordScale"_s, 1.0f, this ) )
49 , mTextureRotationParameter( new Qt3DRender::QParameter( u"texCoordRotation"_s, 0.0f, this ) )
50 , mMetalRoughEffect( new Qt3DRender::QEffect( this ) )
51 , mMetalRoughGL3Technique( new Qt3DRender::QTechnique( this ) )
52 , mMetalRoughGL3RenderPass( new Qt3DRender::QRenderPass( this ) )
53 , mMetalRoughGL3Shader( new Qt3DRender::QShaderProgram( this ) )
54 , mFilterKey( new Qt3DRender::QFilterKey( this ) )
55{
56 init();
57}
58
59QgsMetalRoughMaterial::~QgsMetalRoughMaterial() = default;
60
61void QgsMetalRoughMaterial::setBaseColor( const QColor &baseColor )
62{
63 mBaseColorParameter->setValue( Qgs3DUtils::srgbToLinear( baseColor ) );
64 bool oldUsingBaseColorMap = mUsingBaseColorMap;
65
66 mUsingBaseColorMap = false;
67 if ( mMetalRoughEffect->parameters().contains( mBaseColorMapParameter ) )
68 mMetalRoughEffect->removeParameter( mBaseColorMapParameter );
69 mMetalRoughEffect->addParameter( mBaseColorParameter );
70
71 if ( oldUsingBaseColorMap != mUsingBaseColorMap )
72 updateFragmentShader();
73}
74
75void QgsMetalRoughMaterial::setBaseColorTexture( Qt3DRender::QAbstractTexture *baseColor )
76{
77 mBaseColorMapParameter->setValue( QVariant::fromValue( baseColor ) );
78 bool oldUsingBaseColorMap = mUsingBaseColorMap;
79
80 mUsingBaseColorMap = true;
81 mMetalRoughEffect->addParameter( mBaseColorMapParameter );
82 if ( mMetalRoughEffect->parameters().contains( mBaseColorParameter ) )
83 mMetalRoughEffect->removeParameter( mBaseColorParameter );
84
85 if ( oldUsingBaseColorMap != mUsingBaseColorMap )
86 updateFragmentShader();
87}
88
89void QgsMetalRoughMaterial::setMetalness( float metalness )
90{
91 mMetalnessParameter->setValue( metalness );
92 bool oldUsingMetalnessMap = mUsingMetalnessMap;
93
94 mUsingMetalnessMap = false;
95 if ( mMetalRoughEffect->parameters().contains( mMetalnessMapParameter ) )
96 mMetalRoughEffect->removeParameter( mMetalnessMapParameter );
97 mMetalRoughEffect->addParameter( mMetalnessParameter );
98
99 if ( oldUsingMetalnessMap != mUsingMetalnessMap )
100 updateFragmentShader();
101}
102
103void QgsMetalRoughMaterial::setMetalnessTexture( Qt3DRender::QAbstractTexture *metalness )
104{
105 mMetalnessMapParameter->setValue( QVariant::fromValue( metalness ) );
106 bool oldUsingMetalnessMap = mUsingMetalnessMap;
107
108 mUsingMetalnessMap = true;
109 mMetalRoughEffect->addParameter( mMetalnessMapParameter );
110 if ( mMetalRoughEffect->parameters().contains( mMetalnessParameter ) )
111 mMetalRoughEffect->removeParameter( mMetalnessParameter );
112
113 if ( oldUsingMetalnessMap != mUsingMetalnessMap )
114 updateFragmentShader();
115}
116
117void QgsMetalRoughMaterial::setRoughness( float roughness )
118{
119 mRoughnessParameter->setValue( roughness );
120 bool oldUsingRoughnessMap = mUsingRoughnessMap;
121
122 mUsingRoughnessMap = false;
123 if ( mMetalRoughEffect->parameters().contains( mRoughnessMapParameter ) )
124 mMetalRoughEffect->removeParameter( mRoughnessMapParameter );
125 mMetalRoughEffect->addParameter( mRoughnessParameter );
126
127 if ( oldUsingRoughnessMap != mUsingRoughnessMap )
128 updateFragmentShader();
129}
130
131void QgsMetalRoughMaterial::setRoughnessTexture( Qt3DRender::QAbstractTexture *roughness )
132{
133 mRoughnessMapParameter->setValue( QVariant::fromValue( roughness ) );
134 bool oldUsingRoughnessMap = mUsingRoughnessMap;
135
136 mUsingRoughnessMap = true;
137 mMetalRoughEffect->addParameter( mRoughnessMapParameter );
138 if ( mMetalRoughEffect->parameters().contains( mRoughnessParameter ) )
139 mMetalRoughEffect->removeParameter( mRoughnessParameter );
140
141 if ( oldUsingRoughnessMap != mUsingRoughnessMap )
142 updateFragmentShader();
143}
144
145void QgsMetalRoughMaterial::setAmbientOcclusionTexture( Qt3DRender::QAbstractTexture *ambientOcclusion )
146{
147 bool oldUsingAmbientOcclusionMap = mUsingAmbientOcclusionMap;
148
149 if ( ambientOcclusion )
150 {
151 mAmbientOcclusionMapParameter->setValue( QVariant::fromValue( ambientOcclusion ) );
152 mUsingAmbientOcclusionMap = true;
153 mMetalRoughEffect->addParameter( mAmbientOcclusionMapParameter );
154 }
155 else
156 {
157 mAmbientOcclusionMapParameter->setValue( QVariant() );
158 mUsingAmbientOcclusionMap = false;
159 if ( mMetalRoughEffect->parameters().contains( mAmbientOcclusionMapParameter ) )
160 mMetalRoughEffect->removeParameter( mAmbientOcclusionMapParameter );
161 }
162
163 if ( oldUsingAmbientOcclusionMap != mUsingAmbientOcclusionMap )
164 updateFragmentShader();
165}
166
167void QgsMetalRoughMaterial::setNormalTexture( Qt3DRender::QAbstractTexture *normal )
168{
169 bool oldUsingNormalMap = mUsingNormalMap;
170
171 if ( normal )
172 {
173 mNormalMapParameter->setValue( QVariant::fromValue( normal ) );
174 mUsingNormalMap = true;
175 mMetalRoughEffect->addParameter( mNormalMapParameter );
176 }
177 else
178 {
179 mNormalMapParameter->setValue( QVariant() );
180 mUsingNormalMap = false;
181 if ( mMetalRoughEffect->parameters().contains( mNormalMapParameter ) )
182 mMetalRoughEffect->removeParameter( mNormalMapParameter );
183 }
184
185 if ( oldUsingNormalMap != mUsingNormalMap )
186 updateFragmentShader();
187}
188
189void QgsMetalRoughMaterial::setHeightTexture( Qt3DRender::QAbstractTexture *height )
190{
191 bool oldUsingHeightMap = mUsingHeightMap;
192
193 if ( height )
194 {
195 mHeightMapParameter->setValue( QVariant::fromValue( height ) );
196 mUsingHeightMap = true;
197 mMetalRoughEffect->addParameter( mHeightMapParameter );
198 }
199 else
200 {
201 mHeightMapParameter->setValue( QVariant() );
202 mUsingHeightMap = false;
203 if ( mMetalRoughEffect->parameters().contains( mHeightMapParameter ) )
204 mMetalRoughEffect->removeParameter( mHeightMapParameter );
205 }
206
207 if ( oldUsingHeightMap != mUsingHeightMap )
208 updateFragmentShader();
209}
210
211void QgsMetalRoughMaterial::setParallaxScale( double scale )
212{
213 mParallaxScaleParameter->setValue( scale );
214}
215
216void QgsMetalRoughMaterial::setEmissionTexture( Qt3DRender::QAbstractTexture *emission )
217{
218 bool oldUsingEmissionMap = mUsingEmissionMap;
219
220 if ( emission )
221 {
222 mEmissionMapParameter->setValue( QVariant::fromValue( emission ) );
223 mUsingEmissionMap = true;
224 mMetalRoughEffect->addParameter( mEmissionMapParameter );
225 }
226 else
227 {
228 mEmissionMapParameter->setValue( QVariant() );
229 mUsingEmissionMap = false;
230 if ( mMetalRoughEffect->parameters().contains( mEmissionMapParameter ) )
231 mMetalRoughEffect->removeParameter( mEmissionMapParameter );
232 }
233
234 if ( oldUsingEmissionMap != mUsingEmissionMap )
235 updateFragmentShader();
236}
237
238void QgsMetalRoughMaterial::setEmissionFactor( double factor )
239{
240 mEmissionFactorParameter->setValue( factor );
241}
242
243void QgsMetalRoughMaterial::setTextureScale( float textureScale )
244{
245 mTextureScaleParameter->setValue( textureScale );
246}
247
248void QgsMetalRoughMaterial::setTextureRotation( float textureRotation )
249{
250 mTextureRotationParameter->setValue( textureRotation );
251}
252
253void QgsMetalRoughMaterial::init()
254{
255 const QByteArray vertexShaderCode = Qt3DRender::QShaderProgram::loadSource( QUrl( u"qrc:/shaders/default.vert"_s ) );
256 const QByteArray finalVertexShaderCode = Qgs3DUtils::addDefinesToShaderCode( vertexShaderCode, QStringList( { "TEXTURE_ROTATION" } ) );
257 mMetalRoughGL3Shader->setVertexShaderCode( finalVertexShaderCode );
258
259 updateFragmentShader();
260
261 mMetalRoughGL3Technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
262 mMetalRoughGL3Technique->graphicsApiFilter()->setMajorVersion( 3 );
263 mMetalRoughGL3Technique->graphicsApiFilter()->setMinorVersion( 1 );
264 mMetalRoughGL3Technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
265
266 mFilterKey->setParent( this );
267 mFilterKey->setName( u"renderingStyle"_s );
268 mFilterKey->setValue( u"forward"_s );
269
270 mMetalRoughGL3Technique->addFilterKey( mFilterKey );
271 mMetalRoughGL3RenderPass->setShaderProgram( mMetalRoughGL3Shader );
272 mMetalRoughGL3Technique->addRenderPass( mMetalRoughGL3RenderPass );
273 mMetalRoughEffect->addTechnique( mMetalRoughGL3Technique );
274
275 // Given parameters a parent
276 mBaseColorMapParameter->setParent( mMetalRoughEffect );
277 mMetalnessMapParameter->setParent( mMetalRoughEffect );
278 mRoughnessMapParameter->setParent( mMetalRoughEffect );
279 mNormalMapParameter->setParent( mMetalRoughEffect );
280 mHeightMapParameter->setParent( mMetalRoughEffect );
281 mAmbientOcclusionMapParameter->setParent( mMetalRoughEffect );
282 mEmissionMapParameter->setParent( mMetalRoughEffect );
283
284 mMetalRoughEffect->addParameter( mBaseColorParameter );
285 mMetalRoughEffect->addParameter( mMetalnessParameter );
286 mMetalRoughEffect->addParameter( mRoughnessParameter );
287 mMetalRoughEffect->addParameter( mParallaxScaleParameter );
288 mMetalRoughEffect->addParameter( mEmissionFactorParameter );
289 mMetalRoughEffect->addParameter( mTextureScaleParameter );
290 mMetalRoughEffect->addParameter( mTextureRotationParameter );
291
292 setEffect( mMetalRoughEffect );
293}
294
295void QgsMetalRoughMaterial::updateFragmentShader()
296{
297 // pre-process fragment shader and add #defines based on whether using maps for some properties
298 QByteArray fragmentShaderCode = Qt3DRender::QShaderProgram::loadSource( QUrl( u"qrc:/shaders/metalrough.frag"_s ) );
299 QStringList defines;
300 if ( mUsingBaseColorMap )
301 defines += "BASE_COLOR_MAP";
302 if ( mUsingMetalnessMap )
303 defines += "METALNESS_MAP";
304 if ( mUsingRoughnessMap )
305 defines += "ROUGHNESS_MAP";
306 if ( mUsingAmbientOcclusionMap )
307 defines += "AMBIENT_OCCLUSION_MAP";
308 if ( mUsingNormalMap )
309 defines += "NORMAL_MAP";
310 if ( mUsingHeightMap )
311 defines += "HEIGHT_MAP";
312 if ( mUsingEmissionMap )
313 defines += "EMISSION_MAP";
314
315 if ( mFlatShading )
316 defines += "FLAT_SHADING";
317
318 QByteArray finalShaderCode = Qgs3DUtils::addDefinesToShaderCode( fragmentShaderCode, defines );
319 mMetalRoughGL3Shader->setFragmentShaderCode( finalShaderCode );
320}
321
322void QgsMetalRoughMaterial::setFlatShadingEnabled( bool enabled )
323{
324 if ( enabled != mFlatShading )
325 {
326 mFlatShading = enabled;
327 updateFragmentShader();
328 }
329}
330
Miscellaneous utility functions used from 3D code.
Definition qgs3dutils.h:60
static QByteArray addDefinesToShaderCode(const QByteArray &shaderCode, const QStringList &defines)
Inserts some define macros into a shader source code.
static QColor srgbToLinear(const QColor &color)
Converts a SRGB color to a linear color.
Base class for all materials used within QGIS 3D views.
Definition qgsmaterial.h:40