QGIS API Documentation 3.43.0-Master (ebb4087afc0)
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#include "moc_qgsframegraph.cpp"
20#include "qgspreviewquad.h"
21#include "qgs3dutils.h"
24
25#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
26#include <Qt3DRender/QAttribute>
27#include <Qt3DRender/QBuffer>
28#include <Qt3DRender/QGeometry>
29
30typedef Qt3DRender::QAttribute Qt3DQAttribute;
31typedef Qt3DRender::QBuffer Qt3DQBuffer;
32typedef Qt3DRender::QGeometry Qt3DQGeometry;
33#else
34#include <Qt3DCore/QAttribute>
35#include <Qt3DCore/QBuffer>
36#include <Qt3DCore/QGeometry>
37
38typedef Qt3DCore::QAttribute Qt3DQAttribute;
39typedef Qt3DCore::QBuffer Qt3DQBuffer;
40typedef Qt3DCore::QGeometry Qt3DQGeometry;
41#endif
42
43#include <Qt3DRender/QGeometryRenderer>
44#include <Qt3DRender/QTechnique>
45#include <Qt3DRender/QGraphicsApiFilter>
46#include <Qt3DRender/QBlendEquation>
47#include <Qt3DRender/QColorMask>
48#include <Qt3DRender/QSortPolicy>
49#include <Qt3DRender/QNoDepthMask>
50#include <Qt3DRender/QBlendEquationArguments>
51#include <Qt3DRender/QAbstractTexture>
52#include "qgsfgutils.h"
53#include <Qt3DRender/QNoDraw>
54#include <Qt3DRender/QClipPlane>
55
56Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructForwardRenderPass()
57{
58 // This is where rendering of the 3D scene actually happens.
59 // We define two forward passes: one for solid objects, followed by one for transparent objects.
60 //
61 // |
62 // +-----------------+
63 // | QCameraSelector | (using the main camera)
64 // +-----------------+
65 // |
66 // +-----------------+
67 // | QLayerFilter | (using mForwardRenderLayer)
68 // +-----------------+
69 // |
70 // +-----------------+
71 // | QRenderStateSet | define clip planes
72 // +-----------------+
73 // |
74 // +-----------------------+
75 // | QRenderTargetSelector | (write mForwardColorTexture + mForwardDepthTexture)
76 // +-----------------------+
77 // |
78 // +------------------------+---------------------+
79 // | |
80 // +-----------------+ discard +-----------------+ accept
81 // | QLayerFilter | transparent | QLayerFilter | transparent
82 // +-----------------+ objects +-----------------+ objects
83 // | |
84 // +-----------------+ use depth test +-----------------+ sort entities
85 // | QRenderStateSet | cull back faces | QSortPolicy | back to front
86 // +-----------------+ +-----------------+
87 // | |
88 // +-----------------+ +--------------------+--------------------+
89 // | QFrustumCulling | | |
90 // +-----------------+ +-----------------+ use depth tests +-----------------+ use depth tests
91 // | | QRenderStateSet | don't write depths | QRenderStateSet | write depths
92 // | +-----------------+ write colors +-----------------+ don't write colors
93 // +-----------------+ use alpha blending don't use alpha blending
94 // | QClearBuffers | color and depth no culling no culling
95 // +-----------------+
96
97 mMainCameraSelector = new Qt3DRender::QCameraSelector;
98 mMainCameraSelector->setObjectName( "Forward render pass CameraSelector" );
99 mMainCameraSelector->setCamera( mMainCamera );
100
101 mForwardRenderLayerFilter = new Qt3DRender::QLayerFilter( mMainCameraSelector );
102 mForwardRenderLayerFilter->addLayer( mForwardRenderLayer );
103
104 mClipRenderStateSet = new Qt3DRender::QRenderStateSet( mForwardRenderLayerFilter );
105 mClipRenderStateSet->setObjectName( "Forward render pass Clip Plane RenderStateSet" );
106
107 mForwardColorTexture = new Qt3DRender::QTexture2D;
108 mForwardColorTexture->setWidth( mSize.width() );
109 mForwardColorTexture->setHeight( mSize.height() );
110 mForwardColorTexture->setFormat( Qt3DRender::QAbstractTexture::RGB8_UNorm );
111 mForwardColorTexture->setGenerateMipMaps( false );
112 mForwardColorTexture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
113 mForwardColorTexture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
114 mForwardColorTexture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
115 mForwardColorTexture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
116
117 mForwardDepthTexture = new Qt3DRender::QTexture2D;
118 mForwardDepthTexture->setWidth( mSize.width() );
119 mForwardDepthTexture->setHeight( mSize.height() );
120 mForwardDepthTexture->setFormat( Qt3DRender::QTexture2D::TextureFormat::DepthFormat );
121 mForwardDepthTexture->setGenerateMipMaps( false );
122 mForwardDepthTexture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
123 mForwardDepthTexture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
124 mForwardDepthTexture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
125 mForwardDepthTexture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
126
127 Qt3DRender::QRenderTarget *forwardRenderTarget = new Qt3DRender::QRenderTarget;
128 Qt3DRender::QRenderTargetOutput *forwardRenderTargetDepthOutput = new Qt3DRender::QRenderTargetOutput;
129 forwardRenderTargetDepthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
130 forwardRenderTargetDepthOutput->setTexture( mForwardDepthTexture );
131 forwardRenderTarget->addOutput( forwardRenderTargetDepthOutput );
132 Qt3DRender::QRenderTargetOutput *forwardRenderTargetColorOutput = new Qt3DRender::QRenderTargetOutput;
133 forwardRenderTargetColorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
134 forwardRenderTargetColorOutput->setTexture( mForwardColorTexture );
135 forwardRenderTarget->addOutput( forwardRenderTargetColorOutput );
136
137 mForwardRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mClipRenderStateSet );
138 mForwardRenderTargetSelector->setTarget( forwardRenderTarget );
139
140 // first branch: opaque layer filter
141 Qt3DRender::QLayerFilter *opaqueObjectsFilter = new Qt3DRender::QLayerFilter( mForwardRenderTargetSelector );
142 opaqueObjectsFilter->addLayer( mTransparentObjectsPassLayer );
143 opaqueObjectsFilter->setFilterMode( Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers );
144
145 Qt3DRender::QRenderStateSet *forwardedRenderStateSet = new Qt3DRender::QRenderStateSet( opaqueObjectsFilter );
146
147 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
148 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
149 forwardedRenderStateSet->addRenderState( depthTest );
150
151 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
152 cullFace->setMode( Qt3DRender::QCullFace::CullingMode::Back );
153 forwardedRenderStateSet->addRenderState( cullFace );
154
155 mFrustumCulling = new Qt3DRender::QFrustumCulling( forwardedRenderStateSet );
156
157 mForwardClearBuffers = new Qt3DRender::QClearBuffers( mFrustumCulling );
158 mForwardClearBuffers->setClearColor( QColor::fromRgbF( 0.0, 0.0, 1.0, 1.0 ) );
159 mForwardClearBuffers->setBuffers( Qt3DRender::QClearBuffers::ColorDepthBuffer );
160 mForwardClearBuffers->setClearDepthValue( 1.0f );
161
162 // second branch: transparent layer filter - color
163 Qt3DRender::QLayerFilter *transparentObjectsLayerFilter = new Qt3DRender::QLayerFilter( mForwardRenderTargetSelector );
164 transparentObjectsLayerFilter->addLayer( mTransparentObjectsPassLayer );
165 transparentObjectsLayerFilter->setFilterMode( Qt3DRender::QLayerFilter::AcceptAnyMatchingLayers );
166
167 Qt3DRender::QSortPolicy *sortPolicy = new Qt3DRender::QSortPolicy( transparentObjectsLayerFilter );
168 QVector<Qt3DRender::QSortPolicy::SortType> sortTypes;
169 sortTypes.push_back( Qt3DRender::QSortPolicy::BackToFront );
170 sortPolicy->setSortTypes( sortTypes );
171
172 Qt3DRender::QRenderStateSet *transparentObjectsRenderStateSetColor = new Qt3DRender::QRenderStateSet( sortPolicy );
173 {
174 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
175 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
176 transparentObjectsRenderStateSetColor->addRenderState( depthTest );
177
178 Qt3DRender::QNoDepthMask *noDepthMask = new Qt3DRender::QNoDepthMask;
179 transparentObjectsRenderStateSetColor->addRenderState( noDepthMask );
180
181 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
182 cullFace->setMode( Qt3DRender::QCullFace::CullingMode::NoCulling );
183 transparentObjectsRenderStateSetColor->addRenderState( cullFace );
184
185 Qt3DRender::QBlendEquation *blendEquation = new Qt3DRender::QBlendEquation;
186 blendEquation->setBlendFunction( Qt3DRender::QBlendEquation::Add );
187 transparentObjectsRenderStateSetColor->addRenderState( blendEquation );
188
189 Qt3DRender::QBlendEquationArguments *blendEquationArgs = new Qt3DRender::QBlendEquationArguments;
190 blendEquationArgs->setSourceRgb( Qt3DRender::QBlendEquationArguments::Blending::SourceAlpha );
191 blendEquationArgs->setDestinationRgb( Qt3DRender::QBlendEquationArguments::Blending::OneMinusSourceAlpha );
192 transparentObjectsRenderStateSetColor->addRenderState( blendEquationArgs );
193 }
194
195 // third branch: transparent layer filter - depth
196 Qt3DRender::QRenderStateSet *transparentObjectsRenderStateSetDepth = new Qt3DRender::QRenderStateSet( sortPolicy );
197 {
198 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
199 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
200 transparentObjectsRenderStateSetDepth->addRenderState( depthTest );
201
202 Qt3DRender::QColorMask *noColorMask = new Qt3DRender::QColorMask;
203 noColorMask->setAlphaMasked( false );
204 noColorMask->setRedMasked( false );
205 noColorMask->setGreenMasked( false );
206 noColorMask->setBlueMasked( false );
207 transparentObjectsRenderStateSetDepth->addRenderState( noColorMask );
208
209 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
210 cullFace->setMode( Qt3DRender::QCullFace::CullingMode::NoCulling );
211 transparentObjectsRenderStateSetDepth->addRenderState( cullFace );
212 }
213
214 mDebugOverlay = new Qt3DRender::QDebugOverlay( mForwardClearBuffers );
215 mDebugOverlay->setEnabled( false );
216
217 // cppcheck wrongly believes transparentObjectsRenderStateSetColor and transparentObjectsRenderStateSetDepth will leak
218 // cppcheck-suppress memleak
219 return mMainCameraSelector;
220}
221
222Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructShadowRenderPass()
223{
224 mLightCameraSelectorShadowPass = new Qt3DRender::QCameraSelector;
225 mLightCameraSelectorShadowPass->setObjectName( "Shadow render pass CameraSelector" );
226 mLightCameraSelectorShadowPass->setCamera( mLightCamera );
227
228 mShadowSceneEntitiesFilter = new Qt3DRender::QLayerFilter( mLightCameraSelectorShadowPass );
229 mShadowSceneEntitiesFilter->addLayer( mCastShadowsLayer );
230
231 mShadowMapTexture = new Qt3DRender::QTexture2D;
232 mShadowMapTexture->setWidth( mShadowMapResolution );
233 mShadowMapTexture->setHeight( mShadowMapResolution );
234 mShadowMapTexture->setFormat( Qt3DRender::QTexture2D::TextureFormat::DepthFormat );
235 mShadowMapTexture->setGenerateMipMaps( false );
236 mShadowMapTexture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
237 mShadowMapTexture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
238 mShadowMapTexture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
239 mShadowMapTexture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
240
241 Qt3DRender::QRenderTarget *shadowRenderTarget = new Qt3DRender::QRenderTarget;
242 Qt3DRender::QRenderTargetOutput *shadowRenderTargetOutput = new Qt3DRender::QRenderTargetOutput;
243 shadowRenderTargetOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
244 shadowRenderTargetOutput->setTexture( mShadowMapTexture );
245 shadowRenderTarget->addOutput( shadowRenderTargetOutput );
246
247 mShadowRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mShadowSceneEntitiesFilter );
248 mShadowRenderTargetSelector->setTarget( shadowRenderTarget );
249
250 mShadowClearBuffers = new Qt3DRender::QClearBuffers( mShadowRenderTargetSelector );
251 mShadowClearBuffers->setBuffers( Qt3DRender::QClearBuffers::BufferType::ColorDepthBuffer );
252 mShadowClearBuffers->setClearColor( QColor::fromRgbF( 0.0f, 1.0f, 0.0f ) );
253
254 mShadowRenderStateSet = new Qt3DRender::QRenderStateSet( mShadowClearBuffers );
255
256 Qt3DRender::QDepthTest *shadowDepthTest = new Qt3DRender::QDepthTest;
257 shadowDepthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
258 mShadowRenderStateSet->addRenderState( shadowDepthTest );
259
260 Qt3DRender::QCullFace *shadowCullFace = new Qt3DRender::QCullFace;
261 shadowCullFace->setMode( Qt3DRender::QCullFace::CullingMode::Front );
262 mShadowRenderStateSet->addRenderState( shadowCullFace );
263
264 Qt3DRender::QPolygonOffset *polygonOffset = new Qt3DRender::QPolygonOffset;
265 polygonOffset->setDepthSteps( 4.0 );
266 polygonOffset->setScaleFactor( 1.1 );
267 mShadowRenderStateSet->addRenderState( polygonOffset );
268
269 return mLightCameraSelectorShadowPass;
270}
271
272Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructSubPostPassForTexturesPreview()
273{
274 Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter;
275 layerFilter->setObjectName( "Sub pass TexturesPreview" );
276 layerFilter->addLayer( mPreviewLayer );
277
278 Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet( layerFilter );
279 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
280 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
281 renderStateSet->addRenderState( depthTest );
282 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
283 cullFace->setMode( Qt3DRender::QCullFace::NoCulling );
284 renderStateSet->addRenderState( cullFace );
285
286 return layerFilter;
287}
288
289Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructSubPostPassForProcessing()
290{
291 Qt3DRender::QCameraSelector *cameraSelector = new Qt3DRender::QCameraSelector;
292 cameraSelector->setObjectName( "Sub pass Postprocessing" );
293 cameraSelector->setCamera( mLightCamera );
294
295 Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter( cameraSelector );
296
297 // could be the first of this branch
298 new Qt3DRender::QClearBuffers( layerFilter );
299
300 Qt3DRender::QLayer *postProcessingLayer = new Qt3DRender::QLayer();
301 mPostprocessingEntity = new QgsPostprocessingEntity( this, postProcessingLayer, mRootEntity );
302 layerFilter->addLayer( postProcessingLayer );
303 mPostprocessingEntity->setObjectName( "PostProcessingPassEntity" );
304
305 return cameraSelector;
306}
307
308Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructSubPostPassForRenderCapture()
309{
310 Qt3DRender::QFrameGraphNode *top = new Qt3DRender::QNoDraw;
311 top->setObjectName( "Sub pass RenderCapture" );
312
313 mRenderCapture = new Qt3DRender::QRenderCapture( top );
314
315 return top;
316}
317
318Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructPostprocessingPass()
319{
320 mRenderCaptureTargetSelector = new Qt3DRender::QRenderTargetSelector;
321 mRenderCaptureTargetSelector->setObjectName( "Postprocessing render pass" );
322 mRenderCaptureTargetSelector->setEnabled( mRenderCaptureEnabled );
323
324 Qt3DRender::QRenderTarget *renderTarget = new Qt3DRender::QRenderTarget( mRenderCaptureTargetSelector );
325
326 // The lifetime of the objects created here is managed
327 // automatically, as they become children of this object.
328
329 // Create a render target output for rendering color.
330 Qt3DRender::QRenderTargetOutput *colorOutput = new Qt3DRender::QRenderTargetOutput( renderTarget );
331 colorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
332
333 // Create a texture to render into.
334 mRenderCaptureColorTexture = new Qt3DRender::QTexture2D( colorOutput );
335 mRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
336 mRenderCaptureColorTexture->setFormat( Qt3DRender::QAbstractTexture::RGB8_UNorm );
337 mRenderCaptureColorTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
338 mRenderCaptureColorTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
339 mRenderCaptureColorTexture->setObjectName( "PostProcessingPass::ColorTarget" );
340
341 // Hook the texture up to our output, and the output up to this object.
342 colorOutput->setTexture( mRenderCaptureColorTexture );
343 renderTarget->addOutput( colorOutput );
344
345 Qt3DRender::QRenderTargetOutput *depthOutput = new Qt3DRender::QRenderTargetOutput( renderTarget );
346
347 depthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
348 mRenderCaptureDepthTexture = new Qt3DRender::QTexture2D( depthOutput );
349 mRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
350 mRenderCaptureDepthTexture->setFormat( Qt3DRender::QAbstractTexture::DepthFormat );
351 mRenderCaptureDepthTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
352 mRenderCaptureDepthTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
353 mRenderCaptureDepthTexture->setComparisonFunction( Qt3DRender::QAbstractTexture::CompareLessEqual );
354 mRenderCaptureDepthTexture->setComparisonMode( Qt3DRender::QAbstractTexture::CompareRefToTexture );
355 mRenderCaptureDepthTexture->setObjectName( "PostProcessingPass::DepthTarget" );
356
357 depthOutput->setTexture( mRenderCaptureDepthTexture );
358 renderTarget->addOutput( depthOutput );
359
360 mRenderCaptureTargetSelector->setTarget( renderTarget );
361
362 // sub passes:
363 constructSubPostPassForProcessing()->setParent( mRenderCaptureTargetSelector );
364 constructSubPostPassForTexturesPreview()->setParent( mRenderCaptureTargetSelector );
365 constructSubPostPassForRenderCapture()->setParent( mRenderCaptureTargetSelector );
366
367 return mRenderCaptureTargetSelector;
368}
369
370Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructAmbientOcclusionRenderPass()
371{
372 mAmbientOcclusionRenderCameraSelector = new Qt3DRender::QCameraSelector;
373 mAmbientOcclusionRenderCameraSelector->setObjectName( "AmbientOcclusion render pass CameraSelector" );
374 mAmbientOcclusionRenderCameraSelector->setCamera( mMainCamera );
375
376 mAmbientOcclusionRenderStateSet = new Qt3DRender::QRenderStateSet( mAmbientOcclusionRenderCameraSelector );
377
378 Qt3DRender::QDepthTest *depthRenderDepthTest = new Qt3DRender::QDepthTest;
379 depthRenderDepthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
380 ;
381 Qt3DRender::QCullFace *depthRenderCullFace = new Qt3DRender::QCullFace;
382 depthRenderCullFace->setMode( Qt3DRender::QCullFace::NoCulling );
383
384 mAmbientOcclusionRenderStateSet->addRenderState( depthRenderDepthTest );
385 mAmbientOcclusionRenderStateSet->addRenderState( depthRenderCullFace );
386
387 mAmbientOcclusionRenderLayerFilter = new Qt3DRender::QLayerFilter( mAmbientOcclusionRenderStateSet );
388
389 mAmbientOcclusionRenderCaptureTargetSelector = new Qt3DRender::QRenderTargetSelector( mAmbientOcclusionRenderLayerFilter );
390 Qt3DRender::QRenderTarget *colorRenderTarget = new Qt3DRender::QRenderTarget( mAmbientOcclusionRenderCaptureTargetSelector );
391
392 // The lifetime of the objects created here is managed
393 // automatically, as they become children of this object.
394
395 // Create a render target output for rendering color.
396 Qt3DRender::QRenderTargetOutput *colorOutput = new Qt3DRender::QRenderTargetOutput( colorRenderTarget );
397 colorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
398
399 // Create a texture to render into.
400 mAmbientOcclusionRenderTexture = new Qt3DRender::QTexture2D( colorOutput );
401 mAmbientOcclusionRenderTexture->setSize( mSize.width(), mSize.height() );
402 mAmbientOcclusionRenderTexture->setFormat( Qt3DRender::QAbstractTexture::R32F );
403 mAmbientOcclusionRenderTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
404 mAmbientOcclusionRenderTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
405
406 // Hook the texture up to our output, and the output up to this object.
407 colorOutput->setTexture( mAmbientOcclusionRenderTexture );
408 colorRenderTarget->addOutput( colorOutput );
409
410 mAmbientOcclusionRenderCaptureTargetSelector->setTarget( colorRenderTarget );
411
412 Qt3DRender::QLayer *ambientOcclusionRenderLayer = new Qt3DRender::QLayer();
413 mAmbientOcclusionRenderEntity = new QgsAmbientOcclusionRenderEntity( mForwardDepthTexture, ambientOcclusionRenderLayer, mMainCamera, mRootEntity );
414 mAmbientOcclusionRenderLayerFilter->addLayer( ambientOcclusionRenderLayer );
415
416 return mAmbientOcclusionRenderCameraSelector;
417}
418
419Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructAmbientOcclusionBlurPass()
420{
421 mAmbientOcclusionBlurCameraSelector = new Qt3DRender::QCameraSelector;
422 mAmbientOcclusionBlurCameraSelector->setObjectName( "AmbientOcclusion blur pass CameraSelector" );
423 mAmbientOcclusionBlurCameraSelector->setCamera( mMainCamera );
424
425 mAmbientOcclusionBlurStateSet = new Qt3DRender::QRenderStateSet( mAmbientOcclusionBlurCameraSelector );
426
427 Qt3DRender::QDepthTest *depthRenderDepthTest = new Qt3DRender::QDepthTest;
428 depthRenderDepthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
429 ;
430 Qt3DRender::QCullFace *depthRenderCullFace = new Qt3DRender::QCullFace;
431 depthRenderCullFace->setMode( Qt3DRender::QCullFace::NoCulling );
432
433 mAmbientOcclusionBlurStateSet->addRenderState( depthRenderDepthTest );
434 mAmbientOcclusionBlurStateSet->addRenderState( depthRenderCullFace );
435
436 mAmbientOcclusionBlurLayerFilter = new Qt3DRender::QLayerFilter( mAmbientOcclusionBlurStateSet );
437
438 mAmbientOcclusionBlurRenderCaptureTargetSelector = new Qt3DRender::QRenderTargetSelector( mAmbientOcclusionBlurLayerFilter );
439 Qt3DRender::QRenderTarget *depthRenderTarget = new Qt3DRender::QRenderTarget( mAmbientOcclusionBlurRenderCaptureTargetSelector );
440
441 // The lifetime of the objects created here is managed
442 // automatically, as they become children of this object.
443
444 // Create a render target output for rendering color.
445 Qt3DRender::QRenderTargetOutput *colorOutput = new Qt3DRender::QRenderTargetOutput( depthRenderTarget );
446 colorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
447
448 // Create a texture to render into.
449 mAmbientOcclusionBlurTexture = new Qt3DRender::QTexture2D( colorOutput );
450 mAmbientOcclusionBlurTexture->setSize( mSize.width(), mSize.height() );
451 mAmbientOcclusionBlurTexture->setFormat( Qt3DRender::QAbstractTexture::R32F );
452 mAmbientOcclusionBlurTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
453 mAmbientOcclusionBlurTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
454
455 // Hook the texture up to our output, and the output up to this object.
456 colorOutput->setTexture( mAmbientOcclusionBlurTexture );
457 depthRenderTarget->addOutput( colorOutput );
458
459 mAmbientOcclusionBlurRenderCaptureTargetSelector->setTarget( depthRenderTarget );
460
461 Qt3DRender::QLayer *ambientOcclusionBlurLayer = new Qt3DRender::QLayer();
462 mAmbientOcclusionBlurEntity = new QgsAmbientOcclusionBlurEntity( mAmbientOcclusionRenderTexture, ambientOcclusionBlurLayer, mRootEntity );
463 mAmbientOcclusionBlurLayerFilter->addLayer( ambientOcclusionBlurLayer );
464
465 return mAmbientOcclusionBlurCameraSelector;
466}
467
468
469Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructRubberBandsPass()
470{
471 mRubberBandsCameraSelector = new Qt3DRender::QCameraSelector;
472 mRubberBandsCameraSelector->setObjectName( "RubberBands Pass CameraSelector" );
473 mRubberBandsCameraSelector->setCamera( mMainCamera );
474
475 mRubberBandsLayerFilter = new Qt3DRender::QLayerFilter( mRubberBandsCameraSelector );
476 mRubberBandsLayerFilter->addLayer( mRubberBandsLayer );
477
478 Qt3DRender::QBlendEquationArguments *blendState = new Qt3DRender::QBlendEquationArguments;
479 blendState->setSourceRgb( Qt3DRender::QBlendEquationArguments::SourceAlpha );
480 blendState->setDestinationRgb( Qt3DRender::QBlendEquationArguments::OneMinusSourceAlpha );
481
482 Qt3DRender::QBlendEquation *blendEquation = new Qt3DRender::QBlendEquation;
483 blendEquation->setBlendFunction( Qt3DRender::QBlendEquation::Add );
484
485 mRubberBandsStateSet = new Qt3DRender::QRenderStateSet( mRubberBandsLayerFilter );
486 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
487 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
488 mRubberBandsStateSet->addRenderState( depthTest );
489 mRubberBandsStateSet->addRenderState( blendState );
490 mRubberBandsStateSet->addRenderState( blendEquation );
491
492 // Here we attach our drawings to the render target also used by forward pass.
493 // This is kind of okay, but as a result, post-processing effects get applied
494 // to rubber bands too. Ideally we would want them on top of everything.
495 mRubberBandsRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mRubberBandsStateSet );
496 mRubberBandsRenderTargetSelector->setTarget( mForwardRenderTargetSelector->target() );
497
498 return mRubberBandsCameraSelector;
499}
500
501
502Qt3DRender::QFrameGraphNode *QgsFrameGraph::constructDepthRenderPass()
503{
504 // depth buffer render to copy pass
505
506 mDepthRenderCameraSelector = new Qt3DRender::QCameraSelector;
507 mDepthRenderCameraSelector->setObjectName( "Depth render view CameraSelector" );
508 mDepthRenderCameraSelector->setCamera( mMainCamera );
509
510 mDepthRenderStateSet = new Qt3DRender::QRenderStateSet( mDepthRenderCameraSelector );
511
512 Qt3DRender::QDepthTest *depthRenderDepthTest = new Qt3DRender::QDepthTest;
513 depthRenderDepthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
514 ;
515 Qt3DRender::QCullFace *depthRenderCullFace = new Qt3DRender::QCullFace;
516 depthRenderCullFace->setMode( Qt3DRender::QCullFace::NoCulling );
517
518 mDepthRenderStateSet->addRenderState( depthRenderDepthTest );
519 mDepthRenderStateSet->addRenderState( depthRenderCullFace );
520
521 mDepthRenderLayerFilter = new Qt3DRender::QLayerFilter( mDepthRenderStateSet );
522 mDepthRenderLayerFilter->addLayer( mDepthRenderPassLayer );
523
524 mDepthRenderCaptureTargetSelector = new Qt3DRender::QRenderTargetSelector( mDepthRenderLayerFilter );
525 Qt3DRender::QRenderTarget *depthRenderTarget = new Qt3DRender::QRenderTarget( mDepthRenderCaptureTargetSelector );
526
527 // The lifetime of the objects created here is managed
528 // automatically, as they become children of this object.
529
530 // Create a render target output for rendering color.
531 Qt3DRender::QRenderTargetOutput *colorOutput = new Qt3DRender::QRenderTargetOutput( depthRenderTarget );
532 colorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
533
534 // Create a texture to render into.
535 mDepthRenderCaptureColorTexture = new Qt3DRender::QTexture2D( colorOutput );
536 mDepthRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
537 mDepthRenderCaptureColorTexture->setFormat( Qt3DRender::QAbstractTexture::RGB8_UNorm );
538 mDepthRenderCaptureColorTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
539 mDepthRenderCaptureColorTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
540
541 // Hook the texture up to our output, and the output up to this object.
542 colorOutput->setTexture( mDepthRenderCaptureColorTexture );
543 depthRenderTarget->addOutput( colorOutput );
544
545 Qt3DRender::QRenderTargetOutput *depthOutput = new Qt3DRender::QRenderTargetOutput( depthRenderTarget );
546
547 depthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
548 mDepthRenderCaptureDepthTexture = new Qt3DRender::QTexture2D( depthOutput );
549 mDepthRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
550 mDepthRenderCaptureDepthTexture->setFormat( Qt3DRender::QAbstractTexture::DepthFormat );
551 mDepthRenderCaptureDepthTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
552 mDepthRenderCaptureDepthTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
553 mDepthRenderCaptureDepthTexture->setComparisonFunction( Qt3DRender::QAbstractTexture::CompareLessEqual );
554 mDepthRenderCaptureDepthTexture->setComparisonMode( Qt3DRender::QAbstractTexture::CompareRefToTexture );
555
556 depthOutput->setTexture( mDepthRenderCaptureDepthTexture );
557 depthRenderTarget->addOutput( depthOutput );
558
559 mDepthRenderCaptureTargetSelector->setTarget( depthRenderTarget );
560
561 // Note: We do not a clear buffers node since we are drawing a quad that will override the buffer's content anyway
562 mDepthRenderCapture = new Qt3DRender::QRenderCapture( mDepthRenderCaptureTargetSelector );
563
564 return mDepthRenderCameraSelector;
565}
566
567Qt3DCore::QEntity *QgsFrameGraph::constructDepthRenderQuad()
568{
569 Qt3DCore::QEntity *quad = new Qt3DCore::QEntity;
570 quad->setObjectName( "depthRenderQuad" );
571
572 Qt3DQGeometry *geom = new Qt3DQGeometry;
573 Qt3DQAttribute *positionAttribute = new Qt3DQAttribute;
574 const QVector<float> vert = { -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
575
576 const QByteArray vertexArr( ( const char * ) vert.constData(), vert.size() * sizeof( float ) );
577 Qt3DQBuffer *vertexBuffer = nullptr;
578 vertexBuffer = new Qt3DQBuffer( this );
579 vertexBuffer->setData( vertexArr );
580
581 positionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
582 positionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
583 positionAttribute->setVertexSize( 3 );
584 positionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
585 positionAttribute->setBuffer( vertexBuffer );
586 positionAttribute->setByteOffset( 0 );
587 positionAttribute->setByteStride( 3 * sizeof( float ) );
588 positionAttribute->setCount( 6 );
589
590 geom->addAttribute( positionAttribute );
591
592 Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
593 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::PrimitiveType::Triangles );
594 renderer->setGeometry( geom );
595
596 quad->addComponent( renderer );
597
598 QMatrix4x4 modelMatrix;
599 modelMatrix.setToIdentity();
600
601 // construct material
602
603 Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
604 Qt3DRender::QParameter *textureParameter = new Qt3DRender::QParameter( "depthTexture", mForwardDepthTexture );
605 Qt3DRender::QParameter *textureTransformParameter = new Qt3DRender::QParameter( "modelMatrix", QVariant::fromValue( modelMatrix ) );
606 material->addParameter( textureParameter );
607 material->addParameter( textureTransformParameter );
608
609 Qt3DRender::QEffect *effect = new Qt3DRender::QEffect;
610
611 Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
612
613 Qt3DRender::QGraphicsApiFilter *graphicsApiFilter = technique->graphicsApiFilter();
614 graphicsApiFilter->setApi( Qt3DRender::QGraphicsApiFilter::Api::OpenGL );
615 graphicsApiFilter->setProfile( Qt3DRender::QGraphicsApiFilter::OpenGLProfile::CoreProfile );
616 graphicsApiFilter->setMajorVersion( 1 );
617 graphicsApiFilter->setMinorVersion( 5 );
618
619 Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass;
620
621 Qt3DRender::QShaderProgram *shader = new Qt3DRender::QShaderProgram;
622 shader->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/depth_render.vert" ) ) );
623 shader->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/depth_render.frag" ) ) );
624 renderPass->setShaderProgram( shader );
625
626 technique->addRenderPass( renderPass );
627
628 effect->addTechnique( technique );
629 material->setEffect( effect );
630
631 quad->addComponent( material );
632
633 return quad;
634}
635
636QgsFrameGraph::QgsFrameGraph( QSurface *surface, QSize s, Qt3DRender::QCamera *mainCamera, Qt3DCore::QEntity *root )
637 : Qt3DCore::QEntity( root )
638 , mSize( s )
639{
640 // general overview of how the frame graph looks:
641 //
642 // +------------------------+ using window or
643 // | QRenderSurfaceSelector | offscreen surface
644 // +------------------------+
645 // |
646 // +-----------+
647 // | QViewport | (0,0,1,1)
648 // +-----------+
649 // |
650 // +--------------------------+-------------------+-----------------+
651 // | | | |
652 // +--------------------+ +--------------+ +-----------------+ +-----------------+
653 // | two forward passes | | shadows pass | | depth buffer | | post-processing |
654 // | (solid objects | | | | processing pass | | passes |
655 // | and transparent) | +--------------+ +-----------------+ +-----------------+
656 // +--------------------+
657 //
658 // Notes:
659 // - depth buffer processing pass is used whenever we need depth map information
660 // (for camera navigation) and it converts depth texture to a color texture
661 // so that we can capture it with QRenderCapture - currently it is unable
662 // to capture depth buffer, only colors (see QTBUG-65155)
663 // - there are multiple post-processing passes that take rendered output
664 // of the scene, optionally apply effects (add shadows, ambient occlusion,
665 // eye dome lighting) and finally output to the given surface
666 // - there may be also two more passes when 3D axis is shown - see Qgs3DAxis
667
668 mRootEntity = root;
669 mMainCamera = mainCamera;
670 mLightCamera = new Qt3DRender::QCamera;
671
672 mPreviewLayer = new Qt3DRender::QLayer;
673 mCastShadowsLayer = new Qt3DRender::QLayer;
674 mForwardRenderLayer = new Qt3DRender::QLayer;
675 mDepthRenderPassLayer = new Qt3DRender::QLayer;
676 mTransparentObjectsPassLayer = new Qt3DRender::QLayer;
677 mRubberBandsLayer = new Qt3DRender::QLayer;
678
679 mRubberBandsLayer->setObjectName( "mRubberBandsLayer" );
680
681 mPreviewLayer->setRecursive( true );
682 mCastShadowsLayer->setRecursive( true );
683 mForwardRenderLayer->setRecursive( true );
684 mDepthRenderPassLayer->setRecursive( true );
685 mTransparentObjectsPassLayer->setRecursive( true );
686 mRubberBandsLayer->setRecursive( true );
687
688 mRenderSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector;
689
690 QObject *surfaceObj = dynamic_cast<QObject *>( surface );
691 Q_ASSERT( surfaceObj );
692
693 mRenderSurfaceSelector->setSurface( surfaceObj );
694 mRenderSurfaceSelector->setExternalRenderTargetSize( mSize );
695
696 mMainViewPort = new Qt3DRender::QViewport( mRenderSurfaceSelector );
697 mMainViewPort->setNormalizedRect( QRectF( 0.0f, 0.0f, 1.0f, 1.0f ) );
698
699 // Forward render
700 Qt3DRender::QFrameGraphNode *forwardRenderPass = constructForwardRenderPass();
701 forwardRenderPass->setParent( mMainViewPort );
702
703 // rubber bands (they should be always on top)
704 Qt3DRender::QFrameGraphNode *rubberBandsPass = constructRubberBandsPass();
705 rubberBandsPass->setObjectName( "rubberBandsPass" );
706 rubberBandsPass->setParent( mMainViewPort );
707
708 // shadow rendering pass
709 Qt3DRender::QFrameGraphNode *shadowRenderPass = constructShadowRenderPass();
710 shadowRenderPass->setParent( mMainViewPort );
711
712 // depth buffer processing
713 Qt3DRender::QFrameGraphNode *depthBufferProcessingPass = constructDepthRenderPass();
714 depthBufferProcessingPass->setParent( mMainViewPort );
715
716 // Ambient occlusion factor render pass
717 Qt3DRender::QFrameGraphNode *ambientOcclusionFactorRender = constructAmbientOcclusionRenderPass();
718 ambientOcclusionFactorRender->setParent( mMainViewPort );
719
720 Qt3DRender::QFrameGraphNode *ambientOcclusionBlurPass = constructAmbientOcclusionBlurPass();
721 ambientOcclusionBlurPass->setParent( mMainViewPort );
722
723 // post process
724 Qt3DRender::QFrameGraphNode *postprocessingPass = constructPostprocessingPass();
725 postprocessingPass->setParent( mMainViewPort );
726 postprocessingPass->setObjectName( "PostProcessingPass" );
727
728 mRubberBandsRootEntity = new Qt3DCore::QEntity( mRootEntity );
729 mRubberBandsRootEntity->setObjectName( "mRubberBandsRootEntity" );
730 mRubberBandsRootEntity->addComponent( mRubberBandsLayer );
731
732 Qt3DRender::QParameter *depthMapIsDepthParam = new Qt3DRender::QParameter( "isDepth", true );
733 Qt3DRender::QParameter *shadowMapIsDepthParam = new Qt3DRender::QParameter( "isDepth", true );
734
735 mDebugDepthMapPreviewQuad = this->addTexturePreviewOverlay( mForwardDepthTexture, QPointF( 0.9f, 0.9f ), QSizeF( 0.1, 0.1 ), QVector<Qt3DRender::QParameter *> { depthMapIsDepthParam } );
736 mDebugShadowMapPreviewQuad = this->addTexturePreviewOverlay( mShadowMapTexture, QPointF( 0.9f, 0.9f ), QSizeF( 0.1, 0.1 ), QVector<Qt3DRender::QParameter *> { shadowMapIsDepthParam } );
737 mDebugDepthMapPreviewQuad->setEnabled( false );
738 mDebugShadowMapPreviewQuad->setEnabled( false );
739
740 mDepthRenderQuad = constructDepthRenderQuad();
741 mDepthRenderQuad->addComponent( mDepthRenderPassLayer );
742 mDepthRenderQuad->setParent( mRootEntity );
743}
744
745QgsPreviewQuad *QgsFrameGraph::addTexturePreviewOverlay( Qt3DRender::QTexture2D *texture, const QPointF &centerTexCoords, const QSizeF &sizeTexCoords, QVector<Qt3DRender::QParameter *> additionalShaderParameters )
746{
747 QgsPreviewQuad *previewQuad = new QgsPreviewQuad( texture, centerTexCoords, sizeTexCoords, additionalShaderParameters );
748 previewQuad->addComponent( mPreviewLayer );
749 previewQuad->setParent( mRootEntity );
750 mPreviewQuads.push_back( previewQuad );
751 return previewQuad;
752}
753
754// computes the portion of the Z=z plane the camera is looking at
755void calculateViewExtent( Qt3DRender::QCamera *camera, float shadowRenderingDistance, float z, float &minX, float &maxX, float &minY, float &maxY, float &minZ, float &maxZ )
756{
757 const QVector3D cameraPos = camera->position();
758 const QMatrix4x4 projectionMatrix = camera->projectionMatrix();
759 const QMatrix4x4 viewMatrix = camera->viewMatrix();
760 float depth = 1.0f;
761 QVector4D viewCenter = viewMatrix * QVector4D( camera->viewCenter(), 1.0f );
762 viewCenter /= viewCenter.w();
763 viewCenter = projectionMatrix * viewCenter;
764 viewCenter /= viewCenter.w();
765 depth = viewCenter.z();
766 QVector<QVector3D> viewFrustumPoints = {
767 QVector3D( 0.0f, 0.0f, depth ),
768 QVector3D( 0.0f, 1.0f, depth ),
769 QVector3D( 1.0f, 0.0f, depth ),
770 QVector3D( 1.0f, 1.0f, depth ),
771 QVector3D( 0.0f, 0.0f, 0 ),
772 QVector3D( 0.0f, 1.0f, 0 ),
773 QVector3D( 1.0f, 0.0f, 0 ),
774 QVector3D( 1.0f, 1.0f, 0 )
775 };
776 maxX = std::numeric_limits<float>::lowest();
777 maxY = std::numeric_limits<float>::lowest();
778 maxZ = std::numeric_limits<float>::lowest();
779 minX = std::numeric_limits<float>::max();
780 minY = std::numeric_limits<float>::max();
781 minZ = std::numeric_limits<float>::max();
782 for ( int i = 0; i < viewFrustumPoints.size(); ++i )
783 {
784 // convert from view port space to world space
785 viewFrustumPoints[i] = viewFrustumPoints[i].unproject( viewMatrix, projectionMatrix, QRect( 0, 0, 1, 1 ) );
786 minX = std::min( minX, viewFrustumPoints[i].x() );
787 maxX = std::max( maxX, viewFrustumPoints[i].x() );
788 minY = std::min( minY, viewFrustumPoints[i].y() );
789 maxY = std::max( maxY, viewFrustumPoints[i].y() );
790 minZ = std::min( minZ, viewFrustumPoints[i].z() );
791 maxZ = std::max( maxZ, viewFrustumPoints[i].z() );
792 // find the intersection between the line going from cameraPos to the frustum quad point
793 // and the horizontal plane Z=z
794 // if the intersection is on the back side of the viewing panel we get a point that is
795 // shadowRenderingDistance units in front of the camera
796 const QVector3D pt = cameraPos;
797 const QVector3D vect = ( viewFrustumPoints[i] - pt ).normalized();
798 float t = ( z - pt.z() ) / vect.z();
799 if ( t < 0 )
800 t = shadowRenderingDistance;
801 else
802 t = std::min( t, shadowRenderingDistance );
803 viewFrustumPoints[i] = pt + t * vect;
804 minX = std::min( minX, viewFrustumPoints[i].x() );
805 maxX = std::max( maxX, viewFrustumPoints[i].x() );
806 minY = std::min( minY, viewFrustumPoints[i].y() );
807 maxY = std::max( maxY, viewFrustumPoints[i].y() );
808 minZ = std::min( minZ, viewFrustumPoints[i].z() );
809 maxZ = std::max( maxZ, viewFrustumPoints[i].z() );
810 }
811}
812
813void QgsFrameGraph::setupDirectionalLight( const QgsDirectionalLightSettings &light, float maximumShadowRenderingDistance )
814{
815 float minX, maxX, minY, maxY, minZ, maxZ;
816 QVector3D lookingAt = mMainCamera->viewCenter();
817 const float d = 2 * ( mMainCamera->position() - mMainCamera->viewCenter() ).length();
818
819 const QVector3D lightDirection = QVector3D( light.direction().x(), light.direction().y(), light.direction().z() ).normalized();
820 calculateViewExtent( mMainCamera, maximumShadowRenderingDistance, lookingAt.z(), minX, maxX, minY, maxY, minZ, maxZ );
821
822 lookingAt = QVector3D( 0.5f * ( minX + maxX ), 0.5f * ( minY + maxY ), mMainCamera->viewCenter().z() );
823 const QVector3D lightPosition = lookingAt + QVector3D( 0.0f, 0.0f, d );
824 mLightCamera->setPosition( lightPosition );
825 mLightCamera->setViewCenter( lookingAt );
826 mLightCamera->setUpVector( QVector3D( 0.0f, 1.0f, 0.0f ) );
827 mLightCamera->rotateAboutViewCenter( QQuaternion::rotationTo( QVector3D( 0.0f, 0.0f, -1.0f ), lightDirection ) );
828
829 mLightCamera->setProjectionType( Qt3DRender::QCameraLens::ProjectionType::OrthographicProjection );
830 mLightCamera->lens()->setOrthographicProjection(
831 -0.7f * ( maxX - minX ), 0.7f * ( maxX - minX ),
832 -0.7f * ( maxY - minY ), 0.7f * ( maxY - minY ),
833 1.0f, 2 * ( lookingAt - lightPosition ).length()
834 );
835
836 mPostprocessingEntity->setupShadowRenderingExtent( minX, maxX, minY, maxY );
837 mPostprocessingEntity->setupDirectionalLight( lightPosition, lightDirection );
838}
839
841{
842 QObject *top = mRenderSurfaceSelector;
843 while ( top->parent() && dynamic_cast<Qt3DRender::QFrameGraphNode *>( top->parent() ) )
844 top = top->parent();
845
847 context.lowestId = mMainCamera->id().id();
848 QStringList strList = QgsFgUtils::dumpFrameGraph( dynamic_cast<Qt3DRender::QFrameGraphNode *>( top ), context );
849
850 return qPrintable( strList.join( "\n" ) ) + QString( "\n" );
851}
852
854{
855 QStringList strList = QgsFgUtils::dumpSceneGraph( mRootEntity, QgsFgUtils::FgDumpContext() );
856 return qPrintable( strList.join( "\n" ) ) + QString( "\n" );
857}
858
859void QgsFrameGraph::setClearColor( const QColor &clearColor )
860{
861 mForwardClearBuffers->setClearColor( clearColor );
862}
863
865{
866 mShadowRenderingEnabled = enabled;
867 mPostprocessingEntity->setShadowRenderingEnabled( mShadowRenderingEnabled );
868 if ( mShadowRenderingEnabled )
869 mShadowSceneEntitiesFilter->setEnabled( true );
870 else
871 mShadowSceneEntitiesFilter->setEnabled( false );
872}
873
874void QgsFrameGraph::setShadowBias( float shadowBias )
875{
876 mShadowBias = shadowBias;
877 mPostprocessingEntity->setShadowBias( mShadowBias );
878}
879
881{
882 mShadowMapResolution = resolution;
883 mShadowMapTexture->setWidth( mShadowMapResolution );
884 mShadowMapTexture->setHeight( mShadowMapResolution );
885}
886
888{
889 mAmbientOcclusionEnabled = enabled;
890 mAmbientOcclusionRenderEntity->setEnabled( enabled );
891 mPostprocessingEntity->setAmbientOcclusionEnabled( enabled );
892}
893
895{
896 mAmbientOcclusionIntensity = intensity;
897 mAmbientOcclusionRenderEntity->setIntensity( intensity );
898}
899
901{
902 mAmbientOcclusionRadius = radius;
903 mAmbientOcclusionRenderEntity->setRadius( radius );
904}
905
907{
908 mAmbientOcclusionThreshold = threshold;
909 mAmbientOcclusionRenderEntity->setThreshold( threshold );
910}
911
913{
914 if ( enabled == mFrustumCullingEnabled )
915 return;
916 mFrustumCullingEnabled = enabled;
917 if ( mFrustumCullingEnabled )
918 mFrustumCulling->setParent( mForwardClearBuffers );
919 else
920 mFrustumCulling->setParent( ( Qt3DCore::QNode * ) nullptr );
921}
922
923void QgsFrameGraph::setupEyeDomeLighting( bool enabled, double strength, int distance )
924{
925 mEyeDomeLightingEnabled = enabled;
926 mEyeDomeLightingStrength = strength;
927 mEyeDomeLightingDistance = distance;
928 mPostprocessingEntity->setEyeDomeLightingEnabled( enabled );
929 mPostprocessingEntity->setEyeDomeLightingStrength( strength );
930 mPostprocessingEntity->setEyeDomeLightingDistance( distance );
931}
932
933void QgsFrameGraph::setupShadowMapDebugging( bool enabled, Qt::Corner corner, double size )
934{
935 mDebugShadowMapPreviewQuad->setEnabled( enabled );
936 if ( enabled )
937 {
938 switch ( corner )
939 {
940 case Qt::Corner::TopRightCorner:
941 mDebugShadowMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
942 break;
943 case Qt::Corner::TopLeftCorner:
944 mDebugShadowMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
945 break;
946 case Qt::Corner::BottomRightCorner:
947 mDebugShadowMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
948 break;
949 case Qt::Corner::BottomLeftCorner:
950 mDebugShadowMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
951 break;
952 }
953 }
954}
955
956void QgsFrameGraph::setupDepthMapDebugging( bool enabled, Qt::Corner corner, double size )
957{
958 mDebugDepthMapPreviewQuad->setEnabled( enabled );
959
960 if ( enabled )
961 {
962 switch ( corner )
963 {
964 case Qt::Corner::TopRightCorner:
965 mDebugDepthMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
966 break;
967 case Qt::Corner::TopLeftCorner:
968 mDebugDepthMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
969 break;
970 case Qt::Corner::BottomRightCorner:
971 mDebugDepthMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
972 break;
973 case Qt::Corner::BottomLeftCorner:
974 mDebugDepthMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
975 break;
976 }
977 }
978}
979
981{
982 mSize = s;
983 mForwardColorTexture->setSize( mSize.width(), mSize.height() );
984 mForwardDepthTexture->setSize( mSize.width(), mSize.height() );
985 mRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
986 mRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
987 mDepthRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
988 mDepthRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
989 mRenderSurfaceSelector->setExternalRenderTargetSize( mSize );
990
991 mAmbientOcclusionRenderTexture->setSize( mSize.width(), mSize.height() );
992 mAmbientOcclusionBlurTexture->setSize( mSize.width(), mSize.height() );
993}
994
996{
997 if ( enabled == mRenderCaptureEnabled )
998 return;
999 mRenderCaptureEnabled = enabled;
1000 mRenderCaptureTargetSelector->setEnabled( mRenderCaptureEnabled );
1001}
1002
1004{
1005 mDebugOverlay->setEnabled( enabled );
1006}
1007
1009{
1010 for ( Qt3DRender::QRenderState *state : mClipRenderStateSet->renderStates() )
1011 {
1012 if ( qobject_cast<Qt3DRender::QClipPlane *>( state ) )
1013 {
1014 mClipRenderStateSet->removeRenderState( state );
1015 }
1016 }
1017}
1018
1019void QgsFrameGraph::addClipPlanes( int nrClipPlanes )
1020{
1021 // remove existing QClipPlane
1023
1024 // create new QClipPlane
1025 for ( int i = 0; i < nrClipPlanes; ++i )
1026 {
1027 Qt3DRender::QClipPlane *clipPlane = new Qt3DRender::QClipPlane;
1028 clipPlane->setPlaneIndex( i );
1029 mClipRenderStateSet->addRenderState( clipPlane );
1030 }
1031}
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.
QgsVector3D direction() const
Returns the direction of the light in degrees.
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 addClipPlanes(int nrClipPlanes)
Setups nrClipPlanes clip planes in the forward pass to enable OpenGL clipping.
QString dumpFrameGraph() const
Dumps frame graph as string.
void setRenderCaptureEnabled(bool enabled)
Sets whether it will be possible to render to an image.
void removeClipPlanes()
Disables OpenGL clipping.
void setShadowBias(float shadowBias)
Sets the shadow bias value.
void setupShadowMapDebugging(bool enabled, Qt::Corner corner, double size)
Sets the shadow map debugging view port.
void setClearColor(const QColor &clearColor)
Sets the clear color of the scene (background color)
void setShadowMapResolution(int resolution)
Sets the resolution of the shadow map.
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.
float shadowBias() const
Returns the shadow bias value.
void setFrustumCullingEnabled(bool enabled)
Sets whether frustum culling is enabled.
void setDebugOverlayEnabled(bool enabled)
Sets whether debug overlay is enabled.
void setShadowRenderingEnabled(bool enabled)
Sets whether the shadow rendering is enabled.
void setupDepthMapDebugging(bool enabled, Qt::Corner corner, double size)
Sets the depth map debugging view port.
void setupDirectionalLight(const QgsDirectionalLightSettings &light, float maximumShadowRenderingDistance)
Sets shadow rendering to use a directional light.
void setAmbientOcclusionThreshold(float threshold)
Sets the ambient occlusion threshold.
QString dumpSceneGraph() const
Dumps scene graph as string.
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.
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.
void setupShadowRenderingExtent(float minX, float maxX, float minY, float maxY)
Sets the parts of the scene where objects cast shadows.
void setAmbientOcclusionEnabled(bool enabled)
Sets whether screen space ambient occlusion is enabled.
void setShadowRenderingEnabled(bool enabled)
Sets whether shadow rendering is enabled.
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 setupDirectionalLight(QVector3D position, QVector3D direction)
Sets up a directional light that is used to render shadows.
void setEyeDomeLightingEnabled(bool enabled)
Sets whether eye dome lighting is enabled.
void setViewPort(const QPointF &centerNDC, const QSizeF &size)
Sets where the quad will be located on the scene.
double y() const
Returns Y coordinate.
Definition qgsvector3d.h:50
double z() const
Returns Z coordinate.
Definition qgsvector3d.h:52
double x() const
Returns X coordinate.
Definition qgsvector3d.h:48
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
Qt3DCore::QGeometry Qt3DQGeometry
Qt3DCore::QAttribute Qt3DQAttribute
void calculateViewExtent(Qt3DRender::QCamera *camera, float shadowRenderingDistance, float z, float &minX, float &maxX, float &minY, float &maxY, float &minZ, float &maxZ)
Qt3DCore::QBuffer Qt3DQBuffer
Qt3DCore::QGeometry Qt3DQGeometry