summaryrefslogtreecommitdiffstats
path: root/src/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/render')
-rw-r--r--src/render/backend/abstractrenderer_p.h3
-rw-r--r--src/render/backend/offscreensurfacehelper.cpp1
-rw-r--r--src/render/backend/platformsurfacefilter.cpp4
-rw-r--r--src/render/framegraph/framegraphnode.cpp1
-rw-r--r--src/render/framegraph/qlayerfilter.cpp4
-rw-r--r--src/render/framegraph/qrenderpassfilter.cpp8
-rw-r--r--src/render/framegraph/qrenderstateset.cpp4
-rw-r--r--src/render/framegraph/qsubtreeenabler.cpp2
-rw-r--r--src/render/framegraph/qtechniquefilter.cpp8
-rw-r--r--src/render/frontend/qcomputecommand.cpp2
-rw-r--r--src/render/frontend/qrenderaspect.cpp1
-rw-r--r--src/render/frontend/qrenderaspect_p.h2
-rw-r--r--src/render/frontend/qrenderplugin_p.h4
-rw-r--r--src/render/frontend/qrendertarget.cpp4
-rw-r--r--src/render/frontend/sphere.cpp50
-rw-r--r--src/render/frontend/sphere_p.h13
-rw-r--r--src/render/geometry/buffer.cpp4
-rw-r--r--src/render/geometry/qbuffer.cpp2
-rw-r--r--src/render/geometry/qgeometry.cpp4
-rw-r--r--src/render/jobs/calcboundingvolumejob.cpp78
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp122
-rw-r--r--src/render/jobs/pickboundingvolumejob_p.h3
-rw-r--r--src/render/materialsystem/qeffect.cpp12
-rw-r--r--src/render/materialsystem/qfilterkey.cpp4
-rw-r--r--src/render/materialsystem/qmaterial.cpp4
-rw-r--r--src/render/materialsystem/qparameter.cpp4
-rw-r--r--src/render/materialsystem/qrenderpass.cpp12
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder.cpp88
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder.h1
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder_p.h6
-rw-r--r--src/render/materialsystem/qtechnique.cpp16
-rw-r--r--src/render/materialsystem/shader.cpp38
-rw-r--r--src/render/materialsystem/shader_p.h7
-rw-r--r--src/render/materialsystem/shaderbuilder.cpp63
-rw-r--r--src/render/materialsystem/shaderbuilder_p.h36
-rw-r--r--src/render/picking/objectpicker.cpp55
-rw-r--r--src/render/picking/objectpicker_p.h7
-rw-r--r--src/render/picking/picking.pri1
-rw-r--r--src/render/picking/qobjectpicker.cpp42
-rw-r--r--src/render/picking/qobjectpicker.h3
-rw-r--r--src/render/picking/qobjectpicker_p.h1
-rw-r--r--src/render/picking/qpickevent_p.h4
-rw-r--r--src/render/picking/qpicktriangleevent.cpp51
-rw-r--r--src/render/picking/qpicktriangleevent_p.h69
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp5
-rw-r--r--src/render/renderers/opengl/jobs/renderviewjobutils.cpp2
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp107
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h26
-rw-r--r--src/render/renderers/opengl/renderer/renderview.cpp23
-rw-r--r--src/render/renderstates/qrenderstate.cpp1
-rw-r--r--src/render/texture/qabstracttexture.cpp108
-rw-r--r--src/render/texture/qtexture.cpp82
52 files changed, 799 insertions, 403 deletions
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index 006919512..b618eda55 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
class QSurface;
class QSize;
+class QScreen;
namespace Qt3DCore {
class QAbstractFrameAdvanceService;
@@ -175,6 +176,8 @@ public:
// For QtQuick rendering
virtual void setOpenGLContext(QOpenGLContext *ctx) = 0;
+ virtual void setScreen(QScreen *) {}
+ virtual QScreen *screen() const { return nullptr; }
virtual void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) = 0;
virtual QSurfaceFormat format() = 0;
diff --git a/src/render/backend/offscreensurfacehelper.cpp b/src/render/backend/offscreensurfacehelper.cpp
index 89dc6211f..38558d484 100644
--- a/src/render/backend/offscreensurfacehelper.cpp
+++ b/src/render/backend/offscreensurfacehelper.cpp
@@ -72,6 +72,7 @@ void OffscreenSurfaceHelper::createOffscreenSurface()
m_offscreenSurface = new QOffscreenSurface;
m_offscreenSurface->setParent(this);
m_offscreenSurface->setFormat(m_renderer->format());
+ m_offscreenSurface->setScreen(m_renderer->screen());
m_offscreenSurface->create();
}
diff --git a/src/render/backend/platformsurfacefilter.cpp b/src/render/backend/platformsurfacefilter.cpp
index 7458f607d..891e30c44 100644
--- a/src/render/backend/platformsurfacefilter.cpp
+++ b/src/render/backend/platformsurfacefilter.cpp
@@ -107,10 +107,6 @@ bool PlatformSurfaceFilter::eventFilter(QObject *obj, QEvent *e)
// If we remove it, the call to isSurfaceValid will
// implicitely return false
PlatformSurfaceFilter::m_surfacesValidity.remove(m_surface);
- if (m_obj) {
- m_obj->removeEventFilter(this);
- m_obj = nullptr;
- }
break;
}
diff --git a/src/render/framegraph/framegraphnode.cpp b/src/render/framegraph/framegraphnode.cpp
index 58ff05dc0..40d8fca3d 100644
--- a/src/render/framegraph/framegraphnode.cpp
+++ b/src/render/framegraph/framegraphnode.cpp
@@ -123,6 +123,7 @@ QVector<FrameGraphNode *> FrameGraphNode::children() const
void FrameGraphNode::cleanup()
{
setParentId({});
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
void FrameGraphNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
diff --git a/src/render/framegraph/qlayerfilter.cpp b/src/render/framegraph/qlayerfilter.cpp
index 5080012fd..8bad46f5d 100644
--- a/src/render/framegraph/qlayerfilter.cpp
+++ b/src/render/framegraph/qlayerfilter.cpp
@@ -203,7 +203,7 @@ void QLayerFilter::addLayer(QLayer *layer)
if (!layer->parent())
layer->setParent(this);
- d->update();
+ d->updateNode(layer, "layer", Qt3DCore::PropertyValueAdded);
}
}
@@ -214,7 +214,7 @@ void QLayerFilter::removeLayer(QLayer *layer)
{
Q_ASSERT(layer);
Q_D(QLayerFilter);
- d->update();
+ d->updateNode(layer, "layer", Qt3DCore::PropertyValueRemoved);
d->m_layers.removeOne(layer);
// Remove bookkeeping connection
d->unregisterDestructionHelper(layer);
diff --git a/src/render/framegraph/qrenderpassfilter.cpp b/src/render/framegraph/qrenderpassfilter.cpp
index 778d3fa1f..952657eb6 100644
--- a/src/render/framegraph/qrenderpassfilter.cpp
+++ b/src/render/framegraph/qrenderpassfilter.cpp
@@ -139,7 +139,7 @@ void QRenderPassFilter::addMatch(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- d->update();
+ d->updateNode(filterKey, "match", Qt3DCore::PropertyValueAdded);
}
}
@@ -151,7 +151,7 @@ void QRenderPassFilter::removeMatch(QFilterKey *filterKey)
Q_ASSERT(filterKey);
Q_D(QRenderPassFilter);
- d->update();
+ d->updateNode(filterKey, "match", Qt3DCore::PropertyValueRemoved);
d->m_matchList.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -177,7 +177,7 @@ void QRenderPassFilter::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -189,7 +189,7 @@ void QRenderPassFilter::removeParameter(QParameter *parameter)
Q_ASSERT(parameter);
Q_D(QRenderPassFilter);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
diff --git a/src/render/framegraph/qrenderstateset.cpp b/src/render/framegraph/qrenderstateset.cpp
index 8c2c6ee7f..5341b3c7d 100644
--- a/src/render/framegraph/qrenderstateset.cpp
+++ b/src/render/framegraph/qrenderstateset.cpp
@@ -191,7 +191,7 @@ void QRenderStateSet::addRenderState(QRenderState *state)
if (!state->parent())
state->setParent(this);
- d->update();
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueAdded);
}
}
@@ -203,7 +203,7 @@ void QRenderStateSet::removeRenderState(QRenderState *state)
Q_ASSERT(state);
Q_D(QRenderStateSet);
- d->update();
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueRemoved);
d->m_renderStates.removeOne(state);
// Remove bookkeeping connection
d->unregisterDestructionHelper(state);
diff --git a/src/render/framegraph/qsubtreeenabler.cpp b/src/render/framegraph/qsubtreeenabler.cpp
index d2c25852b..e5d182d00 100644
--- a/src/render/framegraph/qsubtreeenabler.cpp
+++ b/src/render/framegraph/qsubtreeenabler.cpp
@@ -164,7 +164,7 @@ void QSubtreeEnabler::setEnablement(QSubtreeEnabler::Enablement enablement)
/*!
Requests that the subtree be enabled.
- A conveninence method intended to be used with \c SingleShot enablement.
+ A convenience method intended to be used with \c SingleShot enablement.
*/
void QSubtreeEnabler::requestUpdate()
{
diff --git a/src/render/framegraph/qtechniquefilter.cpp b/src/render/framegraph/qtechniquefilter.cpp
index 03e6a8ca7..c22e83381 100644
--- a/src/render/framegraph/qtechniquefilter.cpp
+++ b/src/render/framegraph/qtechniquefilter.cpp
@@ -144,7 +144,7 @@ void QTechniqueFilter::addMatch(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- d->update();
+ d->updateNode(filterKey, "matchAll", Qt3DCore::PropertyValueAdded);
}
}
@@ -155,7 +155,7 @@ void QTechniqueFilter::removeMatch(QFilterKey *filterKey)
{
Q_ASSERT(filterKey);
Q_D(QTechniqueFilter);
- d->update();
+ d->updateNode(filterKey, "matchAll", Qt3DCore::PropertyValueRemoved);
d->m_matchList.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -181,7 +181,7 @@ void QTechniqueFilter::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -192,7 +192,7 @@ void QTechniqueFilter::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QTechniqueFilter);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
diff --git a/src/render/frontend/qcomputecommand.cpp b/src/render/frontend/qcomputecommand.cpp
index d040150d5..d0c9f5805 100644
--- a/src/render/frontend/qcomputecommand.cpp
+++ b/src/render/frontend/qcomputecommand.cpp
@@ -66,7 +66,7 @@ namespace Qt3DRender {
/*!
\qmltype ComputeCommand
\since 5.7
- \inmodule Qt3DRender
+ \inqmlmodule Qt3D.Render
\inherits Component3D
\instantiates Qt3DRender::QComputeCommand
\brief Component to issue work for the compute shader on GPU.
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index 159c11981..271eb9c11 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -562,6 +562,7 @@ void QRenderAspect::onRegistered()
// TO DO: Load proper Renderer class based on Qt configuration preferences
d->m_renderer = new Render::Renderer(d->m_renderType);
+ d->m_renderer->setScreen(d->m_screen);
d->m_renderer->setNodeManagers(d->m_nodeManagers);
// Create a helper for deferring creation of an offscreen surface used during cleanup
diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h
index 8ef4ecd12..62e373b11 100644
--- a/src/render/frontend/qrenderaspect_p.h
+++ b/src/render/frontend/qrenderaspect_p.h
@@ -60,6 +60,7 @@
QT_BEGIN_NAMESPACE
class QSurface;
+class QScreen;
namespace Qt3DRender {
@@ -106,6 +107,7 @@ public:
QVector<Render::QRenderPlugin *> m_renderPlugins;
QRenderAspect::RenderType m_renderType;
Render::OffscreenSurfaceHelper *m_offscreenHelper;
+ QScreen *m_screen = nullptr;
static QMutex m_pluginLock;
static QVector<QString> m_pluginConfig;
diff --git a/src/render/frontend/qrenderplugin_p.h b/src/render/frontend/qrenderplugin_p.h
index c34dabefc..110c8295a 100644
--- a/src/render/frontend/qrenderplugin_p.h
+++ b/src/render/frontend/qrenderplugin_p.h
@@ -75,6 +75,10 @@ protected:
{
aspect->registerBackendType(obj, functor);
}
+ void registerBackendType(QRenderAspect *aspect, const QMetaObject &obj, const Qt3DCore::QBackendNodeMapperPtr &functor, bool supportsSyncing)
+ {
+ aspect->registerBackendType(obj, functor, supportsSyncing);
+ }
void unregisterBackendType(QRenderAspect *aspect, const QMetaObject &obj)
{
aspect->unregisterBackendType(obj);
diff --git a/src/render/frontend/qrendertarget.cpp b/src/render/frontend/qrendertarget.cpp
index 7269a8067..57eecd795 100644
--- a/src/render/frontend/qrendertarget.cpp
+++ b/src/render/frontend/qrendertarget.cpp
@@ -123,7 +123,7 @@ void QRenderTarget::addOutput(QRenderTargetOutput *output)
if (!output->parent())
output->setParent(this);
- d->update();
+ d->updateNode(output, "output", Qt3DCore::PropertyValueAdded);
}
}
@@ -134,7 +134,7 @@ void QRenderTarget::removeOutput(QRenderTargetOutput *output)
{
Q_D(QRenderTarget);
- d->update();
+ d->updateNode(output, "output", Qt3DCore::PropertyValueRemoved);
d->m_outputs.removeOne(output);
// Remove bookkeeping connection
d->unregisterDestructionHelper(output);
diff --git a/src/render/frontend/sphere.cpp b/src/render/frontend/sphere.cpp
index 4909acaef..470dbfe59 100644
--- a/src/render/frontend/sphere.cpp
+++ b/src/render/frontend/sphere.cpp
@@ -44,6 +44,7 @@
#include <QPair>
#include <math.h>
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -55,6 +56,9 @@ namespace {
// returns true and intersection point q; false otherwise
bool intersectRaySphere(const Qt3DRender::RayCasting::QRay3D &ray, const Qt3DRender::Render::Sphere &s, Vector3D *q = nullptr)
{
+ if (s.isNull())
+ return false;
+
const Vector3D p = ray.origin();
const Vector3D d = ray.direction();
const Vector3D m = p - s.center();
@@ -139,11 +143,31 @@ inline void sphereFromExtremePoints(Qt3DRender::Render::Sphere &s, const QVector
inline void constructRitterSphere(Qt3DRender::Render::Sphere &s, const QVector<Vector3D> &points)
{
- // Calculate the sphere encompassing two axially extreme points
- sphereFromExtremePoints(s, points);
-
- // Now make sure the sphere bounds all points by growing if needed
- s.expandToContain(points);
+ //def bounding_sphere(points):
+ // dist = lambda a,b: ((a[0] - b[0])**2 + (a[1] - b[1])**2 + (a[2] - b[2])**2)**0.5
+ // x = points[0]
+ // y = max(points,key= lambda p: dist(p,x) )
+ // z = max(points,key= lambda p: dist(p,y) )
+ // bounding_sphere = (((y[0]+z[0])/2,(y[1]+z[1])/2,(y[2]+z[2])/2), dist(y,z)/2)
+ //
+ // exterior_points = [p for p in points if dist(p,bounding_sphere[0]) > bounding_sphere[1] ]
+ // while ( len(exterior_points) > 0 ):
+ // pt = exterior_points.pop()
+ // if (dist(pt, bounding_sphere[0]) > bounding_sphere[1]):
+ // bounding_sphere = (bounding_sphere[0],dist(pt,bounding_sphere[0]))
+ //
+ // return bounding_sphere
+
+ const Vector3D x = points[0];
+ const Vector3D y = *std::max_element(points.begin(), points.end(), [&x](const Vector3D& lhs, const Vector3D& rhs){ return (lhs - x).lengthSquared() < (rhs - x).lengthSquared(); });
+ const Vector3D z = *std::max_element(points.begin(), points.end(), [&y](const Vector3D& lhs, const Vector3D& rhs){ return (lhs - y).lengthSquared() < (rhs - y).lengthSquared(); });
+
+ const Vector3D center = (y + z) * 0.5f;
+ const Vector3D maxDistPt = *std::max_element(points.begin(), points.end(), [&center](const Vector3D& lhs, const Vector3D& rhs){ return (lhs - center).lengthSquared() < (rhs - center).lengthSquared(); });
+ const float radius = (maxDistPt - center).length();
+
+ s.setCenter(center);
+ s.setRadius(radius);
}
} // anonymous namespace
@@ -169,6 +193,12 @@ void Sphere::initializeFromPoints(const QVector<Vector3D> &points)
void Sphere::expandToContain(const Vector3D &p)
{
+ if (isNull()) {
+ m_center = p;
+ m_radius = 0.0f;
+ return;
+ }
+
const Vector3D d = p - m_center;
const float dist2 = d.lengthSquared();
@@ -184,6 +214,13 @@ void Sphere::expandToContain(const Vector3D &p)
void Sphere::expandToContain(const Sphere &sphere)
{
+ if (isNull()) {
+ *this = sphere;
+ return;
+ } else if (sphere.isNull()) {
+ return;
+ }
+
const Vector3D d(sphere.m_center - m_center);
const float dist2 = d.lengthSquared();
@@ -206,6 +243,9 @@ void Sphere::expandToContain(const Sphere &sphere)
Sphere Sphere::transformed(const Matrix4x4 &mat) const
{
+ if (isNull())
+ return *this;
+
// Transform extremities in x, y, and z directions to find extremities
// of the resulting ellipsoid
Vector3D x = mat.map(m_center + Vector3D(m_radius, 0.0f, 0.0f));
diff --git a/src/render/frontend/sphere_p.h b/src/render/frontend/sphere_p.h
index 10cf92091..b7585f85a 100644
--- a/src/render/frontend/sphere_p.h
+++ b/src/render/frontend/sphere_p.h
@@ -69,7 +69,7 @@ class Q_3DRENDERSHARED_PRIVATE_EXPORT Sphere : public RayCasting::BoundingSphere
public:
inline Sphere(Qt3DCore::QNodeId i = Qt3DCore::QNodeId())
: m_center()
- , m_radius(0.0f)
+ , m_radius(-1.0f)
, m_id(i)
{}
@@ -82,7 +82,7 @@ public:
void setCenter(const Vector3D &c);
Vector3D center() const override;
- inline bool isNull() { return m_center == Vector3D() && m_radius == 0.0f; }
+ bool isNull() const { return m_center == Vector3D() && m_radius == -1.0f; }
void setRadius(float r);
float radius() const override;
@@ -131,7 +131,9 @@ inline Vector3D Sphere::center() const
inline void Sphere::setRadius(float r)
{
- m_radius = r;
+ Q_ASSERT(r >= 0.0f);
+ if (r >= 0.0f)
+ m_radius = r;
}
inline float Sphere::radius() const
@@ -142,11 +144,14 @@ inline float Sphere::radius() const
inline void Sphere::clear()
{
m_center = Vector3D();
- m_radius = 0.0f;
+ m_radius = -1.0f;
}
inline bool intersects(const Sphere &a, const Sphere &b)
{
+ if (a.isNull() || b.isNull())
+ return false;
+
// Calculate squared distance between sphere centers
const Vector3D d = a.center() - b.center();
const float distSq = Vector3D::dotProduct(d, d);
diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp
index 998db3640..0ce81efc1 100644
--- a/src/render/geometry/buffer.cpp
+++ b/src/render/geometry/buffer.cpp
@@ -130,8 +130,10 @@ void Buffer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
if (!node)
return;
- if (firstTime && m_manager != nullptr)
+ if (firstTime && m_manager != nullptr) {
m_manager->addBufferReference(peerId());
+ m_bufferDirty = true;
+ }
m_syncData = node->isSyncData();
m_access = node->accessType();
diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp
index f27005f2b..d27da25c7 100644
--- a/src/render/geometry/qbuffer.cpp
+++ b/src/render/geometry/qbuffer.cpp
@@ -329,7 +329,7 @@ void QBuffer::setData(const QByteArray &bytes)
Q_D(QBuffer);
if (bytes != d->m_data) {
d->m_data = bytes;
- Qt3DCore::QNodePrivate::get(this)->update();
+ d->update();
emit dataChanged(bytes);
}
}
diff --git a/src/render/geometry/qgeometry.cpp b/src/render/geometry/qgeometry.cpp
index 4b0bca3b3..48f054bce 100644
--- a/src/render/geometry/qgeometry.cpp
+++ b/src/render/geometry/qgeometry.cpp
@@ -194,7 +194,7 @@ void QGeometry::addAttribute(QAttribute *attribute)
if (!attribute->parent())
attribute->setParent(this);
- d->update();
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueAdded);
}
}
@@ -209,7 +209,7 @@ void QGeometry::removeAttribute(QAttribute *attribute)
d->m_attributes.removeOne(attribute);
// Remove bookkeeping connection
d->unregisterDestructionHelper(attribute);
- d->update();
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved);
}
void QGeometry::setBoundingVolumePositionAttribute(QAttribute *boundingVolumePositionAttribute)
diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp
index 113dc34ce..9af2f4f38 100644
--- a/src/render/jobs/calcboundingvolumejob.cpp
+++ b/src/render/jobs/calcboundingvolumejob.cpp
@@ -90,30 +90,42 @@ public:
m_min = QVector3D(findExtremePoints.xMin, findExtremePoints.yMin, findExtremePoints.zMin);
m_max = QVector3D(findExtremePoints.xMax, findExtremePoints.yMax, findExtremePoints.zMax);
- // Calculate squared distance for the pairs of points
- const float xDist2 = (findExtremePoints.xMaxPt - findExtremePoints.xMinPt).lengthSquared();
- const float yDist2 = (findExtremePoints.yMaxPt - findExtremePoints.yMinPt).lengthSquared();
- const float zDist2 = (findExtremePoints.zMaxPt - findExtremePoints.zMinPt).lengthSquared();
-
- // Select most distant pair
- Vector3D p = findExtremePoints.xMinPt;
- Vector3D q = findExtremePoints.xMaxPt;
- if (yDist2 > xDist2 && yDist2 > zDist2) {
- p = findExtremePoints.yMinPt;
- q = findExtremePoints.yMaxPt;
+ FindMaxDistantPoint maxDistantPointY(m_manager);
+ maxDistantPointY.setReferencePoint = true;
+ if (!maxDistantPointY.apply(positionAttribute, indexAttribute, drawVertexCount,
+ primitiveRestartEnabled, primitiveRestartIndex)) {
+ return false;
}
- if (zDist2 > xDist2 && zDist2 > yDist2) {
- p = findExtremePoints.zMinPt;
- q = findExtremePoints.zMaxPt;
+ if (maxDistantPointY.hasNoPoints)
+ return false;
+
+ //const Vector3D x = maxDistantPointY.referencePt;
+ const Vector3D y = maxDistantPointY.maxDistPt;
+
+ FindMaxDistantPoint maxDistantPointZ(m_manager);
+ maxDistantPointZ.setReferencePoint = false;
+ maxDistantPointZ.referencePt = y;
+ if (!maxDistantPointZ.apply(positionAttribute, indexAttribute, drawVertexCount,
+ primitiveRestartEnabled, primitiveRestartIndex)) {
+ return false;
+ }
+ const Vector3D z = maxDistantPointZ.maxDistPt;
+
+ const Vector3D center = (y + z) * 0.5f;
+
+ FindMaxDistantPoint maxDistantPointCenter(m_manager);
+ maxDistantPointCenter.setReferencePoint = false;
+ maxDistantPointCenter.referencePt = center;
+ if (!maxDistantPointCenter.apply(positionAttribute, indexAttribute, drawVertexCount,
+ primitiveRestartEnabled, primitiveRestartIndex)) {
+ return false;
}
- const Vector3D c = 0.5f * (p + q);
- m_volume.setCenter(c);
- m_volume.setRadius((q - c).length());
+ const float radius = (center - maxDistantPointCenter.maxDistPt).length();
- ExpandSphere expandSphere(m_manager, m_volume);
- if (!expandSphere.apply(positionAttribute, indexAttribute, drawVertexCount,
- primitiveRestartEnabled, primitiveRestartIndex))
+ m_volume = Qt3DRender::Render::Sphere(center, radius);
+
+ if (m_volume.isNull())
return false;
return true;
@@ -172,18 +184,34 @@ private:
}
};
- class ExpandSphere : public Buffer3fVisitor
+ class FindMaxDistantPoint : public Buffer3fVisitor
{
public:
- ExpandSphere(NodeManagers *manager, Sphere& volume)
- : Buffer3fVisitor(manager), m_volume(volume)
+ FindMaxDistantPoint(NodeManagers *manager)
+ : Buffer3fVisitor(manager)
{ }
- Sphere& m_volume;
+ float maxLengthSquared = 0.0f;
+ Vector3D maxDistPt;
+ Vector3D referencePt;
+ bool setReferencePoint = false;
+ bool hasNoPoints = true;
+
void visit(uint ndx, float x, float y, float z) override
{
Q_UNUSED(ndx);
- m_volume.expandToContain(Vector3D(x, y, z));
+ const Vector3D p = Vector3D(x, y, z);
+
+ if (hasNoPoints && setReferencePoint) {
+ maxLengthSquared = 0.0f;
+ referencePt = p;
+ }
+ const float lengthSquared = (p - referencePt).lengthSquared();
+ if ( lengthSquared >= maxLengthSquared ) {
+ maxDistPt = p;
+ maxLengthSquared = lengthSquared;
+ }
+ hasNoPoints = false;
}
};
};
diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp
index a88e861b6..2973ee100 100644
--- a/src/render/jobs/pickboundingvolumejob.cpp
+++ b/src/render/jobs/pickboundingvolumejob.cpp
@@ -41,7 +41,11 @@
#include "qpicktriangleevent.h"
#include "qpicklineevent.h"
#include "qpickpointevent.h"
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DRender/qobjectpicker.h>
+#include <Qt3DRender/qviewport.h>
#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DRender/private/qobjectpicker_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/entity_p.h>
@@ -65,6 +69,82 @@ using namespace Qt3DRender::RayCasting;
namespace Render {
+class PickBoundingVolumeJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ PickBoundingVolumeJobPrivate() = default;
+ ~PickBoundingVolumeJobPrivate() override = default;
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ enum CustomEventType {
+ MouseButtonClick = QEvent::User,
+ };
+
+ struct EventDetails {
+ Qt3DCore::QNodeId pickerId;
+ int sourceEventType;
+ QPickEventPtr resultingEvent;
+ Qt3DCore::QNodeId viewportNodeId;
+ };
+
+ QVector<EventDetails> dispatches;
+};
+
+
+void PickBoundingVolumeJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ using namespace Qt3DCore;
+ QNodeId previousId;
+ QObjectPicker *node = nullptr;
+
+ for (auto res: qAsConst(dispatches)) {
+ if (previousId != res.pickerId) {
+ node = qobject_cast<QObjectPicker *>(manager->lookupNode(res.pickerId));
+ previousId = res.pickerId;
+ }
+ if (!node)
+ continue;
+
+ QObjectPickerPrivate *dnode = static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node));
+
+ // resolve front end details
+ QPickEvent *pickEvent = res.resultingEvent.data();
+ if (pickEvent) {
+ QPickEventPrivate *dpickEvent = QPickEventPrivate::get(pickEvent);
+ dpickEvent->m_viewport = static_cast<QViewport *>(manager->lookupNode(res.viewportNodeId));
+ dpickEvent->m_entityPtr = static_cast<QEntity *>(manager->lookupNode(dpickEvent->m_entity));
+ }
+
+ // dispatch event
+ switch (res.sourceEventType) {
+ case QEvent::MouseButtonPress:
+ dnode->pressedEvent(pickEvent);
+ break;
+ case QEvent::MouseButtonRelease:
+ dnode->releasedEvent(pickEvent);
+ break;
+ case MouseButtonClick:
+ dnode->clickedEvent(pickEvent);
+ break;
+ case QEvent::MouseMove:
+ dnode->movedEvent(pickEvent);
+ break;
+ case QEvent::Enter:
+ emit node->entered();
+ dnode->setContainsMouse(true);
+ break;
+ case QEvent::Leave:
+ dnode->setContainsMouse(false);
+ emit node->exited();
+ break;
+ default: Q_UNREACHABLE();
+ }
+ }
+
+ dispatches.clear();
+}
+
namespace {
void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &eventButton, int &eventButtons, int &eventModifiers)
@@ -109,10 +189,10 @@ void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &e
} // anonymous
PickBoundingVolumeJob::PickBoundingVolumeJob()
- : AbstractPickingJob()
+ : AbstractPickingJob(*new PickBoundingVolumeJobPrivate)
, m_pickersDirty(true)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::PickBoundingVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::PickBoundingVolume, 0)
}
void PickBoundingVolumeJob::setRoot(Entity *root)
@@ -122,12 +202,12 @@ void PickBoundingVolumeJob::setRoot(Entity *root)
void PickBoundingVolumeJob::setMouseEvents(const QList<QPair<QObject*, QMouseEvent>> &pendingEvents)
{
- m_pendingMouseEvents = pendingEvents;
+ m_pendingMouseEvents.append(pendingEvents);
}
void PickBoundingVolumeJob::setKeyEvents(const QList<QKeyEvent> &pendingEvents)
{
- m_pendingKeyEvents = pendingEvents;
+ m_pendingKeyEvents.append(pendingEvents);
}
void PickBoundingVolumeJob::markPickersDirty()
@@ -300,6 +380,8 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
bool allHitsRequested,
Qt3DCore::QNodeId viewportNodeId)
{
+ Q_D(PickBoundingVolumeJob);
+
ObjectPicker *lastCurrentPicker = m_manager->objectPickerManager()->data(m_currentPicker);
// If we have hits
if (!sphereHits.isEmpty()) {
@@ -383,37 +465,43 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
// Store pressed object handle
m_currentPicker = objectPickerHandle;
// Send pressed event to m_currentPicker
- objectPicker->onPressed(pickEvent, viewportNodeId);
+ d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId});
+ objectPicker->setPressed(true);
break;
}
case QEvent::MouseButtonRelease: {
// Only send the release event if it was pressed
- if (objectPicker->isPressed())
- objectPicker->onReleased(pickEvent, viewportNodeId);
+ if (objectPicker->isPressed()) {
+ d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId});
+ objectPicker->setPressed(false);
+ }
if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) {
- objectPicker->onClicked(pickEvent, viewportNodeId);
+ d->dispatches.push_back({objectPicker->peerId(),
+ PickBoundingVolumeJobPrivate::MouseButtonClick,
+ pickEvent, viewportNodeId});
m_currentPicker = HObjectPicker();
}
break;
}
#if QT_CONFIG(gestures)
case QEvent::Gesture: {
- objectPicker->onClicked(pickEvent, viewportNodeId);
+ d->dispatches.push_back({objectPicker->peerId(),
+ PickBoundingVolumeJobPrivate::MouseButtonClick,
+ pickEvent, viewportNodeId});
break;
}
#endif
case QEvent::MouseMove: {
- if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled()) {
- objectPicker->onMoved(pickEvent, viewportNodeId);
- }
+ if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled())
+ d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId});
Q_FALLTHROUGH(); // fallthrough
}
case QEvent::HoverMove: {
if (!m_hoveredPickers.contains(objectPickerHandle)) {
if (objectPicker->isHoverEnabled()) {
// Send entered event to objectPicker
- objectPicker->onEntered();
+ d->dispatches.push_back({objectPicker->peerId(), QEvent::Enter, pickEvent, viewportNodeId});
// and save it in the hoveredPickers
m_hoveredPickers.push_back(objectPickerHandle);
}
@@ -440,7 +528,8 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
if (lastCurrentPicker != nullptr) {
m_currentPicker = HObjectPicker();
QPickEventPtr pickEvent(new QPickEvent);
- lastCurrentPicker->onReleased(pickEvent, viewportNodeId);
+ lastCurrentPicker->setPressed(false);
+ d->dispatches.push_back({lastCurrentPicker->peerId(), event.type(), pickEvent, viewportNodeId});
}
break;
}
@@ -452,12 +541,15 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
void PickBoundingVolumeJob::clearPreviouslyHoveredPickers()
{
+ Q_D(PickBoundingVolumeJob);
+
for (const HObjectPicker &pickHandle : qAsConst(m_hoveredPickersToClear)) {
ObjectPicker *pick = m_manager->objectPickerManager()->data(pickHandle);
if (pick)
- pick->onExited();
+ d->dispatches.push_back({pick->peerId(), QEvent::Leave, {}, {}});
m_hoveredPickers.removeAll(pickHandle);
}
+
m_hoveredPickersToClear.clear();
}
diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h
index e3d847916..49b11b775 100644
--- a/src/render/jobs/pickboundingvolumejob_p.h
+++ b/src/render/jobs/pickboundingvolumejob_p.h
@@ -70,6 +70,7 @@ namespace Qt3DRender {
class QViewport;
namespace Render {
+class PickBoundingVolumeJobPrivate;
namespace PickingUtils {
typedef QVector<RayCasting::QCollisionQueryResult::Hit> HitList;
@@ -101,6 +102,8 @@ protected:
Qt3DCore::QNodeId viewportNodeId);
private:
+ Q_DECLARE_PRIVATE(PickBoundingVolumeJob)
+
void clearPreviouslyHoveredPickers();
QList<QPair<QObject*, QMouseEvent>> m_pendingMouseEvents;
diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp
index 35f4d64a9..8637a92d4 100644
--- a/src/render/materialsystem/qeffect.cpp
+++ b/src/render/materialsystem/qeffect.cpp
@@ -65,6 +65,8 @@ QEffectPrivate::QEffectPrivate()
An QEffect instance should be shared among several QMaterial instances when possible.
+ \note QEffect node can not be disabled.
+
\code
QEffect *effect = new QEffect();
@@ -111,6 +113,8 @@ QEffectPrivate::QEffectPrivate()
A Parameter defined on an Effect is overridden by a QParameter (of the same
name) defined in a Material, TechniqueFilter, RenderPassFilter.
+ \note Effect node can not be disabled.
+
\code
Effect {
id: effect
@@ -188,7 +192,7 @@ void QEffect::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -202,7 +206,7 @@ void QEffect::removeParameter(QParameter *parameter)
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
}
/*!
@@ -234,7 +238,7 @@ void QEffect::addTechnique(QTechnique *t)
if (!t->parent())
t->setParent(this);
- d->update();
+ d->updateNode(t, "technique", Qt3DCore::PropertyValueAdded);
}
}
@@ -245,7 +249,7 @@ void QEffect::removeTechnique(QTechnique *t)
{
Q_D(QEffect);
if (t)
- d->update();
+ d->updateNode(t, "technique", Qt3DCore::PropertyValueRemoved);
d->m_techniques.removeOne(t);
// Remove bookkeeping connection
d->unregisterDestructionHelper(t);
diff --git a/src/render/materialsystem/qfilterkey.cpp b/src/render/materialsystem/qfilterkey.cpp
index dc968400b..2105da987 100644
--- a/src/render/materialsystem/qfilterkey.cpp
+++ b/src/render/materialsystem/qfilterkey.cpp
@@ -60,6 +60,8 @@ QFilterKeyPrivate::QFilterKeyPrivate()
Filter keys are used by QTechnique and QRenderPass to specify at which stage of rendering the
technique or the render pass is used.
+
+ \note QFilterKey node can not be disabled.
*/
/*!
@@ -73,6 +75,8 @@ QFilterKeyPrivate::QFilterKeyPrivate()
A FilterKey is a storage type for filter key and value pair.
Filter keys are used by Technique and RenderPass to specify at which stage of rendering the
technique or the render pass is used.
+
+ \note FilterKey node can not be disabled.
*/
QFilterKey::QFilterKey(QNode *parent)
diff --git a/src/render/materialsystem/qmaterial.cpp b/src/render/materialsystem/qmaterial.cpp
index db286de6b..edd227500 100644
--- a/src/render/materialsystem/qmaterial.cpp
+++ b/src/render/materialsystem/qmaterial.cpp
@@ -272,7 +272,7 @@ void QMaterial::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -283,7 +283,7 @@ void QMaterial::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QMaterial);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
}
diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp
index 77eda8c8e..969882564 100644
--- a/src/render/materialsystem/qparameter.cpp
+++ b/src/render/materialsystem/qparameter.cpp
@@ -76,6 +76,8 @@
\note when the targeted uniform is an array, the name should be the name
of the uniform with [0] appended to it.
+ \note Parameter node can not be disabled.
+
\code
Parameter {
name: "diffuseValues[0]"
@@ -138,6 +140,8 @@
\note when the targeted uniform is an array, the name should be the name
of the uniform with [0] appended to it.
+ \note QParameter node can not be disabled.
+
\code
QParameter *param = new QParameter();
QVariantList values = QVariantList() << 0.0f << 1.0f << 2.0f << 3.0f << 4.0f << 883.0f << 1340.0f << 1584.0f;
diff --git a/src/render/materialsystem/qrenderpass.cpp b/src/render/materialsystem/qrenderpass.cpp
index e9dd50325..dcb831b13 100644
--- a/src/render/materialsystem/qrenderpass.cpp
+++ b/src/render/materialsystem/qrenderpass.cpp
@@ -274,7 +274,7 @@ void QRenderPass::addFilterKey(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- d->update();
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueAdded);
}
}
@@ -285,7 +285,7 @@ void QRenderPass::removeFilterKey(QFilterKey *filterKey)
{
Q_ASSERT(filterKey);
Q_D(QRenderPass);
- d->update();
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueRemoved);
d->m_filterKeyList.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -322,7 +322,7 @@ void QRenderPass::addRenderState(QRenderState *state)
if (!state->parent())
state->setParent(this);
- d->update();
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueAdded);
}
}
@@ -333,7 +333,7 @@ void QRenderPass::removeRenderState(QRenderState *state)
{
Q_ASSERT(state);
Q_D(QRenderPass);
- d->update();
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueRemoved);
d->m_renderStates.removeOne(state);
// Remove bookkeeping connection
d->unregisterDestructionHelper(state);
@@ -369,7 +369,7 @@ void QRenderPass::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -380,7 +380,7 @@ void QRenderPass::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QRenderPass);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
diff --git a/src/render/materialsystem/qshaderprogrambuilder.cpp b/src/render/materialsystem/qshaderprogrambuilder.cpp
index cafe23ee4..6613661d1 100644
--- a/src/render/materialsystem/qshaderprogrambuilder.cpp
+++ b/src/render/materialsystem/qshaderprogrambuilder.cpp
@@ -79,6 +79,47 @@ QShaderProgramBuilderPrivate::QShaderProgramBuilderPrivate()
{
}
+void QShaderProgramBuilderPrivate::setShaderCode(const QByteArray &code, QShaderProgram::ShaderType type)
+{
+ Q_Q(QShaderProgramBuilder);
+ const bool blocked = q->blockNotifications(true);
+
+ switch (type) {
+ case QShaderProgram::Vertex: {
+ m_vertexShaderCode = code;
+ emit q->vertexShaderCodeChanged(m_vertexShaderCode);
+ break;
+ }
+ case QShaderProgram::Fragment:{
+ m_fragmentShaderCode = code;
+ emit q->fragmentShaderCodeChanged(m_fragmentShaderCode);
+ break;
+ }
+ case QShaderProgram::Geometry: {
+ m_geometryShaderCode = code;
+ emit q->geometryShaderCodeChanged(m_geometryShaderCode);
+ break;
+ }
+ case QShaderProgram::Compute: {
+ m_computeShaderCode = code;
+ emit q->computeShaderCodeChanged(m_computeShaderCode);
+ break;
+ }
+ case QShaderProgram::TessellationControl: {
+ m_tessControlShaderCode = code;
+ emit q->tessellationControlShaderCodeChanged(m_tessControlShaderCode);
+ break;
+ }
+ case QShaderProgram::TessellationEvaluation: {
+ m_tessEvalShaderCode = code;
+ emit q->tessellationEvaluationShaderCodeChanged(m_tessEvalShaderCode);
+ break;
+ }
+ }
+
+ q->blockNotifications(blocked);
+}
+
QShaderProgramBuilder::QShaderProgramBuilder(QNode *parent)
: QNode(*new QShaderProgramBuilderPrivate, parent)
{
@@ -94,53 +135,6 @@ QShaderProgramBuilder::QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, Q
{
}
-void QShaderProgramBuilder::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QShaderProgramBuilder);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("generatedShaderCode")) {
- const bool blocked = blockNotifications(true);
- const QPair<int, QByteArray> data = e->value().value<QPair<int, QByteArray>>();
-
- switch (data.first) {
- case QShaderProgram::Vertex: {
- d->m_vertexShaderCode = data.second;
- emit vertexShaderCodeChanged(d->m_vertexShaderCode);
- break;
- }
- case QShaderProgram::Fragment:{
- d->m_fragmentShaderCode = data.second;
- emit fragmentShaderCodeChanged(d->m_fragmentShaderCode);
- break;
- }
- case QShaderProgram::Geometry: {
- d->m_geometryShaderCode = data.second;
- emit geometryShaderCodeChanged(d->m_geometryShaderCode);
- break;
- }
- case QShaderProgram::Compute: {
- d->m_computeShaderCode = data.second;
- emit computeShaderCodeChanged(d->m_computeShaderCode);
- break;
- }
- case QShaderProgram::TessellationControl: {
- d->m_tessControlShaderCode = data.second;
- emit tessellationControlShaderCodeChanged(d->m_tessControlShaderCode);
- break;
- }
- case QShaderProgram::TessellationEvaluation: {
- d->m_tessEvalShaderCode = data.second;
- emit tessellationEvaluationShaderCodeChanged(d->m_tessEvalShaderCode);
- break;
- }
- }
-
- blockNotifications(blocked);
- }
- }
-}
-
/*!
\qmlproperty string ShaderProgramBuilder::shaderProgram
diff --git a/src/render/materialsystem/qshaderprogrambuilder.h b/src/render/materialsystem/qshaderprogrambuilder.h
index 184093730..5dc6b54ff 100644
--- a/src/render/materialsystem/qshaderprogrambuilder.h
+++ b/src/render/materialsystem/qshaderprogrambuilder.h
@@ -117,7 +117,6 @@ Q_SIGNALS:
protected:
explicit QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, Qt3DCore::QNode *parent = nullptr);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QShaderProgramBuilder)
diff --git a/src/render/materialsystem/qshaderprogrambuilder_p.h b/src/render/materialsystem/qshaderprogrambuilder_p.h
index 2ac765a1d..22f8e6e58 100644
--- a/src/render/materialsystem/qshaderprogrambuilder_p.h
+++ b/src/render/materialsystem/qshaderprogrambuilder_p.h
@@ -52,6 +52,8 @@
//
#include <private/qnode_p.h>
+#include <Qt3DRender/private/qt3drender_global_p.h>
+#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/qshaderprogrambuilder.h>
#include <QtCore/qurl.h>
@@ -60,7 +62,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QShaderProgramBuilderPrivate : public Qt3DCore::QNodePrivate
+class Q_3DRENDERSHARED_PRIVATE_EXPORT QShaderProgramBuilderPrivate : public Qt3DCore::QNodePrivate
{
public:
QShaderProgramBuilderPrivate();
@@ -80,6 +82,8 @@ public:
QByteArray m_geometryShaderCode;
QByteArray m_fragmentShaderCode;
QByteArray m_computeShaderCode;
+
+ void setShaderCode(const QByteArray &code, QShaderProgram::ShaderType type);
};
struct QShaderProgramBuilderData
diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp
index 2b96aa285..a9b7ca82b 100644
--- a/src/render/materialsystem/qtechnique.cpp
+++ b/src/render/materialsystem/qtechnique.cpp
@@ -87,6 +87,8 @@ QTechniquePrivate::~QTechniquePrivate()
QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
will likely have no effect on Qt3D related rendering.
+ \note Technique node can not be disabled.
+
\qml
Technique {
id: gl3Technique
@@ -152,6 +154,8 @@ QTechniquePrivate::~QTechniquePrivate()
QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
will likely have no effect on Qt3D related rendering.
+ \note QTechnique node can not be disabled.
+
\code
QTechnique *gl3Technique = new QTechnique();
@@ -254,7 +258,7 @@ void QTechnique::addFilterKey(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- d->update();
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueAdded);
}
}
@@ -265,7 +269,7 @@ void QTechnique::removeFilterKey(QFilterKey *filterKey)
{
Q_ASSERT(filterKey);
Q_D(QTechnique);
- d->update();
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueRemoved);
d->m_filterKeys.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -301,7 +305,7 @@ void QTechnique::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -312,7 +316,7 @@ void QTechnique::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QTechnique);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
@@ -338,7 +342,7 @@ void QTechnique::addRenderPass(QRenderPass *pass)
if (!pass->parent())
pass->setParent(this);
- d->update();
+ d->updateNode(pass, "pass", Qt3DCore::PropertyValueAdded);
}
}
@@ -349,7 +353,7 @@ void QTechnique::removeRenderPass(QRenderPass *pass)
{
Q_ASSERT(pass);
Q_D(QTechnique);
- d->update();
+ d->updateNode(pass, "pass", Qt3DCore::PropertyValueAdded);
d->m_renderPasses.removeOne(pass);
// Remove bookkeeping connection
d->unregisterDestructionHelper(pass);
diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp
index f35fba9fa..58709b37e 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -64,6 +64,7 @@ Shader::Shader()
, m_dna(0)
, m_graphicsContext(nullptr)
, m_status(QShaderProgram::NotReady)
+ , m_requiresFrontendSync(false)
{
m_shaderCode.resize(static_cast<int>(QShaderProgram::Compute) + 1);
}
@@ -170,8 +171,9 @@ void Shader::setShaderCode(QShaderProgram::ShaderType type, const QByteArray &co
m_shaderCode[type] = code;
m_isLoaded = false;
- setStatus(QShaderProgram::NotReady);
+ m_status = QShaderProgram::NotReady;
updateDNA();
+ m_requiresFrontendSync = true;
markDirty(AbstractRenderer::ShadersDirty);
}
@@ -237,20 +239,13 @@ ShaderStorageBlock Shader::storageBlockForBlockName(const QString &blockName)
return ShaderStorageBlock();
}
-// To be called from a worker thread
-void Shader::submitPendingNotifications()
-{
- const QVector<Qt3DCore::QPropertyUpdatedChangePtr> notifications = std::move(m_pendingNotifications);
- for (const Qt3DCore::QPropertyUpdatedChangePtr &notification : notifications)
- notifyObservers(notification);
-}
-
void Shader::prepareUniforms(ShaderParameterPack &pack)
{
const PackUniformHash &values = pack.uniforms();
auto it = values.cbegin();
const auto end = values.cend();
+
while (it != end) {
// Find if there's a uniform with the same name id
for (const ShaderUniform &uniform : qAsConst(m_uniforms)) {
@@ -412,32 +407,21 @@ void Shader::initializeFromReference(const Shader &other)
m_shaderStorageBlockNames = other.m_shaderStorageBlockNames;
m_shaderStorageBlocks = other.m_shaderStorageBlocks;
m_isLoaded = other.m_isLoaded;
- setStatus(other.status());
- setLog(other.log());
+ m_status = other.m_status;
+ m_log = other.m_log;
+ m_requiresFrontendSync = true;
}
void Shader::setLog(const QString &log)
{
- if (log != m_log) {
- m_log = log;
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("log");
- e->setValue(QVariant::fromValue(m_log));
- m_pendingNotifications.push_back(e);
- }
+ m_log = log;
+ m_requiresFrontendSync = true;
}
void Shader::setStatus(QShaderProgram::Status status)
{
- if (status != m_status) {
- m_status = status;
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("status");
- e->setValue(QVariant::fromValue(m_status));
- m_pendingNotifications.push_back(e);
- }
+ m_status = status;
+ m_requiresFrontendSync = true;
}
} // namespace Render
diff --git a/src/render/materialsystem/shader_p.h b/src/render/materialsystem/shader_p.h
index f8cdde3b7..fe1a401d9 100644
--- a/src/render/materialsystem/shader_p.h
+++ b/src/render/materialsystem/shader_p.h
@@ -122,8 +122,8 @@ public:
inline QString log() const { return m_log; }
inline QShaderProgram::Status status() const { return m_status; }
- void submitPendingNotifications();
- inline bool hasPendingNotifications() const { return !m_pendingNotifications.empty(); }
+ inline bool requiresFrontendSync() const { return m_requiresFrontendSync; }
+ inline void unsetRequiresFrontendSync() { m_requiresFrontendSync = false; }
private:
QVector<QString> m_uniformsNames;
@@ -155,8 +155,7 @@ private:
QMetaObject::Connection m_contextConnection;
QString m_log;
QShaderProgram::Status m_status;
-
- QVector<Qt3DCore::QPropertyUpdatedChangePtr> m_pendingNotifications;
+ bool m_requiresFrontendSync;
void updateDNA();
diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp
index 6116ca56b..23f1400c9 100644
--- a/src/render/materialsystem/shaderbuilder.cpp
+++ b/src/render/materialsystem/shaderbuilder.cpp
@@ -115,31 +115,6 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
-
-namespace {
-
-QShaderProgram::ShaderType toQShaderProgramType(ShaderBuilder::ShaderType type)
-{
- switch (type) {
- case ShaderBuilder::ShaderType::Vertex:
- return QShaderProgram::Vertex;
- case ShaderBuilder::ShaderType::TessellationControl:
- return QShaderProgram::TessellationControl;
- case ShaderBuilder::ShaderType::TessellationEvaluation:
- return QShaderProgram::TessellationEvaluation;
- case ShaderBuilder::ShaderType::Geometry:
- return QShaderProgram::Geometry;
- case ShaderBuilder::ShaderType::Fragment:
- return QShaderProgram::Fragment;
- case ShaderBuilder::ShaderType::Compute:
- return QShaderProgram::Compute;
- default:
- Q_UNREACHABLE();
- }
-}
-
-} // anonymous
-
QString ShaderBuilder::getPrototypesFile()
{
return qt3dGlobalShaderPrototypes->prototypesFile();
@@ -170,6 +145,7 @@ void ShaderBuilder::cleanup()
m_enabledLayers.clear();
m_graphs.clear();
m_dirtyTypes.clear();
+ m_pendingUpdates.clear();
QBackendNode::setEnabled(false);
}
@@ -191,7 +167,7 @@ void ShaderBuilder::setEnabledLayers(const QStringList &layers)
m_enabledLayers = layers;
- for (QHash<ShaderType, QUrl>::const_iterator it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
+ for (auto it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
if (!it.value().isEmpty())
m_dirtyTypes.insert(it.key());
}
@@ -208,18 +184,18 @@ void ShaderBuilder::setGraphicsApi(const GraphicsApiFilterData &graphicsApi)
return;
m_graphicsApi = graphicsApi;
- for (QHash<ShaderType, QUrl>::const_iterator it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
+ for (auto it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
if (!it.value().isEmpty())
m_dirtyTypes.insert(it.key());
}
}
-QUrl ShaderBuilder::shaderGraph(ShaderBuilder::ShaderType type) const
+QUrl ShaderBuilder::shaderGraph(QShaderProgram::ShaderType type) const
{
return m_graphs.value(type);
}
-void ShaderBuilder::setShaderGraph(ShaderBuilder::ShaderType type, const QUrl &url)
+void ShaderBuilder::setShaderGraph(QShaderProgram::ShaderType type, const QUrl &url)
{
if (url != m_graphs.value(type)) {
m_graphs.insert(type, url);
@@ -227,17 +203,17 @@ void ShaderBuilder::setShaderGraph(ShaderBuilder::ShaderType type, const QUrl &u
}
}
-QByteArray ShaderBuilder::shaderCode(ShaderBuilder::ShaderType type) const
+QByteArray ShaderBuilder::shaderCode(QShaderProgram::ShaderType type) const
{
return m_codes.value(type);
}
-bool ShaderBuilder::isShaderCodeDirty(ShaderBuilder::ShaderType type) const
+bool ShaderBuilder::isShaderCodeDirty(QShaderProgram::ShaderType type) const
{
return m_dirtyTypes.contains(type);
}
-void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type)
+void ShaderBuilder::generateCode(QShaderProgram::ShaderType type)
{
const auto graphPath = QUrlHelper::urlToLocalFileOrQrc(shaderGraph(type));
QFile file(graphPath);
@@ -273,12 +249,9 @@ void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type)
m_codes.insert(type, QShaderProgramPrivate::deincludify(code, graphPath + QStringLiteral(".glsl")));
m_dirtyTypes.remove(type);
- // Send notification to the frontend
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- propertyChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- propertyChange->setPropertyName("generatedShaderCode");
- propertyChange->setValue(QVariant::fromValue(qMakePair(int(toQShaderProgramType(type)), m_codes.value(type))));
- notifyObservers(propertyChange);
+ m_pendingUpdates.push_back({ peerId(),
+ type,
+ m_codes.value(type) });
}
void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
@@ -305,13 +278,13 @@ void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
markDirty(AbstractRenderer::ShadersDirty);
}
- static const std::pair<ShaderType, QUrl (QShaderProgramBuilder::*)() const> shaderTypesToGetters[] = {
- {Vertex, &QShaderProgramBuilder::vertexShaderGraph},
- {TessellationControl, &QShaderProgramBuilder::tessellationControlShaderGraph},
- {TessellationEvaluation, &QShaderProgramBuilder::tessellationEvaluationShaderGraph},
- {Geometry, &QShaderProgramBuilder::geometryShaderGraph},
- {Fragment, &QShaderProgramBuilder::fragmentShaderGraph},
- {Compute, &QShaderProgramBuilder::computeShaderGraph},
+ static const std::pair<QShaderProgram::ShaderType, QUrl (QShaderProgramBuilder::*)() const> shaderTypesToGetters[] = {
+ {QShaderProgram::Vertex, &QShaderProgramBuilder::vertexShaderGraph},
+ {QShaderProgram::TessellationControl, &QShaderProgramBuilder::tessellationControlShaderGraph},
+ {QShaderProgram::TessellationEvaluation, &QShaderProgramBuilder::tessellationEvaluationShaderGraph},
+ {QShaderProgram::Geometry, &QShaderProgramBuilder::geometryShaderGraph},
+ {QShaderProgram::Fragment, &QShaderProgramBuilder::fragmentShaderGraph},
+ {QShaderProgram::Compute, &QShaderProgramBuilder::computeShaderGraph},
};
for (auto it = std::cbegin(shaderTypesToGetters), end = std::cend(shaderTypesToGetters); it != end; ++it) {
diff --git a/src/render/materialsystem/shaderbuilder_p.h b/src/render/materialsystem/shaderbuilder_p.h
index 6b92d3114..0a799afaa 100644
--- a/src/render/materialsystem/shaderbuilder_p.h
+++ b/src/render/materialsystem/shaderbuilder_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
+#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/private/qgraphicsapifilter_p.h>
@@ -60,18 +61,16 @@ namespace Qt3DRender {
namespace Render {
+struct ShaderBuilderUpdate
+{
+ Qt3DCore::QNodeId builderId;
+ Qt3DRender::QShaderProgram::ShaderType shaderType;
+ QByteArray shaderCode;
+};
+
class Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderBuilder : public BackendNode
{
public:
- enum ShaderType {
- Vertex = 0,
- TessellationControl,
- TessellationEvaluation,
- Geometry,
- Fragment,
- Compute
- };
-
static QString getPrototypesFile();
static void setPrototypesFile(const QString &file);
static QStringList getPrototypeNames();
@@ -86,25 +85,28 @@ public:
GraphicsApiFilterData graphicsApi() const;
void setGraphicsApi(const GraphicsApiFilterData &graphicsApi);
- QUrl shaderGraph(ShaderType type) const;
- void setShaderGraph(ShaderType type, const QUrl &url);
+ QUrl shaderGraph(QShaderProgram::ShaderType type) const;
+ void setShaderGraph(QShaderProgram::ShaderType type, const QUrl &url);
- QByteArray shaderCode(ShaderType type) const;
- bool isShaderCodeDirty(ShaderType type) const;
+ QByteArray shaderCode(QShaderProgram::ShaderType type) const;
+ bool isShaderCodeDirty(QShaderProgram::ShaderType type) const;
- void generateCode(ShaderType type);
+ void generateCode(QShaderProgram::ShaderType type);
void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+ QVector<ShaderBuilderUpdate> takePendingUpdates() { return std::move(m_pendingUpdates); }
+
private:
void setEnabledLayers(const QStringList &layers);
GraphicsApiFilterData m_graphicsApi;
Qt3DCore::QNodeId m_shaderProgramId;
QStringList m_enabledLayers;
- QHash<ShaderType, QUrl> m_graphs;
- QHash<ShaderType, QByteArray> m_codes;
- QSet<ShaderType> m_dirtyTypes;
+ QHash<QShaderProgram::ShaderType, QUrl> m_graphs;
+ QHash<QShaderProgram::ShaderType, QByteArray> m_codes;
+ QSet<QShaderProgram::ShaderType> m_dirtyTypes;
+ QVector<ShaderBuilderUpdate> m_pendingUpdates;
};
} // namespace Render
diff --git a/src/render/picking/objectpicker.cpp b/src/render/picking/objectpicker.cpp
index e278d6b6f..84169586e 100644
--- a/src/render/picking/objectpicker.cpp
+++ b/src/render/picking/objectpicker.cpp
@@ -43,7 +43,6 @@
#include <Qt3DRender/private/qobjectpicker_p.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/private/pickboundingvolumejob_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -100,7 +99,6 @@ void ObjectPicker::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstT
markDirty(AbstractRenderer::AllDirty);
notifyJob();
}
-
}
void ObjectPicker::notifyJob()
@@ -124,58 +122,9 @@ bool ObjectPicker::isDragEnabled() const
return m_dragEnabled;
}
-void ObjectPicker::onClicked(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("clicked");
- e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId }));
- notifyObservers(e);
-}
-
-void ObjectPicker::onMoved(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("moved");
- e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId }));
- notifyObservers(e);
-}
-
-void ObjectPicker::onPressed(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("pressed");
- e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId }));
- m_isPressed = true;
- notifyObservers(e);
-}
-
-void ObjectPicker::onReleased(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("released");
- e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId }));
- m_isPressed = false;
- notifyObservers(e);
-}
-
-void ObjectPicker::onEntered()
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("entered");
- notifyObservers(e);
-}
-
-void ObjectPicker::onExited()
+void ObjectPicker::setPressed(bool pressed)
{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("exited");
- notifyObservers(e);
+ m_isPressed = pressed;
}
void ObjectPicker::setPriority(int priority)
diff --git a/src/render/picking/objectpicker_p.h b/src/render/picking/objectpicker_p.h
index b4f7d073c..49c8de770 100644
--- a/src/render/picking/objectpicker_p.h
+++ b/src/render/picking/objectpicker_p.h
@@ -74,12 +74,7 @@ public:
bool isHoverEnabled() const;
bool isDragEnabled() const;
- void onClicked(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId);
- void onMoved(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId);
- void onPressed(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId);
- void onReleased(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId);
- void onEntered();
- void onExited();
+ void setPressed(bool pressed);
// Needed for unit tests
void setPriority(int priority);
diff --git a/src/render/picking/picking.pri b/src/render/picking/picking.pri
index 89c549de0..189d64bb6 100644
--- a/src/render/picking/picking.pri
+++ b/src/render/picking/picking.pri
@@ -7,6 +7,7 @@ HEADERS += \
$$PWD/qpicklineevent.h \
$$PWD/qpickpointevent.h \
$$PWD/qpicktriangleevent.h \
+ $$PWD/qpicktriangleevent_p.h \
$$PWD/objectpicker_p.h \
$$PWD/pickeventfilter_p.h \
$$PWD/qobjectpicker_p.h \
diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp
index 9537d4982..7d9741f21 100644
--- a/src/render/picking/qobjectpicker.cpp
+++ b/src/render/picking/qobjectpicker.cpp
@@ -82,6 +82,9 @@ namespace Qt3DRender {
\note Instances of this component shouldn't be shared, not respecting that
condition will most likely result in undefined behavior.
+ \note The camera far plane value affects picking and produces incorrect results due to
+ floating-point precision if it is greater than ~100 000.
+
\since 5.6
*/
@@ -115,6 +118,9 @@ namespace Qt3DRender {
\note Instances of this component shouldn't be shared, not respecting that
condition will most likely result in undefined behavior.
+
+ \note The camera far plane value affects picking and produces incorrect results due to
+ floating-point precision if it is greater than ~100 000.
*/
/*!
@@ -352,33 +358,6 @@ int QObjectPicker::priority() const
return d->m_priority;
}
-/*! \internal */
-void QObjectPicker::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QObjectPicker);
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated) {
- // TO DO: Complete this part
- // to emit the correct signals
- const QByteArray propertyName = e->propertyName();
- if (propertyName == QByteArrayLiteral("pressed")) {
- d->pressedEvent(d->resolvePickEvent(e));
- } else if (propertyName == QByteArrayLiteral("released")) {
- d->releasedEvent(d->resolvePickEvent(e));
- } else if (propertyName == QByteArrayLiteral("clicked")) {
- d->clickedEvent(d->resolvePickEvent(e));
- } else if (propertyName == QByteArrayLiteral("moved")) {
- d->movedEvent(d->resolvePickEvent(e));
- } else if (propertyName == QByteArrayLiteral("entered")) {
- emit entered();
- d->setContainsMouse(true);
- } else if (propertyName == QByteArrayLiteral("exited")) {
- d->setContainsMouse(false);
- emit exited();
- }
- }
-}
-
/*!
\internal
*/
@@ -407,15 +386,6 @@ void QObjectPickerPrivate::setContainsMouse(bool containsMouse)
}
}
-QPickEvent *QObjectPickerPrivate::resolvePickEvent(Qt3DCore::QPropertyUpdatedChangePtr e)
-{
- QObjectPickerEvent ev = e->value().value<QObjectPickerEvent>();
- QPickEvent *pickEvent = ev.event.data();
- pickEvent->d_func()->m_viewport = static_cast<QViewport *>(scene()->lookupNode(ev.viewportNodeId));
- pickEvent->d_func()->m_entityPtr = static_cast<Qt3DCore::QEntity *>(scene()->lookupNode(pickEvent->d_func()->m_entity));
- return pickEvent;
-}
-
void QObjectPickerPrivate::propagateEvent(QPickEvent *event, EventType type)
{
if (!m_entities.isEmpty()) {
diff --git a/src/render/picking/qobjectpicker.h b/src/render/picking/qobjectpicker.h
index 8866c99a9..ee63c9418 100644
--- a/src/render/picking/qobjectpicker.h
+++ b/src/render/picking/qobjectpicker.h
@@ -90,9 +90,6 @@ Q_SIGNALS:
void containsMouseChanged(bool containsMouse);
Q_REVISION(13) void priorityChanged(int priority);
-protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
-
private:
Q_DECLARE_PRIVATE(QObjectPicker)
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
diff --git a/src/render/picking/qobjectpicker_p.h b/src/render/picking/qobjectpicker_p.h
index fb83912b0..69cee529d 100644
--- a/src/render/picking/qobjectpicker_p.h
+++ b/src/render/picking/qobjectpicker_p.h
@@ -91,7 +91,6 @@ public:
Moved
};
- QPickEvent *resolvePickEvent(Qt3DCore::QPropertyUpdatedChangePtr e);
void propagateEvent(QPickEvent *event, EventType type);
void pressedEvent(QPickEvent *event);
diff --git a/src/render/picking/qpickevent_p.h b/src/render/picking/qpickevent_p.h
index 4d2f1e2d4..15eeb04b8 100644
--- a/src/render/picking/qpickevent_p.h
+++ b/src/render/picking/qpickevent_p.h
@@ -37,6 +37,9 @@
**
****************************************************************************/
+#ifndef QT3DRENDER_QPICKEVENT_P_H
+#define QT3DRENDER_QPICKEVENT_P_H
+
//
// W A R N I N G
// -------------
@@ -95,3 +98,4 @@ public:
QT_END_NAMESPACE
+#endif // QT3DRENDER_QPICKEVENT_P_H
diff --git a/src/render/picking/qpicktriangleevent.cpp b/src/render/picking/qpicktriangleevent.cpp
index 3e8e8c72c..c077d412f 100644
--- a/src/render/picking/qpicktriangleevent.cpp
+++ b/src/render/picking/qpicktriangleevent.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qpicktriangleevent.h"
+#include "qpicktriangleevent_p.h"
#include "qpickevent_p.h"
#include <private/qobject_p.h>
@@ -45,24 +46,42 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QPickTriangleEventPrivate : public QPickEventPrivate
+
+Qt3DRender::QPickTriangleEventPrivate::QPickTriangleEventPrivate()
+ : QPickEventPrivate()
+ , m_triangleIndex(0)
+ , m_vertex1Index(0)
+ , m_vertex2Index(0)
+ , m_vertex3Index(0)
+{
+}
+
+const QPickTriangleEventPrivate *QPickTriangleEventPrivate::get(const QPickTriangleEvent *ev)
{
-public:
- QPickTriangleEventPrivate()
- : QPickEventPrivate()
- , m_triangleIndex(0)
- , m_vertex1Index(0)
- , m_vertex2Index(0)
- , m_vertex3Index(0)
- {
- }
+ return ev->d_func();
+}
+
+QPickTriangleEvent *QPickTriangleEventPrivate::clone() const
+{
+ auto res = new QPickTriangleEvent();
+ res->d_func()->m_accepted = m_accepted;
+ res->d_func()->m_position = m_position;
+ res->d_func()->m_worldIntersection = m_worldIntersection;
+ res->d_func()->m_localIntersection = m_localIntersection;
+ res->d_func()->m_distance = m_distance;
+ res->d_func()->m_button = m_button;
+ res->d_func()->m_buttons = m_buttons;
+ res->d_func()->m_modifiers = m_modifiers;
+ res->d_func()->m_entity = m_entity;
+ res->d_func()->m_entityPtr = m_entityPtr;
+ res->d_func()->m_viewport = m_viewport;
+ res->d_func()->m_triangleIndex = m_triangleIndex;
+ res->d_func()->m_vertex1Index = m_vertex1Index;
+ res->d_func()->m_vertex2Index = m_vertex2Index;
+ res->d_func()->m_vertex3Index = m_vertex3Index;
+ return res;
+}
- uint m_triangleIndex;
- uint m_vertex1Index;
- uint m_vertex2Index;
- uint m_vertex3Index;
- QVector3D m_uvw;
-};
/*!
\class Qt3DRender::QPickTriangleEvent
diff --git a/src/render/picking/qpicktriangleevent_p.h b/src/render/picking/qpicktriangleevent_p.h
new file mode 100644
index 000000000..d646ac2bb
--- /dev/null
+++ b/src/render/picking/qpicktriangleevent_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QPICKTRIANGLEEVENT_P_H
+#define QT3DRENDER_QPICKTRIANGLEEVENT_P_H
+
+#include <Qt3DRender/private/qpickevent_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+class QPickTriangleEvent;
+
+class Q_3DRENDERSHARED_PRIVATE_EXPORT QPickTriangleEventPrivate : public QPickEventPrivate
+{
+public:
+ QPickTriangleEventPrivate();
+
+ static const QPickTriangleEventPrivate *get(const QPickTriangleEvent *ev);
+ QPickTriangleEvent *clone() const;
+
+ uint m_triangleIndex;
+ uint m_vertex1Index;
+ uint m_vertex2Index;
+ uint m_vertex3Index;
+ QVector3D m_uvw;
+};
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QPICKTRIANGLEEVENT_P_H
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
index f4bd8b871..333453ac7 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
@@ -279,7 +279,7 @@ void GraphicsContext::introspectShaderInterface(Shader *shader, QOpenGLShaderPro
}
-// Called by GL Command Thread
+// Called by Renderer::updateGLResources
void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager)
{
bool wasPresent = false;
@@ -317,7 +317,8 @@ void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager)
shader->setGraphicsContext(this);
shader->setLoaded(true);
- shader->markDirty(AbstractRenderer::AllDirty);
+ // Will force notifications to be sent to frontend at next frame
+ shader->markDirty(AbstractRenderer::ShadersDirty);
}
}
diff --git a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
index fee1cc4b5..cc211ba68 100644
--- a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
@@ -513,7 +513,7 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData *
// the shaderdata cannot hold transformed properties for multiple
// thread contexts at once
activeUniformNamesToValue.insert(StringToInt::lookupId(varName),
- currentShaderData->getTransformedProperty(qmlPropertyName.toLatin1(), viewMatrix));
+ currentShaderData->getTransformedProperty(qmlPropertyName, viewMatrix));
}
}
}
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index 42af03d11..121a6aa8f 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -91,6 +91,8 @@
#include <Qt3DRender/private/renderviewbuilder_p.h>
#include <Qt3DRender/private/setfence_p.h>
#include <Qt3DRender/private/subtreeenabler_p.h>
+#include <Qt3DRender/private/qshaderprogrambuilder_p.h>
+#include <Qt3DRender/private/qshaderprogram_p.h>
#include <Qt3DRender/qcameralens.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
@@ -191,16 +193,18 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_updateMeshTriangleListJob(Render::UpdateMeshTriangleListJobPtr::create())
, m_filterCompatibleTechniqueJob(Render::FilterCompatibleTechniqueJobPtr::create())
, m_updateEntityLayersJob(Render::UpdateEntityLayersJobPtr::create())
- , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
- , m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
- , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
- , m_sendTextureChangesToFrontendJob(decltype(m_sendTextureChangesToFrontendJob)::create([] {},
- [this] (Qt3DCore::QAspectManager *m) { sendTextureChangesToFrontend(m); },
- JobTypes::SendTextureChangesToFrontend))
- , m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
- , m_sendDisablesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendDisablesToFrontend(); }, JobTypes::SendDisablesToFrontend))
- , m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering))
- , m_syncLoadingJobs(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncLoadingJobs))
+ , m_bufferGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
+ , m_vaoGathererJob(SynchronizerJobPtr::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
+ , m_textureGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
+ , m_sendTextureChangesToFrontendJob(SynchronizerPostFramePtr::create([] {},
+ [this] (Qt3DCore::QAspectManager *m) { sendTextureChangesToFrontend(m); },
+ JobTypes::SendTextureChangesToFrontend))
+ , m_sendSetFenceHandlesToFrontendJob(SynchronizerJobPtr::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
+ , m_sendDisablesToFrontendJob(SynchronizerJobPtr::create([this] { sendDisablesToFrontend(); }, JobTypes::SendDisablesToFrontend))
+ , m_introspectShaderJob(SynchronizerPostFramePtr::create([this] { reloadDirtyShaders(); },
+ [this] (Qt3DCore::QAspectManager *m) { sendShaderChangesToFrontend(m); },
+ JobTypes::DirtyShaderGathering))
+ , m_syncLoadingJobs(SynchronizerJobPtr::create([] {}, JobTypes::SyncLoadingJobs))
, m_ownedContext(false)
, m_offscreenHelper(nullptr)
, m_shouldSwapBuffers(true)
@@ -343,6 +347,16 @@ void Renderer::setOpenGLContext(QOpenGLContext *context)
m_glContext = context;
}
+void Renderer::setScreen(QScreen *scr)
+{
+ m_screen = scr;
+}
+
+QScreen *Renderer::screen() const
+{
+ return m_screen;
+}
+
// Called in RenderThread context by the run method of RenderThread
// RenderThread has locked the mutex already and unlocks it when this
// method termintates
@@ -360,6 +374,8 @@ void Renderer::initialize()
// we need to create it
if (!m_glContext) {
ctx = new QOpenGLContext;
+ if (m_screen)
+ ctx->setScreen(m_screen);
ctx->setShareContext(qt_gl_global_share_context());
// TO DO: Shouldn't we use the highest context available and trust
@@ -389,6 +405,8 @@ void Renderer::initialize()
if (!ctx->shareContext()) {
m_shareContext = new QOpenGLContext;
+ if (ctx->screen())
+ m_shareContext->setScreen(ctx->screen());
m_shareContext->setFormat(ctx->format());
m_shareContext->setShareContext(ctx);
m_shareContext->create();
@@ -482,7 +500,8 @@ void Renderer::releaseGraphicsResources()
QOpenGLContext *context = m_submissionContext->openGLContext();
Q_ASSERT(context);
- if (context->makeCurrent(offscreenSurface)) {
+
+ if (context->thread() == QThread::currentThread() && context->makeCurrent(offscreenSurface)) {
// Clean up the graphics context and any resources
const QVector<HGLTexture> activeTexturesHandles = m_nodesManager->glTextureManager()->activeHandles();
@@ -1104,45 +1123,22 @@ void Renderer::reloadDirtyShaders()
if (shaderBuilder) {
shaderBuilder->setGraphicsApi(*technique->graphicsApiFilter());
- for (int i = 0; i <= ShaderBuilder::Compute; i++) {
- const auto builderType = static_cast<ShaderBuilder::ShaderType>(i);
- if (!shaderBuilder->shaderGraph(builderType).isValid())
+ for (int i = 0; i <= QShaderProgram::Compute; i++) {
+ const auto shaderType = static_cast<QShaderProgram::ShaderType>(i);
+ if (!shaderBuilder->shaderGraph(shaderType).isValid())
continue;
- if (shaderBuilder->isShaderCodeDirty(builderType)) {
- shaderBuilder->generateCode(builderType);
- }
-
- QShaderProgram::ShaderType shaderType = QShaderProgram::Vertex;
- switch (builderType) {
- case ShaderBuilder::Vertex:
- shaderType = QShaderProgram::Vertex;
- break;
- case ShaderBuilder::TessellationControl:
- shaderType = QShaderProgram::TessellationControl;
- break;
- case ShaderBuilder::TessellationEvaluation:
- shaderType = QShaderProgram::TessellationEvaluation;
- break;
- case ShaderBuilder::Geometry:
- shaderType = QShaderProgram::Geometry;
- break;
- case ShaderBuilder::Fragment:
- shaderType = QShaderProgram::Fragment;
- break;
- case ShaderBuilder::Compute:
- shaderType = QShaderProgram::Compute;
- break;
+ if (shaderBuilder->isShaderCodeDirty(shaderType)) {
+ shaderBuilder->generateCode(shaderType);
+ m_shaderBuilderUpdates.append(shaderBuilder->takePendingUpdates());
}
- const auto code = shaderBuilder->shaderCode(builderType);
+ const auto code = shaderBuilder->shaderCode(shaderType);
shader->setShaderCode(shaderType, code);
}
}
- if (Q_UNLIKELY(shader->hasPendingNotifications()))
- shader->submitPendingNotifications();
- // If the shader hasn't be loaded, load it
+ // If the shader hasn't been loaded, load it
if (shader != nullptr && !shader->isLoaded())
loadShader(shader, shaderHandle);
}
@@ -1150,6 +1146,33 @@ void Renderer::reloadDirtyShaders()
}
}
+// Executed in job postFrame
+void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager)
+{
+ Q_ASSERT(isRunning());
+
+ // Sync Shader
+ const QVector<HShader> activeShaders = m_nodesManager->shaderManager()->activeHandles();
+ for (const HShader &handle :activeShaders) {
+ Shader *s = m_nodesManager->shaderManager()->data(handle);
+ if (s->requiresFrontendSync()) {
+ QShaderProgram *frontend = static_cast<decltype(frontend)>(manager->lookupNode(s->peerId()));
+ QShaderProgramPrivate *dFrontend = static_cast<decltype(dFrontend)>(QNodePrivate::get(frontend));
+ s->unsetRequiresFrontendSync();
+ dFrontend->setStatus(s->status());
+ dFrontend->setLog(s->log());
+ }
+ }
+
+ // Sync ShaderBuilder
+ const QVector<ShaderBuilderUpdate> shaderBuilderUpdates = std::move(m_shaderBuilderUpdates);
+ for (const ShaderBuilderUpdate &update : shaderBuilderUpdates) {
+ QShaderProgramBuilder *builder = static_cast<decltype(builder)>(manager->lookupNode(update.builderId));
+ QShaderProgramBuilderPrivate *dBuilder = static_cast<decltype(dBuilder)>(QNodePrivate::get(builder));
+ dBuilder->setShaderCode(update.shaderCode, update.shaderType);
+ }
+}
+
// Executed in a job (as postFrame)
void Renderer::sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager)
{
diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h
index 41a071290..b1cd4aac5 100644
--- a/src/render/renderers/opengl/renderer/renderer_p.h
+++ b/src/render/renderers/opengl/renderer/renderer_p.h
@@ -81,6 +81,7 @@
#include <Qt3DRender/private/renderercache_p.h>
#include <Qt3DRender/private/texture_p.h>
#include <Qt3DRender/private/glfence_p.h>
+#include <Qt3DRender/private/shaderbuilder_p.h>
#include <QHash>
#include <QMatrix4x4>
@@ -105,6 +106,7 @@ QT_BEGIN_NAMESPACE
class QSurface;
class QMouseEvent;
+class QScreen;
namespace Qt3DCore {
class QEntity;
@@ -154,7 +156,7 @@ class UpdateLevelOfDetailJob;
typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
-using IntrospectShadersJobPtr = GenericLambdaJobPtr<std::function<void()>>;
+using SynchronizerPostFramePtr = GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>>;
class Q_3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer
{
@@ -220,7 +222,7 @@ public:
inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; }
inline SynchronizerJobPtr syncLoadingJobs() const { return m_syncLoadingJobs; }
inline UpdateSkinningPaletteJobPtr updateSkinningPaletteJob() const { return m_updateSkinningPaletteJob; }
- inline IntrospectShadersJobPtr introspectShadersJob() const { return m_introspectShaderJob; }
+ inline SynchronizerPostFramePtr introspectShadersJob() const { return m_introspectShaderJob; }
inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; }
inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; }
inline Qt3DCore::QAspectJobPtr sendTextureChangesToFrontendJob() const { return m_sendTextureChangesToFrontendJob; }
@@ -292,6 +294,8 @@ public:
ViewSubmissionResultData submitRenderViews(const QVector<Render::RenderView *> &renderViews);
RendererCache *cache() { return &m_cache; }
+ void setScreen(QScreen *scr) override;
+ QScreen *screen() const override;
#ifdef QT3D_RENDER_UNIT_TESTS
public:
@@ -374,14 +378,13 @@ private:
HVao *previousVAOHandle,
OpenGLVertexArrayObject **vao);
- GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob;
- GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob;
- GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob;
- GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>> m_sendTextureChangesToFrontendJob;
- GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob;
- GenericLambdaJobPtr<std::function<void ()>> m_sendDisablesToFrontendJob;
- IntrospectShadersJobPtr m_introspectShaderJob;
-
+ SynchronizerJobPtr m_bufferGathererJob;
+ SynchronizerJobPtr m_vaoGathererJob;
+ SynchronizerJobPtr m_textureGathererJob;
+ SynchronizerPostFramePtr m_sendTextureChangesToFrontendJob;
+ SynchronizerJobPtr m_sendSetFenceHandlesToFrontendJob;
+ SynchronizerJobPtr m_sendDisablesToFrontendJob;
+ SynchronizerPostFramePtr m_introspectShaderJob;
SynchronizerJobPtr m_syncLoadingJobs;
void lookForAbandonedVaos();
@@ -389,6 +392,7 @@ private:
void lookForDownloadableBuffers();
void lookForDirtyTextures();
void reloadDirtyShaders();
+ void sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager);
void sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager);
void sendSetFenceHandlesToFrontend();
void sendDisablesToFrontend();
@@ -404,6 +408,7 @@ private:
QVector<QPair<Qt3DCore::QNodeId, GLFence>> m_updatedSetFences;
QVector<Qt3DCore::QNodeId> m_updatedDisables;
Qt3DCore::QNodeIdVector m_textureIdsToCleanup;
+ QVector<ShaderBuilderUpdate> m_shaderBuilderUpdates;
bool m_ownedContext;
@@ -424,6 +429,7 @@ private:
bool m_shouldSwapBuffers;
QVector<FrameGraphNode *> m_frameGraphLeaves;
+ QScreen *m_screen = nullptr;
};
} // namespace Render
diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp
index 8fbe8e188..aa9f4d1a5 100644
--- a/src/render/renderers/opengl/renderer/renderview.cpp
+++ b/src/render/renderers/opengl/renderer/renderview.cpp
@@ -102,6 +102,12 @@ int LIGHT_COLOR_NAMES[MAX_LIGHTS];
int LIGHT_INTENSITY_NAMES[MAX_LIGHTS];
QString LIGHT_STRUCT_NAMES[MAX_LIGHTS];
+int LIGHT_POSITION_UNROLL_NAMES[MAX_LIGHTS];
+int LIGHT_TYPE_UNROLL_NAMES[MAX_LIGHTS];
+int LIGHT_COLOR_UNROLL_NAMES[MAX_LIGHTS];
+int LIGHT_INTENSITY_UNROLL_NAMES[MAX_LIGHTS];
+QString LIGHT_STRUCT_UNROLL_NAMES[MAX_LIGHTS];
+
bool wasInitialized = false;
} // anonymous namespace
@@ -261,6 +267,12 @@ RenderView::RenderView()
LIGHT_TYPE_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_NAMES[i] + LIGHT_TYPE_NAME);
LIGHT_COLOR_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_NAMES[i] + LIGHT_COLOR_NAME);
LIGHT_INTENSITY_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_NAMES[i] + LIGHT_INTENSITY_NAME);
+
+ LIGHT_STRUCT_UNROLL_NAMES[i] = QLatin1String("light_") + QLatin1Char(char('0' + i));
+ LIGHT_POSITION_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_POSITION_NAME);
+ LIGHT_TYPE_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_TYPE_NAME);
+ LIGHT_COLOR_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_COLOR_NAME);
+ LIGHT_INTENSITY_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_INTENSITY_NAME);
}
}
}
@@ -1008,6 +1020,11 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[lightIdx], 0.5f);
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[lightIdx], worldPos);
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[lightIdx], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[lightIdx], 0.5f);
+
// There is no risk in doing that even if multithreaded
// since we are sure that a shaderData is unique for a given light
// and won't ever be referenced as a Component either
@@ -1016,6 +1033,7 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
shaderData->updateWorldTransform(*worldTransform);
setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_NAMES[lightIdx]);
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_UNROLL_NAMES[lightIdx]);
++lightIdx;
}
}
@@ -1030,6 +1048,11 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight));
setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f);
+
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[0], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[0], 0.5f);
}
// Environment Light
diff --git a/src/render/renderstates/qrenderstate.cpp b/src/render/renderstates/qrenderstate.cpp
index 8a7d897be..cd5346710 100644
--- a/src/render/renderstates/qrenderstate.cpp
+++ b/src/render/renderstates/qrenderstate.cpp
@@ -59,6 +59,7 @@ namespace Qt3DRender {
/*!
\qmltype RenderState
+ \inqmlmodule Qt3D.Render
\brief An abstract base type for all render states.
\since 5.7
\inherits Node
diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp
index ab9f01d39..7fca2ba3f 100644
--- a/src/render/texture/qabstracttexture.cpp
+++ b/src/render/texture/qabstracttexture.cpp
@@ -139,6 +139,27 @@ void QAbstractTexturePrivate::setHandleType(QAbstractTexture::HandleType type)
*/
/*!
+ \qmltype AbstractTexture
+ \instantiates Qt3DRender::QAbstractTexture
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief A base class to be used to provide textures.
+
+ The AbstractTexture class shouldn't be used directly but rather through one
+ of its subclasses. Each subclass implements a given texture target (2D,
+ 2DArray, 3D, CubeMap ...) Each subclass provides a set of functors for each
+ layer, cube map face and mipmap level. In turn the backend uses those
+ functor to properly fill a corresponding OpenGL texture with data. It is
+ expected the functor does as minimal processing as possible so as not to
+ slow down textures generation and upload. If the content of a texture is
+ the result of a slow procedural generation process, it is recommended not
+ to implement this directly in a functor.
+
+ All textures are unique. If you instantiate twice the same texture this
+ will create 2 identical textures on the GPU, no sharing will take place.
+ */
+
+/*!
\enum Qt3DRender::QAbstractTexture::CubeMapFace
This enum identifies the faces of a cube map texture
@@ -409,6 +430,12 @@ void QAbstractTexture::setSize(int w, int h, int d)
Holds the width of the texture provider.
*/
/*!
+ \qmlproperty int Qt3DRender::QAbstractTexture::width
+
+ Holds the width of the texture provider.
+ */
+
+/*!
Set the width of the texture provider to \a width.
*/
void QAbstractTexture::setWidth(int width)
@@ -426,6 +453,11 @@ void QAbstractTexture::setWidth(int width)
Holds the height of the texture provider.
*/
/*!
+ \qmlproperty int Qt3DRender::QAbstractTexture::height
+
+ Holds the height of the texture provider.
+ */
+/*!
Set the height to \a height.
*/
void QAbstractTexture::setHeight(int height)
@@ -443,6 +475,11 @@ void QAbstractTexture::setHeight(int height)
Holds the depth of the texture provider.
*/
/*!
+ \qmlproperty int Qt3DRender::QAbstractTexture::depth
+
+ Holds the depth of the texture provider.
+ */
+/*!
Set the depth of the texture to \a depth.
*/
void QAbstractTexture::setDepth(int depth)
@@ -491,6 +528,15 @@ int QAbstractTexture::depth() const
array target formats.
*/
/*!
+ \qmlproperty int Qt3DRender::QAbstractTexture::layers
+
+ Holds the maximum layer count of the texture provider. By default, the
+ maximum layer count is 1.
+
+ \note this has a meaning only for texture providers that have 3D or
+ array target formats.
+ */
+/*!
Set the maximum layer count to \a layers.
*/
void QAbstractTexture::setLayers(int layers)
@@ -524,6 +570,15 @@ int QAbstractTexture::layers() const
formats.
*/
/*!
+ \qmlproperty int Qt3DRender::QAbstractTexture::samples
+
+ Holds the number of samples per texel for the texture provider.
+ By default, the number of samples is 1.
+
+ \note this has a meaning only for texture providers that have multisample
+ formats.
+ */
+/*!
Set the number of samples per texel to \a samples.
*/
void QAbstractTexture::setSamples(int samples)
@@ -553,6 +608,11 @@ int QAbstractTexture::samples() const
Holds the format of the texture provider.
*/
/*!
+ \qmlproperty TextureFormat Qt3DRender::QAbstractTexture::format
+
+ Holds the format of the texture provider.
+ */
+/*!
Set the texture format to \a format.
*/
void QAbstractTexture::setFormat(TextureFormat format)
@@ -578,6 +638,11 @@ QAbstractTexture::TextureFormat QAbstractTexture::format() const
Holds the current status of the texture provider.
*/
+/*!
+ \qmlproperty Status Qt3DRender::QAbstractTexture::status readonly
+
+ Holds the current status of the texture provider.
+ */
/*!
\enum Qt3DRender::QAbstractTexture::Status
@@ -648,6 +713,13 @@ QAbstractTexture::Status QAbstractTexture::status() const
\note The target format can only be set once.
*/
/*!
+ \qmlproperty Target Qt3DRender::QAbstractTexture::target readonly
+
+ Holds the target format of the texture provider.
+
+ \note The target format can only be set once.
+ */
+/*!
\enum Qt3DRender::QAbstractTexture::Target
\value TargetAutomatic
@@ -741,6 +813,11 @@ QVector<QAbstractTextureImage *> QAbstractTexture::textureImages() const
Holds whether the texture provider should auto generate mipmaps.
*/
/*!
+ \qmlproperty bool Qt3DRender::QAbstractTexture::generateMipMaps
+
+ Holds whether the texture provider should auto generate mipmaps.
+ */
+/*!
Boolean parameter \a gen sets a flag indicating whether the
texture provider should generate mipmaps or not.
*/
@@ -765,6 +842,11 @@ bool QAbstractTexture::generateMipMaps() const
Holds the minification filter of the texture provider.
*/
/*!
+ \qmlproperty Filter Qt3DRender::QAbstractTexture::minificationFilter
+
+ Holds the minification filter of the texture provider.
+ */
+/*!
Set the minification filter to the specified value \a f.
*/
void QAbstractTexture::setMinificationFilter(Filter f)
@@ -799,6 +881,11 @@ void QAbstractTexture::setMinificationFilter(Filter f)
Holds the magnification filter of the texture provider.
*/
/*!
+ \qmlproperty Filter Qt3DRender::QAbstractTexture::magnificationFilter
+
+ Holds the magnification filter of the texture provider.
+ */
+/*!
Set the magnification filter to \a f.
*/
void QAbstractTexture::setMagnificationFilter(Filter f)
@@ -828,6 +915,11 @@ QAbstractTexture::Filter QAbstractTexture::magnificationFilter() const
Holds the wrap mode of the texture provider.
*/
/*!
+ \qmlproperty QTextureWrapMode Qt3DRender::QAbstractTexture::wrapMode
+
+ Holds the wrap mode of the texture provider.
+ */
+/*!
Set the wrapmode to the value specified in \a wrapMode.
*/
void QAbstractTexture::setWrapMode(const QTextureWrapMode &wrapMode)
@@ -859,6 +951,11 @@ QTextureWrapMode *QAbstractTexture::wrapMode()
Holds the maximum anisotropy of the texture provider.
*/
/*!
+ \qmlproperty bool Qt3DRender::QAbstractTexture::maximumAnisotropy
+
+ Holds the maximum anisotropy of the texture provider.
+ */
+/*!
Sets the maximum anisotropy to \a anisotropy.
*/
void QAbstractTexture::setMaximumAnisotropy(float anisotropy)
@@ -885,6 +982,11 @@ float QAbstractTexture::maximumAnisotropy() const
Holds the comparison function of the texture provider.
*/
/*!
+ \qmlproperty ComparisonFunction Qt3DRender::QAbstractTexture::ComparisonFunction
+
+ Holds the comparison function of the texture provider.
+ */
+/*!
Set the comparison function to \a function.
*/
void QAbstractTexture::setComparisonFunction(QAbstractTexture::ComparisonFunction function)
@@ -910,6 +1012,12 @@ QAbstractTexture::ComparisonFunction QAbstractTexture::comparisonFunction() cons
Holds the comparison mode of the texture provider.
*/
+
+/*!
+ \qmlproperty ComparisonMode Qt3DRender::QAbstractTexture::ComparisonMode
+
+ Holds the comparison mode of the texture provider.
+ */
/*!
Set the comparison mode to \a mode.
*/
diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp
index 734942847..bca66e630 100644
--- a/src/render/texture/qtexture.cpp
+++ b/src/render/texture/qtexture.cpp
@@ -1161,6 +1161,13 @@ void TextureDownloadRequest::onCompleted()
\since 5.5
\brief A QAbstractTexture with a Target1D target format.
*/
+/*!
+ \qmltype Texture1D
+ \instantiates Qt3DRender::QTexture1D
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target1D target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture1D instance with \a parent as parent.
@@ -1182,6 +1189,13 @@ QTexture1D::~QTexture1D()
\since 5.5
\brief A QAbstractTexture with a Target1DArray target format.
*/
+/*!
+ \qmltype Texture1DArray
+ \instantiates Qt3DRender::QTexture1DArray
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target1DArray target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture1DArray instance with \a parent as parent.
@@ -1203,6 +1217,13 @@ QTexture1DArray::~QTexture1DArray()
\since 5.5
\brief A QAbstractTexture with a Target2D target format.
*/
+/*!
+ \qmltype Texture2D
+ \instantiates Qt3DRender::QTexture2D
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target2D target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture2D instance with \a parent as parent.
@@ -1224,6 +1245,13 @@ QTexture2D::~QTexture2D()
\since 5.5
\brief A QAbstractTexture with a Target2DArray target format.
*/
+/*!
+ \qmltype Texture2DArray
+ \instantiates Qt3DRender::QTexture2DArray
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target2DArray target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture2DArray instance with \a parent as parent.
@@ -1245,6 +1273,13 @@ QTexture2DArray::~QTexture2DArray()
\since 5.5
\brief A QAbstractTexture with a Target3D target format.
*/
+/*!
+ \qmltype Texture3D
+ \instantiates Qt3DRender::QTexture3D
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target3D target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture3D instance with \a parent as parent.
@@ -1266,6 +1301,13 @@ QTexture3D::~QTexture3D()
\since 5.5
\brief A QAbstractTexture with a TargetCubeMap target format.
*/
+/*!
+ \qmltype TextureCubeMap
+ \instantiates Qt3DRender::QTextureCubeMap
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a TargetCubeMap target format.
+ */
/*!
Constructs a new Qt3DRender::QTextureCubeMap instance with \a parent as parent.
@@ -1287,6 +1329,13 @@ QTextureCubeMap::~QTextureCubeMap()
\since 5.5
\brief A QAbstractTexture with a TargetCubeMapArray target format.
*/
+/*!
+ \qmltype TextureCubeMapArray
+ \instantiates Qt3DRender::QTextureCubeMapArray
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a TargetCubeMapArray target format.
+ */
/*!
Constructs a new Qt3DRender::QTextureCubeMapArray instance with \a parent as parent.
@@ -1308,6 +1357,13 @@ QTextureCubeMapArray::~QTextureCubeMapArray()
\since 5.5
\brief A QAbstractTexture with a Target2DMultisample target format.
*/
+/*!
+ \qmltype Texture2DMultisample
+ \instantiates Qt3DRender::QTexture2DMultisample
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target2DMultisample target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture2DMultisample instance with \a parent as parent.
@@ -1329,6 +1385,13 @@ QTexture2DMultisample::~QTexture2DMultisample()
\since 5.5
\brief A QAbstractTexture with a Target2DMultisampleArray target format.
*/
+/*!
+ \qmltype Texture2DMultisampleArray
+ \instantiates Qt3DRender::QTexture2DMultisampleArray
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target2DMultisampleArray target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture2DMultisampleArray instance with \a parent as parent.
@@ -1350,6 +1413,13 @@ QTexture2DMultisampleArray::~QTexture2DMultisampleArray()
\since 5.5
\brief A QAbstractTexture with a TargetRectangle target format.
*/
+/*!
+ \qmltype TextureRectangle
+ \instantiates Qt3DRender::QTextureRectangle
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a TargetRectangle target format.
+ */
/*!
Constructs a new Qt3DRender::QTextureRectangle instance with \a parent as parent.
@@ -1371,6 +1441,13 @@ QTextureRectangle::~QTextureRectangle()
\since 5.5
\brief A QAbstractTexture with a TargetBuffer target format.
*/
+/*!
+ \qmltype TextureBuffer
+ \instantiates Qt3DRender::QTextureBuffer
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a TargetBuffer target format.
+ */
/*!
Constructs a new Qt3DRender::QTextureBuffer instance with \a parent as parent.
@@ -1483,6 +1560,11 @@ void QTextureLoader::setSource(const QUrl& source)
Q_D(QTextureLoader);
if (source != d->m_source) {
d->m_source = source;
+
+ // Reset target and format
+ d->m_target = TargetAutomatic;
+ setFormat(NoFormat);
+
d->updateGenerator();
const bool blocked = blockNotifications(true);
emit sourceChanged(source);