QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsoffscreen3dengine.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsoffscreen3dengine.cpp
3  --------------------------------------
4  Date : July 2018
5  Copyright : (C) 2018 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsoffscreen3dengine.h"
17 #include "qgslogger.h"
18 
19 #include <QOffscreenSurface>
20 #include <QSurfaceFormat>
21 #include <QOpenGLFunctions>
22 
23 #include <Qt3DCore/QAspectEngine>
24 #include <Qt3DLogic/QLogicAspect>
25 #include <Qt3DRender/QCamera>
26 #include <Qt3DRender/QCameraSelector>
27 #include <Qt3DRender/QClearBuffers>
28 #include <Qt3DRender/QRenderAspect>
29 #include <Qt3DRender/QRenderCapture>
30 #include <Qt3DRender/QRenderSettings>
31 #include <Qt3DRender/QRenderTarget>
32 #include <Qt3DRender/QRenderTargetOutput>
33 #include <Qt3DRender/QRenderTargetSelector>
34 #include <Qt3DRender/QRenderSurfaceSelector>
35 #include <Qt3DRender/QTexture>
36 #include <Qt3DRender/QViewport>
37 #include <QtGui/QOpenGLContext>
38 
40 {
41  // Set up the default OpenGL surface format.
42  QSurfaceFormat format;
43 
44  // by default we get just some older version of OpenGL from the system,
45  // but for 3D lines we use "primitive restart" functionality supported in OpenGL >= 3.1
46  // Qt3DWindow uses this - requesting OpenGL 4.3 - so let's request the same version.
47 #ifdef QT_OPENGL_ES_2
48  format.setRenderableType( QSurfaceFormat::OpenGLES );
49 #else
50  if ( QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL )
51  {
52  format.setVersion( 4, 3 );
53  format.setProfile( QSurfaceFormat::CoreProfile );
54  }
55 #endif
56 
57  format.setMajorVersion( 3 );
58  format.setDepthBufferSize( 32 ); // TODO: or 24? (used by QWindow3D)
59  format.setSamples( 8 );
60  QSurfaceFormat::setDefaultFormat( format );
61 
62  // Set up a camera to point at the shapes.
63  mCamera = new Qt3DRender::QCamera;
64  mCamera->lens()->setPerspectiveProjection( 45.0f, float( mSize.width() ) / float( mSize.height() ), 0.1f, 1000.0f );
65  mCamera->setPosition( QVector3D( 0, 0, 20.0f ) );
66  mCamera->setUpVector( QVector3D( 0, 1, 0 ) );
67  mCamera->setViewCenter( QVector3D( 0, 0, 0 ) );
68 
69  // Set up the engine and the aspects that we want to use.
70  mAspectEngine = new Qt3DCore::QAspectEngine();
71  mRenderAspect = new Qt3DRender::QRenderAspect( Qt3DRender::QRenderAspect::Threaded ); // Only threaded mode seems to work right now.
72  mLogicAspect = new Qt3DLogic::QLogicAspect();
73 
74  mAspectEngine->registerAspect( mRenderAspect );
75  mAspectEngine->registerAspect( mLogicAspect );
76 
77  // Create the root entity of the engine.
78  // This is not the same as the 3D scene root: the QRenderSettings
79  // component must be held by the root of the QEntity tree,
80  // so it is added to this one. The 3D scene is added as a subtree later,
81  // in setRootEntity().
82  mRoot = new Qt3DCore::QEntity;
83  mRenderSettings = new Qt3DRender::QRenderSettings( mRoot );
84  mRoot->addComponent( mRenderSettings );
85 
86  mCamera->setParent( mRoot );
87 
88  // Create the offscreen frame graph, which will manage all of the resources required
89  // for rendering without a QWindow.
90  mOffscreenSurface = new QOffscreenSurface();
91  mOffscreenSurface->setFormat( QSurfaceFormat::defaultFormat() );
92  mOffscreenSurface->create();
93 
94  mFrameGraph = new QgsShadowRenderingFrameGraph( mOffscreenSurface, mSize, mCamera, mRoot );
97  // Set this frame graph to be in use.
98  // the render settings also sets itself as the parent of mSurfaceSelector
99  mRenderSettings->setActiveFrameGraph( mFrameGraph->frameGraphRoot() );
100 
101  // Set the root entity of the engine. This causes the engine to begin running.
102  mAspectEngine->setRootEntity( Qt3DCore::QEntityPtr( mRoot ) );
103 
104 }
105 
107 {
108  delete mAspectEngine;
109  delete mOffscreenSurface;
110 }
111 
113 {
114  mSize = s;
115 
116  mFrameGraph->setSize( mSize );
117  mCamera->setAspectRatio( float( mSize.width() ) / float( mSize.height() ) );
118 }
119 
120 void QgsOffscreen3DEngine::setClearColor( const QColor &color )
121 {
122  mFrameGraph->setClearColor( color );
123 }
124 
126 {
128 }
129 
130 void QgsOffscreen3DEngine::setRootEntity( Qt3DCore::QEntity *root )
131 {
132  // Make sure any existing scene root is unparented.
133  if ( mSceneRoot )
134  {
135  mSceneRoot->setParent( static_cast<Qt3DCore::QNode *>( nullptr ) );
136  }
137 
138  // Parent the incoming scene root to our current root entity.
139  mSceneRoot = root;
140  mSceneRoot->setParent( mRoot );
141  root->addComponent( mFrameGraph->forwardRenderLayer() );
142  root->addComponent( mFrameGraph->castShadowsLayer() );
143 }
144 
145 Qt3DRender::QRenderSettings *QgsOffscreen3DEngine::renderSettings()
146 {
147  return mRenderSettings;
148 }
149 
150 Qt3DRender::QCamera *QgsOffscreen3DEngine::camera()
151 {
152  return mCamera;
153 }
154 
156 {
157  return mSize;
158 }
159 
161 {
162  return mOffscreenSurface;
163 }
QgsShadowRenderingFrameGraph * mFrameGraph
void setSize(QSize s) override
Sets the size of the rendering area (in pixels)
void setClearColor(const QColor &color) override
Sets background color of the scene.
QSize size() const override
Returns size of the engine's rendering area in pixels.
void setRootEntity(Qt3DCore::QEntity *root) override
Sets root entity of the 3D scene.
void setFrustumCullingEnabled(bool enabled) override
Sets whether frustum culling is enabled (this should make rendering faster by not rendering entities ...
Qt3DRender::QCamera * camera() override
Returns pointer to the engine's camera entity.
Qt3DRender::QRenderSettings * renderSettings() override
Returns access to the engine's render settings (the frame graph can be accessed from here)
QSurface * surface() const override
Returns the surface of the engine.
void setSize(QSize s)
Sets the size of the buffers used for rendering.
Qt3DRender::QLayer * castShadowsLayer()
Returns a layer object used to indicate that an entity will cast shadows.
Qt3DRender::QLayer * forwardRenderLayer()
Returns a layer object used to indicate that an entity will be rendered during the forward rendering ...
void setFrustumCullingEnabled(bool enabled)
Sets whether frustum culling is enabled.
void setClearColor(const QColor &clearColor)
Sets the clear color of the scene (background color)
Qt3DRender::QFrameGraphNode * frameGraphRoot()
Returns the root of the frame graph object.
void setRenderCaptureEnabled(bool enabled)
Sets whether it will be possible to render to an image.
void setShadowRenderingEnabled(bool enabled)
Sets whether the shadow rendering is enabled.