QGIS API Documentation  3.24.2-Tisler (13c1a02865)
qgsshadowrenderingframegraph.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsshadowrenderingframegraph.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 
17 
19 #include "qgscameracontroller.h"
20 #include "qgsrectangle.h"
22 #include "qgspreviewquad.h"
23 #include "qgs3dutils.h"
24 
25 #include <Qt3DRender/QAttribute>
26 #include <Qt3DRender/QBuffer>
27 #include <Qt3DRender/QTechnique>
28 #include <Qt3DRender/QGraphicsApiFilter>
29 
30 
31 Qt3DRender::QFrameGraphNode *QgsShadowRenderingFrameGraph::constructTexturesPreviewPass()
32 {
33  mPreviewLayerFilter = new Qt3DRender::QLayerFilter;
34  mPreviewLayerFilter->addLayer( mPreviewLayer );
35 
36  mPreviewRenderStateSet = new Qt3DRender::QRenderStateSet( mPreviewLayerFilter );
37  mPreviewDepthTest = new Qt3DRender::QDepthTest;
38  mPreviewDepthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );
39  mPreviewRenderStateSet->addRenderState( mPreviewDepthTest );
40  mPreviewCullFace = new Qt3DRender::QCullFace;
41  mPreviewCullFace->setMode( Qt3DRender::QCullFace::NoCulling );
42  mPreviewRenderStateSet->addRenderState( mPreviewCullFace );
43 
44  return mPreviewLayerFilter;
45 }
46 
47 Qt3DRender::QFrameGraphNode *QgsShadowRenderingFrameGraph::constructForwardRenderPass()
48 {
49  mMainCameraSelector = new Qt3DRender::QCameraSelector;
50  mMainCameraSelector->setCamera( mMainCamera );
51 
52  mForwardRenderLayerFilter = new Qt3DRender::QLayerFilter( mMainCameraSelector );
53  mForwardRenderLayerFilter->addLayer( mForwardRenderLayer );
54 
55  mForwardColorTexture = new Qt3DRender::QTexture2D;
56  mForwardColorTexture->setWidth( mSize.width() );
57  mForwardColorTexture->setHeight( mSize.height() );
58  mForwardColorTexture->setFormat( Qt3DRender::QAbstractTexture::RGB8_UNorm );
59  mForwardColorTexture->setGenerateMipMaps( false );
60  mForwardColorTexture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
61  mForwardColorTexture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
62  mForwardColorTexture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
63  mForwardColorTexture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
64 
65  mForwardDepthTexture = new Qt3DRender::QTexture2D;
66  mForwardDepthTexture->setWidth( mSize.width() );
67  mForwardDepthTexture->setHeight( mSize.height() );
68  mForwardDepthTexture->setFormat( Qt3DRender::QTexture2D::TextureFormat::DepthFormat );
69  mForwardDepthTexture->setGenerateMipMaps( false );
70  mForwardDepthTexture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
71  mForwardDepthTexture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
72  mForwardDepthTexture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
73  mForwardDepthTexture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
74 
75  Qt3DRender::QRenderTarget *forwardRenderTarget = new Qt3DRender::QRenderTarget;
76  Qt3DRender::QRenderTargetOutput *forwardRenderTargetDepthOutput = new Qt3DRender::QRenderTargetOutput;
77  forwardRenderTargetDepthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
78  forwardRenderTargetDepthOutput->setTexture( mForwardDepthTexture );
79  forwardRenderTarget->addOutput( forwardRenderTargetDepthOutput );
80  Qt3DRender::QRenderTargetOutput *forwardRenderTargetColorOutput = new Qt3DRender::QRenderTargetOutput;
81  forwardRenderTargetColorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
82  forwardRenderTargetColorOutput->setTexture( mForwardColorTexture );
83  forwardRenderTarget->addOutput( forwardRenderTargetColorOutput );
84 
85  mForwardRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mForwardRenderLayerFilter );
86  mForwardRenderTargetSelector->setTarget( forwardRenderTarget );
87 
88  mForwardClearBuffers = new Qt3DRender::QClearBuffers( mForwardRenderTargetSelector );
89  mForwardClearBuffers->setClearColor( QColor::fromRgbF( 0.0, 0.0, 1.0, 1.0 ) );
90  mForwardClearBuffers->setBuffers( Qt3DRender::QClearBuffers::ColorDepthBuffer );
91  mForwardClearBuffers->setClearDepthValue( 1.0f );
92 
93  Qt3DRender::QRenderStateSet *forwaredRenderStateSet = new Qt3DRender::QRenderStateSet( mForwardClearBuffers );
94 
95  Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
96  depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
97  forwaredRenderStateSet->addRenderState( depthTest );
98 
99  Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
100  cullFace->setMode( Qt3DRender::QCullFace::CullingMode::Back );
101  forwaredRenderStateSet->addRenderState( cullFace );
102 
103  mFrustumCulling = new Qt3DRender::QFrustumCulling( forwaredRenderStateSet );
104 
105  return mMainCameraSelector;
106 }
107 
108 Qt3DRender::QFrameGraphNode *QgsShadowRenderingFrameGraph::constructShadowRenderPass()
109 {
110  mLightCameraSelectorShadowPass = new Qt3DRender::QCameraSelector;
111  mLightCameraSelectorShadowPass->setCamera( mLightCamera );
112 
113  mShadowSceneEntitiesFilter = new Qt3DRender::QLayerFilter( mLightCameraSelectorShadowPass );
114  mShadowSceneEntitiesFilter->addLayer( mCastShadowsLayer );
115 
116  mShadowMapTexture = new Qt3DRender::QTexture2D;
117  mShadowMapTexture->setWidth( mShadowMapResolution );
118  mShadowMapTexture->setHeight( mShadowMapResolution );
119  mShadowMapTexture->setFormat( Qt3DRender::QTexture2D::TextureFormat::DepthFormat );
120  mShadowMapTexture->setGenerateMipMaps( false );
121  mShadowMapTexture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
122  mShadowMapTexture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
123  mShadowMapTexture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
124  mShadowMapTexture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
125 
126  Qt3DRender::QRenderTarget *shadowRenderTarget = new Qt3DRender::QRenderTarget;
127  Qt3DRender::QRenderTargetOutput *shadowRenderTargetOutput = new Qt3DRender::QRenderTargetOutput;
128  shadowRenderTargetOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
129  shadowRenderTargetOutput->setTexture( mShadowMapTexture );
130  shadowRenderTarget->addOutput( shadowRenderTargetOutput );
131 
132  mShadowRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mShadowSceneEntitiesFilter );
133  mShadowRenderTargetSelector->setTarget( shadowRenderTarget );
134 
135  mShadowClearBuffers = new Qt3DRender::QClearBuffers( mShadowRenderTargetSelector );
136  mShadowClearBuffers->setBuffers( Qt3DRender::QClearBuffers::BufferType::ColorDepthBuffer );
137  mShadowClearBuffers->setClearColor( QColor::fromRgbF( 0.0f, 1.0f, 0.0f ) );
138 
139  mShadowRenderStateSet = new Qt3DRender::QRenderStateSet( mShadowClearBuffers );
140 
141  Qt3DRender::QDepthTest *shadowDepthTest = new Qt3DRender::QDepthTest;
142  shadowDepthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
143  mShadowRenderStateSet->addRenderState( shadowDepthTest );
144 
145  Qt3DRender::QCullFace *shadowCullFace = new Qt3DRender::QCullFace;
146  shadowCullFace->setMode( Qt3DRender::QCullFace::CullingMode::Front );
147  mShadowRenderStateSet->addRenderState( shadowCullFace );
148 
149  Qt3DRender::QPolygonOffset *polygonOffset = new Qt3DRender::QPolygonOffset;
150  polygonOffset->setDepthSteps( 4.0 );
151  polygonOffset->setScaleFactor( 1.1 );
152  mShadowRenderStateSet->addRenderState( polygonOffset );
153 
154  return mLightCameraSelectorShadowPass;
155 }
156 
157 Qt3DRender::QFrameGraphNode *QgsShadowRenderingFrameGraph::constructPostprocessingPass()
158 {
159  mPostProcessingCameraSelector = new Qt3DRender::QCameraSelector;
160  mPostProcessingCameraSelector->setCamera( mLightCamera );
161 
162  mPostprocessPassLayerFilter = new Qt3DRender::QLayerFilter( mPostProcessingCameraSelector );
163  mPostprocessPassLayerFilter->addLayer( mPostprocessPassLayer );
164 
165  mPostprocessClearBuffers = new Qt3DRender::QClearBuffers( mPostprocessPassLayerFilter );
166 
167  mRenderCaptureTargetSelector = new Qt3DRender::QRenderTargetSelector( mPostprocessClearBuffers );
168 
169  Qt3DRender::QRenderTarget *renderTarget = new Qt3DRender::QRenderTarget( mRenderCaptureTargetSelector );
170 
171  // The lifetime of the objects created here is managed
172  // automatically, as they become children of this object.
173 
174  // Create a render target output for rendering color.
175  Qt3DRender::QRenderTargetOutput *colorOutput = new Qt3DRender::QRenderTargetOutput( renderTarget );
176  colorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
177 
178  // Create a texture to render into.
179  mRenderCaptureColorTexture = new Qt3DRender::QTexture2D( colorOutput );
180  mRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
181  mRenderCaptureColorTexture->setFormat( Qt3DRender::QAbstractTexture::RGB8_UNorm );
182  mRenderCaptureColorTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
183  mRenderCaptureColorTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
184 
185  // Hook the texture up to our output, and the output up to this object.
186  colorOutput->setTexture( mRenderCaptureColorTexture );
187  renderTarget->addOutput( colorOutput );
188 
189  Qt3DRender::QRenderTargetOutput *depthOutput = new Qt3DRender::QRenderTargetOutput( renderTarget );
190 
191  depthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
192  mRenderCaptureDepthTexture = new Qt3DRender::QTexture2D( depthOutput );
193  mRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
194  mRenderCaptureDepthTexture->setFormat( Qt3DRender::QAbstractTexture::DepthFormat );
195  mRenderCaptureDepthTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
196  mRenderCaptureDepthTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
197  mRenderCaptureDepthTexture->setComparisonFunction( Qt3DRender::QAbstractTexture::CompareLessEqual );
198  mRenderCaptureDepthTexture->setComparisonMode( Qt3DRender::QAbstractTexture::CompareRefToTexture );
199 
200  depthOutput->setTexture( mRenderCaptureDepthTexture );
201  renderTarget->addOutput( depthOutput );
202 
203  mRenderCaptureTargetSelector->setTarget( renderTarget );
204 
205  mRenderCapture = new Qt3DRender::QRenderCapture( mRenderCaptureTargetSelector );
206 
207  return mPostProcessingCameraSelector;
208 }
209 
210 Qt3DRender::QFrameGraphNode *QgsShadowRenderingFrameGraph::constructDepthRenderPass()
211 {
212  // depth buffer render to copy pass
213 
214  mDepthRenderCameraSelector = new Qt3DRender::QCameraSelector;
215  mDepthRenderCameraSelector->setCamera( mMainCamera );
216 
217  mDepthRenderStateSet = new Qt3DRender::QRenderStateSet( mDepthRenderCameraSelector );
218 
219  Qt3DRender::QDepthTest *depthRenderDepthTest = new Qt3DRender::QDepthTest;
220  depthRenderDepthTest->setDepthFunction( Qt3DRender::QDepthTest::Always );;
221  Qt3DRender::QCullFace *depthRenderCullFace = new Qt3DRender::QCullFace;
222  depthRenderCullFace->setMode( Qt3DRender::QCullFace::NoCulling );
223 
224  mDepthRenderStateSet->addRenderState( depthRenderDepthTest );
225  mDepthRenderStateSet->addRenderState( depthRenderCullFace );
226 
227  mDepthRenderLayerFilter = new Qt3DRender::QLayerFilter( mDepthRenderStateSet );
228  mDepthRenderLayerFilter->addLayer( mDepthRenderPassLayer );
229 
230  mDepthRenderCaptureTargetSelector = new Qt3DRender::QRenderTargetSelector( mDepthRenderLayerFilter );
231  Qt3DRender::QRenderTarget *depthRenderTarget = new Qt3DRender::QRenderTarget( mDepthRenderCaptureTargetSelector );
232 
233  // The lifetime of the objects created here is managed
234  // automatically, as they become children of this object.
235 
236  // Create a render target output for rendering color.
237  Qt3DRender::QRenderTargetOutput *colorOutput = new Qt3DRender::QRenderTargetOutput( depthRenderTarget );
238  colorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
239 
240  // Create a texture to render into.
241  mDepthRenderCaptureColorTexture = new Qt3DRender::QTexture2D( colorOutput );
242  mDepthRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
243  mDepthRenderCaptureColorTexture->setFormat( Qt3DRender::QAbstractTexture::RGB8_UNorm );
244  mDepthRenderCaptureColorTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
245  mDepthRenderCaptureColorTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
246 
247  // Hook the texture up to our output, and the output up to this object.
248  colorOutput->setTexture( mDepthRenderCaptureColorTexture );
249  depthRenderTarget->addOutput( colorOutput );
250 
251  Qt3DRender::QRenderTargetOutput *depthOutput = new Qt3DRender::QRenderTargetOutput( depthRenderTarget );
252 
253  depthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
254  mDepthRenderCaptureDepthTexture = new Qt3DRender::QTexture2D( depthOutput );
255  mDepthRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
256  mDepthRenderCaptureDepthTexture->setFormat( Qt3DRender::QAbstractTexture::DepthFormat );
257  mDepthRenderCaptureDepthTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
258  mDepthRenderCaptureDepthTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
259  mDepthRenderCaptureDepthTexture->setComparisonFunction( Qt3DRender::QAbstractTexture::CompareLessEqual );
260  mDepthRenderCaptureDepthTexture->setComparisonMode( Qt3DRender::QAbstractTexture::CompareRefToTexture );
261 
262  depthOutput->setTexture( mDepthRenderCaptureDepthTexture );
263  depthRenderTarget->addOutput( depthOutput );
264 
265  mDepthRenderCaptureTargetSelector->setTarget( depthRenderTarget );
266 
267  // Note: We do not a clear buffers node since we are drawing a quad that will override the buffer's content anyway
268  mDepthRenderCapture = new Qt3DRender::QRenderCapture( mDepthRenderCaptureTargetSelector );
269 
270  return mDepthRenderCameraSelector;
271 }
272 
273 Qt3DCore::QEntity *QgsShadowRenderingFrameGraph::constructDepthRenderQuad()
274 {
275  Qt3DCore::QEntity *quad = new Qt3DCore::QEntity;
276  quad->setObjectName( "depthRenderQuad" );
277 
278  Qt3DRender::QGeometry *geom = new Qt3DRender::QGeometry;
279  Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute;
280  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 };
281 
282  const QByteArray vertexArr( ( const char * ) vert.constData(), vert.size() * sizeof( float ) );
283  Qt3DRender::QBuffer *vertexBuffer = nullptr;
284  vertexBuffer = new Qt3DRender::QBuffer( this );
285  vertexBuffer->setData( vertexArr );
286 
287  positionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
288  positionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
289  positionAttribute->setVertexSize( 3 );
290  positionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
291  positionAttribute->setBuffer( vertexBuffer );
292  positionAttribute->setByteOffset( 0 );
293  positionAttribute->setByteStride( 3 * sizeof( float ) );
294  positionAttribute->setCount( 6 );
295 
296  geom->addAttribute( positionAttribute );
297 
298  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
299  renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::PrimitiveType::Triangles );
300  renderer->setGeometry( geom );
301 
302  quad->addComponent( renderer );
303 
304  QMatrix4x4 modelMatrix;
305  modelMatrix.setToIdentity();
306 
307  // construct material
308 
309  Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
310  Qt3DRender::QParameter *textureParameter = new Qt3DRender::QParameter( "depthTexture", mForwardDepthTexture );
311  Qt3DRender::QParameter *textureTransformParameter = new Qt3DRender::QParameter( "modelMatrix", QVariant::fromValue( modelMatrix ) );
312  material->addParameter( textureParameter );
313  material->addParameter( textureTransformParameter );
314 
315  Qt3DRender::QEffect *effect = new Qt3DRender::QEffect;
316 
317  Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
318 
319  Qt3DRender::QGraphicsApiFilter *graphicsApiFilter = technique->graphicsApiFilter();
320  graphicsApiFilter->setApi( Qt3DRender::QGraphicsApiFilter::Api::OpenGL );
321  graphicsApiFilter->setProfile( Qt3DRender::QGraphicsApiFilter::OpenGLProfile::CoreProfile );
322  graphicsApiFilter->setMajorVersion( 1 );
323  graphicsApiFilter->setMinorVersion( 5 );
324 
325  Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass;
326 
327  Qt3DRender::QShaderProgram *shader = new Qt3DRender::QShaderProgram;
328  shader->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/depth_render.vert" ) ) );
329  shader->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/depth_render.frag" ) ) );
330  renderPass->setShaderProgram( shader );
331 
332  technique->addRenderPass( renderPass );
333 
334  effect->addTechnique( technique );
335  material->setEffect( effect );
336 
337  quad->addComponent( material );
338 
339  return quad;
340 }
341 
342 QgsShadowRenderingFrameGraph::QgsShadowRenderingFrameGraph( QSurface *surface, QSize s, Qt3DRender::QCamera *mainCamera, Qt3DCore::QEntity *root )
343  : Qt3DCore::QEntity( root )
344  , mSize( s )
345 {
346  mRootEntity = root;
347  mMainCamera = mainCamera;
348  mLightCamera = new Qt3DRender::QCamera;
349 
350  mPostprocessPassLayer = new Qt3DRender::QLayer;
351  mPreviewLayer = new Qt3DRender::QLayer;
352  mCastShadowsLayer = new Qt3DRender::QLayer;
353  mForwardRenderLayer = new Qt3DRender::QLayer;
354  mDepthRenderPassLayer = new Qt3DRender::QLayer;
355 
356 
357  mPostprocessPassLayer->setRecursive( true );
358  mPreviewLayer->setRecursive( true );
359  mCastShadowsLayer->setRecursive( true );
360  mForwardRenderLayer->setRecursive( true );
361  mDepthRenderPassLayer->setRecursive( true );
362 
363  mRenderSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector;
364 
365  QObject *surfaceObj = dynamic_cast< QObject * >( surface );
366  Q_ASSERT( surfaceObj );
367 
368  mRenderSurfaceSelector->setSurface( surfaceObj );
369  mRenderSurfaceSelector->setExternalRenderTargetSize( mSize );
370 
371  mMainViewPort = new Qt3DRender::QViewport( mRenderSurfaceSelector );
372  mMainViewPort->setNormalizedRect( QRectF( 0.0f, 0.0f, 1.0f, 1.0f ) );
373 
374  // Forward render
375  Qt3DRender::QFrameGraphNode *forwardRenderPass = constructForwardRenderPass();
376  forwardRenderPass->setParent( mMainViewPort );
377 
378  // shadow rendering pass
379 
380  Qt3DRender::QFrameGraphNode *shadowRenderPass = constructShadowRenderPass();
381  shadowRenderPass->setParent( mMainViewPort );
382 
383  // depth buffer processing
384  Qt3DRender::QFrameGraphNode *depthBufferProcessingPass = constructDepthRenderPass();
385  depthBufferProcessingPass->setParent( mMainViewPort );
386 
387  // post process
388  Qt3DRender::QFrameGraphNode *postprocessingPass = constructPostprocessingPass();
389  postprocessingPass->setParent( mMainViewPort );
390 
391  // textures preview pass
392  Qt3DRender::QFrameGraphNode *previewPass = constructTexturesPreviewPass();
393  previewPass->setParent( mMainViewPort );
394 
395  mPostprocessingEntity = new QgsPostprocessingEntity( this, mRootEntity );
396  mPostprocessingEntity->addComponent( mPostprocessPassLayer );
397 
398  Qt3DRender::QParameter *depthMapIsDepthParam = new Qt3DRender::QParameter( "isDepth", true );
399  Qt3DRender::QParameter *shadowMapIsDepthParam = new Qt3DRender::QParameter( "isDepth", true );
400 
401  mDebugDepthMapPreviewQuad = this->addTexturePreviewOverlay( mForwardDepthTexture, QPointF( 0.9f, 0.9f ), QSizeF( 0.1, 0.1 ), QVector<Qt3DRender::QParameter *> { depthMapIsDepthParam } );
402  mDebugShadowMapPreviewQuad = this->addTexturePreviewOverlay( mShadowMapTexture, QPointF( 0.9f, 0.9f ), QSizeF( 0.1, 0.1 ), QVector<Qt3DRender::QParameter *> { shadowMapIsDepthParam } );
403  mDebugDepthMapPreviewQuad->setEnabled( false );
404  mDebugShadowMapPreviewQuad->setEnabled( false );
405 
406  mDepthRenderQuad = constructDepthRenderQuad();
407  mDepthRenderQuad->addComponent( mDepthRenderPassLayer );
408  mDepthRenderQuad->setParent( mRootEntity );
409 }
410 
411 QgsPreviewQuad *QgsShadowRenderingFrameGraph::addTexturePreviewOverlay( Qt3DRender::QTexture2D *texture, const QPointF &centerTexCoords, const QSizeF &sizeTexCoords, QVector<Qt3DRender::QParameter *> additionalShaderParameters )
412 {
413  QgsPreviewQuad *previewQuad = new QgsPreviewQuad( texture, centerTexCoords, sizeTexCoords, additionalShaderParameters );
414  previewQuad->addComponent( mPreviewLayer );
415  previewQuad->setParent( mRootEntity );
416  mPreviewQuads.push_back( previewQuad );
417  return previewQuad;
418 }
419 
420 // computes the portion of the Y=y plane the camera is looking at
421 void calculateViewExtent( Qt3DRender::QCamera *camera, float shadowRenderingDistance, float y, float &minX, float &maxX, float &minY, float &maxY, float &minZ, float &maxZ )
422 {
423  const QVector3D cameraPos = camera->position();
424  const QMatrix4x4 projectionMatrix = camera->projectionMatrix();
425  const QMatrix4x4 viewMatrix = camera->viewMatrix();
426  float depth = 1.0f;
427  QVector4D viewCenter = viewMatrix * QVector4D( camera->viewCenter(), 1.0f );
428  viewCenter /= viewCenter.w();
429  viewCenter = projectionMatrix * viewCenter;
430  viewCenter /= viewCenter.w();
431  depth = viewCenter.z();
432  QVector<QVector3D> viewFrustumPoints =
433  {
434  QVector3D( 0.0f, 0.0f, depth ),
435  QVector3D( 0.0f, 1.0f, depth ),
436  QVector3D( 1.0f, 0.0f, depth ),
437  QVector3D( 1.0f, 1.0f, depth ),
438  QVector3D( 0.0f, 0.0f, 0 ),
439  QVector3D( 0.0f, 1.0f, 0 ),
440  QVector3D( 1.0f, 0.0f, 0 ),
441  QVector3D( 1.0f, 1.0f, 0 )
442  };
443  maxX = std::numeric_limits<float>::lowest();
444  maxY = std::numeric_limits<float>::lowest();
445  maxZ = std::numeric_limits<float>::lowest();
446  minX = std::numeric_limits<float>::max();
447  minY = std::numeric_limits<float>::max();
448  minZ = std::numeric_limits<float>::max();
449  for ( int i = 0; i < viewFrustumPoints.size(); ++i )
450  {
451  // convert from view port space to world space
452  viewFrustumPoints[i] = viewFrustumPoints[i].unproject( viewMatrix, projectionMatrix, QRect( 0, 0, 1, 1 ) );
453  minX = std::min( minX, viewFrustumPoints[i].x() );
454  maxX = std::max( maxX, viewFrustumPoints[i].x() );
455  minY = std::min( minY, viewFrustumPoints[i].y() );
456  maxY = std::max( maxY, viewFrustumPoints[i].y() );
457  minZ = std::min( minZ, viewFrustumPoints[i].z() );
458  maxZ = std::max( maxZ, viewFrustumPoints[i].z() );
459  // find the intersection between the line going from cameraPos to the frustum quad point
460  // and the horizontal plane Y=y
461  // if the intersection is on the back side of the viewing panel we get a point that is
462  // shadowRenderingDistance units in front of the camera
463  const QVector3D pt = cameraPos;
464  const QVector3D vect = ( viewFrustumPoints[i] - pt ).normalized();
465  float t = ( y - pt.y() ) / vect.y();
466  if ( t < 0 )
467  t = shadowRenderingDistance;
468  else
469  t = std::min( t, shadowRenderingDistance );
470  viewFrustumPoints[i] = pt + t * vect;
471  minX = std::min( minX, viewFrustumPoints[i].x() );
472  maxX = std::max( maxX, viewFrustumPoints[i].x() );
473  minY = std::min( minY, viewFrustumPoints[i].y() );
474  maxY = std::max( maxY, viewFrustumPoints[i].y() );
475  minZ = std::min( minZ, viewFrustumPoints[i].z() );
476  maxZ = std::max( maxZ, viewFrustumPoints[i].z() );
477  }
478 }
479 
480 void QgsShadowRenderingFrameGraph::setupDirectionalLight( const QgsDirectionalLightSettings &light, float maximumShadowRenderingDistance )
481 {
482  float minX, maxX, minY, maxY, minZ, maxZ;
483  QVector3D lookingAt = mMainCamera->viewCenter();
484  const float d = 2 * ( mMainCamera->position() - mMainCamera->viewCenter() ).length();
485 
486  const QVector3D vertical = QVector3D( 0.0f, d, 0.0f );
487  const QVector3D lightDirection = QVector3D( light.direction().x(), light.direction().y(), light.direction().z() ).normalized();
488  calculateViewExtent( mMainCamera, maximumShadowRenderingDistance, lookingAt.y(), minX, maxX, minY, maxY, minZ, maxZ );
489 
490  lookingAt = QVector3D( 0.5 * ( minX + maxX ), mMainCamera->viewCenter().y(), 0.5 * ( minZ + maxZ ) );
491  const QVector3D lightPosition = lookingAt + vertical;
492  mLightCamera->setPosition( lightPosition );
493  mLightCamera->setViewCenter( lookingAt );
494  mLightCamera->setUpVector( QVector3D( 0.0f, 1.0f, 0.0f ) );
495  mLightCamera->rotateAboutViewCenter( QQuaternion::rotationTo( vertical.normalized(), -lightDirection.normalized() ) );
496 
497  mLightCamera->setProjectionType( Qt3DRender::QCameraLens::ProjectionType::OrthographicProjection );
498  mLightCamera->lens()->setOrthographicProjection(
499  - 0.7 * ( maxX - minX ), 0.7 * ( maxX - minX ),
500  - 0.7 * ( maxZ - minZ ), 0.7 * ( maxZ - minZ ),
501  1.0f, 2 * ( lookingAt - lightPosition ).length() );
502 
503  mPostprocessingEntity->setupShadowRenderingExtent( minX, maxX, minZ, maxZ );
504  mPostprocessingEntity->setupDirectionalLight( lightPosition, lightDirection );
505 }
506 
507 void QgsShadowRenderingFrameGraph::setClearColor( const QColor &clearColor )
508 {
509  mForwardClearBuffers->setClearColor( clearColor );
510 }
511 
513 {
514  mShadowRenderingEnabled = enabled;
515  mPostprocessingEntity->setShadowRenderingEnabled( mShadowRenderingEnabled );
516  if ( mShadowRenderingEnabled )
517  mShadowSceneEntitiesFilter->setEnabled( true );
518  else
519  mShadowSceneEntitiesFilter->setEnabled( false );
520 }
521 
523 {
524  mShadowBias = shadowBias;
525  mPostprocessingEntity->setShadowBias( mShadowBias );
526 }
527 
529 {
530  mShadowMapResolution = resolution;
531  mShadowMapTexture->setWidth( mShadowMapResolution );
532  mShadowMapTexture->setHeight( mShadowMapResolution );
533 }
534 
536 {
537  if ( enabled == mFrustumCullingEnabled )
538  return;
539  mFrustumCullingEnabled = enabled;
540  if ( mFrustumCullingEnabled )
541  mFrustumCulling->setParent( mForwardClearBuffers );
542  else
543  mFrustumCulling->setParent( ( Qt3DCore::QNode * )nullptr );
544 }
545 
546 void QgsShadowRenderingFrameGraph::setupEyeDomeLighting( bool enabled, double strength, int distance )
547 {
548  mEyeDomeLightingEnabled = enabled;
549  mEyeDomeLightingStrength = strength;
550  mEyeDomeLightingDistance = distance;
551  mPostprocessingEntity->setEyeDomeLightingEnabled( enabled );
552  mPostprocessingEntity->setEyeDomeLightingStrength( strength );
553  mPostprocessingEntity->setEyeDomeLightingDistance( distance );
554 }
555 
556 void QgsShadowRenderingFrameGraph::setupShadowMapDebugging( bool enabled, Qt::Corner corner, double size )
557 {
558  mDebugShadowMapPreviewQuad->setEnabled( enabled );
559  if ( enabled )
560  {
561  switch ( corner )
562  {
563  case Qt::Corner::TopRightCorner:
564  mDebugShadowMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
565  break;
566  case Qt::Corner::TopLeftCorner:
567  mDebugShadowMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
568  break;
569  case Qt::Corner::BottomRightCorner:
570  mDebugShadowMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
571  break;
572  case Qt::Corner::BottomLeftCorner:
573  mDebugShadowMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
574  break;
575  }
576  }
577 }
578 
579 void QgsShadowRenderingFrameGraph::setupDepthMapDebugging( bool enabled, Qt::Corner corner, double size )
580 {
581  mDebugDepthMapPreviewQuad->setEnabled( enabled );
582 
583  if ( enabled )
584  {
585  switch ( corner )
586  {
587  case Qt::Corner::TopRightCorner:
588  mDebugDepthMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
589  break;
590  case Qt::Corner::TopLeftCorner:
591  mDebugDepthMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 0.0f + size / 2 ), 0.5 * QSizeF( size, size ) );
592  break;
593  case Qt::Corner::BottomRightCorner:
594  mDebugDepthMapPreviewQuad->setViewPort( QPointF( 1.0f - size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
595  break;
596  case Qt::Corner::BottomLeftCorner:
597  mDebugDepthMapPreviewQuad->setViewPort( QPointF( 0.0f + size / 2, 1.0f - size / 2 ), 0.5 * QSizeF( size, size ) );
598  break;
599  }
600  }
601 }
602 
604 {
605  mSize = s;
606  mForwardColorTexture->setSize( mSize.width(), mSize.height() );
607  mForwardDepthTexture->setSize( mSize.width(), mSize.height() );
608  mRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
609  mRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
610  mDepthRenderCaptureDepthTexture->setSize( mSize.width(), mSize.height() );
611  mDepthRenderCaptureColorTexture->setSize( mSize.width(), mSize.height() );
612  mRenderSurfaceSelector->setExternalRenderTargetSize( mSize );
613 }
614 
616 {
617  if ( enabled == mRenderCaptureEnabled )
618  return;
619  mRenderCaptureEnabled = enabled;
620  mRenderCaptureTargetSelector->setEnabled( mRenderCaptureEnabled );
621 }
QgsVector3D direction() const
Returns the direction of the light in degrees.
void setupShadowRenderingExtent(float minX, float maxX, float minZ, float maxZ)
Sets the parts of the scene where objects cast shadows.
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.
void setupDepthMapDebugging(bool enabled, Qt::Corner corner, double size)
Sets the depth map debugging view port.
QgsShadowRenderingFrameGraph(QSurface *surface, QSize s, Qt3DRender::QCamera *mainCamera, Qt3DCore::QEntity *root)
Constructor.
void setupShadowMapDebugging(bool enabled, Qt::Corner corner, double size)
Sets the shadow map debugging view port.
void setShadowBias(float shadowBias)
Sets the shadow bias value.
void setShadowMapResolution(int resolution)
Sets the resolution of the shadow map.
void setSize(QSize s)
Sets the size of the buffers used for rendering.
void setupEyeDomeLighting(bool enabled, double strength, int distance)
Sets eye dome lighting shading related settings.
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.
Qt3DRender::QCamera * mainCamera()
Returns the main camera.
void setFrustumCullingEnabled(bool enabled)
Sets whether frustum culling is enabled.
void setClearColor(const QColor &clearColor)
Sets the clear color of the scene (background color)
void setRenderCaptureEnabled(bool enabled)
Sets whether it will be possible to render to an image.
void setupDirectionalLight(const QgsDirectionalLightSettings &light, float maximumShadowRenderingDistance)
Sets shadow rendering to use a directional light.
float shadowBias() const
Returns the shadow bias value.
void setShadowRenderingEnabled(bool enabled)
Sets whether the shadow rendering is enabled.
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:51
double z() const
Returns Z coordinate.
Definition: qgsvector3d.h:53
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:49
void calculateViewExtent(Qt3DRender::QCamera *camera, float shadowRenderingDistance, float y, float &minX, float &maxX, float &minY, float &maxY, float &minZ, float &maxZ)