QGIS API Documentation 4.1.0-Master (31622b25bb0)
Loading...
Searching...
No Matches
qgsshadowrenderview.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsshadowrenderview.cpp
3 --------------------------------------
4 Date : June 2024
5 Copyright : (C) 2024 by Benoit De Mezzo and (C) 2020 by Belgacem Nedjima
6 Email : benoit dot de dot mezzo at oslandia dot com
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 "qgsshadowrenderview.h"
17
18#include <Qt3DRender/QCamera>
19#include <Qt3DRender/QCameraSelector>
20#include <Qt3DRender/QClearBuffers>
21#include <Qt3DRender/QCullFace>
22#include <Qt3DRender/QDepthTest>
23#include <Qt3DRender/QFrustumCulling>
24#include <Qt3DRender/QLayer>
25#include <Qt3DRender/QLayerFilter>
26#include <Qt3DRender/QParameter>
27#include <Qt3DRender/QPolygonOffset>
28#include <Qt3DRender/QRenderStateSet>
29#include <Qt3DRender/QRenderSurfaceSelector>
30#include <Qt3DRender/QRenderTarget>
31#include <Qt3DRender/QRenderTargetSelector>
32#include <Qt3DRender/QTexture>
33#include <Qt3DRender/QViewport>
34#include <Qt3DRender/qsubtreeenabler.h>
35
36QgsShadowRenderView::QgsShadowRenderView( const QString &viewName, Qt3DCore::QEntity *rootEntity )
37 : QgsAbstractRenderView( viewName )
38 , mRootEntity( rootEntity )
39{
40 mEntityCastingShadowsLayer = new Qt3DRender::QLayer;
41 mEntityCastingShadowsLayer->setRecursive( true );
42 mEntityCastingShadowsLayer->setObjectName( mViewName + "::Layer" );
43
44 // shadow rendering pass
45 buildRenderPass();
46}
47
49{
51 mLayerFilter->setEnabled( enable );
52}
53
54Qt3DRender::QCamera *QgsShadowRenderView::lightCamera( int index )
55{
56 return mLightCameras[index];
57}
58
59void QgsShadowRenderView::buildRenderPass()
60{
61 mMapTextureArray = new Qt3DRender::QTexture2DArray;
62 mMapTextureArray->setWidth( mDefaultMapResolution );
63 mMapTextureArray->setHeight( mDefaultMapResolution );
64 mMapTextureArray->setLayers( Qgs3D::NUM_SHADOW_CASCADES );
65 mMapTextureArray->setFormat( Qt3DRender::QAbstractTexture::TextureFormat::DepthFormat );
66 mMapTextureArray->setGenerateMipMaps( false );
67 mMapTextureArray->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
68 mMapTextureArray->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
69 mMapTextureArray->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
70 mMapTextureArray->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
71 mMapTextureArray->setObjectName( mViewName + "::MapTextureArray" );
72
73 mLayerFilter = new Qt3DRender::QLayerFilter( mRendererEnabler );
74 mLayerFilter->addLayer( mEntityCastingShadowsLayer );
75
76 Qt3DRender::QClearBuffers *clearBuffers = new Qt3DRender::QClearBuffers( mLayerFilter );
77 clearBuffers->setBuffers( Qt3DRender::QClearBuffers::BufferType::DepthBuffer );
78
79 Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet( clearBuffers );
80
81 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
82 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
83 renderStateSet->addRenderState( depthTest );
84
85 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
86 cullFace->setMode( Qt3DRender::QCullFace::CullingMode::Front );
87 renderStateSet->addRenderState( cullFace );
88
89 Qt3DRender::QPolygonOffset *polygonOffset = new Qt3DRender::QPolygonOffset;
90 polygonOffset->setDepthSteps( 4.0 );
91 polygonOffset->setScaleFactor( 1.1 );
92 renderStateSet->addRenderState( polygonOffset );
93
94 // We are using "Cascading Shadow Maps" technique.
95 // Reading/watching which was useful during development:
96 // https://learnopengl.com/Guest-Articles/2021/CSM
97 // https://developer.download.nvidia.com/SDK/10.5/opengl/src/cascaded_shadow_maps/doc/cascaded_shadow_maps.pdf
98 // https://www.youtube.com/watch?v=Jhopq2lkzMQ
99 // https://www.youtube.com/watch?v=qbDrqARX07o
100 // https://web.archive.org/web/20170710150304/https://cesiumjs.org/presentations/ShadowsAndCesiumImplementation.pdf
101 for ( int i = 0; i < Qgs3D::NUM_SHADOW_CASCADES; ++i )
102 {
103 mLightCameras[i] = new Qt3DRender::QCamera( mRootEntity );
104 mLightCameras[i]->setObjectName( mViewName + QString( "::LightCamera_%1" ).arg( i ) );
105 mLightCameras[i]->setProjectionType( Qt3DRender::QCameraLens::ProjectionType::OrthographicProjection );
106
107 Qt3DRender::QCameraSelector *lightCameraSelector = new Qt3DRender::QCameraSelector( renderStateSet );
108 lightCameraSelector->setObjectName( mViewName + QString( "::CameraSelector_%1" ).arg( i ) );
109 lightCameraSelector->setCamera( mLightCameras[i] );
110
111 Qt3DRender::QRenderTargetSelector *renderTargetSelector = new Qt3DRender::QRenderTargetSelector( lightCameraSelector );
112
113 Qt3DRender::QRenderTargetOutput *output = new Qt3DRender::QRenderTargetOutput;
114 output->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
115 output->setTexture( mMapTextureArray );
116 output->setLayer( i );
117
118 Qt3DRender::QRenderTarget *renderTarget = new Qt3DRender::QRenderTarget;
119 renderTarget->setObjectName( mViewName + QString( "::RenderTarget_%1" ).arg( i ) );
120 renderTarget->addOutput( output );
121
122 renderTargetSelector->setTarget( renderTarget );
123 }
124}
125
127{
128 return mEntityCastingShadowsLayer;
129}
130
131void QgsShadowRenderView::setMapSize( int width, int height )
132{
133 mMapTextureArray->setSize( width, height );
134}
135
136Qt3DRender::QTexture2DArray *QgsShadowRenderView::mapTextureArray() const
137{
138 return mMapTextureArray;
139}
static constexpr int NUM_SHADOW_CASCADES
Number of shadow map cascades.
Definition qgs3d.h:104
Qt3DRender::QSubtreeEnabler * mRendererEnabler
virtual void setEnabled(bool enable)
Enable or disable via enable the render view sub tree.
QgsAbstractRenderView(const QString &viewName)
Constructor for QgsAbstractRenderView with the specified parent object.
Qt3DRender::QLayer * entityCastingShadowsLayer() const
Returns the layer to be used by entities to be included in this renderview.
Qt3DRender::QCamera * lightCamera(int index)
Returns the light camera with the specified index.
void setMapSize(int width, int height)
Update shadow depth texture size.
void setEnabled(bool enable) override
Enable or disable via enable the renderview sub tree.
Qt3DRender::QTexture2DArray * mapTextureArray() const
Returns the shadow depth texture array.
QgsShadowRenderView(const QString &viewName, Qt3DCore::QEntity *rootEntity)
Default constructor.