From bc9eae90c098b0080e65b4e553b5c34f040c9382 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 18 May 2018 13:28:43 +0200 Subject: Ensure animated color components are in range [0, 1] ...and never very slightly above 1. Change-Id: I9ba17d75a383c3f2a76464f59db471eb12b045dc Reviewed-by: Christian Stromme --- src/runtime/q3dsanimationmanager.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/runtime/q3dsanimationmanager.cpp b/src/runtime/q3dsanimationmanager.cpp index 9c8eadb..a7cc96b 100644 --- a/src/runtime/q3dsanimationmanager.cpp +++ b/src/runtime/q3dsanimationmanager.cpp @@ -217,6 +217,8 @@ public: void valueChanged(const QVariant &value) override; private: + QVariant stabilizeAnimatedValue(const QVariant &value, Q3DS::PropertyType type); + Q3DSGraphObject *m_target; Q3DSAnimationManager::Animatable m_animMeta; Q3DSAnimationManager *m_animationManager; @@ -229,12 +231,27 @@ void Q3DSAnimationCallback::valueChanged(const QVariant &value) // invoked once per frame. Q3DSAnimationManager::AnimationValueChange change; - change.value = value; + change.value = stabilizeAnimatedValue(value, m_animMeta.type); change.name = m_animMeta.name; change.setter = m_animMeta.setter; m_animationManager->queueChange(m_target, change); } +QVariant Q3DSAnimationCallback::stabilizeAnimatedValue(const QVariant &value, Q3DS::PropertyType type) +{ + if (type == Q3DS::Color && value.type() == QVariant::Vector3D) { + const QVector3D v = value.value(); + // rgb is already in range [0, 1] but let's make sure the 0 and 1 are really 0 and 1. + // This avoids confusing QColor when qFuzzyCompare(r, 1.0f) && r > 1.0f + const float r = qBound(0.0f, v.x(), 1.0f); + const float g = qBound(0.0f, v.y(), 1.0f); + const float b = qBound(0.0f, v.z(), 1.0f); + return QVariant::fromValue(QColor::fromRgbF(qreal(r), qreal(g), qreal(b))); + } + + return value; +} + static int componentSuffixToIndex(const QString &s) { if (s == QStringLiteral("x")) @@ -483,12 +500,21 @@ void Q3DSAnimationManager::updateAnimationHelper(const AnimationTrackListMapchannel); // Figure out the QVariant/QMetaType type enum value. - const int type = Q3DS::animatablePropertyTypeToMetaType(chIt->meta.type); + int type = Q3DS::animatablePropertyTypeToMetaType(chIt->meta.type); if (type == QVariant::Invalid) { qWarning("Cannot map channel type for animated property %s", qPrintable(channelName)); continue; } + // Workaround for QColor::fromRgbF() warning and generating invalid + // colors when some component is very slightly over 1.0. Due to the + // Qt 3D animation fw or QVariant or something else, we get + // sometimes such results. We can handle this in our side but we + // cannot let Qt 3D do the QColor creation. So pretend we have a + // QVector3D instead. This will be 'reversed' in stabilizeAnimatedValue(). + if (type == QVariant::Color) + type = QVariant::Vector3D; + // Create a mapping with a custom callback. QScopedPointer mapping(new Qt3DAnimation::QCallbackMapping); mapping->setChannelName(channelName); -- cgit v1.2.3 From 9dd28cb4e38a685922809e5f690350a7841c632a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 18 May 2018 14:11:17 +0200 Subject: Clamp opacity Change-Id: I37070212c1670c6a467f7bdb47746664832e95eb Reviewed-by: Christian Stromme --- src/runtime/q3dsscenemanager.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index 877a733..478c6d0 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -3711,6 +3711,11 @@ QMatrix4x4 generateRotationMatrix(const QVector3D &nodeRotation, Q3DSNode::Rotat } return rotationMatrix; } + +float clampOpacity(float f) +{ + return qBound(0.0f, f, 1.0f); +} } void Q3DSSceneManager::setNodeProperties(Q3DSNode *node, Qt3DCore::QEntity *entity, @@ -3781,13 +3786,13 @@ void Q3DSSceneManager::updateGlobals(Q3DSNode *node, UpdateGlobalFlags flags) globalTransform = parentData->globalTransform * data->transform->matrix(); } // update the global, inherited opacity - globalOpacity = parentData->globalOpacity * (node->localOpacity() / 100.0f); + globalOpacity = clampOpacity(parentData->globalOpacity * (node->localOpacity() / 100.0f)); // update inherited visibility globalVisibility = node->flags().testFlag(Q3DSNode::Active) && parentData->globalVisibility; } else { if (!flags.testFlag(UpdateGlobalsSkipTransform)) globalTransform = data->transform->matrix(); - globalOpacity = node->localOpacity() / 100.0f; + globalOpacity = clampOpacity(node->localOpacity() / 100.0f); globalVisibility = node->flags().testFlag(Q3DSNode::Active); } @@ -4257,7 +4262,7 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS) QVector params = prepareDefaultMaterial(defaultMaterial, sm.referencedMaterial, model3DS); // Update parameter values. Q3DSDefaultMaterialAttached *defMatData = static_cast(defaultMaterial->attached()); - defMatData->opacity = modelData->globalOpacity * (defaultMaterial->opacity() / 100.0f); + defMatData->opacity = clampOpacity(modelData->globalOpacity * (defaultMaterial->opacity() / 100.0f)); updateDefaultMaterial(defaultMaterial, sm.referencedMaterial); // Setup camera properties @@ -4448,7 +4453,7 @@ void Q3DSSceneManager::retagSubMeshes(Q3DSModelNode *model3DS) // not yet be created. This is not a problem in practice. if (sm.resolvedMaterial->type() == Q3DSGraphObject::DefaultMaterial) { auto defaultMaterial = static_cast(sm.resolvedMaterial); - opacity *= defaultMaterial->opacity() / 100.0f; + opacity = clampOpacity(opacity * defaultMaterial->opacity() / 100.0f); // Check maps for transparency as well hasTransparency = ((defaultMaterial->diffuseMap() && defaultMaterial->diffuseMap()->hasTransparency(m_presentation)) || (defaultMaterial->diffuseMap2() && defaultMaterial->diffuseMap2()->hasTransparency(m_presentation)) || @@ -6372,7 +6377,7 @@ void Q3DSSceneManager::updateModel(Q3DSModelNode *model3DS) auto m = static_cast(sm.resolvedMaterial); auto d = static_cast(m->attached()); if (d && d->materialDiffuseParam) { - const float opacity = data->globalOpacity * (m->opacity() / 100.0f); + const float opacity = clampOpacity(data->globalOpacity * (m->opacity() / 100.0f)); QVector4D c = d->materialDiffuseParam->value().value(); c.setW(opacity); d->materialDiffuseParam->setValue(c); @@ -6809,7 +6814,7 @@ void Q3DSSceneManager::updateSubTreeRecursive(Q3DSGraphObject *obj) Q3DSDefaultMaterialAttached *data = static_cast(mat3DS->attached()); if (data && (data->frameDirty & Q3DSGraphObjectAttached::DefaultMaterialDirty)) { Q3DSModelAttached *modelData = static_cast(data->model3DS->attached()); - data->opacity = modelData->globalOpacity * (mat3DS->opacity() / 100.0f); + data->opacity = clampOpacity(modelData->globalOpacity * (mat3DS->opacity() / 100.0f)); updateDefaultMaterial(mat3DS); retagSubMeshes(data->model3DS); m_wasDirty = true; -- cgit v1.2.3 From 52e15f5a192e196e3d8ab65de0766bee3b03d0a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A4=C3=A4tt=C3=A4=20Antti?= Date: Fri, 18 May 2018 16:30:58 +0300 Subject: Fix custom material area light direction Task-number: QT3DS-1714 Change-Id: I6e54bd90756276ce01f30254f7f8b3721366adec Reviewed-by: Miikka Heikkinen Reviewed-by: Laszlo Agocs --- res/effectlib/sampleArea.glsllib | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/res/effectlib/sampleArea.glsllib b/res/effectlib/sampleArea.glsllib index 70c7ae0..2253359 100644 --- a/res/effectlib/sampleArea.glsllib +++ b/res/effectlib/sampleArea.glsllib @@ -113,7 +113,7 @@ vec4 sampleAreaGlossy( in mat3 tanFrame, in vec3 pos, in int lightIdx, in vec3 v float sigmaV = clamp( 0.5 * roughV, 0.005, 0.5 ); vec2 UVset[5]; - mat3 lightFrame = mat3( arealights[lightIdx].right.xyz, arealights[lightIdx].up.xyz, arealights[lightIdx].direction.xyz ); + mat3 lightFrame = mat3( arealights[lightIdx].right.xyz, arealights[lightIdx].up.xyz, -arealights[lightIdx].direction.xyz ); float thetaI = acos( dot(viewDir, lightFrame[2]) ); vec2 minMaxThetaH = vec2( (thetaI - 1.5707) * 0.5, @@ -154,7 +154,7 @@ vec4 sampleAreaDiffuse( in mat3 tanFrame, in vec3 pos, in int lightIdx ) { float intensity = 0.0; vec3 finalDir; - intensity = calculateDiffuseAreaOld( -arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz, + intensity = calculateDiffuseAreaOld( arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz, arealights[lightIdx].up, arealights[lightIdx].right, pos, finalDir ); intensity *= clamp( dot(finalDir, tanFrame[2]), 0.0, 1.0 ); return vec4( intensity ); @@ -164,7 +164,7 @@ vec4 sampleAreaDiffuseTransmissive( in mat3 tanFrame, in vec3 pos, in int lightI { float intensity = 0.0; vec3 finalDir; - intensity = calculateDiffuseAreaOld( -arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz, + intensity = calculateDiffuseAreaOld( arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz, arealights[lightIdx].up, arealights[lightIdx].right, pos, finalDir ); intensity *= clamp( dot(finalDir, -tanFrame[2]), 0.0, 1.0 ); -- cgit v1.2.3 From bd0b8829a39ccfb9a44bd573ef6e015c8540fb6f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 18 May 2018 16:05:48 +0200 Subject: Make sure an opacity of 1 is really 1 Change-Id: I512a410e3ef0dd56d1035bbb7e35297b21b1f077 Reviewed-by: Christian Stromme --- src/runtime/q3dsscenemanager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index 478c6d0..9fa72a6 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -3714,7 +3714,11 @@ QMatrix4x4 generateRotationMatrix(const QVector3D &nodeRotation, Q3DSNode::Rotat float clampOpacity(float f) { - return qBound(0.0f, f, 1.0f); + f = qBound(0.0f, f, 1.0f); + // make sure 1 is 1 so we won't end up with opacity < 1 == false + if (qFuzzyCompare(f, 1.0f)) + f = 1.0f; + return f; } } -- cgit v1.2.3 From 659c96154079c35e45512b5b4e14eaa6b0c43a8f Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Fri, 18 May 2018 16:27:22 +0200 Subject: Fix IBL Overrides when there are no light probes set on layer The previous code worked only when there was a light probe on the layer to override. Change-Id: I247408111e838e5c8e8b1aa0e7d54c8db640e20f Reviewed-by: Laszlo Agocs --- src/runtime/q3dsscenemanager.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index 9fa72a6..c76ec3f 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -1644,16 +1644,21 @@ void Q3DSSceneManager::setLayerProperties(Q3DSLayerNode *layer3DS) data->iblProbeData.lightProbeProperties = new Qt3DRender::QParameter; data->iblProbeData.lightProbeProperties->setName(QLatin1String("light_probe_props")); } + data->iblProbeData.lightProbeProperties->setValue(QVector4D(0.0f, 0.0f, layer3DS->probehorizon(), layer3DS->probebright() * 0.01f)); + if (!data->iblProbeData.lightProbe2Properties) { data->iblProbeData.lightProbe2Properties = new Qt3DRender::QParameter; data->iblProbeData.lightProbe2Properties->setName(QLatin1String("light_probe2_props")); } + data->iblProbeData.lightProbe2Properties->setValue(QVector4D(0.0f, 0.0f, 0.0f, 0.0f)); + if (!data->iblProbeData.lightProbeOptions) { data->iblProbeData.lightProbeOptions = new Qt3DRender::QParameter; data->iblProbeData.lightProbeOptions->setName(QLatin1String("light_probe_opts")); } data->iblProbeData.lightProbeOptions->setValue(QVector4D(0.01745329251994329547f * layer3DS->probefov(), 0.0f, 0.0f, 0.0f)); + if (layer3DS->lightProbe()) { // initialize light probe parameters if necessary if (!data->iblProbeData.lightProbeTexture) { @@ -1746,12 +1751,6 @@ void Q3DSSceneManager::setLayerProperties(Q3DSLayerNode *layer3DS) data->iblProbeData.lightProbe2Properties->setValue(QVector4D(0.0f, 0.0f, 0.0f, 0.0f)); data->iblProbeData.lightProbeProperties->setValue(QVector4D(0.0f, 0.0f, layer3DS->probehorizon(), layer3DS->probebright() * 0.01f)); } - } else { - // No light probes set - // Still need to setup some defaults since light probes can be set on - // individual materials - data->iblProbeData.lightProbeProperties->setValue(QVector4D(0.0f, 0.0f, -1.0f, 0.0f)); - data->iblProbeData.lightProbe2Properties->setValue(QVector4D(0.0f, 0.0f, 0.0f, 0.0f)); } } @@ -4326,6 +4325,10 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS) params.append(layerData->iblProbeData.lightProbeSampler); params.append(layerData->iblProbeData.lightProbeOffset); params.append(layerData->iblProbeData.lightProbeRotation); + } else { + params.append(defMatData->lightProbeSampler); + params.append(defMatData->lightProbeOffset); + params.append(defMatData->lightProbeRotation); } if (modelData->layer3DS->lightProbe2()) { @@ -4402,6 +4405,10 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS) params.append(layerData->iblProbeData.lightProbeSampler); params.append(layerData->iblProbeData.lightProbeOffset); params.append(layerData->iblProbeData.lightProbeRotation); + } else { + params.append(custMatData->lightProbeSampler); + params.append(custMatData->lightProbeOffset); + params.append(custMatData->lightProbeRotation); } if (modelData->layer3DS->lightProbe2()) { -- cgit v1.2.3 From 14b90ebe65cddbf199f47e5f086fae6cd175222c Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 18 May 2018 16:28:05 +0200 Subject: Handle materials shared between models better Change-Id: Ibf3d150154070622b91362f343b4220d995df3c5 Reviewed-by: Andy Nichols --- src/runtime/q3dsscenemanager.cpp | 357 +++++++++++++++++++++++++-------------- src/runtime/q3dsscenemanager_p.h | 22 ++- 2 files changed, 243 insertions(+), 136 deletions(-) diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index c76ec3f..1cf047c 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -4190,7 +4190,7 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildModel(Q3DSModelNode *model3DS, Q3DSLay // follow the reference for ReferencedMaterial if (sm.material->type() == Q3DSGraphObject::ReferencedMaterial) { Q3DSReferencedMaterial *matRef = static_cast(sm.material); - sm.referencedMaterial = matRef; + sm.referencingMaterial = matRef; if (matRef->referencedMaterial()) sm.resolvedMaterial = matRef->referencedMaterial(); } @@ -4262,11 +4262,13 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS) Q3DSDefaultMaterial *defaultMaterial = static_cast(sm.resolvedMaterial); // Create parameters to the shader. - QVector params = prepareDefaultMaterial(defaultMaterial, sm.referencedMaterial, model3DS); + QVector params = prepareDefaultMaterial(defaultMaterial, sm.referencingMaterial, model3DS); + // Update parameter values. Q3DSDefaultMaterialAttached *defMatData = static_cast(defaultMaterial->attached()); - defMatData->opacity = clampOpacity(modelData->globalOpacity * (defaultMaterial->opacity() / 100.0f)); - updateDefaultMaterial(defaultMaterial, sm.referencedMaterial); + const float opacity = clampOpacity(modelData->globalOpacity * (defaultMaterial->opacity() / 100.0f)); + defMatData->perModelData[model3DS].combinedOpacity = opacity; + updateDefaultMaterial(defaultMaterial, sm.referencingMaterial, model3DS); // Setup camera properties if (layerData->cameraPropertiesParam != nullptr) @@ -4345,14 +4347,14 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS) param->setParent(layerData->entity); } - sm.materialComponent = m_matGen->generateMaterial(defaultMaterial, sm.referencedMaterial, params, lightNodes, modelData->layer3DS); + sm.materialComponent = m_matGen->generateMaterial(defaultMaterial, sm.referencingMaterial, params, lightNodes, modelData->layer3DS); sm.entity->addComponent(sm.materialComponent); } else if (sm.resolvedMaterial->type() == Q3DSGraphObject::CustomMaterial) { Q3DSCustomMaterialInstance *customMaterial = static_cast(sm.resolvedMaterial); - QVector params = prepareCustomMaterial(customMaterial, sm.referencedMaterial, model3DS); + QVector params = prepareCustomMaterial(customMaterial, sm.referencingMaterial, model3DS); Q3DSCustomMaterialAttached *custMatData = static_cast(customMaterial->attached()); - custMatData->opacity = modelData->globalOpacity; - updateCustomMaterial(customMaterial, sm.referencedMaterial); + custMatData->perModelData[model3DS].combinedOpacity = modelData->globalOpacity; + updateCustomMaterial(customMaterial, sm.referencingMaterial, model3DS); if (lightsData) { if (m_gfxLimits.shaderUniformBufferSupported) { @@ -4424,7 +4426,7 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS) // ### TODO support more than one pass auto pass = customMaterial->material()->passes().first(); - sm.materialComponent = m_customMaterialGen->generateMaterial(customMaterial, sm.referencedMaterial, params, lightNodes, modelData->layer3DS, pass); + sm.materialComponent = m_customMaterialGen->generateMaterial(customMaterial, sm.referencingMaterial, params, lightNodes, modelData->layer3DS, pass); sm.entity->addComponent(sm.materialComponent); } } @@ -4594,159 +4596,196 @@ void Q3DSSceneManager::setImageTextureFromSubPresentation(Qt3DRender::QParameter QVector Q3DSSceneManager::prepareDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS) { - QVector params; + // This function can be called more than once for the same 'm' (with a + // different 'model3DS' each time). The returned QParameter list must be + // complete in any case, but returning QParameters that were returned + // before for a different model3DS is fine. - if (!m->attached()) + const bool firstRun = !m->attached(); + if (firstRun) m->setAttached(new Q3DSDefaultMaterialAttached); Q3DSDefaultMaterialAttached *data = static_cast(m->attached()); Q3DSModelAttached *modelData = static_cast(model3DS->attached()); - data->entity = modelData->entity; - data->model3DS = model3DS; + QVector params; + + if (firstRun) + data->entity = modelData->entity; - if (!data->diffuseParam) { + if (firstRun) { data->diffuseParam = new Qt3DRender::QParameter; data->diffuseParam->setName(QLatin1String("diffuse_color")); } params.append(data->diffuseParam); - if (!data->materialDiffuseParam) { - data->materialDiffuseParam = new Qt3DRender::QParameter; - data->materialDiffuseParam->setName(QLatin1String("material_diffuse")); - } - params.append(data->materialDiffuseParam); + Q3DSMaterialAttached::PerModelData md; + md.materialDiffuseParam = new Qt3DRender::QParameter; + md.materialDiffuseParam->setName(QLatin1String("material_diffuse")); + data->perModelData.insert(model3DS, md); + params.append(md.materialDiffuseParam); + data->perModelData.insert(model3DS, md); - if (!data->specularParam) { + if (firstRun) { data->specularParam = new Qt3DRender::QParameter; data->specularParam->setName(QLatin1String("material_specular")); } params.append(data->specularParam); - if (!data->fresnelPowerParam) { + if (firstRun) { data->fresnelPowerParam = new Qt3DRender::QParameter; data->fresnelPowerParam->setName(QLatin1String("fresnelPower")); } params.append(data->fresnelPowerParam); - if (!data->bumpAmountParam) { + if (firstRun) { data->bumpAmountParam = new Qt3DRender::QParameter; data->bumpAmountParam->setName(QLatin1String("bumpAmount")); } params.append(data->bumpAmountParam); - if (!data->materialPropertiesParam) { + if (firstRun) { data->materialPropertiesParam = new Qt3DRender::QParameter; data->materialPropertiesParam->setName(QLatin1String("material_properties")); } params.append(data->materialPropertiesParam); - if (!data->translucentFalloffParam) { + if (firstRun) { data->translucentFalloffParam = new Qt3DRender::QParameter; data->translucentFalloffParam->setName(QLatin1String("translucentFalloff")); } params.append(data->translucentFalloffParam); - if (!data->diffuseLightWrapParam) { + if (firstRun) { data->diffuseLightWrapParam = new Qt3DRender::QParameter; data->diffuseLightWrapParam->setName(QLatin1String("diffuseLightWrap")); } params.append(data->diffuseLightWrapParam); - if (!data->displaceAmountParam) { + if (firstRun) { data->displaceAmountParam = new Qt3DRender::QParameter; data->displaceAmountParam->setName(QLatin1String("displaceAmount")); } params.append(data->displaceAmountParam); if (m->diffuseMap()) { - prepareTextureParameters(data->diffuseMapParams, QLatin1String("diffuseMap"), m->diffuseMap()); + if (firstRun) { + prepareTextureParameters(data->diffuseMapParams, QLatin1String("diffuseMap"), m->diffuseMap()); + static_cast(m->diffuseMap()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->diffuseMapParams.parameters()); - static_cast(m->diffuseMap()->attached())->referencingDefaultMaterials.insert(m); } if (m->diffuseMap2()) { - prepareTextureParameters(data->diffuseMap2Params, QLatin1String("diffuseMap2"), m->diffuseMap2()); + if (firstRun) { + prepareTextureParameters(data->diffuseMap2Params, QLatin1String("diffuseMap2"), m->diffuseMap2()); + static_cast(m->diffuseMap2()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->diffuseMap2Params.parameters()); - static_cast(m->diffuseMap2()->attached())->referencingDefaultMaterials.insert(m); } if (m->diffuseMap3()) { - prepareTextureParameters(data->diffuseMap3Params, QLatin1String("diffuseMap3"), m->diffuseMap3()); + if (firstRun) { + prepareTextureParameters(data->diffuseMap3Params, QLatin1String("diffuseMap3"), m->diffuseMap3()); + static_cast(m->diffuseMap3()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->diffuseMap3Params.parameters()); - static_cast(m->diffuseMap3()->attached())->referencingDefaultMaterials.insert(m); } if (m->specularReflection()) { - prepareTextureParameters(data->specularReflectionParams, QLatin1String("specularreflection"), m->specularReflection()); + if (firstRun) { + prepareTextureParameters(data->specularReflectionParams, QLatin1String("specularreflection"), m->specularReflection()); + static_cast(m->specularReflection()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->specularReflectionParams.parameters()); - static_cast(m->specularReflection()->attached())->referencingDefaultMaterials.insert(m); } if (m->specularMap()) { - prepareTextureParameters(data->specularMapParams, QLatin1String("specularMap"), m->specularMap()); + if (firstRun) { + prepareTextureParameters(data->specularMapParams, QLatin1String("specularMap"), m->specularMap()); + static_cast(m->specularMap()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->specularMapParams.parameters()); - static_cast(m->specularMap()->attached())->referencingDefaultMaterials.insert(m); } if (m->roughnessMap()) { - prepareTextureParameters(data->roughnessMapParams, QLatin1String("roughnessMap"), m->roughnessMap()); + if (firstRun) { + prepareTextureParameters(data->roughnessMapParams, QLatin1String("roughnessMap"), m->roughnessMap()); + static_cast(m->roughnessMap()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->roughnessMapParams.parameters()); - static_cast(m->roughnessMap()->attached())->referencingDefaultMaterials.insert(m); } if (m->bumpMap()) { - prepareTextureParameters(data->bumpMapParams, QLatin1String("bumpMap"), m->bumpMap()); + if (firstRun) { + prepareTextureParameters(data->bumpMapParams, QLatin1String("bumpMap"), m->bumpMap()); + static_cast(m->bumpMap()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->bumpMapParams.parameters()); - static_cast(m->bumpMap()->attached())->referencingDefaultMaterials.insert(m); } if (m->normalMap()) { - prepareTextureParameters(data->normalMapParams, QLatin1String("normalMap"), m->normalMap()); + if (firstRun) { + prepareTextureParameters(data->normalMapParams, QLatin1String("normalMap"), m->normalMap()); + static_cast(m->normalMap()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->normalMapParams.parameters()); - static_cast(m->normalMap()->attached())->referencingDefaultMaterials.insert(m); } if (m->displacementmap()) { - prepareTextureParameters(data->displacementMapParams, QLatin1String("displacementMap"), m->displacementmap()); + if (firstRun) { + prepareTextureParameters(data->displacementMapParams, QLatin1String("displacementMap"), m->displacementmap()); + static_cast(m->displacementmap()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->displacementMapParams.parameters()); - static_cast(m->displacementmap()->attached())->referencingDefaultMaterials.insert(m); } if (m->opacityMap()) { - prepareTextureParameters(data->opacityMapParams, QLatin1String("opacityMap"), m->opacityMap()); + if (firstRun) { + prepareTextureParameters(data->opacityMapParams, QLatin1String("opacityMap"), m->opacityMap()); + static_cast(m->opacityMap()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->opacityMapParams.parameters()); - static_cast(m->opacityMap()->attached())->referencingDefaultMaterials.insert(m); } if (m->emissiveMap()) { - prepareTextureParameters(data->emissiveMapParams, QLatin1String("emissiveMap"), m->emissiveMap()); + if (firstRun) { + prepareTextureParameters(data->emissiveMapParams, QLatin1String("emissiveMap"), m->emissiveMap()); + static_cast(m->emissiveMap()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->emissiveMapParams.parameters()); - static_cast(m->emissiveMap()->attached())->referencingDefaultMaterials.insert(m); } if (m->emissiveMap2()) { - prepareTextureParameters(data->emissiveMap2Params, QLatin1String("emissiveMap2"), m->emissiveMap2()); + if (firstRun) { + prepareTextureParameters(data->emissiveMap2Params, QLatin1String("emissiveMap2"), m->emissiveMap2()); + static_cast(m->emissiveMap2()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->emissiveMap2Params.parameters()); - static_cast(m->emissiveMap2()->attached())->referencingDefaultMaterials.insert(m); } if (m->translucencyMap()) { - prepareTextureParameters(data->translucencyMapParams, QLatin1String("translucencyMap"), m->translucencyMap()); + if (firstRun) { + prepareTextureParameters(data->translucencyMapParams, QLatin1String("translucencyMap"), m->translucencyMap()); + static_cast(m->translucencyMap()->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->translucencyMapParams.parameters()); - static_cast(m->translucencyMap()->attached())->referencingDefaultMaterials.insert(m); } // Lightmaps // check for referencedMaterial Overrides + // Note all the below must ignore firstRun since there's nothing saying the + // first call for a certain 'm' is the one with rm != null. Q3DSImage *lightmapIndirect = nullptr; if (rm && rm->lightmapIndirectMap()) lightmapIndirect = rm->lightmapIndirectMap(); else if (m->lightmapIndirectMap()) lightmapIndirect = m->lightmapIndirectMap(); if (lightmapIndirect) { - prepareTextureParameters(data->lightmapIndirectParams, QLatin1String("lightmapIndirect"), lightmapIndirect); + if (!data->lightmapIndirectParams.sampler) { + prepareTextureParameters(data->lightmapIndirectParams, QLatin1String("lightmapIndirect"), lightmapIndirect); + static_cast(lightmapIndirect->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->lightmapIndirectParams.parameters()); - static_cast(lightmapIndirect->attached())->referencingDefaultMaterials.insert(m); } Q3DSImage *lightmapRadiosity = nullptr; @@ -4755,9 +4794,11 @@ QVector Q3DSSceneManager::prepareDefaultMaterial(Q3DSD else if (m->lightmapRadiosityMap()) lightmapRadiosity = m->lightmapRadiosityMap(); if (lightmapRadiosity) { - prepareTextureParameters(data->lightmapRadiosityParams, QLatin1String("lightmapRadiosity"), lightmapRadiosity); + if (!data->lightmapRadiosityParams.sampler) { + prepareTextureParameters(data->lightmapRadiosityParams, QLatin1String("lightmapRadiosity"), lightmapRadiosity); + static_cast(lightmapRadiosity->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->lightmapRadiosityParams.parameters()); - static_cast(lightmapRadiosity->attached())->referencingDefaultMaterials.insert(m); } Q3DSImage *lightmapShadow = nullptr; @@ -4766,9 +4807,11 @@ QVector Q3DSSceneManager::prepareDefaultMaterial(Q3DSD else if (m->lightmapShadowMap()) lightmapShadow = m->lightmapShadowMap(); if (lightmapShadow) { - prepareTextureParameters(data->lightmapShadowParams, QLatin1String("lightmapShadow"), lightmapShadow); + if (!data->lightmapShadowParams.sampler) { + prepareTextureParameters(data->lightmapShadowParams, QLatin1String("lightmapShadow"), lightmapShadow); + static_cast(lightmapShadow->attached())->referencingDefaultMaterials.insert(m); + } params.append(data->lightmapShadowParams.parameters()); - static_cast(lightmapShadow->attached())->referencingDefaultMaterials.insert(m); } // IBL @@ -4778,27 +4821,36 @@ QVector Q3DSSceneManager::prepareDefaultMaterial(Q3DSD else if (m->lightProbe()) iblOverrideImage = m->lightProbe(); if (iblOverrideImage) { - data->lightProbeOverrideTexture = Q3DSImageManager::instance().newTextureForImageFile( - m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL, - m_profiler, "Texture for image %s", iblOverrideImage->id().constData()); - data->lightProbeSampler = new Qt3DRender::QParameter; - data->lightProbeSampler->setName(QLatin1String("light_probe")); - params.append(data->lightProbeSampler); + if (!data->lightProbeOverrideTexture) { + data->lightProbeOverrideTexture = Q3DSImageManager::instance().newTextureForImageFile( + m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL, + m_profiler, "Texture for image %s", iblOverrideImage->id().constData()); + data->lightProbeSampler = new Qt3DRender::QParameter; + data->lightProbeSampler->setName(QLatin1String("light_probe")); - data->lightProbeRotation = new Qt3DRender::QParameter; - data->lightProbeRotation->setName(QLatin1String("light_probe_rotation")); - params.append(data->lightProbeRotation); + data->lightProbeRotation = new Qt3DRender::QParameter; + data->lightProbeRotation->setName(QLatin1String("light_probe_rotation")); - data->lightProbeOffset = new Qt3DRender::QParameter; - data->lightProbeOffset->setName(QLatin1String("light_probe_offset")); + data->lightProbeOffset = new Qt3DRender::QParameter; + data->lightProbeOffset->setName(QLatin1String("light_probe_offset")); + } + params.append(data->lightProbeSampler); + params.append(data->lightProbeRotation); params.append(data->lightProbeOffset); } return params; } -void Q3DSSceneManager::updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferencedMaterial *rm) +void Q3DSSceneManager::updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS) { + // This function is typically called in a loop for each Q3DSModelNode that + // shares the same Q3DSDefaultMaterial. Having more than one model can only + // happen when a ReferencedMaterial is used. Currently we are somewhat + // wasteful in this case since setting the QParameter values over and over + // again is not really needed, with the exception of the one model-specific + // one. We'll live with this for the time being. + Q3DSDefaultMaterialAttached *data = static_cast(m->attached()); Q_ASSERT(data && data->diffuseParam); @@ -4809,11 +4861,15 @@ void Q3DSSceneManager::updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferen if (hasLighting) emissivePower = m->emissivePower() / 100.0f; + // This one depends on the combinedOpacity which depends on the + // localOpacity from the model. Hence its placement in the perModelData map. + auto perModelDataIt = data->perModelData.find(model3DS); + Q_ASSERT(perModelDataIt != data->perModelData.end()); QVector4D material_diffuse(m->emissiveColor().redF() * emissivePower, m->emissiveColor().greenF() * emissivePower, m->emissiveColor().blueF() * emissivePower, - data->opacity); - data->materialDiffuseParam->setValue(material_diffuse); + perModelDataIt->combinedOpacity); + perModelDataIt->materialDiffuseParam->setValue(material_diffuse); QVector4D material_specular(m->specularTint().redF(), m->specularTint().greenF(), @@ -5036,39 +5092,54 @@ Qt3DRender::QAbstractTexture *Q3DSSceneManager::createCustomPropertyTexture(cons QVector Q3DSSceneManager::prepareCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS) { - if (!m->attached()) + // this function can be called more than once for the same 'm' (with a different 'model3DS' each time) + + const bool firstRun = !m->attached(); + if (firstRun) m->setAttached(new Q3DSCustomMaterialAttached); Q3DSCustomMaterialAttached *data = static_cast(m->attached()); Q3DSModelAttached *modelData = static_cast(model3DS->attached()); - data->entity = modelData->entity; - data->model3DS = model3DS; + + if (firstRun) + data->entity = modelData->entity; // Generate QParameters QVector paramList; - forAllCustomProperties(m, [¶mList, data](const QString &propKey, const QVariant &, const Q3DSMaterial::PropertyElement &propMeta) { - QVariant v(0); // initial value is something dummy, ignore propValue for now - Qt3DRender::QParameter *param = new Qt3DRender::QParameter; - param->setName(propKey); - param->setValue(v); - paramList.append(param); - data->params.insert(propKey, Q3DSCustomPropertyParameter(param, v, propMeta)); - }); + if (firstRun) { + forAllCustomProperties(m, [¶mList, data](const QString &propKey, const QVariant &, const Q3DSMaterial::PropertyElement &propMeta) { + QVariant v(0); // initial value is something dummy, ignore propValue for now + Qt3DRender::QParameter *param = new Qt3DRender::QParameter; + param->setName(propKey); + param->setValue(v); + paramList.append(param); + data->params.insert(propKey, Q3DSCustomPropertyParameter(param, v, propMeta)); + }); + } else { + for (auto it = data->params.cbegin(), itEnd = data->params.cend(); it != itEnd; ++it) + paramList.append(it->param); + } - data->objectOpacityParam = new Qt3DRender::QParameter; - data->objectOpacityParam->setName(QLatin1String("object_opacity")); - paramList.append(data->objectOpacityParam); + Q3DSMaterialAttached::PerModelData md; + md.objectOpacityParam = new Qt3DRender::QParameter; + md.objectOpacityParam->setName(QLatin1String("object_opacity")); + data->perModelData.insert(model3DS, md); + paramList.append(md.objectOpacityParam); + data->perModelData.insert(model3DS, md); // Lightmaps // check for referencedMaterial Overrides + // Note all the below must ignore firstRun since there's nothing saying the + // first call for a certain 'm' is the one with rm != null. Q3DSImage *lightmapIndirect = nullptr; if (rm && rm->lightmapIndirectMap()) lightmapIndirect = rm->lightmapIndirectMap(); else if (m->lightmapIndirectMap()) lightmapIndirect = m->lightmapIndirectMap(); if (lightmapIndirect) { - prepareTextureParameters(data->lightmapIndirectParams, QLatin1String("lightmapIndirect"), lightmapIndirect); + if (!data->lightmapIndirectParams.sampler) + prepareTextureParameters(data->lightmapIndirectParams, QLatin1String("lightmapIndirect"), lightmapIndirect); paramList.append(data->lightmapIndirectParams.parameters()); } @@ -5078,7 +5149,8 @@ QVector Q3DSSceneManager::prepareCustomMaterial(Q3DSCu else if (m->lightmapRadiosityMap()) lightmapRadiosity = m->lightmapRadiosityMap(); if (lightmapRadiosity) { - prepareTextureParameters(data->lightmapRadiosityParams, QLatin1String("lightmapRadiosity"), lightmapRadiosity); + if (!data->lightmapRadiosityParams.sampler) + prepareTextureParameters(data->lightmapRadiosityParams, QLatin1String("lightmapRadiosity"), lightmapRadiosity); paramList.append(data->lightmapRadiosityParams.parameters()); } @@ -5088,7 +5160,8 @@ QVector Q3DSSceneManager::prepareCustomMaterial(Q3DSCu else if (m->lightmapShadowMap()) lightmapShadow = m->lightmapShadowMap(); if (lightmapShadow) { - prepareTextureParameters(data->lightmapShadowParams, QLatin1String("lightmapShadow"), lightmapShadow); + if (!data->lightmapShadowParams.sampler) + prepareTextureParameters(data->lightmapShadowParams, QLatin1String("lightmapShadow"), lightmapShadow); paramList.append(data->lightmapShadowParams.parameters()); } @@ -5099,27 +5172,36 @@ QVector Q3DSSceneManager::prepareCustomMaterial(Q3DSCu else if (m->lightProbe()) iblOverrideImage = m->lightProbe(); if (iblOverrideImage) { - data->lightProbeOverrideTexture = Q3DSImageManager::instance().newTextureForImageFile( - m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL, - m_profiler, "Texture for image %s", iblOverrideImage->id().constData()); - data->lightProbeSampler = new Qt3DRender::QParameter; - data->lightProbeSampler->setName(QLatin1String("light_probe")); - paramList.append(data->lightProbeSampler); + if (!data->lightProbeOverrideTexture) { + data->lightProbeOverrideTexture = Q3DSImageManager::instance().newTextureForImageFile( + m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL, + m_profiler, "Texture for image %s", iblOverrideImage->id().constData()); + data->lightProbeSampler = new Qt3DRender::QParameter; + data->lightProbeSampler->setName(QLatin1String("light_probe")); - data->lightProbeRotation = new Qt3DRender::QParameter; - data->lightProbeRotation->setName(QLatin1String("light_probe_rotation")); - paramList.append(data->lightProbeRotation); + data->lightProbeRotation = new Qt3DRender::QParameter; + data->lightProbeRotation->setName(QLatin1String("light_probe_rotation")); - data->lightProbeOffset = new Qt3DRender::QParameter; - data->lightProbeOffset->setName(QLatin1String("light_probe_offset")); + data->lightProbeOffset = new Qt3DRender::QParameter; + data->lightProbeOffset->setName(QLatin1String("light_probe_offset")); + } + paramList.append(data->lightProbeSampler); + paramList.append(data->lightProbeRotation); paramList.append(data->lightProbeOffset); } return paramList; } -void Q3DSSceneManager::updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm) +void Q3DSSceneManager::updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS) { + // This function is typically called in a loop for each Q3DSModelNode that + // shares the same Q3DSCustomMaterial(Instance). Having more than one model + // can only happen when a ReferencedMaterial is used. Currently we are + // somewhat wasteful in this case since setting the QParameter values over + // and over again is not really needed, with the exception of the one + // model-specific one. We'll live with this for the time being. + Q3DSCustomMaterialAttached *data = static_cast(m->attached()); // set all dynamic property values to the corresponding QParameters @@ -5149,7 +5231,9 @@ void Q3DSSceneManager::updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSR } }); - data->objectOpacityParam->setValue(data->opacity); + auto perModelDataIt = data->perModelData.find(model3DS); + Q_ASSERT(perModelDataIt != data->perModelData.end()); + perModelDataIt->objectOpacityParam->setValue(perModelDataIt->combinedOpacity); // Lightmaps Q3DSImage *lightmapIndirect = nullptr; @@ -6387,11 +6471,14 @@ void Q3DSSceneManager::updateModel(Q3DSModelNode *model3DS) if (sm.resolvedMaterial->type() == Q3DSGraphObject::DefaultMaterial) { auto m = static_cast(sm.resolvedMaterial); auto d = static_cast(m->attached()); - if (d && d->materialDiffuseParam) { - const float opacity = clampOpacity(data->globalOpacity * (m->opacity() / 100.0f)); - QVector4D c = d->materialDiffuseParam->value().value(); - c.setW(opacity); - d->materialDiffuseParam->setValue(c); + if (d) { + auto perModelDataIt = d->perModelData.find(model3DS); + if (perModelDataIt != d->perModelData.end()) { + perModelDataIt->combinedOpacity = clampOpacity(data->globalOpacity * (m->opacity() / 100.0f)); + QVector4D c = perModelDataIt->materialDiffuseParam->value().value(); + c.setW(perModelDataIt->combinedOpacity); + perModelDataIt->materialDiffuseParam->setValue(c); + } } } } @@ -6551,8 +6638,10 @@ void Q3DSSceneManager::updateSubTree(Q3DSGraphObject *obj) } for (Q3DSDefaultMaterial *mat3DS : m_pendingDefMatRebuild) { - if (Q3DSDefaultMaterialAttached *matData = static_cast(mat3DS->attached())) - rebuildModelMaterial(matData->model3DS); + if (Q3DSDefaultMaterialAttached *matData = static_cast(mat3DS->attached())) { + for (auto it = matData->perModelData.cbegin(), itEnd = matData->perModelData.cend(); it != itEnd; ++it) + rebuildModelMaterial(it.key()); + } } if (!m_pendingNodeHide.isEmpty()) { @@ -6677,14 +6766,17 @@ void Q3DSSceneManager::prepareNextFrame() static void markLayerForObjectDirty(Q3DSGraphObject *obj) { - auto findLayerForMat = [](Q3DSGraphObject *obj) { - Q3DSLayerNode *layer3DS = nullptr; + auto findLayersForMat = [](Q3DSGraphObject *obj) { + QVector layers; Q3DSMaterialAttached *data = static_cast(obj->attached()); - if (data && data->model3DS) { - Q3DSNodeAttached *ndata = static_cast(data->model3DS->attached()); - layer3DS = ndata->layer3DS; + if (data) { + for (auto it = data->perModelData.cbegin(), itEnd = data->perModelData.cend(); it != itEnd; ++it) { + Q3DSModelNode *model3DS = it.key(); + Q3DSNodeAttached *ndata = static_cast(model3DS->attached()); + layers.append(ndata->layer3DS); + } } - return layer3DS; + return layers; }; auto markLayerDirty = [](Q3DSLayerNode *layer3DS) { static_cast(layer3DS->attached())->wasDirty = true; @@ -6699,13 +6791,11 @@ static void markLayerForObjectDirty(Q3DSGraphObject *obj) } else if (obj->type() == Q3DSGraphObject::Image) { Q3DSImageAttached *data = static_cast(obj->attached()); for (Q3DSDefaultMaterial *mat3DS : qAsConst(data->referencingDefaultMaterials)) { - Q3DSLayerNode *layer3DS = findLayerForMat(mat3DS); - if (layer3DS) + for (Q3DSLayerNode *layer3DS : findLayersForMat(mat3DS)) markLayerDirty(layer3DS); } } else if (obj->type() == Q3DSGraphObject::DefaultMaterial || obj->type() == Q3DSGraphObject::CustomMaterial) { - Q3DSLayerNode *layer3DS = findLayerForMat(obj); - if (layer3DS) + for (Q3DSLayerNode *layer3DS : findLayersForMat(obj)) markLayerDirty(layer3DS); } else if (obj->type() == Q3DSGraphObject::Effect) { Q3DSEffectAttached *data = static_cast(obj->attached()); @@ -6824,10 +6914,13 @@ void Q3DSSceneManager::updateSubTreeRecursive(Q3DSGraphObject *obj) Q3DSDefaultMaterial *mat3DS = static_cast(obj); Q3DSDefaultMaterialAttached *data = static_cast(mat3DS->attached()); if (data && (data->frameDirty & Q3DSGraphObjectAttached::DefaultMaterialDirty)) { - Q3DSModelAttached *modelData = static_cast(data->model3DS->attached()); - data->opacity = clampOpacity(modelData->globalOpacity * (mat3DS->opacity() / 100.0f)); - updateDefaultMaterial(mat3DS); - retagSubMeshes(data->model3DS); + for (auto it = data->perModelData.begin(), itEnd = data->perModelData.end(); it != itEnd; ++it) { + Q3DSModelNode *model3DS = it.key(); + Q3DSModelAttached *modelData = static_cast(model3DS->attached()); + it->combinedOpacity = clampOpacity(modelData->globalOpacity * (mat3DS->opacity() / 100.0f)); + updateDefaultMaterial(mat3DS, nullptr, model3DS); + retagSubMeshes(model3DS); + } m_wasDirty = true; markLayerForObjectDirty(mat3DS); if (data->frameChangeFlags & Q3DSDefaultMaterial::BlendModeChanges) @@ -6840,10 +6933,13 @@ void Q3DSSceneManager::updateSubTreeRecursive(Q3DSGraphObject *obj) Q3DSCustomMaterialInstance *mat3DS = static_cast(obj); Q3DSCustomMaterialAttached *data = static_cast(mat3DS->attached()); if (data && (data->frameDirty & Q3DSGraphObjectAttached::CustomMaterialDirty)) { - Q3DSModelAttached *modelData = static_cast(data->model3DS->attached()); - data->opacity = modelData->globalOpacity; - updateCustomMaterial(mat3DS); - retagSubMeshes(data->model3DS); + for (auto it = data->perModelData.begin(), itEnd = data->perModelData.end(); it != itEnd; ++it) { + Q3DSModelNode *model3DS = it.key(); + Q3DSModelAttached *modelData = static_cast(model3DS->attached()); + it->combinedOpacity = modelData->globalOpacity; + updateCustomMaterial(mat3DS, nullptr, model3DS); + retagSubMeshes(model3DS); + } m_wasDirty = true; markLayerForObjectDirty(mat3DS); } @@ -6886,8 +6982,11 @@ void Q3DSSceneManager::updateSubTreeRecursive(Q3DSGraphObject *obj) Q3DSImageAttached *data = static_cast(image3DS->attached()); if (data && (data->frameDirty & Q3DSGraphObjectAttached::ImageDirty)) { image3DS->calculateTextureTransform(); - for (Q3DSDefaultMaterial *m : data->referencingDefaultMaterials) - updateDefaultMaterial(m); + for (Q3DSDefaultMaterial *m : data->referencingDefaultMaterials) { + Q3DSDefaultMaterialAttached *matData = m->attached(); + for (auto it = matData->perModelData.cbegin(), itEnd = matData->perModelData.cend(); it != itEnd; ++it) + updateDefaultMaterial(m, nullptr, it.key()); + } m_wasDirty = true; markLayerForObjectDirty(image3DS); } diff --git a/src/runtime/q3dsscenemanager_p.h b/src/runtime/q3dsscenemanager_p.h index d569284..d9877a9 100644 --- a/src/runtime/q3dsscenemanager_p.h +++ b/src/runtime/q3dsscenemanager_p.h @@ -434,7 +434,7 @@ public: Qt3DRender::QMaterial *materialComponent = nullptr; Q3DSGraphObject *material = nullptr; // Default, Custom, Referenced Q3DSGraphObject *resolvedMaterial = nullptr; // Default, Custom normally, but can still be Referenced for invalid refs - Q3DSReferencedMaterial *referencedMaterial = nullptr; // When valid, there are some overrides possible by referenced material + Q3DSReferencedMaterial *referencingMaterial = nullptr; // When valid, there are some overrides possible by referenced material Qt3DCore::QEntity *entity = nullptr; bool hasTransparency = false; }; @@ -460,15 +460,24 @@ struct Q3DSTextureParameters class Q3DSMaterialAttached : public Q3DSGraphObjectAttached { public: - Q3DSModelNode *model3DS = nullptr; - float opacity = 1.0f; + // One default or custom material may be associated with multiple models + // when a ReferencedMaterial is used. + struct PerModelData { + float combinedOpacity = 1.0f; + union { + Qt3DRender::QParameter *materialDiffuseParam; + Qt3DRender::QParameter *objectOpacityParam; + }; + }; + QHash perModelData; }; +Q_DECLARE_TYPEINFO(Q3DSMaterialAttached::PerModelData, Q_MOVABLE_TYPE); + class Q3DSDefaultMaterialAttached : public Q3DSMaterialAttached { public: Qt3DRender::QParameter *diffuseParam = nullptr; - Qt3DRender::QParameter *materialDiffuseParam = nullptr; Qt3DRender::QParameter *materialPropertiesParam = nullptr; Qt3DRender::QParameter *specularParam = nullptr; Qt3DRender::QParameter *fresnelPowerParam = nullptr; @@ -522,7 +531,6 @@ class Q3DSCustomMaterialAttached : public Q3DSMaterialAttached { public: QHash params; - Qt3DRender::QParameter *objectOpacityParam = nullptr; // Lightmaps Q3DSTextureParameters lightmapIndirectParams; Q3DSTextureParameters lightmapRadiosityParams; @@ -778,8 +786,8 @@ private: QVector prepareCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS); void setImageTextureFromSubPresentation(Qt3DRender::QParameter *sampler, Q3DSImage *image); void updateTextureParameters(Q3DSTextureParameters &textureParameters, Q3DSImage *image); - void updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferencedMaterial *rm = nullptr); - void updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm = nullptr); + void updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS); + void updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS); void buildEffect(Q3DSEffectInstance *eff3DS, Q3DSLayerNode *layer3DS); void updateEffectStatus(Q3DSLayerNode *layer3DS); void ensureEffectSource(Q3DSLayerNode *layer3DS); -- cgit v1.2.3 From ec67dfe0e28612ee04c954f46b737d3057d89522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A4=C3=A4tt=C3=A4=20Antti?= Date: Mon, 21 May 2018 15:51:26 +0300 Subject: Fix custom material specularity with transparency The generator needs to check the material transparency and not the shader transparency. Task-number: QT3DS-1728 Change-Id: I63b982dc19b04509006518dee752fe5af55a8562 Reviewed-by: Miikka Heikkinen --- src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp b/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp index 6d646da..e95aa33 100644 --- a/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp +++ b/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp @@ -408,7 +408,8 @@ struct ShaderGenerator : public Q3DSCustomMaterialShaderGenerator fragmentShader << "#include \"customMaterialFragBodyAO.glsllib\"\n"; // for us right now transparency means we render a glass style material - if (m_currentMaterial->shaderHasTransparency() && !m_currentMaterial->shaderIsTransmissive()) + if (m_currentMaterial->materialHasTransparency() + && !m_currentMaterial->shaderIsTransmissive()) fragmentShader << " rgba = computeGlass( normal, materialIOR, alpha, rgba );\n"; if (m_currentMaterial->shaderIsTransmissive()) fragmentShader << " rgba = computeOpacity( rgba );\n"; -- cgit v1.2.3 From 7d821e7c8ba30cb75b3be3ee4d0723c45d7d2a45 Mon Sep 17 00:00:00 2001 From: Jere Tuliniemi Date: Tue, 15 May 2018 11:31:41 +0300 Subject: Add API functions for behaviors to enable LookAt Adds calculateGlobalTransform and lookAt to the behavior API to enable the use of the CameraLookAt behavior. Null check had to be removed from the setAttribute since for vectors it checked if the length was 0 and as such never passed. Task-number: QT3DS-1284 Change-Id: I595a343202a59f4d2a49968b41c4b528259215e6 Reviewed-by: Laszlo Agocs --- src/runtime/behaviorapi/q3dsbehaviorobject.cpp | 119 ++++++++++++++++--------- src/runtime/behaviorapi/q3dsbehaviorobject_p.h | 2 + 2 files changed, 81 insertions(+), 40 deletions(-) diff --git a/src/runtime/behaviorapi/q3dsbehaviorobject.cpp b/src/runtime/behaviorapi/q3dsbehaviorobject.cpp index 9a31ce8..cf258eb 100644 --- a/src/runtime/behaviorapi/q3dsbehaviorobject.cpp +++ b/src/runtime/behaviorapi/q3dsbehaviorobject.cpp @@ -145,47 +145,45 @@ void Q3DSBehaviorObject::setAttribute(const QString &handle, const QString &attr const QStringList vecCompRef = attribute.split(QLatin1Char('.'), QString::SkipEmptyParts); if (vecCompRef.count() == 2) { QVariant newValue = obj->propertyValue(vecCompRef[0]); - if (!newValue.isNull()) { - switch (newValue.type()) { - case QVariant::Vector2D: - { - QVector2D v = newValue.value(); - if (vecCompRef[1] == QStringLiteral("x")) - v.setX(value.toFloat()); - else if (vecCompRef[1] == QStringLiteral("y")) - v.setY(value.toFloat()); - newValue = v; - } - break; - case QVariant::Vector3D: - { - QVector3D v = newValue.value(); - if (vecCompRef[1] == QStringLiteral("x")) - v.setX(value.toFloat()); - else if (vecCompRef[1] == QStringLiteral("y")) - v.setY(value.toFloat()); - else if (vecCompRef[1] == QStringLiteral("z")) - v.setZ(value.toFloat()); - newValue = v; - } - break; - case QVariant::Color: - { - QColor v = newValue.value(); - if (vecCompRef[1] == QStringLiteral("x") || vecCompRef[1] == QStringLiteral("r")) - v.setRedF(value.toFloat()); - else if (vecCompRef[1] == QStringLiteral("y") || vecCompRef[1] == QStringLiteral("g")) - v.setGreenF(value.toFloat()); - else if (vecCompRef[1] == QStringLiteral("z") || vecCompRef[1] == QStringLiteral("b")) - v.setBlueF(value.toFloat()); - newValue = v; - } - break; - default: - break; - } - cl.append(Q3DSPropertyChange::fromVariant(vecCompRef[0], newValue)); + switch (newValue.type()) { + case QVariant::Vector2D: + { + QVector2D v = newValue.value(); + if (vecCompRef[1] == QStringLiteral("x")) + v.setX(value.toFloat()); + else if (vecCompRef[1] == QStringLiteral("y")) + v.setY(value.toFloat()); + newValue = v; } + break; + case QVariant::Vector3D: + { + QVector3D v = newValue.value(); + if (vecCompRef[1] == QStringLiteral("x")) + v.setX(value.toFloat()); + else if (vecCompRef[1] == QStringLiteral("y")) + v.setY(value.toFloat()); + else if (vecCompRef[1] == QStringLiteral("z")) + v.setZ(value.toFloat()); + newValue = v; + } + break; + case QVariant::Color: + { + QColor v = newValue.value(); + if (vecCompRef[1] == QStringLiteral("x") || vecCompRef[1] == QStringLiteral("r")) + v.setRedF(value.toFloat()); + else if (vecCompRef[1] == QStringLiteral("y") || vecCompRef[1] == QStringLiteral("g")) + v.setGreenF(value.toFloat()); + else if (vecCompRef[1] == QStringLiteral("z") || vecCompRef[1] == QStringLiteral("b")) + v.setBlueF(value.toFloat()); + newValue = v; + } + break; + default: + break; + } + cl.append(Q3DSPropertyChange::fromVariant(vecCompRef[0], newValue)); } } else { // for example, setAttribute("rotation", "0 45 0") @@ -265,6 +263,35 @@ void Q3DSBehaviorObject::setDataInputValue(const QString &name, const QVariant & m_engine->setDataInputValue(name, value); } +QMatrix4x4 Q3DSBehaviorObject::calculateGlobalTransform(const QString &handle) +{ + Q3DSGraphObject *obj = m_engine->findObjectByHashIdOrNameOrPath(m_behaviorInstance->parent(), m_presentation, handle); + if (!obj) { + qWarning("calculateGlobalTransform: Invalid object reference %s", qPrintable(handle)); + return QMatrix4x4(); + } + + if (obj->isNode()) { + Q3DSNodeAttached *attached = static_cast(obj->attached()); + const float *m = attached->globalTransform.constData(); + QMatrix4x4 correctedMatrix(m[0], m[1], -m[2], m[3], + m[4], m[5], -m[6], m[7], + -m[8], -m[9], m[10], m[11], + m[12], m[13], -m[14], m[15]); + return correctedMatrix; + } + return QMatrix4x4(); +} + +QVector3D Q3DSBehaviorObject::lookAt(const QVector3D &target) +{ + float mag = qSqrt(target.x() * target.x() + target.z() * target.z()); + float pitch = -qAtan2(target.y(), mag); + float yaw = qAtan2(target.x(), target.z()); + + return QVector3D(qRadiansToDegrees(pitch), qRadiansToDegrees(yaw), 0.0f); +} + /*! \qmltype Behavior \inqmlmodule QtStudio3D @@ -392,6 +419,18 @@ Behavior { Sets the \a value of the data input identified with the \a name. */ +/*! + \qmlmethod matrix4x4 Behavior::calculateGlobalTransform(string handle) + + Returns the transformation matrix of the object identified with the \a handle. +*/ + +/*! + \qmlmethod vector3d Behavior::lookAt(vector3d target) + + Returns the euler angles for looking at the \a target. +*/ + /*! \qmlsignal void Behavior::onInitialize() diff --git a/src/runtime/behaviorapi/q3dsbehaviorobject_p.h b/src/runtime/behaviorapi/q3dsbehaviorobject_p.h index 661e09f..b0bd965 100644 --- a/src/runtime/behaviorapi/q3dsbehaviorobject_p.h +++ b/src/runtime/behaviorapi/q3dsbehaviorobject_p.h @@ -80,6 +80,8 @@ public: Q_INVOKABLE void unregisterForEvent(const QString &event); Q_INVOKABLE void unregisterForEvent(const QString &handle, const QString &event); Q_REVISION(1) Q_INVOKABLE void setDataInputValue(const QString &name, const QVariant &value); + Q_INVOKABLE QMatrix4x4 calculateGlobalTransform(const QString &handle = QString()); + Q_INVOKABLE QVector3D lookAt(const QVector3D &target); signals: void initialize(); -- cgit v1.2.3 From 9c81914c6ce084c077b347893307de045d9add63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A4=C3=A4tt=C3=A4=20Antti?= Date: Tue, 22 May 2018 13:14:53 +0300 Subject: Remove negative scale from camera This messes up the camera handing between the runtimes in lancelot. Change-Id: I5e3394564a296ee5b2a9aa938359b9e91f39a69f Reviewed-by: Andy Nichols --- tests/auto/q3dslancelot/data/cameras/componentCamera.uip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/q3dslancelot/data/cameras/componentCamera.uip b/tests/auto/q3dslancelot/data/cameras/componentCamera.uip index f8ca4fd..f0ae750 100644 --- a/tests/auto/q3dslancelot/data/cameras/componentCamera.uip +++ b/tests/auto/q3dslancelot/data/cameras/componentCamera.uip @@ -84,7 +84,7 @@ - + -- cgit v1.2.3 From 178d755258016b8a3f093e4aee13158bc9800dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 16 May 2018 16:07:55 +0200 Subject: Rollback the master slide's eyeball properties Change-Id: I111a0d538080e6f2b9d2f91402d7f730f6a41793 Reviewed-by: Laszlo Agocs --- src/runtime/q3dsscenemanager.cpp | 13 ------------ src/runtime/q3dsscenemanager_p.h | 1 - src/runtime/q3dsslideplayer.cpp | 43 +++++++++++++++++++++++----------------- src/runtime/q3dsslideplayer_p.h | 3 +-- 4 files changed, 26 insertions(+), 34 deletions(-) diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index 1cf047c..404d28a 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -7021,19 +7021,6 @@ void Q3DSSceneManager::updateNodeFromChangeFlags(Q3DSNode *node, Qt3DCore::QTran } if (changeFlags & Q3DSNode::EyeballChanges) { - // Special case: objects on master slide that get an eyeball change in - // a subslide. These must be tracked so that obj->masterRollbackList() - // can be applied since otherwise there's nothing ensuring the - // visibility is reset when moving to another slide afterwards. - auto nodeData = static_cast(node->attached()); - auto currentSlide = nodeData->component ? nodeData->component->currentSlide() : m_currentSlide; - auto masterSlide = nodeData->component ? nodeData->component->masterSlide() : m_masterSlide; - if (currentSlide && masterSlide->objects().contains(node)) { - Q3DSSlideAttached *data = static_cast(currentSlide->attached()); - Q_ASSERT(data); - data->needsMasterRollback.insert(node); - } - if (node->type() == Q3DSGraphObject::Light) { Q3DSLightAttached *lightData = static_cast(node->attached()); Q3DSGraphObject *rootObject = lightData->layer3DS; diff --git a/src/runtime/q3dsscenemanager_p.h b/src/runtime/q3dsscenemanager_p.h index d9877a9..0ae0d2a 100644 --- a/src/runtime/q3dsscenemanager_p.h +++ b/src/runtime/q3dsscenemanager_p.h @@ -581,7 +581,6 @@ public: Q3DSSlidePlayer *slidePlayer = nullptr; Qt3DAnimation::QClipAnimator *animator = nullptr; QVector animators; - QSet needsMasterRollback; }; class Q3DSImageAttached : public Q3DSGraphObjectAttached diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index f7c2ee2..d510b5c 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -597,7 +597,7 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide, } if (slide && slideDidChange && isSlideVisible(slide)) { - processPropertyChanges(slide, previousSlide); + processPropertyChanges(slide); m_animationManager->updateAnimations(slide, (m_mode == PlayerMode::Editor)); if (parentChanged) setSlideTime(static_cast(slide->parent()), 0.0f); @@ -768,32 +768,17 @@ bool Q3DSSlidePlayer::isSlideVisible(Q3DSSlide *slide) return visible; } -void Q3DSSlidePlayer::processPropertyChanges(Q3DSSlide *currentSlide, - Q3DSSlide *previousSlide) +void Q3DSSlidePlayer::processPropertyChanges(Q3DSSlide *currentSlide) { Q_ASSERT(currentSlide->attached()); - if (previousSlide) { - auto slideData = static_cast(previousSlide->attached()); - for (Q3DSNode *node : qAsConst(slideData->needsMasterRollback)) { - const Q3DSPropertyChangeList *changeList = node->masterRollbackList(); - if (changeList) { - qCDebug(lcScene, "Rolling back %d changes to master for %s", changeList->count(), node->id().constData()); - node->applyPropertyChanges(*changeList); - node->notifyPropertyChanges(*changeList); - m_sceneManager->updateSubTreeRecursive(node); - } - } - slideData->needsMasterRollback.clear(); - } - // Find properties on targets that has dynamic properties. // TODO: Find a better solution (e.g., there can be duplicate updates for e.g., xyz here). QHash dynamicPropertyChanges; const auto &tracks = currentSlide->animations(); std::find_if(tracks.cbegin(), tracks.cend(), [&dynamicPropertyChanges](const Q3DSAnimationTrack &track) { if (track.isDynamic()) { - auto foundIt = dynamicPropertyChanges.constFind(track.target()); + const auto foundIt = dynamicPropertyChanges.constFind(track.target()); Q3DSPropertyChangeList changeList; if (foundIt != dynamicPropertyChanges.constEnd()) changeList = *foundIt; @@ -805,6 +790,28 @@ void Q3DSSlidePlayer::processPropertyChanges(Q3DSSlide *currentSlide, return false; }); + // Rollback master slide properties + if (currentSlide->parent()) { + Q3DSSlide *parent = static_cast(currentSlide->parent()); + const auto &objects = parent->objects(); + std::find_if(objects.constBegin(), objects.constEnd(), [](Q3DSGraphObject *object){ + if (!object->isNode()) + return false; + + Q3DSNode *node = static_cast(object); + const Q3DSPropertyChangeList *masterRollbackList = node->masterRollbackList(); + if (!masterRollbackList) + return false; + + if (masterRollbackList->isEmpty()) + return false; + + node->applyPropertyChanges(*node->masterRollbackList()); + node->notifyPropertyChanges(*node->masterRollbackList()); + return false; + }); + } + // Filter out properties that we needs to be marked dirty, i.e., eyeball changes. const auto &propertyChanges = currentSlide->propertyChanges(); for (auto it = propertyChanges.cbegin(); it != propertyChanges.cend(); ++it) { diff --git a/src/runtime/q3dsslideplayer_p.h b/src/runtime/q3dsslideplayer_p.h index 01020e2..2ffdc62 100644 --- a/src/runtime/q3dsslideplayer_p.h +++ b/src/runtime/q3dsslideplayer_p.h @@ -146,8 +146,7 @@ private: void sendPositionChanged(Q3DSSlide *slide, float pos); void updateNodeVisibility(Q3DSNode *node, bool visible); bool isSlideVisible(Q3DSSlide *slide); - void processPropertyChanges(Q3DSSlide *currentSlide, - Q3DSSlide *previousSlide); + void processPropertyChanges(Q3DSSlide *currentSlide); struct Data { Q3DSSlideDeck *slideDeck = nullptr; -- cgit v1.2.3 From 334135680ce1516551d4f10e387cc291f275f30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Fri, 18 May 2018 09:56:11 +0200 Subject: Store the master rollback list directly in the node Simplefies usage and we're not saving much from allocating it on demand anyways. Change-Id: I14a8921932c7b4ee26f5b2d05588fecfbc1d84b6 Reviewed-by: Laszlo Agocs --- src/runtime/q3dsslideplayer.cpp | 11 ++++------- src/runtime/q3dsuippresentation.cpp | 4 +--- src/runtime/q3dsuippresentation_p.h | 4 ++-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index d510b5c..432bde3 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -799,15 +799,12 @@ void Q3DSSlidePlayer::processPropertyChanges(Q3DSSlide *currentSlide) return false; Q3DSNode *node = static_cast(object); - const Q3DSPropertyChangeList *masterRollbackList = node->masterRollbackList(); - if (!masterRollbackList) + const Q3DSPropertyChangeList &masterRollbackList = node->masterRollbackList(); + if (masterRollbackList.isEmpty()) return false; - if (masterRollbackList->isEmpty()) - return false; - - node->applyPropertyChanges(*node->masterRollbackList()); - node->notifyPropertyChanges(*node->masterRollbackList()); + node->applyPropertyChanges(node->masterRollbackList()); + node->notifyPropertyChanges(node->masterRollbackList()); return false; }); } diff --git a/src/runtime/q3dsuippresentation.cpp b/src/runtime/q3dsuippresentation.cpp index 3633a2a..3d2e4c7 100644 --- a/src/runtime/q3dsuippresentation.cpp +++ b/src/runtime/q3dsuippresentation.cpp @@ -2532,9 +2532,7 @@ void Q3DSNode::setProperties(const QXmlStreamAttributes &attrs, PropSetFlags fla // If this is on the master slide, store some rollback info. if (flags.testFlag(PropSetOnMaster)) { - if (m_masterRollbackList.isNull()) - m_masterRollbackList.reset(new Q3DSPropertyChangeList); - m_masterRollbackList->append(Q3DSPropertyChange(QLatin1String("eyeball"), + m_masterRollbackList.append(Q3DSPropertyChange(QLatin1String("eyeball"), m_flags.testFlag(Q3DSNode::Active) ? QLatin1String("True") : QLatin1String("False"))); diff --git a/src/runtime/q3dsuippresentation_p.h b/src/runtime/q3dsuippresentation_p.h index bc4bec3..899b516 100644 --- a/src/runtime/q3dsuippresentation_p.h +++ b/src/runtime/q3dsuippresentation_p.h @@ -834,7 +834,7 @@ public: void applyPropertyChanges(const Q3DSPropertyChangeList &changeList) override; int mapChangeFlags(const Q3DSPropertyChangeList &changeList) override; - const Q3DSPropertyChangeList *masterRollbackList() const { return m_masterRollbackList.data(); } + const Q3DSPropertyChangeList &masterRollbackList() const { return m_masterRollbackList; } QStringList propertyNames() const override; QVariantList propertyValues() const override; @@ -870,7 +870,7 @@ protected: qint32 m_skeletonId = -1; RotationOrder m_rotationOrder = YXZ; Orientation m_orientation = LeftHanded; - QScopedPointer m_masterRollbackList; + Q3DSPropertyChangeList m_masterRollbackList; private: Q_DISABLE_COPY(Q3DSNode) -- cgit v1.2.3 From 36210fc6084bb56491f71b97ad2d674f625bc277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Tue, 22 May 2018 17:32:45 +0200 Subject: Fix visibility updates of sub-meshs The layer tags for the sub-meshes where not properly removed when the visibility changed. Change-Id: I813872083878974baba5fcbc6234041b0a8ccb3c Reviewed-by: Laszlo Agocs --- src/runtime/q3dsscenemanager.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index 404d28a..6462e94 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -4482,11 +4482,13 @@ void Q3DSSceneManager::retagSubMeshes(Q3DSModelNode *model3DS) sm.hasTransparency = opacity < 1.0f || matDesc->materialHasTransparency() || matDesc->materialHasRefraction(); } - Qt3DRender::QLayer *newTag = sm.hasTransparency ? layerData->transparentTag : layerData->opaqueTag; - if (!sm.entity->components().contains(newTag)) { - Qt3DRender::QLayer *prevTag = newTag == layerData->transparentTag ? layerData->opaqueTag : layerData->transparentTag; - sm.entity->removeComponent(prevTag); - sm.entity->addComponent(newTag); + if (data->globalVisibility) { + Qt3DRender::QLayer *newTag = sm.hasTransparency ? layerData->transparentTag : layerData->opaqueTag; + if (!sm.entity->components().contains(newTag)) { + Qt3DRender::QLayer *prevTag = newTag == layerData->transparentTag ? layerData->opaqueTag : layerData->transparentTag; + sm.entity->removeComponent(prevTag); + sm.entity->addComponent(newTag); + } } profData.needsBlending = sm.hasTransparency; @@ -7078,10 +7080,12 @@ void Q3DSSceneManager::setNodeVisibility(Q3DSNode *node, bool visible) Q3DSModelAttached *mdata = static_cast(node->attached()); for (Q3DSModelAttached::SubMesh &sm : mdata->subMeshes) { Qt3DRender::QLayer *tag = sm.hasTransparency ? layerData->transparentTag : layerData->opaqueTag; - if (!visible) - sm.entity->removeComponent(tag); - else + if (!visible) { + sm.entity->removeComponent(layerData->opaqueTag); + sm.entity->removeComponent(layerData->transparentTag); + } else { sm.entity->addComponent(tag); + } } } -- cgit v1.2.3 From 0d9078ac283a0df63a579d49e3bb36be13a5c8c0 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 22 May 2018 11:25:19 +0200 Subject: doc: Remove the two empty pages from the index Change-Id: I6bee6698981a0564d934fab9e9856d210543dc65 Reviewed-by: Andy Nichols --- src/runtime/doc/src/index.qdoc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/runtime/doc/src/index.qdoc b/src/runtime/doc/src/index.qdoc index 43d8b18..00cfc11 100644 --- a/src/runtime/doc/src/index.qdoc +++ b/src/runtime/doc/src/index.qdoc @@ -34,8 +34,6 @@ \list \li \l {Getting Started} \li \l {System and Application Requirements} - \li \l {Using the Runtime on Android/iOS Devices} - \li \l {Using the Runtime on Embedded Devices} \li \l {Qt 3D Studio Runtime C++ Classes} \li \l {Qt 3D Studio Runtime QML Types} \li \l {Attribute Names}{Scene object attribute list} -- cgit v1.2.3 From f97bddcc4d60230b67298437b475c14c0d75da3e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 22 May 2018 11:30:37 +0200 Subject: doc: Make copyright attributions work again Change-Id: Ic45773074486f3d2a4ee693137a7f98aee0d7255 Reviewed-by: Andy Nichols --- src/3rdparty/imgui/qt_attribution.json | 2 +- src/runtime/doc/src/copyright.qdoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/3rdparty/imgui/qt_attribution.json b/src/3rdparty/imgui/qt_attribution.json index d3b4381..fd789fc 100644 --- a/src/3rdparty/imgui/qt_attribution.json +++ b/src/3rdparty/imgui/qt_attribution.json @@ -2,7 +2,7 @@ { "Id": "imgui", "Name": "Dear ImGui", - "QDocModule": "Qt3DStudioRuntime2", + "QDocModule": "qt3dstudioruntime2", "Description": "Dear ImGui", "QtUsage": "Bloat-free GUI library for in-scene visualization of profiling and debugging data", diff --git a/src/runtime/doc/src/copyright.qdoc b/src/runtime/doc/src/copyright.qdoc index 01275f1..f0574a5 100644 --- a/src/runtime/doc/src/copyright.qdoc +++ b/src/runtime/doc/src/copyright.qdoc @@ -33,5 +33,5 @@ The following table lists parts (modules) of Qt 3D Studio Runtime that incorporate code licensed under third-party open-source licenses: -\annotatedlist attributions-Qt3DStudioRuntime2 +\annotatedlist attributions-qt3dstudioruntime2 */ -- cgit v1.2.3 From 64e7637c58f2492ea4bc32455ed65107ba4687ed Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sun, 20 May 2018 15:08:53 +0200 Subject: doc: Add a page for profileui and expand the common api one Change-Id: I74a40b3ba177e73ca4b424311797a86bd745a735 Reviewed-by: Andy Nichols --- src/runtime/doc/src/images/profileui-example.png | Bin 0 -> 427508 bytes src/runtime/doc/src/images/profileui-tooltips.png | Bin 0 -> 261025 bytes src/runtime/doc/src/index.qdoc | 3 +- src/runtime/doc/src/module.qdoc | 56 ++++++++- src/runtime/doc/src/profileui.qdoc | 133 ++++++++++++++++++++++ 5 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 src/runtime/doc/src/images/profileui-example.png create mode 100644 src/runtime/doc/src/images/profileui-tooltips.png create mode 100644 src/runtime/doc/src/profileui.qdoc diff --git a/src/runtime/doc/src/images/profileui-example.png b/src/runtime/doc/src/images/profileui-example.png new file mode 100644 index 0000000..27c38bd Binary files /dev/null and b/src/runtime/doc/src/images/profileui-example.png differ diff --git a/src/runtime/doc/src/images/profileui-tooltips.png b/src/runtime/doc/src/images/profileui-tooltips.png new file mode 100644 index 0000000..1828ad6 Binary files /dev/null and b/src/runtime/doc/src/images/profileui-tooltips.png differ diff --git a/src/runtime/doc/src/index.qdoc b/src/runtime/doc/src/index.qdoc index 00cfc11..387e86f 100644 --- a/src/runtime/doc/src/index.qdoc +++ b/src/runtime/doc/src/index.qdoc @@ -36,7 +36,8 @@ \li \l {System and Application Requirements} \li \l {Qt 3D Studio Runtime C++ Classes} \li \l {Qt 3D Studio Runtime QML Types} - \li \l {Attribute Names}{Scene object attribute list} + \li \l {Attribute Names}{Scene Object Attribute List} + \li \l {Using the In-Scene Debug and Profile views} \li \l {Examples} \li \l {Copyright Notices} \endlist diff --git a/src/runtime/doc/src/module.qdoc b/src/runtime/doc/src/module.qdoc index d37417f..ba6068f 100644 --- a/src/runtime/doc/src/module.qdoc +++ b/src/runtime/doc/src/module.qdoc @@ -31,7 +31,8 @@ \keyword C++ API \ingroup modules - \brief Qt 3D Studio provides a number of C++ classes to view and control the presentation. + \brief The Qt 3D Studio Runtime provides a number of C++ classes to + integrate and control Qt 3D Studio presentations in Qt applications. To include the definitions of the module's classes, use the following directive: @@ -45,6 +46,36 @@ QT += 3dstudioruntime2 \endcode + \section1 Integrating + + The two main classes are \l Q3DSWidget and \l Q3DSSurfaceViewer. Q3DSWidget + is a QWidget that can be used to show presentations inside a widget-based + user interface. Q3DSSurfaceViewer allows targeting a QWindow or an + offscreen render target (an OpenGL texture). + + \note Qt applications based on QML and Qt Quick will rather want to use the + \l Studio3D type from \l{Qt 3D Studio Runtime QML Types}. + + \section1 Controlling + + Each \l Q3DSWidget and \l Q3DSSurfaceViewer instance exposes a \l + Q3DSPresentation. This, possibly in combination with \l Q3DSDataInput or + \l Q3DSElement objects, allows + + \list + + \li changing scene object properties (for example, the transform of a + model, colors and other settings of a material, etc.), + + \li changing slides (thus starting the relevant animations and applying the + scene object property changes associated with the new slide), + + \li and controlling the timeline (the current playback position for the + key-frame based animations) both on the main scene and on individual + Component nodes. + + \endlist + \section1 Classes \generatelist {classesbymodule 3dstudioruntime2} @@ -59,14 +90,31 @@ \brief QML Types for the Qt 3D Studio Runtime module. - Qt 3D Studio provides a number of QML types to view and control the - presentation. These types can be imported into your application using the - following import statement in your .qml file: + The Qt 3D Studio Runtime provides a number of QML types to integrate and + control Qt 3D Studio presentations in Qt Quick applications. These types + can be imported into your application using the following import statement + in your \c{.qml} file: \badcode import QtStudio3D 2.0 \endcode + The main type for embedding a Qt 3D Studio presentations into a Qt Quick + scene is \l Studio3D. Many of the other types correspond to a C++ class in + the API offered to non-QML based applications, providing the same level of + control described in \l{Qt 3D Studio Runtime C++ Classes}{the C++ + reference}. + + There are also QML types that offer functionality not available via the C++ + classes. The \l SubPresentationSettings type allows defining \c{QML + sub-presentations} (live Qt Quick scenes composed into the 3D scene either + as Qt 3D Studio layers or as texture maps) in-line, inside a Studio3D + element, without having to deploy them as separate \c .qml files. + + \note the \l Behavior type is to be used by \c{behavior scripts} (\c .qml + snippets associated with scene objects during the design phase in Qt 3D + Studio) and is not available in the main application code. + \section1 QML Types \generatelist {qmltypesbymodule QtStudio3D} diff --git a/src/runtime/doc/src/profileui.qdoc b/src/runtime/doc/src/profileui.qdoc new file mode 100644 index 0000000..2aeb928 --- /dev/null +++ b/src/runtime/doc/src/profileui.qdoc @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page qt3d-runtime-profileui.html + \title Using the In-Scene Debug and Profile views + + The Qt 3D Studio Runtime includes a set of built-in views that can be + brought up on top of the scene at any time. These panes are rendered + completely inside the 3D scene and are therefore available on any platform, + even when running on mobile or embedded systems without a windowing system + (for example, via the \c eglfs platform plugin), with the Qt 3D Studio + presentation and the Qt Quick user interface occupying the entire scren. + + \image profileui-example.png + + \section1 Activation + + In the Viewer application, toggle with \c F10 or the \uicontrol{Profile and + Debug} submenu under \uicontrol View. + + In applications these views have no built-in shortcuts. It is up to the + application to toggle visibility. From C++ this is done via \l + Q3DSPresentation::profileUiVisible() or \l + Q3DSViewerSettings::showRenderStats(). From QML the corresponding properties + are \l Presentation::profileUiVisible and \l ViewerSettings::showRenderStats. + + In order to enable all features in the debug and profile views, presentations + must be loaded with profiling enabled. In this mode the Qt 3D objects + managed by the runtime get tracked, and various statistics get collected + internally. This is enabled by default in the Viewer application, whereas + applications have to opt-in explicitly via \l + Q3DSPresentation::profilingEnabled or \l Presentation::profilingEnabled. + + As an example, the following is how the \l{Qt 3D Studio Runtime: Simple QML + Example} enables and connects the toggling of these views to a Qt Quick + Controls button: + + \badcode + Studio3D { + Presentation { + id: presentation + source: "qrc:/presentation/barrel.uip" + profilingEnabled: true + } + } + + Button { + text: "Toggle profile UI" + onClicked: presentation.profileUiVisible = !s3dpres.profileUiVisible + ... + } + } + \endcode + + \section1 Features + + \list + + \li CPU and memory usage of the application process (available on Windows, Linux, and Android) + + \li OpenGL context information + + \li Frame rate, with a visualization of its history during the last 100 frames (configurable) + + \li Various timings from the loading of the scene + + \li Qt 3D object list - showing the active list of mesh and texture objects + can give an approximate understanding of the graphics resource usage and + can also uncover sub-optimal asset situations that lead to degraded + performance. For example, having a large number of meshes in the list for a + seemingly simple scene should warrant an investigation of the assets as + they may be overly complex. Similarly, large textures are often not ideal, + yet they may be overlooked during the design phase of the presentation. + Here it becomes immediately obvious if some texture map is unncessarily + large. + + \li Layer list - showing the list of active and inactive \c layers in the + presentation. A Qt 3D Studio presentations consists of one or more layers + which are backed by OpenGL textures each. These are composed together with + the appropriate blending mode (and optionally with post-postprocessing + effects applied) to get the final output. It is important to understand + that each layer corresponds to a separate render target (e.g. an OpenGL + texture and the corresponding framebuffer setup) in the engine and is using + graphics resources like any other texture map. The performance of the + composition is also important, especially on mobile and embedded where the + fragment processing power can be more limited. + + \li A filterable log view (with the debug messages that are also printed on + the default qDebug output of the platform) + + \li A number of other, experimental views + + \endlist + + The views and their contents are live at any time, meaning they always + reflect the Qt 3D Studio Runtime's state for the current frame. + + Watch out for the tooltips marked with \c{(?)}. Moving the mouse cursor + over these results in showing additional information about the item in + question which can be useful in understanding the implications of certain + statistics. + + \image profileui-tooltips.png + + \note the feature set may get extended or changed in future versions. It is + also possible that certain information gets folded into the Qt 3D Studio + application itself in the future. +*/ -- cgit v1.2.3 From e3f96c934f5ef2251b6748c18e7709fb98033e55 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sun, 20 May 2018 17:15:43 +0200 Subject: doc: Clean up the qml api docs Fix weird language, remove non-existent stuff, take the updated descriptions from the C++ APIs in a few cases, and add a few enhancements, in particular for DataInput and SubPresentationSettings. Change-Id: Icea43b5975bc05625c984f0cef8a2d1aa2f94ae6 Reviewed-by: Andy Nichols --- src/imports/studio3d/q3dsstudio3ditem.cpp | 54 ++++-- .../studio3d/q3dssubpresentationsettings.cpp | 50 ++++-- src/runtime/api/q3dsdatainput.cpp | 79 ++++++-- src/runtime/api/q3dselement.cpp | 65 ++++--- src/runtime/api/q3dspresentation.cpp | 198 +++++++++++++-------- src/runtime/api/q3dssceneelement.cpp | 44 ++--- src/runtime/api/q3dsviewersettings.cpp | 10 +- src/runtime/behaviorapi/q3dsbehaviorobject.cpp | 5 + 8 files changed, 335 insertions(+), 170 deletions(-) diff --git a/src/imports/studio3d/q3dsstudio3ditem.cpp b/src/imports/studio3d/q3dsstudio3ditem.cpp index b585122..1c16b89 100644 --- a/src/imports/studio3d/q3dsstudio3ditem.cpp +++ b/src/imports/studio3d/q3dsstudio3ditem.cpp @@ -89,36 +89,42 @@ QT_BEGIN_NAMESPACE } } \endqml -*/ -/*! - \qmlsignal Studio3D::frameUpdate() + \section2 Controlling the presentation - This signal is emitted each time a frame has been updated regardless of - visibility. This allows a hidden Studio3D element to still process - information every frame, even though the renderer is not rendering. + Like the example above suggests, Studio3D and the other types under the + QtStudio3D import offer more than simply rendering the animated Qt 3D + Studio presentation. They also offer scene manipulation, including - The corresponding handler is \c onFrameUpdate. + \list - To prevent expensive handlers from being processed when hidden, add an - early return to the top like: + \li querying and changing scene object properties (for example, the + transform of a model, colors and other settings of a material, etc.) via + Presentation::getAttribute(), Presentation::setAttribute(), \l Element, and + \l DataInput, - \qml - onFrameUpdate: { - if (!visible) return; - ... - } - \endqml + \li changing slides (and thus starting the relevant animations and applying + the scene object property changes associated with the new slide) via + Presentation::goToSlide(), \l SceneElement, and \l DataInput, + + \li and controlling the timeline (the current playback position for the + key-frame based animations) both on the main scene and on individual + Component nodes via Presentation::goToTime(), \l SceneElement, and \l DataInput. + + \endlist +*/ + +/*! + \qmlsignal Studio3D::frameUpdate() + + This signal is emitted each time a frame has been rendered. */ /*! \qmlsignal Studio3D::presentationReady() This signal is emitted when the viewer has been initialized and the - presentation is ready to be shown. The difference to \c running property is - that the viewer has to be visible for \c running to get \c{true}. This - signal is useful for displaying splash screen while viewer is getting - initialized. + presentation is ready to be shown. */ static bool engineCleanerRegistered = false; @@ -181,6 +187,16 @@ bool Q3DSStudio3DItem::isRunning() const return m_running; } +/*! + \qmlproperty string Studio3D::error + + Contains the text for the error message that was generated during the + loading of the presentation. When no error occurred or there is no + presentation loaded, the value is an empty string. + + This property is read-only. +*/ + QString Q3DSStudio3DItem::error() const { return m_error; diff --git a/src/imports/studio3d/q3dssubpresentationsettings.cpp b/src/imports/studio3d/q3dssubpresentationsettings.cpp index e8ffcea..44d9e43 100644 --- a/src/imports/studio3d/q3dssubpresentationsettings.cpp +++ b/src/imports/studio3d/q3dssubpresentationsettings.cpp @@ -83,6 +83,27 @@ QQmlListProperty Q3DSSubPresentationSettings::qmlS } } \endqml + + \section2 Linking to the Presentation via presentationId + + In Qt 3D Studio presentations QML sub-presentations are specified in the \e + assets element of the presentation's \c{.uia} file. This is important also + when using SubPresentationSettings and QmlStream. + + \badcode + + + + \endcode + + \note the Qt 3D Studio application takes care of generating the \c{.uia} + file based on what the designers have set in the Sub-presentations dialog. + + The \c presentation-id attribute must contain a unique ID for the + sub-presentation. The corresponding \l QmlStream must provide the same + value in its presentationId property. The \c args attribute may contain an + optional preview version of the item, which is only used in the Viewer + application. */ /*! @@ -97,36 +118,27 @@ QQmlListProperty Q3DSSubPresentationSettings::qmlS \ingroup 3dstudioruntime2 \brief QML stream. - This type allows attaching QML sub-presentation with a quick item. The item is rendered to a - texture and used as a part of a Qt 3D Studio presentation. - - The sub-presentation element must be specified in the \e assets element of the presentation - .uia file: - - \badcode - - - - \endcode + This type allows specifying the contents of a QML sub-presentation within + the Studio3D item. QmlStream must be used in combination with + \l SubPresentationSettings. - The \c presentation-id attribute must contain a unique ID of the sub-presentation. - The \c args attribute may contain an optional preview version of the item, which is only - used in the Viewer application. + \sa SubPresentationSettings */ /*! \qmlproperty string QmlStream::presentationId - Holds the string ID of the sub-presentation the item is attached to. The id must be one of - the \c presentation-qml IDs specified in the .uia file. + Holds the string ID of the sub-presentation the contents of which is + specified by \l item. The id must be one of the \c presentation-qml IDs + specified in the \c{.uia} file. */ /*! \qmlproperty Item QmlStream::item - Holds the item attached to the sub-presentation. The item size is used as the the size of the - texture the item is rendered to. Default values \c{(256, 256)} are used if the item doesn't - specify a size. + Holds the item attached to the sub-presentation. The item size is used as + the the size of the texture the item is rendered to. A default value of + \c{(128, 128)} is used when the item does not specify a size. */ QT_END_NAMESPACE diff --git a/src/runtime/api/q3dsdatainput.cpp b/src/runtime/api/q3dsdatainput.cpp index 69cafe3..77b999a 100644 --- a/src/runtime/api/q3dsdatainput.cpp +++ b/src/runtime/api/q3dsdatainput.cpp @@ -111,10 +111,11 @@ void Q3DSDataInput::setName(const QString &name) The value of this property only accounts for changes done via the same Q3DSDataInput instance. If the value of the same data input in the - presentation is changed elsewhere, for example via presentation scripting, - those changes are not reflected in the value of this property. Due to this - uncertainty, this property treats all value sets as changes even if the - newly set value is the same value as the previous value. + presentation is changed elsewhere, for example via animations or + Q3DSPresentation::setAttribute(), those changes are not reflected in the + value of this property. Due to this uncertainty, this property treats all + value sets as changes even if the newly set value is the same value as the + previous value. */ QVariant Q3DSDataInput::value() const { @@ -149,9 +150,54 @@ void Q3DSDataInputPrivate::sendValue() \instantiates Q3DSDataInput \inqmlmodule QtStudio3D \ingroup 3dstudioruntime2 - \brief Control type for data inputs in a Qt 3D Studio presentation. - This type is a convenience type for controlling a data input in a presentation. + \brief Controls a data input entry in a Qt 3D Studio presentation. + + This type is a convenience for controlling a data input in a presentation. + Its functionality is equivalent to Presentation::setDataInputValue(), + however it has a big advantage of being able to use QML property bindings, + thus avoiding the need to having to resort to a JavaScript function call + for every value change. + + As an example, compare the following two approaches: + + \qml + Studio3D { + ... + Presentation { + id: presentation + ... + } + } + + Button { + onClicked: presentation.setAttribute("SomeTextNode", "textstring", "Hello World") + } + \endqml + + \qml + Studio3D { + ... + Presentation { + id: presentation + ... + property string text: "" + DataInput { + name: "inputForSomeTextNode" + value: presentation.text + } + } + } + + Button { + onClicked: presentation.text = "Hello World" + } + \endqml + + The latter assumes that a data input connection was made in Qt 3D Studio + between the \c textstring property of \c SomeTextNode and a data input name + \c inputForSomeTextNode. As the value is now set via a property, the full + set of QML property bindings techniques are available. \sa Studio3D, Presentation */ @@ -159,22 +205,23 @@ void Q3DSDataInputPrivate::sendValue() /*! \qmlproperty string DataInput::name - Specifies the name of the controlled data input element in the presentation. - This property must be set as part of DataInput declaration. + Specifies the name of the controlled data input element in the + presentation. This property must be set as part of DataInput declaration, + although it is changeable afterwards, if desired. */ /*! \qmlproperty variant DataInput::value Specifies the value of the controlled data input element in the presentation. - The changes to the value property are queued and handled asynchronously before the - next frame is displayed. - - The value of this property only accounts for changes done via the same DataInput instance. - If the value of the same data input in the presentation is changed elsewhere, - for example via presentation scripting, those changes are not reflected in - the value of this property. Due to this uncertainty, this property treats all value sets as - changes even if the newly set value is the same value as the previous value. + + The value of this property only accounts for changes done via the same + DataInput instance. If the value of the underlying attribute in the + presentation is changed elsewhere, for example via animations or + Presentation::setAttribute(), those changes are not reflected in the value + of this property. Due to this uncertainty, this property treats all value + sets as changes even if the newly set value is the same value as the + previous value. */ QT_END_NAMESPACE diff --git a/src/runtime/api/q3dselement.cpp b/src/runtime/api/q3dselement.cpp index 3e72e83..a09d21e 100644 --- a/src/runtime/api/q3dselement.cpp +++ b/src/runtime/api/q3dselement.cpp @@ -37,7 +37,7 @@ QT_BEGIN_NAMESPACE \inmodule 3dstudioruntime2 \since Qt 3D Studio 2.0 - \brief Controls a scene object in a Qt 3D Studio presentation. + \brief Controls a scene object (node) in a Qt 3D Studio presentation. This class is a convenience class for controlling the properties of a scene object (such as, model, material, camera, layer) in a Qt 3D Studio @@ -183,10 +183,12 @@ void Q3DSElementPrivate::setPresentation(Q3DSPresentation *pres) \ingroup 3dstudioruntime2 \brief Control type for elements in a Qt 3D Studio presentation. - This type is a convenience type for managing a presentation element. + This type is a convenience for controlling the properties of a scene object + (such as, model, material, camera, layer) in a Qt 3D Studio presentation. - All methods provided by this type are queued and handled asynchronously before the next - frame is displayed. + \note The functionality of Element is equivalent to + Presentation::setAttribute(), Presentation::getAttribute() and + Presentation::fireEvent(). \sa Studio3D, Presentation, SceneElement */ @@ -195,37 +197,54 @@ void Q3DSElementPrivate::setPresentation(Q3DSPresentation *pres) \qmlproperty string Element::elementPath Holds the element path of the presentation element. - This property must be set as part of Element declaration. - You can specify an element of a sub-presentation by adding "SubPresentationId:" - in front of the element path, for example \c{"SubPresentationOne:Scene"}. -*/ -/*! - \qmlmethod void Element::setAttribute(string attributeName, variant value) + An element path refers to an object in the scene either by name or id. The + latter is rarely used in application code since the unique IDs are not + exposed in the Qt 3D Studio application. To refer to an object by id, + prepend \c{#} to the name. Applications will typically refer to objects by + name. - Sets the \a value of an attribute on an element specified by this instance. - The \a attributeName is the \l{Attribute Names}{scripting name} of the attribute. + Names are not necessarily unique, however. To access an object with a + non-unique name, the path can be specified, for example, + \c{Scene.Layer.Camera}. Here the right camera object gets chosen even if + the scene contains other layers with the default camera names (for instance + \c{Scene.Layer2.Camera}). - The attribute must be preserved for scripting to be set by this function, or else it will fail. - An attribute is preserved if it is either \e{animated}, or - \e{an attribute on a master element that is unlinked and changed per-slide}. + If the object is renamed to a unique name in the Qt 3D Studio application's + Timeline view, the path can be omitted. For example, if the camera in + question was renamed to \c MyCamera, applications can then simply pass \c + MyCamera as the element path. + + To access an object in a sub-presentation, prepend the name of the + sub-presentation followed by a colon, for example, + \c{SubPresentationOne:Scene.Layer.Camera}. */ /*! - \qmlmethod void Element::fireEvent(string eventName) + \qmlmethod variant Element::getAttribute(string attributeName) + + Returns the current value of an attribute (property) of the scene object + specified by this Element instance. The \a attributeName is the + \l{Attribute Names}{scripting name} of the attribute. + */ - Dispatches an event with \a eventName on the element specified by this instance. - Appropriate actions created in Qt 3D Studio or callbacks registered using the registerForEvent() - method in attached scripts will be executed in response to the event. +/*! + \qmlmethod void Element::setAttribute(string attributeName, variant value) + + Sets the \a value of an attribute (property) of the scene object specified + by this Element instance. The \a attributeName is the \l{Attribute + Names}{scripting name} of the attribute. */ /*! - \qmlsignal Element::elementPathChanged(string elementPath) + \qmlmethod void Element::fireEvent(string eventName) - This signal is emitted when the element path property changes. - The new value is provided in the \a elementPath parameter. + Dispatches an event with \a eventName on the scene object + specified by elementPath. - The corresponding handler is \c onElementPathChanged. + Appropriate actions created in Qt 3D Studio or callbacks registered using + the registerForEvent() method in attached \c{behavior scripts} will be + executed in response to the event. */ QT_END_NAMESPACE diff --git a/src/runtime/api/q3dspresentation.cpp b/src/runtime/api/q3dspresentation.cpp index 0a797b2..9525422 100644 --- a/src/runtime/api/q3dspresentation.cpp +++ b/src/runtime/api/q3dspresentation.cpp @@ -476,12 +476,76 @@ void Q3DSPresentationPrivate::registerInlineQmlSubPresentations(const QVector Date: Tue, 22 May 2018 10:24:00 +0200 Subject: doc: finish up the C++ docs Change-Id: I26abc856bba4c150b918e1800a2eb34b44bc9f81 Reviewed-by: Andy Nichols --- src/runtime/api/q3dspresentation.cpp | 227 +++++++++++++++++++++++++++- src/runtime/api/q3dssurfaceviewer.cpp | 35 +++++ src/runtime/api/q3dsviewersettings.cpp | 50 +++++- src/runtime/api/q3dswidget.cpp | 56 +++++++ src/runtime/doc/src/images/customsignal.png | Bin 0 -> 28206 bytes src/runtime/doc/src/profileui.qdoc | 4 +- 6 files changed, 361 insertions(+), 11 deletions(-) create mode 100644 src/runtime/doc/src/images/customsignal.png diff --git a/src/runtime/api/q3dspresentation.cpp b/src/runtime/api/q3dspresentation.cpp index 9525422..3a8a055 100644 --- a/src/runtime/api/q3dspresentation.cpp +++ b/src/runtime/api/q3dspresentation.cpp @@ -128,6 +128,25 @@ void Q3DSPresentation::setSource(const QUrl &source) emit sourceChanged(); } +/*! + \property Q3DSPresentation::profilingEnabled + + When enabled, Qt 3D objects managed by the runtime get tracked, + and various statistics get collected internally. These are then + exposed in the views that can be toggled by profileUiVisible. + + The default value is \c false. + + \note Changing the value after the presentation has been loaded + has no effect for the already loaded presentation. Therefore the + changing of this property must happen before calling setSource(). + + \note In the Qt 3D Studio Viewer application presentations are + opened with profiling enabled by default. Therefore, applications + wishing to have an experience comparable to the Viewer, when it + comes to the debug and profile views, should set this property to + \c true. +*/ bool Q3DSPresentation::isProfilingEnabled() const { Q_D(const Q3DSPresentation); @@ -149,6 +168,17 @@ void Q3DSPresentation::setProfilingEnabled(bool enable) } } +/*! + \property Q3DSPresentation::profileUiVisible + + When this property is \c{true}, the interactive statistics and profile + view is displayed in-scene, on top of the 3D content. + + \note This feature can be disabled at build time, in which case this + property has no effect. + + Default value is \c{false}. +*/ bool Q3DSPresentation::isProfileUiVisible() const { Q_D(const Q3DSPresentation); @@ -166,6 +196,13 @@ void Q3DSPresentation::setProfileUiVisible(bool visible) } } +/*! + \property Q3DSPresentation::profileUiScale + + Controls the scale factor of the in-scene debug and profile views. + + The default value is 1.0. +*/ float Q3DSPresentation::profileUiScale() const { Q_D(const Q3DSPresentation); @@ -216,10 +253,11 @@ void Q3DSPresentation::setDataInputValue(const QString &name, const QVariant &va } /*! - Dispatches an event with \a eventName on a specific element found in \a - elementPath. Appropriate actions created in Qt 3D Studio or callbacks - registered using the registerForEvent() method in attached (behavior) - scripts will be executed in response to the event. + Dispatches a Qt 3D Studio presentation event with \a eventName on + scene object specified by \a elementPath. These events provide a + way to communicate with the \c .qml based \c{behavior scripts} + attached to scene objects since they can register to be notified + via Behavior::registerForEvent(). See setAttribute() for a description of \a elementPath. */ @@ -371,10 +409,54 @@ void Q3DSPresentation::setAttribute(const QString &elementPath, const QString &a d->controller->handleSetAttribute(elementPath, attributeName, value); } +/*! + \fn void Q3DSPresentation::customSignalEmitted(const QString &elementPath, const QString &name) + + This signal is emitted when an action with the \c{Emit Signal} + handler is executed in the Qt 3D Studio presentation. \a + elementPath specifies the scene object on which the (Qt 3D Studio) + "signal" \a name was triggered. + + Connecting to this signal offers a way of reacting upon certain + events in the Qt 3D Studio presentation. + + \image customsignal.png + + In this example, pressing or tapping on the Cluster object will result in + emitting \c{customSignalEmitted("Cluster", "clusterPressed")}. +*/ + +/*! + \fn Q3DSPresentation::slideEntered(const QString &elementPath, int index, const QString &name) + + This signal is emitted when a slide is entered in the presentation. The \a + elementPath specifies the time context (a Scene or a Component element) + owning the entered slide. The \a index and \a name contain the index and + the name of the entered slide. +*/ + +/*! + \fn Q3DSPresentation::slideExited(const QString &elementPath, int index, const QString &name) + + This signal is emitted when a slide is exited in the presentation. The \a + elementPath specifies the time context (a Scene or a Component element) + owning the exited slide. The \a index and \a name contain the index and the + name of the exited slide. +*/ + // These event forwarders are not stricly needed, Studio3D et al are fine // without them. However, they are there in 3DS1 and can become handy to feed // arbitrary, application-generated events into the engine. +/*! + Passes a key press event \a e to the presentation. + + \note The event forwarders in Q3DSPresentation are not normally + needed since Q3DSWidget and Studio3D both pass mouse, keyboard and + touch input on to the Qt 3D Studio engine. They may become useful + however with Q3DSSurfaceViewer, or in special situations, in order + to inject input events. +*/ void Q3DSPresentation::keyPressEvent(QKeyEvent *e) { Q_D(Q3DSPresentation); @@ -382,6 +464,15 @@ void Q3DSPresentation::keyPressEvent(QKeyEvent *e) d->controller->handlePresentationKeyPressEvent(e); } +/*! + Passes a key release event \a e to the presentation. + + \note The event forwarders in Q3DSPresentation are not normally + needed since Q3DSWidget and Studio3D both pass mouse, keyboard and + touch input on to the Qt 3D Studio engine. They may become useful + however with Q3DSSurfaceViewer, or in special situations, in order + to inject input events. +*/ void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e) { Q_D(Q3DSPresentation); @@ -389,6 +480,15 @@ void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e) d->controller->handlePresentationKeyReleaseEvent(e); } +/*! + Passes a mouse press event \a e to the presentation. + + \note The event forwarders in Q3DSPresentation are not normally + needed since Q3DSWidget and Studio3D both pass mouse, keyboard and + touch input on to the Qt 3D Studio engine. They may become useful + however with Q3DSSurfaceViewer, or in special situations, in order + to inject input events. +*/ void Q3DSPresentation::mousePressEvent(QMouseEvent *e) { Q_D(Q3DSPresentation); @@ -396,6 +496,15 @@ void Q3DSPresentation::mousePressEvent(QMouseEvent *e) d->controller->handlePresentationMousePressEvent(e); } +/*! + Passes a mouse move event \a e to the presentation. + + \note The event forwarders in Q3DSPresentation are not normally + needed since Q3DSWidget and Studio3D both pass mouse, keyboard and + touch input on to the Qt 3D Studio engine. They may become useful + however with Q3DSSurfaceViewer, or in special situations, in order + to inject input events. +*/ void Q3DSPresentation::mouseMoveEvent(QMouseEvent *e) { Q_D(Q3DSPresentation); @@ -403,6 +512,15 @@ void Q3DSPresentation::mouseMoveEvent(QMouseEvent *e) d->controller->handlePresentationMouseMoveEvent(e); } +/*! + Passes a mouse release event \a e to the presentation. + + \note The event forwarders in Q3DSPresentation are not normally + needed since Q3DSWidget and Studio3D both pass mouse, keyboard and + touch input on to the Qt 3D Studio engine. They may become useful + however with Q3DSSurfaceViewer, or in special situations, in order + to inject input events. +*/ void Q3DSPresentation::mouseReleaseEvent(QMouseEvent *e) { Q_D(Q3DSPresentation); @@ -410,6 +528,15 @@ void Q3DSPresentation::mouseReleaseEvent(QMouseEvent *e) d->controller->handlePresentationMouseReleaseEvent(e); } +/*! + Passes a mouse double click event \a e to the presentation. + + \note The event forwarders in Q3DSPresentation are not normally + needed since Q3DSWidget and Studio3D both pass mouse, keyboard and + touch input on to the Qt 3D Studio engine. They may become useful + however with Q3DSSurfaceViewer, or in special situations, in order + to inject input events. +*/ void Q3DSPresentation::mouseDoubleClickEvent(QMouseEvent *e) { Q_D(Q3DSPresentation); @@ -418,6 +545,15 @@ void Q3DSPresentation::mouseDoubleClickEvent(QMouseEvent *e) } #if QT_CONFIG(wheelevent) +/*! + Passes a mouse wheel event \a e to the presentation. + + \note The event forwarders in Q3DSPresentation are not normally + needed since Q3DSWidget and Studio3D both pass mouse, keyboard and + touch input on to the Qt 3D Studio engine. They may become useful + however with Q3DSSurfaceViewer, or in special situations, in order + to inject input events. +*/ void Q3DSPresentation::wheelEvent(QWheelEvent *e) { Q_D(Q3DSPresentation); @@ -426,6 +562,15 @@ void Q3DSPresentation::wheelEvent(QWheelEvent *e) } #endif +/*! + Passes a touch event \a e to the presentation. + + \note The event forwarders in Q3DSPresentation are not normally + needed since Q3DSWidget and Studio3D both pass mouse, keyboard and + touch input on to the Qt 3D Studio engine. They may become useful + however with Q3DSSurfaceViewer, or in special situations, in order + to inject input events. +*/ void Q3DSPresentation::touchEvent(QTouchEvent *e) { Q_D(Q3DSPresentation); @@ -434,6 +579,15 @@ void Q3DSPresentation::touchEvent(QTouchEvent *e) } #if QT_CONFIG(tabletevent) +/*! + Passes a tablet (pen) event \a e to the presentation. + + \note The event forwarders in Q3DSPresentation are not normally + needed since Q3DSWidget and Studio3D both pass mouse, keyboard and + touch input on to the Qt 3D Studio engine. They may become useful + however with Q3DSSurfaceViewer, or in special situations, in order + to inject input events. +*/ void Q3DSPresentation::tabletEvent(QTabletEvent *e) { Q_D(Q3DSPresentation); @@ -557,6 +711,45 @@ void Q3DSPresentationPrivate::registerInlineQmlSubPresentations(const QVectorfbo = 0; } +/*! + \fn Q3DSSurfaceViewer::frameUpdate() + + This signal is emitted each time a frame has been rendered. +*/ + +/*! + \fn Q3DSSurfaceViewer::presentationLoaded() + + This signal is emitted when the viewer has been initialized and the + presentation is ready to be shown. +*/ + /*! Returns the presentation object used by the Q3DSSurfaceViewer. */ @@ -205,6 +223,15 @@ Q3DSViewerSettings *Q3DSSurfaceViewer::settings() const return d->viewerSettings; } +/*! + \property Q3DSSurfaceViewer::error + + Contains the text for the error message that was generated during the + loading of the presentation. When no error occurred or there is no + presentation loaded, the value is an empty string. + + This property is read-only. + */ QString Q3DSSurfaceViewer::error() const { Q_D(const Q3DSSurfaceViewer); @@ -225,6 +252,14 @@ bool Q3DSSurfaceViewer::isRunning() const return d->engine && d->sourceLoaded; } +/*! + \property Q3DSSurfaceViewer::size + + Holds the desired size of the presentation. Relevant only when + autoSize is set to \c false. + + \sa autoSize +*/ QSize Q3DSSurfaceViewer::size() const { Q_D(const Q3DSSurfaceViewer); diff --git a/src/runtime/api/q3dsviewersettings.cpp b/src/runtime/api/q3dsviewersettings.cpp index d1c1013..c6c65fd 100644 --- a/src/runtime/api/q3dsviewersettings.cpp +++ b/src/runtime/api/q3dsviewersettings.cpp @@ -66,6 +66,32 @@ Q3DSViewerSettings::~Q3DSViewerSettings() { } +/*! + \enum Q3DSViewerSettings::ShadeMode + + This enumeration specifies the possible shading modes. + + \value ShadeModeShaded The objects in the presentation are shaded normally. + \value ShadeModeShadedWireframe The objects in the presentation are shaded + with a super-imposed wireframe on top of the normal shading. Only objects that specify + a tesselation mode will display this wireframe. +*/ + +/*! + \enum Q3DSViewerSettings::ScaleMode + + This enumeration specifies the possible scaling modes. + + \value ScaleModeFit Scales the presentation to fit the viewer. + \value ScaleModeFill Scales the presentation to fill the viewer. + \value ScaleModeCenter Centers the presentation into the viewer without scaling it. +*/ + +/*! + \property Q3DSViewerSettings::matteColor + + \note This property is currently ignored. + */ QColor Q3DSViewerSettings::matteColor() const { Q_D(const Q3DSViewerSettings); @@ -75,7 +101,7 @@ QColor Q3DSViewerSettings::matteColor() const /*! \property Q3DSViewerSettings::showRenderStats - If this property is set to \c{true}, the interactive statistics and profile + When this property is \c{true}, the interactive statistics and profile view is displayed in-scene, on top of the 3D content. \note This feature can be disabled at build time, in which case this @@ -89,12 +115,22 @@ bool Q3DSViewerSettings::isShowingRenderStats() const return d->showRenderStats; } +/*! + \property Q3DSViewerSettings::shadeMode + + \note This property is currently ignored. + */ Q3DSViewerSettings::ShadeMode Q3DSViewerSettings::shadeMode() const { Q_D(const Q3DSViewerSettings); return d->shadeMode; } +/*! + \property Q3DSViewerSettings::scaleMode + + \note This property is currently ignored. + */ Q3DSViewerSettings::ScaleMode Q3DSViewerSettings::scaleMode() const { Q_D(const Q3DSViewerSettings); @@ -140,6 +176,12 @@ void Q3DSViewerSettings::setScaleMode(Q3DSViewerSettings::ScaleMode mode) } } +/*! + Persistently saves the viewer \l{QSettings}{settings} using \a group, \a organization and + \a application. + + \note This function is not currently implemented. + */ void Q3DSViewerSettings::save(const QString &group, const QString &organization, const QString &application) @@ -150,6 +192,12 @@ void Q3DSViewerSettings::save(const QString &group, qWarning() << Q_FUNC_INFO << "not implemented"; } +/*! + Loads previously saved viewer \l{QSettings}{settings} using \a group, \a organization and + \a application. + + \note This function is not currently implemented. + */ void Q3DSViewerSettings::load(const QString &group, const QString &organization, const QString &application) diff --git a/src/runtime/api/q3dswidget.cpp b/src/runtime/api/q3dswidget.cpp index 8cdd898..56d65d5 100644 --- a/src/runtime/api/q3dswidget.cpp +++ b/src/runtime/api/q3dswidget.cpp @@ -89,7 +89,24 @@ Q3DSWidget::~Q3DSWidget() } /*! + \fn Q3DSWidget::frameUpdate() + + This signal is emitted each time a frame has been rendered. +*/ + +/*! + \fn Q3DSWidget::presentationLoaded() + + This signal is emitted when the viewer has been initialized and the + presentation is ready to be shown. +*/ + +/*! + \property Q3DSWidget::presentation + Returns the presentation object used by the Q3DSWidget. + + This property is read-only. */ Q3DSPresentation *Q3DSWidget::presentation() const { @@ -106,6 +123,15 @@ Q3DSViewerSettings *Q3DSWidget::settings() const return d->viewerSettings; } +/*! + \property Q3DSWidget::error + + Contains the text for the error message that was generated during the + loading of the presentation. When no error occurred or there is no + presentation loaded, the value is an empty string. + + This property is read-only. + */ QString Q3DSWidget::error() const { Q_D(const Q3DSWidget); @@ -159,6 +185,9 @@ void Q3DSWidget::setUpdateInterval(int interval) } } +/*! + \internal + */ void Q3DSWidget::keyPressEvent(QKeyEvent *event) { Q_D(Q3DSWidget); @@ -166,6 +195,9 @@ void Q3DSWidget::keyPressEvent(QKeyEvent *event) d->engine->handleKeyPressEvent(event); } +/*! + \internal + */ void Q3DSWidget::keyReleaseEvent(QKeyEvent *event) { Q_D(Q3DSWidget); @@ -173,6 +205,9 @@ void Q3DSWidget::keyReleaseEvent(QKeyEvent *event) d->engine->handleKeyReleaseEvent(event); } +/*! + \internal + */ void Q3DSWidget::mousePressEvent(QMouseEvent *event) { Q_D(Q3DSWidget); @@ -180,6 +215,9 @@ void Q3DSWidget::mousePressEvent(QMouseEvent *event) d->engine->handleMousePressEvent(event); } +/*! + \internal + */ void Q3DSWidget::mouseMoveEvent(QMouseEvent *event) { Q_D(Q3DSWidget); @@ -187,6 +225,9 @@ void Q3DSWidget::mouseMoveEvent(QMouseEvent *event) d->engine->handleMouseMoveEvent(event); } +/*! + \internal + */ void Q3DSWidget::mouseReleaseEvent(QMouseEvent *event) { Q_D(Q3DSWidget); @@ -194,6 +235,9 @@ void Q3DSWidget::mouseReleaseEvent(QMouseEvent *event) d->engine->handleMouseReleaseEvent(event); } +/*! + \internal + */ void Q3DSWidget::mouseDoubleClickEvent(QMouseEvent *event) { Q_D(Q3DSWidget); @@ -202,6 +246,9 @@ void Q3DSWidget::mouseDoubleClickEvent(QMouseEvent *event) } #if QT_CONFIG(wheelevent) +/*! + \internal + */ void Q3DSWidget::wheelEvent(QWheelEvent *event) { Q_D(Q3DSWidget); @@ -210,10 +257,16 @@ void Q3DSWidget::wheelEvent(QWheelEvent *event) } #endif +/*! + \internal + */ void Q3DSWidget::initializeGL() { } +/*! + \internal + */ void Q3DSWidget::resizeGL(int w, int h) { Q_D(Q3DSWidget); @@ -224,6 +277,9 @@ void Q3DSWidget::resizeGL(int w, int h) } } +/*! + \internal + */ void Q3DSWidget::paintGL() { Q_D(Q3DSWidget); diff --git a/src/runtime/doc/src/images/customsignal.png b/src/runtime/doc/src/images/customsignal.png new file mode 100644 index 0000000..eb0e0ba Binary files /dev/null and b/src/runtime/doc/src/images/customsignal.png differ diff --git a/src/runtime/doc/src/profileui.qdoc b/src/runtime/doc/src/profileui.qdoc index 2aeb928..91df0a2 100644 --- a/src/runtime/doc/src/profileui.qdoc +++ b/src/runtime/doc/src/profileui.qdoc @@ -45,8 +45,8 @@ In applications these views have no built-in shortcuts. It is up to the application to toggle visibility. From C++ this is done via \l - Q3DSPresentation::profileUiVisible() or \l - Q3DSViewerSettings::showRenderStats(). From QML the corresponding properties + Q3DSPresentation::profileUiVisible or \l + Q3DSViewerSettings::showRenderStats. From QML the corresponding properties are \l Presentation::profileUiVisible and \l ViewerSettings::showRenderStats. In order to enable all features in the debug and profile views, presentations -- cgit v1.2.3 From b4a7f13326d86db82fe96b7b13cb7f1cdb3bdf33 Mon Sep 17 00:00:00 2001 From: Jere Tuliniemi Date: Wed, 23 May 2018 15:18:06 +0300 Subject: Remove the use of f for floats in shaders Task-number: QT3DS-1765 Change-Id: If398f95fba9ed409761602937c49fc2d93fe46f6 Reviewed-by: Laszlo Agocs --- res/effectlib/Fxaa3_8.glsllib | 2 +- res/effectlib/average.glsllib | 2 +- res/effectlib/calculateRoughness.glsllib | 4 +- res/effectlib/customMaterial.glsllib | 10 ++-- res/effectlib/customMaterialFragBody.glsllib | 8 +-- res/effectlib/customMaterialFragBodyAO.glsllib | 8 +-- res/effectlib/diffuseReflectionBSDF.glsllib | 6 +-- res/effectlib/diffuseTransmissionBSDF.glsllib | 6 +-- res/effectlib/fileBumpTexture.glsllib | 2 +- res/effectlib/flakeNoiseBumpTexture.glsllib | 2 +- res/effectlib/flakeNoiseTexture.glsllib | 8 +-- res/effectlib/fresnelLayer.glsllib | 18 +++---- res/effectlib/gradient3Recolor.glsllib | 14 +++--- res/effectlib/gradientGetPosition.glsllib | 14 +++--- res/effectlib/miNoise.glsllib | 22 ++++----- res/effectlib/microfacetBSDF.glsllib | 14 +++--- res/effectlib/normalizedMix.glsllib | 2 +- res/effectlib/perlinNoise.glsllib | 68 +++++++++++++------------- res/effectlib/physGlossyBSDF.glsllib | 4 +- res/effectlib/sampleArea.glsllib | 2 +- res/effectlib/sampleLight.glsllib | 12 ++--- res/effectlib/simpleGlossyBSDF.glsllib | 18 +++---- res/effectlib/specularBSDF.glsllib | 6 +-- res/effectlib/spotEdf.glsllib | 2 +- 24 files changed, 127 insertions(+), 127 deletions(-) diff --git a/res/effectlib/Fxaa3_8.glsllib b/res/effectlib/Fxaa3_8.glsllib index 7e76ecd..620f565 100644 --- a/res/effectlib/Fxaa3_8.glsllib +++ b/res/effectlib/Fxaa3_8.glsllib @@ -1370,7 +1370,7 @@ float4 FxaaPixelShader( float2 posP = posN; float2 offNP = horzSpan ? FxaaFloat2(rcpFrame.x, 0.0) : - FxaaFloat2(0.0f, rcpFrame.y); + FxaaFloat2(0.0, rcpFrame.y); float lumaEndN; float lumaEndP; bool doneN = false; diff --git a/res/effectlib/average.glsllib b/res/effectlib/average.glsllib index 8c3f3fc..082eec0 100644 --- a/res/effectlib/average.glsllib +++ b/res/effectlib/average.glsllib @@ -30,6 +30,6 @@ float average( in vec3 v ) { - return( ( v.x + v.y + v.z ) / 3.0f ); + return( ( v.x + v.y + v.z ) / 3.0 ); } diff --git a/res/effectlib/calculateRoughness.glsllib b/res/effectlib/calculateRoughness.glsllib index d1e099b..a14083d 100644 --- a/res/effectlib/calculateRoughness.glsllib +++ b/res/effectlib/calculateRoughness.glsllib @@ -55,8 +55,8 @@ float calculateRoughness( in vec3 N, in float roughnessU, in float roughnessV, i float cosPhi = dot( po, minorAxis ); // determine the polar coordinate of viewDir, take that radius as the roughness - float excentricitySquare = 1.0f - square( b / a ); - roughness = b / sqrt( 1.0f - excentricitySquare * square( cosPhi ) ); + float excentricitySquare = 1.0 - square( b / a ); + roughness = b / sqrt( 1.0 - excentricitySquare * square( cosPhi ) ); } return( roughness ); } diff --git a/res/effectlib/customMaterial.glsllib b/res/effectlib/customMaterial.glsllib index e99fa6e..0a4d88b 100644 --- a/res/effectlib/customMaterial.glsllib +++ b/res/effectlib/customMaterial.glsllib @@ -36,11 +36,11 @@ uniform sampler2D samplerName; // some useful defines #ifndef PI -#define PI 3.14159265358979f -#define PI_HALF ( 0.5f * PI ) -#define PI_TWO ( 2.0f * PI ) -#define ONE_OVER_PI ( 1.0f / PI ) -#define TWO_OVER_PI ( 2.0f / PI ) +#define PI 3.14159265358979 +#define PI_HALF ( 0.5 * PI ) +#define PI_TWO ( 2.0 * PI ) +#define ONE_OVER_PI ( 1.0 / PI ) +#define TWO_OVER_PI ( 2.0 / PI ) #define PI_SQUARE ( PI * PI ) #endif diff --git a/res/effectlib/customMaterialFragBody.glsllib b/res/effectlib/customMaterialFragBody.glsllib index 7a1b09a..c20c3e0 100644 --- a/res/effectlib/customMaterialFragBody.glsllib +++ b/res/effectlib/customMaterialFragBody.glsllib @@ -32,7 +32,7 @@ #define CUSTOM_MATERIAL_FRAG_BODY_GLSLLIB bool twoSided = false; - vec3 materialEmissive = vec3( 0.0f, 0.0f, 0.0f ); + vec3 materialEmissive = vec3( 0.0, 0.0, 0.0 ); float materialIOR = computeIOR(); @@ -42,7 +42,7 @@ } else { - materialIOR = 1.0f / materialIOR; + materialIOR = 1.0 / materialIOR; twoSided = evalTwoSided(); if ( twoSided ) { @@ -51,7 +51,7 @@ } } - vec4 rgba = vec4( materialEmissive, 0.0f ); + vec4 rgba = vec4( materialEmissive, 0.0 ); vec3 lightAmbient, lightDiffuse, lightSpecular, L; for ( int i=0 ; i eta = ior -// - when hitting a back face : eta2 == 1.0f, eta1 == ior => eta = 1.0f / ior +// - when hitting a front face: eta2 == ior, eta1 == 1.0 => eta = ior +// - when hitting a back face : eta2 == 1.0, eta1 == ior => eta = 1.0 / ior vec3 fresnel( in vec3 N, in vec3 ior ) { float cosTheta1 = dot( N, viewDir ); if ( gl_FrontFacing ) { - return( vec3( fresnel( 1.0f, ior[0], cosTheta1 ), fresnel( 1.0f, ior[1], cosTheta1 ), fresnel( 1.0f, ior[2], cosTheta1 ) ) ); + return( vec3( fresnel( 1.0, ior[0], cosTheta1 ), fresnel( 1.0, ior[1], cosTheta1 ), fresnel( 1.0, ior[2], cosTheta1 ) ) ); } else { - return( vec3( fresnel( ior[0], 1.0f, cosTheta1 ), fresnel( ior[1], 1.0f, cosTheta1 ), fresnel( ior[2], 1.0f, cosTheta1 ) ) ); + return( vec3( fresnel( ior[0], 1.0, cosTheta1 ), fresnel( ior[1], 1.0, cosTheta1 ), fresnel( ior[2], 1.0, cosTheta1 ) ) ); } } diff --git a/res/effectlib/gradient3Recolor.glsllib b/res/effectlib/gradient3Recolor.glsllib index 18556f3..ba7d593 100644 --- a/res/effectlib/gradient3Recolor.glsllib +++ b/res/effectlib/gradient3Recolor.glsllib @@ -35,15 +35,15 @@ float gradientInterpolate( in int interpolationMode, in float value ) case gradient_interpolation_linear : return( value ); case gradient_interpolation_off : - return( 0.0f ); + return( 0.0 ); case gradient_interpolation_ease_in : - return( 1.0f - pow( 1.0f - value, 2.0f/3.0f ) ); + return( 1.0 - pow( 1.0 - value, 2.0/3.0 ) ); case gradient_interpolation_ease_out : - return( pow( value, 2.0f/3.0f ) ); + return( pow( value, 2.0/3.0 ) ); case gradient_interpolation_ease_in_out : - return( ( value <= 0.5f ) - ? 0.5f * pow( 2.0f * value, 2.0f/3.0f ) - : 0.5f + 0.5f * ( 1.0f - pow( 2.0f * ( 1.0f - value ), 2.0f/3.0f ) ) ); + return( ( value <= 0.5 ) + ? 0.5 * pow( 2.0 * value, 2.0/3.0 ) + : 0.5 + 0.5 * ( 1.0 - pow( 2.0 * ( 1.0 - value ), 2.0/3.0 ) ) ); default: return( value ); // default is linear } @@ -67,7 +67,7 @@ texture_return gradient3Recolor( in float gradientPositions[3], in vec3 gradient float relPos = gradientInterpolate( interpolationModes[index], ( pos - gradientPositions[index] ) / ( gradientPositions[index+1] - gradientPositions[index] ) ); tr.tint = mix( gradientColors[index], gradientColors[index+1], relPos ); } - tr.mono = 0.0f; + tr.mono = 0.0; return( tr ); } diff --git a/res/effectlib/gradientGetPosition.glsllib b/res/effectlib/gradientGetPosition.glsllib index 26b687d..4ceece0 100644 --- a/res/effectlib/gradientGetPosition.glsllib +++ b/res/effectlib/gradientGetPosition.glsllib @@ -39,7 +39,7 @@ float hypot( in float x, in float y ) float t = min( x, y ); x = max( x, y ); t = t/x; - return( x * sqrt( 1.0f + ( t * t ) ) ); + return( x * sqrt( 1.0 + ( t * t ) ) ); } float gradientGetPosition( in int gradientMode, in vec2 xy ) @@ -55,22 +55,22 @@ float gradientGetPosition( in int gradientMode, in vec2 xy ) return( tex.x * tex.x ); case gradient_box : // gradient is based on the distance from the center - return( max( abs( tex.x - 0.5f ), abs( tex.y - 0.5f ) ) ); + return( max( abs( tex.x - 0.5 ), abs( tex.y - 0.5 ) ) ); case gradient_diagonal : // gradient is based on the distance from the diagonal - return( sqrt(2.0f) * abs( tex.x - tex.y ) ); + return( sqrt(2.0) * abs( tex.x - tex.y ) ); case gradient_90_degree : // Need to check - return( 0.0f ); + return( 0.0 ); case gradient_symmetric_90_degree : // Need to check - return( 0.0f ); + return( 0.0 ); case gradient_radial : // Distance from center - return( 2.0f * hypot( tex.x - 0.5f, tex.y - 0.5f ) ); + return( 2.0 * hypot( tex.x - 0.5, tex.y - 0.5 ) ); case gradient_360_degree : // fall through need to check default : - return( 0.0f ); + return( 0.0 ); } } diff --git a/res/effectlib/miNoise.glsllib b/res/effectlib/miNoise.glsllib index f2daa81..5fbff37 100644 --- a/res/effectlib/miNoise.glsllib +++ b/res/effectlib/miNoise.glsllib @@ -30,7 +30,7 @@ vec4 miNoise( in vec3 xyz ) { - const float div = 1.0f / 256.0f; + const float div = 1.0 / 256.0; ivec3 itmp = ivec3( xyz ); ivec3 ixyz[3] = ivec3[]( itmp & 0xFF, itmp+1 & 0xFF, itmp+2 & 0xFF ); @@ -38,19 +38,19 @@ vec4 miNoise( in vec3 xyz ) vec3 dux, ux; dux.z = fxyz.x * div; - dux.y = div - 2.0f * dux.z; + dux.y = div - 2.0 * dux.z; dux.x = dux.z - div; - ux.z = 0.5f * fxyz.x * dux.z; - ux.y = dux.z + 0.5f * ( div - fxyz.x * dux.z ); - ux.x = ux.z - dux.z + 0.5f * div; + ux.z = 0.5 * fxyz.x * dux.z; + ux.y = dux.z + 0.5 * ( div - fxyz.x * dux.z ); + ux.x = ux.z - dux.z + 0.5 * div; vec3 duy, uy; duy.z = fxyz.y; - duy.y = 1.0f - 2.0f * duy.z; - duy.x = duy.z - 1.0f; - uy.z = 0.5f * square( duy.z ); - uy.y = duy.z + 0.5f - square( duy.z ); - uy.x = uy.z - duy.z + 0.5f; + duy.y = 1.0 - 2.0 * duy.z; + duy.x = duy.z - 1.0; + uy.z = 0.5 * square( duy.z ); + uy.y = duy.z + 0.5 - square( duy.z ); + uy.x = uy.z - duy.z + 0.5; float duz[3] = float[]( fxyz.z - 1.0, 1.0 - 2.0 * fxyz.z, fxyz.z ); float uz[3] = float[]( 0.5 * square( fxyz.z ) - fxyz.z + 0.5, fxyz.z + 0.5 - square( fxyz.z ), 0.5 * square( fxyz.z ) ); @@ -83,7 +83,7 @@ vec4 miNoise( in vec3 xyz ) int ixyzzz = ixyz[0].z ^ ixyz[1].z; - vec4 ret = vec4( 0.0f, 0.0f, 0.0f, 0.0f ); + vec4 ret = vec4( 0.0, 0.0, 0.0, 0.0 ); for ( int i=0 ; i<3 ; i++ ) { diff --git a/res/effectlib/microfacetBSDF.glsllib b/res/effectlib/microfacetBSDF.glsllib index e164fca..8e48910 100644 --- a/res/effectlib/microfacetBSDF.glsllib +++ b/res/effectlib/microfacetBSDF.glsllib @@ -93,7 +93,7 @@ float DtermGGXAniso( in mat3 tanFrame, in vec3 L, in vec3 V, in float roughnessU vec4 microfacetBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, float ior, in float roughnessU, in float roughnessV, int mode ) { - vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f ); + vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 ); vec3 H = normalize(L + V); float HdotL = clamp(dot(H, L), 0.0, 1.0); float NdotL = dot(tanFrame[2], L); @@ -123,17 +123,17 @@ vec4 microfacetBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecul vec4 microfacetBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode ) { - vec3 rgb = vec3( 0.0f, 0.0f, 0.0f ); + vec3 rgb = vec3( 0.0, 0.0, 0.0 ); #if !QT3DS_ENABLE_LIGHT_PROBE if ( uEnvironmentMappingEnabled ) { float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] ); vec3 R = reflect( -viewDir, tanFrame[2] ); rgb = 0.01 * evalEnvironmentMap( R, roughness ); - rgb = microfacetBSDF( tanFrame, R, viewDir, rgb, 1.0f, roughnessU, roughnessV, scatter_reflect ).rgb; + rgb = microfacetBSDF( tanFrame, R, viewDir, rgb, 1.0, roughnessU, roughnessV, scatter_reflect ).rgb; } #endif - return( vec4( rgb, 1.0f ) ); + return( vec4( rgb, 1.0 ) ); } @@ -211,7 +211,7 @@ vec3 sampleEnv(in vec3 L, float pdf, uint sampleCount, float roughness ) float b = 0.5*log2( pdf * d ); // convert coord to 2D - vec2 tc = vec2( ( atan( L.x, -L.z ) + PI ) / ( 2.0f * PI ), acos( -L.y ) / PI ); + vec2 tc = vec2( ( atan( L.x, -L.z ) + PI ) / ( 2.0 * PI ), acos( -L.y ) / PI ); float weight = step( 0.0001, roughness ); float lod = max( 0.0, min( (a - b)*weight, envMapLevels )); @@ -221,7 +221,7 @@ vec3 sampleEnv(in vec3 L, float pdf, uint sampleCount, float roughness ) vec4 microfacetSampledBSDF( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode ) { - vec3 rgb = vec3( 0.0f, 0.0f, 0.0f ); + vec3 rgb = vec3( 0.0, 0.0, 0.0 ); float roughness = clamp( calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] ), 0.0, 1.0 ); @@ -253,7 +253,7 @@ vec4 microfacetSampledBSDF( in mat3 tanFrame, in vec3 viewDir, in float roughnes rgb /= float(NumSamples); - return( vec4( rgb, 1.0f ) ); + return( vec4( rgb, 1.0 ) ); } #endif diff --git a/res/effectlib/normalizedMix.glsllib b/res/effectlib/normalizedMix.glsllib index 7a44022..fc90b46 100644 --- a/res/effectlib/normalizedMix.glsllib +++ b/res/effectlib/normalizedMix.glsllib @@ -36,7 +36,7 @@ vec4 normalizedMix( in bsdf_component components[1] ) vec4 normalizedMix( in bsdf_component components[2] ) { float sum = components[0].weight + components[1].weight; - float invSum = ( sum <= 1.0f ) ? 1.0f : 1.0f / sum; + float invSum = ( sum <= 1.0 ) ? 1.0 : 1.0 / sum; return( invSum * ( components[0].weight * components[0].component + components[1].weight * components[1].component ) ); } diff --git a/res/effectlib/perlinNoise.glsllib b/res/effectlib/perlinNoise.glsllib index 1fef880..347386c 100644 --- a/res/effectlib/perlinNoise.glsllib +++ b/res/effectlib/perlinNoise.glsllib @@ -45,13 +45,13 @@ vec2 fade( in vec2 x ) vec3 fade( in vec3 x ) { return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 )); - //return( x * x * ( 3.0f - 2.0f * x ) ); + //return( x * x * ( 3.0 - 2.0 * x ) ); } vec4 fade( in vec4 x ) { return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 )); - //return( x * x * ( 3.0f - 2.0f * x ) ); + //return( x * x * ( 3.0 - 2.0 * x ) ); } float influence( in int hash, in float x ) @@ -80,7 +80,7 @@ float perlinNoise( in float pos ) int intPos = int( floorPos ); float fracPos = pos - floorPos; - return( mix( influence( random255X( intPos ), fracPos ), influence( random255X( intPos+1 ), fracPos - 1.0f ), fade( fracPos ) ) ); + return( mix( influence( random255X( intPos ), fracPos ), influence( random255X( intPos+1 ), fracPos - 1.0 ), fade( fracPos ) ) ); } float perlinNoise( in vec2 pos ) @@ -95,9 +95,9 @@ float perlinNoise( in vec2 pos ) int by = random255Y( int(floorPos.y) + 1 ); return( mix( mix( influence( ax^ay, fracPos.x, fracPos.y ) - , influence( bx^ay, fracPos.x - 1.0f, fracPos.y ), fadedPos.x ) - , mix( influence( ax^by, fracPos.x, fracPos.y - 1.0f ) - , influence( bx^by, fracPos.x - 1.0f, fracPos.y - 1.0f ), fadedPos.x ), fadedPos.y ) ); + , influence( bx^ay, fracPos.x - 1.0, fracPos.y ), fadedPos.x ) + , mix( influence( ax^by, fracPos.x, fracPos.y - 1.0 ) + , influence( bx^by, fracPos.x - 1.0, fracPos.y - 1.0 ), fadedPos.x ), fadedPos.y ) ); } float perlinNoise( in vec3 pos ) @@ -119,13 +119,13 @@ float perlinNoise( in vec3 pos ) int bxby = bx ^ by; return( mix( mix( mix( influence( axay^az, fracPos.x, fracPos.y, fracPos.z ) - , influence( bxay^az, fracPos.x - 1.0f, fracPos.y, fracPos.z ), fadedPos.x ) - , mix( influence( axby^az, fracPos.x, fracPos.y - 1.0f, fracPos.z ) - , influence( bxby^az, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z ), fadedPos.x ), fadedPos.y ) - , mix( mix( influence( axay^bz, fracPos.x, fracPos.y , fracPos.z - 1.0f ) - , influence( bxay^bz, fracPos.x - 1.0f, fracPos.y , fracPos.z - 1.0f ), fadedPos.x ) - , mix( influence( axby^bz, fracPos.x, fracPos.y - 1.0f, fracPos.z - 1.0f ) - , influence( bxby^bz, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z - 1.0f ), fadedPos.x ), fadedPos.y ), fadedPos.z ) ); + , influence( bxay^az, fracPos.x - 1.0, fracPos.y, fracPos.z ), fadedPos.x ) + , mix( influence( axby^az, fracPos.x, fracPos.y - 1.0, fracPos.z ) + , influence( bxby^az, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z ), fadedPos.x ), fadedPos.y ) + , mix( mix( influence( axay^bz, fracPos.x, fracPos.y , fracPos.z - 1.0 ) + , influence( bxay^bz, fracPos.x - 1.0, fracPos.y , fracPos.z - 1.0 ), fadedPos.x ) + , mix( influence( axby^bz, fracPos.x, fracPos.y - 1.0, fracPos.z - 1.0 ) + , influence( bxby^bz, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z - 1.0 ), fadedPos.x ), fadedPos.y ), fadedPos.z ) ); } float perlinNoise( in vec4 pos ) @@ -154,45 +154,45 @@ float perlinNoise( in vec4 pos ) int bzaw = bz ^ aw; result[i] = mix( mix( mix( influence( axay^azaw, fracPos.x, fracPos.y, fracPos.z, fracPos.w ) - , influence( bxay^azaw, fracPos.x - 1.0f, fracPos.y, fracPos.z, fracPos.w ), fadedPos.x ) - , mix( influence( axby^azaw, fracPos.x, fracPos.y - 1.0f, fracPos.z, fracPos.w ) - , influence( bxby^azaw, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z, fracPos.w ), fadedPos.x ), fadedPos.y ) - , mix( mix( influence( axay^bzaw, fracPos.x, fracPos.y, fracPos.z - 1.0f, fracPos.w ) - , influence( bxay^bzaw, fracPos.x - 1.0f, fracPos.y, fracPos.z - 1.0f, fracPos.w ), fadedPos.x ) - , mix( influence( axby^bzaw, fracPos.x, fracPos.y - 1.0f, fracPos.z - 1.0f, fracPos.w ) - , influence( bxby^bzaw, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z - 1.0f, fracPos.w ), fadedPos.x ), fadedPos.y ), fadedPos.z ); + , influence( bxay^azaw, fracPos.x - 1.0, fracPos.y, fracPos.z, fracPos.w ), fadedPos.x ) + , mix( influence( axby^azaw, fracPos.x, fracPos.y - 1.0, fracPos.z, fracPos.w ) + , influence( bxby^azaw, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z, fracPos.w ), fadedPos.x ), fadedPos.y ) + , mix( mix( influence( axay^bzaw, fracPos.x, fracPos.y, fracPos.z - 1.0, fracPos.w ) + , influence( bxay^bzaw, fracPos.x - 1.0, fracPos.y, fracPos.z - 1.0, fracPos.w ), fadedPos.x ) + , mix( influence( axby^bzaw, fracPos.x, fracPos.y - 1.0, fracPos.z - 1.0, fracPos.w ) + , influence( bxby^bzaw, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z - 1.0, fracPos.w ), fadedPos.x ), fadedPos.y ), fadedPos.z ); aw = random255W( int(floorPos.w) + 1 ); - fracPos.w -= 1.0f; + fracPos.w -= 1.0; } return( mix( result[0], result[1], fadedPos.w ) ); } float summedPerlinNoise( in vec3 pos, in int terms, in bool absNoise ) { - float sum = 0.0f; - float weight = 1.0f; + float sum = 0.0; + float weight = 1.0; vec3 p = pos; while ( terms-- != 0 ) { float noise = perlinNoise( p ); sum += weight * ( absNoise ? abs(noise) : noise ); p += p; - weight *= 0.5f; + weight *= 0.5; } return( sum ); } float summedPerlinNoise( in vec4 pos, in int terms, in bool absNoise ) { - float sum = 0.0f; - float weight = 1.0f; + float sum = 0.0; + float weight = 1.0; vec4 p = pos; while ( terms-- != 0 ) { float noise = perlinNoise( p ); sum += weight * ( absNoise ? abs(noise) : noise ); p += p; - weight *= 0.5f; + weight *= 0.5; } return( sum ); } @@ -200,34 +200,34 @@ float summedPerlinNoise( in vec4 pos, in int terms, in bool absNoise ) float perlinNoise( in vec3 pos, in float time, in int terms, in vec3 turbulenceWeight, in bool absoluteNoise, in bool applyMarble , in bool applyDent, in float noiseBands, in float noiseThresholdHigh, in float noiseThresholdLow ) { - float noise = ( time == 0.0f ) ? summedPerlinNoise( pos, terms, absoluteNoise ) : summedPerlinNoise( vec4( pos, time ), terms, absoluteNoise ); - if ( turbulenceWeight != vec3( 0.0f, 0.0f, 0.0f ) ) + float noise = ( time == 0.0 ) ? summedPerlinNoise( pos, terms, absoluteNoise ) : summedPerlinNoise( vec4( pos, time ), terms, absoluteNoise ); + if ( turbulenceWeight != vec3( 0.0, 0.0, 0.0 ) ) { noise = sin( dot( pos, turbulenceWeight ) + noise ); } if ( ! absoluteNoise ) { - noise = 0.5f * noise + 0.5f; // scale [-1,1] to [0,1] + noise = 0.5 * noise + 0.5; // scale [-1,1] to [0,1] } if ( applyMarble ) { - noise = cos( pos.x + 5.0f * noise ); // classic Perlin marble function, with magic 5.0f + noise = cos( pos.x + 5.0 * noise ); // classic Perlin marble function, with magic 5.0 } if ( applyDent ) { noise = cube( noise ); } - if ( noiseBands != 1.0f ) + if ( noiseBands != 1.0 ) { // Create banding/stripes by using the fraction component only noise *= noiseBands; noise -= floor( noise ); - noise += pow( 1.0f - noise, 20.0f ); + noise += pow( 1.0 - noise, 20.0 ); } if ( noiseThresholdLow < noiseThresholdHigh ) { // clamp the noise - noise = clamp( ( noise - noiseThresholdLow ) / ( noiseThresholdHigh - noiseThresholdLow ), 0.0f, 1.0f ); + noise = clamp( ( noise - noiseThresholdLow ) / ( noiseThresholdHigh - noiseThresholdLow ), 0.0, 1.0 ); } return( noise ); } diff --git a/res/effectlib/physGlossyBSDF.glsllib b/res/effectlib/physGlossyBSDF.glsllib index ff0eb8c..ece836b 100644 --- a/res/effectlib/physGlossyBSDF.glsllib +++ b/res/effectlib/physGlossyBSDF.glsllib @@ -66,7 +66,7 @@ vec4 kggxGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecul float NdotL = dot(tanFrame[2], L); float HdotL = clamp(dot(H, L), 0.0, 1.0); - // if (0.0f < NdotL) + // if (0.0 < NdotL) // { vec3 Haf = L + V; @@ -123,7 +123,7 @@ vec4 wardGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecul float NdotL = dot(tanFrame[2], L); float HdotL = clamp(dot(H, L), 0.0, 1.0); -// if (0.0f < NdotL) +// if (0.0 < NdotL) // { vec3 Haf = L + V; diff --git a/res/effectlib/sampleArea.glsllib b/res/effectlib/sampleArea.glsllib index 2253359..01f3a74 100644 --- a/res/effectlib/sampleArea.glsllib +++ b/res/effectlib/sampleArea.glsllib @@ -168,7 +168,7 @@ vec4 sampleAreaDiffuseTransmissive( in mat3 tanFrame, in vec3 pos, in int lightI arealights[lightIdx].up, arealights[lightIdx].right, pos, finalDir ); intensity *= clamp( dot(finalDir, -tanFrame[2]), 0.0, 1.0 ); - float l = 0.2126f * transmissiveColor.r + 0.7152f * transmissiveColor.g + 0.0722f * transmissiveColor.b; + float l = 0.2126 * transmissiveColor.r + 0.7152 * transmissiveColor.g + 0.0722 * transmissiveColor.b; float I = max( 0.0, ((dot(finalDir, -tanFrame[2]) + lightWrap)/ (1.0 + lightWrap)) ); float translucent_thickness = l * l; diff --git a/res/effectlib/sampleLight.glsllib b/res/effectlib/sampleLight.glsllib index 3218cdf..8afd8e2 100644 --- a/res/effectlib/sampleLight.glsllib +++ b/res/effectlib/sampleLight.glsllib @@ -59,7 +59,7 @@ void sampleLight(in LightSource light, out vec3 opSpecular) { float att = 1.0; - if (light.position.w == 0.0f) // directional light + if (light.position.w == 0.0) // directional light { wi = normalize(light.position.xyz); #if QT3DS_ENABLE_SSM @@ -67,7 +67,7 @@ void sampleLight(in LightSource light, att *= sampleOrthographic( shadowMaps[light.shadowIdx], light.shadowControls, light.shadowView, pos, vec2(1.0, light.shadowControls.z) ); #endif } - else if (light.width > 0.01f && light.height > 0.01f) // area light + else if (light.width > 0.01 && light.height > 0.01) // area light { // This approach is based on the 1994 Tech Report by James Arvo -- // The Irradiance Jacobian for Partially Occluded Polyhedral Sources @@ -106,12 +106,12 @@ void sampleLight(in LightSource light, wi = light.position.xyz - pos; float dist = length(wi); wi = wi / dist; // == normalize(wi); - att = 1.0f / (light.constantAttenuation + (light.linearAttenuation + light.quadraticAttenuation * dist) * dist); + att = 1.0 / (light.constantAttenuation + (light.linearAttenuation + light.quadraticAttenuation * dist) * dist); /* - if (light.spotCutoff < 180.0f) // spot light + if (light.spotCutoff < 180.0) // spot light { - float spot = max(0.0f, dot(wi, -light.direction.xyz)); - att *= (spot >= cos(light.spotCutoff * PI / 180.0f)) ? pow(spot, light.spotExponent) : 0.0f; + float spot = max(0.0, dot(wi, -light.direction.xyz)); + att *= (spot >= cos(light.spotCutoff * PI / 180.0)) ? pow(spot, light.spotExponent) : 0.0; } */ #if QT3DS_ENABLE_SSM diff --git a/res/effectlib/simpleGlossyBSDF.glsllib b/res/effectlib/simpleGlossyBSDF.glsllib index 31a9ac5..be6024c 100644 --- a/res/effectlib/simpleGlossyBSDF.glsllib +++ b/res/effectlib/simpleGlossyBSDF.glsllib @@ -31,10 +31,10 @@ vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecular, in float ior , in float roughnessU, in float roughnessV, int mode ) { - vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f ); + vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 ); float cosTheta = dot( tanFrame[2], L ); - if ( 0.0f < cosTheta ) + if ( 0.0 < cosTheta ) { float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] ); @@ -42,7 +42,7 @@ vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecula { vec3 R = reflect( -L, tanFrame[2] ); float cosine = dot( R, V ); - float shine = ( 0.0f < cosine ) ? ( ( 0.0f < roughness ) ? pow( cosine, 1.0f / roughness ) : ( 0.9999f <= cosine ) ? 1.0f : 0.0f ) : 0.0f; + float shine = ( 0.0 < cosine ) ? ( ( 0.0 < roughness ) ? pow( cosine, 1.0 / roughness ) : ( 0.9999 <= cosine ) ? 1.0 : 0.0 ) : 0.0; rgba.rgb = shine * lightSpecular; } } @@ -50,13 +50,13 @@ vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecula { // check against total reflection vec3 R = refract( -V, tanFrame[2], ior ); - if ( R == vec3( 0.0f, 0.0f, 0.0f ) ) + if ( R == vec3( 0.0, 0.0, 0.0 ) ) { - rgba.a = 1.0f; + rgba.a = 1.0; } else { - rgba.a = 0.0f; + rgba.a = 0.0; } } @@ -65,17 +65,17 @@ vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecula vec4 simpleGlossyBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode ) { - vec3 rgb = vec3( 0.0f, 0.0f, 0.0f ); + vec3 rgb = vec3( 0.0, 0.0, 0.0 ); #if !QT3DS_ENABLE_LIGHT_PROBE if ( uEnvironmentMappingEnabled ) { float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] ); vec3 R = reflect( -viewDir, tanFrame[2] ); rgb = evalEnvironmentMap( R, roughness ); - rgb = simpleGlossyBSDF( tanFrame, R, viewDir, rgb, 1.0f, roughnessU, roughnessV, scatter_reflect ).rgb; + rgb = simpleGlossyBSDF( tanFrame, R, viewDir, rgb, 1.0, roughnessU, roughnessV, scatter_reflect ).rgb; } #endif - return( vec4( rgb, 1.0f ) ); + return( vec4( rgb, 1.0 ) ); } // RNM radiosity normal maps diff --git a/res/effectlib/specularBSDF.glsllib b/res/effectlib/specularBSDF.glsllib index 9e31544..78e541a 100644 --- a/res/effectlib/specularBSDF.glsllib +++ b/res/effectlib/specularBSDF.glsllib @@ -34,14 +34,14 @@ vec4 specularBSDFEnvironment( in vec3 N, in vec3 viewDir, in vec3 tint, int mode ) { - vec3 rgb = vec3( 0.0f, 0.0f, 0.0f ); + vec3 rgb = vec3( 0.0, 0.0, 0.0 ); if ( uEnvironmentMappingEnabled ) { vec3 R = reflect( -viewDir, N ); - rgb = evalEnvironmentMap( R, 0.0f ); + rgb = evalEnvironmentMap( R, 0.0 ); rgb = specularBSDF( N, R, viewDir, rgb, 1.0, 256.0, tint, scatter_reflect ).rgb; } - return( vec4( rgb, 1.0f ) ); + return( vec4( rgb, 1.0 ) ); } #endif diff --git a/res/effectlib/spotEdf.glsllib b/res/effectlib/spotEdf.glsllib index 663bd8f..2abe194 100644 --- a/res/effectlib/spotEdf.glsllib +++ b/res/effectlib/spotEdf.glsllib @@ -35,7 +35,7 @@ float spotEdf( float exponent ) float dist = length(viewDir); vec3 spotDir = viewDir / dist; - float spot = max(0.0f, dot(spotDir, normal)); + float spot = max(0.0, dot(spotDir, normal)); att = pow(spot, exponent); return att; -- cgit v1.2.3 From b533d818494b6ed77d1c858e18c56d425f5a6197 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 22 May 2018 17:23:53 +0200 Subject: make the gles 3.1 msaa compositor shaders compile ...with NVIDIA on Android for instance. Task-number: QT3DS-1756 Change-Id: I3f3a4a718b4bebc8b5b8537065ffa6caad5d8bbd Reviewed-by: Christian Stromme Reviewed-by: Andy Nichols --- src/runtime/shaders/compositor_ms2.frag | 5 +++-- src/runtime/shaders/compositor_ms4.frag | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/runtime/shaders/compositor_ms2.frag b/src/runtime/shaders/compositor_ms2.frag index 40b50d4..f920a7b 100644 --- a/src/runtime/shaders/compositor_ms2.frag +++ b/src/runtime/shaders/compositor_ms2.frag @@ -1,14 +1,15 @@ #version 310 es +precision highp float; in vec2 texCoord; -uniform sampler2DMS tex; +uniform highp sampler2DMS tex; out vec4 fragColor; void main() { - ivec2 tc = ivec2(floor(textureSize(tex) * texCoord)); + ivec2 tc = ivec2(floor(vec2(textureSize(tex)) * texCoord)); vec4 c = texelFetch(tex, tc, 0) + texelFetch(tex, tc, 1); c /= 2.0; // This discard, while not necessarily ideal for some GPUs, is necessary to diff --git a/src/runtime/shaders/compositor_ms4.frag b/src/runtime/shaders/compositor_ms4.frag index 12dc470..1bbf3d8 100644 --- a/src/runtime/shaders/compositor_ms4.frag +++ b/src/runtime/shaders/compositor_ms4.frag @@ -1,14 +1,15 @@ #version 310 es +precision highp float; in vec2 texCoord; -uniform sampler2DMS tex; +uniform highp sampler2DMS tex; out vec4 fragColor; void main() { - ivec2 tc = ivec2(floor(textureSize(tex) * texCoord)); + ivec2 tc = ivec2(floor(vec2(textureSize(tex)) * texCoord)); vec4 c = texelFetch(tex, tc, 0) + texelFetch(tex, tc, 1) + texelFetch(tex, tc, 2) + texelFetch(tex, tc, 3); c /= 4.0; // This discard, while not necessarily ideal for some GPUs, is necessary to -- cgit v1.2.3 From 65485e5df4412cc4badf55597603b32124d0196b Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 23 May 2018 13:40:49 +0200 Subject: Drop stencil on GLES <= 3.1 like it's done for GLES 2.0 Change-Id: I4ab6cfda0779bf43bf9a1f125ad1a0265b114c50 Reviewed-by: Christian Stromme --- src/runtime/q3dsscenemanager.cpp | 54 +++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index 6462e94..8ec538a 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -866,7 +866,7 @@ static Qt3DRender::QAbstractTexture *newColorBuffer(const QSize &layerPixelSize, return colorTex; } -static Qt3DRender::QAbstractTexture *newDepthStencilBuffer(const QSize &layerPixelSize, int msaaSampleCount, Qt3DRender::QAbstractTexture::TextureFormat format = Qt3DRender::QAbstractTexture::D24S8) +static Qt3DRender::QAbstractTexture *newDepthStencilBuffer(const QSize &layerPixelSize, int msaaSampleCount, Qt3DRender::QAbstractTexture::TextureFormat format) { // GLES <= 3.1 does not have glFramebufferTexture and support for combined // depth-stencil textures. Here we rely on the fact the Qt3D will @@ -876,9 +876,10 @@ static Qt3DRender::QAbstractTexture *newDepthStencilBuffer(const QSize &layerPix // // The internal difference (renderbuffer vs. texture) won't matter as long // as a custom material or other thing does not need the depth texture. - // When that happens, we will be in trouble when running on GLES < 3.2 ... - // An option then would be to get rid of stencil since plain depth textures - // work in GLES >= 3.0. + // When that happens, we will be in trouble when running on GLES < 3.2. + // + // Therefore, on GLES 2.0, 3.0 and 3.1 we expect to get called with D16 (or + // D24 or D32) and no stencil. (whereas GLES 3.2 or desktop GL will use D24S8) Qt3DRender::QAbstractTexture *dsTexOrRb; if (msaaSampleCount > 1) { @@ -912,28 +913,25 @@ Qt3DRender::QRenderTarget *Q3DSSceneManager::newLayerRenderTarget(const QSize &l rt->addOutput(color); Qt3DRender::QRenderTargetOutput *ds = new Qt3DRender::QRenderTargetOutput; - if (m_gfxLimits.packedDepthStencilBufferSupported) { - ds->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::DepthStencil); - if (!existingDS) { - *dsTexOrRb = newDepthStencilBuffer(layerPixelSize, msaaSampleCount); - m_profiler->trackNewObject(*dsTexOrRb, Q3DSProfiler::Texture2DObject, - "Depth-stencil buffer for layer %s", layer3DS->id().constData()); - (*dsTexOrRb)->setParent(textureParentNode); - } else { - *dsTexOrRb = existingDS; - } + bool noStencil = !m_gfxLimits.packedDepthStencilBufferSupported; // GLES 2.0 + // see newDepthStencilBuffer for a detailed description of this mess + noStencil |= m_gfxLimits.format.renderableType() == QSurfaceFormat::OpenGLES + && Q3DS::graphicsLimits().format.version() <= qMakePair(3, 1); + Qt3DRender::QAbstractTexture::TextureFormat textureFormat = + noStencil ? Qt3DRender::QAbstractTexture::D16 : Qt3DRender::QAbstractTexture::D24S8; + ds->setAttachmentPoint(noStencil ? Qt3DRender::QRenderTargetOutput::Depth + : Qt3DRender::QRenderTargetOutput::DepthStencil); + if (!existingDS) { + if (noStencil) + qCDebug(lcScene, "Render target depth-stencil attachment uses D16 (no stencil)"); + else + qCDebug(lcScene, "Render target depth-stencil attachment uses D24S8"); + *dsTexOrRb = newDepthStencilBuffer(layerPixelSize, msaaSampleCount, textureFormat); + m_profiler->trackNewObject(*dsTexOrRb, Q3DSProfiler::Texture2DObject, + "Depth-stencil buffer for layer %s", layer3DS->id().constData()); + (*dsTexOrRb)->setParent(textureParentNode); } else { - // This is for ES2 case without support for packed depth-stencil buffers - // Depth - ds->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Depth); - if (!existingDS) { - *dsTexOrRb = newDepthStencilBuffer(layerPixelSize, msaaSampleCount, Qt3DRender::QAbstractTexture::D16); - m_profiler->trackNewObject(*dsTexOrRb, Q3DSProfiler::Texture2DObject, - "Depth buffer for layer %s", layer3DS->id().constData()); - (*dsTexOrRb)->setParent(textureParentNode); - } else { - *dsTexOrRb = existingDS; - } + *dsTexOrRb = existingDS; } ds->setTexture(*dsTexOrRb); @@ -2469,7 +2467,7 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi auto createDepthStencil = [size, this]() { Qt3DRender::QTexture2D *dsTexOrRb = new Qt3DRender::QTexture2D; m_profiler->trackNewObject(dsTexOrRb, Q3DSProfiler::Texture2DObject, "Shadow map depth"); - dsTexOrRb->setFormat(Qt3DRender::QAbstractTexture::D24S8); + dsTexOrRb->setFormat(Qt3DRender::QAbstractTexture::D16); dsTexOrRb->setWidth(size); dsTexOrRb->setHeight(size); dsTexOrRb->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear); @@ -2570,7 +2568,7 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi shadowRt->addOutput(shadowRtOutput); shadowRtOutput = new Qt3DRender::QRenderTargetOutput; - shadowRtOutput->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::DepthStencil); + shadowRtOutput->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Depth); shadowRtOutput->setTexture(d->shadowDS); shadowRt->addOutput(shadowRtOutput); @@ -2631,7 +2629,7 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi shadowRt->addOutput(shadowRtOutput); shadowRtOutput = new Qt3DRender::QRenderTargetOutput; - shadowRtOutput->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::DepthStencil); + shadowRtOutput->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Depth); shadowRtOutput->setTexture(d->shadowDS); shadowRt->addOutput(shadowRtOutput); -- cgit v1.2.3 From e21545a9c2e8fd671c449bf9a67368161387308a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 23 May 2018 15:34:55 +0200 Subject: Check for GL_EXT_texture_norm16 on GLES Since GL_R16 is not available otherwise. Fall back to GL_R8 then which leads to worse looking results. Change-Id: I44adeac1940e0c085947547d2ccbc36ef5c9e75a Reviewed-by: Christian Stromme --- src/runtime/q3dsengine.cpp | 6 ++++++ src/runtime/q3dsgraphicslimits_p.h | 1 + src/runtime/q3dsscenemanager.cpp | 11 +++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/runtime/q3dsengine.cpp b/src/runtime/q3dsengine.cpp index 5faae2c..6772184 100644 --- a/src/runtime/q3dsengine.cpp +++ b/src/runtime/q3dsengine.cpp @@ -208,6 +208,12 @@ static void initGraphicsLimits(QOpenGLContext *ctx) if (extensions.contains("GL_EXT_packed_depth_stencil")) gfxLimits.packedDepthStencilBufferSupported = true; qDebug(" packed depth-stencil: %s", gfxLimits.packedDepthStencilBufferSupported ? "true" : "false"); + + if (ctx->isOpenGLES()) + gfxLimits.norm16TexturesSupported = extensions.contains("GL_EXT_texture_norm16"); + else + gfxLimits.norm16TexturesSupported = true; + qDebug(" norm16 textures: %s", gfxLimits.norm16TexturesSupported ? "true" : "false"); } qDebug() << " extensions: " << extensions; diff --git a/src/runtime/q3dsgraphicslimits_p.h b/src/runtime/q3dsgraphicslimits_p.h index 2e624cf..e7b8cfe 100644 --- a/src/runtime/q3dsgraphicslimits_p.h +++ b/src/runtime/q3dsgraphicslimits_p.h @@ -55,6 +55,7 @@ struct Q3DSGraphicsLimits { bool shaderTextureLodSupported = true; bool shaderUniformBufferSupported = true; bool packedDepthStencilBufferSupported = true; + bool norm16TexturesSupported = true; QByteArray renderer; QByteArray vendor; QByteArray version; diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index 8ec538a..42e46b2 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -2516,8 +2516,15 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi "Shadow map temp buffer for light %s", light3DS->id().constData()); } - d->shadowMapTexture->setFormat(Qt3DRender::QAbstractTexture::R16_UNorm); - d->shadowMapTextureTemp->setFormat(Qt3DRender::QAbstractTexture::R16_UNorm); + Qt3DRender::QAbstractTexture::TextureFormat format = Qt3DRender::QAbstractTexture::R16_UNorm; + // GL_R16 does not seem to exist in OpenGL ES unless GL_EXT_texture_norm16 + // is present. Fall back to the GL_R8 when not supported (but this leads + // to uglier output with more artifacts). + if (!m_gfxLimits.norm16TexturesSupported) + format = Qt3DRender::QAbstractTexture::R8_UNorm; + + d->shadowMapTexture->setFormat(format); + d->shadowMapTextureTemp->setFormat(format); d->shadowMapTexture->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear); d->shadowMapTextureTemp->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear); -- cgit v1.2.3 From 9fde01d51d1be7bd630a85f763f0e512b4b2d9d5 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 23 May 2018 16:14:02 +0200 Subject: Make sure GL feature checks are not accidentally left true Change-Id: Ibd4d8751d82690f2856b651203b48b44e714cfa8 Reviewed-by: Christian Stromme --- src/runtime/q3dsengine.cpp | 34 +++++++++++++++------------------- src/runtime/q3dsgraphicslimits_p.h | 8 ++++---- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/runtime/q3dsengine.cpp b/src/runtime/q3dsengine.cpp index 6772184..45d9c67 100644 --- a/src/runtime/q3dsengine.cpp +++ b/src/runtime/q3dsengine.cpp @@ -193,28 +193,24 @@ static void initGraphicsLimits(QOpenGLContext *ctx) qDebug(" multisample textures: %s", gfxLimits.multisampleTextureSupported ? "true" : "false"); auto extensions = ctx->extensions(); - if (!extensions.isEmpty()) { - gfxLimits.extensions = extensions; + gfxLimits.extensions = extensions; - if (ctx->isOpenGLES() && ctx->format().majorVersion() == 2) { - gfxLimits.shaderTextureLodSupported = false; - gfxLimits.shaderUniformBufferSupported = false; - gfxLimits.packedDepthStencilBufferSupported = false; - } - if (extensions.contains("GL_EXT_shader_texture_lod")) - gfxLimits.shaderTextureLodSupported = true; - qDebug(" texture lod: %s", gfxLimits.shaderTextureLodSupported ? "true" : "false"); + if (ctx->isOpenGLES() && ctx->format().majorVersion() < 3) { + gfxLimits.shaderUniformBufferSupported = false; + gfxLimits.shaderTextureLodSupported = extensions.contains("GL_EXT_shader_texture_lod"); + gfxLimits.packedDepthStencilBufferSupported = extensions.contains("GL_EXT_packed_depth_stencil"); + } else { + gfxLimits.shaderUniformBufferSupported = true; + gfxLimits.shaderTextureLodSupported = true; + gfxLimits.packedDepthStencilBufferSupported = true; + } + qDebug(" uniform buffers: %s", gfxLimits.shaderUniformBufferSupported ? "true" : "false"); + qDebug(" texture lod: %s", gfxLimits.shaderTextureLodSupported ? "true" : "false"); + qDebug(" packed depth-stencil: %s", gfxLimits.packedDepthStencilBufferSupported ? "true" : "false"); - if (extensions.contains("GL_EXT_packed_depth_stencil")) - gfxLimits.packedDepthStencilBufferSupported = true; - qDebug(" packed depth-stencil: %s", gfxLimits.packedDepthStencilBufferSupported ? "true" : "false"); + gfxLimits.norm16TexturesSupported = ctx->isOpenGLES() ? extensions.contains("GL_EXT_texture_norm16") : true; + qDebug(" norm16 textures: %s", gfxLimits.norm16TexturesSupported ? "true" : "false"); - if (ctx->isOpenGLES()) - gfxLimits.norm16TexturesSupported = extensions.contains("GL_EXT_texture_norm16"); - else - gfxLimits.norm16TexturesSupported = true; - qDebug(" norm16 textures: %s", gfxLimits.norm16TexturesSupported ? "true" : "false"); - } qDebug() << " extensions: " << extensions; // version string bonanza for the profiler diff --git a/src/runtime/q3dsgraphicslimits_p.h b/src/runtime/q3dsgraphicslimits_p.h index e7b8cfe..6314c7b 100644 --- a/src/runtime/q3dsgraphicslimits_p.h +++ b/src/runtime/q3dsgraphicslimits_p.h @@ -52,10 +52,10 @@ struct Q3DSGraphicsLimits { bool versionedContextFailed = false; int maxDrawBuffers = 4; bool multisampleTextureSupported = false; - bool shaderTextureLodSupported = true; - bool shaderUniformBufferSupported = true; - bool packedDepthStencilBufferSupported = true; - bool norm16TexturesSupported = true; + bool shaderTextureLodSupported = false; + bool shaderUniformBufferSupported = false; + bool packedDepthStencilBufferSupported = false; + bool norm16TexturesSupported = false; QByteArray renderer; QByteArray vendor; QByteArray version; -- cgit v1.2.3 From b7e63b82396abfb25e1c31443ed6c7f9437aa30d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 23 May 2018 15:32:37 +0200 Subject: Fix eyeball updates for effects We need to update these the same way we do node types, which includes storing the rollback data to reset the values once the slide changes. Change-Id: I2f59a68d279d00c331ca63f29885c1b0552008a9 Reviewed-by: Laszlo Agocs --- src/runtime/q3dsslideplayer.cpp | 59 ++++++++++++++++++++++--------------- src/runtime/q3dsslideplayer_p.h | 2 +- src/runtime/q3dsuippresentation.cpp | 7 +++++ src/runtime/q3dsuippresentation_p.h | 3 ++ 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index 432bde3..fd2a328 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -665,17 +665,18 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide, Q_EMIT slideChanged(slide); } -static bool nodeHasVisibilityTag(Q3DSNode *node) +static bool objectHasVisibilityTag(Q3DSGraphObject *object) { - Q_ASSERT(node); - Q_ASSERT(node->attached()); + Q_ASSERT(object); + Q_ASSERT(object->attached()); + Q_ASSERT(object->isNode() || object->type() == Q3DSGraphObject::Effect); - auto nodeAttached = static_cast(node->attached()); - auto entity = nodeAttached->entity; + auto entity = object->attached()->entity; if (!entity) return false; - auto layerAttached = static_cast(nodeAttached->layer3DS->attached()); + auto layerAttached = static_cast(object->isNode() ? object->attached()->layer3DS->attached() + : object->attached()->layer3DS->attached()); if (entity->components().contains(layerAttached->opaqueTag) || entity->components().contains(layerAttached->transparentTag)) return true; @@ -690,20 +691,23 @@ void Q3DSSlidePlayer::setSlideTime(Q3DSSlide *slide, float time, bool parentVisi const bool forceUpdate = parentVisible && (qFuzzyCompare(time, 0.0f) || qFuzzyCompare(time, -1.0f)); for (Q3DSGraphObject *obj : slide->objects()) { - if (!obj->isNode() || obj->type() == Q3DSGraphObject::Camera || obj->type() == Q3DSGraphObject::Layer) + const bool isEffect = (obj->type() == Q3DSGraphObject::Effect); + if ((!obj->isNode() && !isEffect) || obj->type() == Q3DSGraphObject::Camera || obj->type() == Q3DSGraphObject::Layer) continue; - Q3DSNode *node = static_cast(obj); - if (!node->attached()) + Q3DSNode *node = obj->isNode() ? static_cast(obj) : nullptr; + if (node && !node->attached()) continue; + const bool nodeActive = (node && node->flags().testFlag(Q3DSNode::Active) && node->attached()->globalVisibility); + const bool effectActive = isEffect && static_cast(obj)->active(); + const bool shouldBeVisible = parentVisible && time >= obj->startTime() && time <= obj->endTime() - && node->flags().testFlag(Q3DSNode::Active) - && static_cast(node->attached())->globalVisibility; + && (nodeActive || effectActive); - if (forceUpdate || shouldBeVisible != nodeHasVisibilityTag(node)) - updateNodeVisibility(node, shouldBeVisible); + if (forceUpdate || shouldBeVisible != objectHasVisibilityTag(obj)) + updateObjectVisibility(obj, shouldBeVisible); } // This method is called for all slides, but we only want to update the @@ -729,14 +733,21 @@ void Q3DSSlidePlayer::sendPositionChanged(Q3DSSlide *slide, float pos) onSlideFinished(slide); } -void Q3DSSlidePlayer::updateNodeVisibility(Q3DSNode *node, bool shouldBeVisible) +void Q3DSSlidePlayer::updateObjectVisibility(Q3DSGraphObject *obj, bool shouldBeVisible) { - if (shouldBeVisible) { - qCDebug(lcSlidePlayer, "Scheduling node \"%s\" to be shown", node->id().constData()); - m_sceneManager->m_pendingNodeShow.insert(node); + Q_ASSERT(obj->isNode() || obj->type() == Q3DSGraphObject::Effect); + if (obj->isNode()) { + if (shouldBeVisible) { + qCDebug(lcSlidePlayer, "Scheduling node \"%s\" to be shown", obj->id().constData()); + m_sceneManager->m_pendingNodeShow.insert(static_cast(obj)); + } else { + qCDebug(lcSlidePlayer, "Scheduling node \"%s\" to be hidden", obj->id().constData()); + m_sceneManager->m_pendingNodeHide.insert(static_cast(obj)); + } } else { - qCDebug(lcSlidePlayer, "Scheduling node \"%s\" to be hidden", node->id().constData()); - m_sceneManager->m_pendingNodeHide.insert(node); + qCDebug(lcSlidePlayer, "Scheduling effect \"%s\" to be %s", obj->id().constData(), shouldBeVisible ? "shown" : "hidden"); + obj->applyPropertyChanges(Q3DSPropertyChangeList({Q3DSPropertyChange::fromVariant(QLatin1String("eyeball"), QVariant::fromValue(shouldBeVisible))})); + obj->notifyPropertyChanges(Q3DSPropertyChangeList({Q3DSPropertyChange::fromVariant(QLatin1String("eyeball"), QVariant::fromValue(shouldBeVisible))})); } } @@ -795,16 +806,16 @@ void Q3DSSlidePlayer::processPropertyChanges(Q3DSSlide *currentSlide) Q3DSSlide *parent = static_cast(currentSlide->parent()); const auto &objects = parent->objects(); std::find_if(objects.constBegin(), objects.constEnd(), [](Q3DSGraphObject *object){ - if (!object->isNode()) + if (!object->isNode() && object->type() != Q3DSGraphObject::Effect) return false; - Q3DSNode *node = static_cast(object); - const Q3DSPropertyChangeList &masterRollbackList = node->masterRollbackList(); + const Q3DSPropertyChangeList &masterRollbackList = object->isNode() ? static_cast(object)->masterRollbackList() + : static_cast(object)->masterRollbackList(); if (masterRollbackList.isEmpty()) return false; - node->applyPropertyChanges(node->masterRollbackList()); - node->notifyPropertyChanges(node->masterRollbackList()); + object->applyPropertyChanges(masterRollbackList); + object->notifyPropertyChanges(masterRollbackList); return false; }); } diff --git a/src/runtime/q3dsslideplayer_p.h b/src/runtime/q3dsslideplayer_p.h index 2ffdc62..7441bb5 100644 --- a/src/runtime/q3dsslideplayer_p.h +++ b/src/runtime/q3dsslideplayer_p.h @@ -144,7 +144,7 @@ private: // TODO: Move out to a "slide manager"? void setSlideTime(Q3DSSlide *slide, float time, bool parentVisible = true); void sendPositionChanged(Q3DSSlide *slide, float pos); - void updateNodeVisibility(Q3DSNode *node, bool visible); + void updateObjectVisibility(Q3DSGraphObject *obj, bool visible); bool isSlideVisible(Q3DSSlide *slide); void processPropertyChanges(Q3DSSlide *currentSlide); diff --git a/src/runtime/q3dsuippresentation.cpp b/src/runtime/q3dsuippresentation.cpp index 3d2e4c7..75bef24 100644 --- a/src/runtime/q3dsuippresentation.cpp +++ b/src/runtime/q3dsuippresentation.cpp @@ -2323,6 +2323,13 @@ void Q3DSEffectInstance::setProperties(const QXmlStreamAttributes &attrs, PropSe // refer to custom properties defined in the effect. for (const QXmlStreamAttribute &attr : attrs) m_pendingCustomProperties.append(Q3DSPropertyChange(attr.name().toString(), attr.value().toString())); + + // If this is on the master slide, store some rollback info. + if (flags.testFlag(PropSetOnMaster)) { + m_masterRollbackList.append(Q3DSPropertyChange(QLatin1String("eyeball"), m_active ? QLatin1String("True") + : QLatin1String("False"))); + + } } void Q3DSEffectInstance::applyPropertyChanges(const Q3DSPropertyChangeList &changeList) diff --git a/src/runtime/q3dsuippresentation_p.h b/src/runtime/q3dsuippresentation_p.h index 899b516..6345db2 100644 --- a/src/runtime/q3dsuippresentation_p.h +++ b/src/runtime/q3dsuippresentation_p.h @@ -1842,6 +1842,8 @@ public: QVariant customProperty(const QString &name) const { return m_effectPropertyVals.value(name); } Q3DSPropertyChange setCustomProperty(const QString &name, const QVariant &value); + const Q3DSPropertyChangeList &masterRollbackList() const { return m_masterRollbackList; } + private: Q_DISABLE_COPY(Q3DSEffectInstance) template void setProps(const V &attrs, PropSetFlags flags); @@ -1852,6 +1854,7 @@ private: bool m_active = true; QVariantMap m_effectPropertyVals; Q3DSPropertyChangeList m_pendingCustomProperties; + Q3DSPropertyChangeList m_masterRollbackList; }; class Q3DSV_PRIVATE_EXPORT Q3DSBehaviorInstance : public Q3DSGraphObject -- cgit v1.2.3 From b81bba4795eea06d4dcbf39c99f986de2654077d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 23 May 2018 16:06:33 +0200 Subject: Compress the visibility updates of nodes Just keep the last update state for each object or else we end-up doing two calls for each object. Change-Id: I42d98e27513772972c38dbb4dbd36ddc0b84661b Reviewed-by: Laszlo Agocs --- src/runtime/q3dsscenemanager.cpp | 19 +++++-------------- src/runtime/q3dsscenemanager_p.h | 3 +-- src/runtime/q3dsslideplayer.cpp | 26 +++++++++++++++++--------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index 42e46b2..b39795d 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -611,8 +611,7 @@ Q3DSSceneManager::Scene Q3DSSceneManager::buildScene(Q3DSUipPresentation *presen m_scene = m_presentation->scene(); m_masterSlide = m_presentation->masterSlide(); m_currentSlide = nullptr; - m_pendingNodeShow.clear(); - m_pendingNodeHide.clear(); + m_pendingNodeVisibility.clear(); m_pendingSubPresLayers.clear(); m_pendingSubPresImages.clear(); m_subPresentations.clear(); @@ -6651,16 +6650,9 @@ void Q3DSSceneManager::updateSubTree(Q3DSGraphObject *obj) } } - if (!m_pendingNodeHide.isEmpty()) { - for (Q3DSNode *node : m_pendingNodeHide) - setNodeVisibility(node, false); - m_pendingNodeHide.clear(); - } - if (!m_pendingNodeShow.isEmpty()) { - for (Q3DSNode *node : m_pendingNodeShow) - setNodeVisibility(node, true); - m_pendingNodeShow.clear(); - } + for (auto it = m_pendingNodeVisibility.constBegin(); it != m_pendingNodeVisibility.constEnd(); ++it) + setNodeVisibility(it.key(), it.value()); + m_pendingNodeVisibility.clear(); } static Q3DSComponentNode *findNextComponentParent(Q3DSComponentNode *component) @@ -7041,8 +7033,7 @@ void Q3DSSceneManager::updateNodeFromChangeFlags(Q3DSNode *node, Qt3DCore::QTran // Drop whatever is queued since that was based on now-invalid // input. (important when entering slides, where eyball property // changes get processed after an initial visit of all objects) - m_pendingNodeShow.remove(node); - m_pendingNodeHide.remove(node); + m_pendingNodeVisibility.remove(node); const bool active = node->flags().testFlag(Q3DSNode::Active); setNodeVisibility(node, active); diff --git a/src/runtime/q3dsscenemanager_p.h b/src/runtime/q3dsscenemanager_p.h index 0ae0d2a..25f91c8 100644 --- a/src/runtime/q3dsscenemanager_p.h +++ b/src/runtime/q3dsscenemanager_p.h @@ -853,8 +853,7 @@ private: Q3DSTextRenderer *m_textRenderer; QSet m_subTreeWithDirtyLights; QSet m_pendingDefMatRebuild; - QSet m_pendingNodeShow; - QSet m_pendingNodeHide; + QHash m_pendingNodeVisibility; Qt3DRender::QLayer *m_fsQuadTag = nullptr; QStack m_componentNodeStack; QSet m_pendingSubPresLayers; diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index fd2a328..9c7b03e 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -737,17 +737,25 @@ void Q3DSSlidePlayer::updateObjectVisibility(Q3DSGraphObject *obj, bool shouldBe { Q_ASSERT(obj->isNode() || obj->type() == Q3DSGraphObject::Effect); if (obj->isNode()) { - if (shouldBeVisible) { - qCDebug(lcSlidePlayer, "Scheduling node \"%s\" to be shown", obj->id().constData()); - m_sceneManager->m_pendingNodeShow.insert(static_cast(obj)); - } else { - qCDebug(lcSlidePlayer, "Scheduling node \"%s\" to be hidden", obj->id().constData()); - m_sceneManager->m_pendingNodeHide.insert(static_cast(obj)); + Q3DSNode *node = static_cast(obj); + auto foundIt = m_sceneManager->m_pendingNodeVisibility.find(node); + const bool insertValue = (foundIt == m_sceneManager->m_pendingNodeVisibility.end()); + const bool updateValue = (!insertValue && foundIt.value() != shouldBeVisible); + + if (insertValue || updateValue) { + qCDebug(lcSlidePlayer, "Scheduling node \"%s\" to be %s", obj->id().constData(), shouldBeVisible ? "shown" : "hidden"); + if (updateValue) + *foundIt = shouldBeVisible; + else if (insertValue) + m_sceneManager->m_pendingNodeVisibility.insert(node, shouldBeVisible); } } else { - qCDebug(lcSlidePlayer, "Scheduling effect \"%s\" to be %s", obj->id().constData(), shouldBeVisible ? "shown" : "hidden"); - obj->applyPropertyChanges(Q3DSPropertyChangeList({Q3DSPropertyChange::fromVariant(QLatin1String("eyeball"), QVariant::fromValue(shouldBeVisible))})); - obj->notifyPropertyChanges(Q3DSPropertyChangeList({Q3DSPropertyChange::fromVariant(QLatin1String("eyeball"), QVariant::fromValue(shouldBeVisible))})); + Q3DSEffectInstance *effect = static_cast(obj); + if (effect->active() != shouldBeVisible) { + qCDebug(lcSlidePlayer, "Scheduling effect \"%s\" to be %s", obj->id().constData(), shouldBeVisible ? "shown" : "hidden"); + obj->applyPropertyChanges(Q3DSPropertyChangeList({Q3DSPropertyChange::fromVariant(QLatin1String("eyeball"), QVariant::fromValue(shouldBeVisible))})); + obj->notifyPropertyChanges(Q3DSPropertyChangeList({Q3DSPropertyChange::fromVariant(QLatin1String("eyeball"), QVariant::fromValue(shouldBeVisible))})); + } } } -- cgit v1.2.3