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