summaryrefslogtreecommitdiffstats
path: root/src/render/backend/rendershaderdata.cpp
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2015-01-21 15:23:39 +0100
committerPaul Lemire <paul.lemire@kdab.com>2015-01-24 14:30:24 +0100
commiteeab3dabf1b374867377128330c302228759bb5f (patch)
treefd7620fd743a0a57bf7f2f8dff9a9c756c65f100 /src/render/backend/rendershaderdata.cpp
parent7bc827504190858bccdff82f63211f4988bc48df (diff)
RenderShaderData: ModelToEye/ModelToWorld property transform
* Reuse jobs in QRenderAspect * Added FramePreparationJob which: - updates RenderShaderData with node world matrix - create bounding volume for nodes * RenderShaderData slightly modified to accommodate the transformed properties - needsUpdate now takes the viewMatrix - fix a bug where for a nested array, order wasn't maintained if not all the elements had been updated Change-Id: I0d91dc1d52c4333be74cce56c334aea70498138e Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/render/backend/rendershaderdata.cpp')
-rw-r--r--src/render/backend/rendershaderdata.cpp88
1 files changed, 84 insertions, 4 deletions
diff --git a/src/render/backend/rendershaderdata.cpp b/src/render/backend/rendershaderdata.cpp
index 0466f6e67..b8f78aeb5 100644
--- a/src/render/backend/rendershaderdata.cpp
+++ b/src/render/backend/rendershaderdata.cpp
@@ -103,11 +103,37 @@ void RenderShaderData::clearUpdate()
}
// Called by renderview jobs (several concurrent threads)
-bool RenderShaderData::needsUpdate()
+/*!
+ \internal
+ Lookup if the current ShaderData or a nested ShaderData has updated properties.
+ UpdateProperties contains either the value of the propertie of a QNodeId if it's another ShaderData.
+ Transformed properties are updated for all of ShaderData that have ones at the point.
+
+ \note This needs to be performed for every top level RenderShaderData every time it is used.
+ As we don't know if the transformed properties use the same viewMatrix for all RenderViews.
+ */
+bool RenderShaderData::needsUpdate(const QMatrix4x4 &viewMatrix)
{
// We can't perform this only once as we don't know if we would be call as the root or a
// nested RenderShaderData
QMutexLocker lock(m_mutex);
+
+ // Update transformed properties
+ // We check the matrices and decide if the transform has changed since the previous call to needsUpdate
+ if (m_viewMatrix != viewMatrix) {
+ m_viewMatrix = viewMatrix;
+ const QHash<QString, QShaderData::TransformType>::const_iterator transformedEnd = m_transformedProperties.end();
+ QHash<QString, QShaderData::TransformType>::const_iterator transformedIt = m_transformedProperties.begin();
+
+ while (transformedIt != transformedEnd) {
+ if (transformedIt.value() == QShaderData::ModelToEye) {
+ m_updatedProperties.insert(transformedIt.key(), m_viewMatrix * m_worldMatrix * m_originalProperties.value(transformedIt.key()).value<QVector3D>());
+ m_properties.insert(transformedIt.key(), m_viewMatrix * m_worldMatrix * m_originalProperties.value(transformedIt.key()).value<QVector3D>());
+ }
+ ++transformedIt;
+ }
+ }
+
const QHash<QString, QVariant>::const_iterator end = m_nestedShaderDataProperties.end();
QHash<QString, QVariant>::const_iterator it = m_nestedShaderDataProperties.begin();
@@ -116,14 +142,20 @@ bool RenderShaderData::needsUpdate()
QVariantList updatedNodes;
Q_FOREACH (const QVariant &v, it.value().value<QVariantList>()) {
RenderShaderData *nested = m_manager->lookupResource(v.value<QNodeId>());
- if (nested != Q_NULLPTR && nested->needsUpdate())
+ if (nested != Q_NULLPTR) {
+ // We need to add the nested nodes the the updated property list
+ // as if we need to maintain order
+ // if node[0] doesn't need update but node[1] does,
+ // if we only have a single element, the renderer would update element [0]
+ nested->needsUpdate(viewMatrix);
updatedNodes << v;
+ }
}
if (!updatedNodes.empty())
m_updatedProperties.insert(it.key(), updatedNodes);
} else {
RenderShaderData *nested = m_manager->lookupResource(it.value().value<QNodeId>());
- if (nested != Q_NULLPTR && nested->needsUpdate())
+ if (nested != Q_NULLPTR && nested->needsUpdate(viewMatrix))
m_updatedProperties.insert(it.key(), it.value());
}
++it;
@@ -131,6 +163,27 @@ bool RenderShaderData::needsUpdate()
return m_updatedProperties.size() > 0;
}
+void RenderShaderData::updateTransformedProperties(const QMatrix4x4 &nodeWorldMatrix)
+{
+ if (m_worldMatrix != nodeWorldMatrix) {
+ m_worldMatrix = nodeWorldMatrix;
+
+ const QHash<QString, QShaderData::TransformType>::const_iterator transformedEnd = m_transformedProperties.end();
+ QHash<QString, QShaderData::TransformType>::const_iterator transformedIt = m_transformedProperties.begin();
+
+ while (transformedIt != transformedEnd) {
+ if (transformedIt.value() == QShaderData::ModelToEye) {
+ m_updatedProperties.insert(transformedIt.key(), m_viewMatrix * m_worldMatrix * m_originalProperties.value(transformedIt.key()).value<QVector3D>());
+ m_properties.insert(transformedIt.key(), m_viewMatrix * m_worldMatrix * m_originalProperties.value(transformedIt.key()).value<QVector3D>());
+ } else {
+ m_updatedProperties.insert(transformedIt.key(), m_worldMatrix * m_originalProperties.value(transformedIt.key()).value<QVector3D>());
+ m_properties.insert(transformedIt.key(), m_worldMatrix * m_originalProperties.value(transformedIt.key()).value<QVector3D>());
+ }
+ ++transformedIt;
+ }
+ }
+}
+
// This will add the RenderShaderData to be cleared from updates at the end of the frame
// by the cleanup job
// Called by renderview jobs (several concurrent threads)
@@ -157,6 +210,7 @@ void RenderShaderData::readPeerProperties(QShaderData *shaderData)
QString propertyName = QString::fromLatin1(property.name());
m_properties.insert(propertyName, propertyValue);
+ m_originalProperties.insert(propertyName, propertyValue);
// We check if the property is a QNodeId or QList<QNodeId> so that we can
// check nested QShaderData for update
@@ -168,6 +222,21 @@ void RenderShaderData::readPeerProperties(QShaderData *shaderData)
m_nestedShaderDataProperties.insert(propertyName, propertyValue);
}
}
+
+ // We look for transformed properties
+ QHash<QString, QVariant>::iterator it = m_properties.begin();
+ const QHash<QString, QVariant>::iterator end = m_properties.end();
+
+ while (it != end) {
+ if (static_cast<QMetaType::Type>(it.value().type()) == QMetaType::QVector3D) {
+ // if there is a matching QShaderData::TransformType propertyTransformed
+ QVariant value = m_properties.value(it.key() + QStringLiteral("Transformed"));
+ // if that's the case, we apply a space transformation to the property
+ if (value.isValid() && value.type() == QVariant::Int)
+ m_transformedProperties.insert(it.key(), static_cast<QShaderData::TransformType>(value.toInt()));
+ }
+ ++it;
+ }
}
void RenderShaderData::setManager(ShaderDataManager *manager)
@@ -185,7 +254,16 @@ void RenderShaderData::sceneChangeEvent(const QSceneChangePtr &e)
// Note we aren't notified about nested QShaderData in this call
// only scalar / vec properties
if (m_properties.contains(propertyName)) {
- const QVariant &val = m_propertyReader->readProperty(propertyChange->value());
+ QVariant val = m_propertyReader->readProperty(propertyChange->value());
+ // If this is a Transformed property, we need to multiply against the correct
+ // matrices
+ m_originalProperties.insert(propertyName, val);
+ if (m_transformedProperties.contains(propertyName)) {
+ if (m_transformedProperties[propertyName] == QShaderData::ModelToEye)
+ val = m_viewMatrix * m_worldMatrix * val.value<QVector3D>();
+ else
+ val = m_worldMatrix * val.value<QVector3D>();
+ }
m_properties.insert(propertyName, val);
m_updatedProperties.insert(propertyName, val);
}
@@ -193,11 +271,13 @@ void RenderShaderData::sceneChangeEvent(const QSceneChangePtr &e)
}
case NodeAdded: {
m_properties.insert(propertyName, m_propertyReader->readProperty(propertyChange->value()));
+ m_originalProperties.insert(propertyName, m_propertyReader->readProperty(propertyChange->value()));
m_nestedShaderDataProperties.insert(propertyName, propertyChange->value());
break;
}
case NodeRemoved: {
if (m_properties.contains(propertyName)) {
+ m_originalProperties.remove(propertyName);
m_properties.remove(propertyName);
m_nestedShaderDataProperties.remove(propertyName);
}