41QSSGRenderGraphObject *QQuick3DRenderPass::updateSpatialNode(QSSGRenderGraphObject *node)
43 QSSGRenderUserPass *renderPassNode =
static_cast<QSSGRenderUserPass *>(node);
45 bool newBackendNode =
false;
46 if (!renderPassNode) {
47 renderPassNode =
new QSSGRenderUserPass;
48 newBackendNode =
true;
51 const bool fullUpdate = newBackendNode || (m_dirtyAttributes & Dirty::TextureDirty) || (m_dirtyAttributes & CommandsDirty);
53 auto &shaderAugmentation = renderPassNode->shaderAugmentation;
54 auto &uniformProps = shaderAugmentation.propertyUniforms;
61 extractProperties(uniformProps);
64 renderPassNode->resetCommands();
65 clearDirty(Dirty::CommandsDirty);
66 for (QQuick3DShaderUtilsRenderCommand *command : std::as_const(m_commands)) {
67 if (
auto *cmd = command->cloneCommand())
68 renderPassNode->commands.push_back(cmd);
70 markDirty(CommandsDirty,
true);
75 if (m_dirtyAttributes & Dirty::PropertyDirty) {
76 for (
const auto &prop : std::as_const(uniformProps)) {
77 auto p = metaObject()->property(prop.pid);
78 if (Q_LIKELY(p.isValid())) {
79 QVariant v = p.read(
this);
81 if (v.metaType().id() == qMetaTypeId<QQuick3DTexture *>()) {
82 QQuick3DTexture *tex = v.value<QQuick3DTexture *>();
83 auto *po = QQuick3DObjectPrivate::get(tex);
84 QSSGRenderImage *ri =
static_cast<QSSGRenderImage *>(po->spatialNode);
85 prop.value = QVariant::fromValue(ri);
93 clearDirty(Dirty(Dirty::PropertyDirty | Dirty::TextureDirty));
97 if (m_dirtyAttributes & Dirty::ClearDirty) {
98 renderPassNode->renderTargetFlags = QRhiTextureRenderTarget::Flags(m_renderTargetFlags.toInt());
99 renderPassNode->clearColor = m_clearColor;
100 renderPassNode->depthStencilClearValue = { m_depthClearValue, m_stencilClearValue };
102 clearDirty(Dirty::ClearDirty);
105 if (m_dirtyAttributes & Dirty::PassTypeDirty) {
106 switch (m_passMode) {
108 renderPassNode->passMode = QSSGRenderUserPass::UserPass;
111 renderPassNode->passMode = QSSGRenderUserPass::SkyboxPass;
114 renderPassNode->passMode = QSSGRenderUserPass::Item2DPass;
118 clearDirty(Dirty::PassTypeDirty);
122 if (m_passMode != UserPass)
123 return renderPassNode;
125 renderPassNode->materialMode = QSSGRenderUserPass::MaterialModes(m_materialMode);
126 clearDirty(Dirty::MaterialModeDirty);
128 if (renderPassNode->materialMode == QSSGRenderUserPass::OverrideMaterial) {
129 clearDirty(Dirty::OverrideMaterialDirty);
130 if (m_overrideMaterial) {
132 QSSGRenderGraphObject *graphObject = QQuick3DObjectPrivate::get(m_overrideMaterial)->spatialNode;
134 renderPassNode->overrideMaterial = graphObject;
136 markDirty(OverrideMaterialDirty,
true);
139 renderPassNode->overrideMaterial =
nullptr;
141 }
else if (renderPassNode->materialMode == QSSGRenderUserPass::OriginalMaterial) {
143 }
else if (renderPassNode->materialMode == QSSGRenderUserPass::AugmentMaterial) {
145 if (!m_augmentShader.isEmpty()) {
146 const QQmlContext *context = qmlContext(
this);
147 QByteArray shaderPathKey(
"augment material --");
148 QByteArray augment = QSSGShaderUtils::resolveShader(m_augmentShader, context, shaderPathKey);
149 QByteArray augmentSnippet;
150 QByteArray augmentPreamble;
164 static const char *mainFuncStart =
"void MAIN_FRAGMENT_AUGMENT()";
165 qsizetype mainFuncIdx = augment.indexOf(mainFuncStart);
166 if (mainFuncIdx != -1) {
167 qsizetype braceOpenIdx = augment.indexOf(
'{', mainFuncIdx +
int(strlen(mainFuncStart)));
168 if (braceOpenIdx != -1) {
169 qsizetype braceCloseIdx = braceOpenIdx;
170 qsizetype openBraces = 1;
171 while (openBraces > 0 && braceCloseIdx + 1 < augment.size()) {
173 if (augment[braceCloseIdx] ==
'{')
175 else if (augment[braceCloseIdx] ==
'}')
178 if (openBraces == 0) {
180 augmentSnippet = augment.mid(braceOpenIdx + 1, braceCloseIdx - braceOpenIdx - 1);
181 augmentPreamble = augment.left(mainFuncIdx);
182 augmentPreamble += augment.mid(braceCloseIdx + 1);
184 qWarning(
"QQuick3DRenderPass: Could not find the closing brace of MAIN_FRAGMENT_AUGMENT() in shader %s", qPrintable(m_augmentShader.toString()));
187 qWarning(
"QQuick3DRenderPass: Could not find the opening brace of MAIN_FRAGMENT_AUGMENT() in shader %s", qPrintable(m_augmentShader.toString()));
190 qWarning(
"QQuick3DRenderPass: Could not find MAIN_FRAGMENT_AUGMENT() function in shader %s", qPrintable(m_augmentShader.toString()));
193 renderPassNode->shaderAugmentation.body = augmentSnippet;
194 renderPassNode->shaderAugmentation.preamble = augmentPreamble;
195 renderPassNode->markDirty(QSSGRenderUserPass::DirtyFlag::ShaderDirty);
199 return renderPassNode;
382void QQuick3DRenderPass::setOverrideMaterial(QQuick3DMaterial *newOverrideMaterial)
384 if (m_overrideMaterial == newOverrideMaterial)
388 if (m_overrideMaterial && m_overrideMaterialRefed) {
389 QQuick3DObjectPrivate::derefSceneManager(m_overrideMaterial);
390 m_overrideMaterialRefed =
false;
393 QQuick3DObjectPrivate::attachWatcher(
this, &QQuick3DRenderPass::setOverrideMaterial, newOverrideMaterial, m_overrideMaterial);
395 m_overrideMaterial = newOverrideMaterial;
398 if (m_overrideMaterial && m_overrideMaterial->parentItem() ==
nullptr) {
401 QQuick3DObject *parentItem = qobject_cast<QQuick3DObject *>(m_overrideMaterial->parent());
403 m_overrideMaterial->setParentItem(parentItem);
406 const auto &sceneManager = QQuick3DObjectPrivate::get(
this)->sceneManager;
408 QQuick3DObjectPrivate::refSceneManager(m_overrideMaterial, *sceneManager);
409 m_overrideMaterialRefed =
true;
415 emit overrideMaterialChanged();
416 markDirty(OverrideMaterialDirty);