QGIS API Documentation 4.1.0-Master (376402f9aeb)
Loading...
Searching...
No Matches
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
18#include <Qt3DRender/QBlendEquation>
19#include <Qt3DRender/QBlendEquationArguments>
20#include <Qt3DRender/QCamera>
21#include <Qt3DRender/QCameraSelector>
22#include <Qt3DRender/QClearBuffers>
23#include <Qt3DRender/QClipPlane>
24#include <Qt3DRender/QColorMask>
25#include <Qt3DRender/QCullFace>
26#include <Qt3DRender/QDebugOverlay>
27#include <Qt3DRender/QDepthTest>
28#include <Qt3DRender/QFrustumCulling>
29#include <Qt3DRender/QLayer>
30#include <Qt3DRender/QLayerFilter>
31#include <Qt3DRender/QMultiSampleAntiAliasing>
32#include <Qt3DRender/QNoDepthMask>
33#include <Qt3DRender/QParameter>
34#include <Qt3DRender/QPolygonOffset>
35#include <Qt3DRender/QRenderStateSet>
36#include <Qt3DRender/QRenderTarget>
37#include <Qt3DRender/QRenderTargetSelector>
38#include <Qt3DRender/QSortPolicy>
39#include <Qt3DRender/QTexture>
40#include <Qt3DRender/QViewport>
41#include <Qt3DRender/qsubtreeenabler.h>
42
43QgsForwardRenderView::QgsForwardRenderView( const QString &viewName, Qt3DRender::QCamera *mainCamera )
44 : QgsAbstractRenderView( viewName )
45 , mMainCamera( mainCamera )
46{
47 mRenderLayer = new Qt3DRender::QLayer;
48 mRenderLayer->setRecursive( true );
49 mRenderLayer->setObjectName( mViewName + "::Layer" );
50
51 mTransparentObjectsLayer = new Qt3DRender::QLayer;
52 mTransparentObjectsLayer->setRecursive( true );
53 mTransparentObjectsLayer->setObjectName( mViewName + "::TransparentLayer" );
54
55 mBackgroundLayer = new Qt3DRender::QLayer;
56 mBackgroundLayer->setRecursive( true );
57 mBackgroundLayer->setObjectName( mViewName + "::BackgroundLayer" );
58
59 // forward rendering pass
60 buildRenderPasses();
61}
62
63Qt3DRender::QRenderTarget *QgsForwardRenderView::buildTextures()
64{
65 mColorTexture = new Qt3DRender::QTexture2D;
66 mColorTexture->setFormat( Qt3DRender::QAbstractTexture::RGBA16F );
67 mColorTexture->setGenerateMipMaps( false );
68 mColorTexture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
69 mColorTexture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
70 mColorTexture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
71 mColorTexture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
72
73 mDepthTexture = new Qt3DRender::QTexture2D;
74 mDepthTexture->setFormat( Qt3DRender::QAbstractTexture::D24S8 );
75 mDepthTexture->setGenerateMipMaps( false );
76 mDepthTexture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
77 mDepthTexture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
78 mDepthTexture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::ClampToEdge );
79 mDepthTexture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::ClampToEdge );
80
81 Qt3DRender::QRenderTarget *renderTarget = new Qt3DRender::QRenderTarget;
82 Qt3DRender::QRenderTargetOutput *renderTargetDepthOutput = new Qt3DRender::QRenderTargetOutput;
83 renderTargetDepthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::DepthStencil );
84 renderTargetDepthOutput->setTexture( mDepthTexture );
85 renderTarget->addOutput( renderTargetDepthOutput );
86
87 Qt3DRender::QRenderTargetOutput *renderTargetColorOutput = new Qt3DRender::QRenderTargetOutput;
88 renderTargetColorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
89 renderTargetColorOutput->setTexture( mColorTexture );
90 renderTarget->addOutput( renderTargetColorOutput );
91
92 return renderTarget;
93}
94
95Qt3DRender::QRenderTarget *QgsForwardRenderView::buildMsaaTarget()
96{
97 mColorTextureMS = new Qt3DRender::QTexture2DMultisample;
98 mColorTextureMS->setFormat( Qt3DRender::QAbstractTexture::RGBA16F );
99 mColorTextureMS->setSamples( 4 );
100 mColorTextureMS->setGenerateMipMaps( false );
101 mColorTextureMS->setWidth( mCurrentWidth );
102 mColorTextureMS->setHeight( mCurrentHeight );
103
104 mDepthTextureMS = new Qt3DRender::QTexture2DMultisample;
105 mDepthTextureMS->setFormat( Qt3DRender::QAbstractTexture::D24S8 );
106 mDepthTextureMS->setSamples( 4 );
107 mDepthTextureMS->setGenerateMipMaps( false );
108 mDepthTextureMS->setWidth( mCurrentWidth );
109 mDepthTextureMS->setHeight( mCurrentHeight );
110
111 Qt3DRender::QRenderTarget *renderTarget = new Qt3DRender::QRenderTarget;
112 Qt3DRender::QRenderTargetOutput *msaaDepthOutput = new Qt3DRender::QRenderTargetOutput;
113 msaaDepthOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::DepthStencil );
114 msaaDepthOutput->setTexture( mDepthTextureMS );
115 renderTarget->addOutput( msaaDepthOutput );
116
117 Qt3DRender::QRenderTargetOutput *msaaColorOutput = new Qt3DRender::QRenderTargetOutput;
118 msaaColorOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );
119 msaaColorOutput->setTexture( mColorTextureMS );
120 renderTarget->addOutput( msaaColorOutput );
121
122 return renderTarget;
123}
124
125/*
126 * We define four forward passes: one for solid objects, one for background (gradient/skybox),
127 * followed by two for transparent objects (one to write colors but no depths, one to write depths) :
128 *
129 * |
130 * +-----------------+
131 * | QCameraSelector | (using the main camera)
132 * +-----------------+
133 * |
134 * +-----------------+
135 * | QLayerFilter | (using mRenderLayer)
136 * +-----------------+
137 * |
138 * +-----------------+
139 * | QRenderStateSet | define clip planes (MSAA on/off)
140 * +-----------------+
141 * |
142 * +-----------------------+
143 * | QRenderTargetSelector | (write mColorTexture + mDepthTexture)
144 * +-----------------------+
145 * |
146 * +------------------------+----------+---------------------+
147 * | | |
148 * +-----------------+ discard +-----------------+ +-----------------+ accept
149 * | QLayerFilter | transparent | QLayerFilter | | QLayerFilter | transparent
150 * +-----------------+ +-----------------+ +-----------------+ objects
151 * | (background) |
152 * +-----------------+ use depth test +-----------------+ sort entities
153 * | QRenderStateSet | cull back faces | QSortPolicy | back to front
154 * +-----------------+ +-----------------+
155 * | |
156 * +-----------------+ +---------------------+---------------------+
157 * | QFrustumCulling | | |
158 * +-----------------+ +-----------------+ use depth tests +-----------------+ use depth tests
159 * | | QRenderStateSet | don't write depths | QRenderStateSet | write depths
160 * | +-----------------+ write colors +-----------------+ don't write colors
161 * +-----------------+ use alpha blending don't use alpha blending
162 * | QClearBuffers | color and depth no culling no culling
163 * +-----------------+
164 * |
165 * +-----------------+
166 * | QDebugOverlay |
167 * +-----------------+
168 *
169 */
170void QgsForwardRenderView::buildRenderPasses()
171{
172 mMainCameraSelector = new Qt3DRender::QCameraSelector( mRendererEnabler );
173 mMainCameraSelector->setObjectName( mViewName + "::CameraSelector" );
174 mMainCameraSelector->setCamera( mMainCamera );
175
176 mLayerFilter = new Qt3DRender::QLayerFilter( mMainCameraSelector );
177 mLayerFilter->addLayer( mRenderLayer );
178
179 mClipRenderStateSet = new Qt3DRender::QRenderStateSet( mLayerFilter );
180 mClipRenderStateSet->setObjectName( mViewName + "::Clip Plane RenderStateSet" );
181
182 mMsaaRenderState = new Qt3DRender::QMultiSampleAntiAliasing;
183 mMsaaRenderState->setEnabled( false );
184 mClipRenderStateSet->addRenderState( mMsaaRenderState );
185
186 mRegularRenderTarget = buildTextures();
187
188 mRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mClipRenderStateSet );
189 mRenderTargetSelector->setTarget( mRegularRenderTarget );
190
191 // first branch: opaque layer filter
192 Qt3DRender::QLayerFilter *opaqueObjectsFilter = new Qt3DRender::QLayerFilter( mRenderTargetSelector );
193 opaqueObjectsFilter->addLayer( mTransparentObjectsLayer );
194 opaqueObjectsFilter->addLayer( mBackgroundLayer );
195 opaqueObjectsFilter->setFilterMode( Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers );
196
197 Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet( opaqueObjectsFilter );
198
199 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
200 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
201 renderStateSet->addRenderState( depthTest );
202
203 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
204 cullFace->setMode( Qt3DRender::QCullFace::CullingMode::Back );
205 renderStateSet->addRenderState( cullFace );
206
207 mFrustumCulling = new Qt3DRender::QFrustumCulling( renderStateSet );
208
209 mClearBuffers = new Qt3DRender::QClearBuffers( mFrustumCulling );
210 mClearBuffers->setClearColor( QColor::fromRgbF( 0.0, 0.0, 1.0, 1.0 ) );
211 mClearBuffers->setBuffers( Qt3DRender::QClearBuffers::ColorDepthBuffer );
212 mClearBuffers->setClearDepthValue( 1.0f );
213
214 mDebugOverlay = new Qt3DRender::QDebugOverlay( mClearBuffers );
215 mDebugOverlay->setEnabled( false );
216
217 // second branch: background (gradient/skybox)
218 Qt3DRender::QLayerFilter *backgroundLayerFilter = new Qt3DRender::QLayerFilter( mRenderTargetSelector );
219 backgroundLayerFilter->addLayer( mBackgroundLayer );
220
221 // third branch: transparent layer filter - color
222 Qt3DRender::QLayerFilter *transparentObjectsLayerFilter = new Qt3DRender::QLayerFilter( mRenderTargetSelector );
223 transparentObjectsLayerFilter->addLayer( mTransparentObjectsLayer );
224 transparentObjectsLayerFilter->setFilterMode( Qt3DRender::QLayerFilter::AcceptAnyMatchingLayers );
225
226 Qt3DRender::QSortPolicy *sortPolicy = new Qt3DRender::QSortPolicy( transparentObjectsLayerFilter );
227 QVector<Qt3DRender::QSortPolicy::SortType> sortTypes;
228 sortTypes.push_back( Qt3DRender::QSortPolicy::BackToFront );
229 sortPolicy->setSortTypes( sortTypes );
230
231 Qt3DRender::QRenderStateSet *transparentObjectsRenderStateSetColor = new Qt3DRender::QRenderStateSet( sortPolicy );
232 {
233 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
234 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
235 transparentObjectsRenderStateSetColor->addRenderState( depthTest );
236
237 Qt3DRender::QNoDepthMask *noDepthMask = new Qt3DRender::QNoDepthMask;
238 transparentObjectsRenderStateSetColor->addRenderState( noDepthMask );
239
240 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
241 cullFace->setMode( Qt3DRender::QCullFace::CullingMode::NoCulling );
242 transparentObjectsRenderStateSetColor->addRenderState( cullFace );
243
244 Qt3DRender::QBlendEquation *blendEquation = new Qt3DRender::QBlendEquation;
245 blendEquation->setBlendFunction( Qt3DRender::QBlendEquation::Add );
246 transparentObjectsRenderStateSetColor->addRenderState( blendEquation );
247
248 Qt3DRender::QBlendEquationArguments *blendEquationArgs = new Qt3DRender::QBlendEquationArguments;
249 blendEquationArgs->setSourceRgb( Qt3DRender::QBlendEquationArguments::Blending::SourceAlpha );
250 blendEquationArgs->setDestinationRgb( Qt3DRender::QBlendEquationArguments::Blending::OneMinusSourceAlpha );
251 transparentObjectsRenderStateSetColor->addRenderState( blendEquationArgs );
252 }
253
254 // fourth branch: transparent layer filter - depth
255 Qt3DRender::QRenderStateSet *transparentObjectsRenderStateSetDepth = new Qt3DRender::QRenderStateSet( sortPolicy );
256 {
257 Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
258 depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less );
259 transparentObjectsRenderStateSetDepth->addRenderState( depthTest );
260
261 Qt3DRender::QColorMask *noColorMask = new Qt3DRender::QColorMask;
262 noColorMask->setAlphaMasked( false );
263 noColorMask->setRedMasked( false );
264 noColorMask->setGreenMasked( false );
265 noColorMask->setBlueMasked( false );
266 transparentObjectsRenderStateSetDepth->addRenderState( noColorMask );
267
268 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
269 cullFace->setMode( Qt3DRender::QCullFace::CullingMode::NoCulling );
270 transparentObjectsRenderStateSetDepth->addRenderState( cullFace );
271 }
272}
273
274void QgsForwardRenderView::updateWindowResize( int width, int height )
275{
276 mCurrentWidth = width; // we need to store and update the attributes so we can set msaa textures w and h when enabled
277 mCurrentHeight = height;
278 mColorTexture->setSize( width, height );
279 mDepthTexture->setSize( width, height );
280 if ( mColorTextureMS )
281 {
282 mColorTextureMS->setWidth( width );
283 mColorTextureMS->setHeight( height );
284 mDepthTextureMS->setWidth( width );
285 mDepthTextureMS->setHeight( height );
286 }
287}
288
289
290void QgsForwardRenderView::setClearColor( const QColor &clearColor )
291{
292 mClearBuffers->setClearColor( clearColor );
293}
294
295
297{
298 if ( enabled == mFrustumCullingEnabled )
299 return;
300 mFrustumCullingEnabled = enabled;
301 mFrustumCulling->setEnabled( enabled );
302}
303
304
306{
307 mDebugOverlay->setEnabled( enabled );
308}
309
311{
312 if ( enabled && !mMsaaRenderTarget )
313 mMsaaRenderTarget = buildMsaaTarget();
314 mMsaaRenderState->setEnabled( enabled );
315 mRenderTargetSelector->setTarget( enabled ? mMsaaRenderTarget : mRegularRenderTarget );
316 if ( !enabled )
317 {
318 delete mMsaaRenderTarget;
319 mMsaaRenderTarget = nullptr;
320 mColorTextureMS = nullptr;
321 mDepthTextureMS = nullptr;
322 }
323}
324
325Qt3DRender::QTexture2D *QgsForwardRenderView::depthTexture() const
326{
327 return mDepthTexture;
328}
329
330Qt3DRender::QTexture2D *QgsForwardRenderView::colorTexture() const
331{
332 return mColorTexture;
333}
334
336{
337 for ( Qt3DRender::QRenderState *state : mClipRenderStateSet->renderStates() )
338 {
339 if ( qobject_cast<Qt3DRender::QClipPlane *>( state ) )
340 {
341 mClipRenderStateSet->removeRenderState( state );
342 }
343 }
344}
345
347{
348 // remove existing QClipPlane
350
351 // create new QClipPlane
352 for ( int i = 0; i < nrClipPlanes; ++i )
353 {
354 Qt3DRender::QClipPlane *clipPlane = new Qt3DRender::QClipPlane;
355 clipPlane->setPlaneIndex( i );
356 mClipRenderStateSet->addRenderState( clipPlane );
357 }
358}
Qt3DRender::QSubtreeEnabler * mRendererEnabler
QgsAbstractRenderView(const QString &viewName)
Constructor for QgsAbstractRenderView with the specified parent object.
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.
void setMsaaEnabled(bool enabled)
Sets whether multisample anti-aliasing (MSAA) is enabled.
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.