QGIS API Documentation 3.43.0-Master (b60ef06885e)
qgsforwardrenderview.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsforwardrenderview.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
17#include <Qt3DRender/QCamera>
18#include <Qt3DRender/QViewport>
19#include <Qt3DRender/QCameraSelector>
20#include <Qt3DRender/QLayerFilter>
21#include <Qt3DRender/QLayer>
22#include <Qt3DRender/QRenderTargetSelector>
23#include <Qt3DRender/QRenderTarget>
24#include <Qt3DRender/QTexture>
25#include <Qt3DRender/QClearBuffers>
26#include <Qt3DRender/QParameter>
27#include <Qt3DRender/QFrustumCulling>
28#include <Qt3DRender/QRenderStateSet>
29#include <Qt3DRender/QDepthTest>
30#include <Qt3DRender/QCullFace>
31#include <Qt3DRender/QPolygonOffset>
32#include <Qt3DRender/qsubtreeenabler.h>
33#include <Qt3DRender/QBlendEquation>
34#include <Qt3DRender/QColorMask>
35#include <Qt3DRender/QSortPolicy>
36#include <Qt3DRender/QNoDepthMask>
37#include <Qt3DRender/QBlendEquationArguments>
38#include <Qt3DRender/QClipPlane>
39
40#if QT_VERSION >= QT_VERSION_CHECK( 5, 15, 0 )
41#include <Qt3DRender/QDebugOverlay>
42#endif
43
44QgsForwardRenderView::QgsForwardRenderView( const QString &viewName, Qt3DRender::QCamera *mainCamera )
45 : QgsAbstractRenderView( viewName )
46 , mMainCamera( mainCamera )
47{
48 mRenderLayer = new Qt3DRender::QLayer;
49 mRenderLayer->setRecursive( true );
50 mRenderLayer->setObjectName( mViewName + "::Layer" );
51
52 mTransparentObjectsLayer = new Qt3DRender::QLayer;
53 mTransparentObjectsLayer->setRecursive( true );
54 mTransparentObjectsLayer->setObjectName( mViewName + "::TransparentLayer" );
55
56 // forward rendering pass
57 buildRenderPasses();
58}
59
60Qt3DRender::QRenderTarget *QgsForwardRenderView::buildTextures()
61{
62 mColorTexture = new Qt3DRender::QTexture2D;
63 mColorTexture->setFormat( Qt3DRender::QAbstractTexture::RGB8_UNorm );
64 mColorTexture->setGenerateMipMaps( false );
65 mColorTexture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
66 mColorTexture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
67 mColorTexture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
68 mColorTexture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
69
70 mDepthTexture = new Qt3DRender::QTexture2D;
71 mDepthTexture->setFormat( Qt3DRender::QTexture2D::TextureFormat::DepthFormat );
72 mDepthTexture->setGenerateMipMaps( false );
73 mDepthTexture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
74 mDepthTexture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
75 mDepthTexture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
76 mDepthTexture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
77
78 Qt3DRender::QRenderTarget *renderTarget = new Qt3DRender::QRenderTarget;
79 Qt3DRender::QRenderTargetOutput *renderTargetDepthOutput = new Qt3DRender::QRenderTargetOutput;
80 renderTargetDepthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
81 renderTargetDepthOutput->setTexture( mDepthTexture );
82 renderTarget->addOutput( renderTargetDepthOutput );
83
84 Qt3DRender::QRenderTargetOutput *renderTargetColorOutput = new Qt3DRender::QRenderTargetOutput;
85 renderTargetColorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
86 renderTargetColorOutput->setTexture( mColorTexture );
87 renderTarget->addOutput( renderTargetColorOutput );
88
89 return renderTarget;
90}
91
92/*
93 * We define three forward passes: one for solid objects, followed by two for transparent objects (one to write colors but no depths, one to write depths) :
94 *
95 * |
96 * +-----------------+
97 * | QCameraSelector | (using the main camera)
98 * +-----------------+
99 * |
100 * +-----------------+
101 * | QLayerFilter | (using mForwardRenderLayer)
102 * +-----------------+
103 * |
104 * +-----------------+
105 * | QRenderStateSet | define clip planes
106 * +-----------------+
107 * |
108 * +-----------------------+
109 * | QRenderTargetSelector | (write mForwardColorTexture + mForwardDepthTexture)
110 * +-----------------------+
111 * |
112 * +------------------------+---------------------+
113 * | |
114 * +-----------------+ discard +-----------------+ accept
115 * | QLayerFilter | transparent | QLayerFilter | transparent
116 * +-----------------+ objects +-----------------+ objects
117 * | |
118 * +-----------------+ use depth test +-----------------+ sort entities
119 * | QRenderStateSet | cull back faces | QSortPolicy | back to front
120 * +-----------------+ +-----------------+
121 * | |
122 * +-----------------+ +--------------------+--------------------+
123 * | QFrustumCulling | | |
124 * +-----------------+ +-----------------+ use depth tests +-----------------+ use depth tests
125 * | | QRenderStateSet | don't write depths | QRenderStateSet | write depths
126 * | +-----------------+ write colors +-----------------+ don't write colors
127 * +-----------------+ use alpha blending don't use alpha blending
128 * | QClearBuffers | color and depth no culling no culling
129 * +-----------------+
130 * |
131 * +-----------------+
132 * | QDebugOverlay |
133 * +-----------------+
134 *
135 */
136void QgsForwardRenderView::buildRenderPasses()
137{
138 mMainCameraSelector = new Qt3DRender::QCameraSelector( mRendererEnabler );
139 mMainCameraSelector->setObjectName( mViewName + "::CameraSelector" );
140 mMainCameraSelector->setCamera( mMainCamera );
141
142 mLayerFilter = new Qt3DRender::QLayerFilter( mMainCameraSelector );
143 mLayerFilter->addLayer( mRenderLayer );
144
145 mClipRenderStateSet = new Qt3DRender::QRenderStateSet( mLayerFilter );
146 mClipRenderStateSet->setObjectName( mViewName + "::Clip Plane RenderStateSet" );
147
148 Qt3DRender::QRenderTarget *renderTarget = buildTextures();
149
150 mRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mClipRenderStateSet );
151 mRenderTargetSelector->setTarget( renderTarget );
152
153 // first branch: opaque layer filter
154 Qt3DRender::QLayerFilter *opaqueObjectsFilter = new Qt3DRender::QLayerFilter( mRenderTargetSelector );
155 opaqueObjectsFilter->addLayer( mTransparentObjectsLayer );
156 opaqueObjectsFilter->setFilterMode( Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers );
157
158 Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet( opaqueObjectsFilter );
159
160 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
161 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
162 renderStateSet->addRenderState( depthTest );
163
164 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
165 cullFace->setMode( Qt3DRender::QCullFace::CullingMode::Back );
166 renderStateSet->addRenderState( cullFace );
167
168 mFrustumCulling = new Qt3DRender::QFrustumCulling( renderStateSet );
169
170 mClearBuffers = new Qt3DRender::QClearBuffers( mFrustumCulling );
171 mClearBuffers->setClearColor( QColor::fromRgbF( 0.0, 0.0, 1.0, 1.0 ) );
172 mClearBuffers->setBuffers( Qt3DRender::QClearBuffers::ColorDepthBuffer );
173 mClearBuffers->setClearDepthValue( 1.0f );
174
175 // second branch: transparent layer filter - color
176 Qt3DRender::QLayerFilter *transparentObjectsLayerFilter = new Qt3DRender::QLayerFilter( mRenderTargetSelector );
177 transparentObjectsLayerFilter->addLayer( mTransparentObjectsLayer );
178 transparentObjectsLayerFilter->setFilterMode( Qt3DRender::QLayerFilter::AcceptAnyMatchingLayers );
179
180 Qt3DRender::QSortPolicy *sortPolicy = new Qt3DRender::QSortPolicy( transparentObjectsLayerFilter );
181 QVector<Qt3DRender::QSortPolicy::SortType> sortTypes;
182 sortTypes.push_back( Qt3DRender::QSortPolicy::BackToFront );
183 sortPolicy->setSortTypes( sortTypes );
184
185 Qt3DRender::QRenderStateSet *transparentObjectsRenderStateSetColor = new Qt3DRender::QRenderStateSet( sortPolicy );
186 {
187 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
188 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
189 transparentObjectsRenderStateSetColor->addRenderState( depthTest );
190
191 Qt3DRender::QNoDepthMask *noDepthMask = new Qt3DRender::QNoDepthMask;
192 transparentObjectsRenderStateSetColor->addRenderState( noDepthMask );
193
194 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
195 cullFace->setMode( Qt3DRender::QCullFace::CullingMode::NoCulling );
196 transparentObjectsRenderStateSetColor->addRenderState( cullFace );
197
198 Qt3DRender::QBlendEquation *blendEquation = new Qt3DRender::QBlendEquation;
199 blendEquation->setBlendFunction( Qt3DRender::QBlendEquation::Add );
200 transparentObjectsRenderStateSetColor->addRenderState( blendEquation );
201
202 Qt3DRender::QBlendEquationArguments *blendEquationArgs = new Qt3DRender::QBlendEquationArguments;
203 blendEquationArgs->setSourceRgb( Qt3DRender::QBlendEquationArguments::Blending::SourceAlpha );
204 blendEquationArgs->setDestinationRgb( Qt3DRender::QBlendEquationArguments::Blending::OneMinusSourceAlpha );
205 transparentObjectsRenderStateSetColor->addRenderState( blendEquationArgs );
206 }
207
208 // third branch: transparent layer filter - depth
209 Qt3DRender::QRenderStateSet *transparentObjectsRenderStateSetDepth = new Qt3DRender::QRenderStateSet( sortPolicy );
210 {
211 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
212 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
213 transparentObjectsRenderStateSetDepth->addRenderState( depthTest );
214
215 Qt3DRender::QColorMask *noColorMask = new Qt3DRender::QColorMask;
216 noColorMask->setAlphaMasked( false );
217 noColorMask->setRedMasked( false );
218 noColorMask->setGreenMasked( false );
219 noColorMask->setBlueMasked( false );
220 transparentObjectsRenderStateSetDepth->addRenderState( noColorMask );
221
222 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
223 cullFace->setMode( Qt3DRender::QCullFace::CullingMode::NoCulling );
224 transparentObjectsRenderStateSetDepth->addRenderState( cullFace );
225 }
226
227 mDebugOverlay = new Qt3DRender::QDebugOverlay( mClearBuffers );
228 mDebugOverlay->setEnabled( false );
229}
230
231void QgsForwardRenderView::updateWindowResize( int width, int height )
232{
233 mColorTexture->setSize( width, height );
234 mDepthTexture->setSize( width, height );
235}
236
237
238void QgsForwardRenderView::setClearColor( const QColor &clearColor )
239{
240 mClearBuffers->setClearColor( clearColor );
241}
242
243
245{
246 if ( enabled == mFrustumCullingEnabled )
247 return;
248 mFrustumCullingEnabled = enabled;
249 mFrustumCulling->setEnabled( enabled );
250}
251
252
254{
255 mDebugOverlay->setEnabled( enabled );
256}
257
258Qt3DRender::QTexture2D *QgsForwardRenderView::depthTexture() const
259{
260 return mDepthTexture;
261}
262
263Qt3DRender::QTexture2D *QgsForwardRenderView::colorTexture() const
264{
265 return mColorTexture;
266}
267
269{
270 for ( Qt3DRender::QRenderState *state : mClipRenderStateSet->renderStates() )
271 {
272 if ( qobject_cast<Qt3DRender::QClipPlane *>( state ) )
273 {
274 mClipRenderStateSet->removeRenderState( state );
275 }
276 }
277}
278
280{
281 // remove existing QClipPlane
283
284 // create new QClipPlane
285 for ( int i = 0; i < nrClipPlanes; ++i )
286 {
287 Qt3DRender::QClipPlane *clipPlane = new Qt3DRender::QClipPlane;
288 clipPlane->setPlaneIndex( i );
289 mClipRenderStateSet->addRenderState( clipPlane );
290 }
291}
Base class for 3D render view.
Qt3DRender::QSubtreeEnabler * mRendererEnabler
void setClearColor(const QColor &clearColor)
Sets the clear color of the scene (background color)
Qt3DRender::QTexture2D * colorTexture() const
Returns forward color texture.
void setDebugOverlayEnabled(bool enabled)
Sets whether debug overlay is enabled.
virtual void updateWindowResize(int width, int height) override
Called when 3D window is resized.
void setFrustumCullingEnabled(bool enabled)
Sets whether frustum culling is enabled.
Qt3DRender::QTexture2D * depthTexture() const
Returns forward depth texture.
void addClipPlanes(int nrClipPlanes)
Setups nrClipPlanes clip planes in the forward pass to enable OpenGL clipping.
void removeClipPlanes()
Disables OpenGL clipping.
QgsForwardRenderView(const QString &viewName, Qt3DRender::QCamera *mainCamera)
Constructor with 3D scene camera.