diff options
Diffstat (limited to 'src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp')
-rw-r--r-- | src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp | 406 |
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. |