1 /****************************************************************************
2 **
3 ** Copyright (C) 2008-2012 NVIDIA Corporation.
4 ** Copyright (C) 2019 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of Qt Quick 3D.
8 **
9 ** $QT_BEGIN_LICENSE:GPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 or (at your option) any later version
21 ** approved by the KDE Free Qt Foundation. The licenses are as published by
22 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30 
31 #ifndef QSSG_RENDERER_IMPL_LAYER_RENDER_PREPARATION_DATA_H
32 #define QSSG_RENDERER_IMPL_LAYER_RENDER_PREPARATION_DATA_H
33 
34 //
35 //  W A R N I N G
36 //  -------------
37 //
38 // This file is not part of the Qt API.  It exists purely as an
39 // implementation detail.  This header file may change from version to
40 // version without notice, or even be removed.
41 //
42 // We mean it.
43 //
44 
45 #include <QtQuick3DRuntimeRender/private/qssgrendererimpllayerrenderhelper_p.h>
46 #include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h>
47 #include <QtQuick3DRuntimeRender/private/qssgrenderableobjects_p.h>
48 #include <QtQuick3DRuntimeRender/private/qssgrenderclippingfrustum_p.h>
49 #include <QtQuick3DRuntimeRender/private/qssgrenderresourcetexture2d_p.h>
50 #include <QtQuick3DRuntimeRender/private/qssgrendergpuprofiler_p.h>
51 #include <QtQuick3DRuntimeRender/private/qssgrendershadowmap_p.h>
52 #include <QtQuick3DRuntimeRender/private/qssgrenderableobjects_p.h>
53 
54 #include <QtQuick3DRuntimeRender/private/qssgrenderitem2d_p.h>
55 
56 #define QSSG_RENDER_MINIMUM_RENDER_OPACITY .01f
57 
58 QT_BEGIN_NAMESPACE
59 struct QSSGLayerRenderData;
60 class QSSGRendererImpl;
61 struct QSSGRenderableObject;
62 
63 enum class QSSGLayerRenderPreparationResultFlag
64 {
65     // Was the data in this layer dirty (meaning re-render to texture, possibly)
66     WasLayerDataDirty = 1,
67     // Was the data in this layer dirty *or* this layer *or* any effect dirty.
68     WasDirty = 1 << 1,
69 
70     // Should create independent viewport
71     // If we aren't rendering to texture we still may have width/height manipulations
72     // that require our own viewport.
73     ShouldCreateIndependentViewport = 1 << 2,
74 
75     RequiresDepthTexture = 1 << 3,
76 
77     // SSAO should be done in a separate pass
78     // Note that having an AO pass necessitates a DepthTexture so this flag should
79     // never be set without the RequiresDepthTexture flag as well.
80     RequiresSsaoPass = 1 << 4,
81 
82     // if some light cause shadow
83     // we need a separate per light shadow map pass
84     RequiresShadowMapPass = 1 << 5,
85 
86     // This is the case when direct rendering, and need to clear an FBO, but not a Window
87     RequiresTransparentClear = 1 << 6
88 };
89 
90 struct QSSGLayerRenderPreparationResultFlags : public QFlags<QSSGLayerRenderPreparationResultFlag>
91 {
wasLayerDataDirtyQSSGLayerRenderPreparationResultFlags92     bool wasLayerDataDirty() const
93     {
94         return this->operator&(QSSGLayerRenderPreparationResultFlag::WasLayerDataDirty);
95     }
setLayerDataDirtyQSSGLayerRenderPreparationResultFlags96     void setLayerDataDirty(bool inValue)
97     {
98         setFlag(QSSGLayerRenderPreparationResultFlag::WasLayerDataDirty, inValue);
99     }
100 
wasDirtyQSSGLayerRenderPreparationResultFlags101     bool wasDirty() const { return this->operator&(QSSGLayerRenderPreparationResultFlag::WasDirty); }
setWasDirtyQSSGLayerRenderPreparationResultFlags102     void setWasDirty(bool inValue) { setFlag(QSSGLayerRenderPreparationResultFlag::WasDirty, inValue); }
103 
shouldCreateIndependentViewportQSSGLayerRenderPreparationResultFlags104     bool shouldCreateIndependentViewport() const
105     {
106         return this->operator&(QSSGLayerRenderPreparationResultFlag::ShouldCreateIndependentViewport);
107     }
setShouldCreateIndependentViewportQSSGLayerRenderPreparationResultFlags108     void setShouldCreateIndependentViewport(bool inValue)
109     {
110         setFlag(QSSGLayerRenderPreparationResultFlag::ShouldCreateIndependentViewport, inValue);
111     }
112 
requiresDepthTextureQSSGLayerRenderPreparationResultFlags113     bool requiresDepthTexture() const
114     {
115         return this->operator&(QSSGLayerRenderPreparationResultFlag::RequiresDepthTexture);
116     }
setRequiresDepthTextureQSSGLayerRenderPreparationResultFlags117     void setRequiresDepthTexture(bool inValue)
118     {
119         setFlag(QSSGLayerRenderPreparationResultFlag::RequiresDepthTexture, inValue);
120     }
121 
requiresSsaoPassQSSGLayerRenderPreparationResultFlags122     bool requiresSsaoPass() const { return this->operator&(QSSGLayerRenderPreparationResultFlag::RequiresSsaoPass); }
setRequiresSsaoPassQSSGLayerRenderPreparationResultFlags123     void setRequiresSsaoPass(bool inValue)
124     {
125         setFlag(QSSGLayerRenderPreparationResultFlag::RequiresSsaoPass, inValue);
126     }
127 
requiresShadowMapPassQSSGLayerRenderPreparationResultFlags128     bool requiresShadowMapPass() const
129     {
130         return this->operator&(QSSGLayerRenderPreparationResultFlag::RequiresShadowMapPass);
131     }
setRequiresShadowMapPassQSSGLayerRenderPreparationResultFlags132     void setRequiresShadowMapPass(bool inValue)
133     {
134         setFlag(QSSGLayerRenderPreparationResultFlag::RequiresShadowMapPass, inValue);
135     }
136 
requiresTransparentClearQSSGLayerRenderPreparationResultFlags137     bool requiresTransparentClear() const
138     {
139         return this->operator&(QSSGLayerRenderPreparationResultFlag::RequiresTransparentClear);
140     }
141 
setRequiresTransparentClearQSSGLayerRenderPreparationResultFlags142     void setRequiresTransparentClear(bool inValue)
143     {
144         setFlag(QSSGLayerRenderPreparationResultFlag::RequiresTransparentClear, inValue);
145     }
146 
147 };
148 
149 struct QSSGLayerRenderPreparationResult : public QSSGLayerRenderHelper
150 {
151     QSSGRenderEffect *lastEffect = nullptr;
152     QSSGLayerRenderPreparationResultFlags flags;
153     quint32 maxAAPassIndex = 0;
154     QSSGLayerRenderPreparationResult() = default;
QSSGLayerRenderPreparationResultQSSGLayerRenderPreparationResult155     QSSGLayerRenderPreparationResult(const QSSGLayerRenderHelper &inHelper)
156         : QSSGLayerRenderHelper(inHelper), lastEffect(nullptr), maxAAPassIndex(0)
157     {
158     }
159 };
160 
161 struct QSSGRenderableNodeEntry
162 {
163     QSSGRenderNode *node = nullptr;
164     QSSGNodeLightEntryList lights;
165     QSSGRenderableNodeEntry() = default;
QSSGRenderableNodeEntryQSSGRenderableNodeEntry166     QSSGRenderableNodeEntry(QSSGRenderNode &inNode) : node(&inNode) {}
167 };
168 
169 struct QSSGScopedLightsListScope
170 {
171     QVector<QSSGRenderLight *> &lightsList;
172     QVector<QVector3D> &lightDirList;
173     qint32 listOriginalSize;
QSSGScopedLightsListScopeQSSGScopedLightsListScope174     QSSGScopedLightsListScope(QVector<QSSGRenderLight *> &inLights,
175                                 QVector<QVector3D> &inDestLightDirList,
176                                 QVector<QVector3D> &inSrcLightDirList,
177                                 QSSGNodeLightEntryList &inScopedLights)
178         : lightsList(inLights), lightDirList(inDestLightDirList), listOriginalSize(lightsList.size())
179     {
180         auto iter = inScopedLights.begin();
181         const auto end = inScopedLights.end();
182         while (iter != end) {
183             lightsList.push_back(iter->light);
184             lightDirList.push_back(inSrcLightDirList.at(iter->lightIndex));
185             ++iter;
186         }
187     }
~QSSGScopedLightsListScopeQSSGScopedLightsListScope188     ~QSSGScopedLightsListScope()
189     {
190         lightsList.resize(listOriginalSize);
191         lightDirList.resize(listOriginalSize);
192     }
193 };
194 
195 struct QSSGDefaultMaterialPreparationResult
196 {
197     QSSGRenderableImage *firstImage;
198     float opacity;
199     QSSGRenderableObjectFlags renderableFlags;
200     QSSGShaderDefaultMaterialKey materialKey;
201     bool dirty;
202 
203     QSSGDefaultMaterialPreparationResult(QSSGShaderDefaultMaterialKey inMaterialKey);
204 };
205 
206 // Data used strictly in the render preparation step.
207 struct QSSGLayerRenderPreparationData
208 {
209     typedef void (*TRenderRenderableFunction)(QSSGLayerRenderData &inData,
210                                               QSSGRenderableObject &inObject,
211                                               const QVector2D &inCameraProps,
212                                               const ShaderFeatureSetList &inShaderFeatures,
213                                               quint32 lightIndex,
214                                               const QSSGRenderCamera &inCamera);
215     typedef QHash<QSSGRenderLight *, QSSGRenderNode *> TLightToNodeMap;
216     typedef QVector<QSSGModelContext *> TModelContextPtrList;
217     typedef QVector<QSSGRenderableObjectHandle> TRenderableObjectList;
218 
219     // typedef Pool<SNodeLightEntry, ForwardingAllocator> TNodeLightEntryPoolType;
220 
221     enum Enum {
222         MAX_AA_LEVELS = 8,
223         MAX_TEMPORAL_AA_LEVELS = 2,
224     };
225 
226     QSSGRenderLayer &layer;
227     QSSGRef<QSSGRendererImpl> renderer;
228     // List of nodes we can render, not all may be active.  Found by doing a depth-first
229     // search through m_FirstChild if length is zero.
230 
231     // TNodeLightEntryPoolType m_RenderableNodeLightEntryPool;
232     QVector<QSSGRenderableNodeEntry> renderableNodes;
233     QVector<QSSGRenderableNodeEntry> renderableItem2Ds;
234     QVector<QSSGRenderableNodeEntry> renderedItem2Ds;
235     TLightToNodeMap lightToNodeMap; // map of lights to nodes to cache if we have looked up a
236     // given scoped light yet.
237     // Built at the same time as the renderable nodes map.
238     // these are processed so they are available when the shaders for the models
239     // are being generated.
240     QVector<QSSGRenderCamera *> cameras;
241     QVector<QSSGRenderLight *> lights;
242 
243     // Results of prepare for render.
244     QSSGRenderCamera *camera;
245     QVector<QSSGRenderLight *> globalLights; // Only contains lights that are global.
246     TRenderableObjectList opaqueObjects;
247     TRenderableObjectList transparentObjects;
248     // Sorted lists of the rendered objects.  There may be other transforms applied so
249     // it is simplest to duplicate the lists.
250     TRenderableObjectList renderedOpaqueObjects;
251     TRenderableObjectList renderedTransparentObjects;
252     QMatrix4x4 viewProjection;
253     QSSGOption<QSSGClippingFrustum> clippingFrustum;
254     QSSGOption<QSSGLayerRenderPreparationResult> layerPrepResult;
255     QSSGOption<QVector3D> cameraDirection;
256     // Scoped lights need a level of indirection into a light direction list.  The source light
257     // directions list is as long as there are lights on the layer.  It holds invalid
258     // information for
259     // any lights that are not both active and scoped; but the relative position for a given
260     // light
261     // in this list is completely constant and immutable; this relative position is saved on a
262     // structure
263     // and used when looking up the light direction for a given light.
264     QVector<QVector3D> sourceLightDirections;
265     QVector<QVector3D> lightDirections;
266     TModelContextPtrList modelContexts;
267 
268     ShaderFeatureSetList features;
269     bool featuresDirty;
270     size_t featureSetHash;
271     bool tooManyLightsError;
272 
273     // shadow mapps
274     QSSGRef<QSSGRenderShadowMap> shadowMapManager;
275 
276     QSSGLayerRenderPreparationData(QSSGRenderLayer &inLayer, const QSSGRef<QSSGRendererImpl> &inRenderer);
277     virtual ~QSSGLayerRenderPreparationData();
278     void createShadowMapManager();
279 
280     static QByteArray cgLightingFeatureName();
281 
282     QSSGShaderDefaultMaterialKey generateLightingKey(QSSGRenderDefaultMaterial::MaterialLighting inLightingType, bool receivesShadows = true);
283 
284     void prepareImageForRender(QSSGRenderImage &inImage,
285                                QSSGImageMapTypes inMapType,
286                                QSSGRenderableImage *&ioFirstImage,
287                                QSSGRenderableImage *&ioNextImage,
288                                QSSGRenderableObjectFlags &ioFlags,
289                                QSSGShaderDefaultMaterialKey &ioGeneratedShaderKey,
290                                quint32 inImageIndex, QSSGRenderDefaultMaterial *inMaterial = nullptr);
291 
292     void setVertexInputPresence(const QSSGRenderableObjectFlags &renderableFlags,
293                                 QSSGShaderDefaultMaterialKey &key);
294 
295     QSSGDefaultMaterialPreparationResult prepareDefaultMaterialForRender(QSSGRenderDefaultMaterial &inMaterial,
296                                                                            QSSGRenderableObjectFlags &inExistingFlags,
297                                                                            float inOpacity);
298 
299     QSSGDefaultMaterialPreparationResult prepareCustomMaterialForRender(QSSGRenderCustomMaterial &inMaterial,
300                                                                           QSSGRenderableObjectFlags &inExistingFlags,
301                                                                           float inOpacity, bool alreadyDirty);
302 
303     bool prepareModelForRender(QSSGRenderModel &inModel,
304                                const QMatrix4x4 &inViewProjection,
305                                const QSSGOption<QSSGClippingFrustum> &inClipFrustum,
306                                QSSGNodeLightEntryList &inScopedLights);
307 
308     // Helper function used during PRepareForRender and PrepareAndRender
309     bool prepareRenderablesForRender(const QMatrix4x4 &inViewProjection,
310                                      const QSSGOption<QSSGClippingFrustum> &inClipFrustum,
311                                      QSSGLayerRenderPreparationResultFlags &ioFlags);
312 
313     // returns true if this object will render something different than it rendered the last
314     // time.
315     virtual void prepareForRender(const QSize &inViewportDimensions);
316     bool checkLightProbeDirty(QSSGRenderImage &inLightProbe);
317     void setShaderFeature(const char *inName, bool inValue);
318     ShaderFeatureSetList getShaderFeatureSet();
319     size_t getShaderFeatureSetHash();
320 
321     QVector3D getCameraDirection();
322     // Per-frame cache of renderable objects post-sort.
323     const QVector<QSSGRenderableObjectHandle> &getOpaqueRenderableObjects(bool performSort = true);
324     // If layer depth test is false, this may also contain opaque objects.
325     const QVector<QSSGRenderableObjectHandle> &getTransparentRenderableObjects();
326     const QVector<QSSGRenderableNodeEntry> &getRenderableItem2Ds();
327 
328     virtual void resetForFrame();
329 };
330 QT_END_NAMESPACE
331 #endif
332