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;
110 extractProperties(uniformProps);
113 renderPassNode->resetCommands();
114 clearDirty(Dirty::CommandsDirty);
115 for (QQuick3DShaderUtilsRenderCommand *command : std::as_const(m_commands)) {
116 if (
auto *cmd = command->cloneCommand())
117 renderPassNode->commands.push_back(cmd);
119 markDirty(CommandsDirty,
true);
124 if (m_dirtyAttributes & Dirty::PropertyDirty) {
125 for (
const auto &prop : std::as_const(uniformProps)) {
126 auto p = metaObject()->property(prop.pid);
127 if (Q_LIKELY(p.isValid())) {
128 QVariant v = p.read(
this);
130 if (v.metaType().id() == qMetaTypeId<QQuick3DTexture *>()) {
131 QQuick3DTexture *tex = v.value<QQuick3DTexture *>();
132 auto *po = QQuick3DObjectPrivate::get(tex);
133 QSSGRenderImage *ri =
static_cast<QSSGRenderImage *>(po->spatialNode);
134 prop.value = QVariant::fromValue(ri);
142 clearDirty(Dirty(Dirty::PropertyDirty | Dirty::TextureDirty));
146 if (m_dirtyAttributes & Dirty::ClearDirty) {
147 renderPassNode->renderTargetFlags = QRhiTextureRenderTarget::Flags(m_renderTargetFlags.toInt());
148 renderPassNode->clearColor = m_clearColor;
149 renderPassNode->depthStencilClearValue = { m_depthClearValue, m_stencilClearValue };
151 clearDirty(Dirty::ClearDirty);
154 if (m_dirtyAttributes & Dirty::PassTypeDirty) {
155 switch (m_passMode) {
157 renderPassNode->passMode = QSSGRenderUserPass::UserPass;
160 renderPassNode->passMode = QSSGRenderUserPass::SkyboxPass;
163 renderPassNode->passMode = QSSGRenderUserPass::Item2DPass;
167 clearDirty(Dirty::PassTypeDirty);
171 if (m_passMode != UserPass)
172 return renderPassNode;
174 renderPassNode->materialMode = QSSGRenderUserPass::MaterialModes(m_materialMode);
175 clearDirty(Dirty::MaterialModeDirty);
177 if (renderPassNode->materialMode == QSSGRenderUserPass::OverrideMaterial) {
178 clearDirty(Dirty::OverrideMaterialDirty);
179 if (m_overrideMaterial) {
181 QSSGRenderGraphObject *graphObject = QQuick3DObjectPrivate::get(m_overrideMaterial)->spatialNode;
183 renderPassNode->overrideMaterial = graphObject;
185 markDirty(OverrideMaterialDirty,
true);
188 renderPassNode->overrideMaterial =
nullptr;
190 }
else if (renderPassNode->materialMode == QSSGRenderUserPass::OriginalMaterial) {
192 }
else if (renderPassNode->materialMode == QSSGRenderUserPass::AugmentMaterial) {
194 if (!m_augmentShader.isEmpty()) {
195 const QQmlContext *context = qmlContext(
this);
196 QByteArray shaderPathKey(
"augment material --");
197 QByteArray augment = QSSGShaderUtils::resolveShader(m_augmentShader, context, shaderPathKey);
198 QByteArray augmentSnippet;
199 QByteArray augmentPreamble;
213 static const char *mainFuncStart =
"void MAIN_FRAGMENT_AUGMENT()";
214 qsizetype mainFuncIdx = augment.indexOf(mainFuncStart);
215 if (mainFuncIdx != -1) {
216 qsizetype braceOpenIdx = augment.indexOf(
'{', mainFuncIdx +
int(strlen(mainFuncStart)));
217 if (braceOpenIdx != -1) {
218 qsizetype braceCloseIdx = braceOpenIdx;
219 qsizetype openBraces = 1;
220 while (openBraces > 0 && braceCloseIdx + 1 < augment.size()) {
222 if (augment[braceCloseIdx] ==
'{')
224 else if (augment[braceCloseIdx] ==
'}')
227 if (openBraces == 0) {
229 augmentSnippet = augment.mid(braceOpenIdx + 1, braceCloseIdx - braceOpenIdx - 1);
230 augmentPreamble = augment.left(mainFuncIdx);
231 augmentPreamble += augment.mid(braceCloseIdx + 1);
233 qWarning(
"QQuick3DRenderPass: Could not find the closing brace of MAIN_FRAGMENT_AUGMENT() in shader %s", qPrintable(m_augmentShader.toString()));
236 qWarning(
"QQuick3DRenderPass: Could not find the opening brace of MAIN_FRAGMENT_AUGMENT() in shader %s", qPrintable(m_augmentShader.toString()));
239 qWarning(
"QQuick3DRenderPass: Could not find MAIN_FRAGMENT_AUGMENT() function in shader %s", qPrintable(m_augmentShader.toString()));
242 renderPassNode->shaderAugmentation.body = augmentSnippet;
243 renderPassNode->shaderAugmentation.preamble = augmentPreamble;
244 renderPassNode->markDirty(QSSGRenderUserPass::DirtyFlag::ShaderDirty);
248 return renderPassNode;
454void QQuick3DRenderPass::setOverrideMaterial(QQuick3DMaterial *newOverrideMaterial)
456 if (m_overrideMaterial == newOverrideMaterial)
460 if (m_overrideMaterial && m_overrideMaterialRefed) {
461 QQuick3DObjectPrivate::derefSceneManager(m_overrideMaterial);
462 m_overrideMaterialRefed =
false;
465 QQuick3DObjectPrivate::attachWatcher(
this, &QQuick3DRenderPass::setOverrideMaterial, newOverrideMaterial, m_overrideMaterial);
467 m_overrideMaterial = newOverrideMaterial;
470 if (m_overrideMaterial && m_overrideMaterial->parentItem() ==
nullptr) {
473 QQuick3DObject *parentItem = qobject_cast<QQuick3DObject *>(m_overrideMaterial->parent());
475 m_overrideMaterial->setParentItem(parentItem);
478 const auto &sceneManager = QQuick3DObjectPrivate::get(
this)->sceneManager;
480 QQuick3DObjectPrivate::refSceneManager(m_overrideMaterial, *sceneManager);
481 m_overrideMaterialRefed =
true;
487 emit overrideMaterialChanged();
488 markDirty(OverrideMaterialDirty);