90QSSGRenderGraphObject *QQuick3DRenderPass::updateSpatialNode(QSSGRenderGraphObject *node)
92 QSSGRenderUserPass *renderPassNode =
static_cast<QSSGRenderUserPass *>(node);
94 bool newBackendNode =
false;
95 if (!renderPassNode) {
96 renderPassNode =
new QSSGRenderUserPass;
97 newBackendNode =
true;
100 const bool fullUpdate = newBackendNode || (m_dirtyAttributes & Dirty::TextureDirty) || (m_dirtyAttributes & CommandsDirty);
102 auto &shaderAugmentation = renderPassNode->shaderAugmentation;
103 auto &uniformProps = shaderAugmentation.propertyUniforms;
109 uniformProps = extractProperties();
112 renderPassNode->resetCommands();
113 clearDirty(Dirty::CommandsDirty);
114 for (QQuick3DShaderUtilsRenderCommand *command : std::as_const(m_commands)) {
115 if (
auto *cmd = command->cloneCommand())
116 renderPassNode->commands.push_back(cmd);
118 markDirty(CommandsDirty,
true);
123 if (m_dirtyAttributes & Dirty::PropertyDirty) {
124 for (
const auto &prop : std::as_const(uniformProps)) {
125 auto p = metaObject()->property(prop.pid);
126 if (Q_LIKELY(p.isValid())) {
127 QVariant v = p.read(
this);
129 if (v.metaType().id() == qMetaTypeId<QQuick3DTexture *>()) {
130 QQuick3DTexture *tex = v.value<QQuick3DTexture *>();
131 auto *po = QQuick3DObjectPrivate::get(tex);
132 QSSGRenderImage *ri =
static_cast<QSSGRenderImage *>(po->spatialNode);
133 prop.value = QVariant::fromValue(ri);
141 clearDirty(Dirty(Dirty::PropertyDirty | Dirty::TextureDirty));
145 if (m_dirtyAttributes & Dirty::ClearDirty) {
146 renderPassNode->renderTargetFlags = QRhiTextureRenderTarget::Flags(m_renderTargetFlags.toInt());
147 renderPassNode->clearColor = m_clearColor;
148 renderPassNode->depthStencilClearValue = { m_depthClearValue, m_stencilClearValue };
150 clearDirty(Dirty::ClearDirty);
153 if (m_dirtyAttributes & Dirty::PassTypeDirty) {
154 switch (m_passMode) {
156 renderPassNode->passMode = QSSGRenderUserPass::UserPass;
159 renderPassNode->passMode = QSSGRenderUserPass::SkyboxPass;
162 renderPassNode->passMode = QSSGRenderUserPass::Item2DPass;
166 clearDirty(Dirty::PassTypeDirty);
170 if (m_passMode != UserPass)
171 return renderPassNode;
173 renderPassNode->materialMode = QSSGRenderUserPass::MaterialModes(m_materialMode);
174 clearDirty(Dirty::MaterialModeDirty);
176 if (renderPassNode->materialMode == QSSGRenderUserPass::OverrideMaterial) {
177 clearDirty(Dirty::OverrideMaterialDirty);
178 if (m_overrideMaterial) {
180 QSSGRenderGraphObject *graphObject = QQuick3DObjectPrivate::get(m_overrideMaterial)->spatialNode;
182 renderPassNode->overrideMaterial = graphObject;
184 markDirty(OverrideMaterialDirty,
true);
187 renderPassNode->overrideMaterial =
nullptr;
189 }
else if (renderPassNode->materialMode == QSSGRenderUserPass::OriginalMaterial) {
191 }
else if (renderPassNode->materialMode == QSSGRenderUserPass::AugmentMaterial) {
193 if (!m_augmentShader.isEmpty()) {
194 const QQmlContext *context = qmlContext(
this);
195 QByteArray shaderPathKey(
"augment material --");
196 QByteArray augment = QSSGShaderUtils::resolveShader(m_augmentShader, context, shaderPathKey);
197 QByteArray augmentSnippet;
198 QByteArray augmentPreamble;
212 static const char *mainFuncStart =
"void MAIN_FRAGMENT_AUGMENT()";
213 qsizetype mainFuncIdx = augment.indexOf(mainFuncStart);
214 if (mainFuncIdx != -1) {
215 qsizetype braceOpenIdx = augment.indexOf(
'{', mainFuncIdx +
int(strlen(mainFuncStart)));
216 if (braceOpenIdx != -1) {
217 qsizetype braceCloseIdx = braceOpenIdx;
218 qsizetype openBraces = 1;
219 while (openBraces > 0 && braceCloseIdx + 1 < augment.size()) {
221 if (augment[braceCloseIdx] ==
'{')
223 else if (augment[braceCloseIdx] ==
'}')
226 if (openBraces == 0) {
228 augmentSnippet = augment.mid(braceOpenIdx + 1, braceCloseIdx - braceOpenIdx - 1);
229 augmentPreamble = augment.left(mainFuncIdx);
230 augmentPreamble += augment.mid(braceCloseIdx + 1);
232 qWarning(
"QQuick3DRenderPass: Could not find the closing brace of MAIN_FRAGMENT_AUGMENT() in shader %s", qPrintable(m_augmentShader.toString()));
235 qWarning(
"QQuick3DRenderPass: Could not find the opening brace of MAIN_FRAGMENT_AUGMENT() in shader %s", qPrintable(m_augmentShader.toString()));
238 qWarning(
"QQuick3DRenderPass: Could not find MAIN_FRAGMENT_AUGMENT() function in shader %s", qPrintable(m_augmentShader.toString()));
241 renderPassNode->shaderAugmentation.body = augmentSnippet;
242 renderPassNode->shaderAugmentation.preamble = augmentPreamble;
243 renderPassNode->markDirty(QSSGRenderUserPass::DirtyFlag::ShaderDirty);
247 return renderPassNode;
453void QQuick3DRenderPass::setOverrideMaterial(QQuick3DMaterial *newOverrideMaterial)
455 if (m_overrideMaterial == newOverrideMaterial)
459 if (m_overrideMaterial && m_overrideMaterialRefed) {
460 QQuick3DObjectPrivate::derefSceneManager(m_overrideMaterial);
461 m_overrideMaterialRefed =
false;
464 QQuick3DObjectPrivate::attachWatcher(
this, &QQuick3DRenderPass::setOverrideMaterial, newOverrideMaterial, m_overrideMaterial);
466 m_overrideMaterial = newOverrideMaterial;
469 if (m_overrideMaterial && m_overrideMaterial->parentItem() ==
nullptr) {
472 QQuick3DObject *parentItem = qobject_cast<QQuick3DObject *>(m_overrideMaterial->parent());
474 m_overrideMaterial->setParentItem(parentItem);
477 const auto &sceneManager = QQuick3DObjectPrivate::get(
this)->sceneManager;
479 QQuick3DObjectPrivate::refSceneManager(m_overrideMaterial, *sceneManager);
480 m_overrideMaterialRefed =
true;
486 emit overrideMaterialChanged();
487 markDirty(OverrideMaterialDirty);