summaryrefslogtreecommitdiffstats
path: root/src/runtime/q3dsscenemanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/q3dsscenemanager.cpp')
-rw-r--r--src/runtime/q3dsscenemanager.cpp820
1 files changed, 514 insertions, 306 deletions
diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp
index 6c40962..77d4c61 100644
--- a/src/runtime/q3dsscenemanager.cpp
+++ b/src/runtime/q3dsscenemanager.cpp
@@ -47,6 +47,7 @@
#include "q3dslogging_p.h"
#include "q3dsviewportsettings_p.h"
#include "q3dstextmesh_p.h"
+#include "q3dsimagemanager_p.h"
#if QT_CONFIG(q3ds_profileui)
#include "profileui/q3dsprofileui_p.h"
#include "q3dsconsolecommands_p.h"
@@ -58,6 +59,7 @@
#include <qmath.h>
#include <QTextLayout>
#include <QOpenGLContext>
+#include <QTimer>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QTransform>
@@ -447,7 +449,7 @@ static const int LAYER_CACHING_THRESHOLD = 4;
*/
-Q3DSSceneManager::Q3DSSceneManager()
+Q3DSSceneManager::Q3DSSceneManager(ParentChildPairs *pairs)
: m_gfxLimits(Q3DS::graphicsLimits()),
m_matGen(new Q3DSDefaultMaterialGenerator),
m_customMaterialGen(new Q3DSCustomMaterialGenerator),
@@ -459,7 +461,8 @@ Q3DSSceneManager::Q3DSSceneManager()
m_glyphCacheManager(nullptr),
#endif
m_profiler(new Q3DSProfiler),
- m_inputManager(new Q3DSInputManager(this))
+ m_inputManager(new Q3DSInputManager(this)),
+ m_pairs(pairs)
{
if (Q3DSSlideUtils::useDragonWings())
m_slidePlayer = new Q3DSSlidePlayerNg(this);
@@ -648,7 +651,10 @@ void Q3DSSceneManager::uncacheLayers()
void Q3DSSceneManager::prepareAnimators()
{
- m_slidePlayer->sceneReady();
+ if (!m_animatorsInitialized) {
+ m_slidePlayer->sceneReady();
+ m_animatorsInitialized = true;
+ }
}
QDebug operator<<(QDebug dbg, const Q3DSSceneManager::SceneBuilderParams &p)
@@ -668,6 +674,8 @@ void Q3DSSceneManager::prepareEngineReset()
delete m_slidePlayer;
m_slidePlayer = nullptr;
+ m_animatorsInitialized = false;
+
#if QT_CONFIG(q3ds_profileui)
if (m_profileUi)
m_profileUi->releaseResources();
@@ -813,6 +821,10 @@ Q3DSSceneManager::Scene Q3DSSceneManager::buildScene(Q3DSUipPresentation *presen
Qt3DLogic::QFrameAction *nodeUpdater = new Qt3DLogic::QFrameAction;
m_frameUpdater = new Q3DSFrameUpdater(this);
QObject::connect(nodeUpdater, &Qt3DLogic::QFrameAction::triggered, m_frameUpdater, &Q3DSFrameUpdater::frameAction);
+ if (m_pairs) {
+ m_pairs->addPair(m_rootEntity, nodeUpdater);
+ m_pairs->addPair(m_rootEntity, m_frameUpdater);
+ }
m_rootEntity->addComponent(nodeUpdater);
Qt3DRender::QRenderSettings *frameGraphComponent;
@@ -854,14 +866,19 @@ Q3DSSceneManager::Scene Q3DSSceneManager::buildScene(Q3DSUipPresentation *presen
// Do some pre-processing and early setup for some objects.
initSubTree(m_scene);
+ m_engine->loadSlideResources(m_masterSlide, m_presentation);
+ m_engine->loadSlideResources(m_currentSlide, m_presentation);
+
// Build the (offscreen) Qt3D scene
m_layerContainerFg = new Qt3DRender::QFrameGraphNode(frameGraphRoot);
new Qt3DRender::QNoDraw(m_layerContainerFg); // in case there are no layers at all
+
Q3DSUipPresentation::forAllLayers(m_scene, [=](Q3DSLayerNode *layer3DS) {
if (layer3DS->sourcePath().isEmpty())
buildLayer(layer3DS, m_layerContainerFg, m_outputPixelSize);
else
buildSubPresentationLayer(layer3DS, m_outputPixelSize);
+
});
// The Scene object may have non-layer children.
@@ -874,7 +891,6 @@ Q3DSSceneManager::Scene Q3DSSceneManager::buildScene(Q3DSUipPresentation *presen
// Onscreen (or not) compositor (still offscreen when this is a subpresentation)
buildCompositor(frameGraphRoot, m_rootEntity);
-
// Profiling UI (main presentation only)
#if QT_CONFIG(q3ds_profileui)
if (!m_flags.testFlag(SubPresentation)) {
@@ -981,16 +997,17 @@ void Q3DSSceneManager::finalizeMainScene()
#endif
}
-void Q3DSSceneManager::loadSubUipPresentation(Q3DSSubPresentation *sp)
+void Q3DSSceneManager::finalizeSubpresentationLoading(Q3DSSubPresentation *sp)
{
- const QString id = sp->id;
- Q_ASSERT(!id.isEmpty());
- *sp = m_engine->loadSubUipPresentation(sp->id);
- sp->id = id;
if (sp->colorTex && sp->sceneManager) {
+ for (int i = 0; i < m_subPresentations.size(); ++i) {
+ if (m_subPresentations[i].id == sp->id) {
+ m_subPresentations[i] = *sp;
+ break;
+ }
+ }
sp->sceneManager->setSubPresentations(m_subPresentations);
if (!m_inSetSubPresentations) {
- sp->sceneManager->prepareAnimators();
m_profiler->registerSubPresentationProfiler(sp->sceneManager->m_profiler);
Q3DSUipPresentation::forAllObjectsOfType(sp->sceneManager->m_presentation->scene(),
Q3DSGraphObject::Behavior,
@@ -1004,6 +1021,12 @@ void Q3DSSceneManager::loadSubUipPresentation(Q3DSSubPresentation *sp)
}
}
+static bool isAsyncSubpresentationLoadingEnabled()
+{
+ static bool enabled = (qEnvironmentVariableIntValue("Q3DS_ASYNC_LOADING") & 8) > 0;
+ return enabled;
+}
+
void Q3DSSceneManager::updateSubPresentationHosts()
{
for (Q3DSLayerNode *layer3DS : m_pendingSubPresLayers) {
@@ -1012,25 +1035,39 @@ void Q3DSSceneManager::updateSubPresentationHosts()
auto it = std::find_if(m_subPresentations.begin(), m_subPresentations.end(),
[subPresId](const Q3DSSubPresentation &sp) { return sp.id == subPresId; });
if (it != m_subPresentations.end()) {
- if (!it->colorTex)
- loadSubUipPresentation(it);
- if (it->colorTex) {
- qCDebug(lcScene, "Directing subpresentation %s to layer %s", qPrintable(it->id), layer3DS->id().constData());
- Q3DSLayerAttached *layerData = static_cast<Q3DSLayerAttached *>(layer3DS->attached());
- layerData->eyeMono->layerTexture = it->colorTex;
+
+ auto setSubpresentationTolayer = [this](Q3DSLayerNode *layer, Q3DSSubPresentation *sp){
+ qCDebug(lcScene, "Directing subpresentation %s to layer %s", qPrintable(sp->id), layer->id().constData());
+ Q3DSLayerAttached *layerData = static_cast<Q3DSLayerAttached *>(layer->attached());
+ layerData->eyeMono->layerTexture = sp->colorTex;
layerData->eyeMono->compositorSourceParam->setValue(QVariant::fromValue(layerData->eyeMono->layerTexture));
- layerData->eyeLeft->layerTexture = it->colorTex;
- layerData->eyeRight->layerTexture = it->colorTex;
+ layerData->eyeLeft->layerTexture = sp->colorTex;
+ layerData->eyeRight->layerTexture = sp->colorTex;
layerData->eyeLeft->compositorSourceParam->setValue(QVariant::fromValue(layerData->eyeLeft->layerTexture));
layerData->eyeRight->compositorSourceParam->setValue(QVariant::fromValue(layerData->eyeRight->layerTexture));
layerData->updateSubPresentationSize();
+ };
+
+ if (!it->colorTex) {
+ if (isAsyncSubpresentationLoadingEnabled()) {
+ m_engine->loadSubUipPresentation(subPresId, [this, setSubpresentationTolayer](
+ Q3DSSubPresentation *sp, Q3DSLayerNode *layer) {
+ finalizeSubpresentationLoading(sp);
+ setSubpresentationTolayer(layer, sp);
+ }, layer3DS);
+ } else {
+ *it = m_engine->loadSubUipPresentation(subPresId);
+ finalizeSubpresentationLoading(it);
+ setSubpresentationTolayer(layer3DS, it);
+ }
+ } else {
+ setSubpresentationTolayer(layer3DS, it);
}
} else {
qCDebug(lcScene, "Subpresentation %s for layer %s not found",
qPrintable(subPresId), layer3DS->id().constData());
}
}
-
for (auto p : m_pendingSubPresImages)
setImageTextureFromSubPresentation(p.first, p.second);
@@ -1563,7 +1600,9 @@ void Q3DSSceneManager::buildLayer(Q3DSLayerNode *layer3DS,
// Generate Qt3D material components.
Q3DSUipPresentation::forAllModels(layer3DS->firstChild(),
- [this](Q3DSModelNode *model3DS) { buildModelMaterial(model3DS); },
+ [this](Q3DSModelNode *model3DS) {
+ buildModelMaterial(model3DS);
+ },
true); // include hidden ones too
// Set up effects.
@@ -2152,7 +2191,7 @@ void Q3DSSceneManager::setLayerProperties(Q3DSLayerNode *layer3DS)
if (layer3DS->lightProbe()) {
// initialize light probe parameters if necessary
if (!data->iblProbeData.lightProbeTexture) {
- data->iblProbeData.lightProbeTexture = Q3DSImageManager::instance().newTextureForImage(
+ data->iblProbeData.lightProbeTexture = Q3DSImageManager::instance().newReloadableTextureForImage(
m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL,
layer3DS->lightProbe()->id(),
m_profiler, "iblProbe texture for image %s", layer3DS->lightProbe()->id().constData());
@@ -2175,59 +2214,75 @@ void Q3DSSceneManager::setLayerProperties(Q3DSLayerNode *layer3DS)
// Update light probe parameter values
// also sets min/mag and generates mipmaps
- Q3DSImageManager::instance().setSource(data->iblProbeData.lightProbeTexture,
- QUrl::fromLocalFile(layer3DS->lightProbe()->sourcePath()),
- m_presentation->preferKtx());
- data->iblProbeData.lightProbeSampler->setValue(QVariant::fromValue(data->iblProbeData.lightProbeTexture));
+ data->iblProbeData.lightProbeTexture->setSource(m_presentation->imageUrl(
+ layer3DS->lightProbe()->sourcePath()));
+ data->iblProbeData.lightProbeTexture->onLoad([](Qt3DRender::QAbstractTexture *texture,
+ Q3DSLayerNode *layer3DS) {
+ Q3DSLayerAttached *data = static_cast<Q3DSLayerAttached *>(layer3DS->attached());
+ data->iblProbeData.lightProbeSampler->setValue(QVariant::fromValue(texture));
- Qt3DRender::QTextureWrapMode wrapMode;
+ Qt3DRender::QTextureWrapMode wrapMode;
- switch (layer3DS->lightProbe()->horizontalTiling()) {
- case Q3DSImage::Tiled:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
- break;
- case Q3DSImage::Mirrored:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::MirroredRepeat);
- break;
- default:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
- break;
- }
+ switch (layer3DS->lightProbe()->horizontalTiling()) {
+ case Q3DSImage::Tiled:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ case Q3DSImage::Mirrored:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::MirroredRepeat);
+ break;
+ default:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
- switch (layer3DS->lightProbe()->verticalTiling()) {
- case Q3DSImage::Tiled:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
- break;
- case Q3DSImage::Mirrored:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::MirroredRepeat);
- break;
- default:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
- break;
- }
+ switch (layer3DS->lightProbe()->verticalTiling()) {
+ case Q3DSImage::Tiled:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ case Q3DSImage::Mirrored:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::MirroredRepeat);
+ break;
+ default:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
- Qt3DRender::QAbstractTexture *texture = data->iblProbeData.lightProbeTexture;
- texture->setWrapMode(wrapMode);
+ texture->setWrapMode(wrapMode);
- const QMatrix4x4 &textureTransform = layer3DS->lightProbe()->textureTransform();
- const float *m = textureTransform.constData();
+ const QMatrix4x4 &textureTransform = layer3DS->lightProbe()->textureTransform();
+ const float *m = textureTransform.constData();
- // offsets.w = max mip level
- const QSize texSize = Q3DSImageManager::instance().size(texture);
- float mipLevels = float(qCeil(qLog2(qMax(texSize.width(), texSize.height()))));
- QVector4D offsets(m[12], m[13], 0.0f, mipLevels);
- data->iblProbeData.lightProbeOffset->setValue(offsets);
+ const QSize texSize = Q3DSImageManager::instance().size(texture);
+ float mipLevels = float(qCeil(qLog2(qMax(texSize.width(), texSize.height()))));
+ QVector4D offsets(m[12], m[13], 0.0f, mipLevels);
+ data->iblProbeData.lightProbeOffset->setValue(offsets);
+
+ QVector4D rotations(m[0], m[4], m[1], m[5]);
+ data->iblProbeData.lightProbeRotation->setValue(rotations);
+ }, layer3DS);
+
+ data->iblProbeData.lightProbeTexture->onUnload([](Qt3DRender::QAbstractTexture *texture,
+ Q3DSLayerNode *layer3DS) {
+ Q_UNUSED(texture);
+ Q3DSLayerAttached *data = static_cast<Q3DSLayerAttached *>(layer3DS->attached());
+ data->iblProbeData.lightProbeSampler->setValue({});
+ QVector4D offsets(0.f, 0.f, 0.f, 0.f);
+ data->iblProbeData.lightProbeOffset->setValue(offsets);
+
+ QVector4D rotations(0.f, 0.f, 0.f, 0.f);
+ data->iblProbeData.lightProbeRotation->setValue(rotations);
+ }, layer3DS);
- QVector4D rotations(m[0], m[4], m[1], m[5]);
- data->iblProbeData.lightProbeRotation->setValue(rotations);
if (layer3DS->lightProbe2()) {
// Initialize light probe 2 parameters
if (!data->iblProbeData.lightProbe2Texture) {
- data->iblProbeData.lightProbe2Texture = Q3DSImageManager::instance().newTextureForImage(
+ data->iblProbeData.lightProbe2Texture
+ = Q3DSImageManager::instance().newReloadableTextureForImage(
m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL,
layer3DS->lightProbe2()->id(),
- m_profiler, "iblProbe2 texture for image %s", layer3DS->lightProbe2()->id().constData());
+ m_profiler, "iblProbe2 texture for image %s",
+ layer3DS->lightProbe2()->id().constData());
}
if (!data->iblProbeData.lightProbe2Sampler) {
@@ -2238,22 +2293,63 @@ void Q3DSSceneManager::setLayerProperties(Q3DSLayerNode *layer3DS)
// Update light probe 2 parameter values
// also sets min/mag and generates mipmaps
- Q3DSImageManager::instance().setSource(data->iblProbeData.lightProbe2Texture,
- QUrl::fromLocalFile(layer3DS->lightProbe2()->sourcePath()),
- m_presentation->preferKtx());
- data->iblProbeData.lightProbe2Sampler->setValue(QVariant::fromValue(data->iblProbeData.lightProbe2Texture));
+ data->iblProbeData.lightProbe2Texture->setSource(
+ m_presentation->imageUrl(layer3DS->lightProbe2()->sourcePath()));
+ data->iblProbeData.lightProbe2Texture->onLoad([](Qt3DRender::QAbstractTexture *texture,
+ Q3DSLayerNode *layer3DS) {
+ Q3DSLayerAttached *data = static_cast<Q3DSLayerAttached *>(layer3DS->attached());
+ data->iblProbeData.lightProbe2Sampler->setValue(QVariant::fromValue(texture));
+
+ Qt3DRender::QTextureWrapMode wrapMode;
+
+ switch (layer3DS->lightProbe()->horizontalTiling()) {
+ case Q3DSImage::Tiled:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ case Q3DSImage::Mirrored:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::MirroredRepeat);
+ break;
+ default:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
- data->iblProbeData.lightProbe2Texture->setWrapMode(wrapMode);
+ switch (layer3DS->lightProbe()->verticalTiling()) {
+ case Q3DSImage::Tiled:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ case Q3DSImage::Mirrored:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::MirroredRepeat);
+ break;
+ default:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
- QVector4D probe2Props(layer3DS->probe2Window(), layer3DS->probe2Pos(), layer3DS->probe2Fade(), 1.0f);
- data->iblProbeData.lightProbe2Properties->setValue(probe2Props);
- const QMatrix4x4 &textureTransform = layer3DS->lightProbe2()->textureTransform();
- const float *m = textureTransform.constData();
- QVector4D probeProps(m[12], m[13], layer3DS->probeHorizon(), layer3DS->probeBright() * 0.01f);
- data->iblProbeData.lightProbeProperties->setValue(probeProps);
+ texture->setWrapMode(wrapMode);
+
+ QVector4D probe2Props(layer3DS->probe2Window(), layer3DS->probe2Pos(),
+ layer3DS->probe2Fade(), 1.0f);
+ data->iblProbeData.lightProbe2Properties->setValue(probe2Props);
+ const QMatrix4x4 &textureTransform = layer3DS->lightProbe2()->textureTransform();
+ const float *m = textureTransform.constData();
+ QVector4D probeProps(m[12], m[13], layer3DS->probeHorizon(),
+ layer3DS->probeBright() * 0.01f);
+ data->iblProbeData.lightProbeProperties->setValue(probeProps);
+ }, layer3DS);
+ data->iblProbeData.lightProbe2Texture->onUnload(
+ [](Qt3DRender::QAbstractTexture *texture, Q3DSLayerNode *layer3DS) {
+ Q_UNUSED(texture);
+ Q3DSLayerAttached *data = static_cast<Q3DSLayerAttached *>(layer3DS->attached());
+ data->iblProbeData.lightProbe2Sampler->setValue({});
+ data->iblProbeData.lightProbe2Properties->setValue({});
+ data->iblProbeData.lightProbeProperties->setValue({});
+ }, layer3DS);
} else {
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));
+ data->iblProbeData.lightProbeProperties->setValue(
+ QVector4D(0.0f, 0.0f, layer3DS->probeHorizon(),
+ layer3DS->probeBright() * 0.01f));
}
}
}
@@ -4814,7 +4910,8 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN
data->entity->setObjectName(QObject::tr("top level text %1").arg(QString::fromUtf8(text3DS->id())));
#if QT_VERSION >= QT_VERSION_CHECK(5,12,2)
- if (shouldDistanceFieldRender) {
+ bool useDistanceFields = shouldDistanceFieldRender && text3DS->wordWrap() != Q3DSTextNode::Clip;
+ if (useDistanceFields) {
data->distanceFieldText = true;
data->dropShadow = text3DS->shadow();
QVector2D boundingBox = text3DS->boundingBox();
@@ -5049,8 +5146,10 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN
cache->processPendingGlyphs();
qreal fontPixelSize = glyphRun.rawFont().pixelSize();
- float shadowOffsetX = float(fontPixelSize) * text3DS->shadowOffsetX() / 1000.0f;
- float shadowOffsetY = float(fontPixelSize) * text3DS->shadowOffsetY() / 1000.0f;
+
+ float shadowOffsetX = float(cache->fontSize()) * text3DS->shadowOffsetX() / 1000.0f;
+ float shadowOffsetY = float(cache->fontSize()) * text3DS->shadowOffsetY() / 1000.0f;
+
qreal maxTexMargin = cache->distanceFieldRadius();
qreal fontScale = cache->fontScale(fontPixelSize);
qreal margin = 2;
@@ -5087,8 +5186,15 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN
float cy2 = cy1 + float(metrics.height);
if (text3DS->shadow()) {
- cx2 += shadowOffsetX;
- cy2 += shadowOffsetY;
+ if (shadowOffsetX < 0.0)
+ cx1 += shadowOffsetX * fontScale;
+ else
+ cx2 += shadowOffsetX * fontScale;
+
+ if (shadowOffsetY < 0.0)
+ cy1 += shadowOffsetY * fontScale;
+ else
+ cy2 += shadowOffsetY * fontScale;
}
float tx1 = float(c.x + c.xMargin);
@@ -5096,12 +5202,22 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN
float ty1 = float(c.y + c.yMargin);
float ty2 = ty1 + float(c.height);
+ // Preserve original bounds of glyphs
+ float ttx1 = tx1;
+ float tty1 = ty1;
float ttx2 = tx2;
float tty2 = ty2;
if (text3DS->shadow()) {
- tx2 += float(c.width) * shadowOffsetX / float(metrics.width);
- ty2 += float(c.height) * shadowOffsetY / float(metrics.height);
+ if (shadowOffsetX < 0.0)
+ tx1 += float(c.width) * shadowOffsetX * fontScale / float(metrics.width);
+ else
+ tx2 += float(c.width) * shadowOffsetX * fontScale / float(metrics.width);
+
+ if (shadowOffsetY < 0.0)
+ ty1 += float(c.height) * shadowOffsetY * fontScale / float(metrics.height);
+ else
+ ty2 += float(c.height) * shadowOffsetY * fontScale / float(metrics.height);
}
const QSGDistanceFieldGlyphCache::Texture *texture = cache->glyphTexture(glyphIndex);
@@ -5127,8 +5243,8 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN
vertexes.append(ty1);
if (text3DS->shadow()) {
- vertexes.append(tx1);
- vertexes.append(ty1);
+ vertexes.append(ttx1);
+ vertexes.append(tty1);
vertexes.append(ttx2);
vertexes.append(tty2);
}
@@ -5140,8 +5256,8 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN
vertexes.append(ty1);
if (text3DS->shadow()) {
- vertexes.append(tx1);
- vertexes.append(ty1);
+ vertexes.append(ttx1);
+ vertexes.append(tty1);
vertexes.append(ttx2);
vertexes.append(tty2);
}
@@ -5153,8 +5269,8 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN
vertexes.append(ty2);
if (text3DS->shadow()) {
- vertexes.append(tx1);
- vertexes.append(ty1);
+ vertexes.append(ttx1);
+ vertexes.append(tty1);
vertexes.append(ttx2);
vertexes.append(tty2);
}
@@ -5166,8 +5282,8 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildText(Q3DSTextNode *text3DS, Q3DSLayerN
vertexes.append(ty2);
if (text3DS->shadow()) {
- vertexes.append(tx1);
- vertexes.append(ty1);
+ vertexes.append(ttx1);
+ vertexes.append(tty1);
vertexes.append(ttx2);
vertexes.append(tty2);
}
@@ -5380,7 +5496,6 @@ void Q3DSSceneManager::updateText(Q3DSTextNode *text3DS, bool needsNewImage)
Qt3DCore::QEntity *parentEntity = data->entity->parentEntity();
buildText(text3DS, data->layer3DS, parentEntity);
- setNodeVisibility(text3DS, text3DS->flags().testFlag(Q3DSNode::Active));
}
} else
#endif
@@ -5434,6 +5549,10 @@ void Q3DSSceneManager::updateText(Q3DSTextNode *text3DS, bool needsNewImage)
if (textOffsetX != 0 || textOffsetY != 0) {
QVector3D pos = text3DS->position();
+ QVector3D rot = text3DS->rotation();
+ // Apply text rotation to the translation amount
+ textOffsetX *= qCos(qDegreesToRadians(rot.y()));
+ textOffsetY *= qCos(qDegreesToRadians(rot.x()));
data->transform->setTranslation(QVector3D(pos.x() + textOffsetX,
pos.y() + textOffsetY,
pos.z()));
@@ -5757,7 +5876,6 @@ static void addShadowSsaoParams(Q3DSLayerAttached *layerData, QVector<Qt3DRender
void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
{
// Scene building phase 2: all lights are known -> generate actual Qt3D materials
-
Q3DSModelAttached *modelData = static_cast<Q3DSModelAttached *>(model3DS->attached());
if (!modelData)
return;
@@ -5785,7 +5903,6 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
// matters so much.
lightNodes.resize(m_gfxLimits.maxLightsPerLayer);
}
-
for (Q3DSModelAttached::SubMesh &sm : modelData->subMeshes) {
if (sm.resolvedMaterial && !sm.materialComponent && sm.resolvedMaterial->type() != Q3DSGraphObject::ReferencedMaterial) {
Q_ASSERT(sm.resolvedMaterial->attached());
@@ -5867,7 +5984,7 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
param->setParent(layerData->entity);
}
- sm.materialComponent = m_matGen->generateMaterial(defaultMaterial, sm.referencingMaterial, params, lightNodes, modelData->layer3DS);
+ sm.materialComponent = m_matGen->generateMaterial(m_pairs, defaultMaterial, sm.referencingMaterial, params, lightNodes, modelData->layer3DS);
sm.entity->addComponent(sm.materialComponent);
} else if (sm.resolvedMaterial->type() == Q3DSGraphObject::CustomMaterial) {
Q3DSCustomMaterialInstance *customMaterial = static_cast<Q3DSCustomMaterialInstance *>(sm.resolvedMaterial);
@@ -5948,7 +6065,8 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
if (!passes.isEmpty()) {
// ### TODO support more than one pass
auto pass = passes.first();
- sm.materialComponent = m_customMaterialGen->generateMaterial(customMaterial, sm.referencingMaterial, params, lightNodes, modelData->layer3DS, pass);
+ bool gles = m_gfxLimits.format.renderableType() == QSurfaceFormat::OpenGLES;
+ sm.materialComponent = m_customMaterialGen->generateMaterial(m_pairs, customMaterial, sm.referencingMaterial, params, lightNodes, modelData->layer3DS, pass, gles);
} else {
qCDebug(lcScene, "Custom material %s has no passes. Using dummy material. Object %s will not show.",
customMaterial->id().constData(), model3DS->id().constData());
@@ -5972,6 +6090,7 @@ void Q3DSSceneManager::rebuildModelMaterial(Q3DSModelNode *model3DS)
for (Q3DSModelAttached::SubMesh &sm : modelData->subMeshes) {
if (sm.resolvedMaterial && sm.materialComponent) {
qCDebug(lcPerf, "Rebuilding material for %s (entity %p)", model3DS->id().constData(), sm.entity);
+
delete sm.materialComponent;
sm.materialComponent = nullptr;
}
@@ -6062,15 +6181,58 @@ void Q3DSSceneManager::prepareTextureParameters(Q3DSTextureParameters &texturePa
textureParameters.size = new Qt3DRender::QParameter;
textureParameters.size->setName(name + QLatin1String("_size"));
-
- textureParameters.texture = Q3DSImageManager::instance().newTextureForImage(
- m_rootEntity, 0, image3DS->id(), m_profiler, "Texture for image %s", image3DS->id().constData());
}
void Q3DSSceneManager::updateTextureParameters(Q3DSTextureParameters &textureParameters, Q3DSImage *image)
{
// note that this function is called frequently (whenever any Image parameter changes)
+ auto setupTexture = [](Q3DSTextureParameters &textureParameters, Q3DSImage *image) {
+ Qt3DRender::QTextureWrapMode wrapMode;
+ switch (image->horizontalTiling()) {
+ case Q3DSImage::Tiled:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ case Q3DSImage::Mirrored:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::MirroredRepeat);
+ break;
+ default:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
+ switch (image->verticalTiling()) {
+ case Q3DSImage::Tiled:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ case Q3DSImage::Mirrored:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::MirroredRepeat);
+ break;
+ default:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
+
+ Qt3DRender::QAbstractTexture *texture
+ = textureParameters.sampler->value().value<Qt3DRender::QAbstractTexture *>();
+ Q_ASSERT(texture || !image->subPresentation().isEmpty());
+ if (!texture)
+ return;
+
+ texture->setWrapMode(wrapMode);
+ // min/mag are already set at this point
+
+ const QMatrix4x4 &textureTransform = image->textureTransform();
+ const float *m = textureTransform.constData();
+
+ QVector3D offsets(m[12], m[13], image->hasPremultipliedAlpha() ? 1 : 0);
+ textureParameters.offsets->setValue(offsets);
+
+ QVector4D rotations(m[0], m[4], m[1], m[5]);
+ textureParameters.rotations->setValue(rotations);
+ const QSize size = Q3DSImageManager::instance().size(texture);
+ textureParameters.size->setValue(QVector2D(size.width(), size.height()));
+ };
+
if (!image->subPresentation().isEmpty()) {
if (textureParameters.subPresId != image->subPresentation()) {
textureParameters.subPresId = image->subPresentation();
@@ -6082,60 +6244,40 @@ void Q3DSSceneManager::updateTextureParameters(Q3DSTextureParameters &texturePar
setImageTextureFromSubPresentation(textureParameters.sampler, image);
}
}
+ setupTexture(textureParameters, image);
} else if (!image->sourcePath().isEmpty()) {
- Q3DSImageManager::instance().setSource(textureParameters.texture, QUrl::fromLocalFile(image->sourcePath()),
- m_presentation->preferKtx());
- textureParameters.sampler->setValue(QVariant::fromValue(textureParameters.texture));
+ if (!textureParameters.textureSource) {
+ textureParameters.textureSource
+ = Q3DSImageManager::instance().newReloadableTextureForImage(
+ m_rootEntity, 0, image->id(), m_profiler, "Texture for image %s",
+ image->id().constData());
+ }
+ textureParameters.textureSource->setSource(m_presentation->imageUrl(image->sourcePath()));
+ textureParameters.textureSource->onLoad(
+ [setupTexture](Qt3DRender::QAbstractTexture *texture,
+ Q3DSTextureParameters *param, Q3DSImage *image) {
+ param->sampler->setValue(QVariant::fromValue(texture));
+ setupTexture(*param, image);
+ }, &textureParameters, image);
+ textureParameters.textureSource->onUnload([](Qt3DRender::QAbstractTexture *texture,
+ Q3DSTextureParameters *param) {
+ Q_UNUSED(texture);
+ param->sampler->setValue({});
+ param->offsets->setValue({});
+ param->rotations->setValue({});
+ param->size->setValue({});
+ }, &textureParameters);
} else if (!image->customImage().isNull()) {
+ textureParameters.texture
+ = Q3DSImageManager::instance().newTextureForImage(m_rootEntity, 0, image->id(),
+ m_profiler, QStringLiteral("Texture for image %1").arg(image->id().constData()));
Q3DSImageManager::instance().setSource(textureParameters.texture, image->customImage());
textureParameters.sampler->setValue(QVariant::fromValue(textureParameters.texture));
+ setupTexture(textureParameters, image);
} else {
textureParameters.sampler->setValue(QVariant::fromValue(dummyTexture(image->id())));
+ setupTexture(textureParameters, image);
}
-
- Qt3DRender::QTextureWrapMode wrapMode;
- switch (image->horizontalTiling()) {
- case Q3DSImage::Tiled:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
- break;
- case Q3DSImage::Mirrored:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::MirroredRepeat);
- break;
- default:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
- break;
- }
- switch (image->verticalTiling()) {
- case Q3DSImage::Tiled:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
- break;
- case Q3DSImage::Mirrored:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::MirroredRepeat);
- break;
- default:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
- break;
- }
-
- Qt3DRender::QAbstractTexture *texture = textureParameters.sampler->value().value<Qt3DRender::QAbstractTexture *>();
- Q_ASSERT(texture || !image->subPresentation().isEmpty());
- if (!texture)
- return;
-
- texture->setWrapMode(wrapMode);
- // min/mag are already set at this point
-
- const QMatrix4x4 &textureTransform = image->textureTransform();
- const float *m = textureTransform.constData();
-
- QVector3D offsets(m[12], m[13], image->hasPremultipliedAlpha() ? 1 : 0);
- textureParameters.offsets->setValue(offsets);
-
- QVector4D rotations(m[0], m[4], m[1], m[5]);
- textureParameters.rotations->setValue(rotations);
-
- const QSize size = Q3DSImageManager::instance().size(texture);
- textureParameters.size->setValue(QVector2D(size.width(), size.height()));
}
void Q3DSSceneManager::setImageTextureFromSubPresentation(Qt3DRender::QParameter *sampler, Q3DSImage *image)
@@ -6143,17 +6285,36 @@ void Q3DSSceneManager::setImageTextureFromSubPresentation(Qt3DRender::QParameter
auto it = std::find_if(m_subPresentations.begin(), m_subPresentations.end(),
[image](const Q3DSSubPresentation &sp) { return sp.id == image->subPresentation(); });
if (it != m_subPresentations.cend()) {
- if (!it->colorTex)
- loadSubUipPresentation(it);
- qCDebug(lcScene, "Directing subpresentation %s to image %s",
- qPrintable(image->subPresentation()), image->id().constData());
- sampler->setValue(QVariant::fromValue(it->colorTex));
- qCDebug(lcPerf, "Using a subpresentation as texture map (not as layer) makes layer caching in main presentation less efficient");
- // QML subpresentations will not have a scenemanager
- if (it->sceneManager)
- m_layerCacheDeps.insert(it->sceneManager);
- else
- m_hasQmlSubPresAsTextureMap = true;
+ auto handleSubpresentation = [this](
+ Q3DSSubPresentation *sp, Qt3DRender::QParameter *sampler, Q3DSImage *image) {
+ qCDebug(lcScene, "Directing subpresentation %s to image %s",
+ qPrintable(image->subPresentation()), image->id().constData());
+ sampler->setValue(QVariant::fromValue(sp->colorTex));
+ qCDebug(lcPerf, "Using a subpresentation as texture map (not as layer) makes layer caching in main presentation less efficient");
+ // QML subpresentations will not have a scenemanager
+ if (sp->sceneManager)
+ m_layerCacheDeps.insert(sp->sceneManager);
+ else
+ m_hasQmlSubPresAsTextureMap = true;
+ };
+ if (!it->colorTex) {
+ if (isAsyncSubpresentationLoadingEnabled()) {
+ m_engine->loadSubUipPresentation(image->subPresentation(),
+ [this, handleSubpresentation]
+ (Q3DSSubPresentation *sp,
+ Qt3DRender::QParameter *sampler,
+ Q3DSImage *image) {
+ finalizeSubpresentationLoading(sp);
+ handleSubpresentation(sp, sampler, image);
+ }, sampler, image);
+ } else {
+ *it = m_engine->loadSubUipPresentation(image->subPresentation());
+ finalizeSubpresentationLoading(it);
+ handleSubpresentation(it, sampler, image);
+ }
+ } else {
+ handleSubpresentation(it, sampler, image);
+ }
} else {
qCDebug(lcScene, "Subpresentation %s for image %s not found",
qPrintable(image->subPresentation()), image->id().constData());
@@ -6389,10 +6550,11 @@ QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareDefaultMaterial(Q3DSD
iblOverrideImage = m->lightProbe();
if (iblOverrideImage) {
if (!data->lightProbeOverrideTexture) {
- data->lightProbeOverrideTexture = Q3DSImageManager::instance().newTextureForImage(
+ data->lightProbeOverrideTexture
+ = Q3DSImageManager::instance().newReloadableTextureForImage(
m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL,
- iblOverrideImage->id(),
- m_profiler, "Texture for image %s", iblOverrideImage->id().constData());
+ iblOverrideImage->id(), m_profiler,
+ "Texture for image %s", iblOverrideImage->id().constData());
data->lightProbeSampler = new Qt3DRender::QParameter;
data->lightProbeSampler->setName(QLatin1String("light_probe"));
@@ -6534,6 +6696,48 @@ void Q3DSSceneManager::updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferen
// IBL
if (iblOverride) {
+ auto setupTexture = [](Qt3DRender::QAbstractTexture *texture,
+ Q3DSDefaultMaterialAttached *data, Q3DSImage *iblOverride) {
+ Qt3DRender::QTextureWrapMode wrapMode;
+
+ switch (iblOverride->horizontalTiling()) {
+ case Q3DSImage::Tiled:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ case Q3DSImage::Mirrored:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::MirroredRepeat);
+ break;
+ default:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
+
+ switch (iblOverride->verticalTiling()) {
+ case Q3DSImage::Tiled:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ case Q3DSImage::Mirrored:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::MirroredRepeat);
+ break;
+ default:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
+
+ texture->setWrapMode(wrapMode);
+
+ const QMatrix4x4 &textureTransform = iblOverride->textureTransform();
+ const float *m = textureTransform.constData();
+
+ // offsets.w = max mip level
+ const QSize texSize = Q3DSImageManager::instance().size(texture);
+ float mipLevels = float(qCeil(qLog2(qMax(texSize.width(), texSize.height()))));
+ QVector4D offsets(m[12], m[13], 0.0f, mipLevels);
+ data->lightProbeOffset->setValue(offsets);
+
+ QVector4D rotations(m[0], m[4], m[1], m[5]);
+ data->lightProbeRotation->setValue(rotations);
+ };
// also sets min/mag and generates mipmaps
if (!iblOverride->subPresentation().isEmpty()) {
if (m_subPresentations.isEmpty())
@@ -6541,52 +6745,23 @@ void Q3DSSceneManager::updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferen
else
setImageTextureFromSubPresentation(data->lightProbeSampler, iblOverride);
} else {
- Q3DSImageManager::instance().setSource(data->lightProbeOverrideTexture,
- QUrl::fromLocalFile(iblOverride->sourcePath()),
- m_presentation->preferKtx());
- data->lightProbeSampler->setValue(QVariant::fromValue(data->lightProbeOverrideTexture));
- }
-
- Qt3DRender::QTextureWrapMode wrapMode;
-
- switch (iblOverride->horizontalTiling()) {
- case Q3DSImage::Tiled:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
- break;
- case Q3DSImage::Mirrored:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::MirroredRepeat);
- break;
- default:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
- break;
- }
-
- switch (iblOverride->verticalTiling()) {
- case Q3DSImage::Tiled:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
- break;
- case Q3DSImage::Mirrored:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::MirroredRepeat);
- break;
- default:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
- break;
+ data->lightProbeOverrideTexture->setSource(
+ m_presentation->imageUrl(iblOverride->sourcePath()));
+ data->lightProbeOverrideTexture->onLoad([setupTexture](
+ Qt3DRender::QAbstractTexture *texture,
+ Q3DSDefaultMaterialAttached *data,
+ Q3DSImage *iblOverride) {
+ data->lightProbeSampler->setValue(QVariant::fromValue(texture));
+ setupTexture(texture, data, iblOverride);
+ }, data, iblOverride);
+ data->lightProbeOverrideTexture->onUnload([](Qt3DRender::QAbstractTexture *texture,
+ Q3DSDefaultMaterialAttached *data) {
+ Q_UNUSED(texture);
+ data->lightProbeSampler->setValue({});
+ data->lightProbeOffset->setValue({});
+ data->lightProbeRotation->setValue({});
+ }, data);
}
-
- Q_ASSERT(data->lightProbeOverrideTexture);
- data->lightProbeOverrideTexture->setWrapMode(wrapMode);
-
- const QMatrix4x4 &textureTransform = iblOverride->textureTransform();
- const float *m = textureTransform.constData();
-
- // offsets.w = max mip level
- const QSize texSize = Q3DSImageManager::instance().size(data->lightProbeOverrideTexture);
- float mipLevels = float(qCeil(qLog2(qMax(texSize.width(), texSize.height()))));
- QVector4D offsets(m[12], m[13], 0.0f, mipLevels);
- data->lightProbeOffset->setValue(offsets);
-
- QVector4D rotations(m[0], m[4], m[1], m[5]);
- data->lightProbeRotation->setValue(rotations);
}
}
@@ -6614,71 +6789,91 @@ static inline void forAllCustomProperties(Q3DSEffectInstance *eff3DS, CustomProp
iterateCustomProperties(eff3DS->dynamicProperties(), eff3DS->effect()->properties(), callback);
}
-Qt3DRender::QAbstractTexture *Q3DSSceneManager::createCustomPropertyTexture(const Q3DSCustomPropertyParameter &p, const QByteArray &id)
+void Q3DSSceneManager::createCustomPropertyTexture(Q3DSCustomPropertyParameter &p,
+ const QByteArray &id)
{
+ // now override the defaults set in setSource() with whatever the metadata specifies
+ auto setupTexture = [](Q3DSCustomPropertyParameter *p, Qt3DRender::QAbstractTexture *texture) {
+ switch (p->meta.magFilterType) {
+ case Q3DSMaterial::Nearest:
+ texture->setMagnificationFilter(Qt3DRender::QAbstractTexture::Nearest);
+ break;
+ default:
+ texture->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ break;
+ }
+
+ switch (p->meta.minFilterType) {
+ case Q3DSMaterial::Nearest:
+ texture->setMinificationFilter(Qt3DRender::QAbstractTexture::Nearest);
+ break;
+ case Q3DSMaterial::Linear:
+ texture->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ break;
+ case Q3DSMaterial::NearestMipmapNearest:
+ texture->setMinificationFilter(Qt3DRender::QAbstractTexture::NearestMipMapNearest);
+ texture->setGenerateMipMaps(true);
+ break;
+ case Q3DSMaterial::NearestMipmapLinear:
+ texture->setMinificationFilter(Qt3DRender::QAbstractTexture::NearestMipMapLinear);
+ texture->setGenerateMipMaps(true);
+ break;
+ case Q3DSMaterial::LinearMipmapNearest:
+ texture->setMinificationFilter(Qt3DRender::QAbstractTexture::LinearMipMapNearest);
+ texture->setGenerateMipMaps(true);
+ break;
+ default:
+ texture->setMinificationFilter(Qt3DRender::QAbstractTexture::LinearMipMapLinear);
+ texture->setGenerateMipMaps(true);
+ break;
+ }
+
+ Qt3DRender::QTextureWrapMode wrapMode;
+ switch (p->meta.clampType) {
+ case Q3DSMaterial::Repeat:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ default:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
+ texture->setWrapMode(wrapMode);
+ };
+
const QString source = p.inputValue.toString();
Qt3DRender::QAbstractTexture *texture;
if (source.isEmpty()) {
texture = dummyTexture(id);
+ setupTexture(&p, texture);
+ p.param->setValue(QVariant::fromValue(texture));
} else {
- texture = Q3DSImageManager::instance().newTextureForImage(m_rootEntity, 0, id, m_profiler,
- "Custom property texture %s", qPrintable(source));
+ p.texture = Q3DSImageManager::instance().newReloadableTextureForImage(
+ m_rootEntity, 0, id, m_profiler, "Custom property texture %s",
+ qPrintable(source));
qCDebug(lcScene, "Creating custom property texture %s", qPrintable(source));
- Q3DSImageManager::instance().setSource(texture, QUrl::fromLocalFile(source),
- m_presentation->preferKtx());
- }
-
- // now override the defaults set in setSource() with whatever the metadata specifies
-
- switch (p.meta.magFilterType) {
- case Q3DSMaterial::Nearest:
- texture->setMagnificationFilter(Qt3DRender::QAbstractTexture::Nearest);
- break;
- default:
- texture->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);
- break;
- }
-
- switch (p.meta.minFilterType) {
- case Q3DSMaterial::Nearest:
- texture->setMinificationFilter(Qt3DRender::QAbstractTexture::Nearest);
- break;
- case Q3DSMaterial::Linear:
- texture->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
- break;
- case Q3DSMaterial::NearestMipmapNearest:
- texture->setMinificationFilter(Qt3DRender::QAbstractTexture::NearestMipMapNearest);
- texture->setGenerateMipMaps(true);
- break;
- case Q3DSMaterial::NearestMipmapLinear:
- texture->setMinificationFilter(Qt3DRender::QAbstractTexture::NearestMipMapLinear);
- texture->setGenerateMipMaps(true);
- break;
- case Q3DSMaterial::LinearMipmapNearest:
- texture->setMinificationFilter(Qt3DRender::QAbstractTexture::LinearMipMapNearest);
- texture->setGenerateMipMaps(true);
- break;
- default:
- texture->setMinificationFilter(Qt3DRender::QAbstractTexture::LinearMipMapLinear);
- texture->setGenerateMipMaps(true);
- break;
-
- }
-
- Qt3DRender::QTextureWrapMode wrapMode;
- switch (p.meta.clampType) {
- case Q3DSMaterial::Repeat:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
- wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
- break;
- default:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
- wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
- break;
+ p.texture->setSource(m_presentation->imageUrl(source));
+ p.texture->onLoad([setupTexture](Qt3DRender::QAbstractTexture *texture,
+ Q3DSCustomPropertyParameter *p) {
+ p->param->setValue(QVariant::fromValue(texture));
+ if (p->texFlagParam)
+ p->texFlagParam->setValue(1);
+ const QSize size = Q3DSImageManager::instance().size(texture);
+ const bool isPremultiplied = false;
+ if (p->texInfoParam) {
+ p->texInfoParam->setValue(QVector4D(size.width(), size.height(),
+ isPremultiplied ? 1 : 0, 0));
+ }
+ setupTexture(p, texture);
+ }, &p);
+ p.texture->onUnload([](Qt3DRender::QAbstractTexture *texture,
+ Q3DSCustomPropertyParameter *p) {
+ Q_UNUSED(texture);
+ p->param->setValue({});
+ p->texInfoParam->setValue({});
+ }, &p);
}
- texture->setWrapMode(wrapMode);
-
- return texture;
}
QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS)
@@ -6770,7 +6965,8 @@ QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareCustomMaterial(Q3DSCu
iblOverrideImage = m->lightProbe();
if (iblOverrideImage) {
if (!data->lightProbeOverrideTexture) {
- data->lightProbeOverrideTexture = Q3DSImageManager::instance().newTextureForImage(
+ data->lightProbeOverrideTexture
+ = Q3DSImageManager::instance().newReloadableTextureForImage(
m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL,
iblOverrideImage->id(),
m_profiler, "Texture for image %s", iblOverrideImage->id().constData());
@@ -6818,7 +7014,7 @@ void Q3DSSceneManager::updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSR
// point whereas we need a proper Qt 3D texture.
switch (p.meta.type) {
case Q3DS::Texture:
- p.param->setValue(QVariant::fromValue(createCustomPropertyTexture(p, m->id())));
+ createCustomPropertyTexture(p, m->id());
break;
// Buffer, Image2D, etc. are not used for custom materials
@@ -6868,52 +7064,61 @@ void Q3DSSceneManager::updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSR
// IBL
if (iblOverride) {
// also sets min/mag and generates mipmaps
- Q3DSImageManager::instance().setSource(data->lightProbeOverrideTexture,
- QUrl::fromLocalFile(iblOverride->sourcePath()),
- m_presentation->preferKtx());
- data->lightProbeSampler->setValue(QVariant::fromValue(data->lightProbeOverrideTexture));
-
- Qt3DRender::QTextureWrapMode wrapMode;
- wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
-
- switch (iblOverride->horizontalTiling()) {
- case Q3DSImage::Tiled:
+ data->lightProbeOverrideTexture->setSource(
+ m_presentation->imageUrl(iblOverride->sourcePath()));
+ data->lightProbeOverrideTexture->onLoad([](Qt3DRender::QAbstractTexture *texture,
+ Q3DSImage *iblOverride,
+ Q3DSCustomMaterialAttached *data) {
+ data->lightProbeSampler->setValue(QVariant::fromValue(texture));
+
+ Qt3DRender::QTextureWrapMode wrapMode;
wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
- break;
- case Q3DSImage::Mirrored:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::MirroredRepeat);
- break;
- default:
- wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
- break;
- }
- switch (iblOverride->verticalTiling()) {
- case Q3DSImage::Tiled:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
- break;
- case Q3DSImage::Mirrored:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::MirroredRepeat);
- break;
- default:
- wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
- break;
- }
+ switch (iblOverride->horizontalTiling()) {
+ case Q3DSImage::Tiled:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ case Q3DSImage::Mirrored:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::MirroredRepeat);
+ break;
+ default:
+ wrapMode.setX(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
+
+ switch (iblOverride->verticalTiling()) {
+ case Q3DSImage::Tiled:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::Repeat);
+ break;
+ case Q3DSImage::Mirrored:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::MirroredRepeat);
+ break;
+ default:
+ wrapMode.setY(Qt3DRender::QTextureWrapMode::ClampToEdge);
+ break;
+ }
- Q_ASSERT(data->lightProbeOverrideTexture);
- data->lightProbeOverrideTexture->setWrapMode(wrapMode);
+ texture->setWrapMode(wrapMode);
- const QMatrix4x4 &textureTransform = iblOverride->textureTransform();
- const float *m = textureTransform.constData();
+ const QMatrix4x4 &textureTransform = iblOverride->textureTransform();
+ const float *m = textureTransform.constData();
- // offsets.w = max mip level
- const QSize texSize = Q3DSImageManager::instance().size(data->lightProbeOverrideTexture);
- float mipLevels = float(qCeil(qLog2(qMax(texSize.width(), texSize.height()))));
- QVector4D offsets(m[12], m[13], 0.0f, mipLevels);
- data->lightProbeOffset->setValue(offsets);
+ // offsets.w = max mip level
+ const QSize texSize = Q3DSImageManager::instance().size(texture);
+ float mipLevels = float(qCeil(qLog2(qMax(texSize.width(), texSize.height()))));
+ QVector4D offsets(m[12], m[13], 0.0f, mipLevels);
+ data->lightProbeOffset->setValue(offsets);
- QVector4D rotations(m[0], m[4], m[1], m[5]);
- data->lightProbeRotation->setValue(rotations);
+ QVector4D rotations(m[0], m[4], m[1], m[5]);
+ data->lightProbeRotation->setValue(rotations);
+ }, iblOverride, data);
+ data->lightProbeOverrideTexture->onUnload([](Qt3DRender::QAbstractTexture *texture,
+ Q3DSCustomMaterialAttached *data) {
+ Q_UNUSED(texture);
+ data->lightProbeSampler->setValue({});
+ data->lightProbeOffset->setValue({});
+ data->lightProbeRotation->setValue({});
+ }, data);
}
}
@@ -7896,10 +8101,7 @@ void Q3DSSceneManager::updateEffect(Q3DSEffectInstance *eff3DS)
switch (p.meta.type) {
case Q3DS::Texture:
{
- Qt3DRender::QAbstractTexture *tex = createCustomPropertyTexture(p, eff3DS->id());
- p.param->setValue(QVariant::fromValue(tex));
- setTextureInfoUniform(p.texInfoParam, tex);
- p.texFlagParam->setValue(1);
+ createCustomPropertyTexture(p, eff3DS->id());
}
break;
@@ -8397,7 +8599,8 @@ void Q3DSSceneManager::syncScene()
for (Q3DSModelNode *model3DS : needsRebuild)
rebuildModelMaterial(model3DS);
- Q3DSImageManager::instance().finishAsyncLoad();
+ m_engine->finishAsyncLoad(false);
+ Q3DSImageManager::instance().finishAsyncLoad(false);
}
void Q3DSSceneManager::setPendingVisibilities()
@@ -9073,6 +9276,11 @@ void Q3DSFrameUpdater::frameAction(float dt)
// the time includes all subpresentations too)
m_sceneManager->m_profiler->reportTotalParseBuildTime(m_sceneManager->m_engine->totalLoadTimeMsecs());
}
+
+ // At this point do synchronized start of engine animations
+ QTimer::singleShot(0, [this]() {
+ m_sceneManager->engine()->startAnimations();
+ });
}
m_sceneManager->m_profiler->reportBehaviorStats(m_sceneManager->m_engine->behaviorLoadTimeMsecs(),
m_sceneManager->m_engine->behaviorHandles().count());