| 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 |  |