QGIS API Documentation 3.43.0-Master (32433f7016e)
qgsframegraph.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsframegraph.cpp
3 --------------------------------------
4 Date : August 2020
5 Copyright : (C) 2020 by Belgacem Nedjima
6 Email : gb underscore nedjima at esi dot dz
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 "qgsframegraph.h"
17#include "moc_qgsframegraph.cpp"
20#include "qgspreviewquad.h"
21#include "qgs3dutils.h"
22#include "qgsframegraphutils.h"
24#include "qgsshadowrenderview.h"
25
28
29#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
30#include <Qt3DRender/QAttribute>
31#include <Qt3DRender/QBuffer>
32#include <Qt3DRender/QGeometry>
33
34typedef Qt3DRender::QAttribute Qt3DQAttribute;
35typedef Qt3DRender::QBuffer Qt3DQBuffer;
36typedef Qt3DRender::QGeometry Qt3DQGeometry;
37#else
38#include <Qt3DCore/QAttribute>
39#include <Qt3DCore/QBuffer>
40#include <Qt3DCore/QGeometry>
41
42typedef Qt3DCore::QAttribute Qt3DQAttribute;
43typedef Qt3DCore::QBuffer Qt3DQBuffer;
44typedef Qt3DCore::QGeometry Qt3DQGeometry;
45#endif
46
47#include <Qt3DRender/QGeometryRenderer>
48#include <Qt3DRender/QTechnique>
49#include <Qt3DRender/QGraphicsApiFilter>
50#include <Qt3DRender/QBlendEquation>
51#include <Qt3DRender/QColorMask>
52#include <Qt3DRender/QSortPolicy>
53#include <Qt3DRender/QNoDepthMask>
54#include <Qt3DRender/QBlendEquationArguments>
55#include <Qt3DRender/QAbstractTexture>
56#include <Qt3DRender/QNoDraw>
57#include "qgsshadowrenderview.h"
59#include "qgsdepthrenderview.h"
60#include "qgsdepthentity.h"
61
62const QString QgsFrameGraph::FORWARD_RENDERVIEW = "forward";
63const QString QgsFrameGraph::SHADOW_RENDERVIEW = "shadow";
64const QString QgsFrameGraph::AXIS3D_RENDERVIEW = "3daxis";
65const QString QgsFrameGraph::DEPTH_RENDERVIEW = "depth";
66
67void QgsFrameGraph::constructForwardRenderPass()
68{
69 registerRenderView( std::make_unique<QgsForwardRenderView>( FORWARD_RENDERVIEW, mMainCamera ), FORWARD_RENDERVIEW );
70}
71
72void QgsFrameGraph::constructShadowRenderPass()
73{
74 registerRenderView( std::make_unique<QgsShadowRenderView>( SHADOW_RENDERVIEW ), SHADOW_RENDERVIEW );
75}
76
77Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructSubPostPassForTexturesPreview()
78{
79 Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter;
80 layerFilter->setObjectName( "Sub pass TexturesPreview" );
81 layerFilter->addLayer( mPreviewLayer );
82
83 Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet( layerFilter );
84 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
85 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
86 renderStateSet->addRenderState( depthTest );
87 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
88 cullFace->setMode( Qt3DRender::QCullFace::NoCulling );
89 renderStateSet->addRenderState( cullFace );
90
91 return layerFilter;
92}
93
94Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructSubPostPassForProcessing()
95{
96 Qt3DRender::QCameraSelector *cameraSelector = new Qt3DRender::QCameraSelector;
97 cameraSelector->setObjectName( "Sub pass Postprocessing" );
98 cameraSelector->setCamera( shadowRenderView().lightCamera() );
99
100 Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter( cameraSelector );
101
102 // could be the first of this branch
103 new Qt3DRender::QClearBuffers( layerFilter );
104
105 Qt3DRender::QLayer *postProcessingLayer = new Qt3DRender::QLayer();
106 mPostprocessingEntity = new QgsPostprocessingEntity( this, postProcessingLayer, mRootEntity );
107 layerFilter->addLayer( postProcessingLayer );
108 mPostprocessingEntity->setObjectName( "PostProcessingPassEntity" );
109
110 return cameraSelector;
111}
112
113Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructSubPostPassForRenderCapture()
114{
115 Qt3DRender::QFrameGraphNode *top = new Qt3DRender::QNoDraw;
116 top->setObjectName( "Sub pass RenderCapture" );
117
118 mRenderCapture = new Qt3DRender::QRenderCapture( top );
119
120 return top;
121}
122
123Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructPostprocessingPass()
124{
125 mRenderCaptureTargetSelector = new Qt3DRender::QRenderTargetSelector;
126 mRenderCaptureTargetSelector->setObjectName( "Postprocessing render pass" );
127 mRenderCaptureTargetSelector->setEnabled( mRenderCaptureEnabled );
128
129 Qt3DRender::QRenderTarget *renderTarget = new Qt3DRender::QRenderTarget( mRenderCaptureTargetSelector );
130
131 // The lifetime of the objects created here is managed
132 // automatically, as they become children of this object.
133
134 // Create a render target output for rendering color.
135 Qt3DRender::QRenderTargetOutput *colorOutput = new Qt3DRender::QRenderTargetOutput( renderTarget );
136 colorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
137
138 // Create a texture to render into.
139 mRenderCaptureColorTexture = new Qt3DRender::QTexture2D( colorOutput );
140 mRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
141 mRenderCaptureColorTexture->setFormat( Qt3DRender::QAbstractTexture::RGB8_UNorm );
142 mRenderCaptureColorTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
143 mRenderCaptureColorTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
144 mRenderCaptureColorTexture->setObjectName( "PostProcessingPass::ColorTarget" );
145
146 // Hook the texture up to our output, and the output up to this object.
147 colorOutput->setTexture( mRenderCaptureColorTexture );
148 renderTarget->addOutput( colorOutput );
149
150 Qt3DRender::QRenderTargetOutput *depthOutput = new Qt3DRender::QRenderTargetOutput( renderTarget );
151
152 depthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
153 mRenderCaptureDepthTexture = new Qt3DRender::QTexture2D( depthOutput );
154 mRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
155 mRenderCaptureDepthTexture->setFormat( Qt3DRender::QAbstractTexture::DepthFormat );
156 mRenderCaptureDepthTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
157 mRenderCaptureDepthTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
158 mRenderCaptureDepthTexture->setComparisonFunction( Qt3DRender::QAbstractTexture::CompareLessEqual );
159 mRenderCaptureDepthTexture->setComparisonMode( Qt3DRender::QAbstractTexture::CompareRefToTexture );
160 mRenderCaptureDepthTexture->setObjectName( "PostProcessingPass::DepthTarget" );
161
162 depthOutput->setTexture( mRenderCaptureDepthTexture );
163 renderTarget->addOutput( depthOutput );
164
165 mRenderCaptureTargetSelector->setTarget( renderTarget );
166
167 // sub passes:
168 constructSubPostPassForProcessing()->setParent( mRenderCaptureTargetSelector );
169 constructSubPostPassForTexturesPreview()->setParent( mRenderCaptureTargetSelector );
170 constructSubPostPassForRenderCapture()->setParent( mRenderCaptureTargetSelector );
171
172 return mRenderCaptureTargetSelector;
173}
174
175Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructAmbientOcclusionRenderPass()
176{
177 mAmbientOcclusionRenderCameraSelector = new Qt3DRender::QCameraSelector;
178 mAmbientOcclusionRenderCameraSelector->setObjectName( "AmbientOcclusion render pass CameraSelector" );
179 mAmbientOcclusionRenderCameraSelector->setCamera( mMainCamera );
180
181 mAmbientOcclusionRenderStateSet = new Qt3DRender::QRenderStateSet( mAmbientOcclusionRenderCameraSelector );
182
183 Qt3DRender::QDepthTest *depthRenderDepthTest = new Qt3DRender::QDepthTest;
184 depthRenderDepthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
185 ;
186 Qt3DRender::QCullFace *depthRenderCullFace = new Qt3DRender::QCullFace;
187 depthRenderCullFace->setMode( Qt3DRender::QCullFace::NoCulling );
188
189 mAmbientOcclusionRenderStateSet->addRenderState( depthRenderDepthTest );
190 mAmbientOcclusionRenderStateSet->addRenderState( depthRenderCullFace );
191
192 mAmbientOcclusionRenderLayerFilter = new Qt3DRender::QLayerFilter( mAmbientOcclusionRenderStateSet );
193
194 mAmbientOcclusionRenderCaptureTargetSelector = new Qt3DRender::QRenderTargetSelector( mAmbientOcclusionRenderLayerFilter );
195 Qt3DRender::QRenderTarget *colorRenderTarget = new Qt3DRender::QRenderTarget( mAmbientOcclusionRenderCaptureTargetSelector );
196
197 // The lifetime of the objects created here is managed
198 // automatically, as they become children of this object.
199
200 // Create a render target output for rendering color.
201 Qt3DRender::QRenderTargetOutput *colorOutput = new Qt3DRender::QRenderTargetOutput( colorRenderTarget );
202 colorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
203
204 // Create a texture to render into.
205 mAmbientOcclusionRenderTexture = new Qt3DRender::QTexture2D( colorOutput );
206 mAmbientOcclusionRenderTexture->setSize( mSize.width(), mSize.height() );
207 mAmbientOcclusionRenderTexture->setFormat( Qt3DRender::QAbstractTexture::R32F );
208 mAmbientOcclusionRenderTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
209 mAmbientOcclusionRenderTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
210
211 // Hook the texture up to our output, and the output up to this object.
212 colorOutput->setTexture( mAmbientOcclusionRenderTexture );
213 colorRenderTarget->addOutput( colorOutput );
214
215 mAmbientOcclusionRenderCaptureTargetSelector->setTarget( colorRenderTarget );
216
217 Qt3DRender::QLayer *ambientOcclusionRenderLayer = new Qt3DRender::QLayer();
218 Qt3DRender::QTexture2D *forwardDepthTexture = forwardRenderView().depthTexture();
219 mAmbientOcclusionRenderEntity = new QgsAmbientOcclusionRenderEntity( forwardDepthTexture, ambientOcclusionRenderLayer, mMainCamera, mRootEntity );
220 mAmbientOcclusionRenderLayerFilter->addLayer( ambientOcclusionRenderLayer );
221
222 return mAmbientOcclusionRenderCameraSelector;
223}
224
225Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructAmbientOcclusionBlurPass()
226{
227 mAmbientOcclusionBlurCameraSelector = new Qt3DRender::QCameraSelector;
228 mAmbientOcclusionBlurCameraSelector->setObjectName( "AmbientOcclusion blur pass CameraSelector" );
229 mAmbientOcclusionBlurCameraSelector->setCamera( mMainCamera );
230
231 mAmbientOcclusionBlurStateSet = new Qt3DRender::QRenderStateSet( mAmbientOcclusionBlurCameraSelector );
232
233 Qt3DRender::QDepthTest *depthRenderDepthTest = new Qt3DRender::QDepthTest;
234 depthRenderDepthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
235 ;
236 Qt3DRender::QCullFace *depthRenderCullFace = new Qt3DRender::QCullFace;
237 depthRenderCullFace->setMode( Qt3DRender::QCullFace::NoCulling );
238
239 mAmbientOcclusionBlurStateSet->addRenderState( depthRenderDepthTest );
240 mAmbientOcclusionBlurStateSet->addRenderState( depthRenderCullFace );
241
242 mAmbientOcclusionBlurLayerFilter = new Qt3DRender::QLayerFilter( mAmbientOcclusionBlurStateSet );
243
244 mAmbientOcclusionBlurRenderCaptureTargetSelector = new Qt3DRender::QRenderTargetSelector( mAmbientOcclusionBlurLayerFilter );
245 Qt3DRender::QRenderTarget *depthRenderTarget = new Qt3DRender::QRenderTarget( mAmbientOcclusionBlurRenderCaptureTargetSelector );
246
247 // The lifetime of the objects created here is managed
248 // automatically, as they become children of this object.
249
250 // Create a render target output for rendering color.
251 Qt3DRender::QRenderTargetOutput *colorOutput = new Qt3DRender::QRenderTargetOutput( depthRenderTarget );
252 colorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
253
254 // Create a texture to render into.
255 mAmbientOcclusionBlurTexture = new Qt3DRender::QTexture2D( colorOutput );
256 mAmbientOcclusionBlurTexture->setSize( mSize.width(), mSize.height() );
257 mAmbientOcclusionBlurTexture->setFormat( Qt3DRender::QAbstractTexture::R32F );
258 mAmbientOcclusionBlurTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
259 mAmbientOcclusionBlurTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
260
261 // Hook the texture up to our output, and the output up to this object.
262 colorOutput->setTexture( mAmbientOcclusionBlurTexture );
263 depthRenderTarget->addOutput( colorOutput );
264
265 mAmbientOcclusionBlurRenderCaptureTargetSelector->setTarget( depthRenderTarget );
266
267 Qt3DRender::QLayer *ambientOcclusionBlurLayer = new Qt3DRender::QLayer();
268 mAmbientOcclusionBlurEntity = new QgsAmbientOcclusionBlurEntity( mAmbientOcclusionRenderTexture, ambientOcclusionBlurLayer, mRootEntity );
269 mAmbientOcclusionBlurLayerFilter->addLayer( ambientOcclusionBlurLayer );
270
271 return mAmbientOcclusionBlurCameraSelector;
272}
273
274
275Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructRubberBandsPass()
276{
277 mRubberBandsCameraSelector = new Qt3DRender::QCameraSelector;
278 mRubberBandsCameraSelector->setObjectName( "RubberBands Pass CameraSelector" );
279 mRubberBandsCameraSelector->setCamera( mMainCamera );
280
281 mRubberBandsLayerFilter = new Qt3DRender::QLayerFilter( mRubberBandsCameraSelector );
282 mRubberBandsLayerFilter->addLayer( mRubberBandsLayer );
283
284 Qt3DRender::QBlendEquationArguments *blendState = new Qt3DRender::QBlendEquationArguments;
285 blendState->setSourceRgb( Qt3DRender::QBlendEquationArguments::SourceAlpha );
286 blendState->setDestinationRgb( Qt3DRender::QBlendEquationArguments::OneMinusSourceAlpha );
287
288 Qt3DRender::QBlendEquation *blendEquation = new Qt3DRender::QBlendEquation;
289 blendEquation->setBlendFunction( Qt3DRender::QBlendEquation::Add );
290
291 mRubberBandsStateSet = new Qt3DRender::QRenderStateSet( mRubberBandsLayerFilter );
292 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
293 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
294 mRubberBandsStateSet->addRenderState( depthTest );
295 mRubberBandsStateSet->addRenderState( blendState );
296 mRubberBandsStateSet->addRenderState( blendEquation );
297
298 // Here we attach our drawings to the render target also used by forward pass.
299 // This is kind of okay, but as a result, post-processing effects get applied
300 // to rubber bands too. Ideally we would want them on top of everything.
301 mRubberBandsRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mRubberBandsStateSet );
302 mRubberBandsRenderTargetSelector->setTarget( forwardRenderView().renderTargetSelector()->target() );
303
304 return mRubberBandsCameraSelector;
305}
306
307
308void QgsFrameGraph::constructDepthRenderPass()
309{
310 // entity used to draw the depth texture and convert it to rgb image
311 Qt3DRender::QTexture2D *forwardDepthTexture = forwardRenderView().depthTexture();
312 QgsDepthRenderView *rv = new QgsDepthRenderView( DEPTH_RENDERVIEW, mSize, forwardDepthTexture, mRootEntity );
313 registerRenderView( std::unique_ptr<QgsDepthRenderView>( rv ), DEPTH_RENDERVIEW );
314}
315
316Qt3DRender::QRenderCapture *QgsFrameGraph::depthRenderCapture()
317{
319}
320
321QgsFrameGraph::QgsFrameGraph( QSurface *surface, QSize s, Qt3DRender::QCamera *mainCamera, Qt3DCore::QEntity *root )
322 : Qt3DCore::QEntity( root )
323 , mSize( s )
324{
325 // general overview of how the frame graph looks:
326 //
327 // +------------------------+ using window or
328 // | QRenderSurfaceSelector | offscreen surface
329 // +------------------------+
330 // |
331 // +-----------+
332 // | QViewport | (0,0,1,1)
333 // +-----------+
334 // |
335 // +--------------------------+-------------------+-----------------+
336 // | | | |
337 // +--------------------+ +--------------+ +-----------------+ +-----------------+
338 // | two forward passes | | shadows pass | | depth buffer | | post-processing |
339 // | (solid objects | | | | processing pass | | passes |
340 // | and transparent) | +--------------+ +-----------------+ +-----------------+
341 // +--------------------+
342 //
343 // Notes:
344 // - depth buffer processing pass is used whenever we need depth map information
345 // (for camera navigation) and it converts depth texture to a color texture
346 // so that we can capture it with QRenderCapture - currently it is unable
347 // to capture depth buffer, only colors (see QTBUG-65155)
348 // - there are multiple post-processing passes that take rendered output
349 // of the scene, optionally apply effects (add shadows, ambient occlusion,
350 // eye dome lighting) and finally output to the given surface
351 // - there may be also two more passes when 3D axis is shown - see Qgs3DAxis
352
353 mRootEntity = root;
354 mMainCamera = mainCamera;
355
356 mPreviewLayer = new Qt3DRender::QLayer;
357 mRubberBandsLayer = new Qt3DRender::QLayer;
358
359 mRubberBandsLayer->setObjectName( "mRubberBandsLayer" );
360
361 mPreviewLayer->setRecursive( true );
362 mRubberBandsLayer->setRecursive( true );
363
364 mRenderSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector;
365
366 QObject *surfaceObj = dynamic_cast<QObject *>( surface );
367 Q_ASSERT( surfaceObj );
368
369 mRenderSurfaceSelector->setSurface( surfaceObj );
370 mRenderSurfaceSelector->setExternalRenderTargetSize( mSize );
371
372 mMainViewPort = new Qt3DRender::QViewport( mRenderSurfaceSelector );
373 mMainViewPort->setNormalizedRect( QRectF( 0.0f, 0.0f, 1.0f, 1.0f ) );
374
375 // Forward render
376 constructForwardRenderPass();
377
378 // rubber bands (they should be always on top)
379 Qt3DRender::QFrameGraphNode *rubberBandsPass = constructRubberBandsPass();
380 rubberBandsPass->setObjectName( "rubberBandsPass" );
381 rubberBandsPass->setParent( mMainViewPort );
382
383 // shadow rendering pass
384 constructShadowRenderPass();
385
386 // depth buffer processing
387 constructDepthRenderPass();
388
389 // Ambient occlusion factor render pass
390 Qt3DRender::QFrameGraphNode *ambientOcclusionFactorRender = constructAmbientOcclusionRenderPass();
391 ambientOcclusionFactorRender->setParent( mMainViewPort );
392
393 Qt3DRender::QFrameGraphNode *ambientOcclusionBlurPass = constructAmbientOcclusionBlurPass();
394 ambientOcclusionBlurPass->setParent( mMainViewPort );
395
396 // post process
397 Qt3DRender::QFrameGraphNode *postprocessingPass = constructPostprocessingPass();
398 postprocessingPass->setParent( mMainViewPort );
399 postprocessingPass->setObjectName( "PostProcessingPass" );
400
401 mRubberBandsRootEntity = new Qt3DCore::QEntity( mRootEntity );
402 mRubberBandsRootEntity->setObjectName( "mRubberBandsRootEntity" );
403 mRubberBandsRootEntity->addComponent( mRubberBandsLayer );
404
405 Qt3DRender::QParameter *depthMapIsDepthParam = new Qt3DRender::QParameter( "isDepth", true );
406 Qt3DRender::QParameter *shadowMapIsDepthParam = new Qt3DRender::QParameter( "isDepth", true );
407
408 Qt3DRender::QTexture2D *forwardDepthTexture = forwardRenderView().depthTexture();
409 mDebugDepthMapPreviewQuad = this->addTexturePreviewOverlay( forwardDepthTexture, QPointF( 0.9f, 0.9f ), QSizeF( 0.1, 0.1 ), QVector<Qt3DRender::QParameter *> { depthMapIsDepthParam } );
410
411 Qt3DRender::QTexture2D *shadowMapTexture = shadowRenderView().mapTexture();
412 mDebugShadowMapPreviewQuad = this->addTexturePreviewOverlay( shadowMapTexture, QPointF( 0.9f, 0.9f ), QSizeF( 0.1, 0.1 ), QVector<Qt3DRender::QParameter *> { shadowMapIsDepthParam } );
413
414 mDebugDepthMapPreviewQuad->setEnabled( false );
415 mDebugShadowMapPreviewQuad->setEnabled( false );
416}
417
418void QgsFrameGraph::unregisterRenderView( const QString &name )
419{
420 if ( mRenderViewMap.find( name ) != mRenderViewMap.end() )
421 {
422 mRenderViewMap[name]->topGraphNode()->setParent( ( QNode * ) nullptr );
423 mRenderViewMap.erase( name );
424 }
425}
426
427bool QgsFrameGraph::registerRenderView( std::unique_ptr<QgsAbstractRenderView> renderView, const QString &name )
428{
429 bool out;
430 if ( mRenderViewMap.find( name ) == mRenderViewMap.end() )
431 {
432 mRenderViewMap[name] = std::move( renderView );
433 mRenderViewMap[name]->topGraphNode()->setParent( mMainViewPort );
434 mRenderViewMap[name]->updateWindowResize( mSize.width(), mSize.height() );
435 out = true;
436 }
437 else
438 out = false;
439
440 return out;
441}
442
443void QgsFrameGraph::setRenderViewEnabled( const QString &name, bool enable )
444{
445 if ( mRenderViewMap[name] )
446 {
447 mRenderViewMap[name]->setEnabled( enable );
448 }
449}
450
452{
453 if ( mRenderViewMap.find( name ) != mRenderViewMap.end() )
454 {
455 return mRenderViewMap[name].get();
456 }
457 return nullptr;
458}
459
460bool QgsFrameGraph::isRenderViewEnabled( const QString &name )
461{
462 return mRenderViewMap[name] != nullptr && mRenderViewMap[name]->isEnabled();
463}
464
465QgsPreviewQuad *QgsFrameGraph::addTexturePreviewOverlay( Qt3DRender::QTexture2D *texture, const QPointF &centerTexCoords, const QSizeF &sizeTexCoords, QVector<Qt3DRender::QParameter *> additionalShaderParameters )
466{
467 QgsPreviewQuad *previewQuad = new QgsPreviewQuad( texture, centerTexCoords, sizeTexCoords, additionalShaderParameters );
468 previewQuad->addComponent( mPreviewLayer );
469 previewQuad->setParent( mRootEntity );
470 mPreviewQuads.push_back( previewQuad );
471 return previewQuad;
472}
473
474void QgsFrameGraph::updateShadowSettings( const QgsShadowSettings &shadowSettings, const QList<QgsLightSource *> &lightSources )
475{
476 if ( shadowSettings.renderShadows() )
477 {
478 int selectedLight = shadowSettings.selectedDirectionalLight();
479 QgsDirectionalLightSettings *light = nullptr;
480 for ( int i = 0, dirLight = 0; !light && i < lightSources.size(); i++ )
481 {
482 if ( lightSources[i]->type() == Qgis::LightSourceType::Directional )
483 {
484 if ( dirLight == selectedLight )
485 light = qgis::down_cast< QgsDirectionalLightSettings * >( lightSources[i] );
486 dirLight++;
487 }
488 }
489
490 if ( light )
491 {
492 shadowRenderView().setMapSize( shadowSettings.shadowMapResolution(), shadowSettings.shadowMapResolution() );
494 mPostprocessingEntity->setShadowRenderingEnabled( true );
495 mPostprocessingEntity->setShadowBias( static_cast<float>( shadowSettings.shadowBias() ) );
496 mPostprocessingEntity->updateShadowSettings( *light, static_cast<float>( shadowSettings.maximumShadowRenderingDistance() ) );
497 }
498 }
499 else
500 {
501 shadowRenderView().setEnabled( false );
502 mPostprocessingEntity->setShadowRenderingEnabled( false );
503 }
504}
505
507{
508 QObject *top = mRenderSurfaceSelector;
509 while ( top->parent() && dynamic_cast<Qt3DRender::QFrameGraphNode *>( top->parent() ) )
510 top = top->parent();
511
513 context.lowestId = mMainCamera->id().id();
514 QStringList strList = QgsFrameGraphUtils::dumpFrameGraph( dynamic_cast<Qt3DRender::QFrameGraphNode *>( top ), context );
515
516 return strList.join( "\n" ) + QString( "\n" );
517}
518
520{
521 QStringList strList = QgsFrameGraphUtils::dumpSceneGraph( mRootEntity, QgsFrameGraphUtils::FgDumpContext() );
522 return strList.join( "\n" ) + QString( "\n" );
523}
524
525void QgsFrameGraph::setClearColor( const QColor &clearColor )
526{
527 forwardRenderView().setClearColor( clearColor );
528}
529
531{
532 mAmbientOcclusionEnabled = enabled;
533 mAmbientOcclusionRenderEntity->setEnabled( enabled );
534 mPostprocessingEntity->setAmbientOcclusionEnabled( enabled );
535}
536
538{
539 mAmbientOcclusionIntensity = intensity;
540 mAmbientOcclusionRenderEntity->setIntensity( intensity );
541}
542
544{
545 mAmbientOcclusionRadius = radius;
546 mAmbientOcclusionRenderEntity->setRadius( radius );
547}
548
550{
551 mAmbientOcclusionThreshold = threshold;
552 mAmbientOcclusionRenderEntity->setThreshold( threshold );
553}
554
559
560void QgsFrameGraph::setupEyeDomeLighting( bool enabled, double strength, int distance )
561{
562 mEyeDomeLightingEnabled = enabled;
563 mEyeDomeLightingStrength = strength;
564 mEyeDomeLightingDistance = distance;
565 mPostprocessingEntity->setEyeDomeLightingEnabled( enabled );
566 mPostprocessingEntity->setEyeDomeLightingStrength( strength );
567 mPostprocessingEntity->setEyeDomeLightingDistance( distance );
568}
569
570void QgsFrameGraph::setupShadowMapDebugging( bool enabled, Qt::Corner corner, double size )
571{
572 mDebugShadowMapPreviewQuad->setEnabled( enabled );
573 if ( enabled )
574 {
575 switch ( corner )
576 {
577 case Qt::Corner::TopRightCorner:
578 mDebugShadowMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
579 break;
580 case Qt::Corner::TopLeftCorner:
581 mDebugShadowMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
582 break;
583 case Qt::Corner::BottomRightCorner:
584 mDebugShadowMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
585 break;
586 case Qt::Corner::BottomLeftCorner:
587 mDebugShadowMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
588 break;
589 }
590 }
591}
592
593void QgsFrameGraph::setupDepthMapDebugging( bool enabled, Qt::Corner corner, double size )
594{
595 mDebugDepthMapPreviewQuad->setEnabled( enabled );
596
597 if ( enabled )
598 {
599 switch ( corner )
600 {
601 case Qt::Corner::TopRightCorner:
602 mDebugDepthMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
603 break;
604 case Qt::Corner::TopLeftCorner:
605 mDebugDepthMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
606 break;
607 case Qt::Corner::BottomRightCorner:
608 mDebugDepthMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
609 break;
610 case Qt::Corner::BottomLeftCorner:
611 mDebugDepthMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
612 break;
613 }
614 }
615}
616
618{
619 mSize = s;
620 for ( auto it = mRenderViewMap.begin(); it != mRenderViewMap.end(); ++it )
621 {
622 QgsAbstractRenderView *rv = it->second.get();
623 rv->updateWindowResize( mSize.width(), mSize.height() );
624 }
625
626 mRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
627 mRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
628 mRenderSurfaceSelector->setExternalRenderTargetSize( mSize );
629
630 mAmbientOcclusionRenderTexture->setSize( mSize.width(), mSize.height() );
631 mAmbientOcclusionBlurTexture->setSize( mSize.width(), mSize.height() );
632}
633
635{
636 if ( enabled == mRenderCaptureEnabled )
637 return;
638 mRenderCaptureEnabled = enabled;
639 mRenderCaptureTargetSelector->setEnabled( mRenderCaptureEnabled );
640}
641
646
651
652void QgsFrameGraph::addClipPlanes( int nrClipPlanes )
653{
654 forwardRenderView().addClipPlanes( nrClipPlanes );
655}
656
658{
660 return *( dynamic_cast<QgsForwardRenderView *>( rv ) );
661}
662
664{
666 return *( dynamic_cast<QgsShadowRenderView *>( rv ) );
667}
668
670{
671 QgsAbstractRenderView *rv = mRenderViewMap[QgsFrameGraph::DEPTH_RENDERVIEW].get();
672 return *( dynamic_cast<QgsDepthRenderView *>( rv ) );
673}
@ Directional
Directional light source.
Base class for 3D render view.
virtual void updateWindowResize(int width, int height)
Called when 3D window is resized.
An entity that is responsible for blurring the ambient occlusion factor texture.
An entity that is responsible for producing an ambient occlusion factor map.
void setThreshold(float threshold)
Sets the amount of occlusion when the effects starts to kick in.
void setRadius(float radius)
Sets the radius for the ambient occlusion effect.
void setIntensity(float intensity)
Sets the intensity for the ambient occlusion effect.
Container class that holds different objects related to depth rendering.
Qt3DRender::QRenderCapture * renderCapture()
Returns the render capture object used to take an image of the depth buffer of the scene.
Definition of a directional light in a 3D map scene.
Container class that holds different objects related to forward rendering.
void setClearColor(const QColor &clearColor)
Sets the clear color of the scene (background color)
void setDebugOverlayEnabled(bool enabled)
Sets whether debug overlay is enabled.
void setFrustumCullingEnabled(bool enabled)
Sets whether frustum culling is enabled.
Qt3DRender::QTexture2D * depthTexture() const
Returns forward depth texture.
void addClipPlanes(int nrClipPlanes)
Setups nrClipPlanes clip planes in the forward pass to enable OpenGL clipping.
void removeClipPlanes()
Disables OpenGL clipping.
static QStringList dumpFrameGraph(const Qt3DCore::QNode *node, FgDumpContext context)
Returns a tree view of the frame graph starting from node. The object ids will be given relatively to...
static QStringList dumpSceneGraph(const Qt3DCore::QNode *node, FgDumpContext context)
Returns a tree view of the scene graph starting from node. The object ids will be given relatively to...
bool isRenderViewEnabled(const QString &name)
Returns true if the render view named name is found and enabled.
void setRenderViewEnabled(const QString &name, bool enable)
Enables or disables the render view named name according to enable.
void updateShadowSettings(const QgsShadowSettings &shadowSettings, const QList< QgsLightSource * > &lightSources)
Updates shadow bias, light and texture size according to shadowSettings and lightSources.
void addClipPlanes(int nrClipPlanes)
Setups nrClipPlanes clip planes in the forward pass to enable OpenGL clipping.
void unregisterRenderView(const QString &name)
Unregisters the render view named name, if any.
QString dumpFrameGraph() const
Dumps frame graph as string.
void setRenderCaptureEnabled(bool enabled)
Sets whether it will be possible to render to an image.
Qt3DRender::QRenderCapture * depthRenderCapture()
Returns the render capture object used to take an image of the depth buffer of the scene.
QgsAbstractRenderView * renderView(const QString &name)
Returns the render view named name, if any.
void removeClipPlanes()
Disables OpenGL clipping.
bool registerRenderView(std::unique_ptr< QgsAbstractRenderView > renderView, const QString &name)
Registers a new the render view renderView with name name.
void setupShadowMapDebugging(bool enabled, Qt::Corner corner, double size)
Sets the shadow map debugging view port.
QgsDepthRenderView & depthRenderView()
Returns depth renderview.
void setClearColor(const QColor &clearColor)
Sets the clear color of the scene (background color)
QgsPreviewQuad * addTexturePreviewOverlay(Qt3DRender::QTexture2D *texture, const QPointF &centerNDC, const QSizeF &size, QVector< Qt3DRender::QParameter * > additionalShaderParameters=QVector< Qt3DRender::QParameter * >())
Adds an preview entity that shows a texture in real time for debugging purposes.
void setAmbientOcclusionIntensity(float intensity)
Sets the ambient occlusion intensity.
static const QString FORWARD_RENDERVIEW
void setFrustumCullingEnabled(bool enabled)
Sets whether frustum culling is enabled.
static const QString SHADOW_RENDERVIEW
void setDebugOverlayEnabled(bool enabled)
Sets whether debug overlay is enabled.
void setupDepthMapDebugging(bool enabled, Qt::Corner corner, double size)
Sets the depth map debugging view port.
static const QString AXIS3D_RENDERVIEW
QgsForwardRenderView & forwardRenderView()
Returns forward renderview.
void setAmbientOcclusionThreshold(float threshold)
Sets the ambient occlusion threshold.
QString dumpSceneGraph() const
Dumps scene graph as string.
QgsShadowRenderView & shadowRenderView()
Returns shadow renderview.
void setupEyeDomeLighting(bool enabled, double strength, int distance)
Sets eye dome lighting shading related settings.
void setSize(QSize s)
Sets the size of the buffers used for rendering.
void setAmbientOcclusionEnabled(bool enabled)
Sets whether Screen Space Ambient Occlusion will be enabled.
static const QString DEPTH_RENDERVIEW
void setAmbientOcclusionRadius(float radius)
Sets the ambient occlusion radius.
Qt3DRender::QCamera * mainCamera()
Returns the main camera.
QgsFrameGraph(QSurface *surface, QSize s, Qt3DRender::QCamera *mainCamera, Qt3DCore::QEntity *root)
Constructor.
An entity that is responsible for applying post processing effects.
void setAmbientOcclusionEnabled(bool enabled)
Sets whether screen space ambient occlusion is enabled.
void setShadowRenderingEnabled(bool enabled)
Sets whether shadow rendering is enabled.
void updateShadowSettings(const QgsDirectionalLightSettings &light, float maximumShadowRenderingDistance)
Sets shadow rendering to use a directional light.
void setEyeDomeLightingDistance(int distance)
Sets the eye dome lighting distance (contributes to the contrast of the image)
void setShadowBias(float shadowBias)
Sets the shadow bias value.
void setEyeDomeLightingStrength(double strength)
Sets the eye dome lighting strength.
void setEyeDomeLightingEnabled(bool enabled)
Sets whether eye dome lighting is enabled.
Rectangular quad entity used for debugging depth maps.
void setViewPort(const QPointF &centerNDC, const QSizeF &size)
Sets where the quad will be located on the scene.
Container class that holds different objects related to shadow rendering.
void setMapSize(int width, int height)
Update shadow depth texture size.
virtual void setEnabled(bool enable) override
Enable or disable via enable the renderview sub tree.
Qt3DRender::QTexture2D * mapTexture() const
Returns shadow depth texture.
Contains configuration for rendering shadows.
int selectedDirectionalLight() const
Returns the selected direcctional light used to cast shadows.
bool renderShadows() const
Returns whether shadow rendering is enabled.
int shadowMapResolution() const
Returns the resolution of the shadow map texture used to generate the shadows.
double maximumShadowRenderingDistance() const
Returns the maximum shadow rendering distance accounted for when rendering shadows Objects further aw...
double shadowBias() const
Returns the shadow bias used to correct the numerical imprecision of shadows (for the depth test) Thi...
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
Qt3DCore::QGeometry Qt3DQGeometry