summaryrefslogtreecommitdiffstats
path: root/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp')
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp406
1 files changed, 338 insertions, 68 deletions
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
index df60f64..c8c287c 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(),
@@ -140,6 +155,7 @@ namespace render {
, m_FeaturesDirty(true)
, m_FeatureSetHash(0)
, m_TooManyLightsError(false)
+ , m_StereoMode(StereoModes::Mono)
{
}
@@ -246,10 +262,12 @@ 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());
+
// Setup the object's sorting information
for (QT3DSU32 idx = 0, end = m_RenderedOpaqueObjects.size(); idx < end; ++idx) {
SRenderableObject &theInfo = *m_RenderedOpaqueObjects[idx];
@@ -273,10 +291,19 @@ namespace render {
m_RenderedTransparentObjects.assign(m_TransparentObjects.begin(),
m_TransparentObjects.end());
+ m_RenderedTransparentObjects.insert(m_RenderedTransparentObjects.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();
- if (m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest() == false) {
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());
@@ -287,7 +314,11 @@ namespace render {
SRenderableObject &theInfo = *m_RenderedTransparentObjects[idx];
QT3DSVec3 difference = theInfo.m_WorldCenterPoint - theCameraPosition;
theInfo.m_CameraDistanceSq = difference.dot(theCameraDirection);
+
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
+ theInfo.m_RenderableFlags.setAlphaTest(0);
}
+
ForwardingAllocator alloc(m_Renderer.GetPerFrameAllocator(), "SortAllocations");
// render furthest to nearest.
eastl::merge_sort(m_RenderedTransparentObjects.begin(),
@@ -365,7 +396,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 +456,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 +495,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);
@@ -603,7 +640,10 @@ namespace render {
IOffscreenRenderManager &theOffscreenRenderManager(
qt3dsContext.GetOffscreenRenderManager());
IRenderPluginManager &theRenderPluginManager(qt3dsContext.GetRenderPluginManager());
- if (inImage.ClearDirty(bufferManager, theOffscreenRenderManager, theRenderPluginManager))
+ if (inImage.ClearDirty(bufferManager, theOffscreenRenderManager, theRenderPluginManager,
+ m_Layer.m_Scene->m_Presentation->m_preferKTX,
+ inImage.m_MappingMode == ImageMappingModes::LightProbe,
+ m_Layer.m_Scene->m_Presentation->m_flipCompressedTextures))
ioFlags |= RenderPreparationResultFlagValues::Dirty;
// All objects with offscreen renderers are pickable so we can pass the pick through to the
@@ -790,7 +830,8 @@ namespace render {
// Enable alpha test, but only if the whole object opacity is full
// so parts of the object might be fully opaque
if (renderableFlags & RenderPreparationResultFlagValues::HasTransparency
- && subsetOpacity >= 1.0f && transparencyImagesHaveOpaquePixels) {
+ && subsetOpacity >= 1.0f && transparencyImagesHaveOpaquePixels
+ && theMaterial->m_BlendMode != DefaultMaterialBlendMode::Screen) {
m_Renderer.DefaultMaterialShaderKeyProperties()
.m_AlphaTestEnabled.SetValue(theGeneratedKey, true);
renderableFlags.setAlphaTest(true);
@@ -825,7 +866,10 @@ namespace render {
// If the custom material uses subpresentations, those have to be rendered before
// the custom material itself
- m_Renderer.GetQt3DSContext().GetCustomMaterialSystem().renderSubpresentations(inMaterial);
+ if (m_Renderer.GetQt3DSContext().GetCustomMaterialSystem()
+ .renderSubpresentations(inMaterial)) {
+ retval.m_Dirty = true;
+ }
// set wireframe mode
m_Renderer.DefaultMaterialShaderKeyProperties().m_WireframeMode.SetValue(
@@ -862,17 +906,17 @@ namespace render {
CHECK_IMAGE_AND_PREPARE(inMaterial.m_Lightmaps.m_LightmapShadow,
ImageMapTypes::LightmapShadow,
SShaderDefaultMaterialKeyProperties::LightmapShadow);
- if (inMaterial.m_imageMaps && inMaterial.m_imageMaps->size() > 0) {
- auto iter = inMaterial.m_imageMaps->begin();
- auto end = inMaterial.m_imageMaps->end();
+ if (inMaterial.m_images.size() > 0) {
+ auto iter = inMaterial.m_images.begin();
+ auto end = inMaterial.m_images.end();
for (; iter != end; iter++) {
- CHECK_IMAGE_AND_PREPARE(iter->second,
+ CHECK_IMAGE_AND_PREPARE(*iter,
ImageMapTypes::Unknown,
SShaderDefaultMaterialKeyProperties::ImageMapCount);
}
}
#undef CHECK_IMAGE_AND_PREPARE
-
+ retval.m_Dirty |= renderableFlags.IsDirty();
retval.m_FirstImage = firstImage;
if (retval.m_Dirty || alreadyDirty)
m_Renderer.addMaterialDirtyClear(&inMaterial);
@@ -881,7 +925,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();
@@ -1011,6 +1056,7 @@ namespace render {
subsetOpacity, subsetDirty));
SShaderDefaultMaterialKey theGeneratedKey = theMaterialPrepResult.m_MaterialKey;
subsetOpacity = theMaterialPrepResult.m_Opacity;
+ subsetDirty |= theMaterialPrepResult.m_Dirty;
SRenderableImage *firstImage(theMaterialPrepResult.m_FirstImage);
renderableFlags = theMaterialPrepResult.m_RenderableFlags;
@@ -1037,12 +1083,26 @@ namespace render {
theRenderableObject->m_ScopedLights = inScopedLights;
// set tessellation
theRenderableObject->m_TessellationMode = inModel.m_TessellationMode;
-
- if (theRenderableObject->m_RenderableFlags.HasTransparency()
- || theRenderableObject->m_RenderableFlags.HasRefraction()) {
- m_TransparentObjects.push_back(theRenderableObject);
+ bool transparentObject = theRenderableObject->m_RenderableFlags.HasTransparency()
+ || theRenderableObject->m_RenderableFlags.HasRefraction();
+ bool alphaTestObject = theRenderableObject->m_RenderableFlags.hasAlphaTest();
+
+ // Only put transparent object into ordered group if depth test is on
+ // Put object into both lists if it is alpha-test object
+ // object must have transparency on if it is alpha-test object
+ if (group && (!m_Layer.m_Flags.IsLayerEnableDepthTest() || transparentObject)) {
+ group->m_renderables.push_back(theRenderableObject);
+ if (alphaTestObject)
+ m_OpaqueObjects.push_back(theRenderableObject);
} else {
- m_OpaqueObjects.push_back(theRenderableObject);
+ if (transparentObject && alphaTestObject) {
+ m_TransparentObjects.push_back(theRenderableObject);
+ m_OpaqueObjects.push_back(theRenderableObject);
+ } else if (transparentObject) {
+ m_TransparentObjects.push_back(theRenderableObject);
+ } else {
+ m_OpaqueObjects.push_back(theRenderableObject);
+ }
}
}
}
@@ -1055,24 +1115,43 @@ namespace render {
QT3DSF32 inTextScaleFactor, SLayerRenderPreparationResultFlags &ioFlags)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::PrepareRenderablesForRender")
+ "LayerRenderData: PrepareRenderablesForRender")
m_ViewProjection = inViewProjection;
QT3DSF32 theTextScaleFactor = inTextScaleFactor;
bool wasDataDirty = false;
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;
@@ -1085,7 +1164,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;
}
@@ -1095,7 +1174,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;
@@ -1112,7 +1192,9 @@ namespace render {
IQt3DSRenderContext &theContext(m_Renderer.GetQt3DSContext());
return inLightProbe.ClearDirty(theContext.GetBufferManager(),
theContext.GetOffscreenRenderManager(),
- theContext.GetRenderPluginManager(), true);
+ theContext.GetRenderPluginManager(),
+ m_Layer.m_Scene->m_Presentation->m_preferKTX, true,
+ m_Layer.m_Scene->m_Presentation->m_flipCompressedTextures);
}
struct SLightNodeMarker
@@ -1161,12 +1243,187 @@ namespace render {
}
};
- void SLayerRenderPreparationData::PrepareForRender(const QSize &inViewportDimensions)
+ void SLayerRenderPreparationData::calculateDynamicLayerSize(
+ SLayerRenderPreparationResult &prepResult)
+ {
+ m_boundPoints.clear();
+ if (m_Layer.m_DynamicCombine) {
+ // Combine all bounds of the layer objects to one spanning the whole active scene
+ // Only needs 8 projections but has low accuracy
+ NVBounds3 layerBounds;
+ layerBounds.setEmpty();
+ for (SNode *child = m_Layer.m_FirstChild; child; child = child->m_NextSibling) {
+ if (child->m_Flags.IsActive()) {
+ auto &context = m_Renderer.GetQt3DSContext();
+ qt3ds::NVBounds3 childBounds = child->GetActiveBounds(
+ context.GetBufferManager(), context.GetPathManager());
+ if (childBounds.isEmpty() == false) {
+ childBounds.transform(child->m_GlobalTransform);
+ layerBounds.include(childBounds);
+ }
+ }
+ }
+
+ m_boundPoints += QT3DSVec3(layerBounds.minimum.x, layerBounds.minimum.y,
+ layerBounds.minimum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.maximum.x, layerBounds.minimum.y,
+ layerBounds.minimum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.maximum.x, layerBounds.maximum.y,
+ layerBounds.minimum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.minimum.x, layerBounds.maximum.y,
+ layerBounds.minimum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.minimum.x, layerBounds.minimum.y,
+ layerBounds.maximum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.maximum.x, layerBounds.minimum.y,
+ layerBounds.maximum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.maximum.x, layerBounds.maximum.y,
+ layerBounds.maximum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.minimum.x, layerBounds.maximum.y,
+ layerBounds.maximum.z);
+ } else {
+ // Add 8 points for each active object to the point list
+ // Provides accurate 2d bounds, but causes a lot of projections for large scenes
+ for (SNode *child = m_Layer.m_FirstChild; child; child = child->m_NextSibling) {
+ if (child->m_Flags.IsActive()) {
+ auto &context = m_Renderer.GetQt3DSContext();
+ child->GetActiveBoundsList(m_boundPoints, context.GetBufferManager(),
+ context.GetPathManager(), child->m_GlobalTransform);
+ }
+ }
+ }
+
+ auto layerViewport = prepResult.GetLayerToPresentationViewport();
+
+ QT3DSVec2 projectedMinimum(std::numeric_limits<float>::max(),
+ std::numeric_limits<float>::max());
+ QT3DSVec2 projectedMaximum(std::numeric_limits<float>::lowest(),
+ std::numeric_limits<float>::lowest());
+
+ for (const auto &point : qAsConst(m_boundPoints)) {
+ QT3DSVec4 projectedPoint = m_ViewProjection.transform(QT3DSVec4(point, 1.0f));
+ projectedPoint.x /= projectedPoint.w;
+ projectedPoint.y /= projectedPoint.w;
+ projectedPoint.x += 1.0f;
+ projectedPoint.y += 1.0f;
+ projectedPoint.x *= 0.5f;
+ projectedPoint.y *= 0.5f;
+
+ QT3DSVec2 dims(QT3DSF32(layerViewport.m_Width),
+ QT3DSF32(layerViewport.m_Height));
+ projectedPoint.x *= dims.x;
+ projectedPoint.y *= dims.y;
+ projectedPoint.x += layerViewport.m_X;
+ projectedPoint.y += layerViewport.m_Y;
+
+ if (projectedPoint.x < projectedMinimum.x)
+ projectedMinimum.x = projectedPoint.x;
+ if (projectedPoint.y < projectedMinimum.y)
+ projectedMinimum.y = projectedPoint.y;
+ if (projectedPoint.x > projectedMaximum.x)
+ projectedMaximum.x = projectedPoint.x;
+ if (projectedPoint.y > projectedMaximum.y)
+ projectedMaximum.y = projectedPoint.y;
+ }
+
+ float boundsLeft = projectedMinimum.x;
+ float boundsBottom = projectedMinimum.y;
+ float boundsWidth = qAbs(projectedMaximum.x - projectedMinimum.x);
+ float boundsHeight = qAbs(projectedMaximum.y - projectedMinimum.y);
+
+ float paddedBoundsLeft = boundsLeft;
+ float paddedBoundsBottom = boundsBottom;
+ float paddedBoundsWidth = boundsWidth;
+ float paddedBoundsHeight = boundsHeight;
+
+ if (m_Layer.m_DynamicPadding > 0) {
+ float unpaddedBoundsLeft;
+ float unpaddedBoundsBottom;
+ float unpaddedBoundsWidth;
+ float unpaddedBoundsHeight;
+
+ if (m_Layer.m_DynamicPaddingUnits == LayerUnitTypes::Pixels) {
+ paddedBoundsLeft = boundsLeft - m_Layer.m_DynamicPadding;
+ paddedBoundsBottom = boundsBottom - m_Layer.m_DynamicPadding;
+ paddedBoundsWidth = boundsWidth + m_Layer.m_DynamicPadding * 2;
+ paddedBoundsHeight = boundsHeight + m_Layer.m_DynamicPadding * 2;
+
+ unpaddedBoundsLeft = boundsLeft + m_Layer.m_DynamicPadding;
+ unpaddedBoundsBottom = boundsBottom + m_Layer.m_DynamicPadding;
+ unpaddedBoundsWidth = boundsWidth - m_Layer.m_DynamicPadding * 2;
+ unpaddedBoundsHeight = boundsHeight - m_Layer.m_DynamicPadding * 2;
+ } else {
+ const float leftPadding = boundsWidth * m_Layer.m_DynamicPadding * 0.01f;
+ const float bottomPadding = boundsHeight * m_Layer.m_DynamicPadding * 0.01f;
+ const float widthPadding = m_Layer.m_DynamicPadding * 0.02f;
+ const float heightPadding = m_Layer.m_DynamicPadding * 0.02f;
+
+ paddedBoundsLeft = boundsLeft - leftPadding;
+ paddedBoundsBottom = boundsBottom - bottomPadding;
+ paddedBoundsWidth = boundsWidth * (1.0f + widthPadding);
+ paddedBoundsHeight = boundsHeight * (1.0f + heightPadding);
+
+ unpaddedBoundsLeft = boundsLeft + leftPadding;
+ unpaddedBoundsBottom = boundsBottom + bottomPadding;
+ unpaddedBoundsWidth = boundsWidth * (1.0f - widthPadding);
+ unpaddedBoundsHeight = boundsHeight * (1.0f - heightPadding);
+ }
+
+ // Both the padded and unpadded bounds are calculated
+ // Padded provides the upper bound when size has to be recalculated
+ // Unpadded provides the lower bound
+ // If the newly calculated bounds fit between the padded and unpadded ones
+ // use the previous calculations instead
+ if (m_Layer.m_DynamicPadding == m_lastDynamicPadding
+ && m_Layer.m_DynamicPaddingUnits == m_lastDynamicPaddingUnits
+ && m_unpaddedDynamicSize.m_X >= boundsLeft
+ && m_unpaddedDynamicSize.m_Y >= boundsBottom
+ && m_unpaddedDynamicSize.m_X + m_unpaddedDynamicSize.m_Width
+ <= boundsLeft + boundsWidth
+ && m_unpaddedDynamicSize.m_Y + m_unpaddedDynamicSize.m_Height
+ <= boundsBottom + boundsHeight
+ && m_dynamicSize.m_X <= boundsLeft
+ && m_dynamicSize.m_Y <= boundsBottom
+ && m_dynamicSize.m_X + m_dynamicSize.m_Width
+ >= boundsLeft + boundsWidth
+ && m_dynamicSize.m_Y + m_dynamicSize.m_Height
+ >= boundsBottom + boundsHeight) {
+ paddedBoundsLeft = m_dynamicSize.m_X;
+ paddedBoundsBottom = m_dynamicSize.m_Y;
+ paddedBoundsWidth = m_dynamicSize.m_Width;
+ paddedBoundsHeight = m_dynamicSize.m_Height;
+ } else {
+ m_unpaddedDynamicSize = NVRenderRectF(unpaddedBoundsLeft,
+ unpaddedBoundsBottom,
+ unpaddedBoundsWidth,
+ unpaddedBoundsHeight);
+ m_dynamicSize = NVRenderRectF(paddedBoundsLeft,
+ paddedBoundsBottom,
+ paddedBoundsWidth,
+ paddedBoundsHeight);
+ }
+ m_lastDynamicPadding = m_Layer.m_DynamicPadding;
+ m_lastDynamicPaddingUnits = m_Layer.m_DynamicPaddingUnits;
+ }
+
+ if (paddedBoundsLeft < layerViewport.m_X)
+ paddedBoundsLeft = layerViewport.m_X;
+ if (paddedBoundsBottom < layerViewport.m_Y)
+ paddedBoundsBottom = layerViewport.m_Y;
+ if (paddedBoundsWidth > layerViewport.m_Width)
+ paddedBoundsWidth = layerViewport.m_Width;
+ if (paddedBoundsHeight > layerViewport.m_Height)
+ paddedBoundsHeight = layerViewport.m_Height;
+
+ prepResult.setViewport(NVRenderRectF(paddedBoundsLeft, paddedBoundsBottom,
+ paddedBoundsWidth, paddedBoundsHeight));
+ }
+
+ bool SLayerRenderPreparationData::PrepareForRender(const QSize &inViewportDimensions)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::PrepareForRender")
+ "LayerRenderData: PrepareForRender")
if (m_LayerPrepResult.hasValue())
- return;
+ return false;
m_Features.clear();
m_FeatureSetHash = 0;
@@ -1176,7 +1433,7 @@ namespace render {
NVRenderRect theViewport(theGraph.GetViewport());
NVRenderRect theScissor(theGraph.GetViewport());
if (theGraph.IsScissorTestEnabled())
- theScissor = m_Renderer.GetContext().GetScissorRect();
+ theScissor = theGraph.GetScissor();
bool wasDirty = false;
bool wasDataDirty = false;
wasDirty = m_Layer.m_Flags.IsDirty();
@@ -1189,10 +1446,10 @@ namespace render {
// Uncomment the line below to disable all progressive AA.
// maxNumAAPasses = 0;
- SLayerRenderPreparationResult thePrepResult;
bool hasOffscreenRenderer = GetOffscreenRenderer();
- bool SSAOEnabled = (m_Layer.m_AoStrength > 0.0f && m_Layer.m_AoDistance > 0.0f);
+ bool SSAOEnabled = (m_Layer.m_AoStrength > 0.0f && m_Layer.m_AoDistance > 0.0f
+ && m_Layer.m_AoEnabled);
bool SSDOEnabled = (m_Layer.m_ShadowStrength > 0.0f && m_Layer.m_ShadowDist > 0.0f);
SetShaderFeature("QT3DS_ENABLE_SSAO", SSAOEnabled);
SetShaderFeature("QT3DS_ENABLE_SSDO", SSDOEnabled);
@@ -1217,20 +1474,18 @@ namespace render {
&& theEffectSystem.DoesEffectRequireDepthTexture(theEffect->m_ClassName))
requiresDepthPrepass = true;
- if (theEffect->m_imageMaps && theEffect->m_imageMaps->size() > 0) {
+ if (theEffect->m_images.size() > 0) {
SRenderableImage *firstImage = nullptr;
SRenderableImage *nextImage = nullptr;
SShaderDefaultMaterialKey key;
SRenderableObjectFlags flags;
- auto iter = theEffect->m_imageMaps->begin();
- auto end = theEffect->m_imageMaps->end();
+ auto iter = theEffect->m_images.begin();
+ auto end = theEffect->m_images.end();
for (; iter != end; iter++) {
- if (iter->second) {
- PrepareImageForRender(*iter->second, ImageMapTypes::Unknown,
- firstImage, nextImage, flags, key,
- SShaderDefaultMaterialKeyProperties::ImageMapCount,
- nullptr);
- }
+ PrepareImageForRender(**iter, ImageMapTypes::Unknown,
+ firstImage, nextImage, flags, key,
+ SShaderDefaultMaterialKeyProperties::ImageMapCount,
+ nullptr);
}
}
}
@@ -1250,22 +1505,23 @@ namespace render {
maxNumAAPasses = 0;
}
- thePrepResult = SLayerRenderPreparationResult(SLayerRenderHelper(
+ m_LayerPrepResult = SLayerRenderPreparationResult(SLayerRenderHelper(
theViewport, theScissor, m_Layer.m_Scene->m_Presentation->m_PresentationDimensions,
m_Layer, shouldRenderToTexture, m_Renderer.GetQt3DSContext().GetScaleMode(),
m_Renderer.GetQt3DSContext().GetStereoMode(),
m_Renderer.GetQt3DSContext().GetStereoView(),
m_Renderer.GetQt3DSContext().GetStereoEyeSeparation(),
+ m_Renderer.GetQt3DSContext().GetStereoEyeRotation(),
m_Renderer.GetQt3DSContext().GetPresentationScaleFactor()));
- thePrepResult.m_LastEffect = theLastEffect;
- thePrepResult.m_MaxAAPassIndex = maxNumAAPasses;
- thePrepResult.m_Flags.SetRequiresDepthTexture(requiresDepthPrepass
+ m_LayerPrepResult->m_LastEffect = theLastEffect;
+ m_LayerPrepResult->m_MaxAAPassIndex = maxNumAAPasses;
+ m_LayerPrepResult->m_Flags.SetRequiresDepthTexture(requiresDepthPrepass
|| NeedsWidgetTexture());
- thePrepResult.m_Flags.SetShouldRenderToTexture(shouldRenderToTexture);
+ m_LayerPrepResult->m_Flags.SetShouldRenderToTexture(shouldRenderToTexture);
if (m_Renderer.GetContext().GetRenderContextType() != NVRenderContextValues::GLES2)
- thePrepResult.m_Flags.SetRequiresSsaoPass(SSAOEnabled);
+ m_LayerPrepResult->m_Flags.SetRequiresSsaoPass(SSAOEnabled);
- if (thePrepResult.IsLayerVisible()) {
+ if (m_LayerPrepResult->IsLayerVisible()) {
if (shouldRenderToTexture) {
m_Renderer.GetQt3DSContext().GetRenderList().AddRenderTask(
CreateRenderToTextureRunnable());
@@ -1274,6 +1530,12 @@ namespace render {
m_Renderer.PrepareImageForIbl(*m_Layer.m_LightProbe);
wasDataDirty = true;
}
+ if (m_StereoMode != m_LayerPrepResult->getStereoMode()) {
+ // When stereo mode changes we need to mark data dirty
+ // for e.g. temporalAA to render correctly.
+ m_StereoMode = m_LayerPrepResult->getStereoMode();
+ wasDataDirty = true;
+ }
bool lightProbeValid = HasValidLightProbe(m_Layer.m_LightProbe);
@@ -1292,11 +1554,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();
@@ -1320,10 +1583,10 @@ namespace render {
// SetupCameraForRender() sets the camera used for picking and
// updates global state e.g. IsGloballyActive()
SCameraGlobalCalculationResult theResult =
- thePrepResult.SetupCameraForRender(*theCamera);
+ m_LayerPrepResult->SetupCameraForRender(*theCamera);
wasDataDirty = wasDataDirty || theResult.m_WasDirty;
if (theCamera->m_Flags.IsGloballyActive())
- m_Camera = thePrepResult.GetCamera();
+ m_Camera = m_LayerPrepResult->GetCamera();
if (theResult.m_ComputeFrustumSucceeded == false) {
qCCritical(INTERNAL_ERROR, "Failed to calculate camera frustum");
}
@@ -1363,7 +1626,7 @@ namespace render {
m_Lights.size() - 1, mapSize, mapSize,
NVRenderTextureFormats::R16F, 1, mapMode,
ShadowFilterValues::NONE);
- thePrepResult.m_Flags.SetRequiresShadowMapPass(true);
+ m_LayerPrepResult->m_Flags.SetRequiresShadowMapPass(true);
SetShaderFeature("QT3DS_ENABLE_SSM", true);
}
}
@@ -1430,9 +1693,13 @@ namespace render {
QT3DSF32 theTextScaleFactor = 1.0f;
if (m_Camera) {
m_Camera->CalculateViewProjectionMatrix(m_ViewProjection);
+
+ if (m_Layer.m_DynamicResize)
+ calculateDynamicLayerSize(*m_LayerPrepResult);
+
theTextScaleFactor = m_Camera->GetTextScaleFactor(
- thePrepResult.GetLayerToPresentationViewport(),
- thePrepResult.GetPresentationDesignDimensions());
+ m_LayerPrepResult->GetLayerToPresentationViewport(),
+ m_LayerPrepResult->GetPresentationDesignDimensions());
if (m_Camera->m_EnableFrustumCulling) {
SClipPlane nearPlane;
QT3DSMat33 theUpper33(m_Camera->m_GlobalTransform.getUpper3x3InverseTranspose());
@@ -1464,16 +1731,16 @@ namespace render {
bool renderablesDirty =
PrepareRenderablesForRender(m_ViewProjection,
m_ClippingFrustum,
- theTextScaleFactor, thePrepResult.m_Flags);
+ theTextScaleFactor, m_LayerPrepResult->m_Flags);
wasDataDirty = wasDataDirty || renderablesDirty;
- if (thePrepResult.m_Flags.RequiresStencilBuffer())
- thePrepResult.m_Flags.SetShouldRenderToTexture(true);
+ if (m_LayerPrepResult->m_Flags.RequiresStencilBuffer())
+ m_LayerPrepResult->m_Flags.SetShouldRenderToTexture(true);
} else {
NVRenderRect theViewport =
- thePrepResult.GetLayerToPresentationViewport().ToIntegerRect();
+ m_LayerPrepResult->GetLayerToPresentationViewport().ToIntegerRect();
bool theScissor = true;
NVRenderRect theScissorRect =
- thePrepResult.GetLayerToPresentationScissorRect().ToIntegerRect();
+ m_LayerPrepResult->GetLayerToPresentationScissorRect().ToIntegerRect();
// This happens here because if there are any fancy render steps
IRenderList &theRenderList(m_Renderer.GetQt3DSContext().GetRenderList());
NVRenderContext &theContext(m_Renderer.GetContext());
@@ -1503,12 +1770,13 @@ namespace render {
wasDataDirty = wasDataDirty || theResult.m_HasChangedSinceLastFrame;
}
}
+ } else {
+ // m_LayerPrepResult must always be set.
+ m_LayerPrepResult = SLayerRenderPreparationResult();
}
wasDirty = wasDirty || wasDataDirty;
- thePrepResult.m_Flags.SetWasDirty(wasDirty);
- thePrepResult.m_Flags.SetLayerDataDirty(wasDataDirty);
-
- m_LayerPrepResult = thePrepResult;
+ m_LayerPrepResult->m_Flags.SetWasDirty(wasDirty);
+ m_LayerPrepResult->m_Flags.SetLayerDataDirty(wasDataDirty);
// Per-frame cache of renderable objects post-sort.
GetOpaqueRenderableObjects();
@@ -1516,12 +1784,14 @@ namespace render {
GetTransparentRenderableObjects();
GetCameraDirection();
+ return wasDirty;
}
void SLayerRenderPreparationData::ResetForFrame()
{
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.