diff options
-rw-r--r-- | examples/deferred-renderer/FinalEffect.qml | 8 | ||||
-rw-r--r-- | examples/deferred-renderer/SceneEffect.qml | 8 | ||||
-rw-r--r-- | examples/rollerball/AdsEffect.qml | 4 | ||||
-rw-r--r-- | examples/simple-qml/main.qml | 20 | ||||
-rw-r--r-- | src/render/backend/renderer.cpp | 4 | ||||
-rw-r--r-- | src/render/backend/rendershader.cpp | 145 | ||||
-rw-r--r-- | src/render/backend/rendershader_p.h | 7 | ||||
-rw-r--r-- | src/render/frontend/qshaderprogram.cpp | 322 | ||||
-rw-r--r-- | src/render/frontend/qshaderprogram.h | 96 | ||||
-rw-r--r-- | src/render/frontend/qshaderprogram_p.h | 12 | ||||
-rw-r--r-- | src/render/io/gltfparser.cpp | 4 |
11 files changed, 465 insertions, 165 deletions
diff --git a/examples/deferred-renderer/FinalEffect.qml b/examples/deferred-renderer/FinalEffect.qml index 754d10b0c..7bc4a3a10 100644 --- a/examples/deferred-renderer/FinalEffect.qml +++ b/examples/deferred-renderer/FinalEffect.qml @@ -51,7 +51,7 @@ Effect { criteria : Criterion { name : "pass"; value : "final" } shaderProgram : ShaderProgram { id : finalShaderGL3 - vertexShader: + vertexShaderCode: " #version 140 @@ -63,7 +63,7 @@ Effect { gl_Position = modelMatrix * vertexPosition; } " - fragmentShader: + fragmentShaderCode: " #version 140 @@ -111,7 +111,7 @@ Effect { criteria : Criterion { name : "pass"; value : "final" } shaderProgram : ShaderProgram { id : finalShaderGL2 - vertexShader: + vertexShaderCode: " #version 110 @@ -123,7 +123,7 @@ Effect { gl_Position = modelMatrix * vertexPosition; } " - fragmentShader: + fragmentShaderCode: " #version 110 diff --git a/examples/deferred-renderer/SceneEffect.qml b/examples/deferred-renderer/SceneEffect.qml index 60612f81f..5aac9ba78 100644 --- a/examples/deferred-renderer/SceneEffect.qml +++ b/examples/deferred-renderer/SceneEffect.qml @@ -52,7 +52,7 @@ Effect { criteria : Criterion { name : "pass"; value : "geometry" } shaderProgram : ShaderProgram { id : sceneShaderGL3 - vertexShader: + vertexShaderCode: " #version 140 @@ -76,7 +76,7 @@ Effect { gl_Position = mvp * vertexPosition; } " - fragmentShader: + fragmentShaderCode: " #version 140 @@ -105,7 +105,7 @@ Effect { criteria : Criterion { name : "pass"; value : "geometry" } shaderProgram : ShaderProgram { id : sceneShaderGL2 - vertexShader: + vertexShaderCode: " #version 110 @@ -129,7 +129,7 @@ Effect { gl_Position = mvp * vertexPosition; } " - fragmentShader: + fragmentShaderCode: " #version 110 diff --git a/examples/rollerball/AdsEffect.qml b/examples/rollerball/AdsEffect.qml index 0a0f59eae..c7d964951 100644 --- a/examples/rollerball/AdsEffect.qml +++ b/examples/rollerball/AdsEffect.qml @@ -99,8 +99,8 @@ Effect { ] shaderProgram: ShaderProgram { - vertexSourceFile: ":/shaders/phong.vert" - fragmentSourceFile: ":/shaders/phong.frag" + vertexShaderSourceFile: ":/shaders/phong.vert" + fragmentShaderSourceFile: ":/shaders/phong.frag" } } ] diff --git a/examples/simple-qml/main.qml b/examples/simple-qml/main.qml index 8f79298b5..0e13d35cf 100644 --- a/examples/simple-qml/main.qml +++ b/examples/simple-qml/main.qml @@ -272,7 +272,7 @@ Entity { shaderProgram : ShaderProgram { id : textureShaderLighting - vertexShader: " + vertexShaderCode: " #version 140 in vec4 vertexPosition; in vec3 vertexNormal; @@ -294,7 +294,7 @@ Entity { gl_Position = customMvp * vertexPosition; }" - fragmentShader: " + fragmentShaderCode: " #version 140 in vec2 texCoord; in vec3 worldPosition; @@ -328,7 +328,7 @@ Entity { RenderPass { criteria : [Criterion {name : "Name"; value : "Texture" }] shaderProgram : ShaderProgram { - vertexShader : " + vertexShaderCode : " #version 140 in vec4 vertexPosition; in vec2 vertexTexCoord; @@ -342,7 +342,7 @@ Entity { gl_Position = mvp * vertexPosition; }" - fragmentShader: " + fragmentShaderCode: " #version 140 in vec2 texCoord; out vec4 fragColor; @@ -363,7 +363,7 @@ Entity { DepthTest { func : DepthTest.LessOrEqual} ] shaderProgram : ShaderProgram { - vertexShader: " + vertexShaderCode: " #version 140 in vec4 vertexPosition; in vec3 vertexNormal; @@ -383,7 +383,7 @@ Entity { } " - fragmentShader: " + fragmentShaderCode: " #version 140 in vec3 worldPosition; in vec3 normal; @@ -415,7 +415,7 @@ Entity { RenderPass { criteria : Criterion {name : "Name"; value : "Final" } shaderProgram : ShaderProgram { - vertexShader: " + vertexShaderCode: " #version 140 in vec4 vertexPosition; in vec2 vertexTexCoord; @@ -429,7 +429,7 @@ Entity { } " - fragmentShader: " + fragmentShaderCode: " #version 140 in vec2 texCoord; out vec4 fragColor; @@ -502,8 +502,8 @@ Entity { ] shaderProgram : ShaderProgram { id : diffuseShader - vertexSourceFile: ":/shaders/diffuse.vert" - fragmentSourceFile: ":/shaders/diffuse.frag" + vertexShaderSourceFile: ":/shaders/diffuse.vert" + fragmentShaderSourceFile: ":/shaders/diffuse.frag" } } ] diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 0e911dbe4..3e3d92f7a 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -181,8 +181,8 @@ void Renderer::buildDefaultTechnique() m_defaultTechnique->setObjectName(QStringLiteral("default-technique")); QShaderProgram* defaultShader = new QShaderProgram; - defaultShader->setVertexSourceFile(QStringLiteral(":/shaders/diffuse.vert")); - defaultShader->setFragmentSourceFile(QStringLiteral(":/shaders/diffuse.frag")); + defaultShader->setVertexShaderSourceFile(QStringLiteral(":/shaders/diffuse.vert")); + defaultShader->setFragmentShaderSourceFile(QStringLiteral(":/shaders/diffuse.frag")); defaultShader->setObjectName(QStringLiteral("DefaultShader")); QRenderPass* basicPass = new QRenderPass; diff --git a/src/render/backend/rendershader.cpp b/src/render/backend/rendershader.cpp index 46d773e5c..3b0d49f64 100644 --- a/src/render/backend/rendershader.cpp +++ b/src/render/backend/rendershader.cpp @@ -59,11 +59,13 @@ QT_BEGIN_NAMESPACE namespace Qt3D { namespace Render { -RenderShader::RenderShader() : - m_program(Q_NULLPTR), - m_renderer(Q_NULLPTR), - m_isLoaded(false) +RenderShader::RenderShader() + : m_program(Q_NULLPTR) + , m_renderer(Q_NULLPTR) + , m_isLoaded(false) { + m_shaderCode.resize(static_cast<int>(QShaderProgram::Compute) + 1); + m_shaderSourceFiles.resize(static_cast<int>(QShaderProgram::Compute) + 1); } RenderShader::~RenderShader() @@ -88,16 +90,21 @@ void RenderShader::setPeer(QShaderProgram *peer) if (!m_shaderUuid.isNull()) { arbiter->unregisterObserver(this, m_shaderUuid); m_shaderUuid = QUuid(); - m_vertexSourceCode.clear(); - m_fragmentSourceCode.clear(); + + for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i) { + m_shaderCode[i].clear(); + m_shaderSourceFiles[i].clear(); + } } + m_isLoaded = false; m_shaderUuid = peerUuid; arbiter->registerObserver(this, m_shaderUuid, NodeUpdated); - m_vertexSourceCode = peer->vertexSourceCode(); - m_vertexSourceFile = peer->vertexSourceFile(); - m_fragmentSourceCode = peer->fragmentSourceCode(); - m_fragmentSourceFile = peer->fragmentSourceFile(); + for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i) { + QShaderProgram::ShaderType type = static_cast<const QShaderProgram::ShaderType>(i); + m_shaderCode[i] = peer->shaderCode(type); + m_shaderSourceFiles[i] = peer->shaderSourceFile(type); + } } } @@ -123,24 +130,45 @@ QUuid RenderShader::shaderUuid() const void RenderShader::sceneChangeEvent(const QSceneChangePtr &e) { - QScenePropertyChangePtr propertyChange = e.staticCast<QScenePropertyChange>(); - QVariant propertyValue = propertyChange->value(); - if (e->type() == NodeUpdated) { + QScenePropertyChangePtr propertyChange = e.staticCast<QScenePropertyChange>(); + QVariant propertyValue = propertyChange->value(); + if (propertyChange->propertyName() == QByteArrayLiteral("vertexSourceCode")) { - m_vertexSourceCode = propertyValue.toByteArray(); + m_shaderCode[QShaderProgram::Vertex] = propertyValue.toByteArray(); m_isLoaded = false; - } - else if (propertyChange->propertyName() == QByteArrayLiteral("fragmentSourceCode")) { - m_fragmentSourceCode = propertyValue.toByteArray(); + } else if (propertyChange->propertyName() == QByteArrayLiteral("fragmentSourceCode")) { + m_shaderCode[QShaderProgram::Fragment] = propertyValue.toByteArray(); m_isLoaded = false; - } - else if (propertyChange->propertyName() == QByteArrayLiteral("vertexSourceFile")) { - m_vertexSourceFile = propertyValue.toString(); + } else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationControlSourceCode")) { + m_shaderCode[QShaderProgram::TessellationControl] = propertyValue.toByteArray(); m_isLoaded = false; - } - else if (propertyChange->propertyName() == QByteArrayLiteral("fragmentSourceFile")) { - m_fragmentSourceFile = propertyValue.toString(); + } else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationEvaluationSourceCode")) { + m_shaderCode[QShaderProgram::TessellationEvaluation] = propertyValue.toByteArray(); + m_isLoaded = false; + } else if (propertyChange->propertyName() == QByteArrayLiteral("geometrySourceCode")) { + m_shaderCode[QShaderProgram::Geometry] = propertyValue.toByteArray(); + m_isLoaded = false; + } else if (propertyChange->propertyName() == QByteArrayLiteral("computeSourceCode")) { + m_shaderCode[QShaderProgram::Compute] = propertyValue.toByteArray(); + m_isLoaded = false; + } else if (propertyChange->propertyName() == QByteArrayLiteral("vertexSourceFile")) { + m_shaderSourceFiles[QShaderProgram::Vertex] = propertyValue.toString(); + m_isLoaded = false; + } else if (propertyChange->propertyName() == QByteArrayLiteral("fragmentSourceFile")) { + m_shaderSourceFiles[QShaderProgram::Fragment] = propertyValue.toString(); + m_isLoaded = false; + } else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationControlSourceFile")) { + m_shaderSourceFiles[QShaderProgram::TessellationControl] = propertyValue.toString(); + m_isLoaded = false; + } else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationEvaluationSourceFile")) { + m_shaderSourceFiles[QShaderProgram::TessellationEvaluation] = propertyValue.toString(); + m_isLoaded = false; + } else if (propertyChange->propertyName() == QByteArrayLiteral("geometrySourceFile")) { + m_shaderSourceFiles[QShaderProgram::Geometry] = propertyValue.toString(); + m_isLoaded = false; + } else if (propertyChange->propertyName() == QByteArrayLiteral("computeSourceFile")) { + m_shaderSourceFiles[QShaderProgram::Compute] = propertyValue.toString(); m_isLoaded = false; } } @@ -181,55 +209,52 @@ void RenderShader::setFragOutputs(const QHash<QString, int> &fragOutputs) m_fragOutputs = fragOutputs; } +static QOpenGLShader::ShaderType shaderType(QShaderProgram::ShaderType type) +{ + switch (type) { + case QShaderProgram::Vertex: return QOpenGLShader::Vertex; + case QShaderProgram::TessellationControl: return QOpenGLShader::TessellationControl; + case QShaderProgram::TessellationEvaluation: return QOpenGLShader::TessellationEvaluation; + case QShaderProgram::Geometry: return QOpenGLShader::Geometry; + case QShaderProgram::Fragment: return QOpenGLShader::Fragment; + case QShaderProgram::Compute: return QOpenGLShader::Compute; + default: Q_UNREACHABLE(); + } +} + QOpenGLShaderProgram* RenderShader::createProgram(QGraphicsContext *context) { Q_ASSERT(QOpenGLContext::currentContext()); - // scoped pointer so early-returns delete automatically + // Scoped pointer so early-returns delete automatically QScopedPointer<QOpenGLShaderProgram> p(new QOpenGLShaderProgram); - if (!m_fragmentSourceFile.isEmpty()) { - QFile f(m_fragmentSourceFile); - if (!f.exists()) { - qWarning() << "couldn't find shader source file:" << m_fragmentSourceFile; - } else { - f.open(QIODevice::ReadOnly); - m_fragmentSourceCode = f.readAll(); - f.close(); - } - } - if (!m_vertexSourceFile.isEmpty()) { - QFile vs(m_vertexSourceFile); - if (!vs.exists()) { - qWarning() << "couldn't find shader source file:" << m_vertexSourceFile; - } else { - vs.open(QIODevice::ReadOnly); - m_vertexSourceCode = vs.readAll(); - vs.close(); + for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i) { + QShaderProgram::ShaderType type = static_cast<const QShaderProgram::ShaderType>(i); + const QString sourceFile = m_shaderSourceFiles[type]; + if (!sourceFile.isEmpty()) { + QFile f(sourceFile); + if (!f.exists()) { + qWarning() << "Couldn't read shader source file:" << sourceFile; + } else { + f.open(QIODevice::ReadOnly | QIODevice::Text); + m_shaderCode[type] = f.readAll(); + } } - } - bool ok = p->addShaderFromSourceCode(QOpenGLShader::Vertex, - m_vertexSourceCode); - if (!ok) { - qWarning() << "bad vertex source:" << p->log(); - return Q_NULLPTR; - } - - ok = p->addShaderFromSourceCode(QOpenGLShader::Fragment, - m_fragmentSourceCode); - if (!ok) { - qWarning() << "bad fragment source:" << p->log(); - return Q_NULLPTR; + // Compile shaders + if (!m_shaderCode[type].isEmpty()) { + if (!p->addShaderFromSourceCode(shaderType(type), m_shaderCode[type])) + qWarning() << "Failed to compile shader:" << p->log(); + } } - // glBindFragDataLocation at that point + // Call glBindFragDataLocation and link the program context->bindFragOutputs(p->programId(), m_fragOutputs); - - ok = p->link(); - if (!ok) { - qWarning() << "program failed to link:" << p->log(); + if (!p->link()) { + qWarning() << "Failed to link shader program:" << p->log(); return Q_NULLPTR; } + // take from scoped-pointer so it doesn't get deleted return p.take(); } diff --git a/src/render/backend/rendershader_p.h b/src/render/backend/rendershader_p.h index 9d3c117bc..5a8878789 100644 --- a/src/render/backend/rendershader_p.h +++ b/src/render/backend/rendershader_p.h @@ -84,7 +84,6 @@ public: bool isLoaded() const; private: - QOpenGLShaderProgram *m_program; Renderer *m_renderer; @@ -95,10 +94,8 @@ private: QHash<QString, int> m_attributes; QHash<QString, int> m_fragOutputs; - QByteArray m_vertexSourceCode; - QByteArray m_fragmentSourceCode; - QString m_vertexSourceFile; - QString m_fragmentSourceFile; + QVector<QByteArray> m_shaderCode; + QVector<QString> m_shaderSourceFiles; QUuid m_shaderUuid; diff --git a/src/render/frontend/qshaderprogram.cpp b/src/render/frontend/qshaderprogram.cpp index c63eda809..e9d4c5c5b 100644 --- a/src/render/frontend/qshaderprogram.cpp +++ b/src/render/frontend/qshaderprogram.cpp @@ -65,11 +65,19 @@ void QShaderProgram::copy(const QNode *ref) QAbstractShader::copy(ref); const QShaderProgram *prog = qobject_cast<const QShaderProgram *>(ref); if (prog != Q_NULLPTR) { - // TO DO : Move loading to the backend - d->m_vertexSourceFile = prog->vertexSourceFile(); - d->m_fragmentSourceFile = prog->fragmentSourceFile(); - d->m_cachedFragmentCode = prog->d_func()->m_cachedFragmentCode; - d->m_cachedVertexCode = prog->d_func()->m_cachedVertexCode; + d->m_vertexSourceFile = prog->d_func()->m_vertexSourceFile; + d->m_tessControlSourceFile = prog->d_func()->m_tessControlSourceFile; + d->m_tessEvalSourceFile = prog->d_func()->m_tessEvalSourceFile; + d->m_geometrySourceFile = prog->d_func()->m_geometrySourceFile; + d->m_fragmentSourceFile = prog->d_func()->m_fragmentSourceFile; + d->m_computeSourceFile = prog->d_func()->m_computeSourceFile; + + d->m_vertexShaderCode = prog->d_func()->m_vertexShaderCode; + d->m_tessControlShaderCode = prog->d_func()->m_tessControlShaderCode; + d->m_tessEvalShaderCode = prog->d_func()->m_tessEvalShaderCode; + d->m_geometryShaderCode = prog->d_func()->m_geometryShaderCode; + d->m_fragmentShaderCode = prog->d_func()->m_fragmentShaderCode; + d->m_computeShaderCode = prog->d_func()->m_computeShaderCode; } } @@ -83,98 +91,308 @@ QShaderProgram *QShaderProgram::doClone(QNode *clonedParent) const return new QShaderProgram(clonedParent); } -void QShaderProgram::setVertexSourceFile(const QString& vertexSourceFile) +void QShaderProgram::setVertexShaderSourceFile(const QString& vertexShaderSourceFile) { Q_D(QShaderProgram); - if (vertexSourceFile != d->m_vertexSourceFile) { - d->m_vertexSourceFile = vertexSourceFile; - emit vertexSourceFileChanged(); - - if (d->m_changeArbiter != Q_NULLPTR) { - QScenePropertyChangePtr e(new QScenePropertyChange(NodeUpdated, this)); - e->setPropertyName(QByteArrayLiteral("vertexSourceFile")); - e->setValue(vertexSourceFile); - notifyObservers(e); - } + if (vertexShaderSourceFile != d->m_vertexSourceFile) { + d->m_vertexSourceFile = vertexShaderSourceFile; + notifyPropertyChange(QByteArrayLiteral("vertexSourceFile"), + vertexShaderSourceFile); + emit vertexShaderSourceFileChanged(); } } -QString QShaderProgram::vertexSourceFile() const +QString QShaderProgram::vertexShaderSourceFile() const { Q_D(const QShaderProgram); return d->m_vertexSourceFile; } -void QShaderProgram::setFragmentSourceFile(const QString& fragmentSourceFile) +void QShaderProgram::setTessellationControlShaderSourceFile(const QString &tessellationControlShaderSourceFile) { Q_D(QShaderProgram); - if (fragmentSourceFile != d->m_fragmentSourceFile) { - d->m_fragmentSourceFile = fragmentSourceFile; - emit fragmentSourceFileChanged(); + if (tessellationControlShaderSourceFile != d->m_tessControlSourceFile) { + d->m_tessControlSourceFile = tessellationControlShaderSourceFile; + notifyPropertyChange(QByteArrayLiteral("tessellationControlShaderSourceFile"), + tessellationControlShaderSourceFile); + emit tessellationControlShaderSourceFileChanged(); + } +} + +QString QShaderProgram::tessellationControlShaderSourceFile() const +{ + Q_D(const QShaderProgram); + return d->m_tessControlSourceFile; +} - if (d->m_changeArbiter != Q_NULLPTR) { - QScenePropertyChangePtr e(new QScenePropertyChange(NodeUpdated, this)); - e->setPropertyName(QByteArrayLiteral("fragmentSourceFile")); - e->setValue(fragmentSourceFile); - notifyObservers(e); - } +void QShaderProgram::setTessellationEvaluationShaderSourceFile(const QString &tessellationEvaluationShaderSourceFile) +{ + Q_D(QShaderProgram); + if (tessellationEvaluationShaderSourceFile != d->m_tessEvalSourceFile) { + d->m_tessEvalSourceFile = tessellationEvaluationShaderSourceFile; + notifyPropertyChange(QByteArrayLiteral("tessellationEvaluationShaderSourceFile"), + tessellationEvaluationShaderSourceFile); + emit tessellationEvaluationShaderSourceFileChanged(); } } -QString QShaderProgram::fragmentSourceFile() const +QString QShaderProgram::tessellationEvaluationShaderSourceFile() const +{ + Q_D(const QShaderProgram); + return d->m_tessEvalSourceFile; +} + +void QShaderProgram::setGeometryShaderSourceFile(const QString &geometryShaderSourceFile) +{ + Q_D(QShaderProgram); + if (geometryShaderSourceFile != d->m_geometrySourceFile) { + d->m_geometrySourceFile = geometryShaderSourceFile; + notifyPropertyChange(QByteArrayLiteral("geometryShaderSourceFile"), + geometryShaderSourceFile); + emit geometryShaderSourceFileChanged(); + } +} + +QString QShaderProgram::geometryShaderSourceFile() const +{ + Q_D(const QShaderProgram); + return d->m_geometrySourceFile; +} + +void QShaderProgram::setFragmentShaderSourceFile(const QString& fragmentShaderSourceFile) +{ + Q_D(QShaderProgram); + if (fragmentShaderSourceFile != d->m_fragmentSourceFile) { + d->m_fragmentSourceFile = fragmentShaderSourceFile; + notifyPropertyChange(QByteArrayLiteral("fragmentSourceFile"), + fragmentShaderSourceFile); + emit fragmentShaderSourceFileChanged(); + } +} + +QString QShaderProgram::fragmentShaderSourceFile() const { Q_D(const QShaderProgram); return d->m_fragmentSourceFile; } +void QShaderProgram::setComputeShaderSourceFile(const QString &computeShaderSourceFile) +{ + Q_D(QShaderProgram); + if (computeShaderSourceFile != d->m_computeSourceFile) { + d->m_computeSourceFile = computeShaderSourceFile; + notifyPropertyChange(QByteArrayLiteral("computeShaderSourceFile"), + computeShaderSourceFile); + emit computeShaderSourceFileChanged(); + } +} + +QString QShaderProgram::computeShaderSourceFile() const +{ + Q_D(const QShaderProgram); + return d->m_computeSourceFile; +} + +void QShaderProgram::setShaderSourceFile(ShaderType type, const QString &sourceFile) +{ + switch (type) { + case Vertex: + setVertexShaderSourceFile(sourceFile); + break; + case TessellationControl: + setTessellationControlShaderSourceFile(sourceFile); + break; + case TessellationEvaluation: + setTessellationEvaluationShaderSourceFile(sourceFile); + break; + case Geometry: + setGeometryShaderSourceFile(sourceFile); + break; + case Fragment: + setFragmentShaderSourceFile(sourceFile); + break; + case Compute: + setComputeShaderSourceFile(sourceFile); + break; + default: + Q_UNREACHABLE(); + } +} + +QString QShaderProgram::shaderSourceFile(ShaderType type) const +{ + Q_D(const QShaderProgram); + switch (type) { + case Vertex: + return d->m_vertexSourceFile; + case TessellationControl: + return d->m_tessControlSourceFile; + case TessellationEvaluation: + return d->m_tessEvalSourceFile; + case Geometry: + return d->m_geometrySourceFile; + case Fragment: + return d->m_fragmentSourceFile; + case Compute: + return d->m_computeSourceFile; + default: + Q_UNREACHABLE(); + } +} + /*! * Sets the vertexShader from raw data in \a vertexShader. */ -void QShaderProgram::setVertexShader(const QByteArray &vertexShader) +void QShaderProgram::setVertexShaderCode(const QByteArray &vertexShaderCode) +{ + Q_D(QShaderProgram); + if (vertexShaderCode != d->m_vertexShaderCode) { + d->m_vertexShaderCode = vertexShaderCode; + notifyPropertyChange(QByteArrayLiteral("vertexSourceCode"), + vertexShaderCode); + emit vertexShaderCodeChanged(); + } +} + +QByteArray QShaderProgram::vertexShaderCode() const +{ + Q_D(const QShaderProgram); + return d->m_vertexShaderCode; +} + +void QShaderProgram::setTessellationControlShaderCode(const QByteArray &tessellationControlShaderCode) +{ + Q_D(QShaderProgram); + if (tessellationControlShaderCode != d->m_tessControlShaderCode) { + d->m_tessControlShaderCode = tessellationControlShaderCode; + notifyPropertyChange(QByteArrayLiteral("tessellationControlSourceCode"), + tessellationControlShaderCode); + emit tessellationControlShaderCodeChanged(); + } +} + +QByteArray QShaderProgram::tessellationControlShaderCode() const +{ + Q_D(const QShaderProgram); + return d->m_tessControlShaderCode; +} + +void QShaderProgram::setTessellationEvaluationShaderCode(const QByteArray &tessellationEvaluationShaderCode) { Q_D(QShaderProgram); - if (vertexShader != d->m_cachedVertexCode) { - d->m_cachedVertexCode = vertexShader; - emit vertexShaderChanged(); + if (tessellationEvaluationShaderCode != d->m_tessEvalShaderCode) { + d->m_tessEvalShaderCode = tessellationEvaluationShaderCode; + notifyPropertyChange(QByteArrayLiteral("tessellationEvaluationSourceCode"), + tessellationEvaluationShaderCode); + emit tessellationEvaluationShaderCodeChanged(); + } +} + +QByteArray QShaderProgram::tessellationEvaluationShaderCode() const +{ + Q_D(const QShaderProgram); + return d->m_tessEvalShaderCode; +} - if (d->m_changeArbiter != Q_NULLPTR) { - QScenePropertyChangePtr e(new QScenePropertyChange(NodeUpdated, this)); - e->setPropertyName(QByteArrayLiteral("vertexSourceCode")); - e->setValue(d->m_cachedVertexCode); - notifyObservers(e); - } +void QShaderProgram::setGeometryShaderCode(const QByteArray &geometryShaderCode) +{ + Q_D(QShaderProgram); + if (geometryShaderCode != d->m_geometryShaderCode) { + d->m_geometryShaderCode = geometryShaderCode; + notifyPropertyChange(QByteArrayLiteral("geometrySourceCode"), + geometryShaderCode); + emit geometryShaderCodeChanged(); } } +QByteArray QShaderProgram::geometryShaderCode() const +{ + Q_D(const QShaderProgram); + return d->m_geometryShaderCode; +} + /*! * Sets the fragmentShader from raw data in \a fragmentShader. */ -void QShaderProgram::setFragmentShader(const QByteArray &fragmentShader) +void QShaderProgram::setFragmentShaderCode(const QByteArray &fragmentShaderCode) { Q_D(QShaderProgram); - if (fragmentShader != d->m_cachedFragmentCode) { - d->m_cachedFragmentCode = fragmentShader; - emit fragmentShaderChanged(); + if (fragmentShaderCode != d->m_fragmentShaderCode) { + d->m_fragmentShaderCode = fragmentShaderCode; + notifyPropertyChange(QByteArrayLiteral("fragmentSourceCode"), + fragmentShaderCode); + emit fragmentShaderCodeChanged(); + } +} - if (d->m_changeArbiter != Q_NULLPTR) { - QScenePropertyChangePtr e(new QScenePropertyChange(NodeUpdated, this)); - e->setPropertyName(QByteArrayLiteral("fragmentSourceCode")); - e->setValue(d->m_cachedFragmentCode); - notifyObservers(e); - } +QByteArray QShaderProgram::fragmentShaderCode() const +{ + Q_D(const QShaderProgram); + return d->m_fragmentShaderCode; +} + +void QShaderProgram::setComputeShaderCode(const QByteArray &computeShaderCode) +{ + Q_D(QShaderProgram); + if (computeShaderCode != d->m_computeShaderCode) { + d->m_computeShaderCode = computeShaderCode; + notifyPropertyChange(QByteArrayLiteral("computeSourceCode"), + computeShaderCode); + emit computeShaderCodeChanged(); } } -QByteArray QShaderProgram::vertexSourceCode() const +QByteArray QShaderProgram::computeShaderCode() const { Q_D(const QShaderProgram); - return d->m_cachedVertexCode; + return d->m_computeShaderCode; } -QByteArray QShaderProgram::fragmentSourceCode() const +void QShaderProgram::setShaderCode(ShaderType type, const QByteArray &shaderCode) +{ + switch (type) { + case Vertex: + setVertexShaderCode(shaderCode); + break; + case TessellationControl: + setTessellationControlShaderCode(shaderCode); + break; + case TessellationEvaluation: + setTessellationEvaluationShaderCode(shaderCode); + break; + case Geometry: + setGeometryShaderCode(shaderCode); + break; + case Fragment: + setFragmentShaderCode(shaderCode); + break; + case Compute: + setComputeShaderCode(shaderCode); + break; + default: + Q_UNREACHABLE(); + } +} + +QByteArray QShaderProgram::shaderCode(ShaderType type) const { Q_D(const QShaderProgram); - return d->m_cachedFragmentCode; + switch (type) { + case Vertex: + return d->m_vertexShaderCode; + case TessellationControl: + return d->m_tessControlShaderCode; + case TessellationEvaluation: + return d->m_tessEvalShaderCode; + case Geometry: + return d->m_geometryShaderCode; + case Fragment: + return d->m_fragmentShaderCode; + case Compute: + return d->m_computeShaderCode; + default: + Q_UNREACHABLE(); + } } } // of namespace Qt3D diff --git a/src/render/frontend/qshaderprogram.h b/src/render/frontend/qshaderprogram.h index 444bc33fe..350e25f18 100644 --- a/src/render/frontend/qshaderprogram.h +++ b/src/render/frontend/qshaderprogram.h @@ -55,41 +55,93 @@ class QShaderProgramPrivate; class QT3DRENDERERSHARED_EXPORT QShaderProgram : public QAbstractShader { Q_OBJECT - Q_PROPERTY(QString vertexSourceFile READ vertexSourceFile WRITE setVertexSourceFile NOTIFY vertexSourceFileChanged) - Q_PROPERTY(QString fragmentSourceFile READ fragmentSourceFile WRITE setFragmentSourceFile NOTIFY fragmentSourceFileChanged) - Q_PROPERTY(QByteArray vertexShader READ vertexSourceCode WRITE setVertexShader NOTIFY vertexShaderChanged) - Q_PROPERTY(QByteArray fragmentShader READ fragmentSourceCode WRITE setFragmentShader NOTIFY fragmentShaderChanged) + + Q_PROPERTY(QString vertexShaderSourceFile READ vertexShaderSourceFile WRITE setVertexShaderSourceFile NOTIFY vertexShaderSourceFileChanged) + Q_PROPERTY(QString tessellationControlShaderSourceFile READ tessellationControlShaderSourceFile WRITE setTessellationControlShaderSourceFile NOTIFY tessellationControlShaderSourceFileChanged) + Q_PROPERTY(QString tessellationEvaluationShaderSourceFile READ tessellationEvaluationShaderSourceFile WRITE setTessellationEvaluationShaderSourceFile NOTIFY tessellationEvaluationShaderSourceFileChanged) + Q_PROPERTY(QString geometryShaderSourceFile READ geometryShaderSourceFile WRITE setGeometryShaderSourceFile NOTIFY geometryShaderSourceFileChanged) + Q_PROPERTY(QString fragmentShaderSourceFile READ fragmentShaderSourceFile WRITE setFragmentShaderSourceFile NOTIFY fragmentShaderSourceFileChanged) + Q_PROPERTY(QString computeShaderSourceFile READ computeShaderSourceFile WRITE setComputeShaderSourceFile NOTIFY computeShaderSourceFileChanged) + Q_PROPERTY(QByteArray vertexShaderCode READ vertexShaderCode WRITE setVertexShaderCode NOTIFY vertexShaderCodeChanged) + Q_PROPERTY(QByteArray tessellationControlShaderCode READ tessellationControlShaderCode WRITE setTessellationControlShaderCode NOTIFY tessellationControlShaderCodeChanged) + Q_PROPERTY(QByteArray tessellationEvaluationShaderCode READ tessellationEvaluationShaderCode WRITE setTessellationEvaluationShaderCode NOTIFY tessellationEvaluationShaderCodeChanged) + Q_PROPERTY(QByteArray geometryShaderCode READ geometryShaderCode WRITE setGeometryShaderCode NOTIFY geometryShaderCodeChanged) + Q_PROPERTY(QByteArray fragmentShaderCode READ fragmentShaderCode WRITE setFragmentShaderCode NOTIFY fragmentShaderCodeChanged) + Q_PROPERTY(QByteArray computeShaderCode READ computeShaderCode WRITE setComputeShaderCode NOTIFY computeShaderCodeChanged) + Q_ENUMS(ShaderType) public: explicit QShaderProgram(QNode *parent = 0); + enum ShaderType { + Vertex = 0, + Fragment, + TessellationControl, + TessellationEvaluation, + Geometry, + Compute + }; + void copy(const QNode *ref) Q_DECL_OVERRIDE; - void setVertexSourceFile(const QString &vertexSourceFile); - QString vertexSourceFile() const; + // Source from file + void setVertexShaderSourceFile(const QString &vertexShaderSourceFile); + QString vertexShaderSourceFile() const; + + void setTessellationControlShaderSourceFile(const QString &tessellationControlShaderSourceFile); + QString tessellationControlShaderSourceFile() const; + + void setTessellationEvaluationShaderSourceFile(const QString &tessellationEvaluationShaderSourceFile); + QString tessellationEvaluationShaderSourceFile() const; + + void setGeometryShaderSourceFile(const QString &geometryShaderSourceFile); + QString geometryShaderSourceFile() const; + + void setFragmentShaderSourceFile(const QString &fragmentShaderSourceFile); + QString fragmentShaderSourceFile() const; + + void setComputeShaderSourceFile(const QString &computeShaderSourceFile); + QString computeShaderSourceFile() const; + + void setShaderSourceFile(ShaderType type, const QString &sourceFile); + QString shaderSourceFile(ShaderType type) const; + + // Source code in-line + void setVertexShaderCode(const QByteArray &vertexShaderCode); + QByteArray vertexShaderCode() const; + + void setTessellationControlShaderCode(const QByteArray &tessellationControlShaderCode); + QByteArray tessellationControlShaderCode() const; - void setFragmentSourceFile(const QString &fragmentSource); - QString fragmentSourceFile() const; + void setTessellationEvaluationShaderCode(const QByteArray &tessellationEvaluationShaderCode); + QByteArray tessellationEvaluationShaderCode() const; - void setVertexShader(const QByteArray &vertexShader); - void setFragmentShader(const QByteArray &fragmentShader); + void setGeometryShaderCode(const QByteArray &geometryShaderCode); + QByteArray geometryShaderCode() const; - QByteArray vertexSourceCode() const; - QByteArray fragmentSourceCode() const; + void setFragmentShaderCode(const QByteArray &fragmentShaderCode); + QByteArray fragmentShaderCode() const; - bool isLoaded() const; + void setComputeShaderCode(const QByteArray &computeShaderCode); + QByteArray computeShaderCode() const; - /** - * @brief load - call from main / worker thread to do synchronous - * loading of shader source files - */ - void load(); + void setShaderCode(ShaderType type, const QByteArray &shaderCode); + QByteArray shaderCode(ShaderType type) const; Q_SIGNALS: - void vertexSourceFileChanged(); - void fragmentSourceFileChanged(); - void vertexShaderChanged(); - void fragmentShaderChanged(); + void vertexShaderSourceFileChanged(); + void tessellationControlShaderSourceFileChanged(); + void tessellationEvaluationShaderSourceFileChanged(); + void geometryShaderSourceFileChanged(); + void fragmentShaderSourceFileChanged(); + void computeShaderSourceFileChanged(); + + void vertexShaderCodeChanged(); + void tessellationControlShaderCodeChanged(); + void tessellationEvaluationShaderCodeChanged(); + void geometryShaderCodeChanged(); + void fragmentShaderCodeChanged(); + void computeShaderCodeChanged(); protected: Q_DECLARE_PRIVATE(QShaderProgram) diff --git a/src/render/frontend/qshaderprogram_p.h b/src/render/frontend/qshaderprogram_p.h index ec3863054..2489c95da 100644 --- a/src/render/frontend/qshaderprogram_p.h +++ b/src/render/frontend/qshaderprogram_p.h @@ -57,9 +57,17 @@ public: Q_DECLARE_PUBLIC(QShaderProgram) QString m_vertexSourceFile; + QString m_tessControlSourceFile; + QString m_tessEvalSourceFile; + QString m_geometrySourceFile; QString m_fragmentSourceFile; - QByteArray m_cachedVertexCode; - QByteArray m_cachedFragmentCode; + QString m_computeSourceFile; + QByteArray m_vertexShaderCode; + QByteArray m_tessControlShaderCode; + QByteArray m_tessEvalShaderCode; + QByteArray m_geometryShaderCode; + QByteArray m_fragmentShaderCode; + QByteArray m_computeShaderCode; }; } // Qt3D diff --git a/src/render/io/gltfparser.cpp b/src/render/io/gltfparser.cpp index 91ae3f81f..527f10272 100644 --- a/src/render/io/gltfparser.cpp +++ b/src/render/io/gltfparser.cpp @@ -733,8 +733,8 @@ void GLTFParser::processJSONProgram( QString id, QJsonObject jsonObj) return; } - prog->setFragmentSourceFile(m_shaderPaths[fragName]); - prog->setVertexSourceFile(m_shaderPaths[vertName]); + prog->setFragmentShaderSourceFile(m_shaderPaths[fragName]); + prog->setVertexShaderSourceFile(m_shaderPaths[vertName]); m_programs[id] = prog; } |