Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qssgrenderhelpers.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
8
9#include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h>
10#include <QtQuick3DRuntimeRender/private/qssgrenderhelpers_p.h>
11#include <QtQuick3DRuntimeRender/private/qssglayerrenderdata_p.h>
12
13#include "graphobjects/qssgrendermodel_p.h"
14#include <QtQuick3DRuntimeRender/private/qssgrendercamera_p.h>
15
16#include <QtQuick3DUtils/private/qssgassert_p.h>
17
19
20 /*!
21 \class QSSGRenderHelpers
22 \inmodule QtQuick3D
23 \since 6.7
24
25 \brief Class containing helper functions for setting up and render QtQuick3D renderables.
26*/
27
28/*!
29 \typedef QSSGPrepContextId
30 \relates QtQuick3D
31
32 Handle to a preparation context. Setting up a preparation context is the first
33 step needed before renderables can be created and rendered.
34
35 \sa QSSGRenderHelpers::prepareForRender()
36*/
37
38/*!
39 \typedef QSSGRenderablesId
40 \brief Handle to a set of renderables.
41 \relates QtQuick3D
42
43 Handle to a set of renderables created for one or more node(s). This \c id can be used
44 to for example modify the renderables created for a specific model.
45*/
46
47/*!
48 \typedef QSSGPrepResultId
49 \relates QtQuick3D
50
51 Handle to a preparation result.
52
53 Once the \l {QSSGRenderHelpers::createRenderables}{renderables} for a frame are updated and ready
54 to be translated into rendering code by the engine, the \l {QSSGRenderHelpers::createRenderables}{renderables}
55 and the \l {QSSGRenderHelpers::prepareForRender()}{preparation context} can be \l {QSSGRenderHelpers::commit()}{committed}.
56 If the commit succeeds, the returned preparation result can be used to \l {QSSGRenderHelpers::prepareRenderables()}{prepare}
57 and \l {QSSGRenderHelpers::renderRenderables}{record} the rendering for the frame.
58*/
59
60/*!
61 \enum QSSGRenderHelpers::CreateFlag
62
63 \value None The default value. Renderables are created only for the nodes specified.
64 \value Recurse Renderables are created for each node and their children.
65 \value Steal Renderables are taken from the engine and won't be rendered by QtQuick3D.
66
67 \note Calling \l QSSGRenderHelpers::createRenderables() without the {QSSGRenderHelpers::CreateFlag::Steal}{Steal}
68 flag set means nodes are duplicated and QtQuick3D will render its copy of the nodes as normal.
69*/
70
71/*!
72 Takes a list of node ids and create renderables that can be further processed by the renderer.
73 If there are no nodes, or no renderable nodes in the list, the returned id will be invalid.
74
75 By default the function does not recurse down and included children of the \a nodes in the list.
76 Enabling recursion can be achieved by passing in the \l{CreateFlag::}{Recurse} flag in
77 the \a flags argument.
78
79 \return an id to the created renderables.
80
81 \a frameData, \a prepId
82
83 \sa CreateFlags, prepareForRender()
84 */
85QSSGRenderablesId QSSGRenderHelpers::createRenderables(const QSSGFrameData &frameData,
86 QSSGPrepContextId prepId,
87 const QSSGNodeIdList &nodes,
88 CreateFlags flags)
89{
90 QSSGRenderablesId rid { QSSGRenderablesId::Invalid };
91 if (nodes.size() > 0) {
92 auto *ctx = frameData.contextInterface();
93 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
94 QSSG_ASSERT_X(layer, "No active layer for renderer!", return rid);
95 return layer->createRenderables(prepId, nodes, flags);
96 }
97
98 return rid;
99}
100
101/*!
102 prepareForRender() creates a context for collecting and storing information about the render-data
103 associated with this render extension.
104
105 If the same nodes are to be rendered more then once but with different properties, for example
106 a different material or camera, then a new context will be needed. To create several contexts for
107 one extension the \a slot argument can be used. The default context is created in slot \b 0.
108
109 \return an id to the prep context.
110
111 \a frameData, \a ext, \a cameraId
112
113 \sa commit()
114 */
115
116QSSGPrepContextId QSSGRenderHelpers::prepareForRender(const QSSGFrameData &frameData,
117 const QSSGRenderExtension &ext,
118 QSSGCameraId cameraId,
119 quint32 slot)
120{
121 auto *cn = QSSGRenderGraphObjectUtils::getCamera<QSSGRenderCamera>(cameraId);
122 QSSG_ASSERT_X(cn && QSSGRenderGraphObject::isCamera(cn->type), "CameraId is not a camera!", return QSSGPrepContextId::Invalid);
123 auto *ctx = frameData.contextInterface();
124 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
125 QSSG_ASSERT_X(layer, "No active layer for renderer!", return QSSGPrepContextId::Invalid);
126 return layer->getOrCreateExtensionContext(ext, cn, slot);
127}
128
129/*!
130 Once the required changes have been done to the renderables, the data can marked as ready for
131 the renderer.
132
133 \return an id to the preparation result.
134
135 \a frameData, \a prepId, \a renderablesId, \a lodThreshold
136
137 \sa prepareRenderables(), renderRenderables()
138 */
139QSSGPrepResultId QSSGRenderHelpers::commit(const QSSGFrameData &frameData,
140 QSSGPrepContextId prepId,
141 QSSGRenderablesId renderablesId,
142 float lodThreshold)
143{
144 auto *ctx = frameData.contextInterface();
145 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
146 QSSG_ASSERT_X(layer, "No active layer for renderer!", return QSSGPrepResultId::Invalid);
147 return layer->prepareModelsForRender(*ctx, prepId, renderablesId, lodThreshold);
148}
149
150/*!
151 Prepare the draw call data needed for the renderables before calling \l {renderRenderables}.
152
153 \return an id to the preparation result.
154
155 \a frameData, \a renderPassDescriptor, \a ps, \a prepId, \a filter
156
157 \sa renderRenderables()
158 */
159void QSSGRenderHelpers::prepareRenderables(const QSSGFrameData &frameData,
160 QSSGPrepResultId prepId,
161 QRhiRenderPassDescriptor *renderPassDescriptor,
162 QSSGRhiGraphicsPipelineState &ps,
163 QSSGRenderablesFilters filter)
164{
165 auto *ctx = frameData.contextInterface();
166 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
167 QSSG_ASSERT_X(layer, "No active layer for renderer!", return);
168 layer->prepareRenderables(*ctx, prepId, renderPassDescriptor, ps, filter);
169}
170
171/*!
172 Render the renderables.
173
174 \a frameData, \a prepId
175
176 \sa prepareRenderables()
177 */
178void QSSGRenderHelpers::renderRenderables(const QSSGFrameData &frameData,
179 QSSGPrepResultId prepId)
180{
181 QSSGRenderContextInterface *ctx = frameData.contextInterface();
182 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
183 QSSG_ASSERT_X(layer, "No active layer for renderer!", return);
184 layer->renderRenderables(*ctx, prepId);
185}
186
187QSSGRenderHelpers::QSSGRenderHelpers()
188{
189
190}
191
192 /*!
193 \class QSSGModelHelpers
194 \inmodule QtQuick3D
195 \since 6.7
196
197 \brief Class containing helper functions for modifying and setting data for model renderables.
198*/
199
200/*!
201 Sets the \a materials to be used on \a model.
202
203 \note As with the \l {QtQuick3D::Model::materials}{materials} on the \l {QtQuick3D::Model}{model} item,
204 materials are applied in the same manner.
205
206 The sub-mesh uses a material from the \l{materials} list, corresponding to its index. If the number
207 of materials is less than the sub-meshes, the last material in the list is used for subsequent
208 sub-meshes.
209
210 \a frameData \a renderablesId
211
212 \sa QSSGRenderHelpers::createRenderables()
213 */
214void QSSGModelHelpers::setModelMaterials(const QSSGFrameData &frameData,
215 QSSGRenderablesId renderablesId,
216 QSSGNodeId model,
217 MaterialList materials)
218{
219 auto *ctx = frameData.contextInterface();
220 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
221 QSSG_ASSERT_X(layer, "No active layer for renderer!", return);
222 auto *renderModel = QSSGRenderGraphObjectUtils::getNode<QSSGRenderModel>(model);
223 QSSG_ASSERT_X(renderModel && renderModel->type == QSSGRenderGraphObject::Type::Model, "Invalid model-id!", return);
224 layer->setModelMaterials(renderablesId, *renderModel, materials);
225}
226
227/*!
228 Convenience function to apply \a materials to all models in the renderablesId set.
229
230 \a frameData, \a renderablesId
231
232 \sa QSSGRenderHelpers::createRenderables()
233 */
234void QSSGModelHelpers::setModelMaterials(const QSSGFrameData &frameData,
235 QSSGRenderablesId renderablesId,
236 MaterialList materials)
237{
238 auto *ctx = frameData.contextInterface();
239 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
240 QSSG_ASSERT_X(layer, "No active layer for renderer!", return);
241 layer->setModelMaterials(renderablesId, materials);
242}
243
244/*!
245 \return Returns the global transform for the \a model in context of the \a prepId. By default the prep context argument is
246 QSSGPrepContextId::Uninitialized which returns the model's original global transform.
247
248 \a frameData
249
250 \sa QSSGRenderHelpers::createRenderables()
251*/
252QMatrix4x4 QSSGModelHelpers::getGlobalTransform(const QSSGFrameData &frameData,
253 QSSGNodeId model,
254 QSSGPrepContextId prepId)
255{
256 auto *ctx = frameData.contextInterface();
257 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
258 QSSG_ASSERT_X(layer, "No active layer for renderer!", return {});
259 auto *renderModel = QSSGRenderGraphObjectUtils::getNode<QSSGRenderModel>(model);
260 QSSG_ASSERT_X(renderModel && renderModel->type == QSSGRenderGraphObject::Type::Model, "Invalid model-id!", return {});
261 return (prepId != QSSGPrepContextId::Invalid) ? layer->getGlobalTransform(prepId, *renderModel)
262 : layer->getGlobalTransform(*renderModel);
263}
264
265/*!
266 \return Returns the local transform for the \a model.
267
268 \a frameData
269*/
270QMatrix4x4 QSSGModelHelpers::getLocalTransform(const QSSGFrameData &frameData, QSSGNodeId model)
271{
272 Q_UNUSED(frameData);
273 auto *renderModel = QSSGRenderGraphObjectUtils::getNode<QSSGRenderModel>(model);
274 QSSG_ASSERT_X(renderModel && renderModel->type == QSSGRenderGraphObject::Type::Model, "Invalid model-id!", return {});
275 return renderModel->localTransform;
276}
277
278/*!
279 \return Returns the global opacity for the \a model.
280
281 \a frameData
282*/
283float QSSGModelHelpers::getGlobalOpacity(const QSSGFrameData &frameData, QSSGNodeId model)
284{
285 auto *ctx = frameData.contextInterface();
286 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
287 QSSG_ASSERT_X(layer, "No active layer for renderer!", return {});
288 auto *renderModel = QSSGRenderGraphObjectUtils::getNode<QSSGRenderModel>(model);
289 QSSG_ASSERT_X(renderModel && renderModel->type == QSSGRenderGraphObject::Type::Model, "Invalid model-id!", return {});
290 return layer->getGlobalOpacity(*renderModel);
291}
292
293/*!
294 \return Returns the global opacity for the \a model in context of the \a prepId. By default the prep context argument is
295 QSSGPrepContextId::Uninitialized which returns the model's original global opacity.
296
297 \a frameData
298
299 \sa QSSGRenderHelpers::createRenderables()
300*/
301float QSSGModelHelpers::getGlobalOpacity(const QSSGFrameData &frameData, QSSGNodeId model, QSSGPrepContextId prepId = QSSGPrepContextId::Invalid)
302{
303 auto *ctx = frameData.contextInterface();
304 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
305 QSSG_ASSERT_X(layer, "No active layer for renderer!", return {});
306 auto *renderModel = QSSGRenderGraphObjectUtils::getNode<QSSGRenderModel>(model);
307 QSSG_ASSERT_X(renderModel && renderModel->type == QSSGRenderGraphObject::Type::Model, "Invalid model-id!", return {});
308 return (prepId != QSSGPrepContextId::Invalid) ? layer->getGlobalOpacity(prepId, *renderModel) : layer->getGlobalOpacity(*renderModel);
309}
310
311/*!
312 \return Returns the local opacity for the \a model.
313
314 \a frameData
315*/
316float QSSGModelHelpers::getLocalOpacity(const QSSGFrameData &frameData, QSSGNodeId model)
317{
318 Q_UNUSED(frameData);
319 auto *renderModel = QSSGRenderGraphObjectUtils::getNode<QSSGRenderModel>(model);
320 QSSG_ASSERT_X(renderModel && renderModel->type == QSSGRenderGraphObject::Type::Model, "Invalid model-id!", return {});
321 return renderModel->localOpacity;
322}
323
324/*!
325 Sets the global transform for \a model in the context of the \a renderablesId.
326
327 \a frameData, \a transform
328
329 \sa QSSGRenderHelpers::createRenderables()
330 */
331void QSSGModelHelpers::setGlobalTransform(const QSSGFrameData &frameData,
332 QSSGRenderablesId renderablesId,
333 QSSGNodeId model,
334 const QMatrix4x4 &transform)
335{
336 auto *ctx = frameData.contextInterface();
337 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
338 QSSG_ASSERT_X(layer, "No active layer for renderer!", return);
339 auto *node = QSSGRenderGraphObjectUtils::getNode(model);
340 QSSG_ASSERT_X(node && node->type == QSSGRenderGraphObject::Type::Model, "Invalid model-id!", return);
341 const auto &renderModel = static_cast<const QSSGRenderModel &>(*node);
342 layer->setGlobalTransform(renderablesId, renderModel, transform);
343}
344
345/*!
346 Sets the global opacity for \a model in the context of the \a renderablesId.
347
348 \a frameData, \a opacity
349
350 \sa QSSGRenderHelpers::createRenderables()
351 */
352void QSSGModelHelpers::setGlobalOpacity(const QSSGFrameData &frameData, QSSGRenderablesId renderablesId, QSSGNodeId model, float opacity)
353{
354 auto *ctx = frameData.contextInterface();
355 auto *layer = QSSGLayerRenderData::getCurrent(*ctx->renderer());
356 QSSG_ASSERT_X(layer, "No active layer for renderer!", return);
357 auto *node = QSSGRenderGraphObjectUtils::getNode(model);
358 QSSG_ASSERT_X(node && node->type == QSSGRenderGraphObject::Type::Model, "Invalid model-id!", return);
359 const auto &renderModel = static_cast<const QSSGRenderModel &>(*node);
360 layer->setGlobalOpacity(renderablesId, renderModel, opacity);
361}
362
363 /*!
364 \class QSSGCameraHelpers
365 \inmodule QtQuick3D
366 \since 6.7
367
368 \brief Class containing helper functions for getting camera data used for rendering.
369*/
370
371/*!
372 Get the projection matrix for \a cameraId. An optional transform argument can be given to be used
373 instead of the cameras global transform when calculating the projection matrix.
374
375 \return projection matrix for \a cameraId
376
377 \a globalTransform
378
379 \sa QSSGRenderHelpers::createRenderables()
380 */
381QMatrix4x4 QSSGCameraHelpers::getViewProjectionMatrix(const QSSGCameraId cameraId,
382 const QMatrix4x4 *globalTransform)
383{
384 auto *renderCamera = QSSGRenderGraphObjectUtils::getCamera<QSSGRenderCamera>(cameraId);
385 QSSG_ASSERT(renderCamera && QSSGRenderGraphObject::isCamera(renderCamera->type), return {});
386
387 QMatrix4x4 mat44{Qt::Uninitialized};
388 const auto &projection = renderCamera->projection;
389 const auto &transform = (globalTransform != 0) ? *globalTransform : renderCamera->localTransform;
390 QSSGRenderCamera::calculateViewProjectionMatrix(transform, projection, mat44);
391 return mat44;
392}
393
394 /*!
395 \class QSSGRenderExtensionHelpers
396 \inmodule QtQuick3D
397 \since 6.7
398
399 \brief Class containing helper functions for the extensions.
400*/
401
402/*!
403 Register a render result, in form of a texture, for this \a extension. Once a texture is registered,
404 the extension can be used as a {QtQuick3D::Texture::textureProvider}{texture provider} in QML.
405
406 \note To ensure that the \a texture is available for renderables, for example to be used by a {QtQuick3D::Texture} item,
407 textures should be registered during the \l QSSGRenderExtension::prepareData call of the extension.
408
409 \note Calling this function with a new texture will unregister any previously registered texture.
410 To unregister a texture, call this function with a \c nullptr texture.
411
412 \a frameData
413
414 \sa {QtQuick3D::Texture::textureProvider}{textureProvider}
415 */
416void QSSGRenderExtensionHelpers::registerRenderResult(const QSSGFrameData &frameData,
417 QSSGExtensionId extension,
418 QRhiTexture *texture)
419{
420 if (auto *ext = QSSGRenderGraphObjectUtils::getExtension<QSSGRenderExtension>(extension)) {
421 const QSSGRenderContextInterface *ctx = frameData.contextInterface();
422 ctx->bufferManager()->registerExtensionResult(*ext, texture);
423 }
424}
425
426QT_END_NAMESPACE
Combined button and popup list for selecting options.