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 "qshaderprogram.h" |
41 | #include "qshaderprogram_p.h" |
42 | #include <Qt3DCore/qpropertyupdatedchange.h> |
43 | #include <Qt3DRender/private/qurlhelper_p.h> |
44 | #include <QDebug> |
45 | #include <QFile> |
46 | #include <QFileInfo> |
47 | #include <QUrl> |
48 | |
49 | /*! |
50 | \class Qt3DRender::QShaderProgram |
51 | \inmodule Qt3DRender |
52 | \brief Encapsulates a Shader Program. |
53 | \inherits Qt3DCore::QNode |
54 | \since 5.5 |
55 | |
56 | A shader program consists of several different shaders, such as vertex and fragment shaders. |
57 | |
58 | Qt3D will automatically populate a set of default uniforms if they are |
59 | encountered during the shader instrospection phase. |
60 | |
61 | \table |
62 | \header |
63 | \li {1, 1} Default Uniform |
64 | \li {2, 1} Associated Qt3D Parameter name |
65 | \li {3, 1} GLSL declaration |
66 | |
67 | \row |
68 | \li {1, 1} ModelMatrix |
69 | \li {2, 1} modelMatrix |
70 | \li {3, 1} uniform mat4 modelMatrix; |
71 | |
72 | \row |
73 | \li {1, 1} ViewMatrix |
74 | \li {2, 1} viewMatrix |
75 | \li {3, 1} uniform mat4 viewMatrix; |
76 | |
77 | \row |
78 | \li {1, 1} ProjectionMatrix |
79 | \li {2, 1} projectionMatrix |
80 | \li {3, 1} uniform mat4 projectionMatrix; |
81 | |
82 | \row |
83 | \li {1, 1} ModelViewMatrix |
84 | \li {2, 1} modelView |
85 | \li {3, 1} uniform mat4 modelView; |
86 | |
87 | \row |
88 | \li {1, 1} ViewProjectionMatrix |
89 | \li {2, 1} viewProjectionMatrix |
90 | \li {3, 1} uniform mat4 viewProjectionMatrix; |
91 | |
92 | \row |
93 | \li {1, 1} ModelViewProjectionMatrix |
94 | \li {2, 1} modelViewProjection \br mvp |
95 | \li {3, 1} uniform mat4 modelViewProjection; \br uniform mat4 mvp; |
96 | |
97 | \row |
98 | \li {1, 1} InverseModelMatrix |
99 | \li {2, 1} inverseModelMatrix |
100 | \li {3, 1} uniform mat4 inverseModelMatrix; |
101 | |
102 | \row |
103 | \li {1, 1} InverseViewMatrix |
104 | \li {2, 1} inverseViewMatrix |
105 | \li {3, 1} uniform mat4 inverseViewMatrix; |
106 | |
107 | \row |
108 | \li {1, 1} InverseProjectionMatrix |
109 | \li {2, 1} inverseProjectionMatrix |
110 | \li {3, 1} uniform mat4 inverseProjectionMatrix; |
111 | |
112 | \row |
113 | \li {1, 1} InverseModelViewMatrix |
114 | \li {2, 1} inverseModelView |
115 | \li {3, 1} uniform mat4 inverseModelView; |
116 | |
117 | \row |
118 | \li {1, 1} InverseViewProjectionMatrix |
119 | \li {2, 1} inverseViewProjectionMatrix |
120 | \li {3, 1} uniform mat4 inverseViewProjectionMatrix; |
121 | |
122 | \row |
123 | \li {1, 1} InverseModelViewProjectionMatrix |
124 | \li {2, 1} inverseModelViewProjection |
125 | \li {3, 1} uniform mat4 inverseModelViewProjection; |
126 | |
127 | \row |
128 | \li {1, 1} ModelNormalMatrix |
129 | \li {2, 1} modelNormalMatrix |
130 | \li {3, 1} uniform mat3 modelNormalMatrix; |
131 | |
132 | \row |
133 | \li {1, 1} ModelViewNormalMatrix |
134 | \li {2, 1} modelViewNormal |
135 | \li {3, 1} uniform mat3 modelViewNormal; |
136 | |
137 | \row |
138 | \li {1, 1} ViewportMatrix |
139 | \li {2, 1} viewportMatrix |
140 | \li {3, 1} uniform mat4 viewportMatrix; |
141 | |
142 | \row |
143 | \li {1, 1} InverseViewportMatrix |
144 | \li {2, 1} inverseViewportMatrix |
145 | \li {3, 1} uniform mat4 inverseViewportMatrix; |
146 | |
147 | \row |
148 | \li {1, 1} AspectRatio \br (surface width / surface height) |
149 | \li {2, 1} aspectRatio |
150 | \li {3, 1} uniform float aspectRatio; |
151 | |
152 | \row |
153 | \li {1, 1} Exposure |
154 | \li {2, 1} exposure |
155 | \li {3, 1} uniform float exposure; |
156 | |
157 | \row |
158 | \li {1, 1} Gamma |
159 | \li {2, 1} gamma |
160 | \li {3, 1} uniform float gamma; |
161 | |
162 | \row |
163 | \li {1, 1} Time \br (in nano seconds) |
164 | \li {2, 1} time |
165 | \li {3, 1} uniform float time; |
166 | |
167 | \row |
168 | \li {1, 1} EyePosition |
169 | \li {2, 1} eyePosition |
170 | \li {3, 1} uniform vec3 eyePosition; |
171 | |
172 | \row |
173 | \li {1, 1} SkinningPalette |
174 | \li {2, 1} skinningPalette[0] |
175 | \li {3, 1} const int maxJoints = 100; \br uniform mat4 skinningPalette[maxJoints]; |
176 | |
177 | \endtable |
178 | */ |
179 | |
180 | /*! |
181 | \qmltype ShaderProgram |
182 | \instantiates Qt3DRender::QShaderProgram |
183 | \inqmlmodule Qt3D.Render |
184 | \brief Encapsulates a Shader Program. |
185 | \since 5.5 |
186 | |
187 | ShaderProgram class encapsulates a shader program. A shader program consists of several |
188 | different shaders, such as vertex and fragment shaders. |
189 | |
190 | Qt3D will automatically populate a set of default uniforms if they are |
191 | encountered during the shader instrospection phase. |
192 | |
193 | \table |
194 | \header |
195 | \li {1, 1} Default Uniform |
196 | \li {2, 1} Associated Qt3D Parameter name |
197 | \li {3, 1} GLSL declaration |
198 | |
199 | \row |
200 | \li {1, 1} ModelMatrix |
201 | \li {2, 1} modelMatrix |
202 | \li {3, 1} uniform mat4 modelMatrix; |
203 | |
204 | \row |
205 | \li {1, 1} ViewMatrix |
206 | \li {2, 1} viewMatrix |
207 | \li {3, 1} uniform mat4 viewMatrix; |
208 | |
209 | \row |
210 | \li {1, 1} ProjectionMatrix |
211 | \li {2, 1} projectionMatrix |
212 | \li {3, 1} uniform mat4 projectionMatrix; |
213 | |
214 | \row |
215 | \li {1, 1} ModelViewMatrix |
216 | \li {2, 1} modelView |
217 | \li {3, 1} uniform mat4 modelView; |
218 | |
219 | \row |
220 | \li {1, 1} ViewProjectionMatrix |
221 | \li {2, 1} viewProjectionMatrix |
222 | \li {3, 1} uniform mat4 viewProjectionMatrix; |
223 | |
224 | \row |
225 | \li {1, 1} ModelViewProjectionMatrix |
226 | \li {2, 1} modelViewProjection \br mvp |
227 | \li {3, 1} uniform mat4 modelViewProjection; \br uniform mat4 mvp; |
228 | |
229 | \row |
230 | \li {1, 1} InverseModelMatrix |
231 | \li {2, 1} inverseModelMatrix |
232 | \li {3, 1} uniform mat4 inverseModelMatrix; |
233 | |
234 | \row |
235 | \li {1, 1} InverseViewMatrix |
236 | \li {2, 1} inverseViewMatrix |
237 | \li {3, 1} uniform mat4 inverseViewMatrix; |
238 | |
239 | \row |
240 | \li {1, 1} InverseProjectionMatrix |
241 | \li {2, 1} inverseProjectionMatrix |
242 | \li {3, 1} uniform mat4 inverseProjectionMatrix; |
243 | |
244 | \row |
245 | \li {1, 1} InverseModelViewMatrix |
246 | \li {2, 1} inverseModelView |
247 | \li {3, 1} uniform mat4 inverseModelView; |
248 | |
249 | \row |
250 | \li {1, 1} InverseViewProjectionMatrix |
251 | \li {2, 1} inverseViewProjectionMatrix |
252 | \li {3, 1} uniform mat4 inverseViewProjectionMatrix; |
253 | |
254 | \row |
255 | \li {1, 1} InverseModelViewProjectionMatrix |
256 | \li {2, 1} inverseModelViewProjection |
257 | \li {3, 1} uniform mat4 inverseModelViewProjection; |
258 | |
259 | \row |
260 | \li {1, 1} ModelNormalMatrix |
261 | \li {2, 1} modelNormalMatrix |
262 | \li {3, 1} uniform mat3 modelNormalMatrix; |
263 | |
264 | \row |
265 | \li {1, 1} ModelViewNormalMatrix |
266 | \li {2, 1} modelViewNormal |
267 | \li {3, 1} uniform mat3 modelViewNormal; |
268 | |
269 | \row |
270 | \li {1, 1} ViewportMatrix |
271 | \li {2, 1} viewportMatrix |
272 | \li {3, 1} uniform mat4 viewportMatrix; |
273 | |
274 | \row |
275 | \li {1, 1} InverseViewportMatrix |
276 | \li {2, 1} inverseViewportMatrix |
277 | \li {3, 1} uniform mat4 inverseViewportMatrix; |
278 | |
279 | \row |
280 | \li {1, 1} AspectRatio \br (surface width / surface height) |
281 | \li {2, 1} aspectRatio |
282 | \li {3, 1} uniform float aspectRatio; |
283 | |
284 | \row |
285 | \li {1, 1} Exposure |
286 | \li {2, 1} exposure |
287 | \li {3, 1} uniform float exposure; |
288 | |
289 | \row |
290 | \li {1, 1} Gamma |
291 | \li {2, 1} gamma |
292 | \li {3, 1} uniform float gamma; |
293 | |
294 | \row |
295 | \li {1, 1} Time \br (in nano seconds) |
296 | \li {2, 1} time |
297 | \li {3, 1} uniform float time; |
298 | |
299 | \row |
300 | \li {1, 1} EyePosition |
301 | \li {2, 1} eyePosition |
302 | \li {3, 1} uniform vec3 eyePosition; |
303 | |
304 | \row |
305 | \li {1, 1} SkinningPalette |
306 | \li {2, 1} skinningPalette[0] |
307 | \li {3, 1} const int maxJoints = 100; \br uniform mat4 skinningPalette[maxJoints]; |
308 | |
309 | \endtable |
310 | */ |
311 | |
312 | /*! |
313 | \enum QShaderProgram::ShaderType |
314 | |
315 | This enum identifies the type of shader used. |
316 | |
317 | \value Vertex Vertex shader |
318 | \value Fragment Fragment shader |
319 | \value TessellationControl Tesselation control shader |
320 | \value TessellationEvaluation Tesselation evaluation shader |
321 | \value Geometry Geometry shader |
322 | \value Compute Compute shader |
323 | */ |
324 | |
325 | /*! |
326 | \enum QShaderProgram::Status |
327 | |
328 | This enum identifies the status of shader used. |
329 | |
330 | \value NotReady The shader hasn't been compiled and linked yet |
331 | \value Ready The shader was successfully compiled |
332 | \value Error An error occurred while compiling the shader |
333 | */ |
334 | |
335 | /*! |
336 | \enum QShaderProgram::Format |
337 | |
338 | This enum identifies the format of the shader code used. |
339 | |
340 | \value GLSL OpenGL |
341 | \value SPIRV Vulkan, OpenGL 5 |
342 | |
343 | \since 5.15 |
344 | */ |
345 | |
346 | QT_BEGIN_NAMESPACE |
347 | |
348 | namespace Qt3DRender { |
349 | |
350 | QShaderProgramPrivate::QShaderProgramPrivate() |
351 | : QNodePrivate() |
352 | , m_status(QShaderProgram::NotReady) |
353 | , m_format(QShaderProgram::GLSL) |
354 | { |
355 | } |
356 | |
357 | void QShaderProgramPrivate::setLog(const QString &log) |
358 | { |
359 | Q_Q(QShaderProgram); |
360 | if (log != m_log) { |
361 | m_log = log; |
362 | const bool blocked = q->blockNotifications(block: true); |
363 | emit q->logChanged(log: m_log); |
364 | q->blockNotifications(block: blocked); |
365 | } |
366 | } |
367 | |
368 | void QShaderProgramPrivate::setStatus(QShaderProgram::Status status) |
369 | { |
370 | Q_Q(QShaderProgram); |
371 | if (status != m_status) { |
372 | m_status = status; |
373 | const bool blocked = q->blockNotifications(block: true); |
374 | emit q->statusChanged(status: m_status); |
375 | q->blockNotifications(block: blocked); |
376 | } |
377 | } |
378 | |
379 | QShaderProgram::QShaderProgram(QNode *parent) |
380 | : QNode(*new QShaderProgramPrivate, parent) |
381 | { |
382 | } |
383 | |
384 | QShaderProgram::~QShaderProgram() |
385 | { |
386 | } |
387 | |
388 | /*! \internal */ |
389 | QShaderProgram::QShaderProgram(QShaderProgramPrivate &dd, QNode *parent) |
390 | : QNode(dd, parent) |
391 | { |
392 | } |
393 | |
394 | /*! |
395 | Posts a scene change with parameter \a change. |
396 | */ |
397 | void QShaderProgram::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) |
398 | { |
399 | Q_D(QShaderProgram); |
400 | if (change->type() == Qt3DCore::PropertyUpdated) { |
401 | const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(src: change); |
402 | if (e->propertyName() == QByteArrayLiteral("log" )) |
403 | d->setLog(e->value().toString()); |
404 | else if (e->propertyName() == QByteArrayLiteral("status" )) |
405 | d->setStatus(static_cast<QShaderProgram::Status>(e->value().toInt())); |
406 | } |
407 | } |
408 | |
409 | /*! |
410 | \qmlproperty string ShaderProgram::vertexShaderCode |
411 | |
412 | Holds the vertex shader code used by this shader program. |
413 | */ |
414 | /*! |
415 | \property QShaderProgram::vertexShaderCode |
416 | |
417 | Holds the vertex shader code used by this shader program. |
418 | */ |
419 | void QShaderProgram::setVertexShaderCode(const QByteArray &vertexShaderCode) |
420 | { |
421 | Q_D(QShaderProgram); |
422 | if (vertexShaderCode != d->m_vertexShaderCode) { |
423 | d->m_vertexShaderCode = vertexShaderCode; |
424 | emit vertexShaderCodeChanged(vertexShaderCode); |
425 | } |
426 | } |
427 | |
428 | QByteArray QShaderProgram::vertexShaderCode() const |
429 | { |
430 | Q_D(const QShaderProgram); |
431 | return d->m_vertexShaderCode; |
432 | } |
433 | |
434 | /*! |
435 | \qmlproperty string ShaderProgram::tessellationControlShaderCode |
436 | |
437 | Holds the tesselation control shader code used by this shader program. |
438 | */ |
439 | /*! |
440 | \property QShaderProgram::tessellationControlShaderCode |
441 | |
442 | Holds the tesselation control shader code used by this shader program. |
443 | */ |
444 | void QShaderProgram::setTessellationControlShaderCode(const QByteArray &tessellationControlShaderCode) |
445 | { |
446 | Q_D(QShaderProgram); |
447 | if (tessellationControlShaderCode != d->m_tessControlShaderCode) { |
448 | d->m_tessControlShaderCode = tessellationControlShaderCode; |
449 | emit tessellationControlShaderCodeChanged(tessellationControlShaderCode); |
450 | } |
451 | } |
452 | |
453 | QByteArray QShaderProgram::tessellationControlShaderCode() const |
454 | { |
455 | Q_D(const QShaderProgram); |
456 | return d->m_tessControlShaderCode; |
457 | } |
458 | |
459 | /*! |
460 | \qmlproperty string ShaderProgram::tessellationEvaluationShaderCode |
461 | |
462 | Holds the tesselation evaluation shader code used by this shader program. |
463 | */ |
464 | /*! |
465 | \property QShaderProgram::tessellationEvaluationShaderCode |
466 | |
467 | Holds the tesselation evaluation shader code used by this shader program. |
468 | */ |
469 | void QShaderProgram::setTessellationEvaluationShaderCode(const QByteArray &tessellationEvaluationShaderCode) |
470 | { |
471 | Q_D(QShaderProgram); |
472 | if (tessellationEvaluationShaderCode != d->m_tessEvalShaderCode) { |
473 | d->m_tessEvalShaderCode = tessellationEvaluationShaderCode; |
474 | emit tessellationEvaluationShaderCodeChanged(tessellationEvaluationShaderCode); |
475 | } |
476 | } |
477 | |
478 | QByteArray QShaderProgram::tessellationEvaluationShaderCode() const |
479 | { |
480 | Q_D(const QShaderProgram); |
481 | return d->m_tessEvalShaderCode; |
482 | } |
483 | |
484 | /*! |
485 | \qmlproperty string ShaderProgram::geometryShaderCode |
486 | |
487 | Holds the geometry shader code used by this shader program. |
488 | */ |
489 | /*! |
490 | \property QShaderProgram::geometryShaderCode |
491 | |
492 | Holds the geometry shader code used by this shader program. |
493 | */ |
494 | void QShaderProgram::setGeometryShaderCode(const QByteArray &geometryShaderCode) |
495 | { |
496 | Q_D(QShaderProgram); |
497 | if (geometryShaderCode != d->m_geometryShaderCode) { |
498 | d->m_geometryShaderCode = geometryShaderCode; |
499 | emit geometryShaderCodeChanged(geometryShaderCode); |
500 | } |
501 | } |
502 | |
503 | QByteArray QShaderProgram::geometryShaderCode() const |
504 | { |
505 | Q_D(const QShaderProgram); |
506 | return d->m_geometryShaderCode; |
507 | } |
508 | |
509 | /*! |
510 | \qmlproperty string ShaderProgram::fragmentShaderCode |
511 | |
512 | Holds the fragment shader code used by this shader program. |
513 | */ |
514 | /*! |
515 | \property QShaderProgram::fragmentShaderCode |
516 | |
517 | Holds the fragment shader code used by this shader program. |
518 | */ |
519 | void QShaderProgram::setFragmentShaderCode(const QByteArray &fragmentShaderCode) |
520 | { |
521 | Q_D(QShaderProgram); |
522 | if (fragmentShaderCode != d->m_fragmentShaderCode) { |
523 | d->m_fragmentShaderCode = fragmentShaderCode; |
524 | emit fragmentShaderCodeChanged(fragmentShaderCode); |
525 | } |
526 | } |
527 | |
528 | QByteArray QShaderProgram::fragmentShaderCode() const |
529 | { |
530 | Q_D(const QShaderProgram); |
531 | return d->m_fragmentShaderCode; |
532 | } |
533 | |
534 | /*! |
535 | \qmlproperty string ShaderProgram::computeShaderCode |
536 | |
537 | Holds the compute shader code used by this shader program. |
538 | */ |
539 | /*! |
540 | \property QShaderProgram::computeShaderCode |
541 | |
542 | Holds the compute shader code used by this shader program. |
543 | */ |
544 | void QShaderProgram::setComputeShaderCode(const QByteArray &computeShaderCode) |
545 | { |
546 | Q_D(QShaderProgram); |
547 | if (computeShaderCode != d->m_computeShaderCode) { |
548 | d->m_computeShaderCode = computeShaderCode; |
549 | emit computeShaderCodeChanged(computeShaderCode); |
550 | } |
551 | } |
552 | |
553 | QByteArray QShaderProgram::computeShaderCode() const |
554 | { |
555 | Q_D(const QShaderProgram); |
556 | return d->m_computeShaderCode; |
557 | } |
558 | |
559 | |
560 | /*! |
561 | Sets the shader code for \a type of shader to the \a shaderCode. |
562 | */ |
563 | void QShaderProgram::setShaderCode(ShaderType type, const QByteArray &shaderCode) |
564 | { |
565 | switch (type) { |
566 | case Vertex: |
567 | setVertexShaderCode(shaderCode); |
568 | break; |
569 | case TessellationControl: |
570 | setTessellationControlShaderCode(shaderCode); |
571 | break; |
572 | case TessellationEvaluation: |
573 | setTessellationEvaluationShaderCode(shaderCode); |
574 | break; |
575 | case Geometry: |
576 | setGeometryShaderCode(shaderCode); |
577 | break; |
578 | case Fragment: |
579 | setFragmentShaderCode(shaderCode); |
580 | break; |
581 | case Compute: |
582 | setComputeShaderCode(shaderCode); |
583 | break; |
584 | default: |
585 | Q_UNREACHABLE(); |
586 | } |
587 | } |
588 | |
589 | /*! |
590 | Returns the shader code for \a type. |
591 | */ |
592 | QByteArray QShaderProgram::shaderCode(ShaderType type) const |
593 | { |
594 | Q_D(const QShaderProgram); |
595 | switch (type) { |
596 | case Vertex: |
597 | return d->m_vertexShaderCode; |
598 | case TessellationControl: |
599 | return d->m_tessControlShaderCode; |
600 | case TessellationEvaluation: |
601 | return d->m_tessEvalShaderCode; |
602 | case Geometry: |
603 | return d->m_geometryShaderCode; |
604 | case Fragment: |
605 | return d->m_fragmentShaderCode; |
606 | case Compute: |
607 | return d->m_computeShaderCode; |
608 | default: |
609 | Q_UNREACHABLE(); |
610 | } |
611 | } |
612 | |
613 | /*! |
614 | \qmlproperty string ShaderProgram::log |
615 | |
616 | Holds the log of the current shader program. This is useful to diagnose a |
617 | compilation failure of the shader program. |
618 | */ |
619 | /*! |
620 | \property QShaderProgram::log |
621 | |
622 | Holds the log of the current shader program. This is useful to diagnose a |
623 | compilation failure of the shader program. |
624 | */ |
625 | QString QShaderProgram::log() const |
626 | { |
627 | Q_D(const QShaderProgram); |
628 | return d->m_log; |
629 | } |
630 | |
631 | /*! |
632 | \qmlproperty enumeration ShaderProgram::status |
633 | |
634 | Holds the status of the current shader program. |
635 | */ |
636 | /*! |
637 | \property QShaderProgram::status |
638 | |
639 | Holds the status of the current shader program. |
640 | */ |
641 | /*! |
642 | Returns the status of the current shader program. |
643 | */ |
644 | QShaderProgram::Status QShaderProgram::status() const |
645 | { |
646 | Q_D(const QShaderProgram); |
647 | return d->m_status; |
648 | } |
649 | |
650 | void QShaderProgram::setFormat(QShaderProgram::Format format) |
651 | { |
652 | Q_D(QShaderProgram); |
653 | if (format != d->m_format) { |
654 | d->m_format = format; |
655 | emit formatChanged(format); |
656 | } |
657 | } |
658 | |
659 | /*! |
660 | \qmlproperty enumeration ShaderProgram::format |
661 | \since 5.15 |
662 | |
663 | Holds the format of the code provided on the ShaderProgram. |
664 | The default is ShaderProgram.GLSL |
665 | */ |
666 | /*! |
667 | \property QShaderProgram::format |
668 | \since 5.15 |
669 | |
670 | Holds the format of the code provided on the ShaderProgram. |
671 | The default is ShaderProgram.GLSL |
672 | */ |
673 | QShaderProgram::Format QShaderProgram::format() const |
674 | { |
675 | Q_D(const QShaderProgram); |
676 | return d->m_format; |
677 | } |
678 | |
679 | QByteArray QShaderProgramPrivate::deincludify(const QString &filePath) |
680 | { |
681 | QFile f(filePath); |
682 | if (!f.open(flags: QIODevice::ReadOnly | QIODevice::Text)) { |
683 | qWarning() << "Could not read shader source file:" << f.fileName(); |
684 | return QByteArray(); |
685 | } |
686 | |
687 | QByteArray contents = f.readAll(); |
688 | return deincludify(contents, filePath); |
689 | } |
690 | |
691 | QByteArray QShaderProgramPrivate::deincludify(const QByteArray &contents, const QString &filePath) |
692 | { |
693 | QByteArrayList lines = contents.split(sep: '\n'); |
694 | const QByteArray includeDirective = QByteArrayLiteral("#pragma include" ); |
695 | for (int i = 0; i < lines.count(); ++i) { |
696 | const auto line = lines[i].simplified(); |
697 | if (line.startsWith(a: includeDirective)) { |
698 | const QString includePartialPath = QString::fromUtf8(str: line.mid(index: includeDirective.count() + 1)); |
699 | |
700 | QString includePath = QFileInfo(includePartialPath).isAbsolute() ? includePartialPath |
701 | : QFileInfo(filePath).absolutePath() + QLatin1Char('/') + includePartialPath; |
702 | if (qEnvironmentVariableIsSet(varName: "QT3D_GLSL100_WORKAROUND" )) { |
703 | QString candidate = includePath + QLatin1String("100" ); |
704 | if (QFile::exists(fileName: candidate)) |
705 | includePath = candidate; |
706 | } |
707 | lines.removeAt(i); |
708 | QByteArray includedContents = deincludify(filePath: includePath); |
709 | lines.insert(i, t: includedContents); |
710 | QString lineDirective = QString(QStringLiteral("#line %1" )).arg(a: i + 2); |
711 | lines.insert(i: i + 1, t: lineDirective.toUtf8()); |
712 | } |
713 | } |
714 | |
715 | return lines.join(sep: '\n'); |
716 | } |
717 | |
718 | /*! |
719 | \qmlmethod string ShaderProgram::loadSource(url sourceUrl) |
720 | |
721 | Returns the shader code loaded from \a sourceUrl. |
722 | */ |
723 | /*! |
724 | Returns the shader code loaded from \a sourceUrl. |
725 | */ |
726 | QByteArray QShaderProgram::loadSource(const QUrl &sourceUrl) |
727 | { |
728 | // TO DO: Handle remote path |
729 | return QShaderProgramPrivate::deincludify(filePath: Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(url: sourceUrl)); |
730 | } |
731 | |
732 | Qt3DCore::QNodeCreatedChangeBasePtr QShaderProgram::createNodeCreationChange() const |
733 | { |
734 | auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QShaderProgramData>::create(arguments: this); |
735 | auto &data = creationChange->data; |
736 | Q_D(const QShaderProgram); |
737 | data.vertexShaderCode = d->m_vertexShaderCode; |
738 | data.tessellationControlShaderCode = d->m_tessControlShaderCode; |
739 | data.tessellationEvaluationShaderCode = d->m_tessEvalShaderCode; |
740 | data.geometryShaderCode = d->m_geometryShaderCode; |
741 | data.fragmentShaderCode = d->m_fragmentShaderCode; |
742 | data.computeShaderCode = d->m_computeShaderCode; |
743 | data.format = d->m_format; |
744 | return creationChange; |
745 | } |
746 | |
747 | } // of namespace Qt3DRender |
748 | |
749 | QT_END_NAMESPACE |
750 | |