summaryrefslogtreecommitdiffstats
path: root/src/render/materialsystem/shaderdata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/materialsystem/shaderdata.cpp')
-rw-r--r--src/render/materialsystem/shaderdata.cpp195
1 files changed, 65 insertions, 130 deletions
diff --git a/src/render/materialsystem/shaderdata.cpp b/src/render/materialsystem/shaderdata.cpp
index 1f68bed13..e7c8a1c37 100644
--- a/src/render/materialsystem/shaderdata.cpp
+++ b/src/render/materialsystem/shaderdata.cpp
@@ -94,7 +94,6 @@ void ShaderData::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
const QVariant &propertyValue = entry.second;
const QString propertyName = QString::fromLatin1(entry.first);
- m_properties.insert(propertyName, propertyValue);
m_originalProperties.insert(propertyName, propertyValue);
// We check if the property is a QNodeId or QVector<QNodeId> so that we can
@@ -108,14 +107,15 @@ void ShaderData::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
}
}
- // We look for transformed properties
- QHash<QString, QVariant>::iterator it = m_properties.begin();
- const QHash<QString, QVariant>::iterator end = m_properties.end();
+ // We look for transformed properties once the complete hash of
+ // originalProperties is available
+ QHash<QString, QVariant>::iterator it = m_originalProperties.begin();
+ const QHash<QString, QVariant>::iterator end = m_originalProperties.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() + QLatin1String("Transformed"));
+ QVariant value = m_originalProperties.value(it.key() + QLatin1String("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<TransformType>(value.toInt()));
@@ -138,135 +138,67 @@ ShaderData *ShaderData::lookupResource(QNodeId id)
// Call by cleanup job (single thread)
void ShaderData::clearUpdatedProperties()
{
- m_updatedProperties.clear();
- const QHash<QString, QVariant>::const_iterator end = m_nestedShaderDataProperties.end();
- QHash<QString, QVariant>::const_iterator it = m_nestedShaderDataProperties.begin();
-
- while (it != end) {
- if (it.value().userType() == QMetaType::QVariantList) {
- const auto values = it.value().value<QVariantList>();
- for (const QVariant &v : values) {
- ShaderData *nested = lookupResource(v.value<QNodeId>());
- if (nested != nullptr)
- nested->clearUpdatedProperties();
- }
- } else {
- ShaderData *nested = lookupResource(it.value().value<QNodeId>());
- if (nested != nullptr)
- nested->clearUpdatedProperties();
- }
- ++it;
- }
+ // DISABLED: Is only useful when building UBO from a ShaderData, which is disable since 5.7
+ // const QHash<QString, QVariant>::const_iterator end = m_nestedShaderDataProperties.end();
+ // QHash<QString, QVariant>::const_iterator it = m_nestedShaderDataProperties.begin();
+
+ // while (it != end) {
+ // if (it.value().userType() == QMetaType::QVariantList) {
+ // const auto values = it.value().value<QVariantList>();
+ // for (const QVariant &v : values) {
+ // ShaderData *nested = lookupResource(v.value<QNodeId>());
+ // if (nested != nullptr)
+ // nested->clearUpdatedProperties();
+ // }
+ // } else {
+ // ShaderData *nested = lookupResource(it.value().value<QNodeId>());
+ // if (nested != nullptr)
+ // nested->clearUpdatedProperties();
+ // }
+ // ++it;
+ // }
}
void ShaderData::cleanup(NodeManagers *managers)
{
- for (Qt3DCore::QNodeId id : qAsConst(m_updatedShaderData)) {
- ShaderData *shaderData = ShaderData::lookupResource(managers, id);
- if (shaderData)
- shaderData->clearUpdatedProperties();
- }
+ Q_UNUSED(managers)
+ // DISABLED: Is only useful when building UBO from a ShaderData, which is disable since 5.7
+ // for (Qt3DCore::QNodeId id : qAsConst(m_updatedShaderData)) {
+ // ShaderData *shaderData = ShaderData::lookupResource(managers, id);
+ // if (shaderData)
+ // shaderData->clearUpdatedProperties();
+ // }
m_updatedShaderData.clear();
}
-// Called by renderview jobs (several concurrent threads)
-/*!
- \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 ShaderData every time it is used.
- As we don't know if the transformed properties use the same viewMatrix for all RenderViews.
- */
-bool ShaderData::updateViewTransform(const QMatrix4x4 &viewMatrix)
+QVariant ShaderData::getTransformedProperty(const QString &name, 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 ShaderData
- 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, TransformType>::const_iterator transformedEnd = m_transformedProperties.end();
- QHash<QString, TransformType>::const_iterator transformedIt = m_transformedProperties.begin();
-
- while (transformedIt != transformedEnd) {
- if (transformedIt.value() == 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;
+ // Note protecting m_worldMatrix at this point as we assume all world updates
+ // have been performed when reaching this point
+ auto it = m_transformedProperties.find(name);
+ if (it != m_transformedProperties.end()) {
+ const TransformType transformType = it.value();
+ switch (transformType) {
+ case ModelToEye:
+ return QVariant::fromValue(viewMatrix * m_worldMatrix * m_originalProperties.value(name).value<QVector3D>());
+ case ModelToWorld:
+ return QVariant::fromValue(m_worldMatrix * m_originalProperties.value(it.key()).value<QVector3D>());
+ case ModelToWorldDirection:
+ return QVariant::fromValue((m_worldMatrix * QVector4D(m_originalProperties.value(it.key()).value<QVector3D>(), 0.0f)).toVector3D());
+ case NoTransform:
+ break;
}
}
- const QHash<QString, QVariant>::const_iterator end = m_nestedShaderDataProperties.end();
- QHash<QString, QVariant>::const_iterator it = m_nestedShaderDataProperties.begin();
-
- while (it != end) {
- const int userType = it.value().userType();
-
- if (userType == QMetaType::QVariantList) {
- QVariantList updatedNodes;
- bool nestedNeedsUpdate = false;
- const QVariantList values = variant_value<QVariantList>(it.value());
- for (const QVariant &v : values) {
- if (v.userType() != qNodeIdTypeId)
- continue;
-
- const Qt3DCore::QNodeId nestedId = variant_value<Qt3DCore::QNodeId>(v);
- ShaderData *nested = lookupResource(nestedId);
- if (nested != nullptr) {
- // We need to add the nested nodes to the updated property list
- // as 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]
- nestedNeedsUpdate |= nested->updateViewTransform(viewMatrix);
- updatedNodes << v;
- }
- }
- // Of course we only add all the nodes if at least one of the nested nodes required and update
- if (nestedNeedsUpdate && !updatedNodes.empty())
- m_updatedProperties.insert(it.key(), updatedNodes);
- } else if (userType == qNodeIdTypeId) {
- const Qt3DCore::QNodeId nestedId = variant_value<Qt3DCore::QNodeId>(it.value());
- ShaderData *nested = lookupResource(nestedId);
- if (nested != nullptr && nested->updateViewTransform(viewMatrix))
- m_updatedProperties.insert(it.key(), it.value());
- }
- ++it;
- }
- return m_updatedProperties.size() > 0;
+ return QVariant();
}
-bool ShaderData::updateWorldTransform(const QMatrix4x4 &worldMatrix)
+// Called by FramePreparationJob or by RenderView when dealing with lights
+void ShaderData::updateWorldTransform(const QMatrix4x4 &worldMatrix)
{
- // TODO: Factor this out into a job that populates data in the corresponding
- // renderview or other intermediate data structure. See QTBUG-54818
QMutexLocker lock(&m_mutex);
if (m_worldMatrix != worldMatrix) {
m_worldMatrix = worldMatrix;
-
- const QHash<QString, TransformType>::const_iterator transformedEnd = m_transformedProperties.end();
- QHash<QString, TransformType>::const_iterator transformedIt = m_transformedProperties.begin();
-
- while (transformedIt != transformedEnd) {
- if (transformedIt.value() == 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 if (transformedIt.value() == ModelToWorldDirection) {
- auto localDirection = QVector4D(m_originalProperties.value(transformedIt.key()).value<QVector3D>(), 0.0f);
- auto worldDirection = (m_worldMatrix * localDirection).toVector3D();
- m_updatedProperties.insert(transformedIt.key(), worldDirection);
- m_properties.insert(transformedIt.key(), worldDirection);
- } 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;
- }
}
- return m_updatedProperties.size() > 0;
}
// This will add the ShaderData to be cleared from updates at the end of the frame
@@ -279,6 +211,21 @@ void ShaderData::markDirty()
ShaderData::m_updatedShaderData.append(peerId());
}
+/*!
+ \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 ShaderData every time it is used.
+ As we don't know if the transformed properties use the same viewMatrix for all RenderViews.
+ */
+
+ShaderData::TransformType ShaderData::propertyTransformType(const QString &name) const
+{
+ return m_transformedProperties.value(name, TransformType::NoTransform);
+}
+
void ShaderData::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
if (!m_propertyReader.isNull() && e->type() == PropertyUpdated) {
@@ -297,19 +244,7 @@ void ShaderData::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
// Note we aren't notified about nested QShaderData in this call
// only scalar / vec properties
- if (m_properties.contains(propertyName)) {
- // If this is a Transformed property, we need to multiply against the correct
- // matrices
- m_originalProperties.insert(propertyName, propertyValue);
- if (m_transformedProperties.contains(propertyName)) {
- if (m_transformedProperties[propertyName] == ModelToEye)
- propertyValue = m_viewMatrix * m_worldMatrix * propertyValue.value<QVector3D>();
- else
- propertyValue = m_worldMatrix * propertyValue.value<QVector3D>();
- }
- m_properties.insert(propertyName, propertyValue);
- m_updatedProperties.insert(propertyName, propertyValue);
- }
+ m_originalProperties.insert(propertyName, propertyValue);
BackendNode::markDirty(AbstractRenderer::AllDirty);
}