1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3dpointlight_p.h"
5#include "qquick3dobject_p.h"
6
7#include <QtQuick3DRuntimeRender/private/qssgrenderlight_p.h>
8
9#include "qquick3dnode_p_p.h"
10
11QT_BEGIN_NAMESPACE
12
13/*!
14 \qmltype PointLight
15 \inherits Light
16 \inqmlmodule QtQuick3D
17 \brief Defines a point light in the scene.
18
19 The point light can be described as a sphere, emitting light with equal strength in all
20 directions from the center of the light. This is similar to the way a light bulb emits light.
21
22 Rotating or scaling a point light does not have any effect. Moving a point light will change
23 the position from where the light is emitted.
24
25 By default, a point light intensity diminishes according to inverse-square-law. However, the fade-off
26 (and range) can be controlled with the \l {constantFade}, \l {linearFade}, and
27 \l quadraticFade properties. Light attenuation is calculated using the formula:
28 \l {constantFade} + \c distance * (\l {linearFade} * 0.01) + \c distance^2 * (\l {quadraticFade} * 0.0001)
29
30 \section2 A simple example: shading a sphere in three different ways
31
32 Take a scene containing a sphere in front of a scaled up rectangle in the
33 background. The default base color of the PrincipledMaterial of the
34 rectangle is white.
35
36 Without any lights and disabling light-related shading for the two meshes,
37 we get the following:
38
39 \qml
40 import QtQuick
41 import QtQuick3D
42 View3D {
43 anchors.fill: parent
44
45 PerspectiveCamera { z: 600 }
46
47 Model {
48 source: "#Rectangle"
49 scale: Qt.vector3d(10, 10, 10)
50 z: -100
51 materials: PrincipledMaterial {
52 lighting: PrincipledMaterial.NoLighting
53 }
54 }
55
56 Model {
57 source: "#Sphere"
58 scale: Qt.vector3d(2, 2, 2)
59 materials: PrincipledMaterial {
60 lighting: PrincipledMaterial.NoLighting
61 baseColor: "#40c060"
62 roughness: 0.1
63 }
64 }
65 }
66 \endqml
67
68 \image pointlight-1.png
69
70 Adding a directional light, emitting down the Z axis by default, leads to the following:
71
72 \qml
73 import QtQuick
74 import QtQuick3D
75 View3D {
76 anchors.fill: parent
77
78 PerspectiveCamera { z: 600 }
79
80 DirectionalLight { }
81
82 Model {
83 source: "#Rectangle"
84 scale: Qt.vector3d(10, 10, 10)
85 z: -100
86 materials: PrincipledMaterial { }
87 }
88
89 Model {
90 source: "#Sphere"
91 scale: Qt.vector3d(2, 2, 2)
92 materials: PrincipledMaterial {
93 baseColor: "#40c060"
94 roughness: 0.1
95 }
96 }
97 }
98 \endqml
99
100 \image pointlight-2.png
101
102 What if we now replace DirectionalLight with:
103
104 \qml
105 PointLight {
106 z: 300
107 }
108 \endqml
109
110 The white colored PointLight here is moved on the Z axis so that it is
111 halfway between the camera and the center of the scene. Unlike
112 DirectionalLight, the rotation of the PointLight does not matter, whereas
113 its position is significant. The diminishing intensity is visible here,
114 especially on the rectangle mesh in the background.
115
116 \image pointlight-3.png
117
118 For more usage examples, see \l{Qt Quick 3D - Lights Example}.
119
120 \sa DirectionalLight, SpotLight
121*/
122
123/*!
124 \qmlproperty real PointLight::constantFade
125
126 This property is constant factor of the attenuation term of the light.
127 The default value is 1.0.
128 */
129
130/*!
131 \qmlproperty real PointLight::linearFade
132
133 This property increases the rate at which the lighting effect dims the light
134 in proportion to the distance to the light. The default value is \c 0.0, meaning the light doesn't
135 have linear fade. The value used here is multiplied by \c 0.01 before being used to
136 calculate light attenuation.
137*/
138
139/*!
140 \qmlproperty real PointLight::quadraticFade
141
142 This property increases the rate at which the lighting effect dims the light
143 in proportion to the inverse square law. The default value is 1.0 meaning the point light
144 fade exactly follows the inverse square law i.e. when distance to an object doubles the
145 light intensity decreases to 1/4th. The value used here is multiplied by \c 0.0001 before
146 being used to calculate light attenuation.
147*/
148
149QQuick3DPointLight::QQuick3DPointLight(QQuick3DNode *parent)
150 : QQuick3DAbstractLight(*(new QQuick3DNodePrivate(QQuick3DNodePrivate::Type::PointLight)), parent) {}
151
152float QQuick3DPointLight::constantFade() const
153{
154 return m_constantFade;
155}
156
157float QQuick3DPointLight::linearFade() const
158{
159 return m_linearFade;
160}
161
162float QQuick3DPointLight::quadraticFade() const
163{
164 return m_quadraticFade;
165}
166
167void QQuick3DPointLight::setConstantFade(float constantFade)
168{
169 if (qFuzzyCompare(p1: m_constantFade, p2: constantFade))
170 return;
171
172 m_constantFade = constantFade;
173 m_dirtyFlags.setFlag(flag: DirtyFlag::FadeDirty);
174 emit constantFadeChanged();
175 update();
176}
177
178void QQuick3DPointLight::setLinearFade(float linearFade)
179{
180 if (qFuzzyCompare(p1: m_linearFade, p2: linearFade))
181 return;
182
183 m_linearFade = linearFade;
184 m_dirtyFlags.setFlag(flag: DirtyFlag::FadeDirty);
185 emit linearFadeChanged();
186 update();
187}
188
189void QQuick3DPointLight::setQuadraticFade(float quadraticFade)
190{
191 if (qFuzzyCompare(p1: m_quadraticFade, p2: quadraticFade))
192 return;
193
194 m_quadraticFade = quadraticFade;
195 m_dirtyFlags.setFlag(flag: DirtyFlag::FadeDirty);
196 emit quadraticFadeChanged();
197 update();
198}
199
200QSSGRenderGraphObject *QQuick3DPointLight::updateSpatialNode(QSSGRenderGraphObject *node)
201{
202 if (!node) {
203 markAllDirty();
204 node = new QSSGRenderLight(QSSGRenderLight::Type::PointLight);
205 }
206
207 QQuick3DAbstractLight::updateSpatialNode(node); // Marks the light node dirty if m_dirtyFlags != 0
208
209 QSSGRenderLight *light = static_cast<QSSGRenderLight *>(node);
210
211 if (m_dirtyFlags.testFlag(flag: DirtyFlag::FadeDirty)) {
212 m_dirtyFlags.setFlag(flag: DirtyFlag::FadeDirty, on: false);
213 light->m_constantFade = m_constantFade;
214 light->m_linearFade = m_linearFade;
215 light->m_quadraticFade = m_quadraticFade;
216 }
217
218 return node;
219}
220
221QT_END_NAMESPACE
222

source code of qtquick3d/src/quick3d/qquick3dpointlight.cpp