summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Määttä <antti.maatta@qt.io>2019-12-17 18:22:59 +0200
committerAntti Määttä <antti.maatta@qt.io>2020-01-13 13:27:28 +0200
commit49fba62dfff3166e44a4b85f99180c27f2bba69e (patch)
treeb7d1d2efb96115e30b44354f0f2e2eaa494aef60
parent9f9c5497ac52b40ef336a0931cbac6068f6035e9 (diff)
Implement ordered group
Add ordered property to group, which disables automatic depth sorting for that group and all it's children. The group as a whole gets sorted with other objects as if it was one object. Task-number: QT3DS-3820 Change-Id: Iea71917fc78f4c543aa944d851c77b6794bd7d80 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r--res/DataModelMetadata/en-us/MetaData.xml2
-rw-r--r--src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp1
-rw-r--r--src/dm/systems/Qt3DSDMComposerTypeDefinitions.h1
-rw-r--r--src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp1
-rw-r--r--src/runtime/Qt3DSAttributeHashes.cpp1
-rw-r--r--src/runtime/Qt3DSAttributeHashes.h1
-rw-r--r--src/runtime/Qt3DSAttributeHashes.txt2
-rw-r--r--src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp4
-rw-r--r--src/runtimerender/Qt3DSRenderUIPLoader.cpp2
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderNode.cpp4
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderNode.h3
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp9
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h23
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp111
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp332
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h7
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp101
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h11
18 files changed, 417 insertions, 199 deletions
diff --git a/res/DataModelMetadata/en-us/MetaData.xml b/res/DataModelMetadata/en-us/MetaData.xml
index e249d22..a4d6d45 100644
--- a/res/DataModelMetadata/en-us/MetaData.xml
+++ b/res/DataModelMetadata/en-us/MetaData.xml
@@ -227,6 +227,8 @@
</Component>
<Group>
+ <!-- Basic Properties -->
+ <Property name="ordered" formalName="Ordered" type="Boolean" default="False" category="Basic Properties" description="The group is ordered. Draw objects in the group order (disables dynamic depth sorting). " />
<!-- Variant Tags -->
<Property name="variants" type="String" animatable="False" category="Variant Tags" />
diff --git a/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp
index c1c0071..c529515 100644
--- a/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp
+++ b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp
@@ -317,6 +317,7 @@ struct DataConstructor<SObjectRefType>
#define QT3DS_WCHAR_T_lightmapshadow L"lightmapshadow"
#define QT3DS_WCHAR_T_controlledproperty L"controlledproperty"
#define QT3DS_WCHAR_T_variants L"variants"
+#define QT3DS_WCHAR_T_ordered L"ordered"
const wchar_t *ComposerObjectTypes::Convert(ComposerObjectTypes::Enum inType)
{
diff --git a/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h
index ce49f07..0e0ada5 100644
--- a/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h
+++ b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h
@@ -243,6 +243,7 @@ class IPropertySystem;
HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"")
#define ITERATE_COMPOSER_GROUP_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(ordered, m_ordered, bool, false) \
HANDLE_COMPOSER_PROPERTY_DUPLICATE(variants, m_variants, TDataStrPtr, L"") \
#define ITERATE_COMPOSER_LIGHT_PROPERTIES \
diff --git a/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp b/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp
index c40dd42..998fedb 100644
--- a/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp
+++ b/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp
@@ -493,6 +493,7 @@ struct SRuntimePropertyParser
#define Node_LocalOpacity ATTRIBUTE_OPACITY
#define Node_RotationOrder ATTRIBUTE_ROTATIONORDER
#define Node_LeftHanded ATTRIBUTE_ORIENTATION
+#define Group_ordered ATTRIBUTE_ORDERED
#define Layer_TemporalAAEnabled ATTRIBUTE_TEMPORALAA
#define Layer_LayerEnableDepthTest ATTRIBUTE_DISABLEDEPTHTEST
#define Layer_LayerEnableDepthPrePass ATTRIBUTE_DISABLEDEPTHPREPASS
diff --git a/src/runtime/Qt3DSAttributeHashes.cpp b/src/runtime/Qt3DSAttributeHashes.cpp
index 9d248b7..da74931 100644
--- a/src/runtime/Qt3DSAttributeHashes.cpp
+++ b/src/runtime/Qt3DSAttributeHashes.cpp
@@ -285,6 +285,7 @@ const char *GetAttributeString(const EAttribute inAttribute)
case ATTRIBUTE_LIFETIME: return "lifetime";
case ATTRIBUTE_CONTROLLEDPROPERTY: return "controlledproperty";
case ATTRIBUTE_OBSERVEDPROPERTY: return "observedproperty";
+ case ATTRIBUTE_ORDERED: return "ordered";
case ATTRIBUTE_QT_IO: return "qt.io";
default: {
static char s_UnknownHash[16];
diff --git a/src/runtime/Qt3DSAttributeHashes.h b/src/runtime/Qt3DSAttributeHashes.h
index 3f53541..f8f7bec 100644
--- a/src/runtime/Qt3DSAttributeHashes.h
+++ b/src/runtime/Qt3DSAttributeHashes.h
@@ -276,6 +276,7 @@ enum EAttribute {
ATTRIBUTE_LIFETIME = 0x0033D297, // lifetime
ATTRIBUTE_CONTROLLEDPROPERTY = 0x022C0A1D, // controlledproperty
ATTRIBUTE_OBSERVEDPROPERTY = 0x02D1CE03, // observedproperty
+ ATTRIBUTE_ORDERED = 0x038AEAD3, // ordered
ATTRIBUTE_QT_IO = 0x010EF2CF, // qt.io
}; // enum EAttribute
diff --git a/src/runtime/Qt3DSAttributeHashes.txt b/src/runtime/Qt3DSAttributeHashes.txt
index b8e2a7f..21b9646 100644
--- a/src/runtime/Qt3DSAttributeHashes.txt
+++ b/src/runtime/Qt3DSAttributeHashes.txt
@@ -249,3 +249,5 @@ lifetime
controlledproperty
observedproperty
+
+ordered
diff --git a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp
index 51e3d70..462cca8 100644
--- a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp
+++ b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp
@@ -447,9 +447,11 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
<< " = getTransformedUVCoords( environment_map_reflection, uTransform, "
"vTransform );"
<< Endl;
- if (image.m_Image.m_TextureData.m_TextureFlags.IsInvertUVCoords())
+
+ if (image.m_Image.m_TextureData.m_TextureFlags.IsInvertUVCoords()) {
fragmentShader << " " << m_ImageFragCoords << ".y = 1.0 - " << m_ImageFragCoords
<< ".y;" << Endl;
+ }
}
}
diff --git a/src/runtimerender/Qt3DSRenderUIPLoader.cpp b/src/runtimerender/Qt3DSRenderUIPLoader.cpp
index df02e78..9433b50 100644
--- a/src/runtimerender/Qt3DSRenderUIPLoader.cpp
+++ b/src/runtimerender/Qt3DSRenderUIPLoader.cpp
@@ -716,6 +716,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
#define Node_LocalOpacity "opacity"
#define Node_RotationOrder "rotationorder"
#define Node_LeftHanded "orientation"
+#define Group_ordered "ordered"
#define Layer_Variants "variants"
#define Layer_TemporalAAEnabled "temporalaa"
#define Layer_LayerEnableDepthTest "disabledepthtest"
@@ -928,6 +929,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
inItem.m_Flags.SetActive(eyeball);
ITERATE_QT3DS_RENDER_NODE_PROPERTIES
ParseProperty(inParser, "boneid", inItem.m_SkeletonId);
+ ParseProperty(inParser, "ordered", inItem.m_ordered);
bool ignoreParent = false;
if (ParseProperty(inParser, "ignoresparent", ignoreParent))
inItem.m_Flags.SetIgnoreParentTransform(ignoreParent);
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderNode.cpp b/src/runtimerender/graphobjects/Qt3DSRenderNode.cpp
index bf47bb8..9d42aa5 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderNode.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderNode.cpp
@@ -47,11 +47,13 @@ SNode::SNode(GraphObjectTypes::Enum inGraphObjectType)
, m_LocalOpacity(1.0f)
, m_GlobalOpacity(1.0f)
, m_SkeletonId(-1)
+ , m_ordered(false)
, m_Parent(NULL)
, m_NextSibling(NULL)
, m_PreviousSibling(NULL)
, m_FirstChild(NULL)
, m_DFSIndex(0)
+ , m_GroupIndex(0)
{
m_Flags.SetDirty(true);
m_Flags.SetTransformDirty(true);
@@ -72,11 +74,13 @@ SNode::SNode(const SNode &inCloningObject, NVAllocatorCallback &inAllocator)
, m_GlobalTransform(inCloningObject.m_GlobalTransform)
, m_GlobalOpacity(inCloningObject.m_GlobalOpacity)
, m_SkeletonId(inCloningObject.m_SkeletonId)
+ , m_ordered(inCloningObject.m_ordered)
, m_Parent(NULL)
, m_NextSibling(NULL)
, m_PreviousSibling(NULL)
, m_FirstChild(NULL)
, m_DFSIndex(0)
+ , m_GroupIndex(0)
{
m_Flags.SetDirty(true);
m_Flags.SetTransformDirty(true);
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderNode.h b/src/runtimerender/graphobjects/Qt3DSRenderNode.h
index 87a1500..751ed27 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderNode.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderNode.h
@@ -201,6 +201,7 @@ namespace render {
QT3DSMat44 m_GlobalTransform;
QT3DSF32 m_GlobalOpacity;
QT3DSI32 m_SkeletonId;
+ bool m_ordered;
// node graph members.
SNode *m_Parent;
@@ -210,6 +211,8 @@ namespace render {
// Property maintained solely by the render system.
// Depth-first-search index assigned and maintained by render system.
QT3DSU32 m_DFSIndex;
+ // Index to the group of the node
+ QT3DSU32 m_GroupIndex;
SNode(GraphObjectTypes::Enum inType = GraphObjectTypes::Node);
SNode(const SNode &inCloningObject, NVAllocatorCallback &inAllocator);
diff --git a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
index 712214a..2705b18 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
@@ -600,5 +600,14 @@ namespace render {
theRenderContext, m_Generator.GetLayerGlobalRenderProperties(),
TShaderFeatureSet());
}
+
+ void SOrderedGroupRenderable::update()
+ {
+ QT3DSVec3 sum(0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < m_renderables.size(); i++)
+ sum += m_renderables[i]->m_WorldCenterPoint;
+ sum *= 1.0f / m_renderables.size();
+ m_WorldCenterPoint = sum;
+ }
}
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h
index abc8143..12533c4 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h
@@ -63,6 +63,7 @@ namespace render {
ShadowCaster = 1 << 10,
DistanceField = 1 << 11,
HasAlphaTest = 1 << 12,
+ OrderedGroup = 1 << 13,
};
};
@@ -167,6 +168,14 @@ namespace render {
{
return *this & RenderPreparationResultFlagValues::HasAlphaTest;
}
+ bool isOrderedGroup() const
+ {
+ return *this & RenderPreparationResultFlagValues::OrderedGroup;
+ }
+ void setOrderedGroup(bool ordered)
+ {
+ ClearOrSet(ordered, RenderPreparationResultFlagValues::OrderedGroup);
+ }
};
struct SNodeLightEntry
@@ -480,6 +489,20 @@ namespace render {
void RenderShadowMapPass(const QT3DSVec2 &inCameraVec, const SLight *inLight,
const SCamera &inCamera, SShadowMapEntry *inShadowMapEntry);
};
+
+ struct SOrderedGroupRenderable : public SRenderableObject
+ {
+ SOrderedGroupRenderable(SRenderableObjectFlags inFlags, const QT3DSVec3 &inWorldCenterPt,
+ const QT3DSMat44 &inGlobalTransform, const NVBounds3 &inBounds,
+ NVAllocatorCallback &allocator)
+ : SRenderableObject(inFlags, inWorldCenterPt, inGlobalTransform, inBounds)
+ , m_renderables(allocator, "SOrderedGroupRenderable::m_renderables")
+ {
+ m_RenderableFlags.setOrderedGroup(true);
+ }
+ void update();
+ nvvector<SRenderableObject *> m_renderables;
+ };
}
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
index a0ea8b1..0484390 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
@@ -1405,61 +1405,72 @@ namespace render {
}
void Qt3DSRendererImpl::GetLayerHitObjectList(SLayerRenderData &inLayerRenderData,
- const QT3DSVec2 &inViewportDimensions,
- const QT3DSVec2 &inPresCoords, bool inPickEverything,
- TPickResultArray &outIntersectionResult,
- NVAllocatorCallback &inTempAllocator)
+ const QT3DSVec2 &inViewportDimensions,
+ const QT3DSVec2 &inPresCoords,
+ bool inPickEverything,
+ TPickResultArray &outIntersectionResult,
+ NVAllocatorCallback &inTempAllocator)
{
// This function assumes the layer was rendered to the scene itself. There is another
- // function
- // for completely offscreen layers that don't get rendered to the scene.
+ // function for completely offscreen layers that don't get rendered to the scene.
bool wasRenderToTarget(inLayerRenderData.m_Layer.m_Flags.IsLayerRenderToTarget());
- if (wasRenderToTarget && inLayerRenderData.m_Camera != nullptr) {
- Option<SRay> theHitRay;
- if (inLayerRenderData.m_LayerPrepResult.hasValue()) {
- theHitRay = inLayerRenderData.m_LayerPrepResult->GetPickRay(
- inPresCoords, inViewportDimensions, false, m_Context->isSceneCameraView());
- }
- if (inLayerRenderData.m_LastFrameOffscreenRenderer.mPtr == nullptr) {
- if (theHitRay.hasValue()) {
- // Scale the mouse coords to change them into the camera's numerical space.
- SRay thePickRay = *theHitRay;
- for (QT3DSU32 idx = inLayerRenderData.m_OpaqueObjects.size(), end = 0; idx > end;
- --idx) {
- SRenderableObject *theRenderableObject =
- inLayerRenderData.m_OpaqueObjects[idx - 1];
- if (inPickEverything
- || theRenderableObject->m_RenderableFlags.GetPickable())
- IntersectRayWithSubsetRenderable(thePickRay, *theRenderableObject,
- outIntersectionResult,
- inTempAllocator);
- }
- for (QT3DSU32 idx = inLayerRenderData.m_TransparentObjects.size(), end = 0;
- idx > end; --idx) {
- SRenderableObject *theRenderableObject =
- inLayerRenderData.m_TransparentObjects[idx - 1];
- if (inPickEverything
- || theRenderableObject->m_RenderableFlags.GetPickable())
- IntersectRayWithSubsetRenderable(thePickRay, *theRenderableObject,
- outIntersectionResult,
- inTempAllocator);
- }
+ if (!wasRenderToTarget || !inLayerRenderData.m_Camera)
+ return;
+
+ Option<SRay> theHitRay;
+ if (inLayerRenderData.m_LayerPrepResult.hasValue()) {
+ theHitRay = inLayerRenderData.m_LayerPrepResult->GetPickRay(
+ inPresCoords, inViewportDimensions, false, m_Context->isSceneCameraView());
+ }
+ if (inLayerRenderData.m_LastFrameOffscreenRenderer.mPtr) {
+ IGraphObjectPickQuery *theQuery =
+ inLayerRenderData.m_LastFrameOffscreenRenderer->GetGraphObjectPickQuery(this);
+ if (theQuery) {
+ Qt3DSRenderPickResult theResult =
+ theQuery->Pick(inPresCoords, inViewportDimensions, inPickEverything);
+ if (theResult.m_HitObject) {
+ theResult.m_OffscreenRenderer =
+ inLayerRenderData.m_LastFrameOffscreenRenderer;
+ outIntersectionResult.push_back(theResult);
}
} else {
- IGraphObjectPickQuery *theQuery =
- inLayerRenderData.m_LastFrameOffscreenRenderer->GetGraphObjectPickQuery(this);
- if (theQuery) {
- Qt3DSRenderPickResult theResult =
- theQuery->Pick(inPresCoords, inViewportDimensions, inPickEverything);
- if (theResult.m_HitObject) {
- theResult.m_OffscreenRenderer =
- inLayerRenderData.m_LastFrameOffscreenRenderer;
- outIntersectionResult.push_back(theResult);
- }
- } else
- inLayerRenderData.m_LastFrameOffscreenRenderer->Pick(inPresCoords,
- inViewportDimensions,
- this);
+ inLayerRenderData.m_LastFrameOffscreenRenderer->Pick(inPresCoords,
+ inViewportDimensions,
+ this);
+ }
+ return;
+ }
+ if (!theHitRay.hasValue())
+ return;
+ // Scale the mouse coords to change them into the camera's coordinate space.
+ SRay thePickRay = *theHitRay;
+ for (QT3DSU32 idx = inLayerRenderData.m_OpaqueObjects.size(), end = 0; idx > end; --idx) {
+ SRenderableObject *theRenderableObject = inLayerRenderData.m_OpaqueObjects[idx - 1];
+ if (inPickEverything || theRenderableObject->m_RenderableFlags.GetPickable()) {
+ IntersectRayWithSubsetRenderable(thePickRay, *theRenderableObject,
+ outIntersectionResult,
+ inTempAllocator);
+ }
+ }
+ for (QT3DSU32 idx = inLayerRenderData.m_GroupObjects.size(), end = 0; idx > end; --idx) {
+ SRenderableObject *object = inLayerRenderData.m_GroupObjects[idx - 1];
+ SOrderedGroupRenderable &group(static_cast<SOrderedGroupRenderable &>(*object));
+ Q_ASSERT(object->m_RenderableFlags.isOrderedGroup());
+ for (int i = 0; i < group.m_renderables.size(); ++i) {
+ if (inPickEverything || group.m_renderables[i]->m_RenderableFlags.GetPickable()) {
+ IntersectRayWithSubsetRenderable(thePickRay, *group.m_renderables[i],
+ outIntersectionResult,
+ inTempAllocator);
+ }
+ }
+ }
+ for (QT3DSU32 idx = inLayerRenderData.m_TransparentObjects.size(), end = 0;
+ idx > end; --idx) {
+ SRenderableObject *renderableObject = inLayerRenderData.m_TransparentObjects[idx - 1];
+ if (inPickEverything || renderableObject->m_RenderableFlags.GetPickable()) {
+ IntersectRayWithSubsetRenderable(thePickRay, *renderableObject,
+ outIntersectionResult,
+ inTempAllocator);
}
}
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
index 9c92bda..c43ed1a 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
@@ -674,8 +674,9 @@ namespace render {
return;
// Check if we have anything to render
- if ((m_OpaqueObjects.size() == 0 && GetTransparentRenderableObjects().size() == 0)
- || m_Lights.size() == 0) {
+ if ((m_OpaqueObjects.empty() && GetTransparentRenderableObjects().size() == 0
+ && m_GroupObjects.empty())
+ || m_Lights.empty()) {
return;
}
@@ -832,7 +833,7 @@ namespace render {
// Avoid running this method if possible.
if ((inEnableTransparentDepthWrite == false
- && ((m_OpaqueObjects.size() == 0 && m_TransparentObjects.size() == 0)
+ && ((m_GroupObjects.empty() && m_OpaqueObjects.empty() && m_TransparentObjects.empty())
|| m_Layer.m_Flags.IsLayerEnableDepthPrepass() == false))
|| m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
return;
@@ -895,79 +896,156 @@ namespace render {
}
}
- void SLayerRenderData::renderTransparentObjectsPass(
- TRenderRenderableFunction inRenderFn, bool inEnableBlending,
- bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
- const SCamera &inCamera, CResourceFrameBuffer *theFB)
- {
- NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
- NVRenderContext &theRenderContext(m_Renderer.GetContext());
- QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
- if (inEnableBlending || m_Layer.m_Flags.IsLayerEnableDepthTest() == false) {
- theRenderContext.SetBlendingEnabled(true && inEnableBlending);
+void SLayerRenderData::renderOrderedGroup(
+ SRenderableObject &theObject, TRenderRenderableFunction inRenderFn, bool inEnableBlending,
+ bool inEnableDepthWrite, bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB)
+{
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ SOrderedGroupRenderable &group(static_cast<SOrderedGroupRenderable &>(theObject));
+ const bool opaqueDepthTest = m_Layer.m_Flags.IsLayerEnableDepthTest();
+ const bool opaqueDepthWrite = opaqueDepthTest && inEnableDepthWrite;
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
+ for (int i = 0; i < group.m_renderables.size(); ++i) {
+ SRenderableObject &object(*group.m_renderables[i]);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ SScopedLightsListScope lightsScope(m_Lights, m_LightDirections,
+ m_SourceLightDirections,
+ object.m_ScopedLights);
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ // SW fallback for advanced blend modes.
+ // Renders transparent objects to a separate FBO and blends them in shader
+ // with the opaque items and background.
+ DefaultMaterialBlendMode::Enum blendMode
+ = DefaultMaterialBlendMode::Enum::Normal;
+ if (theObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
+ blendMode = static_cast<SSubsetRenderable &>(theObject).getBlendingMode();
+ bool useBlendFallback
+ = (blendMode == DefaultMaterialBlendMode::Overlay
+ || blendMode == DefaultMaterialBlendMode::ColorBurn
+ || blendMode == DefaultMaterialBlendMode::ColorDodge)
+ && !theRenderContext.IsAdvancedBlendHwSupported()
+ && !theRenderContext.IsAdvancedBlendHwSupportedKHR() && m_LayerPrepassDepthTexture;
+ if (useBlendFallback)
+ SetupDrawFB(true);
+#endif
+ if (object.m_RenderableFlags.hasAlphaTest()) {
+ theRenderContext.SetBlendingEnabled(false);
+ theRenderContext.SetDepthWriteEnabled(opaqueDepthWrite);
+ m_Renderer.setAlphaTest(true, 1.0f, -1.0f + (1.0f / 255.0f));
+ inRenderFn(*this, object, theCameraProps, GetShaderFeatureSet(), indexLight,
+ inCamera);
+ theRenderContext.SetBlendingEnabled(inEnableBlending);
theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
-
- // Assume all objects have transparency if the layer's depth test enabled flag is true.
- if (m_Layer.m_Flags.IsLayerEnableDepthTest() == true) {
- for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
- SRenderableObject &theObject(*theTransparentObjects[idx]);
- if (!(theObject.m_RenderableFlags.IsCompletelyTransparent())) {
+ m_Renderer.setAlphaTest(true, -1.0f, 1.0f);
+ inRenderFn(*this, object, theCameraProps, GetShaderFeatureSet(), indexLight,
+ inCamera);
+ m_Renderer.setAlphaTest(false, 1.0, 1.0);
+ } else {
+ const bool transparency
+ = object.m_RenderableFlags.HasTransparency() && inEnableBlending;
+ theRenderContext.SetBlendingEnabled(transparency);
+ theRenderContext.SetDepthWriteEnabled((!transparency && opaqueDepthWrite)
+ || inEnableTransparentDepthWrite);
+ inRenderFn(*this, object, theCameraProps, GetShaderFeatureSet(), indexLight,
+ inCamera);
+ }
#ifdef ADVANCED_BLEND_SW_FALLBACK
- // SW fallback for advanced blend modes.
- // Renders transparent objects to a separate FBO and blends them in shader
- // with the opaque items and background.
- DefaultMaterialBlendMode::Enum blendMode
- = DefaultMaterialBlendMode::Enum::Normal;
- if (theObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
- blendMode = static_cast<SSubsetRenderable &>(theObject).getBlendingMode();
- bool useBlendFallback = (blendMode == DefaultMaterialBlendMode::Overlay ||
- blendMode == DefaultMaterialBlendMode::ColorBurn ||
- blendMode == DefaultMaterialBlendMode::ColorDodge) &&
- !theRenderContext.IsAdvancedBlendHwSupported() &&
- !theRenderContext.IsAdvancedBlendHwSupportedKHR() &&
- m_LayerPrepassDepthTexture;
- if (useBlendFallback)
- SetupDrawFB(true);
+ // SW fallback for advanced blend modes.
+ // Continue blending after transparent objects have been rendered to a FBO
+ if (useBlendFallback) {
+ BlendAdvancedToFB(blendMode, true, theFB);
+ // restore blending status
+ theRenderContext.SetBlendingEnabled(inEnableBlending);
+ // restore depth test status
+ theRenderContext.SetDepthTestEnabled(
+ m_Layer.m_Flags.IsLayerEnableDepthTest());
+ theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
+ }
#endif
- SScopedLightsListScope lightsScope(m_Lights, m_LightDirections,
- m_SourceLightDirections,
- theObject.m_ScopedLights);
- SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ }
+}
- inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(),
- indexLight, inCamera);
+void SLayerRenderData::renderTransparentObjectsPass(
+ TRenderRenderableFunction inRenderFn, bool inEnableBlending, bool inEnableDepthWrite,
+ bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB)
+{
+ NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
+ if (inEnableBlending || m_Layer.m_Flags.IsLayerEnableDepthTest() == false) {
+ theRenderContext.SetBlendingEnabled(true && inEnableBlending);
+ theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
+
+ // Assume all objects have transparency if the layer's depth test enabled flag is true.
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest()) {
+ for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theTransparentObjects[idx]);
+ if (!(theObject.m_RenderableFlags.IsCompletelyTransparent())) {
#ifdef ADVANCED_BLEND_SW_FALLBACK
- // SW fallback for advanced blend modes.
- // Continue blending after transparent objects have been rendered to a FBO
- if (useBlendFallback) {
- BlendAdvancedToFB(blendMode, true, theFB);
- // restore blending status
- theRenderContext.SetBlendingEnabled(inEnableBlending);
- // restore depth test status
- theRenderContext.SetDepthTestEnabled(
- m_Layer.m_Flags.IsLayerEnableDepthTest());
- theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
- }
+ // SW fallback for advanced blend modes.
+ // Renders transparent objects to a separate FBO and blends them in shader
+ // with the opaque items and background.
+ DefaultMaterialBlendMode::Enum blendMode
+ = DefaultMaterialBlendMode::Enum::Normal;
+ if (theObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
+ blendMode = static_cast<SSubsetRenderable &>(theObject).getBlendingMode();
+ bool useBlendFallback
+ = (blendMode == DefaultMaterialBlendMode::Overlay
+ || blendMode == DefaultMaterialBlendMode::ColorBurn
+ || blendMode == DefaultMaterialBlendMode::ColorDodge)
+ && !theRenderContext.IsAdvancedBlendHwSupported()
+ && !theRenderContext.IsAdvancedBlendHwSupportedKHR()
+ && m_LayerPrepassDepthTexture;
+ if (useBlendFallback)
+ SetupDrawFB(true);
#endif
+ SScopedLightsListScope lightsScope(m_Lights, m_LightDirections,
+ m_SourceLightDirections,
+ theObject.m_ScopedLights);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+
+ inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(),
+ indexLight, inCamera);
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ // SW fallback for advanced blend modes.
+ // Continue blending after transparent objects have been rendered to a FBO
+ if (useBlendFallback) {
+ BlendAdvancedToFB(blendMode, true, theFB);
+ // restore blending status
+ theRenderContext.SetBlendingEnabled(inEnableBlending);
+ // restore depth test status
+ theRenderContext.SetDepthTestEnabled(
+ m_Layer.m_Flags.IsLayerEnableDepthTest());
+ theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
}
+#endif
}
}
- // If the layer doesn't have depth enabled then we have to render via an alternate route
- // where the transparent objects vector could have both opaque and transparent objects.
- else {
- for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
- SRenderableObject &theObject(*theTransparentObjects[idx]);
- if (!(theObject.m_RenderableFlags.IsCompletelyTransparent())) {
+ }
+ // If the layer doesn't have depth enabled then we have to render via an alternate route
+ // where the transparent objects vector could have both opaque and transparent objects.
+ else {
+ for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theTransparentObjects[idx]);
+ if (!(theObject.m_RenderableFlags.IsCompletelyTransparent())) {
+ if (theObject.m_RenderableFlags.isOrderedGroup()) {
+ renderOrderedGroup(theObject, inRenderFn, inEnableBlending,
+ inEnableDepthWrite, inEnableTransparentDepthWrite,
+ indexLight, inCamera, theFB);
+ } else {
#ifdef ADVANCED_BLEND_SW_FALLBACK
DefaultMaterialBlendMode::Enum blendMode
= DefaultMaterialBlendMode::Enum::Normal;
if (theObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
blendMode = static_cast<SSubsetRenderable &>(theObject).getBlendingMode();
- bool useBlendFallback = (blendMode == DefaultMaterialBlendMode::Overlay ||
- blendMode == DefaultMaterialBlendMode::ColorBurn ||
- blendMode == DefaultMaterialBlendMode::ColorDodge) &&
- !theRenderContext.IsAdvancedBlendHwSupported() &&
- !theRenderContext.IsAdvancedBlendHwSupportedKHR();
+ bool useBlendFallback
+ = (blendMode == DefaultMaterialBlendMode::Overlay
+ || blendMode == DefaultMaterialBlendMode::ColorBurn
+ || blendMode == DefaultMaterialBlendMode::ColorDodge)
+ && !theRenderContext.IsAdvancedBlendHwSupported()
+ && !theRenderContext.IsAdvancedBlendHwSupportedKHR();
if (theObject.m_RenderableFlags.HasTransparency()) {
theRenderContext.SetBlendingEnabled(true && inEnableBlending);
@@ -996,76 +1074,83 @@ namespace render {
}
}
}
- };
-
- void SLayerRenderData::RunRenderPass(TRenderRenderableFunction inRenderFn,
- bool inEnableBlending, bool inEnableDepthWrite,
- bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
- const SCamera &inCamera, CResourceFrameBuffer *theFB)
+ }
+};
+
+void SLayerRenderData::RunRenderPass(TRenderRenderableFunction inRenderFn,
+ bool inEnableBlending, bool inEnableDepthWrite,
+ bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB)
+{
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ theRenderContext.SetDepthFunction(qt3ds::render::NVRenderBoolOp::LessThanOrEqual);
+ theRenderContext.SetBlendingEnabled(false);
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
{
- NVRenderContext &theRenderContext(m_Renderer.GetContext());
- theRenderContext.SetDepthFunction(qt3ds::render::NVRenderBoolOp::LessThanOrEqual);
- theRenderContext.SetBlendingEnabled(false);
- QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
- {
- QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "LayerRenderData: Render opaque")
- NVDataRef<SRenderableObject *> theOpaqueObjects = GetOpaqueRenderableObjects();
+ QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
+ "LayerRenderData: Render opaque")
+ NVDataRef<SRenderableObject *> theOpaqueObjects = GetOpaqueRenderableObjects();
- if (m_Layer.m_Flags.IsLayerEnableDepthTest()) {
- theRenderContext.SetDepthTestEnabled(true);
- theRenderContext.SetDepthWriteEnabled(inEnableDepthWrite);
- } else {
- theRenderContext.SetDepthWriteEnabled(false);
- theRenderContext.SetDepthTestEnabled(false);
- }
+ const bool opaqueDepthTest = m_Layer.m_Flags.IsLayerEnableDepthTest();
+ const bool opaqueDepthWrite = opaqueDepthTest && inEnableDepthWrite;
- for (QT3DSU32 idx = 0, end = theOpaqueObjects.size(); idx < end; ++idx) {
- SRenderableObject &theObject(*theOpaqueObjects[idx]);
- SScopedLightsListScope lightsScope(m_Lights, m_LightDirections, m_SourceLightDirections,
- theObject.m_ScopedLights);
- SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
- inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(), indexLight,
- inCamera);
- }
- }
- {
- QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "LayerRenderData: Render transparent pass1")
+ theRenderContext.SetDepthTestEnabled(opaqueDepthTest);
+ theRenderContext.SetDepthWriteEnabled(opaqueDepthWrite);
- NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
- // Also draw opaque parts of transparent objects
- m_Renderer.setAlphaTest(true, 1.0f, -1.0f + (1.0f / 255.0f));
- for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
- SRenderableObject &theObject(*theTransparentObjects[idx]);
+ for (QT3DSU32 idx = 0, end = theOpaqueObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theOpaqueObjects[idx]);
+
+ if (theObject.m_RenderableFlags.isOrderedGroup()) {
+ renderOrderedGroup(theObject, inRenderFn, inEnableBlending, inEnableDepthWrite,
+ inEnableTransparentDepthWrite, indexLight, inCamera, theFB);
+ } else {
+ theRenderContext.SetBlendingEnabled(false);
+ theRenderContext.SetDepthWriteEnabled(opaqueDepthWrite);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
SScopedLightsListScope lightsScope(m_Lights, m_LightDirections, m_SourceLightDirections,
theObject.m_ScopedLights);
- SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(), indexLight,
inCamera);
}
}
+ }
+ {
+ QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
+ "LayerRenderData: Render transparent pass1")
- {
- QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "LayerRenderData: Render transparent pass2")
- m_Renderer.setAlphaTest(true, -1.0f, 1.0f);
- // transparent parts of transparent objects
- // does not render objects without alpha test enabled so
- // we need another pass without alpha test
- renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableTransparentDepthWrite,
- indexLight, inCamera, theFB);
- }
- {
- QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "LayerRenderData: Render transparent pass3")
- m_Renderer.setAlphaTest(false, 1.0, 1.0);
- // transparent objects without alpha test
- renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableTransparentDepthWrite,
- indexLight, inCamera, theFB);
+ NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
+ // Also draw opaque parts of transparent objects
+ m_Renderer.setAlphaTest(true, 1.0f, -1.0f + (1.0f / 255.0f));
+ for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theTransparentObjects[idx]);
+ SScopedLightsListScope lightsScope(m_Lights, m_LightDirections, m_SourceLightDirections,
+ theObject.m_ScopedLights);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(), indexLight,
+ inCamera);
}
}
+ {
+ QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
+ "LayerRenderData: Render transparent pass2")
+ m_Renderer.setAlphaTest(true, -1.0f, 1.0f);
+ // transparent parts of transparent objects
+ // does not render objects without alpha test enabled so
+ // we need another pass without alpha test
+ renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableTransparentDepthWrite,
+ inEnableDepthWrite, indexLight, inCamera, theFB);
+ }
+ {
+ QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
+ "LayerRenderData: Render transparent pass3")
+ m_Renderer.setAlphaTest(false, 1.0, 1.0);
+ // transparent objects without alpha test
+ renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableTransparentDepthWrite,
+ inEnableDepthWrite, indexLight, inCamera, theFB);
+ }
+}
+
void SLayerRenderData::Render(CResourceFrameBuffer *theFB)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
@@ -1546,7 +1631,8 @@ namespace render {
// to that frame buffer.
theFB.EnsureFrameBuffer();
- bool hasDepthObjects = m_OpaqueObjects.size() > 0 || m_TransparentObjects.size() > 0;
+ bool hasDepthObjects = m_OpaqueObjects.size() > 0 || m_TransparentObjects.size() > 0
+ || m_GroupObjects.size() > 0;
bool requiresDepthStencilBuffer =
hasDepthObjects || thePrepResult.m_Flags.RequiresStencilBuffer();
NVRenderRect theNewViewport(0, 0, theLayerTextureDimensions.width(),
@@ -1834,13 +1920,13 @@ namespace render {
void SLayerRenderData::RunnableRenderToViewport(qt3ds::render::NVRenderFrameBuffer *theFB)
{
// If we have an effect, an opaque object, or any transparent objects that aren't completely
- // transparent
- // or an offscreen renderer or a layer widget texture
+ // transparent or an offscreen renderer or a layer widget texture
// Then we can't possible affect the resulting render target.
- bool needsToRender = m_Layer.m_FirstEffect != NULL || m_OpaqueObjects.empty() == false
+ bool needsToRender = m_Layer.m_FirstEffect || !m_OpaqueObjects.empty()
|| AnyCompletelyNonTransparentObjects(m_TransparentObjects) || GetOffscreenRenderer()
|| m_LayerWidgetTexture || m_BoundingRectColor.hasValue()
- || m_Layer.m_Background == LayerBackground::Color;
+ || m_Layer.m_Background == LayerBackground::Color
+ || !m_GroupObjects.empty();
if (needsToRender == false)
return;
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
index 0f0a838..aa4d456 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
@@ -125,6 +125,10 @@ struct AdvancedBlendModes
void Render(CResourceFrameBuffer *theFB = NULL);
void ResetForFrame() override;
+ void renderOrderedGroup(SRenderableObject &theObject, TRenderRenderableFunction inRenderFn,
+ bool inEnableBlending, bool inEnableDepthWrite,
+ bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB);
void CreateGpuProfiler();
void StartProfiling(CRegisteredString &nameID, bool sync);
@@ -179,7 +183,8 @@ struct AdvancedBlendModes
CResourceFrameBuffer *theFB);
#endif
void renderTransparentObjectsPass(TRenderRenderableFunction inRenderFn,
- bool inEnableBlending, bool inEnableTransparentDepthWrite,
+ bool inEnableBlending, bool inEnableDepthWrite,
+ bool inEnableTransparentDepthWrite,
QT3DSU32 indexLight, const SCamera &inCamera,
CResourceFrameBuffer *theFB);
};
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
index 45839e0..b6cd2a0 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
@@ -72,18 +72,29 @@ namespace render {
namespace {
void MaybeQueueNodeForRender(SNode &inNode, nvvector<SRenderableNodeEntry> &outRenderables,
- nvvector<SNode *> &outCamerasAndLights, QT3DSU32 &ioDFSIndex)
+ nvvector<SRenderableNodeEntry> &outGroups,
+ nvvector<SNode *> &outCamerasAndLights, QT3DSU32 &ioDFSIndex,
+ QT3DSU32 groupNode = 0)
{
++ioDFSIndex;
inNode.m_DFSIndex = ioDFSIndex;
- if (GraphObjectTypes::IsRenderableType(inNode.m_Type))
+ inNode.m_GroupIndex = groupNode;
+ if (GraphObjectTypes::IsRenderableType(inNode.m_Type)) {
outRenderables.push_back(inNode);
- else if (GraphObjectTypes::IsLightCameraType(inNode.m_Type))
+ } else if (GraphObjectTypes::IsLightCameraType(inNode.m_Type)) {
outCamerasAndLights.push_back(&inNode);
+ } else if (GraphObjectTypes::IsNodeType(inNode.m_Type) && inNode.m_ordered
+ && !groupNode) {
+ outGroups.push_back(inNode);
+ groupNode = outGroups.size();
+ inNode.m_GroupIndex = groupNode;
+ }
for (SNode *theChild = inNode.m_FirstChild; theChild != NULL;
- theChild = theChild->m_NextSibling)
- MaybeQueueNodeForRender(*theChild, outRenderables, outCamerasAndLights, ioDFSIndex);
+ theChild = theChild->m_NextSibling) {
+ MaybeQueueNodeForRender(*theChild, outRenderables, outGroups, outCamerasAndLights,
+ ioDFSIndex, groupNode);
+ }
}
bool HasValidLightProbe(SImage *inLightProbeImage)
@@ -113,6 +124,8 @@ namespace render {
"SLayerRenderPreparationData::m_RenderableNodes"))
, m_RenderableNodes(inRenderer.GetContext().GetAllocator(),
"SLayerRenderPreparationData::m_RenderableNodes")
+ , m_GroupNodes(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_GroupNodes")
, m_LightToNodeMap(inRenderer.GetContext().GetAllocator(),
"SLayerRenderPreparationData::m_LightToNodeMap")
, m_CamerasAndLights(inRenderer.GetContext().GetAllocator(),
@@ -123,6 +136,8 @@ namespace render {
"SLayerRenderPreparationData::m_OpaqueObjects")
, m_TransparentObjects(inRenderer.GetContext().GetAllocator(),
"SLayerRenderPreparationData::m_TransparentObjects")
+ , m_GroupObjects(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_GroupObjects")
, m_RenderedOpaqueObjects(inRenderer.GetContext().GetAllocator(),
"SLayerRenderPreparationData::m_RenderedOpaqueObjects")
, m_RenderedTransparentObjects(inRenderer.GetContext().GetAllocator(),
@@ -246,10 +261,18 @@ namespace render {
{
if (m_RenderedOpaqueObjects.empty() == false || m_Camera == NULL)
return m_RenderedOpaqueObjects;
- if (m_Layer.m_Flags.IsLayerEnableDepthTest() && m_OpaqueObjects.empty() == false) {
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest()
+ && (!m_OpaqueObjects.empty() || !m_GroupObjects.empty())) {
QT3DSVec3 theCameraDirection(GetCameraDirection());
QT3DSVec3 theCameraPosition = m_Camera->GetGlobalPos();
m_RenderedOpaqueObjects.assign(m_OpaqueObjects.begin(), m_OpaqueObjects.end());
+ m_RenderedOpaqueObjects.insert(m_RenderedOpaqueObjects.end(), m_GroupObjects.begin(),
+ m_GroupObjects.end());
+
+ // Set position for group objects
+ for (int i = 0; i < m_GroupObjects.size(); i++)
+ static_cast<SOrderedGroupRenderable *>(m_GroupObjects[i])->update();
+
// Setup the object's sorting information
for (QT3DSU32 idx = 0, end = m_RenderedOpaqueObjects.size(); idx < end; ++idx) {
SRenderableObject &theInfo = *m_RenderedOpaqueObjects[idx];
@@ -274,9 +297,12 @@ namespace render {
m_RenderedTransparentObjects.assign(m_TransparentObjects.begin(),
m_TransparentObjects.end());
- if (m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
+ if (!m_Layer.m_Flags.IsLayerEnableDepthTest()) {
m_RenderedTransparentObjects.insert(m_RenderedTransparentObjects.end(),
m_OpaqueObjects.begin(), m_OpaqueObjects.end());
+ m_RenderedTransparentObjects.insert(m_RenderedTransparentObjects.end(),
+ m_GroupObjects.begin(), m_GroupObjects.end());
+ }
if (m_RenderedTransparentObjects.empty() == false) {
QT3DSVec3 theCameraDirection(GetCameraDirection());
@@ -365,7 +391,8 @@ namespace render {
bool SLayerRenderPreparationData::PrepareTextForRender(
SText &inText, const QT3DSMat44 &inViewProjection,
- QT3DSF32 inTextScaleFactor, SLayerRenderPreparationResultFlags &ioFlags)
+ QT3DSF32 inTextScaleFactor, SLayerRenderPreparationResultFlags &ioFlags,
+ qt3ds::render::SOrderedGroupRenderable *group)
{
ITextTextureCache *theTextRenderer = m_Renderer.GetQt3DSContext().GetTextureCache();
if (theTextRenderer == nullptr && !IQt3DSRenderContextCore::distanceFieldEnabled())
@@ -424,8 +451,12 @@ namespace render {
// After preparation, do not push object back to queue if it is not
// active, because we prepare text elements regardless of their
// visibility (=active status).
- if (inText.m_Flags.IsGloballyActive())
- m_TransparentObjects.push_back(theRenderable);
+ if (inText.m_Flags.IsGloballyActive()) {
+ if (group)
+ group->m_renderables.push_back(theRenderable);
+ else
+ m_TransparentObjects.push_back(theRenderable);
+ }
}
return retval;
}
@@ -459,7 +490,8 @@ namespace render {
bool SLayerRenderPreparationData::PreparePathForRender(
SPath &inPath, const QT3DSMat44 &inViewProjection,
- const Option<SClippingFrustum> &inClipFrustum, SLayerRenderPreparationResultFlags &ioFlags)
+ const Option<SClippingFrustum> &inClipFrustum, SLayerRenderPreparationResultFlags &ioFlags,
+ SOrderedGroupRenderable *group)
{
SRenderableObjectFlags theSharedFlags;
theSharedFlags.SetPickable(true);
@@ -882,7 +914,8 @@ namespace render {
bool SLayerRenderPreparationData::PrepareModelForRender(
SModel &inModel, const QT3DSMat44 &inViewProjection,
- const Option<SClippingFrustum> &inClipFrustum, TNodeLightEntryList &inScopedLights)
+ const Option<SClippingFrustum> &inClipFrustum, TNodeLightEntryList &inScopedLights,
+ SOrderedGroupRenderable *group)
{
IQt3DSRenderContext &qt3dsContext(m_Renderer.GetQt3DSContext());
IBufferManager &bufferManager = qt3dsContext.GetBufferManager();
@@ -1039,11 +1072,15 @@ namespace render {
// set tessellation
theRenderableObject->m_TessellationMode = inModel.m_TessellationMode;
- if (theRenderableObject->m_RenderableFlags.HasTransparency()
- || theRenderableObject->m_RenderableFlags.HasRefraction()) {
- m_TransparentObjects.push_back(theRenderableObject);
+ if (group) {
+ group->m_renderables.push_back(theRenderableObject);
} else {
- m_OpaqueObjects.push_back(theRenderableObject);
+ if (theRenderableObject->m_RenderableFlags.HasTransparency()
+ || theRenderableObject->m_RenderableFlags.HasRefraction()) {
+ m_TransparentObjects.push_back(theRenderableObject);
+ } else {
+ m_OpaqueObjects.push_back(theRenderableObject);
+ }
}
}
}
@@ -1063,17 +1100,36 @@ namespace render {
bool hasTextRenderer
= m_Renderer.GetQt3DSContext().getDistanceFieldRenderer() != nullptr
|| m_Renderer.GetQt3DSContext().GetTextRenderer() != nullptr;
+ for (QT3DSU32 idx = 0, end = m_GroupNodes.size(); idx < end; ++idx) {
+ SRenderableNodeEntry &theNodeEntry(m_GroupNodes[idx]);
+ SRenderableObjectFlags flags;
+ QT3DSVec3 inWorldCenterPt;
+ QT3DSMat44 inGlobalTransform;
+ NVBounds3 inBounds;
+ SOrderedGroupRenderable *renderable
+ = RENDER_FRAME_NEW(SOrderedGroupRenderable)(
+ flags, inWorldCenterPt, inGlobalTransform, inBounds,
+ m_Renderer.GetPerFrameAllocator());
+ m_GroupObjects.push_back(renderable);
+ }
+
for (QT3DSU32 idx = 0, end = m_RenderableNodes.size(); idx < end; ++idx) {
SRenderableNodeEntry &theNodeEntry(m_RenderableNodes[idx]);
SNode *theNode = theNodeEntry.m_Node;
wasDataDirty = wasDataDirty || theNode->m_Flags.IsDirty();
+ SOrderedGroupRenderable *group = nullptr;
+ if (theNode->m_GroupIndex) {
+ group = static_cast<SOrderedGroupRenderable *>(
+ m_GroupObjects[theNode->m_GroupIndex - 1]);
+ }
+
switch (theNode->m_Type) {
case GraphObjectTypes::Model: {
SModel *theModel = static_cast<SModel *>(theNode);
theModel->CalculateGlobalVariables();
if (theModel->m_Flags.IsGloballyActive()) {
bool wasModelDirty = PrepareModelForRender(
- *theModel, inViewProjection, inClipFrustum, theNodeEntry.m_Lights);
+ *theModel, inViewProjection, inClipFrustum, theNodeEntry.m_Lights, group);
wasDataDirty = wasDataDirty || wasModelDirty;
}
} break;
@@ -1086,7 +1142,7 @@ namespace render {
// large delay for distance field text items becoming active
// mid-animation.
bool wasTextDirty = PrepareTextForRender(*theText, inViewProjection,
- theTextScaleFactor, ioFlags);
+ theTextScaleFactor, ioFlags, group);
wasDataDirty = wasDataDirty || wasTextDirty;
}
@@ -1096,7 +1152,8 @@ namespace render {
thePath->CalculateGlobalVariables();
if (thePath->m_Flags.IsGloballyActive()) {
bool wasPathDirty =
- PreparePathForRender(*thePath, inViewProjection, inClipFrustum, ioFlags);
+ PreparePathForRender(*thePath, inViewProjection, inClipFrustum, ioFlags,
+ group);
wasDataDirty = wasDataDirty || wasPathDirty;
}
} break;
@@ -1293,11 +1350,12 @@ namespace render {
// Push nodes in reverse depth first order
if (m_RenderableNodes.empty()) {
m_CamerasAndLights.clear();
+ m_GroupNodes.clear();
QT3DSU32 dfsIndex = 0;
for (SNode *theChild = m_Layer.m_FirstChild; theChild;
theChild = theChild->m_NextSibling)
- MaybeQueueNodeForRender(*theChild, m_RenderableNodes, m_CamerasAndLights,
- dfsIndex);
+ MaybeQueueNodeForRender(*theChild, m_RenderableNodes, m_GroupNodes,
+ m_CamerasAndLights, dfsIndex);
reverse(m_CamerasAndLights.begin(), m_CamerasAndLights.end());
reverse(m_RenderableNodes.begin(), m_RenderableNodes.end());
m_LightToNodeMap.clear();
@@ -1523,6 +1581,7 @@ namespace render {
{
m_TransparentObjects.clear_unsafe();
m_OpaqueObjects.clear_unsafe();
+ m_GroupObjects.clear_unsafe();
m_LayerPrepResult.setEmpty();
// The check for if the camera is or is not null is used
// to figure out if this layer was rendered at all.
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h
index eae29f6..53b60f2 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h
@@ -253,6 +253,7 @@ namespace render {
TNodeLightEntryPoolType m_RenderableNodeLightEntryPool;
nvvector<SRenderableNodeEntry> m_RenderableNodes;
+ nvvector<SRenderableNodeEntry> m_GroupNodes;
TLightToNodeMap m_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.
@@ -265,6 +266,7 @@ namespace render {
nvvector<SLight *> m_Lights; // Only contains lights that are global.
TRenderableObjectList m_OpaqueObjects;
TRenderableObjectList m_TransparentObjects;
+ TRenderableObjectList m_GroupObjects;
// Sorted lists of the rendered objects. There may be other transforms applied so
// it is simplest to duplicate the lists.
TRenderableObjectList m_RenderedOpaqueObjects;
@@ -323,14 +325,17 @@ namespace render {
bool PrepareModelForRender(SModel &inModel, const QT3DSMat44 &inViewProjection,
const Option<SClippingFrustum> &inClipFrustum,
- TNodeLightEntryList &inScopedLights);
+ TNodeLightEntryList &inScopedLights,
+ SOrderedGroupRenderable *group);
bool PrepareTextForRender(SText &inText, const QT3DSMat44 &inViewProjection,
QT3DSF32 inTextScaleFactor,
- SLayerRenderPreparationResultFlags &ioFlags);
+ SLayerRenderPreparationResultFlags &ioFlags,
+ SOrderedGroupRenderable *group);
bool PreparePathForRender(SPath &inPath, const QT3DSMat44 &inViewProjection,
const Option<SClippingFrustum> &inClipFrustum,
- SLayerRenderPreparationResultFlags &ioFlags);
+ SLayerRenderPreparationResultFlags &ioFlags,
+ SOrderedGroupRenderable *group);
// Helper function used during PRepareForRender and PrepareAndRender
bool PrepareRenderablesForRender(const QT3DSMat44 &inViewProjection,
const Option<SClippingFrustum> &inClipFrustum,