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