blob: 7d16624b31a1f94bea5700310e28cd98f0a445eb [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2008-2012 NVIDIA Corporation.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick 3D.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSSG_RENDERER_IMPL_LAYER_RENDER_PREPARATION_DATA_H
#define QSSG_RENDERER_IMPL_LAYER_RENDER_PREPARATION_DATA_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtQuick3DRuntimeRender/private/qssgrendererimpllayerrenderhelper_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderableobjects_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderclippingfrustum_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderresourcetexture2d_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendergpuprofiler_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendershadowmap_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderableobjects_p.h>
QT_BEGIN_NAMESPACE
struct QSSGLayerRenderData;
class QSSGRendererImpl;
struct QSSGRenderableObject;
enum class QSSGLayerRenderPreparationResultFlag
{
// Was the data in this layer dirty (meaning re-render to texture, possibly)
WasLayerDataDirty = 1,
// Was the data in this layer dirty *or* this layer *or* any effect dirty.
WasDirty = 1 << 1,
// Should create independent viewport
// If we aren't rendering to texture we still may have width/height manipulations
// that require our own viewport.
ShouldCreateIndependentViewport = 1 << 2,
RequiresDepthTexture = 1 << 3,
// SSAO should be done in a separate pass
// Note that having an AO pass necessitates a DepthTexture so this flag should
// never be set without the RequiresDepthTexture flag as well.
RequiresSsaoPass = 1 << 4,
// if some light cause shadow
// we need a separate per light shadow map pass
RequiresShadowMapPass = 1 << 5,
// This is the case when direct rendering, and need to clear an FBO, but not a Window
RequiresTransparentClear = 1 << 6
};
struct QSSGLayerRenderPreparationResultFlags : public QFlags<QSSGLayerRenderPreparationResultFlag>
{
bool wasLayerDataDirty() const
{
return this->operator&(QSSGLayerRenderPreparationResultFlag::WasLayerDataDirty);
}
void setLayerDataDirty(bool inValue)
{
setFlag(QSSGLayerRenderPreparationResultFlag::WasLayerDataDirty, inValue);
}
bool wasDirty() const { return this->operator&(QSSGLayerRenderPreparationResultFlag::WasDirty); }
void setWasDirty(bool inValue) { setFlag(QSSGLayerRenderPreparationResultFlag::WasDirty, inValue); }
bool shouldCreateIndependentViewport() const
{
return this->operator&(QSSGLayerRenderPreparationResultFlag::ShouldCreateIndependentViewport);
}
void setShouldCreateIndependentViewport(bool inValue)
{
setFlag(QSSGLayerRenderPreparationResultFlag::ShouldCreateIndependentViewport, inValue);
}
bool requiresDepthTexture() const
{
return this->operator&(QSSGLayerRenderPreparationResultFlag::RequiresDepthTexture);
}
void setRequiresDepthTexture(bool inValue)
{
setFlag(QSSGLayerRenderPreparationResultFlag::RequiresDepthTexture, inValue);
}
bool requiresSsaoPass() const { return this->operator&(QSSGLayerRenderPreparationResultFlag::RequiresSsaoPass); }
void setRequiresSsaoPass(bool inValue)
{
setFlag(QSSGLayerRenderPreparationResultFlag::RequiresSsaoPass, inValue);
}
bool requiresShadowMapPass() const
{
return this->operator&(QSSGLayerRenderPreparationResultFlag::RequiresShadowMapPass);
}
void setRequiresShadowMapPass(bool inValue)
{
setFlag(QSSGLayerRenderPreparationResultFlag::RequiresShadowMapPass, inValue);
}
bool requiresTransparentClear() const
{
return this->operator&(QSSGLayerRenderPreparationResultFlag::RequiresTransparentClear);
}
void setRequiresTransparentClear(bool inValue)
{
setFlag(QSSGLayerRenderPreparationResultFlag::RequiresTransparentClear, inValue);
}
};
struct QSSGLayerRenderPreparationResult : public QSSGLayerRenderHelper
{
QSSGLayerRenderPreparationResultFlags flags;
quint32 maxAAPassIndex = 0;
QSSGLayerRenderPreparationResult() = default;
QSSGLayerRenderPreparationResult(const QSSGLayerRenderHelper &inHelper)
: QSSGLayerRenderHelper(inHelper)
, maxAAPassIndex(0)
{
}
};
struct QSSGRenderableNodeEntry
{
QSSGRenderNode *node = nullptr;
QSSGNodeLightEntryList lights;
QSSGRenderableNodeEntry() = default;
QSSGRenderableNodeEntry(QSSGRenderNode &inNode) : node(&inNode) {}
};
struct QSSGScopedLightsListScope
{
QVector<QSSGRenderLight *> &lightsList;
QVector<QVector3D> &lightDirList;
qint32 listOriginalSize;
QSSGScopedLightsListScope(QVector<QSSGRenderLight *> &inLights,
QVector<QVector3D> &inDestLightDirList,
QVector<QVector3D> &inSrcLightDirList,
QSSGNodeLightEntryList &inScopedLights)
: lightsList(inLights), lightDirList(inDestLightDirList), listOriginalSize(lightsList.size())
{
auto iter = inScopedLights.begin();
const auto end = inScopedLights.end();
while (iter != end) {
lightsList.push_back(iter->light);
lightDirList.push_back(inSrcLightDirList.at(iter->lightIndex));
++iter;
}
}
~QSSGScopedLightsListScope()
{
lightsList.resize(listOriginalSize);
lightDirList.resize(listOriginalSize);
}
};
struct QSSGDefaultMaterialPreparationResult
{
QSSGRenderableImage *firstImage;
float opacity;
QSSGRenderableObjectFlags renderableFlags;
QSSGShaderDefaultMaterialKey materialKey;
bool dirty;
QSSGDefaultMaterialPreparationResult(QSSGShaderDefaultMaterialKey inMaterialKey);
};
// Data used strictly in the render preparation step.
struct QSSGLayerRenderPreparationData
{
typedef void (*TRenderRenderableFunction)(QSSGLayerRenderData &inData,
QSSGRenderableObject &inObject,
const QVector2D &inCameraProps,
const ShaderFeatureSetList &inShaderFeatures,
quint32 lightIndex,
const QSSGRenderCamera &inCamera);
typedef QHash<QSSGRenderLight *, QSSGRenderNode *> TLightToNodeMap;
typedef QVector<QSSGModelContext *> TModelContextPtrList;
typedef QVector<QSSGRenderableObjectHandle> TRenderableObjectList;
// typedef Pool<SNodeLightEntry, ForwardingAllocator> TNodeLightEntryPoolType;
enum Enum {
MAX_AA_LEVELS = 8,
MAX_TEMPORAL_AA_LEVELS = 2,
};
QSSGRenderLayer &layer;
QSSGRef<QSSGRendererImpl> renderer;
// List of nodes we can render, not all may be active. Found by doing a depth-first
// search through m_FirstChild if length is zero.
// TNodeLightEntryPoolType m_RenderableNodeLightEntryPool;
QVector<QSSGRenderableNodeEntry> renderableNodes;
TLightToNodeMap lightToNodeMap; // map of lights to nodes to cache if we have looked up a
// given scoped light yet.
// Built at the same time as the renderable nodes map.
// these are processed so they are available when the shaders for the models
// are being generated.
QVector<QSSGRenderCamera *> cameras;
QVector<QSSGRenderLight *> lights;
// Results of prepare for render.
QSSGRenderCamera *camera;
QVector<QSSGRenderLight *> globalLights; // Only contains lights that are global.
TRenderableObjectList opaqueObjects;
TRenderableObjectList transparentObjects;
// Sorted lists of the rendered objects. There may be other transforms applied so
// it is simplest to duplicate the lists.
TRenderableObjectList renderedOpaqueObjects;
TRenderableObjectList renderedTransparentObjects;
QMatrix4x4 viewProjection;
QSSGOption<QSSGClippingFrustum> clippingFrustum;
QSSGOption<QSSGLayerRenderPreparationResult> layerPrepResult;
QSSGOption<QVector3D> cameraDirection;
// Scoped lights need a level of indirection into a light direction list. The source light
// directions list is as long as there are lights on the layer. It holds invalid
// information for
// any lights that are not both active and scoped; but the relative position for a given
// light
// in this list is completely constant and immutable; this relative position is saved on a
// structure
// and used when looking up the light direction for a given light.
QVector<QVector3D> sourceLightDirections;
QVector<QVector3D> lightDirections;
TModelContextPtrList modelContexts;
ShaderFeatureSetList features;
bool featuresDirty;
size_t featureSetHash;
bool tooManyLightsError;
// shadow mapps
QSSGRef<QSSGRenderShadowMap> shadowMapManager;
QSSGLayerRenderPreparationData(QSSGRenderLayer &inLayer, const QSSGRef<QSSGRendererImpl> &inRenderer);
virtual ~QSSGLayerRenderPreparationData();
void createShadowMapManager();
static QByteArray cgLightingFeatureName();
QSSGShaderDefaultMaterialKey generateLightingKey(QSSGRenderDefaultMaterial::MaterialLighting inLightingType, bool receivesShadows = true);
void prepareImageForRender(QSSGRenderImage &inImage,
QSSGImageMapTypes inMapType,
QSSGRenderableImage *&ioFirstImage,
QSSGRenderableImage *&ioNextImage,
QSSGRenderableObjectFlags &ioFlags,
QSSGShaderDefaultMaterialKey &ioGeneratedShaderKey,
quint32 inImageIndex);
QSSGDefaultMaterialPreparationResult prepareDefaultMaterialForRender(QSSGRenderDefaultMaterial &inMaterial,
QSSGRenderableObjectFlags &inExistingFlags,
float inOpacity);
QSSGDefaultMaterialPreparationResult prepareCustomMaterialForRender(QSSGRenderCustomMaterial &inMaterial,
QSSGRenderableObjectFlags &inExistingFlags,
float inOpacity, bool alreadyDirty);
bool prepareModelForRender(QSSGRenderModel &inModel,
const QMatrix4x4 &inViewProjection,
const QSSGOption<QSSGClippingFrustum> &inClipFrustum,
QSSGNodeLightEntryList &inScopedLights);
// Helper function used during PRepareForRender and PrepareAndRender
bool prepareRenderablesForRender(const QMatrix4x4 &inViewProjection,
const QSSGOption<QSSGClippingFrustum> &inClipFrustum,
QSSGLayerRenderPreparationResultFlags &ioFlags);
// returns true if this object will render something different than it rendered the last
// time.
virtual void prepareForRender(const QSize &inViewportDimensions);
bool checkLightProbeDirty(QSSGRenderImage &inLightProbe);
void setShaderFeature(const char *inName, bool inValue);
ShaderFeatureSetList getShaderFeatureSet();
size_t getShaderFeatureSetHash();
QVector3D getCameraDirection();
// Per-frame cache of renderable objects post-sort.
const QVector<QSSGRenderableObjectHandle> &getOpaqueRenderableObjects(bool performSort = true);
// If layer depth test is false, this may also contain opaque objects.
const QVector<QSSGRenderableObjectHandle> &getTransparentRenderableObjects();
virtual void resetForFrame();
};
QT_END_NAMESPACE
#endif