17#include <Qt3DRender/QParameter>
18#include <Qt3DRender/QRenderPass>
19#include <Qt3DRender/QTechnique>
20#include <Qt3DRender/QTexture>
21#include <Qt3DRender/QAbstractTexture>
22#include <Qt3DRender/QEffect>
23#include <Qt3DRender/QShaderProgramBuilder>
24#include <Qt3DRender/QGraphicsApiFilter>
27QgsMetalRoughMaterial::QgsMetalRoughMaterial( QNode *parent )
29 , mBaseColorParameter( new
Qt3DRender::QParameter( QStringLiteral(
"baseColor" ), QColor(
"grey" ), this ) )
30 , mMetalnessParameter( new
Qt3DRender::QParameter( QStringLiteral(
"metalness" ), 0.0f, this ) )
31 , mRoughnessParameter( new
Qt3DRender::QParameter( QStringLiteral(
"roughness" ), 0.0f, this ) )
32 , mBaseColorMapParameter( new
Qt3DRender::QParameter( QStringLiteral(
"baseColorMap" ), QVariant(), this ) )
33 , mMetalnessMapParameter( new
Qt3DRender::QParameter( QStringLiteral(
"metalnessMap" ), QVariant(), this ) )
34 , mRoughnessMapParameter( new
Qt3DRender::QParameter( QStringLiteral(
"roughnessMap" ), QVariant(), this ) )
35 , mAmbientOcclusionMapParameter( new
Qt3DRender::QParameter( QStringLiteral(
"ambientOcclusionMap" ), QVariant(), this ) )
36 , mNormalMapParameter( new
Qt3DRender::QParameter( QStringLiteral(
"normalMap" ), QVariant(), this ) )
37 , mTextureScaleParameter( new
Qt3DRender::QParameter( QStringLiteral(
"texCoordScale" ), 1.0f, this ) )
38 , mMetalRoughEffect( new
Qt3DRender::QEffect( this ) )
39 , mMetalRoughGL3Technique( new
Qt3DRender::QTechnique( this ) )
40 , mMetalRoughGL3RenderPass( new
Qt3DRender::QRenderPass( this ) )
41 , mMetalRoughGL3Shader( new
Qt3DRender::QShaderProgram( this ) )
42 , mFilterKey( new
Qt3DRender::QFilterKey( this ) )
47QgsMetalRoughMaterial::~QgsMetalRoughMaterial() =
default;
49QVariant QgsMetalRoughMaterial::baseColor()
const
51 return mBaseColorParameter->value();
54QVariant QgsMetalRoughMaterial::metalness()
const
56 return mMetalnessParameter->value();
59QVariant QgsMetalRoughMaterial::roughness()
const
61 return mRoughnessParameter->value();
64QVariant QgsMetalRoughMaterial::ambientOcclusion()
const
66 return mAmbientOcclusionMapParameter->value();
69QVariant QgsMetalRoughMaterial::normal()
const
71 return mNormalMapParameter->value();
74float QgsMetalRoughMaterial::textureScale()
const
76 return mTextureScaleParameter->value().toFloat();
79void QgsMetalRoughMaterial::setBaseColor(
const QVariant &baseColor )
81 mBaseColorParameter->setValue( baseColor );
82 mBaseColorMapParameter->setValue( baseColor );
83 bool oldUsingBaseColorMap = mUsingBaseColorMap;
85 if ( baseColor.value<Qt3DRender::QAbstractTexture *>() )
87 mUsingBaseColorMap =
true;
88 mMetalRoughEffect->addParameter( mBaseColorMapParameter );
89 if ( mMetalRoughEffect->parameters().contains( mBaseColorParameter ) )
90 mMetalRoughEffect->removeParameter( mBaseColorParameter );
94 mUsingBaseColorMap =
false;
95 if ( mMetalRoughEffect->parameters().contains( mBaseColorMapParameter ) )
96 mMetalRoughEffect->removeParameter( mBaseColorMapParameter );
97 mMetalRoughEffect->addParameter( mBaseColorParameter );
100 if ( oldUsingBaseColorMap != mUsingBaseColorMap )
101 updateFragmentShader();
104void QgsMetalRoughMaterial::setMetalness(
const QVariant &metalness )
106 mMetalnessParameter->setValue( metalness );
107 mMetalnessMapParameter->setValue( metalness );
108 bool oldUsingMetalnessMap = mUsingMetalnessMap;
110 if ( metalness.value<Qt3DRender::QAbstractTexture *>() )
112 mUsingMetalnessMap =
true;
113 mMetalRoughEffect->addParameter( mMetalnessMapParameter );
114 if ( mMetalRoughEffect->parameters().contains( mMetalnessParameter ) )
115 mMetalRoughEffect->removeParameter( mMetalnessParameter );
119 mUsingMetalnessMap =
false;
120 if ( mMetalRoughEffect->parameters().contains( mMetalnessMapParameter ) )
121 mMetalRoughEffect->removeParameter( mMetalnessMapParameter );
122 mMetalRoughEffect->addParameter( mMetalnessParameter );
125 if ( oldUsingMetalnessMap != mUsingMetalnessMap )
126 updateFragmentShader();
129void QgsMetalRoughMaterial::setRoughness(
const QVariant &roughness )
131 mRoughnessParameter->setValue( roughness );
132 mRoughnessMapParameter->setValue( roughness );
133 bool oldUsingRoughnessMap = mUsingRoughnessMap;
135 if ( roughness.value<Qt3DRender::QAbstractTexture *>() )
137 mUsingRoughnessMap =
true;
138 mMetalRoughEffect->addParameter( mRoughnessMapParameter );
139 if ( mMetalRoughEffect->parameters().contains( mRoughnessParameter ) )
140 mMetalRoughEffect->removeParameter( mRoughnessParameter );
144 mUsingRoughnessMap =
false;
145 if ( mMetalRoughEffect->parameters().contains( mRoughnessMapParameter ) )
146 mMetalRoughEffect->removeParameter( mRoughnessMapParameter );
147 mMetalRoughEffect->addParameter( mRoughnessParameter );
150 if ( oldUsingRoughnessMap != mUsingRoughnessMap )
151 updateFragmentShader();
154void QgsMetalRoughMaterial::setAmbientOcclusion(
const QVariant &ambientOcclusion )
156 mAmbientOcclusionMapParameter->setValue( ambientOcclusion );
157 bool oldUsingAmbientOcclusionMap = mUsingAmbientOcclusionMap;
159 if ( ambientOcclusion.value<Qt3DRender::QAbstractTexture *>() )
161 mUsingAmbientOcclusionMap =
true;
162 mMetalRoughEffect->addParameter( mAmbientOcclusionMapParameter );
166 mUsingAmbientOcclusionMap =
false;
167 if ( mMetalRoughEffect->parameters().contains( mAmbientOcclusionMapParameter ) )
168 mMetalRoughEffect->removeParameter( mAmbientOcclusionMapParameter );
171 if ( oldUsingAmbientOcclusionMap != mUsingAmbientOcclusionMap )
172 updateFragmentShader();
175void QgsMetalRoughMaterial::setNormal(
const QVariant &normal )
177 mNormalMapParameter->setValue( normal );
178 bool oldUsingNormalMap = mUsingNormalMap;
180 if ( normal.value<Qt3DRender::QAbstractTexture *>() )
182 mUsingNormalMap =
true;
183 mMetalRoughEffect->addParameter( mNormalMapParameter );
187 mUsingNormalMap =
false;
188 if ( mMetalRoughEffect->parameters().contains( mNormalMapParameter ) )
189 mMetalRoughEffect->removeParameter( mNormalMapParameter );
192 if ( oldUsingNormalMap != mUsingNormalMap )
193 updateFragmentShader();
196void QgsMetalRoughMaterial::setTextureScale(
float textureScale )
198 mTextureScaleParameter->setValue( textureScale );
201QByteArray addDefinesToShaderCode(
const QByteArray &shaderCode,
const QStringList &defines )
207 QStringList defineLines;
208 for (
const QString &define : defines )
209 defineLines +=
"#define " + define +
"\n";
211 QString definesText = defineLines.join( QString() );
213 QByteArray newShaderCode = shaderCode;
214 int versionIndex = shaderCode.indexOf(
"#version " );
215 int insertionIndex = versionIndex == -1 ? 0 : shaderCode.indexOf(
'\n', versionIndex + 1 ) + 1;
216 newShaderCode.insert( insertionIndex, definesText.toLatin1() );
217 return newShaderCode;
220void QgsMetalRoughMaterial::init()
222 QObject::connect( mBaseColorParameter, &Qt3DRender::QParameter::valueChanged,
223 this, &QgsMetalRoughMaterial::baseColorChanged );
224 QObject::connect( mMetalnessParameter, &Qt3DRender::QParameter::valueChanged,
225 this, &QgsMetalRoughMaterial::metalnessChanged );
226 QObject::connect( mRoughnessParameter, &Qt3DRender::QParameter::valueChanged,
227 this, &QgsMetalRoughMaterial::roughnessChanged );
228 QObject::connect( mAmbientOcclusionMapParameter, &Qt3DRender::QParameter::valueChanged,
229 this, &QgsMetalRoughMaterial::ambientOcclusionChanged );
230 QObject::connect( mNormalMapParameter, &Qt3DRender::QParameter::valueChanged,
231 this, &QgsMetalRoughMaterial::normalChanged );
232 connect( mTextureScaleParameter, &Qt3DRender::QParameter::valueChanged,
233 this, &QgsMetalRoughMaterial::handleTextureScaleChanged );
235 mMetalRoughGL3Shader->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/default.vert" ) ) ) );
237 updateFragmentShader();
239 mMetalRoughGL3Technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
240 mMetalRoughGL3Technique->graphicsApiFilter()->setMajorVersion( 3 );
241 mMetalRoughGL3Technique->graphicsApiFilter()->setMinorVersion( 1 );
242 mMetalRoughGL3Technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
244 mFilterKey->setParent(
this );
245 mFilterKey->setName( QStringLiteral(
"renderingStyle" ) );
246 mFilterKey->setValue( QStringLiteral(
"forward" ) );
248 mMetalRoughGL3Technique->addFilterKey( mFilterKey );
249 mMetalRoughGL3RenderPass->setShaderProgram( mMetalRoughGL3Shader );
250 mMetalRoughGL3Technique->addRenderPass( mMetalRoughGL3RenderPass );
251 mMetalRoughEffect->addTechnique( mMetalRoughGL3Technique );
254 mBaseColorMapParameter->setParent( mMetalRoughEffect );
255 mMetalnessMapParameter->setParent( mMetalRoughEffect );
256 mRoughnessMapParameter->setParent( mMetalRoughEffect );
258 mMetalRoughEffect->addParameter( mBaseColorParameter );
259 mMetalRoughEffect->addParameter( mMetalnessParameter );
260 mMetalRoughEffect->addParameter( mRoughnessParameter );
261 mMetalRoughEffect->addParameter( mTextureScaleParameter );
263 setEffect( mMetalRoughEffect );
266void QgsMetalRoughMaterial::updateFragmentShader()
269 QByteArray fragmentShaderCode = Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/metalrough.frag" ) ) );
271 if ( mUsingBaseColorMap )
272 defines +=
"BASE_COLOR_MAP";
273 if ( mUsingMetalnessMap )
274 defines +=
"METALNESS_MAP";
275 if ( mUsingRoughnessMap )
276 defines +=
"ROUGHNESS_MAP";
277 if ( mUsingAmbientOcclusionMap )
278 defines +=
"AMBIENT_OCCLUSION_MAP";
279 if ( mUsingNormalMap )
280 defines +=
"NORMAL_MAP";
283 defines +=
"FLAT_SHADING";
285 QByteArray finalShaderCode = addDefinesToShaderCode( fragmentShaderCode, defines );
286 mMetalRoughGL3Shader->setFragmentShaderCode( finalShaderCode );
289void QgsMetalRoughMaterial::handleTextureScaleChanged(
const QVariant &var )
291 emit textureScaleChanged( var.toFloat() );
294bool QgsMetalRoughMaterial::flatShadingEnabled()
const
299void QgsMetalRoughMaterial::setFlatShadingEnabled(
bool enabled )
301 if ( enabled != mFlatShading )
303 mFlatShading = enabled;
304 updateFragmentShader();