1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 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 "qgoochmaterial.h" |
41 | #include "qgoochmaterial_p.h" |
42 | |
43 | #include <Qt3DRender/qfilterkey.h> |
44 | #include <Qt3DRender/qeffect.h> |
45 | #include <Qt3DRender/qgraphicsapifilter.h> |
46 | #include <Qt3DRender/qparameter.h> |
47 | #include <Qt3DRender/qrenderpass.h> |
48 | #include <Qt3DRender/qtechnique.h> |
49 | #include <QtCore/qurl.h> |
50 | |
51 | QT_BEGIN_NAMESPACE |
52 | |
53 | namespace Qt3DExtras { |
54 | |
55 | QGoochMaterialPrivate::() |
56 | : QMaterialPrivate() |
57 | , m_effect(new Qt3DRender::QEffect) |
58 | , m_diffuseParameter(new Qt3DRender::QParameter(QStringLiteral("kd" ), QColor::fromRgbF(r: 0.0f, g: 0.0f, b: 0.0f))) |
59 | , m_specularParameter(new Qt3DRender::QParameter(QStringLiteral("ks" ), QColor::fromRgbF(r: 0.0f, g: 0.0f, b: 0.0f))) |
60 | , m_coolParameter(new Qt3DRender::QParameter(QStringLiteral("kblue" ), QColor::fromRgbF(r: 0.0f, g: 0.0f, b: 0.4f))) |
61 | , m_warmParameter(new Qt3DRender::QParameter(QStringLiteral("kyellow" ), QColor::fromRgbF(r: 0.4f, g: 0.4f, b: 0.0f))) |
62 | , m_alphaParameter(new Qt3DRender::QParameter(QStringLiteral("alpha" ), 0.25f)) |
63 | , m_betaParameter(new Qt3DRender::QParameter(QStringLiteral("beta" ), 0.5f)) |
64 | , m_shininessParameter(new Qt3DRender::QParameter(QStringLiteral("shininess" ), 100.0f)) |
65 | , m_gl3Technique(new Qt3DRender::QTechnique) |
66 | , m_gl2Technique(new Qt3DRender::QTechnique) |
67 | , m_es2Technique(new Qt3DRender::QTechnique) |
68 | , m_rhiTechnique(new Qt3DRender::QTechnique) |
69 | , m_gl3RenderPass(new Qt3DRender::QRenderPass) |
70 | , m_gl2RenderPass(new Qt3DRender::QRenderPass) |
71 | , m_es2RenderPass(new Qt3DRender::QRenderPass) |
72 | , m_rhiRenderPass(new Qt3DRender::QRenderPass) |
73 | , m_gl3Shader(new Qt3DRender::QShaderProgram) |
74 | , m_gl2ES2Shader(new Qt3DRender::QShaderProgram) |
75 | , m_rhiShader(new Qt3DRender::QShaderProgram) |
76 | , m_filterKey(new Qt3DRender::QFilterKey) |
77 | { |
78 | } |
79 | |
80 | void QGoochMaterialPrivate::() |
81 | { |
82 | Q_Q(QGoochMaterial); |
83 | |
84 | connect(sender: m_diffuseParameter, signal: &Qt3DRender::QParameter::valueChanged, |
85 | receiverPrivate: this, slot: &QGoochMaterialPrivate::handleDiffuseChanged); |
86 | connect(sender: m_specularParameter, signal: &Qt3DRender::QParameter::valueChanged, |
87 | receiverPrivate: this, slot: &QGoochMaterialPrivate::handleSpecularChanged); |
88 | connect(sender: m_coolParameter, signal: &Qt3DRender::QParameter::valueChanged, |
89 | receiverPrivate: this, slot: &QGoochMaterialPrivate::handleCoolChanged); |
90 | connect(sender: m_warmParameter, signal: &Qt3DRender::QParameter::valueChanged, |
91 | receiverPrivate: this, slot: &QGoochMaterialPrivate::handleWarmChanged); |
92 | connect(sender: m_alphaParameter, signal: &Qt3DRender::QParameter::valueChanged, |
93 | receiverPrivate: this, slot: &QGoochMaterialPrivate::handleAlphaChanged); |
94 | connect(sender: m_betaParameter, signal: &Qt3DRender::QParameter::valueChanged, |
95 | receiverPrivate: this, slot: &QGoochMaterialPrivate::handleBetaChanged); |
96 | connect(sender: m_shininessParameter, signal: &Qt3DRender::QParameter::valueChanged, |
97 | receiverPrivate: this, slot: &QGoochMaterialPrivate::handleShininessChanged); |
98 | |
99 | m_gl3Shader->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(sourceUrl: QUrl(QStringLiteral("qrc:/shaders/gl3/gooch.vert" )))); |
100 | m_gl3Shader->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(sourceUrl: QUrl(QStringLiteral("qrc:/shaders/gl3/gooch.frag" )))); |
101 | m_gl2ES2Shader->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(sourceUrl: QUrl(QStringLiteral("qrc:/shaders/es2/gooch.vert" )))); |
102 | m_gl2ES2Shader->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(sourceUrl: QUrl(QStringLiteral("qrc:/shaders/es2/gooch.frag" )))); |
103 | m_rhiShader->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(sourceUrl: QUrl(QStringLiteral("qrc:/shaders/rhi/gooch.vert" )))); |
104 | m_rhiShader->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(sourceUrl: QUrl(QStringLiteral("qrc:/shaders/rhi/gooch.frag" )))); |
105 | |
106 | m_gl3Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); |
107 | m_gl3Technique->graphicsApiFilter()->setMajorVersion(3); |
108 | m_gl3Technique->graphicsApiFilter()->setMinorVersion(1); |
109 | m_gl3Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); |
110 | |
111 | m_gl2Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); |
112 | m_gl2Technique->graphicsApiFilter()->setMajorVersion(2); |
113 | m_gl2Technique->graphicsApiFilter()->setMinorVersion(0); |
114 | m_gl2Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); |
115 | |
116 | m_es2Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGLES); |
117 | m_es2Technique->graphicsApiFilter()->setMajorVersion(2); |
118 | m_es2Technique->graphicsApiFilter()->setMinorVersion(0); |
119 | m_es2Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); |
120 | |
121 | m_rhiTechnique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::RHI); |
122 | m_rhiTechnique->graphicsApiFilter()->setMajorVersion(1); |
123 | m_rhiTechnique->graphicsApiFilter()->setMinorVersion(0); |
124 | m_rhiTechnique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); |
125 | |
126 | m_filterKey->setParent(q); |
127 | m_filterKey->setName(QStringLiteral("renderingStyle" )); |
128 | m_filterKey->setValue(QStringLiteral("forward" )); |
129 | |
130 | m_gl3Technique->addFilterKey(filterKey: m_filterKey); |
131 | m_gl2Technique->addFilterKey(filterKey: m_filterKey); |
132 | m_es2Technique->addFilterKey(filterKey: m_filterKey); |
133 | m_rhiTechnique->addFilterKey(filterKey: m_filterKey); |
134 | |
135 | m_gl3RenderPass->setShaderProgram(m_gl3Shader); |
136 | m_gl2RenderPass->setShaderProgram(m_gl2ES2Shader); |
137 | m_es2RenderPass->setShaderProgram(m_gl2ES2Shader); |
138 | m_rhiRenderPass->setShaderProgram(m_rhiShader); |
139 | |
140 | m_gl3Technique->addRenderPass(pass: m_gl3RenderPass); |
141 | m_gl2Technique->addRenderPass(pass: m_gl2RenderPass); |
142 | m_es2Technique->addRenderPass(pass: m_es2RenderPass); |
143 | m_rhiTechnique->addRenderPass(pass: m_rhiRenderPass); |
144 | |
145 | m_effect->addTechnique(t: m_gl3Technique); |
146 | m_effect->addTechnique(t: m_gl2Technique); |
147 | m_effect->addTechnique(t: m_es2Technique); |
148 | m_effect->addTechnique(t: m_rhiTechnique); |
149 | |
150 | m_effect->addParameter(parameter: m_diffuseParameter); |
151 | m_effect->addParameter(parameter: m_specularParameter); |
152 | m_effect->addParameter(parameter: m_coolParameter); |
153 | m_effect->addParameter(parameter: m_warmParameter); |
154 | m_effect->addParameter(parameter: m_alphaParameter); |
155 | m_effect->addParameter(parameter: m_betaParameter); |
156 | m_effect->addParameter(parameter: m_shininessParameter); |
157 | |
158 | q->setEffect(m_effect); |
159 | } |
160 | |
161 | void QGoochMaterialPrivate::handleDiffuseChanged(const QVariant &var) |
162 | { |
163 | Q_Q(QGoochMaterial); |
164 | emit q->diffuseChanged(diffuse: var.value<QColor>()); |
165 | } |
166 | |
167 | void QGoochMaterialPrivate::handleSpecularChanged(const QVariant &var) |
168 | { |
169 | Q_Q(QGoochMaterial); |
170 | emit q->specularChanged(specular: var.value<QColor>()); |
171 | } |
172 | |
173 | void QGoochMaterialPrivate::handleCoolChanged(const QVariant &var) |
174 | { |
175 | Q_Q(QGoochMaterial); |
176 | emit q->coolChanged(cool: var.value<QColor>()); |
177 | } |
178 | |
179 | void QGoochMaterialPrivate::handleWarmChanged(const QVariant &var) |
180 | { |
181 | Q_Q(QGoochMaterial); |
182 | emit q->warmChanged(warm: var.value<QColor>()); |
183 | } |
184 | |
185 | void QGoochMaterialPrivate::handleAlphaChanged(const QVariant &var) |
186 | { |
187 | Q_Q(QGoochMaterial); |
188 | emit q->alphaChanged(alpha: var.toFloat()); |
189 | } |
190 | |
191 | void QGoochMaterialPrivate::handleBetaChanged(const QVariant &var) |
192 | { |
193 | Q_Q(QGoochMaterial); |
194 | emit q->betaChanged(beta: var.toFloat()); |
195 | } |
196 | |
197 | void QGoochMaterialPrivate::handleShininessChanged(const QVariant &var) |
198 | { |
199 | Q_Q(QGoochMaterial); |
200 | emit q->shininessChanged(shininess: var.toFloat()); |
201 | } |
202 | |
203 | /*! |
204 | \class Qt3DExtras::QGoochMaterial |
205 | \ingroup qt3d-extras-materials |
206 | \brief The QGoochMaterial provides a material that implements the Gooch |
207 | shading model, popular in CAD and CAM applications. |
208 | \inmodule Qt3DExtras |
209 | \since 5.7 |
210 | \inherits Qt3DRender::QMaterial |
211 | |
212 | The Gooch lighting model uses both color and brightness to help show the |
213 | curvature of 3D surfaces. This is often better than models such as Phong |
214 | that rely purely upon changes in brightness. In situations such as in CAD |
215 | and CAM applications where photorealism is not a goal, the Gooch shading |
216 | model in conjunction with some kind of silhouette edge inking is a popular |
217 | solution. |
218 | |
219 | The Gooch lighting model is explained fully in the \l{original Gooch |
220 | paper}. The Gooch model mixes a diffuse object color with a user-provided |
221 | cool color and warm color to produce the end points of a color ramp that is |
222 | used to shade the object based upon the cosine of the angle between the |
223 | vector from the fragment to the light source and the fragment's normal |
224 | vector. Optionally, a specular highlight can be added on top. The relative |
225 | contributions to the cool and warm colors by the diffuse color are |
226 | controlled by the alpha and beta properties respecitvely. |
227 | |
228 | This material uses an effect with a single render pass approach and |
229 | performs per fragment lighting. Techniques are provided for OpenGL 2, |
230 | OpenGL 3 or above as well as OpenGL ES 2. |
231 | */ |
232 | |
233 | /*! |
234 | Constructs a new QGoochMaterial instance with parent object \a parent. |
235 | */ |
236 | QGoochMaterial::(QNode *parent) |
237 | : QMaterial(*new QGoochMaterialPrivate, parent) |
238 | { |
239 | Q_D(QGoochMaterial); |
240 | d->init(); |
241 | } |
242 | |
243 | /*! \internal */ |
244 | QGoochMaterial::() |
245 | { |
246 | } |
247 | |
248 | QGoochMaterial::(QGoochMaterialPrivate &dd, QNode *parent) |
249 | : QMaterial(dd, parent) |
250 | { |
251 | Q_D(QGoochMaterial); |
252 | d->init(); |
253 | } |
254 | |
255 | /*! |
256 | \property QGoochMaterial::diffuse |
257 | |
258 | Holds the current diffuse color. |
259 | */ |
260 | QColor QGoochMaterial::() const |
261 | { |
262 | Q_D(const QGoochMaterial); |
263 | return d->m_diffuseParameter->value().value<QColor>(); |
264 | } |
265 | |
266 | /*! |
267 | \property QGoochMaterial::specular |
268 | |
269 | Holds the current specular color. |
270 | */ |
271 | QColor QGoochMaterial::() const |
272 | { |
273 | Q_D(const QGoochMaterial); |
274 | return d->m_specularParameter->value().value<QColor>(); |
275 | } |
276 | |
277 | /*! |
278 | \property QGoochMaterial::cool |
279 | |
280 | Holds the current cool color. |
281 | */ |
282 | QColor QGoochMaterial::() const |
283 | { |
284 | Q_D(const QGoochMaterial); |
285 | return d->m_coolParameter->value().value<QColor>(); |
286 | } |
287 | |
288 | /*! |
289 | \property QGoochMaterial::warm |
290 | |
291 | Holds the current warm color. |
292 | */ |
293 | QColor QGoochMaterial::() const |
294 | { |
295 | Q_D(const QGoochMaterial); |
296 | return d->m_warmParameter->value().value<QColor>(); |
297 | } |
298 | |
299 | /*! |
300 | \property QGoochMaterial::alpha |
301 | |
302 | Holds the current alpha value. The start point of the color ramp |
303 | used by the Gooch shader is calculated as {c = cool + alpha * diffuse}. |
304 | */ |
305 | float QGoochMaterial::() const |
306 | { |
307 | Q_D(const QGoochMaterial); |
308 | return d->m_alphaParameter->value().toFloat(); |
309 | } |
310 | |
311 | /*! |
312 | \property QGoochMaterial::beta |
313 | |
314 | Holds the current beta value. The start point of the color ramp |
315 | used by the Gooch shader is calculated as {c = warm + beta * diffuse}. |
316 | */ |
317 | float QGoochMaterial::() const |
318 | { |
319 | Q_D(const QGoochMaterial); |
320 | return d->m_betaParameter->value().toFloat(); |
321 | } |
322 | |
323 | /*! |
324 | \property QGoochMaterial::shininess |
325 | |
326 | Holds the current shininess value. Higher values of shininess result in |
327 | a smaller and brighter highlight. |
328 | */ |
329 | float QGoochMaterial::() const |
330 | { |
331 | Q_D(const QGoochMaterial); |
332 | return d->m_shininessParameter->value().toFloat(); |
333 | } |
334 | |
335 | void QGoochMaterial::(const QColor &diffuse) |
336 | { |
337 | Q_D(QGoochMaterial); |
338 | return d->m_diffuseParameter->setValue(diffuse); |
339 | } |
340 | |
341 | void QGoochMaterial::(const QColor &specular) |
342 | { |
343 | Q_D(QGoochMaterial); |
344 | return d->m_specularParameter->setValue(specular); |
345 | } |
346 | |
347 | void QGoochMaterial::(const QColor &cool) |
348 | { |
349 | Q_D(QGoochMaterial); |
350 | return d->m_coolParameter->setValue(cool); |
351 | } |
352 | |
353 | void QGoochMaterial::(const QColor &warm) |
354 | { |
355 | Q_D(QGoochMaterial); |
356 | return d->m_warmParameter->setValue(warm); |
357 | } |
358 | |
359 | void QGoochMaterial::(float alpha) |
360 | { |
361 | Q_D(QGoochMaterial); |
362 | return d->m_alphaParameter->setValue(alpha); |
363 | } |
364 | |
365 | void QGoochMaterial::(float beta) |
366 | { |
367 | Q_D(QGoochMaterial); |
368 | return d->m_betaParameter->setValue(beta); |
369 | } |
370 | |
371 | void QGoochMaterial::(float shininess) |
372 | { |
373 | Q_D(QGoochMaterial); |
374 | return d->m_shininessParameter->setValue(shininess); |
375 | } |
376 | |
377 | } |
378 | |
379 | QT_END_NAMESPACE |
380 | |