summaryrefslogtreecommitdiffstats
path: root/src/runtimerender/rendererimpl
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtimerender/rendererimpl')
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp35
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h23
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp167
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImpl.h13
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp497
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h20
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp119
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h18
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp406
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h21
10 files changed, 974 insertions, 345 deletions
diff --git a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
index 712214a..095badc 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
@@ -290,9 +290,31 @@ namespace render {
}
}
- context.SetCullingEnabled(true);
+ context.SetCullingEnabled(m_Material.m_CullMode != DefaultMaterialCullMode::None);
context.SetInputAssembler(m_Subset.m_InputAssembler);
- context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
+ if (m_Material.m_CullMode != DefaultMaterialCullMode::None) {
+ NVScopedRefCounted<qt3ds::render::NVRenderRasterizerState> rsdefaultstate =
+ context.CreateRasterizerState(0.0, 0.0, qt3ds::render::NVRenderFaces::Back);
+ qt3ds::render::NVRenderFaces::Enum face = qt3ds::render::NVRenderFaces::Back;
+ switch (m_Material.m_CullMode) {
+ case DefaultMaterialCullMode::Front:
+ face = qt3ds::render::NVRenderFaces::Front;
+ break;
+ case DefaultMaterialCullMode::FrontAndBack:
+ face = qt3ds::render::NVRenderFaces::FrontAndBack;
+ break;
+ default:
+ break;
+ }
+
+ NVScopedRefCounted<qt3ds::render::NVRenderRasterizerState> rasterState =
+ context.CreateRasterizerState(0.0, 0.0, face);
+ context.SetRasterizerState(rasterState);
+ context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
+ context.SetRasterizerState(rsdefaultstate);
+ } else {
+ context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
+ }
}
void SSubsetRenderable::RenderShadow(const QT3DSVec2 &inCameraVec,
@@ -600,5 +622,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..b39cc91 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
@@ -57,6 +57,7 @@
#include "Qt3DSRenderPath.h"
#include "Qt3DSRenderShaderCodeGeneratorV2.h"
#include "Qt3DSRenderDefaultMaterialShaderGenerator.h"
+#include "backends/gl/Qt3DSOpenGLUtil.h"
#include <stdlib.h>
#ifdef _WIN32
@@ -128,6 +129,7 @@ namespace render {
, m_PickRenderPlugins(true)
, m_LayerCachingEnabled(true)
, m_LayerGPuProfilingEnabled(false)
+ , m_SignalProxy(ctx.GetSignalProxy())
{
}
Qt3DSRendererImpl::~Qt3DSRendererImpl()
@@ -232,11 +234,9 @@ namespace render {
}
bool Qt3DSRendererImpl::PrepareLayerForRender(SLayer &inLayer,
- const QT3DSVec2 &inViewportDimensions,
bool inRenderSiblings,
const SRenderInstanceId id)
{
- (void)inViewportDimensions;
nvvector<SLayer *> renderableLayers(m_qt3dsContext.GetPerFrameAllocator(), "LayerVector");
// Found by fair roll of the dice.
renderableLayers.reserve(4);
@@ -253,7 +253,7 @@ namespace render {
SLayerRenderData *theRenderData = GetOrCreateLayerRenderDataForNode(*theLayer, id);
if (theRenderData) {
- theRenderData->PrepareForRender();
+ bool needsRender = theRenderData->PrepareForRender();
if (id) {
if (m_initialPrepareData.contains(theLayer)) {
// Copy dirty state from the initial since the graph is
@@ -268,7 +268,8 @@ namespace render {
m_initialPrepareData.insert(theLayer, theRenderData);
}
}
- retval = retval || theRenderData->m_LayerPrepResult->m_Flags.WasDirty();
+ retval = retval || needsRender
+ || theRenderData->m_LayerPrepResult->m_Flags.WasDirty() ;
} else {
QT3DS_ASSERT(false);
}
@@ -367,7 +368,7 @@ namespace render {
SLayerRenderData *theRenderData = QT3DS_NEW(m_Context->GetAllocator(), SLayerRenderData)(
const_cast<SLayer &>(*theLayer), *this);
m_InstanceRenderMap.insert(make_pair(combineLayerAndId(theLayer, id), theRenderData));
-
+ theRenderData->m_SignalProxy = (QRuntimeViewSignalProxy *)m_SignalProxy;
// create a profiler if enabled
if (IsLayerGpuProfilingEnabled() && theRenderData)
theRenderData->CreateGpuProfiler();
@@ -968,20 +969,53 @@ namespace render {
return mouseVec;
}
- uint Qt3DSRendererImpl::getLayerTextureId(SLayer &layer)
+ uint Qt3DSRendererImpl::getLayerTextureId(SLayer &layer, const SRenderInstanceId id)
{
- SLayerRenderData *data = GetOrCreateLayerRenderDataForNode(layer);
- if (data->m_LayerCachedTexture) {
+ SLayerRenderData *data = GetOrCreateLayerRenderDataForNode(layer, id);
+ if (data->m_LayerCachedTexture[data->getCameraIndex()]) {
return static_cast<uint>(reinterpret_cast<size_t>(
- data->m_LayerCachedTexture->GetTextureObjectHandle()));
+ data->m_LayerCachedTexture[data->getCameraIndex()]->GetTextureObjectHandle()));
}
- if (data->m_LayerTexture) {
+ if (data->m_LayerTexture[data->getCameraIndex()]) {
return static_cast<uint>(reinterpret_cast<size_t>(
- data->m_LayerTexture->GetTextureObjectHandle()));
+ data->m_LayerTexture[data->getCameraIndex()]->GetTextureObjectHandle()));
}
return 0;
}
+ GLenum Qt3DSRendererImpl::getTextureGlFormat(NVRenderTextureFormats::Enum internalFormat)
+ {
+ auto ctxType = m_Context->GetRenderContextType();
+ GLConversion conversion;
+ GLenum glInternalFormat, glformat, gltype;
+
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat)) {
+ conversion.fromUncompressedTextureFormatToGL(ctxType, internalFormat,
+ glformat, gltype, glInternalFormat);
+ return glInternalFormat;
+ } else if (NVRenderTextureFormats::isCompressedTextureFormat(internalFormat)) {
+ return conversion.fromCompressedTextureFormatToGL(internalFormat);
+ } else if (NVRenderTextureFormats::isDepthTextureFormat(internalFormat)) {
+ conversion.fromDepthTextureFormatToGL(ctxType, internalFormat, glformat,
+ gltype, glInternalFormat);
+ return glInternalFormat;
+ } else {
+ return GL_INVALID_ENUM;
+ }
+ }
+
+ STextureDetails Qt3DSRendererImpl::getLayerTextureDetails(SLayer &inLayer, const SRenderInstanceId id)
+ {
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer, id);
+
+ if (theData->m_LayerCachedTexture[theData->getCameraIndex()])
+ return theData->m_LayerCachedTexture[theData->getCameraIndex()]->GetTextureDetails();
+ if (theData->m_LayerTexture[theData->getCameraIndex()])
+ return theData->m_LayerTexture[theData->getCameraIndex()]->GetTextureDetails();
+
+ return {};
+ }
+
Option<SLayerPickSetup> Qt3DSRendererImpl::GetLayerPickSetup(SLayer &inLayer,
const QT3DSVec2 &inMouseCoords,
const QSize &inPickDims)
@@ -1405,61 +1439,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/Qt3DSRendererImpl.h b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h
index 792d71e..2230733 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h
@@ -296,6 +296,7 @@ namespace render {
bool m_PickRenderPlugins;
bool m_LayerCachingEnabled;
bool m_LayerGPuProfilingEnabled;
+ void *m_SignalProxy;
SShaderDefaultMaterialKeyProperties m_DefaultMaterialShaderKeyProperties;
QHash<SLayer *, SLayerRenderData *> m_initialPrepareData;
@@ -305,6 +306,7 @@ namespace render {
float m_alphaOp = 1.0f;
float m_alphaRef = 1.0f;
+
public:
Qt3DSRendererImpl(IQt3DSRenderContext &ctx);
virtual ~Qt3DSRendererImpl();
@@ -342,8 +344,8 @@ namespace render {
// Calls prepare layer for render
// and then do render layer.
- bool PrepareLayerForRender(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
- bool inRenderSiblings, const SRenderInstanceId id) override;
+ bool PrepareLayerForRender(SLayer &inLayer, bool inRenderSiblings,
+ const SRenderInstanceId id) override;
void RenderLayer(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
bool clear, QT3DSVec4 clearColor, bool inRenderSiblings,
const SRenderInstanceId id) override;
@@ -386,7 +388,11 @@ namespace render {
const QT3DSVec3 &inMouseVec) const override;
QT3DSVec3 ProjectPosition(SNode &inNode, const QT3DSVec3 &inPosition) const override;
- uint getLayerTextureId(SLayer &layer) override;
+ uint getLayerTextureId(SLayer &layer, const SRenderInstanceId id) override;
+
+ STextureDetails getLayerTextureDetails(SLayer &inLayer, const SRenderInstanceId id) override;
+
+ GLenum getTextureGlFormat(NVRenderTextureFormats::Enum internalFormat) override;
Option<SLayerPickSetup> GetLayerPickSetup(SLayer &inLayer,
const QT3DSVec2 &inMouseCoords,
@@ -566,7 +572,6 @@ namespace render {
Option<QT3DSVec2> GetLayerMouseCoords(SLayer &inLayer, const QT3DSVec2 &inMouseCoords,
const QT3DSVec2 &inViewportDimensions,
bool forceImageIntersect = false) const override;
-
protected:
Option<QT3DSVec2> GetLayerMouseCoords(SLayerRenderData &inLayer, const QT3DSVec2 &inMouseCoords,
const QT3DSVec2 &inViewportDimensions,
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
index 95cbc9e..7348fb2 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
@@ -77,7 +77,8 @@ namespace render {
SLayerRenderData::SLayerRenderData(SLayer &inLayer, Qt3DSRendererImpl &inRenderer)
: SLayerRenderPreparationData(inLayer, inRenderer)
- , m_LayerTexture(inRenderer.GetQt3DSContext().GetResourceManager())
+ , m_LayerTexture{inRenderer.GetQt3DSContext().GetResourceManager(),
+ inRenderer.GetQt3DSContext().GetResourceManager()}
, m_TemporalAATexture{inRenderer.GetQt3DSContext().GetResourceManager(),
inRenderer.GetQt3DSContext().GetResourceManager()}
, m_LayerDepthTexture(inRenderer.GetQt3DSContext().GetResourceManager())
@@ -87,7 +88,7 @@ namespace render {
, m_LayerMultisampleTexture(inRenderer.GetQt3DSContext().GetResourceManager())
, m_LayerMultisamplePrepassDepthTexture(inRenderer.GetQt3DSContext().GetResourceManager())
, m_LayerMultisampleWidgetTexture(inRenderer.GetQt3DSContext().GetResourceManager())
- , m_LayerCachedTexture(NULL)
+ , m_LayerCachedTexture{NULL, NULL}
, m_AdvancedBlendDrawTexture(NULL)
, m_AdvancedBlendBlendTexture(NULL)
, m_AdvancedModeDrawFB(NULL)
@@ -105,8 +106,10 @@ namespace render {
SLayerRenderData::~SLayerRenderData()
{
IResourceManager &theResourceManager(m_Renderer.GetQt3DSContext().GetResourceManager());
- if (m_LayerCachedTexture && m_LayerCachedTexture != m_LayerTexture)
- theResourceManager.Release(*m_LayerCachedTexture);
+ if (m_LayerCachedTexture[0] && m_LayerCachedTexture[0] != m_LayerTexture[0])
+ theResourceManager.Release(*m_LayerCachedTexture[0]);
+ if (m_LayerCachedTexture[1] && m_LayerCachedTexture[1] != m_LayerTexture[1])
+ theResourceManager.Release(*m_LayerCachedTexture[1]);
if (m_AdvancedModeDrawFB) {
m_AdvancedModeDrawFB->release();
m_AdvancedModeDrawFB = NULL;
@@ -120,9 +123,9 @@ namespace render {
if (m_AdvancedBlendDrawTexture)
m_AdvancedBlendDrawTexture = NULL;
}
- void SLayerRenderData::PrepareForRender(const QSize &inViewportDimensions)
+ bool SLayerRenderData::PrepareForRender(const QSize &inViewportDimensions)
{
- SLayerRenderPreparationData::PrepareForRender(inViewportDimensions);
+ bool needsRender = SLayerRenderPreparationData::PrepareForRender(inViewportDimensions);
SLayerRenderPreparationResult &thePrepResult(*m_LayerPrepResult);
IResourceManager &theResourceManager(m_Renderer.GetQt3DSContext().GetResourceManager());
@@ -133,13 +136,13 @@ namespace render {
}
// Get rid of the layer texture if we aren't rendering to texture this frame.
- if (m_LayerTexture && !thePrepResult.m_Flags.ShouldRenderToTexture()) {
- if (m_LayerCachedTexture && m_LayerCachedTexture != m_LayerTexture) {
- theResourceManager.Release(*m_LayerCachedTexture);
- m_LayerCachedTexture = NULL;
+ if (m_LayerTexture[getCameraIndex()] && !thePrepResult.m_Flags.ShouldRenderToTexture()) {
+ if (m_LayerCachedTexture[getCameraIndex()] && m_LayerCachedTexture[getCameraIndex()] != m_LayerTexture[getCameraIndex()]) {
+ theResourceManager.Release(*m_LayerCachedTexture[getCameraIndex()]);
+ m_LayerCachedTexture[getCameraIndex()] = NULL;
}
- m_LayerTexture.ReleaseTexture();
+ m_LayerTexture[getCameraIndex()].ReleaseTexture();
m_LayerDepthTexture.ReleaseTexture();
m_LayerWidgetTexture.ReleaseTexture();
m_LayerSsaoTexture.ReleaseTexture();
@@ -162,7 +165,7 @@ namespace render {
// Clean up the texture cache if layer dimensions changed
if (inViewportDimensions.width() != m_previousDimensions.width()
|| inViewportDimensions.height() != m_previousDimensions.height()) {
- m_LayerTexture.ReleaseTexture();
+ m_LayerTexture[getCameraIndex()].ReleaseTexture();
m_LayerDepthTexture.ReleaseTexture();
m_LayerSsaoTexture.ReleaseTexture();
m_LayerWidgetTexture.ReleaseTexture();
@@ -182,6 +185,13 @@ namespace render {
m_Renderer.GetQt3DSContext().GetEffectSystem().GetResourceManager()
.DestroyFreeSizedResources();
}
+ bool isProgressiveAABlendPass =
+ m_ProgressiveAAPassIndex && m_ProgressiveAAPassIndex < thePrepResult.m_MaxAAPassIndex;
+ // Save left eye flags for later
+ if (getCameraIndex() == 0)
+ m_LeftFlags = SLayerRenderPreparationResultFlags(thePrepResult.m_Flags);
+
+ return needsRender || isProgressiveAABlendPass;
}
NVRenderTextureFormats::Enum SLayerRenderData::GetDepthBufferFormat()
@@ -309,6 +319,36 @@ namespace render {
}
namespace {
+ NVBounds3 calculateShadowCameraBoundingBox(const QT3DSVec3 *points,
+ const QT3DSVec3 &forward,
+ const QT3DSVec3 &up, const QT3DSVec3 &right)
+ {
+ float minDistanceZ = std::numeric_limits<float>::max();
+ float maxDistanceZ = -std::numeric_limits<float>::max();
+ float minDistanceY = std::numeric_limits<float>::max();
+ float maxDistanceY = -std::numeric_limits<float>::max();
+ float minDistanceX = std::numeric_limits<float>::max();
+ float maxDistanceX = -std::numeric_limits<float>::max();
+ for (int i = 0; i < 8; ++i) {
+ float distanceZ = points[i].dot(forward);
+ if (distanceZ < minDistanceZ)
+ minDistanceZ = distanceZ;
+ if (distanceZ > maxDistanceZ)
+ maxDistanceZ = distanceZ;
+ float distanceY = points[i].dot(up);
+ if (distanceY < minDistanceY)
+ minDistanceY = distanceY;
+ if (distanceY > maxDistanceY)
+ maxDistanceY = distanceY;
+ float distanceX = points[i].dot(right);
+ if (distanceX < minDistanceX)
+ minDistanceX = distanceX;
+ if (distanceX > maxDistanceX)
+ maxDistanceX = distanceX;
+ }
+ return NVBounds3(QT3DSVec3(minDistanceX, minDistanceY, minDistanceZ),
+ QT3DSVec3(maxDistanceX, maxDistanceY, maxDistanceZ));
+ }
void computeFrustumBounds(const SCamera &inCamera, const NVRenderRectF &inViewPort,
QT3DSVec3 &ctrBound, QT3DSVec3 camVerts[8])
@@ -350,7 +390,8 @@ namespace render {
void SetupCameraForShadowMap(const QT3DSVec2 &inCameraVec, NVRenderContext & /*inContext*/,
const NVRenderRectF &inViewport, const SCamera &inCamera,
- const SLight *inLight, SCamera &theCamera)
+ const SLight *inLight, SCamera &theCamera,
+ QT3DSVec3 *scenePoints = nullptr)
{
// setup light matrix
QT3DSU32 mapRes = 1 << inLight->m_ShadowMapRes;
@@ -368,8 +409,15 @@ namespace render {
theCamera.m_FOV = inLight->m_ShadowMapFov * QT3DS_DEGREES_TO_RADIANS;
if (inLight->m_LightType == RenderLightTypes::Directional) {
- QT3DSVec3 frustBounds[8], boundCtr;
- computeFrustumBounds(inCamera, inViewport, boundCtr, frustBounds);
+ QT3DSVec3 frustumPoints[8], boundCtr, sceneCtr;
+ computeFrustumBounds(inCamera, inViewport, boundCtr, frustumPoints);
+
+ if (scenePoints) {
+ sceneCtr = QT3DSVec3(0, 0, 0);
+ for (int i = 0; i < 8; ++i)
+ sceneCtr += scenePoints[i];
+ sceneCtr *= 0.125f;
+ }
QT3DSVec3 forward = inLightDir;
forward.normalize();
@@ -379,37 +427,26 @@ namespace render {
up.normalize();
// Calculate bounding box of the scene camera frustum
- float minDistanceZ = std::numeric_limits<float>::max();
- float maxDistanceZ = -std::numeric_limits<float>::max();
- float minDistanceY = std::numeric_limits<float>::max();
- float maxDistanceY = -std::numeric_limits<float>::max();
- float minDistanceX = std::numeric_limits<float>::max();
- float maxDistanceX = -std::numeric_limits<float>::max();
- for (int i = 0; i < 8; ++i) {
- float distanceZ = frustBounds[i].dot(forward);
- if (distanceZ < minDistanceZ)
- minDistanceZ = distanceZ;
- if (distanceZ > maxDistanceZ)
- maxDistanceZ = distanceZ;
- float distanceY = frustBounds[i].dot(up);
- if (distanceY < minDistanceY)
- minDistanceY = distanceY;
- if (distanceY > maxDistanceY)
- maxDistanceY = distanceY;
- float distanceX = frustBounds[i].dot(right);
- if (distanceX < minDistanceX)
- minDistanceX = distanceX;
- if (distanceX > maxDistanceX)
- maxDistanceX = distanceX;
+ NVBounds3 bounds = calculateShadowCameraBoundingBox(frustumPoints, forward, up,
+ right);
+ inLightPos = boundCtr;
+ if (scenePoints) {
+ NVBounds3 sceneBounds = calculateShadowCameraBoundingBox(scenePoints, forward,
+ up, right);
+ if (sceneBounds.getExtents().x * sceneBounds.getExtents().y
+ * sceneBounds.getExtents().z < bounds.getExtents().x
+ * bounds.getExtents().y * bounds.getExtents().z) {
+ bounds = sceneBounds;
+ inLightPos = sceneCtr;
+ }
}
// Apply bounding box parameters to shadow map camera projection matrix
// so that the whole scene is fit inside the shadow map
- inLightPos = boundCtr;
- theViewport.m_Height = abs(maxDistanceY - minDistanceY);
- theViewport.m_Width = abs(maxDistanceX - minDistanceX);
- theCamera.m_ClipNear = -abs(maxDistanceZ - minDistanceZ);
- theCamera.m_ClipFar = abs(maxDistanceZ - minDistanceZ);
+ theViewport.m_Height = bounds.getExtents().y * 2;
+ theViewport.m_Width = bounds.getExtents().x * 2;
+ theCamera.m_ClipNear = -bounds.getExtents().z * 2;
+ theCamera.m_ClipFar = bounds.getExtents().z * 2;
}
theCamera.m_Flags.SetLeftHanded(false);
@@ -668,14 +705,15 @@ namespace render {
void SLayerRenderData::RenderShadowMapPass(CResourceFrameBuffer *theFB)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::RenderShadowMapPass")
+ "LayerRenderData: RenderShadowMapPass")
if (m_Camera == NULL || !GetShadowMapManager())
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;
}
@@ -706,6 +744,18 @@ namespace render {
| qt3ds::render::NVRenderClearValues::Stencil
| qt3ds::render::NVRenderClearValues::Color);
+ auto bounds = m_Camera->m_Parent->GetBounds(m_Renderer.GetQt3DSContext().GetBufferManager(),
+ m_Renderer.GetQt3DSContext().GetPathManager());
+ QT3DSVec3 scenePoints[8];
+ scenePoints[0] = bounds.minimum;
+ scenePoints[1] = QT3DSVec3(bounds.maximum.x, bounds.minimum.y, bounds.minimum.z);
+ scenePoints[2] = QT3DSVec3(bounds.minimum.x, bounds.maximum.y, bounds.minimum.z);
+ scenePoints[3] = QT3DSVec3(bounds.maximum.x, bounds.maximum.y, bounds.minimum.z);
+ scenePoints[4] = QT3DSVec3(bounds.minimum.x, bounds.minimum.y, bounds.maximum.z);
+ scenePoints[5] = QT3DSVec3(bounds.maximum.x, bounds.minimum.y, bounds.maximum.z);
+ scenePoints[6] = QT3DSVec3(bounds.minimum.x, bounds.maximum.y, bounds.maximum.z);
+ scenePoints[7] = bounds.maximum;
+
for (QT3DSU32 i = 0; i < m_Lights.size(); i++) {
// don't render shadows when not casting
if (m_Lights[i]->m_CastShadow == false)
@@ -717,7 +767,7 @@ namespace render {
QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
SetupCameraForShadowMap(theCameraProps, m_Renderer.GetContext(),
__viewport.m_InitialValue, *m_Camera,
- m_Lights[i], theCamera);
+ m_Lights[i], theCamera, scenePoints);
// we need this matrix for the final rendering
theCamera.CalculateViewProjectionMatrix(pEntry->m_LightVP);
pEntry->m_LightView = theCamera.m_GlobalTransform.getInverse();
@@ -826,13 +876,13 @@ namespace render {
void SLayerRenderData::RenderDepthPass(bool inEnableTransparentDepthWrite)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::RenderDepthPass")
+ "LayerRenderData: RenderDepthPass")
if (m_Camera == NULL)
return;
// Avoid running this method if possible.
- if ((inEnableTransparentDepthWrite == false
- && ((m_OpaqueObjects.size() == 0 && m_TransparentObjects.size() == 0)
+ if ((inEnableTransparentDepthWrite
+ && ((m_GroupObjects.empty() && m_OpaqueObjects.empty() && m_TransparentObjects.empty())
|| m_Layer.m_Flags.IsLayerEnableDepthPrepass() == false))
|| m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
return;
@@ -895,23 +945,98 @@ 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);
+ 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.
+ // 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
+ }
+}
- // 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())) {
+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())) {
+ if (theObject.m_RenderableFlags.isOrderedGroup()) {
+ renderOrderedGroup(theObject, inRenderFn, inEnableBlending,
+ inEnableDepthWrite, inEnableTransparentDepthWrite,
+ indexLight, inCamera, theFB);
+ } else {
#ifdef ADVANCED_BLEND_SW_FALLBACK
// SW fallback for advanced blend modes.
// Renders transparent objects to a separate FBO and blends them in shader
@@ -920,12 +1045,13 @@ namespace render {
= 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;
+ bool useBlendFallback
+ = (blendMode == DefaultMaterialBlendMode::Overlay
+ || blendMode == DefaultMaterialBlendMode::ColorBurn
+ || blendMode == DefaultMaterialBlendMode::ColorDodge)
+ && !theRenderContext.IsAdvancedBlendHwSupported()
+ && !theRenderContext.IsAdvancedBlendHwSupportedKHR()
+ && m_LayerPrepassDepthTexture;
if (useBlendFallback)
SetupDrawFB(true);
#endif
@@ -934,6 +1060,11 @@ namespace render {
theObject.m_ScopedLights);
SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ if (theObject.m_RenderableFlags.hasAlphaTest())
+ m_Renderer.setAlphaTest(true, -1.0f, 1.0f);
+ else
+ m_Renderer.setAlphaTest(false, 1.0f, 1.0f);
+
inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(),
indexLight, inCamera);
#ifdef ADVANCED_BLEND_SW_FALLBACK
@@ -952,22 +1083,29 @@ namespace render {
}
}
}
- // 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);
@@ -982,6 +1120,12 @@ namespace render {
m_SourceLightDirections,
theObject.m_ScopedLights);
SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+
+ if (theObject.m_RenderableFlags.hasAlphaTest())
+ m_Renderer.setAlphaTest(true, -1.0f, 1.0f);
+ else
+ m_Renderer.setAlphaTest(false, 1.0f, 1.0f);
+
inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(),
indexLight, inCamera);
#ifdef ADVANCED_BLEND_SW_FALLBACK
@@ -996,65 +1140,63 @@ 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();
- 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;
+
+ theRenderContext.SetDepthTestEnabled(opaqueDepthTest);
+ theRenderContext.SetDepthWriteEnabled(opaqueDepthWrite);
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);
- }
- 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]);
+ QT3DS_ASSERT(!theObject.m_RenderableFlags.isOrderedGroup());
+
+ 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);
+
+ if (theObject.m_RenderableFlags.hasAlphaTest())
+ m_Renderer.setAlphaTest(true, 1.0f, -1.0f + (1.0f / 255.0f));
+ else
+ m_Renderer.setAlphaTest(false, 1.0f, 1.0f);
+
inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(), indexLight,
inCamera);
}
+ }
- 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 pass")
m_Renderer.setAlphaTest(false, 1.0, 1.0);
- // transparent objects without alpha test
- renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableTransparentDepthWrite,
- indexLight, inCamera, theFB);
+ renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableDepthWrite,
+ inEnableTransparentDepthWrite, indexLight, inCamera, theFB);
}
+}
void SLayerRenderData::Render(CResourceFrameBuffer *theFB)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::Render")
+ "LayerRenderData: Render")
if (m_Camera == NULL)
return;
@@ -1217,7 +1359,7 @@ namespace render {
theRenderContext.SetDepthTestEnabled(false);
theRenderContext.SetDepthWriteEnabled(false);
}
- BlendAdvancedEquationSwFallback(m_AdvancedBlendDrawTexture, m_LayerTexture, advancedMode);
+ BlendAdvancedEquationSwFallback(m_AdvancedBlendDrawTexture, m_LayerTexture[getCameraIndex()], advancedMode);
theRenderContext.SetRenderTarget(*theFB);
// setup read target
theRenderContext.SetReadTarget(m_AdvancedModeBlendFB);
@@ -1293,6 +1435,12 @@ namespace render {
CRegisteredString depthPassStr;
+ int SLayerRenderData::getCameraIndex() const
+ {
+ StereoViews::Enum stereoView = m_Renderer.GetQt3DSContext().GetStereoView();
+ return (stereoView == StereoViews::Right) ? 1 : 0;
+ }
+
// Render this layer's data to a texture. Required if we have any effects,
// prog AA, or if forced.
void SLayerRenderData::RenderToTexture()
@@ -1300,7 +1448,7 @@ namespace render {
QT3DS_ASSERT(m_LayerPrepResult->m_Flags.ShouldRenderToTexture());
SLayerRenderPreparationResult &thePrepResult(*m_LayerPrepResult);
NVRenderContext &theRenderContext(m_Renderer.GetContext());
- QSize theLayerTextureDimensions = thePrepResult.GetTextureDimensions();
+ QSize theLayerTextureDimensions(thePrepResult.GetTextureDimensions());
QSize theLayerOriginalTextureDimensions = theLayerTextureDimensions;
NVRenderTextureFormats::Enum DepthTextureFormat = NVRenderTextureFormats::Depth24Stencil8;
NVRenderTextureFormats::Enum ColorTextureFormat = NVRenderTextureFormats::RGBA8;
@@ -1332,13 +1480,14 @@ namespace render {
// progressive AA algorithm.
if (thePrepResult.m_Flags.WasLayerDataDirty()
|| thePrepResult.m_Flags.WasDirty()
+ || (getCameraIndex() == 1 && (m_LeftFlags.WasLayerDataDirty() || m_LeftFlags.WasDirty()))
|| m_Renderer.IsLayerCachingEnabled() == false) {
m_ProgressiveAAPassIndex = 0;
m_NonDirtyTemporalAAPassIndex = 0;
needsRender = true;
}
- CResourceTexture2D *renderColorTexture = &m_LayerTexture;
+ CResourceTexture2D *renderColorTexture = &m_LayerTexture[getCameraIndex()];
CResourceTexture2D *renderPrepassDepthTexture = &m_LayerPrepassDepthTexture;
CResourceTexture2D *renderWidgetTexture = &m_LayerWidgetTexture;
NVRenderContextScopedProperty<bool> __multisampleEnabled(
@@ -1356,7 +1505,7 @@ namespace render {
QT3DSU32 maxTemporalPassIndex = m_Layer.m_TemporalAAEnabled ? 2 : 0;
// If all the dimensions match then we do not have to re-render the layer.
- if (m_LayerTexture.TextureMatches(theLayerTextureDimensions.width(),
+ if (m_LayerTexture[getCameraIndex()].TextureMatches(theLayerTextureDimensions.width(),
theLayerTextureDimensions.height(), ColorTextureFormat)
&& (!thePrepResult.m_Flags.RequiresDepthTexture()
|| m_LayerDepthTexture.TextureMatches(theLayerTextureDimensions.width(),
@@ -1432,19 +1581,21 @@ namespace render {
if (isProgressiveAABlendPass || isTemporalAABlendPass) {
theBlendShader = m_Renderer.GetLayerProgAABlendShader();
if (theBlendShader) {
- m_LayerTexture.EnsureTexture(theLayerOriginalTextureDimensions.width(),
+ m_LayerTexture[getCameraIndex()].EnsureTexture(theLayerOriginalTextureDimensions.width(),
theLayerOriginalTextureDimensions.height(),
ColorTextureFormat);
QT3DSVec2 theVertexOffsets;
if (isProgressiveAABlendPass) {
- theLastLayerTexture.StealTexture(m_LayerTexture);
+ theLastLayerTexture.StealTexture(m_LayerTexture[getCameraIndex()]);
aaFactorIndex = (m_ProgressiveAAPassIndex - 1);
theVertexOffsets = s_VertexOffsets[aaFactorIndex];
} else {
- if (temporalAATexture.GetTexture())
- theLastLayerTexture.StealTexture(temporalAATexture);
- else if (hadLayerTexture)
- theLastLayerTexture.StealTexture(m_LayerTexture);
+ if (hadLayerTexture) {
+ if (temporalAATexture.GetTexture())
+ theLastLayerTexture.StealTexture(temporalAATexture);
+ else
+ theLastLayerTexture.StealTexture(m_LayerTexture[getCameraIndex()]);
+ }
theVertexOffsets = s_TemporalVertexOffsets[m_TemporalAAPassIndex];
++m_TemporalAAPassIndex;
@@ -1531,11 +1682,26 @@ 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(),
theLayerTextureDimensions.height());
+
+ if (m_Layer.m_DynamicResize && theLayerOriginalTextureDimensions.width() != 0) {
+ // With dynamic resize the viewport should behave like it just crops the full layer
+ // So a special viewport has to be calculated that keeps the original object sizes
+ float ratio = theLayerTextureDimensions.width()
+ / theLayerOriginalTextureDimensions.width();
+ auto originalLayerViewport = thePrepResult.getOriginalLayerToPresentationViewport();
+ auto layerViewport = thePrepResult.GetLayerToPresentationViewport();
+ theNewViewport = NVRenderRect((-layerViewport.m_X + originalLayerViewport.m_X) * ratio,
+ (-layerViewport.m_Y + originalLayerViewport.m_Y) * ratio,
+ originalLayerViewport.m_Width * ratio,
+ originalLayerViewport.m_Height * ratio);
+ }
+
{
theRenderContext.SetRenderTarget(theFB);
NVRenderContextScopedProperty<NVRenderRect> __viewport(
@@ -1630,6 +1796,9 @@ namespace render {
// will do this.
StartProfiling("Render pass", false);
Render(&theFB);
+
+ if (m_SignalProxy) // Editor does not have signal proxy, and this signal is not needed
+ Q_EMIT m_SignalProxy->SigFrameDraw();
// Debug measure to view the depth map to ensure we're rendering it correctly.
//if (m_Layer.m_TemporalAAEnabled) {
// RenderFakeDepthMapPass(m_ShadowMapManager->GetShadowMapEntry(0)->m_DepthMap,
@@ -1644,7 +1813,7 @@ namespace render {
if (m_Layer.m_MultisampleAAMode != AAModeValues::SSAA) {
// Resolve the FBO to the layer texture
CRendererUtil::ResolveMutisampleFBOColorOnly(
- theResourceManager, m_LayerTexture, theRenderContext,
+ theResourceManager, m_LayerTexture[getCameraIndex()], theRenderContext,
theLayerTextureDimensions.width(), theLayerTextureDimensions.height(),
ColorTextureFormat, *theFB);
@@ -1652,7 +1821,7 @@ namespace render {
} else {
// Resolve the FBO to the layer texture
CRendererUtil::ResolveSSAAFBOColorOnly(
- theResourceManager, m_LayerTexture,
+ theResourceManager, m_LayerTexture[getCameraIndex()],
theLayerOriginalTextureDimensions.width(),
theLayerOriginalTextureDimensions.height(), theRenderContext,
theLayerTextureDimensions.width(), theLayerTextureDimensions.height(),
@@ -1700,18 +1869,18 @@ namespace render {
theRenderContext.SetCullingEnabled(false);
theRenderContext.SetActiveShader(theBlendShader->m_Shader);
theBlendShader->m_AccumSampler.Set(theLastLayerTexture);
- theBlendShader->m_LastFrame.Set(m_LayerTexture);
+ theBlendShader->m_LastFrame.Set(m_LayerTexture[getCameraIndex()]);
theBlendShader->m_BlendFactors.Set(theBlendFactors);
m_Renderer.RenderQuad();
theFB->Attach(NVRenderFrameBufferAttachments::Color0,
qt3ds::render::NVRenderTextureOrRenderBuffer());
if (isTemporalAABlendPass)
- temporalAATexture.StealTexture(m_LayerTexture);
- m_LayerTexture.StealTexture(targetTexture);
+ temporalAATexture.StealTexture(m_LayerTexture[getCameraIndex()]);
+ m_LayerTexture[getCameraIndex()].StealTexture(targetTexture);
}
- m_LayerTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
- m_LayerTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ m_LayerTexture[getCameraIndex()]->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ m_LayerTexture[getCameraIndex()]->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
// Don't remember why needs widget texture is false here.
// Should have commented why progAA plus widgets is a fail.
@@ -1734,6 +1903,8 @@ namespace render {
qt3ds::render::NVRenderTextureOrRenderBuffer(), thFboAttachTarget);
// Let natural scoping rules destroy the other stuff.
}
+ if (m_Layer.m_DynamicResize)
+ theResourceManager.DestroyFreeSizedResources();
}
void SLayerRenderData::ApplyLayerPostEffects()
@@ -1749,10 +1920,10 @@ namespace render {
}
}
if (!effectsActive || !m_Camera) {
- if (m_LayerCachedTexture) {
+ if (m_LayerCachedTexture[getCameraIndex()]) {
IResourceManager &theResourceManager(m_Renderer.GetQt3DSContext().GetResourceManager());
- theResourceManager.Release(*m_LayerCachedTexture);
- m_LayerCachedTexture = NULL;
+ theResourceManager.Release(*m_LayerCachedTexture[getCameraIndex()]);
+ m_LayerCachedTexture[getCameraIndex()] = NULL;
}
return;
}
@@ -1760,14 +1931,24 @@ namespace render {
IEffectSystem &theEffectSystem(m_Renderer.GetQt3DSContext().GetEffectSystem());
IResourceManager &theResourceManager(m_Renderer.GetQt3DSContext().GetResourceManager());
// we use the non MSAA buffer for the effect
- NVRenderTexture2D *theLayerColorTexture = m_LayerTexture;
+ NVRenderTexture2D *theLayerColorTexture = m_LayerTexture[getCameraIndex()];
NVRenderTexture2D *theLayerDepthTexture = m_LayerDepthTexture;
- if (!m_LayerCachedTexture) {
+ if (m_LayerCachedTexture[getCameraIndex()]) {
+ STextureDetails details(theLayerColorTexture->GetTextureDetails());
+ STextureDetails cachedDetails(m_LayerCachedTexture[getCameraIndex()]->GetTextureDetails());
+ if (cachedDetails.m_Width != details.m_Width
+ || cachedDetails.m_Height != details.m_Height) {
+ theResourceManager.Release(*m_LayerCachedTexture[getCameraIndex()]);
+ m_LayerCachedTexture[getCameraIndex()] = nullptr;
+ }
+ }
+
+ if (!m_LayerCachedTexture[getCameraIndex()]) {
STextureDetails details(theLayerColorTexture->GetTextureDetails());
QT3DSU32 finalWidth = ITextRenderer::NextMultipleOf4((QT3DSU32)(details.m_Width));
QT3DSU32 finalHeight = ITextRenderer::NextMultipleOf4((QT3DSU32)(details.m_Height));
- m_LayerCachedTexture = theResourceManager.AllocateTexture2D(finalWidth, finalHeight,
+ m_LayerCachedTexture[getCameraIndex()] = theResourceManager.AllocateTexture2D(finalWidth, finalHeight,
details.m_Format);
}
@@ -1777,7 +1958,7 @@ namespace render {
if (theEffect->m_Flags.IsActive()) {
NVRenderTexture2D *targetTexture = nullptr;
if (theEffect == lastEffect)
- targetTexture = m_LayerCachedTexture;
+ targetTexture = m_LayerCachedTexture[getCameraIndex()];
StartProfiling(theEffect->m_ClassName, false);
@@ -1819,13 +2000,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;
@@ -1872,7 +2053,7 @@ namespace render {
// The render graph should have taken care of the render to texture step.
#ifdef QT3DS_CACHED_POST_EFFECT
NVRenderTexture2D *theLayerColorTexture =
- (m_LayerCachedTexture) ? m_LayerCachedTexture : m_LayerTexture;
+ (m_LayerCachedTexture[getCameraIndex()]) ? m_LayerCachedTexture[getCameraIndex()] : m_LayerTexture[getCameraIndex()];
#else
// Then render all but the last effect
IEffectSystem &theEffectSystem(m_Renderer.GetQt3DSContext().GetEffectSystem());
@@ -1913,10 +2094,12 @@ namespace render {
// transform.
QT3DSMat44 theFinalMVP(QT3DSMat44::createIdentity());
SCamera theTempCamera;
+ // When layer & scene are part of subpresentation, ignore stereoscopic viewport adjustments
+ bool noStereo = m_Layer.m_Scene && m_Layer.m_Scene->m_IsSubPresentationScene;
NVRenderRect theLayerViewport(
- thePrepResult.GetLayerToPresentationViewport().ToIntegerRect());
+ thePrepResult.GetLayerToPresentationViewport(noStereo).ToIntegerRect());
NVRenderRect theLayerClip(
- thePrepResult.GetLayerToPresentationScissorRect().ToIntegerRect());
+ thePrepResult.GetLayerToPresentationScissorRect(noStereo).ToIntegerRect());
{
QT3DSMat33 ignored;
@@ -2214,7 +2397,7 @@ namespace render {
void SLayerRenderData::AddLayerRenderStep()
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::AddLayerRenderStep")
+ "LayerRenderData: AddLayerRenderStep")
QT3DS_ASSERT(m_Camera);
if (!m_Camera)
return;
@@ -2227,13 +2410,13 @@ namespace render {
QSize(theCurrentViewport.m_Width, theCurrentViewport.m_Height));
}
- void SLayerRenderData::PrepareForRender()
+ bool SLayerRenderData::PrepareForRender()
{
// When we render to the scene itself (as opposed to an offscreen buffer somewhere)
// then we use the MVP of the layer somewhat.
NVRenderRect theViewport = m_Renderer.GetQt3DSContext().GetRenderList().GetViewport();
- PrepareForRender(
- QSize((QT3DSU32)theViewport.m_Width, (QT3DSU32)theViewport.m_Height));
+ return PrepareForRender(
+ QSize((QT3DSU32)theViewport.m_Width, (QT3DSU32)theViewport.m_Height));
}
void SLayerRenderData::ResetForFrame()
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
index 0f0a838..623e8b2 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
@@ -33,6 +33,7 @@
#include "Qt3DSRender.h"
#include "Qt3DSRendererImplLayerRenderPreparationData.h"
#include "Qt3DSRenderResourceBufferObjects.h"
+#include "Qt3DSRuntimeView.h"
namespace qt3ds {
namespace render {
@@ -52,7 +53,7 @@ struct AdvancedBlendModes
// Layers can be rendered offscreen for many reasons; effects, progressive aa,
// or just because a flag forces it. If they are rendered offscreen we can then
// cache the result so we don't render the layer again if it isn't dirty.
- CResourceTexture2D m_LayerTexture;
+ CResourceTexture2D m_LayerTexture[2];
// Multiple temporal AA textures for stereoscopic needs.
// First used for mono/left view, second for right view.
CResourceTexture2D m_TemporalAATexture[2];
@@ -66,7 +67,7 @@ struct AdvancedBlendModes
CResourceTexture2D m_LayerMultisamplePrepassDepthTexture;
CResourceTexture2D m_LayerMultisampleWidgetTexture;
// the texture contains the render result inclusive post effects
- NVRenderTexture2D *m_LayerCachedTexture;
+ NVRenderTexture2D *m_LayerCachedTexture[2];
NVRenderTexture2D *m_AdvancedBlendDrawTexture;
NVRenderTexture2D *m_AdvancedBlendBlendTexture;
@@ -97,15 +98,19 @@ struct AdvancedBlendModes
NVRenderTextureFormats::Enum m_DepthBufferFormat;
QSize m_previousDimensions;
+ QRuntimeViewSignalProxy *m_SignalProxy;
+ SLayerRenderPreparationResultFlags m_LeftFlags;
+
+ int getCameraIndex() const;
SLayerRenderData(SLayer &inLayer, Qt3DSRendererImpl &inRenderer);
virtual ~SLayerRenderData();
- void PrepareForRender();
+ bool PrepareForRender();
// Internal Call
- void PrepareForRender(const QSize &inViewportDimensions) override;
+ bool PrepareForRender(const QSize &inViewportDimensions) override;
NVRenderTextureFormats::Enum GetDepthBufferFormat();
NVRenderFrameBufferAttachments::Enum
@@ -125,6 +130,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 +188,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/Qt3DSRendererImplLayerRenderHelper.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp
index 4dae3f9..f75a673 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp
@@ -70,8 +70,8 @@ QT3DSVec2 ToRectRelativeCoords(const QT3DSVec2 &inCoords, const NVRenderRectF &i
SLayerRenderHelper::SLayerRenderHelper()
: m_Layer(nullptr)
, m_Camera(nullptr)
- , m_CameraLeftEye(nullptr)
- , m_CameraRightEye(nullptr)
+ , m_CameraLeftEye()
+ , m_CameraRightEye()
, m_Offscreen(false)
{
}
@@ -84,19 +84,21 @@ SLayerRenderHelper::SLayerRenderHelper(const NVRenderRectF &inPresentationViewpo
qt3ds::render::StereoModes::Enum inStereoMode,
qt3ds::render::StereoViews::Enum inStereoView,
double inStereoEyeSeparation,
+ double inStereoEyeRotation,
qt3ds::QT3DSVec2 inScaleFactor)
: m_PresentationViewport(inPresentationViewport)
, m_PresentationScissor(inPresentationScissor)
, m_PresentationDesignDimensions(inPresentationDesignDimensions)
, m_Layer(&inLayer)
, m_Camera(nullptr)
- , m_CameraLeftEye(nullptr)
- , m_CameraRightEye(nullptr)
+ , m_CameraLeftEye()
+ , m_CameraRightEye()
, m_Offscreen(inOffscreen)
, m_ScaleMode(inScaleMode)
, m_StereoMode(inStereoMode)
, m_StereoView(inStereoView)
, m_StereoEyeSeparation(QT3DSF32(inStereoEyeSeparation))
+ , m_StereoEyeRotation(QT3DSF32(inStereoEyeRotation))
, m_ScaleFactor(inScaleFactor)
{
{
@@ -178,9 +180,9 @@ SLayerRenderHelper::SLayerRenderHelper(const NVRenderRectF &inPresentationViewpo
m_Viewport.m_Width = NVMax(1.0f, m_Viewport.m_Width);
m_Viewport.m_Height = NVMax(1.0f, m_Viewport.m_Height);
- // Now force the viewport to be a multiple of four in width and height. This is because
+ // Now force the viewport to be a multiple of four in width and height. This is because
// when rendering to a texture we have to respect this and not forcing it causes scaling issues
- // that are noticeable especially in situations where customers are using text and such.
+ // that are noticeable especially in situations where customers are using text.
QT3DSF32 originalWidth = m_Viewport.m_Width;
QT3DSF32 originalHeight = m_Viewport.m_Height;
@@ -191,6 +193,7 @@ SLayerRenderHelper::SLayerRenderHelper(const NVRenderRectF &inPresentationViewpo
m_Viewport.m_X += (originalWidth - m_Viewport.m_Width) / 2.0f;
m_Viewport.m_Y += (originalHeight - m_Viewport.m_Height) / 2.0f;
+ m_originalViewport = m_Viewport;
m_Scissor = m_Viewport;
m_Scissor.EnsureInBounds(inPresentationScissor);
QT3DS_ASSERT(m_Scissor.m_Width >= 0.0f);
@@ -206,8 +209,11 @@ NVRenderRectF SLayerRenderHelper::GetLayerRenderViewport() const
return m_Viewport;
}
-NVRenderRectF SLayerRenderHelper::GetLayerToPresentationViewport() const
+NVRenderRectF SLayerRenderHelper::GetLayerToPresentationViewport(bool noStereo) const
{
+ if (noStereo)
+ return m_Viewport;
+
if (m_StereoMode == StereoModes::LeftRight) {
if (m_StereoView == StereoViews::Left) {
return NVRenderRectF(m_Viewport.m_X, m_Viewport.m_Y, m_Viewport.m_Width/2,
@@ -230,8 +236,11 @@ NVRenderRectF SLayerRenderHelper::GetLayerToPresentationViewport() const
return m_Viewport;
}
-NVRenderRectF SLayerRenderHelper::GetLayerToPresentationScissorRect() const
+NVRenderRectF SLayerRenderHelper::GetLayerToPresentationScissorRect(bool noStereo) const
{
+ if (noStereo)
+ return m_Scissor;
+
if (m_StereoMode == StereoModes::LeftRight) {
if (m_StereoView == StereoViews::Left) {
return NVRenderRectF(m_Scissor.m_X, m_Scissor.m_Y,
@@ -265,9 +274,9 @@ QSize SLayerRenderHelper::GetTextureDimensions() const
SCamera *SLayerRenderHelper::GetCamera() {
if (m_StereoView == StereoViews::Left)
- return m_CameraLeftEye;
+ return &m_CameraLeftEye;
if (m_StereoView == StereoViews::Right)
- return m_CameraRightEye;
+ return &m_CameraRightEye;
return m_Camera;
}
@@ -275,8 +284,10 @@ SCameraGlobalCalculationResult SLayerRenderHelper::SetupCameraForRender(SCamera
{
m_Camera = &inCamera;
- if (isStereoscopic())
+ if (isStereoscopic()) {
+ m_Camera->AddChild(*GetCamera());
adjustCameraStereoSeparation();
+ }
NVRenderRectF rect = GetLayerRenderViewport();
if (m_ScaleMode == ScaleModes::FitSelected) {
@@ -286,10 +297,13 @@ SCameraGlobalCalculationResult SLayerRenderHelper::SetupCameraForRender(SCamera
(QT3DSF32)(ITextRenderer::NextMultipleOf4((QT3DSU32)(rect.m_Height / m_ScaleFactor.y)));
}
// Always calculate main camera variables
- if (isStereoscopic())
- m_Camera->CalculateGlobalVariables(rect, m_PresentationDesignDimensions);
- // Return current camera variables
- return GetCamera()->CalculateGlobalVariables(rect, m_PresentationDesignDimensions);
+ auto ret = m_Camera->CalculateGlobalVariables(rect, m_PresentationDesignDimensions);
+ if (isStereoscopic()) {
+ GetCamera()->CalculateGlobalVariables(rect, m_PresentationDesignDimensions);
+ m_Camera->RemoveChild(*GetCamera());
+ }
+
+ return ret;
}
Option<QT3DSVec2> SLayerRenderHelper::GetLayerMouseCoords(const QT3DSVec2 &inMouseCoords,
@@ -299,7 +313,16 @@ Option<QT3DSVec2> SLayerRenderHelper::GetLayerMouseCoords(const QT3DSVec2 &inMou
// First invert the y so we are dealing with numbers in a normal coordinate space.
// Second, move into our layer's coordinate space
QT3DSVec2 correctCoords(inMouseCoords.x, inWindowDimensions.y - inMouseCoords.y);
- QT3DSVec2 theLocalMouse = m_Viewport.ToRectRelative(correctCoords);
+ QT3DSVec2 theLocalMouse;
+
+ if (m_Layer->m_DynamicResize) {
+ float widthRatio = m_Viewport.m_Width / m_originalViewport.m_Width;
+ float heightRatio = m_Viewport.m_Height / m_originalViewport.m_Height;
+ theLocalMouse = m_originalViewport.ToRectRelative(correctCoords);
+ theLocalMouse = QT3DSVec2(theLocalMouse.x * widthRatio, theLocalMouse.y * heightRatio);
+ } else {
+ theLocalMouse = m_Viewport.ToRectRelative(correctCoords);
+ }
QT3DSF32 theRenderRectWidth = m_Viewport.m_Width;
QT3DSF32 theRenderRectHeight = m_Viewport.m_Height;
@@ -341,8 +364,32 @@ bool SLayerRenderHelper::isStereoscopic() const
return m_StereoMode != StereoModes::Mono;
}
-void SLayerRenderHelper::copyCameraProperties(SCamera *sourceCamera,
- SCamera *destinationCamera)
+void SLayerRenderHelper::setViewport(const NVRenderRectF &viewport)
+{
+ m_Viewport = viewport;
+ m_Viewport.m_Width = NVMax(1.0f, m_Viewport.m_Width);
+ m_Viewport.m_Height = NVMax(1.0f, m_Viewport.m_Height);
+ // Now force the viewport to be a multiple of four in width and height. This is because
+ // when rendering to a texture we have to respect this and not forcing it causes scaling issues
+ // that are noticeable especially in situations where customers are using text.
+ QT3DSF32 originalWidth = m_Viewport.m_Width;
+ QT3DSF32 originalHeight = m_Viewport.m_Height;
+
+ m_Viewport.m_Width = (QT3DSF32)ITextRenderer::NextMultipleOf4((QT3DSU32)m_Viewport.m_Width);
+ m_Viewport.m_Height = (QT3DSF32)ITextRenderer::NextMultipleOf4((QT3DSU32)m_Viewport.m_Height);
+
+ // Now fudge the offsets to account for this slight difference
+ m_Viewport.m_X += (originalWidth - m_Viewport.m_Width) / 2.0f;
+ m_Viewport.m_Y += (originalHeight - m_Viewport.m_Height) / 2.0f;
+}
+
+NVRenderRectF SLayerRenderHelper::getOriginalLayerToPresentationViewport() const
+{
+ return m_originalViewport;
+}
+
+void SLayerRenderHelper::copyCameraStereoProperties(SCamera *sourceCamera,
+ SCamera *destinationCamera)
{
if (!sourceCamera || !destinationCamera)
return;
@@ -360,33 +407,27 @@ void SLayerRenderHelper::copyCameraProperties(SCamera *sourceCamera,
destinationCamera->m_Pivot = sourceCamera->m_Pivot;
destinationCamera->m_Scale = sourceCamera->m_Scale;
destinationCamera->m_DFSIndex = sourceCamera->m_DFSIndex;
- destinationCamera->m_Position = sourceCamera->m_Position;
- destinationCamera->m_Rotation = sourceCamera->m_Rotation;
- destinationCamera->m_UserData = sourceCamera->m_UserData;
- destinationCamera->m_LocalOpacity = sourceCamera->m_LocalOpacity;
- destinationCamera->m_GlobalOpacity = sourceCamera->m_GlobalOpacity;
destinationCamera->m_RotationOrder = sourceCamera->m_RotationOrder;
- destinationCamera->m_LocalTransform = sourceCamera->m_LocalTransform;
- destinationCamera->m_GlobalTransform = sourceCamera->m_GlobalTransform;
}
void SLayerRenderHelper::adjustCameraStereoSeparation()
{
- if (!m_CameraLeftEye)
- m_CameraLeftEye = new SCamera();
- if (!m_CameraRightEye)
- m_CameraRightEye = new SCamera();
-
// Copy m_Camera properties into left & right cameras
- copyCameraProperties(m_Camera, m_CameraLeftEye);
- copyCameraProperties(m_Camera, m_CameraRightEye);
+ copyCameraStereoProperties(m_Camera, &m_CameraLeftEye);
+ copyCameraStereoProperties(m_Camera, &m_CameraRightEye);
// Adjust left & right camera positions by eye separation
- m_CameraLeftEye->m_Position.x -= m_StereoEyeSeparation;
- m_CameraLeftEye->m_Flags.SetTransformDirty(true);
- m_CameraRightEye->m_Position.x += m_StereoEyeSeparation;
- m_CameraRightEye->m_Flags.SetTransformDirty(true);
-
- m_CameraLeftEye->MarkDirty();
- m_CameraRightEye->MarkDirty();
+ QT3DSVec3 eyeMove(m_StereoEyeSeparation, 0, 0);
+ m_CameraLeftEye.m_Position = -eyeMove;
+ m_CameraLeftEye.m_Flags.SetTransformDirty(true);
+ m_CameraRightEye.m_Position = eyeMove;
+ m_CameraRightEye.m_Flags.SetTransformDirty(true);
+
+ // Adjust left & right camera rotations
+ QT3DSVec3 eyeRotation(0, m_StereoEyeRotation, 0);
+ m_CameraLeftEye.m_Rotation = eyeRotation;
+ m_CameraRightEye.m_Rotation = -eyeRotation;
+
+ m_CameraLeftEye.MarkDirty();
+ m_CameraRightEye.MarkDirty();
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h
index 19fd3f5..2c64569 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h
@@ -60,10 +60,11 @@ namespace render {
QT3DSVec2 m_PresentationDesignDimensions;
SLayer *m_Layer;
SCamera *m_Camera;
- SCamera *m_CameraLeftEye;
- SCamera *m_CameraRightEye;
+ SCamera m_CameraLeftEye;
+ SCamera m_CameraRightEye;
bool m_Offscreen;
+ NVRenderRectF m_originalViewport;
NVRenderRectF m_Viewport;
NVRenderRectF m_Scissor;
@@ -72,6 +73,7 @@ namespace render {
StereoModes::Enum m_StereoMode = StereoModes::Mono;
StereoViews::Enum m_StereoView = StereoViews::Mono;
QT3DSF32 m_StereoEyeSeparation = 0.4f;
+ QT3DSF32 m_StereoEyeRotation = 0.0f;
QT3DSVec2 m_ScaleFactor;
@@ -85,6 +87,7 @@ namespace render {
qt3ds::render::StereoModes::Enum inStereoMode,
qt3ds::render::StereoViews::Enum inStereoView,
double inStereoEyeSeparation,
+ double inStereoEyeRotation,
qt3ds::QT3DSVec2 inScaleFactor);
NVRenderRectF GetPresentationViewport() const { return m_PresentationViewport; }
@@ -102,13 +105,18 @@ namespace render {
// Get/set eye (camera) separation.
QT3DSF32 getEyeSeparation() const { return m_StereoEyeSeparation; }
void setEyeSeparation(QT3DSF32 separation) { m_StereoEyeSeparation = separation; }
+ // Get/set eye (camera) rotation.
+ QT3DSF32 getEyeRotation() const { return m_StereoEyeRotation; }
+ void setEyeRotation(QT3DSF32 rotation) { m_StereoEyeRotation = rotation; }
+ void setViewport(const NVRenderRectF &viewport);
// Does not differ whether offscreen or not, simply states how this layer maps to the
// presentation
- NVRenderRectF GetLayerToPresentationViewport() const;
+ NVRenderRectF getOriginalLayerToPresentationViewport() const;
+ NVRenderRectF GetLayerToPresentationViewport(bool noStereo = false) const;
// Does not differ whether offscreen or not, scissor rect of how this layer maps to
// presentation.
- NVRenderRectF GetLayerToPresentationScissorRect() const;
+ NVRenderRectF GetLayerToPresentationScissorRect(bool noStereo = false) const;
QSize GetTextureDimensions() const;
@@ -130,7 +138,7 @@ namespace render {
// different than the layer to presentation viewport.
NVRenderRectF GetLayerRenderViewport() const;
- void copyCameraProperties(SCamera *sourceCamera, SCamera *destinationCamera);
+ void copyCameraStereoProperties(SCamera *sourceCamera, SCamera *destinationCamera);
void adjustCameraStereoSeparation();
};
}
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.
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h
index eae29f6..fd9b86e 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,12 @@ namespace render {
nvvector<SLight *> m_Lights; // Only contains lights that are global.
TRenderableObjectList m_OpaqueObjects;
TRenderableObjectList m_TransparentObjects;
+ TRenderableObjectList m_GroupObjects;
+ QVector<QT3DSVec3> m_boundPoints;
+ NVRenderRectF m_dynamicSize;
+ NVRenderRectF m_unpaddedDynamicSize;
+ float m_lastDynamicPadding = 0;
+ LayerUnitTypes::Enum m_lastDynamicPaddingUnits = LayerUnitTypes::Percent;
// Sorted lists of the rendered objects. There may be other transforms applied so
// it is simplest to duplicate the lists.
TRenderableObjectList m_RenderedOpaqueObjects;
@@ -294,6 +301,7 @@ namespace render {
bool m_FeaturesDirty;
size_t m_FeatureSetHash;
bool m_TooManyLightsError;
+ StereoModes::Enum m_StereoMode;
// shadow mapps
NVScopedRefCounted<Qt3DSShadowMap> m_ShadowMapManager;
@@ -323,23 +331,28 @@ 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,
QT3DSF32 inTextScaleFactor,
SLayerRenderPreparationResultFlags &ioFlags);
+ void calculateDynamicLayerSize(SLayerRenderPreparationResult &prepResult);
+
// returns true if this object will render something different than it rendered the last
// time.
- virtual void PrepareForRender(const QSize &inViewportDimensions);
+ virtual bool PrepareForRender(const QSize &inViewportDimensions);
bool CheckLightProbeDirty(SImage &inLightProbe);
void AddRenderWidget(IRenderWidget &inWidget);
void SetShaderFeature(const char *inName, bool inValue);