summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2015-08-12 14:12:49 -0700
committerSean Harmer <sean.harmer@kdab.com>2015-10-19 10:51:19 +0000
commitd9ae5577ea87ae23731fe54dd79fd80ecd1de1fa (patch)
tree6aa31bf99d839cf8ab9c3de757410052581d045a
parent6753c0238bd137f2d5f2528ada2d333e38ef2376 (diff)
Add an example showing instancing using VBO with divisor of 1
Change-Id: I710df314902ca592c236e2120119718fc3b90c2c Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--examples/qt3d/instanced-arrays-qml/instancebuffer.cpp80
-rw-r--r--examples/qt3d/instanced-arrays-qml/instancebuffer.h62
-rw-r--r--examples/qt3d/instanced-arrays-qml/instanced-arrays-qml.pro17
-rw-r--r--examples/qt3d/instanced-arrays-qml/instanced-arrays-qml.qrc7
-rw-r--r--examples/qt3d/instanced-arrays-qml/instanced.frag43
-rw-r--r--examples/qt3d/instanced-arrays-qml/instanced.vert51
-rw-r--r--examples/qt3d/instanced-arrays-qml/main.cpp68
-rw-r--r--examples/qt3d/instanced-arrays-qml/main.qml155
-rw-r--r--examples/qt3d/qt3d.pro3
-rw-r--r--src/render/geometry/qbuffer.h2
10 files changed, 486 insertions, 2 deletions
diff --git a/examples/qt3d/instanced-arrays-qml/instancebuffer.cpp b/examples/qt3d/instanced-arrays-qml/instancebuffer.cpp
new file mode 100644
index 000000000..f457c96b9
--- /dev/null
+++ b/examples/qt3d/instanced-arrays-qml/instancebuffer.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "instancebuffer.h"
+
+#include <QtGui/qvector3d.h>
+
+static const int rowCount = 20;
+static const int colCount = 20;
+static const int maxInstanceCount = rowCount * colCount;
+
+InstanceBuffer::InstanceBuffer(Qt3DCore::QNode *parent)
+ : Qt3DRender::QBuffer(QBuffer::VertexBuffer, parent)
+ , m_instanceCount(maxInstanceCount)
+{
+ // Create some per instance data - position of each instance
+ QByteArray ba;
+ ba.resize(maxInstanceCount * sizeof(QVector3D));
+ QVector3D *posData = reinterpret_cast<QVector3D *>(ba.data());
+ for (int j = 0; j < rowCount; ++j) {
+ const float z = float(j);
+ for (int i = 0; i < colCount; ++i) {
+ const float x = float(i);
+ const QVector3D pos(x, 0.0f, z);
+ *posData = pos;
+ ++posData;
+ }
+ }
+
+ // Put the data into the buffer
+ setData(ba);
+}
+
+int InstanceBuffer::instanceCount() const
+{
+ return m_instanceCount;
+}
+
+void InstanceBuffer::setInstanceCount(int instanceCount)
+{
+ if (m_instanceCount == instanceCount)
+ return;
+
+ m_instanceCount = instanceCount;
+ emit instanceCountChanged(instanceCount);
+}
+
diff --git a/examples/qt3d/instanced-arrays-qml/instancebuffer.h b/examples/qt3d/instanced-arrays-qml/instancebuffer.h
new file mode 100644
index 000000000..6bea7ca97
--- /dev/null
+++ b/examples/qt3d/instanced-arrays-qml/instancebuffer.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INSTANCEBUFFER_H
+#define INSTANCEBUFFER_H
+
+#include <Qt3DRenderer/QBuffer>
+
+class InstanceBuffer : public Qt3DRender::QBuffer
+{
+ Q_OBJECT
+ Q_PROPERTY(int instanceCount READ instanceCount WRITE setInstanceCount NOTIFY instanceCountChanged)
+
+public:
+ InstanceBuffer(Qt3DCore::QNode *parent = 0);
+
+ int instanceCount() const;
+
+public slots:
+ void setInstanceCount(int instanceCount);
+
+signals:
+ void instanceCountChanged(int instanceCount);
+
+private:
+ int m_instanceCount;
+};
+
+#endif // INSTANCEBUFFER_H
diff --git a/examples/qt3d/instanced-arrays-qml/instanced-arrays-qml.pro b/examples/qt3d/instanced-arrays-qml/instanced-arrays-qml.pro
new file mode 100644
index 000000000..a6f569ffc
--- /dev/null
+++ b/examples/qt3d/instanced-arrays-qml/instanced-arrays-qml.pro
@@ -0,0 +1,17 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+QT += qml quick 3dcore 3drenderer 3dinput 3dquick
+
+SOURCES += \
+ main.cpp \
+ instancebuffer.cpp
+
+RESOURCES += \
+ instanced-arrays-qml.qrc
+
+OTHER_FILES += *.qml
+
+HEADERS += \
+ instancebuffer.h
diff --git a/examples/qt3d/instanced-arrays-qml/instanced-arrays-qml.qrc b/examples/qt3d/instanced-arrays-qml/instanced-arrays-qml.qrc
new file mode 100644
index 000000000..3e4910f7a
--- /dev/null
+++ b/examples/qt3d/instanced-arrays-qml/instanced-arrays-qml.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>instanced.frag</file>
+ <file>instanced.vert</file>
+ </qresource>
+</RCC>
diff --git a/examples/qt3d/instanced-arrays-qml/instanced.frag b/examples/qt3d/instanced-arrays-qml/instanced.frag
new file mode 100644
index 000000000..cc41fee8e
--- /dev/null
+++ b/examples/qt3d/instanced-arrays-qml/instanced.frag
@@ -0,0 +1,43 @@
+#version 150 core
+
+uniform vec4 lightPosition = vec4( 0.0, 0.0, 0.0, 1.0 );
+uniform vec3 lightIntensity = vec3( 1.0, 1.0, 1.0 );
+
+uniform vec3 ka; // Ambient reflectivity
+uniform vec3 ks = vec3( 1.0, 1.0, 1.0 ); // Specular reflectivity
+uniform float shininess = 150.0; // Specular shininess factor
+
+in vec3 position;
+in vec3 normal;
+in vec3 kd; // Diffuse reflectivity
+
+out vec4 fragColor;
+
+vec3 adsModel( const in vec3 pos, const in vec3 n )
+{
+ // Calculate the vector from the light to the fragment
+ vec3 s = normalize( vec3( lightPosition ) - pos );
+
+ // Calculate the vector from the fragment to the eye position
+ // (origin since this is in "eye" or "camera" space)
+ vec3 v = normalize( -pos );
+
+ // Reflect the light beam using the normal at this fragment
+ vec3 r = reflect( -s, n );
+
+ // Calculate the diffuse component
+ float diffuse = max( dot( s, n ), 0.0 );
+
+ // Calculate the specular component
+ float specular = 0.0;
+ if ( dot( s, n ) > 0.0 )
+ specular = pow( max( dot( r, v ), 0.0 ), shininess );
+
+ // Combine the ambient, diffuse and specular contributions
+ return lightIntensity * ( ka + kd * diffuse + ks * specular );
+}
+
+void main()
+{
+ fragColor = vec4( adsModel( position, normalize( normal ) ), 1.0 );
+}
diff --git a/examples/qt3d/instanced-arrays-qml/instanced.vert b/examples/qt3d/instanced-arrays-qml/instanced.vert
new file mode 100644
index 000000000..6cbab9d40
--- /dev/null
+++ b/examples/qt3d/instanced-arrays-qml/instanced.vert
@@ -0,0 +1,51 @@
+#version 150 core
+
+in vec3 vertexPosition;
+in vec3 vertexNormal;
+in vec3 pos;
+
+out vec3 position;
+out vec3 normal;
+out vec3 kd;
+
+uniform mat4 modelView;
+uniform mat3 modelViewNormal;
+uniform mat4 mvp;
+
+// Calculate RGB triplet from HSV
+vec3 hsvToRGB( float h, float s, float v )
+{
+ if ( s <= 0.0 )
+ return vec3( v );
+
+ h = h * 6.0;
+ float c = v * s;
+ float x = ( 1.0 - abs( ( mod( h, 2 ) - 1 ) ) ) * c;
+ float m = v - c;
+ float r = 0.0;
+ float g = 0.0;
+ float b = 0.0;
+
+ if ( h < 1.0 ) { r = c; g = x; b = 0.0;}
+ else if ( h < 2.0 ) { r = x; g = c; b = 0.0; }
+ else if ( h < 3.0 ) { r = 0.0; g = c; b = x; }
+ else if ( h < 4.0 ) { r = 0.0; g = x; b = c; }
+ else if ( h < 5.0 ) { r = x; g = 0.0; b = c; }
+ else { r = c; g = 0.0; b = x; }
+
+ return vec3( r + m, g + m, b + m );
+}
+
+void main()
+{
+ normal = normalize( modelViewNormal * vertexNormal );
+
+ vec3 offsetPos = vertexPosition + pos;
+ position = vec3(modelView * vec4(offsetPos, 1.0));
+
+ float hue = fract( pos.x / 10.0 );
+ float saturation = fract( pos.z / 20.0 );
+ kd = hsvToRGB( hue, saturation, 1.0 );
+
+ gl_Position = mvp * vec4(offsetPos, 1.0);
+}
diff --git a/examples/qt3d/instanced-arrays-qml/main.cpp b/examples/qt3d/instanced-arrays-qml/main.cpp
new file mode 100644
index 000000000..4638d910f
--- /dev/null
+++ b/examples/qt3d/instanced-arrays-qml/main.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "instancebuffer.h"
+#include <window.h>
+#include <Qt3DRenderer/QRenderAspect>
+#include <Qt3DInput/QInputAspect>
+#include <Qt3DQuick/QQmlAspectEngine>
+#include <QtQml>
+#include <QGuiApplication>
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ Window view;
+ Qt3DCore::Quick::QQmlAspectEngine engine;
+
+ engine.aspectEngine()->registerAspect(new Qt3DRender::QRenderAspect());
+ engine.aspectEngine()->registerAspect(new Qt3DInput::QInputAspect());
+ engine.aspectEngine()->initialize();
+ QVariantMap data;
+ data.insert(QStringLiteral("surface"), QVariant::fromValue(static_cast<QSurface *>(&view)));
+ data.insert(QStringLiteral("eventSource"), QVariant::fromValue(&view));
+ engine.aspectEngine()->setData(data);
+
+ InstanceBuffer buffer;
+ engine.qmlEngine()->rootContext()->setContextProperty("_instanceBuffer", &buffer);
+
+ engine.setSource(QUrl("qrc:/main.qml"));
+
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/qt3d/instanced-arrays-qml/main.qml b/examples/qt3d/instanced-arrays-qml/main.qml
new file mode 100644
index 000000000..6f16af66e
--- /dev/null
+++ b/examples/qt3d/instanced-arrays-qml/main.qml
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.0
+import Qt3D.Renderer 2.0
+import QtQuick 2.2 as QQ2
+
+Entity {
+ id: sceneRoot
+
+ Camera {
+ id: camera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 22.5
+ aspectRatio: 16/9
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d(10.0, 7.0, 35.0)
+ upVector: Qt.vector3d(0.0, 1.0, 0.0)
+ viewCenter: Qt.vector3d(10.0, 0.5, 0.0)
+ }
+
+ Configuration {
+ controlledCamera: camera
+ }
+
+ components: [
+ FrameGraph {
+ activeFrameGraph: ForwardRenderer {
+ clearColor: Qt.rgba(0, 0.5, 1, 1)
+ camera: camera
+ }
+ }
+ ]
+
+ Material {
+ id: instancedPhongMaterial
+ effect: Effect {
+ techniques: Technique {
+ openGLFilter {
+ api: OpenGLFilter.Desktop
+ profile: OpenGLFilter.Core
+ minorVersion: 2
+ majorVersion: 3
+ }
+ renderPasses: RenderPass {
+ bindings: [
+ ParameterMapping { parameterName: "pos"; shaderVariableName: "pos"; bindingType: ParameterMapping.Attribute }
+ ]
+ shaderProgram: ShaderProgram {
+ vertexShaderCode: loadSource("qrc:/instanced.vert")
+ fragmentShaderCode: loadSource("qrc:/instanced.frag")
+ }
+ }
+ }
+ }
+ }
+
+ // Create a GeometryRenderer component that uses the standard CylinderGeometry to
+ // create the base vertex and index data buffers and attributes.
+ GeometryRenderer {
+ id: cylinderMeshInstanced
+ enabled: instanceCount != 0
+
+ geometry: CylinderGeometry {
+ rings: 50
+ slices: 30
+ radius: 0.3
+ length: 3.0
+
+ attributes: [ instanceDataAttribute ]
+ }
+
+ // Use our buffer created from C++ as per-instance position data to render
+ // many instances (copies) of the base cylinder geometry in a single OpenGL
+ // draw call where supported (OpenGL >=3.3 or OpenGL ES 3). On older versions
+ // of OpenGL the instancing is emulated on the CPU using multiple draw calls.
+ QQ2.SequentialAnimation {
+ running: true
+ loops: QQ2.Animation.Infinite
+
+ QQ2.NumberAnimation {
+ target: cylinderMeshInstanced
+ property: "instanceCount"
+ duration: 5000
+ from: 0
+ to: _instanceBuffer.instanceCount
+ }
+
+ QQ2.PauseAnimation {
+ duration: 3000
+ }
+
+ QQ2.NumberAnimation {
+ target: cylinderMeshInstanced
+ property: "instanceCount"
+ duration: 5000
+ from: _instanceBuffer.instanceCount
+ to: 0
+ }
+
+ QQ2.PauseAnimation {
+ duration: 3000
+ }
+ }
+
+ Attribute {
+ id: instanceDataAttribute
+ name: "pos"
+ attributeType: AbstractAttribute.VertexAttribute
+ dataType: AbstractAttribute.Float
+ dataSize: 3
+ divisor: 1
+ buffer: _instanceBuffer
+ }
+ }
+
+ Entity {
+ id: torusEntity
+ components: [ cylinderMeshInstanced, instancedPhongMaterial ]
+ }
+}
diff --git a/examples/qt3d/qt3d.pro b/examples/qt3d/qt3d.pro
index 001729a61..26fbd89a5 100644
--- a/examples/qt3d/qt3d.pro
+++ b/examples/qt3d/qt3d.pro
@@ -40,7 +40,8 @@ SUBDIRS += \
mouseinput-qml \
custom-mesh-cpp \
bigscene-instanced-qml \
- custom-mesh-qml
+ custom-mesh-qml \
+ instanced-arrays-qml
# TODO Port the old examples to new APIs
#SUBDIRS += qt3d
diff --git a/src/render/geometry/qbuffer.h b/src/render/geometry/qbuffer.h
index c2da32fbe..da1e4293f 100644
--- a/src/render/geometry/qbuffer.h
+++ b/src/render/geometry/qbuffer.h
@@ -85,7 +85,7 @@ public:
};
Q_ENUM(UsageType)
- QBuffer(BufferType ty = QBuffer::VertexBuffer, Qt3DCore::QNode *parent = 0);
+ explicit QBuffer(BufferType ty = QBuffer::VertexBuffer, Qt3DCore::QNode *parent = 0);
~QBuffer();
void setUsage(UsageType usage);