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