1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt3D module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qnormaldiffusespecularmapmaterial.h"
41 #include "qnormaldiffusespecularmapmaterial_p.h"
42 
43 #include <Qt3DRender/qfilterkey.h>
44 #include <Qt3DRender/qmaterial.h>
45 #include <Qt3DRender/qeffect.h>
46 #include <Qt3DRender/qtexture.h>
47 #include <Qt3DRender/qtechnique.h>
48 #include <Qt3DRender/qshaderprogram.h>
49 #include <Qt3DRender/qshaderprogrambuilder.h>
50 #include <Qt3DRender/qparameter.h>
51 #include <Qt3DRender/qrenderpass.h>
52 #include <Qt3DRender/qgraphicsapifilter.h>
53 #include <QtCore/QUrl>
54 #include <QtGui/QVector3D>
55 #include <QtGui/QVector4D>
56 
57 QT_BEGIN_NAMESPACE
58 
59 using namespace Qt3DRender;
60 
61 namespace Qt3DExtras {
62 
QNormalDiffuseSpecularMapMaterialPrivate()63 QNormalDiffuseSpecularMapMaterialPrivate::QNormalDiffuseSpecularMapMaterialPrivate()
64     : QMaterialPrivate()
65     , m_normalDiffuseSpecularEffect(new QEffect())
66     , m_diffuseTexture(new QTexture2D())
67     , m_normalTexture(new QTexture2D())
68     , m_specularTexture(new QTexture2D())
69     , m_ambientParameter(new QParameter(QStringLiteral("ka"), QColor::fromRgbF(0.05f, 0.05f, 0.05f, 1.0f)))
70     , m_diffuseParameter(new QParameter(QStringLiteral("diffuseTexture"), m_diffuseTexture))
71     , m_normalParameter(new QParameter(QStringLiteral("normalTexture"), m_normalTexture))
72     , m_specularParameter(new QParameter(QStringLiteral("specularTexture"), m_specularTexture))
73     , m_shininessParameter(new QParameter(QStringLiteral("shininess"), 150.0f))
74     , m_textureScaleParameter(new QParameter(QStringLiteral("texCoordScale"), 1.0f))
75     , m_normalDiffuseSpecularGL3Technique(new QTechnique())
76     , m_normalDiffuseSpecularGL2Technique(new QTechnique())
77     , m_normalDiffuseSpecularES2Technique(new QTechnique())
78     , m_normalDiffuseSpecularRHITechnique(new QTechnique())
79     , m_normalDiffuseSpecularGL3RenderPass(new QRenderPass())
80     , m_normalDiffuseSpecularGL2RenderPass(new QRenderPass())
81     , m_normalDiffuseSpecularES2RenderPass(new QRenderPass())
82     , m_normalDiffuseSpecularRHIRenderPass(new QRenderPass())
83     , m_normalDiffuseSpecularGL3Shader(new QShaderProgram())
84     , m_normalDiffuseSpecularGL3ShaderBuilder(new QShaderProgramBuilder())
85     , m_normalDiffuseSpecularGL2ES2Shader(new QShaderProgram())
86     , m_normalDiffuseSpecularGL2ES2ShaderBuilder(new QShaderProgramBuilder())
87     , m_normalDiffuseSpecularRHIShader(new QShaderProgram())
88     , m_normalDiffuseSpecularRHIShaderBuilder(new QShaderProgramBuilder())
89     , m_filterKey(new QFilterKey)
90 {
91     m_diffuseTexture->setMagnificationFilter(QAbstractTexture::Linear);
92     m_diffuseTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
93     m_diffuseTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
94     m_diffuseTexture->setGenerateMipMaps(true);
95     m_diffuseTexture->setMaximumAnisotropy(16.0f);
96 
97     m_normalTexture->setMagnificationFilter(QAbstractTexture::Linear);
98     m_normalTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
99     m_normalTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
100     m_normalTexture->setGenerateMipMaps(true);
101     m_normalTexture->setMaximumAnisotropy(16.0f);
102 
103     m_specularTexture->setMagnificationFilter(QAbstractTexture::Linear);
104     m_specularTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
105     m_specularTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
106     m_specularTexture->setGenerateMipMaps(true);
107     m_specularTexture->setMaximumAnisotropy(16.0f);
108 }
109 
init()110 void QNormalDiffuseSpecularMapMaterialPrivate::init()
111 {
112     Q_Q(QNormalDiffuseSpecularMapMaterial);
113 
114     connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged,
115             this, &QNormalDiffuseSpecularMapMaterialPrivate::handleAmbientChanged);
116     connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged,
117             this, &QNormalDiffuseSpecularMapMaterialPrivate::handleDiffuseChanged);
118     connect(m_normalParameter, &Qt3DRender::QParameter::valueChanged,
119             this, &QNormalDiffuseSpecularMapMaterialPrivate::handleNormalChanged);
120     connect(m_specularParameter, &Qt3DRender::QParameter::valueChanged,
121             this, &QNormalDiffuseSpecularMapMaterialPrivate::handleSpecularChanged);
122     connect(m_shininessParameter, &Qt3DRender::QParameter::valueChanged,
123             this, &QNormalDiffuseSpecularMapMaterialPrivate::handleShininessChanged);
124     connect(m_textureScaleParameter, &Qt3DRender::QParameter::valueChanged,
125             this, &QNormalDiffuseSpecularMapMaterialPrivate::handleTextureScaleChanged);
126 
127     m_normalDiffuseSpecularGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/default.vert"))));
128     m_normalDiffuseSpecularGL3ShaderBuilder->setParent(q);
129     m_normalDiffuseSpecularGL3ShaderBuilder->setShaderProgram(m_normalDiffuseSpecularGL3Shader);
130     m_normalDiffuseSpecularGL3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json")));
131     m_normalDiffuseSpecularGL3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"),
132                                                                QStringLiteral("specularTexture"),
133                                                                QStringLiteral("normalTexture")});
134 
135     m_normalDiffuseSpecularGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert"))));
136     m_normalDiffuseSpecularGL2ES2ShaderBuilder->setParent(q);
137     m_normalDiffuseSpecularGL2ES2ShaderBuilder->setShaderProgram(m_normalDiffuseSpecularGL2ES2Shader);
138     m_normalDiffuseSpecularGL2ES2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json")));
139     m_normalDiffuseSpecularGL2ES2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"),
140                                                                   QStringLiteral("specularTexture"),
141                                                                   QStringLiteral("normalTexture")});
142 
143     m_normalDiffuseSpecularRHIShader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/rhi/default.vert"))));
144     m_normalDiffuseSpecularRHIShaderBuilder->setParent(q);
145     m_normalDiffuseSpecularRHIShaderBuilder->setShaderProgram(m_normalDiffuseSpecularRHIShader);
146     m_normalDiffuseSpecularRHIShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json")));
147     m_normalDiffuseSpecularRHIShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"),
148                                                                QStringLiteral("specularTexture"),
149                                                                QStringLiteral("normalTexture")});
150 
151     m_normalDiffuseSpecularGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
152     m_normalDiffuseSpecularGL3Technique->graphicsApiFilter()->setMajorVersion(3);
153     m_normalDiffuseSpecularGL3Technique->graphicsApiFilter()->setMinorVersion(1);
154     m_normalDiffuseSpecularGL3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
155 
156     m_normalDiffuseSpecularGL2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
157     m_normalDiffuseSpecularGL2Technique->graphicsApiFilter()->setMajorVersion(2);
158     m_normalDiffuseSpecularGL2Technique->graphicsApiFilter()->setMinorVersion(0);
159     m_normalDiffuseSpecularGL2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
160 
161     m_normalDiffuseSpecularES2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGLES);
162     m_normalDiffuseSpecularES2Technique->graphicsApiFilter()->setMajorVersion(2);
163     m_normalDiffuseSpecularES2Technique->graphicsApiFilter()->setMinorVersion(0);
164     m_normalDiffuseSpecularES2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
165 
166     m_normalDiffuseSpecularRHITechnique->graphicsApiFilter()->setApi(QGraphicsApiFilter::RHI);
167     m_normalDiffuseSpecularRHITechnique->graphicsApiFilter()->setMajorVersion(1);
168     m_normalDiffuseSpecularRHITechnique->graphicsApiFilter()->setMinorVersion(0);
169 
170     m_filterKey->setParent(q);
171     m_filterKey->setName(QStringLiteral("renderingStyle"));
172     m_filterKey->setValue(QStringLiteral("forward"));
173 
174     m_normalDiffuseSpecularGL3Technique->addFilterKey(m_filterKey);
175     m_normalDiffuseSpecularGL2Technique->addFilterKey(m_filterKey);
176     m_normalDiffuseSpecularES2Technique->addFilterKey(m_filterKey);
177     m_normalDiffuseSpecularRHITechnique->addFilterKey(m_filterKey);
178 
179     m_normalDiffuseSpecularGL3RenderPass->setShaderProgram(m_normalDiffuseSpecularGL3Shader);
180     m_normalDiffuseSpecularGL2RenderPass->setShaderProgram(m_normalDiffuseSpecularGL2ES2Shader);
181     m_normalDiffuseSpecularES2RenderPass->setShaderProgram(m_normalDiffuseSpecularGL2ES2Shader);
182     m_normalDiffuseSpecularRHIRenderPass->setShaderProgram(m_normalDiffuseSpecularRHIShader);
183 
184     m_normalDiffuseSpecularGL3Technique->addRenderPass(m_normalDiffuseSpecularGL3RenderPass);
185     m_normalDiffuseSpecularGL2Technique->addRenderPass(m_normalDiffuseSpecularGL2RenderPass);
186     m_normalDiffuseSpecularES2Technique->addRenderPass(m_normalDiffuseSpecularES2RenderPass);
187     m_normalDiffuseSpecularRHITechnique->addRenderPass(m_normalDiffuseSpecularRHIRenderPass);
188 
189     m_normalDiffuseSpecularEffect->addTechnique(m_normalDiffuseSpecularGL3Technique);
190     m_normalDiffuseSpecularEffect->addTechnique(m_normalDiffuseSpecularGL2Technique);
191     m_normalDiffuseSpecularEffect->addTechnique(m_normalDiffuseSpecularES2Technique);
192     m_normalDiffuseSpecularEffect->addTechnique(m_normalDiffuseSpecularRHITechnique);
193 
194     m_normalDiffuseSpecularEffect->addParameter(m_ambientParameter);
195     m_normalDiffuseSpecularEffect->addParameter(m_diffuseParameter);
196     m_normalDiffuseSpecularEffect->addParameter(m_normalParameter);
197     m_normalDiffuseSpecularEffect->addParameter(m_specularParameter);
198     m_normalDiffuseSpecularEffect->addParameter(m_shininessParameter);
199     m_normalDiffuseSpecularEffect->addParameter(m_textureScaleParameter);
200 
201     q->setEffect(m_normalDiffuseSpecularEffect);
202 }
203 
handleAmbientChanged(const QVariant & var)204 void QNormalDiffuseSpecularMapMaterialPrivate::handleAmbientChanged(const QVariant &var)
205 {
206     Q_Q(QNormalDiffuseSpecularMapMaterial);
207     emit q->ambientChanged(var.value<QColor>());
208 }
209 
handleDiffuseChanged(const QVariant & var)210 void QNormalDiffuseSpecularMapMaterialPrivate::handleDiffuseChanged(const QVariant &var)
211 {
212     Q_Q(QNormalDiffuseSpecularMapMaterial);
213     emit q->diffuseChanged(var.value<QAbstractTexture *>());
214 }
215 
handleNormalChanged(const QVariant & var)216 void QNormalDiffuseSpecularMapMaterialPrivate::handleNormalChanged(const QVariant &var)
217 {
218     Q_Q(QNormalDiffuseSpecularMapMaterial);
219     emit q->normalChanged(var.value<QAbstractTexture *>());
220 }
221 
handleSpecularChanged(const QVariant & var)222 void QNormalDiffuseSpecularMapMaterialPrivate::handleSpecularChanged(const QVariant &var)
223 {
224     Q_Q(QNormalDiffuseSpecularMapMaterial);
225     emit q->specularChanged(var.value<QAbstractTexture *>());
226 }
227 
handleShininessChanged(const QVariant & var)228 void QNormalDiffuseSpecularMapMaterialPrivate::handleShininessChanged(const QVariant &var)
229 {
230     Q_Q(QNormalDiffuseSpecularMapMaterial);
231     emit q->shininessChanged(var.toFloat());
232 }
233 
handleTextureScaleChanged(const QVariant & var)234 void QNormalDiffuseSpecularMapMaterialPrivate::handleTextureScaleChanged(const QVariant &var)
235 {
236     Q_Q(QNormalDiffuseSpecularMapMaterial);
237     emit q->textureScaleChanged(var.toFloat());
238 }
239 
240 /*!
241     \class Qt3DExtras::QNormalDiffuseSpecularMapMaterial
242     \brief The QNormalDiffuseSpecularMapMaterial provides a default implementation of the phong
243     lighting and bump effect where the diffuse and specular light components are read from texture
244     maps and the normals of the mesh being rendered from a normal texture map.
245     \inmodule Qt3DExtras
246     \since 5.7
247     \inherits Qt3DRender::QMaterial
248 
249     \deprecated
250     This class is deprecated; use QDiffuseSpecularMaterial instead.
251 
252     The specular lighting effect is based on the combination of 3 lighting components ambient,
253     diffuse and specular. The relative strengths of these components are controlled by means of
254     their reflectivity coefficients which are modelled as RGB triplets:
255 
256     \list
257     \li Ambient is the color that is emitted by an object without any other light source.
258     \li Diffuse is the color that is emitted for rought surface reflections with the lights.
259     \li Specular is the color emitted for shiny surface reflections with the lights.
260     \li The shininess of a surface is controlled by a float property.
261     \endlist
262 
263     This material uses an effect with a single render pass approach and performs per fragment
264     lighting. Techniques are provided for OpenGL 2, OpenGL 3 or above as well as OpenGL ES 2.
265 */
266 
267 /*!
268     Constructs a new QNormalDiffuseSpecularMapMaterial instance with parent object \a parent.
269 */
QNormalDiffuseSpecularMapMaterial(QNode * parent)270 QNormalDiffuseSpecularMapMaterial::QNormalDiffuseSpecularMapMaterial(QNode *parent)
271     : QMaterial(*new QNormalDiffuseSpecularMapMaterialPrivate, parent)
272 {
273     Q_D(QNormalDiffuseSpecularMapMaterial);
274     d->init();
275 }
276 
277 /*! \internal */
QNormalDiffuseSpecularMapMaterial(QNormalDiffuseSpecularMapMaterialPrivate & dd,QNode * parent)278 QNormalDiffuseSpecularMapMaterial::QNormalDiffuseSpecularMapMaterial(QNormalDiffuseSpecularMapMaterialPrivate &dd, QNode *parent)
279     : QMaterial(dd, parent)
280 {
281     Q_D(QNormalDiffuseSpecularMapMaterial);
282     d->init();
283 }
284 
285 /*!
286     Destroys the QNormalDiffuseSpecularMapMaterial instance.
287 */
~QNormalDiffuseSpecularMapMaterial()288 QNormalDiffuseSpecularMapMaterial::~QNormalDiffuseSpecularMapMaterial()
289 {
290 }
291 
292 /*!
293     \property QNormalDiffuseSpecularMapMaterial::ambient
294 
295     Holds the current ambient color.
296 */
ambient() const297 QColor QNormalDiffuseSpecularMapMaterial::ambient() const
298 {
299     Q_D(const QNormalDiffuseSpecularMapMaterial);
300     return d->m_ambientParameter->value().value<QColor>();
301 }
302 
303 /*!
304     \property QNormalDiffuseSpecularMapMaterial::diffuse
305 
306     Holds the current diffuse map texture.
307 
308     By default, the diffuse texture has the following properties:
309 
310     \list
311         \li Linear minification and magnification filters
312         \li Linear mipmap with mipmapping enabled
313         \li Repeat wrap mode
314         \li Maximum anisotropy of 16.0
315     \endlist
316 */
diffuse() const317 QAbstractTexture *QNormalDiffuseSpecularMapMaterial::diffuse() const
318 {
319     Q_D(const QNormalDiffuseSpecularMapMaterial);
320     return d->m_diffuseParameter->value().value<QAbstractTexture *>();
321 }
322 
323 /*!
324     \property QNormalDiffuseSpecularMapMaterial::normal
325 
326     Holds the current normal map texture.
327 
328     By default, the normal texture has the following properties:
329 
330     \list
331         \li Linear minification and magnification filters
332         \li Repeat wrap mode
333         \li Maximum anisotropy of 16.0
334     \endlist
335 */
normal() const336 QAbstractTexture *QNormalDiffuseSpecularMapMaterial::normal() const
337 {
338     Q_D(const QNormalDiffuseSpecularMapMaterial);
339     return d->m_normalParameter->value().value<QAbstractTexture *>();
340 }
341 
342 /*!
343     \property QNormalDiffuseSpecularMapMaterial::specular
344 
345     Holds the current specular map texture.
346 
347     By default, the specular texture has the following properties:
348 
349     \list
350         \li Linear minification and magnification filters
351         \li Linear mipmap with mipmapping enabled
352         \li Repeat wrap mode
353         \li Maximum anisotropy of 16.0
354     \endlist
355 */
specular() const356 QAbstractTexture *QNormalDiffuseSpecularMapMaterial::specular() const
357 {
358     Q_D(const QNormalDiffuseSpecularMapMaterial);
359     return d->m_specularParameter->value().value<QAbstractTexture *>();
360 }
361 
362 /*!
363     \property QNormalDiffuseSpecularMapMaterial::shininess
364 
365     Holds the current shininess as a float value.
366 */
shininess() const367 float QNormalDiffuseSpecularMapMaterial::shininess() const
368 {
369     Q_D(const QNormalDiffuseSpecularMapMaterial);
370     return d->m_shininessParameter->value().toFloat();
371 }
372 
373 /*!
374     \property QNormalDiffuseSpecularMapMaterial::textureScale
375 
376     Holds the current texture scale. It is applied as a multiplier to texture
377     coordinates at render time. Defaults to 1.0.
378 
379     When used in conjunction with QTextureWrapMode::Repeat, textureScale provides a simple
380     way to tile a texture across a surface. For example, a texture scale of \c 4.0
381     would result in 16 (4x4) tiles.
382 */
textureScale() const383 float QNormalDiffuseSpecularMapMaterial::textureScale() const
384 {
385     Q_D(const QNormalDiffuseSpecularMapMaterial);
386     return d->m_textureScaleParameter->value().toFloat();
387 }
388 
setAmbient(const QColor & ambient)389 void QNormalDiffuseSpecularMapMaterial::setAmbient(const QColor &ambient)
390 {
391     Q_D(QNormalDiffuseSpecularMapMaterial);
392     d->m_ambientParameter->setValue(ambient);
393 }
394 
setDiffuse(QAbstractTexture * diffuse)395 void QNormalDiffuseSpecularMapMaterial::setDiffuse(QAbstractTexture *diffuse)
396 {
397     Q_D(QNormalDiffuseSpecularMapMaterial);
398     d->m_diffuseParameter->setValue(QVariant::fromValue(diffuse));
399 }
400 
setNormal(QAbstractTexture * normal)401 void QNormalDiffuseSpecularMapMaterial::setNormal(QAbstractTexture *normal)
402 {
403     Q_D(QNormalDiffuseSpecularMapMaterial);
404     d->m_normalParameter->setValue(QVariant::fromValue(normal));
405 }
406 
setSpecular(QAbstractTexture * specular)407 void QNormalDiffuseSpecularMapMaterial::setSpecular(QAbstractTexture *specular)
408 {
409     Q_D(QNormalDiffuseSpecularMapMaterial);
410     d->m_specularParameter->setValue(QVariant::fromValue(specular));
411 }
412 
setShininess(float shininess)413 void QNormalDiffuseSpecularMapMaterial::setShininess(float shininess)
414 {
415     Q_D(QNormalDiffuseSpecularMapMaterial);
416     d->m_shininessParameter->setValue(shininess);
417 }
418 
setTextureScale(float textureScale)419 void QNormalDiffuseSpecularMapMaterial::setTextureScale(float textureScale)
420 {
421     Q_D(QNormalDiffuseSpecularMapMaterial);
422     d->m_textureScaleParameter->setValue(textureScale);
423 }
424 
425 } // namespace Qt3DExtras
426 
427 QT_END_NAMESPACE
428