1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2022 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5#ifndef QSSG_LAYER_RENDER_DATA_H
6#define QSSG_LAYER_RENDER_DATA_H
7
8
9//
10// W A R N I N G
11// -------------
12//
13// This file is not part of the Qt API. It exists purely as an
14// implementation detail. This header file may change from version to
15// version without notice, or even be removed.
16//
17// We mean it.
18//
19
20#include <QtQuick3DRuntimeRender/private/qssgrenderitem2d_p.h>
21#include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h>
22#include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h>
23#include <QtQuick3DRuntimeRender/private/qssgrenderableobjects_p.h>
24#include <QtQuick3DRuntimeRender/private/qssgrenderclippingfrustum_p.h>
25#include <QtQuick3DRuntimeRender/private/qssgrendershadowmap_p.h>
26#include <QtQuick3DRuntimeRender/private/qssgrendereffect_p.h>
27#include <QtQuick3DRuntimeRender/private/qssgrenderresourceloader_p.h>
28#include <QtQuick3DRuntimeRender/private/qssgrenderreflectionmap_p.h>
29#include <QtQuick3DRuntimeRender/private/qssgrendercamera_p.h>
30#include <QtQuick3DRuntimeRender/private/qssgrhicontext_p.h>
31#include <QtQuick3DRuntimeRender/private/qssgrenderextensions_p.h>
32
33#include <QtQuick3DUtils/private/qssgrenderbasetypes_p.h>
34
35#include <optional>
36
37#include "qssgrenderpass_p.h"
38
39#define QSSG_RENDER_MINIMUM_RENDER_OPACITY .01f
40
41QT_BEGIN_NAMESPACE
42
43struct QSSGRenderableObject;
44
45enum class QSSGLayerRenderPreparationResultFlag
46{
47 // Was the data in this layer dirty (meaning re-render to texture, possibly)
48 WasLayerDataDirty = 1 << 0,
49
50 // Was the data in this layer dirty *or* this layer *or* any effect dirty.
51 WasDirty = 1 << 1,
52
53 RequiresDepthTexture = 1 << 2,
54
55 // SSAO should be done in a separate pass
56 // Note that having an AO pass necessitates a DepthTexture so this flag should
57 // never be set without the RequiresDepthTexture flag as well.
58 RequiresSsaoPass = 1 << 3,
59
60 // if some light cause shadow
61 // we need a separate per light shadow map pass
62 RequiresShadowMapPass = 1 << 4,
63
64 RequiresScreenTexture = 1 << 5,
65
66 // set together with RequiresScreenTexture when SCREEN_MIP_TEXTURE is used
67 RequiresMipmapsForScreenTexture = 1 << 6
68};
69
70struct QSSGLayerRenderPreparationResultFlags : public QFlags<QSSGLayerRenderPreparationResultFlag>
71{
72 bool wasLayerDataDirty() const
73 {
74 return this->operator&(other: QSSGLayerRenderPreparationResultFlag::WasLayerDataDirty);
75 }
76 void setLayerDataDirty(bool inValue)
77 {
78 setFlag(flag: QSSGLayerRenderPreparationResultFlag::WasLayerDataDirty, on: inValue);
79 }
80
81 bool wasDirty() const { return this->operator&(other: QSSGLayerRenderPreparationResultFlag::WasDirty); }
82 void setWasDirty(bool inValue) { setFlag(flag: QSSGLayerRenderPreparationResultFlag::WasDirty, on: inValue); }
83
84 bool requiresDepthTexture() const
85 {
86 return this->operator&(other: QSSGLayerRenderPreparationResultFlag::RequiresDepthTexture);
87 }
88 void setRequiresDepthTexture(bool inValue)
89 {
90 setFlag(flag: QSSGLayerRenderPreparationResultFlag::RequiresDepthTexture, on: inValue);
91 }
92
93 bool requiresSsaoPass() const { return this->operator&(other: QSSGLayerRenderPreparationResultFlag::RequiresSsaoPass); }
94 void setRequiresSsaoPass(bool inValue)
95 {
96 setFlag(flag: QSSGLayerRenderPreparationResultFlag::RequiresSsaoPass, on: inValue);
97 }
98
99 bool requiresShadowMapPass() const
100 {
101 return this->operator&(other: QSSGLayerRenderPreparationResultFlag::RequiresShadowMapPass);
102 }
103 void setRequiresShadowMapPass(bool inValue)
104 {
105 setFlag(flag: QSSGLayerRenderPreparationResultFlag::RequiresShadowMapPass, on: inValue);
106 }
107
108 bool requiresScreenTexture() const
109 {
110 return this->operator&(other: QSSGLayerRenderPreparationResultFlag::RequiresScreenTexture);
111 }
112 void setRequiresScreenTexture(bool inValue)
113 {
114 setFlag(flag: QSSGLayerRenderPreparationResultFlag::RequiresScreenTexture, on: inValue);
115 }
116
117 bool requiresMipmapsForScreenTexture() const
118 {
119 return this->operator&(other: QSSGLayerRenderPreparationResultFlag::RequiresMipmapsForScreenTexture);
120 }
121 void setRequiresMipmapsForScreenTexture(bool inValue)
122 {
123 setFlag(flag: QSSGLayerRenderPreparationResultFlag::RequiresMipmapsForScreenTexture, on: inValue);
124 }
125};
126
127struct QSSGCameraRenderData
128{
129 QMatrix4x4 viewProjection;
130 std::optional<QSSGClippingFrustum> clippingFrustum;
131 QVector3D direction { 0.0f, 0.0f, -1.0f };
132 QVector3D position;
133};
134
135struct QSSGLayerRenderPreparationResult
136{
137 QSSGLayerRenderPreparationResultFlags flags;
138 QRectF viewport;
139 QSSGRenderLayer *layer = nullptr;
140
141 QSSGLayerRenderPreparationResult() = default;
142 QSSGLayerRenderPreparationResult(const QRectF &inViewport, QSSGRenderLayer &inLayer);
143
144 bool isLayerVisible() const;
145 QSize textureDimensions() const;
146 QSSGCameraGlobalCalculationResult setupCameraForRender(QSSGRenderCamera &inCamera);
147};
148
149struct QSSGDefaultMaterialPreparationResult
150{
151 QSSGRenderableImage *firstImage;
152 float opacity;
153 QSSGRenderableObjectFlags renderableFlags;
154 QSSGShaderDefaultMaterialKey materialKey;
155 bool dirty;
156
157 explicit QSSGDefaultMaterialPreparationResult(QSSGShaderDefaultMaterialKey inMaterialKey);
158};
159
160struct QSSGBakedLightingModel
161{
162 QSSGBakedLightingModel(const QSSGRenderModel *model, const QVector<QSSGRenderableObjectHandle> &renderables)
163 : model(model),
164 renderables(renderables)
165 { }
166
167 const QSSGRenderModel *model;
168 QVector<QSSGRenderableObjectHandle> renderables;
169};
170
171class Q_QUICK3DRUNTIMERENDER_EXPORT QSSGLayerRenderData
172{
173public:
174 enum Enum {
175 MAX_AA_LEVELS = 8,
176 MAX_TEMPORAL_AA_LEVELS = 2,
177 };
178
179 using RenderableFilter = std::function<bool(QSSGModelContext *)>;
180
181 QSSGLayerRenderData(QSSGRenderLayer &inLayer, QSSGRenderer &inRenderer);
182 ~QSSGLayerRenderData();
183
184 typedef QVector<QSSGModelContext *> TModelContextPtrList;
185 using RenderableNodeEntries = QVector<QSSGRenderableNodeEntry>;
186 using RenderableItem2DEntries = QVector<QSSGRenderItem2D *>;
187
188 QSSGShaderDefaultMaterialKey generateLightingKey(QSSGRenderDefaultMaterial::MaterialLighting inLightingType,
189 const QSSGShaderLightListView &lights, bool receivesShadows = true);
190
191 void prepareImageForRender(QSSGRenderImage &inImage,
192 QSSGRenderableImage::Type inMapType,
193 QSSGRenderableImage *&ioFirstImage,
194 QSSGRenderableImage *&ioNextImage,
195 QSSGRenderableObjectFlags &ioFlags,
196 QSSGShaderDefaultMaterialKey &ioGeneratedShaderKey,
197 quint32 inImageIndex, QSSGRenderDefaultMaterial *inMaterial = nullptr);
198
199 void setVertexInputPresence(const QSSGRenderableObjectFlags &renderableFlags,
200 QSSGShaderDefaultMaterialKey &key,
201 QSSGRenderer *renderer);
202
203 // Load meshes as needed
204 static void prepareModelMeshes(const QSSGRenderContextInterface &contextInterface,
205 RenderableNodeEntries &renderableModels);
206
207 static void prepareModelBoneTextures(const QSSGRenderContextInterface &contextInterface,
208 const RenderableNodeEntries &renderableModels);
209
210 // Helper functions used during PrepareForRender and PrepareAndRender
211 // Updates lights with model receivesShadows. Do not pass globalLights.
212 bool prepareModelsForRender(const RenderableNodeEntries &renderableModels,
213 QSSGLayerRenderPreparationResultFlags &ioFlags,
214 const QSSGCameraRenderData &cameraData,
215 RenderableFilter filter,
216 float lodThreshold = 0.0f);
217 bool prepareParticlesForRender(const RenderableNodeEntries &renderableParticles, const QSSGCameraRenderData &cameraData);
218 bool prepareItem2DsForRender(const QSSGRenderContextInterface &ctxIfc,
219 const RenderableItem2DEntries &renderableItem2Ds);
220
221 void prepareResourceLoaders();
222
223 void prepareForRender();
224 // Helper function used during prepareForRender
225 void prepareReflectionProbesForRender();
226
227 static qsizetype frustumCulling(const QSSGClippingFrustum &clipFrustum, const QSSGRenderableObjectList &renderables, QSSGRenderableObjectList &visibleRenderables);
228 [[nodiscard]] static qsizetype frustumCullingInline(const QSSGClippingFrustum &clipFrustum, QSSGRenderableObjectList &renderables);
229
230
231 // Per-frame cache of renderable objects post-sort (for the MAIN rendering camera, i.e., don't use these lists for rendering from a different camera).
232 const QSSGRenderableObjectList &getSortedOpaqueRenderableObjects();
233 // If layer depth test is false, this may also contain opaque objects.
234 const QSSGRenderableObjectList &getSortedTransparentRenderableObjects();
235 const QSSGRenderableObjectList &getSortedScreenTextureRenderableObjects();
236 const QVector<QSSGBakedLightingModel> &getSortedBakedLightingModels();
237 const RenderableItem2DEntries &getRenderableItem2Ds();
238 const QSSGRenderableObjectList &getSortedRenderedDepthWriteObjects();
239 const QSSGRenderableObjectList &getSortedrenderedOpaqueDepthPrepassObjects();
240
241 void resetForFrame();
242
243 void maybeBakeLightmap();
244
245 QSSGFrameData &getFrameData();
246
247 ShadowMapPass shadowMapPass;
248 ReflectionMapPass reflectionMapPass;
249 ZPrePassPass zPrePassPass;
250 SSAOMapPass ssaoMapPass;
251 DepthMapPass depthMapPass;
252 ScreenMapPass screenMapPass;
253 ScreenReflectionPass reflectionPass;
254 Item2DPass item2DPass;
255 SkyboxPass skyboxPass;
256 SkyboxCubeMapPass skyboxCubeMapPass;
257 static constexpr size_t USERPASSES = 2; // See QSSGRenderLayer::RenderExtensionMode::Count
258 UserPass userPasses[USERPASSES];
259 OpaquePass opaquePass;
260 TransparentPass transparentPass;
261 InfiniteGridPass infiniteGridPass;
262 DebugDrawPass debugDrawPass;
263
264 // Built-in passes
265 QVarLengthArray<QSSGRenderPass *, 16> activePasses;
266
267 QSSGRenderLayer &layer;
268 QSSGRenderer *renderer = nullptr;
269 // List of nodes we can render, not all may be active. Found by doing a depth-first
270 // search through m_FirstChild if length is zero.
271
272 // renderableNodes have all lights, but properties configured for specific node
273 RenderableNodeEntries renderableModels;
274 RenderableNodeEntries renderableParticles;
275 QVector<QSSGRenderItem2D *> renderableItem2Ds;
276 QVector<QSSGRenderCamera *> cameras;
277 QVector<QSSGRenderLight *> lights;
278 QVector<QSSGRenderReflectionProbe *> reflectionProbes;
279
280 // Results of prepare for render.
281 QSSGRenderCamera *camera = nullptr;
282 QSSGShaderLightList globalLights; // All non-scoped lights
283 QSSGRenderableObjectList opaqueObjects;
284 QSSGRenderableObjectList transparentObjects;
285 QSSGRenderableObjectList screenTextureObjects;
286 QVector<QSSGBakedLightingModel> bakedLightingModels;
287 // Sorted lists of the rendered objects. There may be other transforms applied so
288 // it is simplest to duplicate the lists.
289 QSSGRenderableObjectList renderedOpaqueObjects;
290 QSSGRenderableObjectList renderedTransparentObjects;
291 QSSGRenderableObjectList renderedScreenTextureObjects;
292 QSSGRenderableObjectList renderedOpaqueDepthPrepassObjects;
293 QSSGRenderableObjectList renderedDepthWriteObjects;
294 QVector<QSSGBakedLightingModel> renderedBakedLightingModels;
295 RenderableItem2DEntries renderedItem2Ds;
296
297 std::optional<QSSGClippingFrustum> clippingFrustum;
298 std::optional<QSSGLayerRenderPreparationResult> layerPrepResult;
299 std::optional<QSSGCameraRenderData> cameraData;
300
301 TModelContextPtrList modelContexts;
302
303
304 bool tooManyLightsWarningShown = false;
305 bool tooManyShadowLightsWarningShown = false;
306
307 QSSGLightmapper *m_lightmapper = nullptr;
308
309 QSSGShaderFeatures getShaderFeatures() const { return features; }
310 QSSGRhiGraphicsPipelineState getPipelineState() const { return ps; }
311
312 bool interactiveLightmapBakingRequested = false;
313 QSSGLightmapper::Callback lightmapBakingOutputCallback;
314
315 [[nodiscard]] QSSGRenderableNodeEntry getNode(QSSGNodeId id) const;
316 [[nodiscard]] QSSGRenderableNodeEntry takeNode(QSSGNodeId id);
317
318 [[nodiscard]] QSSGRenderGraphObject *getResource(QSSGResourceId id) const;
319
320 [[nodiscard]] QSSGRenderCamera *activeCamera() const { return camera; }
321
322 [[nodiscard]] QSSGCameraRenderData getCameraRenderData(const QSSGRenderCamera *camera);
323 [[nodiscard]] QSSGCameraRenderData getCameraRenderData(const QSSGRenderCamera *camera) const;
324
325 void setLightmapTexture(const QSSGModelContext &modelContext, QRhiTexture *lightmapTexture);
326 [[nodiscard]] QRhiTexture *getLightmapTexture(const QSSGModelContext &modelContext) const;
327
328 void setBonemapTexture(const QSSGModelContext &modelContext, QRhiTexture *bonemapTexture);
329 [[nodiscard]] QRhiTexture *getBonemapTexture(const QSSGModelContext &modelContext) const;
330
331 [[nodiscard]] QSSGRenderContextInterface *contextInterface() const;
332 // Note: temp. API to report the state of the z-prepass step
333 [[nodiscard]] bool isZPrePassActive() const { return zPrePassActive; }
334 void setZPrePassPrepResult(bool res) { zPrePassActive = res; }
335
336
337 // Temp. API. Ideally there shouldn't be a reason for anyone to hold onto these,
338 // but we follow the existing pattern for now.
339 const QSSGRenderShadowMapPtr &requestShadowMapManager();
340 const QSSGRenderReflectionMapPtr &requestReflectionMapManager();
341 const QSSGRenderShadowMapPtr &getShadowMapManager() const { return shadowMapManager; }
342 const QSSGRenderReflectionMapPtr &getReflectionMapManager() const { return reflectionMapManager; }
343
344 static bool prepareInstancing(QSSGRhiContext *rhiCtx,
345 QSSGSubsetRenderable *renderable,
346 const QVector3D &cameraDirection,
347 const QVector3D &cameraPosition,
348 float minThreshold,
349 float maxThreshold);
350
351 [[nodiscard]] QSSGRhiRenderableTexture *getRenderResult(QSSGFrameData::RenderResult id) { return &renderResults[size_t(id)]; }
352 [[nodiscard]] const QSSGRhiRenderableTexture *getRenderResult(QSSGFrameData::RenderResult id) const { return &renderResults[size_t(id)]; }
353
354private:
355 friend class QSSGRenderer;
356 friend class QSSGFrameData;
357 friend class QSSGModelHelpers;
358 friend class QSSGRenderHelpers;
359
360 [[nodiscard]] QSSGCameraRenderData getCachedCameraData();
361 void updateSortedDepthObjectsListImp();
362
363 [[nodiscard]] static QSSGLayerRenderData *getCurrent(const QSSGRenderer &renderer) { return renderer.m_currentLayer; }
364
365 QSSGDefaultMaterialPreparationResult prepareDefaultMaterialForRender(QSSGRenderDefaultMaterial &inMaterial,
366 QSSGRenderableObjectFlags &inExistingFlags,
367 float inOpacity,
368 const QSSGShaderLightListView &lights,
369 QSSGLayerRenderPreparationResultFlags &ioFlags);
370
371 QSSGDefaultMaterialPreparationResult prepareCustomMaterialForRender(QSSGRenderCustomMaterial &inMaterial,
372 QSSGRenderableObjectFlags &inExistingFlags,
373 float inOpacity, bool alreadyDirty,
374 const QSSGShaderLightListView &lights,
375 QSSGLayerRenderPreparationResultFlags &ioFlags);
376
377
378 static void prepareModelMeshesForRenderInternal(const QSSGRenderContextInterface &contextInterface,
379 RenderableNodeEntries &renderableModels,
380 bool globalPickingEnabled);
381
382 QSSGFrameData frameData;
383 QSSGRhiGraphicsPipelineState ps; // Base pipleline state
384 QSSGShaderFeatures features; // Base feature set
385 bool particlesEnabled = true;
386 bool hasDepthWriteObjects = false;
387 bool zPrePassActive = false;
388 enum class DepthPrepassObject : quint8
389 {
390 None = 0x0,
391 ScreenTexture = 0x1,
392 Transparent = 0x2,
393 Opaque = 0x4
394 };
395 using DepthPrepassObjectStateT = std::underlying_type_t<DepthPrepassObject>;
396 DepthPrepassObjectStateT depthPrepassObjectsState { DepthPrepassObjectStateT(DepthPrepassObject::None) };
397 QSSGRenderShadowMapPtr shadowMapManager;
398 QSSGRenderReflectionMapPtr reflectionMapManager;
399 QHash<const QSSGModelContext *, QRhiTexture *> lightmapTextures;
400 QHash<const QSSGModelContext *, QRhiTexture *> bonemapTextures;
401 QSSGRhiRenderableTexture renderResults[3] {};
402};
403
404QT_END_NAMESPACE
405
406#endif // QSSG_LAYER_RENDER_DATA_H
407
408

source code of qtquick3d/src/runtimerender/rendererimpl/qssglayerrenderdata_p.h