1/****************************************************************************
2**
3** Copyright (C) 2017 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 "qenvironmentlight.h"
41#include "qenvironmentlight_p.h"
42#include "qabstracttexture.h"
43#include <QVector3D>
44
45#include <cmath>
46
47QT_BEGIN_NAMESPACE
48
49namespace Qt3DRender
50{
51
52/*!
53 * \qmltype EnvironmentLight
54 * \inqmlmodule Qt3D.Render
55 * \instantiates Qt3DRender::QEnvironmentLight
56 * \brief Encapsulate an environment light object in a Qt 3D scene.
57 * \since 5.9
58 *
59 * EnvironmentLight uses cubemaps to implement image-based lighting (IBL), a technique
60 * often used in conjunction with physically-based rendering (PBR). The cubemaps are
61 * typically expected be based on high dynamic range (HDR) images, with a suitable
62 * OpenGL format (such as RGBA16F) that can handle the increased range of values.
63 *
64 * There are a variety of tools that can be used to produce the cubemaps needed by
65 * EnvironmentLight. Some examples include
66 *
67 * \list
68 * \li \l {https://github.com/dariomanesku/cmftStudio}{cmftStudio}
69 * \li \l {https://github.com/derkreature/IBLBaker}{IBLBaker}
70 * \li \l {https://www.knaldtech.com/lys/}{Lys}
71 * \endlist
72 *
73 * \l {https://hdrihaven.com/hdris/}{HDRI Haven} provides many CC0-licensed HDR images
74 * that can be used as source material for the above tools.
75 */
76
77QEnvironmentLightPrivate::QEnvironmentLightPrivate()
78 : m_shaderData(new QShaderData)
79 , m_irradiance(nullptr)
80 , m_specular(nullptr)
81{
82}
83
84QEnvironmentLightPrivate::~QEnvironmentLightPrivate()
85{
86}
87
88void QEnvironmentLightPrivate::_q_updateEnvMapsSize()
89{
90 QVector3D irradianceSize;
91 if (m_irradiance != nullptr)
92 irradianceSize = QVector3D(m_irradiance->width(),
93 m_irradiance->height(),
94 m_irradiance->depth());
95 m_shaderData->setProperty(name: "irradianceSize", value: QVariant::fromValue(value: irradianceSize));
96
97 QVector3D specularSize;
98 if (m_specular != nullptr)
99 specularSize = QVector3D(m_specular->width(),
100 m_specular->height(),
101 m_specular->depth());
102 m_shaderData->setProperty(name: "specularSize", value: QVariant::fromValue(value: specularSize));
103
104 const int levels = int(std::log2(x: specularSize.x() > 0.0f ? specularSize.x() : 1.0f)) + 1;
105 m_shaderData->setProperty(name: "specularMipLevels", value: QVariant::fromValue(value: levels));
106}
107
108Qt3DCore::QNodeCreatedChangeBasePtr QEnvironmentLight::createNodeCreationChange() const
109{
110 auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QEnvironmentLightData>::create(arguments: this);
111 auto &data = creationChange->data;
112 Q_D(const QEnvironmentLight);
113 data.shaderDataId = qIdForNode(node: d->m_shaderData);
114 return creationChange;
115}
116
117/*!
118 \class Qt3DRender::QEnvironmentLight
119 \inmodule Qt3DRender
120 \brief Encapsulate an environment light object in a Qt 3D scene.
121 \since 5.9
122
123 QEnvironmentLight uses cubemaps to implement image-based lighting (IBL), a technique
124 often used in conjunction with physically-based rendering (PBR). The cubemaps are
125 typically expected be based on high dynamic range (HDR) images, with a suitable
126 OpenGL format (such as RGBA16F) that can handle the increased range of values.
127
128 There are a variety of tools that can be used to produce the cubemaps needed by
129 QEnvironmentLight. Some examples include
130
131 \list
132 \li \l {https://github.com/dariomanesku/cmftStudio}{cmftStudio}
133 \li \l {https://github.com/derkreature/IBLBaker}{IBLBaker}
134 \li \l {https://www.knaldtech.com/lys/}{Lys}
135 \endlist
136
137 \l {https://hdrihaven.com/hdris/}{HDRI Haven} provides many CC0-licensed HDR images
138 that can be used as source material for the above tools.
139*/
140
141QEnvironmentLight::QEnvironmentLight(Qt3DCore::QNode *parent)
142 : QComponent(*new QEnvironmentLightPrivate, parent)
143{
144 Q_D(QEnvironmentLight);
145 d->m_shaderData->setParent(this);
146}
147
148/*! \internal */
149QEnvironmentLight::QEnvironmentLight(QEnvironmentLightPrivate &dd, QNode *parent)
150 : QComponent(dd, parent)
151{
152 Q_D(QEnvironmentLight);
153 d->m_shaderData->setParent(this);
154}
155
156QEnvironmentLight::~QEnvironmentLight()
157{
158}
159
160/*!
161 \qmlproperty Texture EnvironmentLight::irradiance
162
163 Holds the current environment irradiance map texture.
164
165 By default, the environment irradiance texture is null.
166
167 \note The exact meaning and use of this property is up to the
168 material implementation.
169*/
170
171/*!
172 \property QEnvironmentLight::irradiance
173
174 Holds the current environment irradiance map texture.
175
176 By default, the environment irradiance texture is null.
177
178 \note The exact meaning and use of this property is up to the
179 material implementation.
180*/
181QAbstractTexture *QEnvironmentLight::irradiance() const
182{
183 Q_D(const QEnvironmentLight);
184 return d->m_irradiance;
185}
186
187/*!
188 \qmlproperty Texture EnvironmentLight::specular
189
190 Holds the current environment specular map texture.
191
192 By default, the environment specular texture is null.
193
194 \note The exact meaning and use of this property is up to the
195 material implementation.
196*/
197
198/*!
199 \property QEnvironmentLight::specular
200
201 Holds the current environment specular map texture.
202
203 By default, the environment specular texture is null.
204
205 \note The exact meaning and use of this property is up to the
206 material implementation.
207*/
208QAbstractTexture *QEnvironmentLight::specular() const
209{
210 Q_D(const QEnvironmentLight);
211 return d->m_specular;
212}
213
214void QEnvironmentLight::setIrradiance(QAbstractTexture *i)
215{
216 Q_D(QEnvironmentLight);
217 if (irradiance() == i)
218 return;
219
220 if (irradiance()) {
221 d->unregisterDestructionHelper(node: d->m_irradiance);
222 QObject::disconnect(sender: d->m_irradiance, SIGNAL(widthChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
223 QObject::disconnect(sender: d->m_irradiance, SIGNAL(heightChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
224 QObject::disconnect(sender: d->m_irradiance, SIGNAL(depthChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
225 }
226
227 if (i && !i->parent())
228 i->setParent(this);
229
230 d->m_irradiance = i;
231 d->m_shaderData->setProperty(name: "irradiance", value: QVariant::fromValue(value: i));
232 d->_q_updateEnvMapsSize();
233
234 if (i) {
235 d->registerDestructionHelper(node: i, func: &QEnvironmentLight::setIrradiance, i);
236 QObject::connect(sender: d->m_irradiance, SIGNAL(widthChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
237 QObject::connect(sender: d->m_irradiance, SIGNAL(heightChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
238 QObject::connect(sender: d->m_irradiance, SIGNAL(depthChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
239 }
240
241 emit irradianceChanged(environmentIrradiance: i);
242}
243
244void QEnvironmentLight::setSpecular(QAbstractTexture *s)
245{
246 Q_D(QEnvironmentLight);
247 if (specular() == s)
248 return;
249
250 if (specular()) {
251 d->unregisterDestructionHelper(node: d->m_specular);
252 QObject::disconnect(sender: d->m_specular, SIGNAL(widthChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
253 QObject::disconnect(sender: d->m_specular, SIGNAL(heightChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
254 QObject::disconnect(sender: d->m_specular, SIGNAL(depthChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
255 }
256
257 if (s && !s->parent())
258 s->setParent(this);
259
260 d->m_specular = s;
261 d->m_shaderData->setProperty(name: "specular", value: QVariant::fromValue(value: s));
262 d->_q_updateEnvMapsSize();
263
264 if (s) {
265 d->registerDestructionHelper(node: s, func: &QEnvironmentLight::setSpecular, s);
266 QObject::connect(sender: d->m_specular, SIGNAL(widthChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
267 QObject::connect(sender: d->m_specular, SIGNAL(heightChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
268 QObject::connect(sender: d->m_specular, SIGNAL(depthChanged(int)), receiver: this, SLOT(_q_updateEnvMapsSize()));
269 }
270
271 emit specularChanged(environmentSpecular: s);
272}
273
274} // namespace Qt3DRender
275
276QT_END_NAMESPACE
277
278#include "moc_qenvironmentlight.cpp"
279

source code of qt3d/src/render/lights/qenvironmentlight.cpp