QGIS API Documentation 4.1.0-Master (ca2ac17535b)
Loading...
Searching...
No Matches
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
18#include "qgs3dutils.h"
21#include "qgsbloomrenderview.h"
22#include "qgsdepthrenderview.h"
25#include "qgsframegraphutils.h"
30#include "qgsshadowrenderview.h"
31#include "qgssunlightsettings.h"
32
33#include <Qt3DCore/QAttribute>
34#include <Qt3DCore/QBuffer>
35#include <Qt3DCore/QGeometry>
36#include <Qt3DRender/QAbstractTexture>
37#include <Qt3DRender/QBlendEquation>
38#include <Qt3DRender/QBlendEquationArguments>
39#include <Qt3DRender/QBlitFramebuffer>
40#include <Qt3DRender/QColorMask>
41#include <Qt3DRender/QGeometryRenderer>
42#include <Qt3DRender/QGraphicsApiFilter>
43#include <Qt3DRender/QNoDepthMask>
44#include <Qt3DRender/QNoDraw>
45#include <Qt3DRender/QSortPolicy>
46#include <Qt3DRender/QTechnique>
47
48#ifdef HAVE_TRACY
49#include "tracy/Tracy.hpp"
50#endif
51
52#include "moc_qgsframegraph.cpp"
53
54const QString QgsFrameGraph::FORWARD_RENDERVIEW = "forward";
55const QString QgsFrameGraph::SHADOW_RENDERVIEW = "shadow";
56const QString QgsFrameGraph::AXIS3D_RENDERVIEW = "3daxis";
57const QString QgsFrameGraph::DEPTH_RENDERVIEW = "depth";
58const QString QgsFrameGraph::OVERLAY_RENDERVIEW = "overlay_texture";
59const QString QgsFrameGraph::AMBIENT_OCCLUSION_RENDERVIEW = "ambient_occlusion";
60const QString QgsFrameGraph::BLOOM_RENDERVIEW = "bloom";
61const QString QgsFrameGraph::HIGHLIGHTS_RENDERVIEW = "highlights";
62
63void QgsFrameGraph::constructForwardRenderPass()
64{
65 registerRenderView( std::make_unique<QgsForwardRenderView>( FORWARD_RENDERVIEW, mMainCamera ), FORWARD_RENDERVIEW );
66}
67
68void QgsFrameGraph::constructHighlightsPass()
69{
70 registerRenderView( std::make_unique<QgsHighlightsRenderView>( HIGHLIGHTS_RENDERVIEW, forwardRenderView().renderTargetSelector()->target(), mMainCamera ), HIGHLIGHTS_RENDERVIEW );
71}
72
73void QgsFrameGraph::constructShadowRenderPass()
74{
75 registerRenderView( std::make_unique<QgsShadowRenderView>( SHADOW_RENDERVIEW, mRootEntity ), SHADOW_RENDERVIEW );
76}
77
78void QgsFrameGraph::constructOverlayTexturePass( Qt3DRender::QFrameGraphNode *topNode )
79{
80 registerRenderView( std::make_unique<QgsOverlayTextureRenderView>( OVERLAY_RENDERVIEW ), OVERLAY_RENDERVIEW, topNode );
81}
82
83Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructSubPostPassForProcessing()
84{
85 Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter();
86
87 // could be the first of this branch
88 new Qt3DRender::QClearBuffers( layerFilter );
89
90 Qt3DRender::QLayer *postProcessingLayer = new Qt3DRender::QLayer();
91 mPostprocessingEntity = new QgsPostprocessingEntity( this, postProcessingLayer, mRootEntity );
92 layerFilter->addLayer( postProcessingLayer );
93 mPostprocessingEntity->setObjectName( "PostProcessingPassEntity" );
94
95 return layerFilter;
96}
97
98Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructSubPostPassForRenderCapture()
99{
100 Qt3DRender::QFrameGraphNode *top = new Qt3DRender::QNoDraw;
101 top->setObjectName( "Sub pass RenderCapture" );
102
103 mRenderCapture = new Qt3DRender::QRenderCapture( top );
104
105 return top;
106}
107
108void QgsFrameGraph::updateThumbnailTextureSize()
109{
110 // Tracy requires width/height to be multiples of 4, otherwise it will show
111 // just a black rectangle.
112 const int width = ( mSize.width() / 10 ) & ~3;
113 const int height = ( mSize.height() / 10 ) & ~3;
114 mThumbnailTexture->setSize( width, height );
115}
116
117void QgsFrameGraph::constructThumbnailCapturePass()
118{
119 // Diagram of the nodes we're creating:
120 // mMainViewPort
121 // ├── QBlitFramebuffer (copy from forwardRenderView to mThumbnailTexture)
122 // └── QRenderTargetSelector (set to mThumbnailTexture)
123 // └── QRenderCapture (mThumbnailCapture)
124
125 mThumbnailTexture = new Qt3DRender::QTexture2D( this );
126 mThumbnailTexture->setFormat( Qt3DRender::QAbstractTexture::RGBA8_UNorm );
127 updateThumbnailTextureSize();
128
129 Qt3DRender::QRenderTargetOutput *renderTargetOutput = new Qt3DRender::QRenderTargetOutput( this );
130 renderTargetOutput->setTexture( mThumbnailTexture );
131
132 Qt3DRender::QRenderTarget *renderTarget = new Qt3DRender::QRenderTarget( this );
133 renderTarget->addOutput( renderTargetOutput );
134
135 // Copy from forward render pass to thumbnail texture
136 Qt3DRender::QBlitFramebuffer *blit = new Qt3DRender::QBlitFramebuffer( mMainViewPort );
137 blit->setObjectName( "Framebuffer copy for thumbnail" );
138 blit->setSource( forwardRenderView().renderTargetSelector()->target() );
139 blit->setDestination( renderTarget );
140 blit->setSourceRect( QRectF( 0, 0, 1, 1 ) );
141 blit->setDestinationRect( QRectF( 0, 0, 1, 1 ) );
142 blit->setInterpolationMethod( Qt3DRender::QBlitFramebuffer::Linear );
143
144 Qt3DRender::QRenderTargetSelector *targetSelector = new Qt3DRender::QRenderTargetSelector( mMainViewPort );
145 targetSelector->setObjectName( "Thumbnail capture target selector" );
146 targetSelector->setTarget( renderTarget );
147
148 mThumbnailCapture = new Qt3DRender::QRenderCapture( targetSelector );
149 mThumbnailCapture->setObjectName( "Thumbnail capture" );
150
151 // Request initial capture
152 // Ugly hack: Requesting just once results in a capture every two frames.
153 // "Buffering" an extra capture like this works around that.
154 Qt3DRender::QRenderCaptureReply *reply1 = mThumbnailCapture->requestCapture();
155 Qt3DRender::QRenderCaptureReply *reply2 = mThumbnailCapture->requestCapture();
156 for ( Qt3DRender::QRenderCaptureReply *reply : { reply1, reply2 } )
157 connect( reply, &Qt3DRender::QRenderCaptureReply::completed, this, [this, reply]() { onThumbnailCaptureCompleted( reply ); } );
158}
159
160void QgsFrameGraph::onThumbnailCaptureCompleted( Qt3DRender::QRenderCaptureReply *reply )
161{
162 reply->deleteLater();
163
164#ifdef HAVE_TRACY
165 // Convert to RGBA8888 format (required by Tracy)
166 QImage rgbaImage = reply->image().convertToFormat( QImage::Format_RGBA8888 );
167
168 // Send to Tracy
169 FrameImage(
170 rgbaImage.constBits(),
171 static_cast<uint16_t>( rgbaImage.width() ),
172 static_cast<uint16_t>( rgbaImage.height() ),
173 0, // offset: 0 = current frame
174 true // flip Y coord: true for OpenGL
175 );
176#endif
177
178 // Request next frame capture
179 Qt3DRender::QRenderCaptureReply *nextReply = mThumbnailCapture->requestCapture();
180 connect( nextReply, &Qt3DRender::QRenderCaptureReply::completed, this, [this, nextReply]() { onThumbnailCaptureCompleted( nextReply ); } );
181}
182
183Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructPostprocessingPass()
184{
185 mRenderCaptureTargetSelector = new Qt3DRender::QRenderTargetSelector;
186 mRenderCaptureTargetSelector->setObjectName( "Postprocessing render pass" );
187 mRenderCaptureTargetSelector->setEnabled( mRenderCaptureEnabled );
188
189 Qt3DRender::QRenderTarget *renderTarget = new Qt3DRender::QRenderTarget( mRenderCaptureTargetSelector );
190
191 // The lifetime of the objects created here is managed
192 // automatically, as they become children of this object.
193
194 // Create a render target output for rendering color.
195 Qt3DRender::QRenderTargetOutput *colorOutput = new Qt3DRender::QRenderTargetOutput( renderTarget );
196 colorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
197
198 // Create a texture to render into.
199 mRenderCaptureColorTexture = new Qt3DRender::QTexture2D( colorOutput );
200 mRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
201 mRenderCaptureColorTexture->setFormat( Qt3DRender::QAbstractTexture::RGB8_UNorm );
202 mRenderCaptureColorTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
203 mRenderCaptureColorTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
204 mRenderCaptureColorTexture->setObjectName( "PostProcessingPass::ColorTarget" );
205
206 // Hook the texture up to our output, and the output up to this object.
207 colorOutput->setTexture( mRenderCaptureColorTexture );
208 renderTarget->addOutput( colorOutput );
209
210 Qt3DRender::QRenderTargetOutput *depthOutput = new Qt3DRender::QRenderTargetOutput( renderTarget );
211
212 depthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
213 mRenderCaptureDepthTexture = new Qt3DRender::QTexture2D( depthOutput );
214 mRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
215 mRenderCaptureDepthTexture->setFormat( Qt3DRender::QAbstractTexture::DepthFormat );
216 mRenderCaptureDepthTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
217 mRenderCaptureDepthTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
218 mRenderCaptureDepthTexture->setComparisonFunction( Qt3DRender::QAbstractTexture::CompareLessEqual );
219 mRenderCaptureDepthTexture->setComparisonMode( Qt3DRender::QAbstractTexture::CompareRefToTexture );
220 mRenderCaptureDepthTexture->setObjectName( "PostProcessingPass::DepthTarget" );
221
222 depthOutput->setTexture( mRenderCaptureDepthTexture );
223 renderTarget->addOutput( depthOutput );
224
225 mRenderCaptureTargetSelector->setTarget( renderTarget );
226
227 // sub passes:
228 constructSubPostPassForProcessing()->setParent( mRenderCaptureTargetSelector );
229 constructOverlayTexturePass( mRenderCaptureTargetSelector );
230 constructSubPostPassForRenderCapture()->setParent( mRenderCaptureTargetSelector );
231
232 return mRenderCaptureTargetSelector;
233}
234
235void QgsFrameGraph::constructAmbientOcclusionRenderPass()
236{
237 Qt3DRender::QTexture2D *forwardDepthTexture = forwardRenderView().depthTexture();
238
239 QgsAmbientOcclusionRenderView *aorv = new QgsAmbientOcclusionRenderView( AMBIENT_OCCLUSION_RENDERVIEW, mMainCamera, mSize, forwardDepthTexture, mRootEntity );
240 registerRenderView( std::unique_ptr<QgsAmbientOcclusionRenderView>( aorv ), AMBIENT_OCCLUSION_RENDERVIEW );
241}
242
243void QgsFrameGraph::constructBloomRenderPass()
244{
245 Qt3DRender::QTexture2D *forwardColorTexture = forwardRenderView().colorTexture();
246
247 QgsBloomRenderView *rv = new QgsBloomRenderView( BLOOM_RENDERVIEW, forwardColorTexture, mSize, mRootEntity );
248 registerRenderView( std::unique_ptr<QgsBloomRenderView>( rv ), BLOOM_RENDERVIEW );
249}
250
251Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructRubberBandsPass()
252{
253 mRubberBandsCameraSelector = new Qt3DRender::QCameraSelector;
254 mRubberBandsCameraSelector->setObjectName( "RubberBands Pass CameraSelector" );
255 mRubberBandsCameraSelector->setCamera( mMainCamera );
256
257 mRubberBandsLayerFilter = new Qt3DRender::QLayerFilter( mRubberBandsCameraSelector );
258 mRubberBandsLayerFilter->addLayer( mRubberBandsLayer );
259
260 Qt3DRender::QBlendEquationArguments *blendState = new Qt3DRender::QBlendEquationArguments;
261 blendState->setSourceRgb( Qt3DRender::QBlendEquationArguments::SourceAlpha );
262 blendState->setDestinationRgb( Qt3DRender::QBlendEquationArguments::OneMinusSourceAlpha );
263
264 Qt3DRender::QBlendEquation *blendEquation = new Qt3DRender::QBlendEquation;
265 blendEquation->setBlendFunction( Qt3DRender::QBlendEquation::Add );
266
267 mRubberBandsStateSet = new Qt3DRender::QRenderStateSet( mRubberBandsLayerFilter );
268 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
269 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
270 mRubberBandsStateSet->addRenderState( depthTest );
271 mRubberBandsStateSet->addRenderState( blendState );
272 mRubberBandsStateSet->addRenderState( blendEquation );
273
274 // Here we attach our drawings to the render target also used by forward pass.
275 // This is kind of okay, but as a result, post-processing effects get applied
276 // to rubber bands too. Ideally we would want them on top of everything.
277 mRubberBandsRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mRubberBandsStateSet );
278 mRubberBandsRenderTargetSelector->setTarget( forwardRenderView().renderTargetSelector()->target() );
279
280 return mRubberBandsCameraSelector;
281}
282
283void QgsFrameGraph::constructDepthRenderPass()
284{
285 // entity used to draw the depth texture and convert it to rgb image
286 Qt3DRender::QTexture2D *forwardDepthTexture = forwardRenderView().depthTexture();
287 QgsDepthRenderView *rv = new QgsDepthRenderView( DEPTH_RENDERVIEW, mSize, forwardDepthTexture, mRootEntity );
288 registerRenderView( std::unique_ptr<QgsDepthRenderView>( rv ), DEPTH_RENDERVIEW );
289}
290
291Qt3DRender::QRenderCapture *QgsFrameGraph::depthRenderCapture()
292{
294}
295
296void QgsFrameGraph::addGlobalParameters( const QList<Qt3DRender::QParameter *> &parameters )
297{
298 for ( Qt3DRender::QParameter *param : parameters )
299 {
300 mGlobalParamsStorage->addParameter( param );
301 }
302}
303
304QgsFrameGraph::QgsFrameGraph( QSurface *surface, QSize s, Qt3DRender::QCamera *mainCamera, Qt3DCore::QEntity *root )
305 : Qt3DCore::QEntity( root )
306 , mSize( s )
307{
308 // general overview of how the frame graph looks:
309 //
310 // +------------------------+ using window or
311 // | QRenderSurfaceSelector | offscreen surface
312 // +------------------------+
313 // |
314 // +-----------+
315 // | QViewport | (0,0,1,1)
316 // +-----------+
317 // |
318 // +---------------------+---------------+------------------------+-------------------+
319 // | | | | |
320 // | | | (optional) | |
321 // +--------------+ +------------------+ +-----------------+ +-----------------+ +-----------------+
322 // | shadows pass | | forward passes | | MSAA blit | | depth buffer | | post-processing |
323 // | | | (solid objects, | | (color + depth) | | processing pass | | passes |
324 // +--------------+ | transparent, | +-----------------+ +-----------------+ +-----------------+
325 // | highlights, |
326 // | rubber bands) |
327 // +------------------+
328 //
329 // Notes:
330 // - (optional) MSAA blits multisampled (4 samples) color and depth textures
331 // so that other passes can sample them
332 // - shadows pass MUST come before other forward passes, as we use the shadow
333 // information in the material shaders
334 // - depth buffer processing pass is used whenever we need depth map information
335 // (for camera navigation) and it converts depth texture to a color texture
336 // so that we can capture it with QRenderCapture - currently it is unable
337 // to capture depth buffer, only colors (see QTBUG-65155)
338 // - there are multiple post-processing passes that take rendered output
339 // of the scene, optionally apply effects (add shadows, ambient occlusion,
340 // eye dome lighting) and finally output to the given surface
341 // - there may be also two more passes when 3D axis is shown - see Qgs3DAxis
342
343 mRootEntity = root;
344 mMainCamera = mainCamera;
345
346 mRubberBandsLayer = new Qt3DRender::QLayer;
347 mRubberBandsLayer->setObjectName( "mRubberBandsLayer" );
348 mRubberBandsLayer->setRecursive( true );
349
350 mRenderSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector;
351
352 QObject *surfaceObj = dynamic_cast<QObject *>( surface );
353 Q_ASSERT( surfaceObj );
354
355 mRenderSurfaceSelector->setSurface( surfaceObj );
356 mRenderSurfaceSelector->setExternalRenderTargetSize( mSize );
357
358 mMainViewPort = new Qt3DRender::QViewport( mRenderSurfaceSelector );
359 mMainViewPort->setNormalizedRect( QRectF( 0.0f, 0.0f, 1.0f, 1.0f ) );
360
361 mGlobalParamsStorage = new Qt3DRender::QRenderPassFilter( mMainViewPort );
362 mGlobalParamsStorage->setObjectName( "GlobalParametersStore" );
363
364 // shadow rendering pass -- must be constructed BEFORE the forward render pass,
365 // to ensure it always has the correct depth available.
366 constructShadowRenderPass();
367
368 // Forward render
369 constructForwardRenderPass();
370
371 // Highlighted items pass
372 constructHighlightsPass();
373
374 // rubber bands (they should be always on top)
375 Qt3DRender::QFrameGraphNode *rubberBandsPass = constructRubberBandsPass();
376 rubberBandsPass->setObjectName( "rubberBandsPass" );
377 rubberBandsPass->setParent( mGlobalParamsStorage );
378
379 mMsaaBlitNode = new Qt3DRender::QBlitFramebuffer( mGlobalParamsStorage );
380 mMsaaBlitNode->setObjectName( "MsaaBlitFramebuffer" );
381 mMsaaBlitNode->setEnabled( false );
382
383 mMsaaDepthBlitNode = new Qt3DRender::QBlitFramebuffer( mGlobalParamsStorage );
384 mMsaaDepthBlitNode->setObjectName( "MsaaDepthBlitFramebuffer" );
385 mMsaaDepthBlitNode->setEnabled( false );
386
387 // depth buffer processing
388 constructDepthRenderPass();
389
390 // Ambient occlusion factor render pass
391 constructAmbientOcclusionRenderPass();
392
393 constructBloomRenderPass();
394
395 // post process
396 Qt3DRender::QFrameGraphNode *postprocessingPass = constructPostprocessingPass();
397 postprocessingPass->setParent( mGlobalParamsStorage );
398 postprocessingPass->setObjectName( "PostProcessingPass" );
399
400#ifdef HAVE_TRACY
401 constructThumbnailCapturePass();
402#endif
403
404 mRubberBandsRootEntity = new Qt3DCore::QEntity( mRootEntity );
405 mRubberBandsRootEntity->setObjectName( "mRubberBandsRootEntity" );
406 mRubberBandsRootEntity->addComponent( mRubberBandsLayer );
407}
408
409void QgsFrameGraph::unregisterRenderView( const QString &name )
410{
411 if ( mRenderViewMap.find( name ) != mRenderViewMap.end() )
412 {
413 mRenderViewMap[name]->topGraphNode()->setParent( ( QNode * ) nullptr );
414 mRenderViewMap.erase( name );
415 }
416}
417
418bool QgsFrameGraph::registerRenderView( std::unique_ptr<QgsAbstractRenderView> renderView, const QString &name, Qt3DRender::QFrameGraphNode *topNode )
419{
420 bool out;
421 if ( mRenderViewMap.find( name ) == mRenderViewMap.end() )
422 {
423 mRenderViewMap[name] = std::move( renderView );
424 mRenderViewMap[name]->topGraphNode()->setParent( topNode ? topNode : mGlobalParamsStorage );
425 mRenderViewMap[name]->updateWindowResize( mSize.width(), mSize.height() );
426 out = true;
427 }
428 else
429 out = false;
430
431 return out;
432}
433
434void QgsFrameGraph::setRenderViewEnabled( const QString &name, bool enable )
435{
436 if ( mRenderViewMap[name] )
437 {
438 mRenderViewMap[name]->setEnabled( enable );
439 }
440}
441
443{
444 if ( mRenderViewMap.find( name ) != mRenderViewMap.end() )
445 {
446 return mRenderViewMap[name].get();
447 }
448 return nullptr;
449}
450
451bool QgsFrameGraph::isRenderViewEnabled( const QString &name )
452{
453 return mRenderViewMap[name] != nullptr && mRenderViewMap[name]->isEnabled();
454}
455
457{
459
460 aoRenderView.setRadius( settings.radius() );
461 aoRenderView.setIntensity( settings.intensity() );
462 aoRenderView.setThreshold( settings.threshold() );
463 aoRenderView.setEnabled( settings.isEnabled() );
464
465 mPostprocessingEntity->setAmbientOcclusionEnabled( settings.isEnabled() );
466}
467
469{
470 mPostprocessingEntity->setEyeDomeLightingEnabled( settings.eyeDomeLightingEnabled() );
471 mPostprocessingEntity->setEyeDomeLightingStrength( settings.eyeDomeLightingStrength() );
472 mPostprocessingEntity->setEyeDomeLightingDistance( settings.eyeDomeLightingDistance() );
473}
474
476{
478
479 renderView.setEnabled( settings.isEnabled() );
480 mPostprocessingEntity->setBloomEnabled( settings.isEnabled() );
481 mPostprocessingEntity->setBloomFactor( static_cast< float >( settings.intensity() ) );
482 renderView.setFilterRadius( static_cast< float >( settings.radius() ) );
483}
484
486{
487 mPostprocessingEntity->updateColorGradingSettings( settings );
488}
489
491{
492 const QgsShadowSettings shadowSettings = mapSettings.shadowSettings();
493 const QList<QgsLightSource *> lightSources = mapSettings.lightSources();
494 if ( shadowSettings.renderShadows() )
495 {
496 const QString lightSourceId = shadowSettings.lightSource();
497 QgsLightSource *light = nullptr;
498 int globalLightIndex = 0;
499 for ( int i = 0; !light && i < lightSources.size(); i++ )
500 {
501 if ( lightSources[i]->id() == lightSourceId )
502 {
503 light = lightSources[i];
504 globalLightIndex = i;
505 }
506 }
507
508 if ( light )
509 {
510 QgsVector3D lightDirection;
511 if ( auto directionalLight = dynamic_cast< QgsDirectionalLightSettings * >( light ) )
512 {
513 lightDirection = directionalLight->direction();
514 }
515 else if ( auto sunLight = dynamic_cast< QgsSunLightSettings * >( light ) )
516 {
517 lightDirection = sunLight->direction( mapSettings );
518 }
519
520 const int size = shadowSettings.qualityToMapResolution( shadowSettings.shadowQuality() );
521 shadowRenderView().setMapSize( size, size );
523 mPostprocessingEntity->setShadowRenderingEnabled( true );
524 mPostprocessingEntity->setShadowMapResolution( size );
525 mPostprocessingEntity->setShadowLightIndex( globalLightIndex );
526 mPostprocessingEntity->setShadowBias( static_cast<float>( shadowSettings.shadowBias() ) );
527 mPostprocessingEntity->updateShadowSettings( lightDirection, static_cast<float>( shadowSettings.maximumShadowRenderingDistance() ) );
528 mPostprocessingEntity->setShowCascadingShadowSplits( shadowSettings.showCascadeSplits() );
529 }
530 }
531 else
532 {
533 shadowRenderView().setEnabled( false );
534 mPostprocessingEntity->setShadowRenderingEnabled( false );
535 }
536}
537
539{
540 QgsOverlayTextureRenderView *debugRenderView = dynamic_cast<QgsOverlayTextureRenderView *>( mRenderViewMap[OVERLAY_RENDERVIEW].get() );
541 if ( !debugRenderView )
542 return;
543
544 if ( !mDepthTextureDebugging && settings.debugDepthMapEnabled() )
545 {
546 Qt3DRender::QTexture2D *forwardDepthTexture = forwardRenderView().depthTexture();
547 mDepthTextureDebugging = new QgsOverlayTextureEntity( forwardDepthTexture, debugRenderView->overlayLayer(), this );
548 }
549
550 debugRenderView->setEnabled( settings.debugDepthMapEnabled() || settings.is2DMapOverlayEnabled() );
551
552 if ( mDepthTextureDebugging )
553 {
554 mDepthTextureDebugging->setEnabled( settings.debugDepthMapEnabled() );
555 if ( settings.debugDepthMapEnabled() )
556 mDepthTextureDebugging->setPosition( settings.debugDepthMapCorner(), settings.debugDepthMapSize() );
557 else
558 {
559 delete mDepthTextureDebugging;
560 mDepthTextureDebugging = nullptr;
561 }
562 }
563}
564
566{
567 QObject *top = mRenderSurfaceSelector;
568 while ( top->parent() && dynamic_cast<Qt3DRender::QFrameGraphNode *>( top->parent() ) )
569 top = top->parent();
570
572 context.lowestId = mMainCamera->id().id();
573 QStringList strList = QgsFrameGraphUtils::dumpFrameGraph( dynamic_cast<Qt3DRender::QFrameGraphNode *>( top ), context );
574
575 return strList.join( "\n" ) + QString( "\n" );
576}
577
579{
580 QStringList strList = QgsFrameGraphUtils::dumpSceneGraph( mRootEntity, QgsFrameGraphUtils::FgDumpContext() );
581 return strList.join( "\n" ) + QString( "\n" );
582}
583
584void QgsFrameGraph::setClearColor( const QColor &clearColor )
585{
586 forwardRenderView().setClearColor( clearColor );
587}
588
593
595{
596 mSize = s;
597 for ( auto it = mRenderViewMap.begin(); it != mRenderViewMap.end(); ++it )
598 {
599 QgsAbstractRenderView *rv = it->second.get();
600 rv->updateWindowResize( mSize.width(), mSize.height() );
601 }
602
603 mRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
604 mRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
605 mRenderSurfaceSelector->setExternalRenderTargetSize( mSize );
606
607 mMsaaBlitNode->setSourceRect( QRect( 0, 0, mSize.width(), mSize.height() ) );
608 mMsaaBlitNode->setDestinationRect( QRect( 0, 0, mSize.width(), mSize.height() ) );
609 mMsaaDepthBlitNode->setSourceRect( QRect( 0, 0, mSize.width(), mSize.height() ) );
610 mMsaaDepthBlitNode->setDestinationRect( QRect( 0, 0, mSize.width(), mSize.height() ) );
611
612 if ( mThumbnailTexture )
613 updateThumbnailTextureSize();
614}
615
616Qt3DRender::QRenderCapture *QgsFrameGraph::renderCapture()
617{
618 return mRenderCapture;
619}
620
622{
623 if ( enabled == mRenderCaptureEnabled )
624 return;
625 mRenderCaptureEnabled = enabled;
626 mRenderCaptureTargetSelector->setEnabled( mRenderCaptureEnabled );
627}
628
633
635{
636 mMsaaEnabled = enabled;
637
638 if ( !enabled && mMsaaBlitConfigured )
639 {
640 mMsaaBlitNode->setSource( nullptr );
641 mMsaaBlitNode->setDestination( nullptr );
642 mMsaaDepthBlitNode->setSource( nullptr );
643 mMsaaDepthBlitNode->setDestination( nullptr );
644 mMsaaBlitConfigured = false;
645 }
646
648
649 if ( enabled && !mMsaaBlitConfigured )
650 {
651 mMsaaBlitConfigured = true;
652 mMsaaBlitNode->setSource( forwardRenderView().msaaRenderTarget() );
653 mMsaaBlitNode->setDestination( forwardRenderView().regularRenderTarget() );
654 mMsaaBlitNode->setSourceRect( QRect( 0, 0, mSize.width(), mSize.height() ) );
655 mMsaaBlitNode->setDestinationRect( QRect( 0, 0, mSize.width(), mSize.height() ) );
656 mMsaaBlitNode->setSourceAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
657 mMsaaBlitNode->setDestinationAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
658 mMsaaBlitNode->setInterpolationMethod( Qt3DRender::QBlitFramebuffer::Nearest );
659
660 mMsaaDepthBlitNode->setSource( forwardRenderView().msaaRenderTarget() );
661 mMsaaDepthBlitNode->setDestination( forwardRenderView().regularRenderTarget() );
662 mMsaaDepthBlitNode->setSourceRect( QRect( 0, 0, mSize.width(), mSize.height() ) );
663 mMsaaDepthBlitNode->setDestinationRect( QRect( 0, 0, mSize.width(), mSize.height() ) );
664 mMsaaDepthBlitNode->setSourceAttachmentPoint( Qt3DRender::QRenderTargetOutput::DepthStencil );
665 mMsaaDepthBlitNode->setDestinationAttachmentPoint( Qt3DRender::QRenderTargetOutput::DepthStencil );
666 mMsaaDepthBlitNode->setInterpolationMethod( Qt3DRender::QBlitFramebuffer::Nearest );
667 }
668
669 Qt3DRender::QRenderTarget *target = enabled ? forwardRenderView().msaaRenderTarget() : forwardRenderView().regularRenderTarget();
671 mRubberBandsRenderTargetSelector->setTarget( target );
672 mMsaaBlitNode->setEnabled( enabled );
673 mMsaaDepthBlitNode->setEnabled( enabled );
674}
675
680
681void QgsFrameGraph::addClipPlanes( int nrClipPlanes )
682{
683 forwardRenderView().addClipPlanes( nrClipPlanes );
684}
685
687{
689 return *( dynamic_cast<QgsForwardRenderView *>( rv ) );
690}
691
693{
695 return *( dynamic_cast<QgsShadowRenderView *>( rv ) );
696}
697
699{
700 QgsAbstractRenderView *rv = mRenderViewMap[QgsFrameGraph::DEPTH_RENDERVIEW].get();
701 return *( dynamic_cast<QgsDepthRenderView *>( rv ) );
702}
703
709
711{
712 QgsAbstractRenderView *rv = mRenderViewMap[QgsFrameGraph::BLOOM_RENDERVIEW].get();
713 return *( dynamic_cast<QgsBloomRenderView *>( rv ) );
714}
715
721
Definition of the world.
Qt::Corner debugDepthMapCorner() const
Returns the corner where the shadow map preview is displayed.
bool debugDepthMapEnabled() const
Returns whether the shadow map debugging is enabled.
double eyeDomeLightingStrength() const
Returns the eye dome lighting strength value.
QgsShadowSettings shadowSettings() const
Returns the current configuration of shadows.
QList< QgsLightSource * > lightSources() const
Returns list of directional light sources defined in the scene.
double debugDepthMapSize() const
Returns the size of the shadow map preview.
bool is2DMapOverlayEnabled() const
Returns whether 2D map overlay is enabled.
int eyeDomeLightingDistance() const
Returns the eye dome lighting distance value (contributes to the contrast of the image).
bool eyeDomeLightingEnabled() const
Returns whether eye dome lighting is used.
Base class for 3D render view.
virtual void setEnabled(bool enable)
Enable or disable via enable the render view sub tree.
virtual bool isEnabled() const
Returns true if render view is enabled.
virtual void updateWindowResize(int width, int height)
Called when 3D window is resized.
Container class that holds different objects related to ambient occlusion rendering.
void setRadius(float radius)
Delegates to QgsAmbientOcclusionRenderEntity::setRadius.
void setEnabled(bool enable) override
Enable or disable via enable the render view sub tree.
void setIntensity(float intensity)
Delegates to QgsAmbientOcclusionRenderEntity::setIntensity.
void setThreshold(float threshold)
Delegates to QgsAmbientOcclusionRenderEntity::setThreshold.
Contains the configuration of ambient occlusion rendering.
float radius() const
Returns the radius parameter of the ambient occlusion effect.
bool isEnabled() const
Returns whether ambient occlusion effect is enabled.
float intensity() const
Returns the shading factor of the ambient occlusion effect.
float threshold() const
Returns at what amount of occlusion the effect will kick in.
Container class that holds different objects related to bloom rendering.
Contains the configuration of the lighting "bloom" effect.
double intensity() const
Returns the intensity of the bloom effect.
double radius() const
Returns the filter radius for the bloom.
bool isEnabled() const
Returns whether the bloom effect is enabled.
Contains the configuration of the scene's color grading settings, such as exposure and tone mapping.
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).
Qt3DRender::QTexture2D * colorTexture() const
Returns forward color texture.
void setDebugOverlayEnabled(bool enabled)
Sets whether debug overlay is enabled.
void setMsaaEnabled(bool enabled)
Sets whether multisample anti-aliasing (MSAA) 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.
Qt3DRender::QRenderTarget * msaaRenderTarget() const
Returns the multisampled render target used as blit source when MSAA is enabled.
Qt3DRender::QRenderTarget * regularRenderTarget() const
Returns the regular (single-sample) render target used as blit destination and postprocessing input.
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...
void addGlobalParameters(const QList< Qt3DRender::QParameter * > &parameters)
Adds additional global parameters to the graph.
void setMsaaEnabled(bool enabled)
Sets whether multisample anti-aliasing (MSAA) is enabled.
void updateAmbientOcclusionSettings(const QgsAmbientOcclusionSettings &settings)
Updates settings for ambient occlusion.
void updateEyeDomeSettings(const Qgs3DMapSettings &settings)
Updates settings for eye dome lighting.
void updateBloomSettings(const QgsBloomSettings &settings)
Updates settings for the bloom lighting effect.
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 addClipPlanes(int nrClipPlanes)
Setups nrClipPlanes clip planes in the forward pass to enable OpenGL clipping.
void updateColorGradingSettings(const QgsColorGradingSettings &settings)
Updates settings for color grading.
void unregisterRenderView(const QString &name)
Unregisters the render view named name, if any.
bool registerRenderView(std::unique_ptr< QgsAbstractRenderView > renderView, const QString &name, Qt3DRender::QFrameGraphNode *topNode=nullptr)
Registers a new the render view renderView with name name.
QString dumpFrameGraph() const
Dumps frame graph as string.
void setRenderCaptureEnabled(bool enabled)
Sets whether it will be possible to render to an image.
QgsAmbientOcclusionRenderView & ambientOcclusionRenderView()
Returns ambient occlusion renderview.
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.
static const QString AMBIENT_OCCLUSION_RENDERVIEW
Ambient occlusion render view name.
QgsDepthRenderView & depthRenderView()
Returns depth renderview.
void setClearColor(const QColor &clearColor)
Sets the clear color of the scene (background color).
static const QString FORWARD_RENDERVIEW
void setFrustumCullingEnabled(bool enabled)
Sets whether frustum culling is enabled.
void updateShadowSettings(const Qgs3DMapSettings &mapSettings)
Updates shadow bias, light and texture size according to shadowSettings and lightSources.
static const QString SHADOW_RENDERVIEW
void setDebugOverlayEnabled(bool enabled)
Sets whether debug overlay is enabled.
static const QString HIGHLIGHTS_RENDERVIEW
QgsHighlightsRenderView & highlightsRenderView()
Returns the highlights renderview, used for rendering highlight overlays of identified features.
static const QString OVERLAY_RENDERVIEW
void updateDebugDepthMapSettings(const Qgs3DMapSettings &settings)
Updates settings for depth debug map.
static const QString AXIS3D_RENDERVIEW
QgsForwardRenderView & forwardRenderView()
Returns forward renderview.
QgsOverlayTextureRenderView & overlayTextureRenderView()
Returns overlay texture renderview.
QString dumpSceneGraph() const
Dumps scene graph as string.
QgsShadowRenderView & shadowRenderView()
Returns shadow renderview.
void setSize(QSize s)
Sets the size of the buffers used for rendering.
static const QString BLOOM_RENDERVIEW
QgsBloomRenderView & bloomRenderView()
Returns the bloom render view.
static const QString DEPTH_RENDERVIEW
Qt3DRender::QCamera * mainCamera()
Returns the main camera.
QgsFrameGraph(QSurface *surface, QSize s, Qt3DRender::QCamera *mainCamera, Qt3DCore::QEntity *root)
Constructor.
Qt3DRender::QRenderCapture * renderCapture()
Returns the render capture object used to take an image of the scene.
Container class that holds different objects related to highlighting identified features.
void setRenderTarget(Qt3DRender::QRenderTarget *target)
Switches the render target (called when toggling MSAA on/off).
Base class for light sources in 3d scenes.
An entity responsible for rendering an overlay texture in 3D view.
Simple render view to preview overlay textures in 3D view.
Qt3DRender::QLayer * overlayLayer() const
Returns layer in which entities must be added in the in order to be processed by this renderview.
Container class that holds different objects related to shadow rendering.
void setMapSize(int width, int height)
Update shadow depth texture size.
void setEnabled(bool enable) override
Enable or disable via enable the renderview sub tree.
Contains configuration for rendering shadows.
bool renderShadows() const
Returns whether shadow rendering is enabled.
static int qualityToMapResolution(Qgis::ShadowQuality quality)
Returns the shadow map resolution corresponding to the specified shadow quality.
double maximumShadowRenderingDistance() const
Returns the maximum shadow rendering distance accounted for when rendering shadows Objects further aw...
QString lightSource() const
Returns the ID of the light source casting shadows.
double shadowBias() const
Returns the shadow bias used to correct the numerical imprecision of shadows (for the depth test) Thi...
Qgis::ShadowQuality shadowQuality() const
Returns the quality of the shadow map texture used to generate the shadows.
bool showCascadeSplits() const
Returns true if the cascading shadow splits should be tinted in the view.
Definition of a sun light in a 3D map scene.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
Definition qgsvector3d.h:33