summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2014-09-20 15:52:08 +0100
committerSean Harmer <sean.harmer@kdab.com>2014-09-21 13:27:04 +0200
commit1d2aaae6a0e9d832690a7b6b1f872aaeca3ed86a (patch)
tree76a8abea41870d60953a75b4da8a29fe3cd7f1f9 /src
parent8f8ef078353dd4d96b35804117acf914a93f9412 (diff)
Add support for remaining shader stages and rename some properties
Examples updated to reflect new QShaderProgram property names. Next commit will add a new example to test the handling of tessellation and geometry shader stages. We need to somehow expose buffers and image units to make use of compute shaders. Change-Id: Idf76cef97a42d5829402c8aa8cc4e288678a3407 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/render/backend/renderer.cpp4
-rw-r--r--src/render/backend/rendershader.cpp145
-rw-r--r--src/render/backend/rendershader_p.h7
-rw-r--r--src/render/frontend/qshaderprogram.cpp322
-rw-r--r--src/render/frontend/qshaderprogram.h96
-rw-r--r--src/render/frontend/qshaderprogram_p.h12
-rw-r--r--src/render/io/gltfparser.cpp4
7 files changed, 445 insertions, 145 deletions
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;
}