From e24f5cbbef615d94dda7cfc2d6dd578601e815b4 Mon Sep 17 00:00:00 2001 From: NEDJIMAbelgacem Date: Tue, 10 May 2022 13:36:35 +0100 Subject: [PATCH] Add transparency support for phong materials --- .../materials/qgsphongmaterialsettings.sip.in | 16 +++ src/3d/materials/qgsphongmaterialsettings.cpp | 21 ++++ src/3d/materials/qgsphongmaterialsettings.h | 15 +++ src/3d/qgs3dmapscene.cpp | 14 +++ src/3d/qgsshadowrenderingframegraph.cpp | 55 +++++++-- src/3d/qgsshadowrenderingframegraph.h | 7 ++ src/app/3d/qgsphongmaterialwidget.cpp | 7 ++ src/ui/3d/phongmaterialwidget.ui | 89 +++++++++----- src/ui/3d/phongtexturedmaterialwidgetbase.ui | 116 ++++++++++-------- 9 files changed, 254 insertions(+), 86 deletions(-) diff --git a/python/3d/auto_generated/materials/qgsphongmaterialsettings.sip.in b/python/3d/auto_generated/materials/qgsphongmaterialsettings.sip.in index 9f529c00a73..fab073363da 100644 --- a/python/3d/auto_generated/materials/qgsphongmaterialsettings.sip.in +++ b/python/3d/auto_generated/materials/qgsphongmaterialsettings.sip.in @@ -66,6 +66,13 @@ Returns specular color component float shininess() const; %Docstring Returns shininess of the surface +%End + + float opacity() const; +%Docstring +Returns the opacity of the surface + +.. versionadded:: 3.26 %End virtual QMap toExportParameters() const; @@ -88,6 +95,15 @@ Sets specular color component Sets shininess of the surface %End + void setOpacity( float opacity ); +%Docstring +Sets shininess of the surface + +.. versionadded:: 3.26 +%End + + + virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context ); virtual void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const; diff --git a/src/3d/materials/qgsphongmaterialsettings.cpp b/src/3d/materials/qgsphongmaterialsettings.cpp index ebbec217a1d..18954cfbe17 100644 --- a/src/3d/materials/qgsphongmaterialsettings.cpp +++ b/src/3d/materials/qgsphongmaterialsettings.cpp @@ -20,6 +20,7 @@ #include "qgsimagecache.h" #include #include +#include #include #include #include @@ -69,6 +70,7 @@ void QgsPhongMaterialSettings::readXml( const QDomElement &elem, const QgsReadWr mDiffuse = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "diffuse" ), QStringLiteral( "178,178,178" ) ) ); mSpecular = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "specular" ), QStringLiteral( "255,255,255" ) ) ); mShininess = elem.attribute( QStringLiteral( "shininess" ) ).toFloat(); + mOpacity = elem.attribute( QStringLiteral( "opacity" ), QStringLiteral( "1.0" ) ).toFloat(); QgsAbstractMaterialSettings::readXml( elem, context ); } @@ -79,6 +81,7 @@ void QgsPhongMaterialSettings::writeXml( QDomElement &elem, const QgsReadWriteCo elem.setAttribute( QStringLiteral( "diffuse" ), QgsSymbolLayerUtils::encodeColor( mDiffuse ) ); elem.setAttribute( QStringLiteral( "specular" ), QgsSymbolLayerUtils::encodeColor( mSpecular ) ); elem.setAttribute( QStringLiteral( "shininess" ), mShininess ); + elem.setAttribute( QStringLiteral( "opacity" ), mOpacity ); QgsAbstractMaterialSettings::writeXml( elem, context ); } @@ -98,6 +101,24 @@ Qt3DRender::QMaterial *QgsPhongMaterialSettings::toMaterial( QgsMaterialSettings if ( dataDefinedProperties().hasActiveProperties() ) return dataDefinedMaterial(); + if ( mOpacity != 1 ) + { + Qt3DExtras::QPhongAlphaMaterial *material = new Qt3DExtras::QPhongAlphaMaterial; + material->setDiffuse( mDiffuse ); + material->setAmbient( mAmbient ); + material->setSpecular( mSpecular ); + material->setShininess( mShininess ); + material->setAlpha( mOpacity ); + + if ( context.isSelected() ) + { + // update the material with selection colors + material->setDiffuse( context.selectionColor() ); + material->setAmbient( context.selectionColor().darker() ); + } + return material; + } + Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial; material->setDiffuse( mDiffuse ); material->setAmbient( mAmbient ); diff --git a/src/3d/materials/qgsphongmaterialsettings.h b/src/3d/materials/qgsphongmaterialsettings.h index 6eccd85bbfa..97a1828d4f5 100644 --- a/src/3d/materials/qgsphongmaterialsettings.h +++ b/src/3d/materials/qgsphongmaterialsettings.h @@ -73,6 +73,12 @@ class _3D_EXPORT QgsPhongMaterialSettings : public QgsAbstractMaterialSettings //! Returns shininess of the surface float shininess() const { return mShininess; } + /** + * Returns the opacity of the surface + * \since QGIS 3.26 + */ + float opacity() const { return mOpacity; } + QMap toExportParameters() const override; //! Sets ambient color component @@ -84,6 +90,14 @@ class _3D_EXPORT QgsPhongMaterialSettings : public QgsAbstractMaterialSettings //! Sets shininess of the surface void setShininess( float shininess ) { mShininess = shininess; } + /** + * Sets shininess of the surface + * \since QGIS 3.26 + */ + void setOpacity( float opacity ) { mOpacity = opacity; } + + + void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override; void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override; @@ -110,6 +124,7 @@ class _3D_EXPORT QgsPhongMaterialSettings : public QgsAbstractMaterialSettings QColor mDiffuse{ QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) }; QColor mSpecular{ QColor::fromRgbF( 1.0f, 1.0f, 1.0f, 1.0f ) }; float mShininess = 0.0f; + float mOpacity = 1.0f; //! Constructs a material from shader files Qt3DRender::QMaterial *dataDefinedMaterial() const; diff --git a/src/3d/qgs3dmapscene.cpp b/src/3d/qgs3dmapscene.cpp index dd181e2f5a1..f38bbb567fa 100644 --- a/src/3d/qgs3dmapscene.cpp +++ b/src/3d/qgs3dmapscene.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -911,6 +912,19 @@ void Qgs3DMapScene::finalizeNewEntity( Qt3DCore::QEntity *newEntity ) bm->setViewportSize( mCameraController->viewport().size() ); } + + // Finalize adding the 3D transparent objects by adding the layer components to the entities + for ( Qt3DExtras::QPhongAlphaMaterial *ph : newEntity->findChildren() ) + { + Qt3DCore::QEntity *entity = qobject_cast( ph->parent() ); + if ( !entity ) + continue; + QgsShadowRenderingFrameGraph *frameGraph = mEngine->frameGraph(); + Qt3DRender::QLayer *layer = frameGraph->transparentObjectLayer(); + if ( entity->components().contains( layer ) ) + continue; + entity->addComponent( layer ); + } } int Qgs3DMapScene::maximumTextureSize() const diff --git a/src/3d/qgsshadowrenderingframegraph.cpp b/src/3d/qgsshadowrenderingframegraph.cpp index 94a51ad670a..f5724c41358 100644 --- a/src/3d/qgsshadowrenderingframegraph.cpp +++ b/src/3d/qgsshadowrenderingframegraph.cpp @@ -26,7 +26,8 @@ #include #include #include - +#include +#include Qt3DRender::QFrameGraphNode *QgsShadowRenderingFrameGraph::constructTexturesPreviewPass() { @@ -46,6 +47,14 @@ Qt3DRender::QFrameGraphNode *QgsShadowRenderingFrameGraph::constructTexturesPrev Qt3DRender::QFrameGraphNode *QgsShadowRenderingFrameGraph::constructForwardRenderPass() { + // The branch structure: + // mMainCameraSelector + // mForwardRenderLayerFilter + // mForwardRenderTargetSelector + // opaqueObjectsFilter | transparentObjectsLayerFilter + // forwaredRenderStateSet | sortPolicy + // mFrustumCulling | transparentObjectsRenderStateSet + // mForwardClearBuffers | mMainCameraSelector = new Qt3DRender::QCameraSelector; mMainCameraSelector->setCamera( mMainCamera ); @@ -85,12 +94,11 @@ Qt3DRender::QFrameGraphNode *QgsShadowRenderingFrameGraph::constructForwardRende mForwardRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mForwardRenderLayerFilter ); mForwardRenderTargetSelector->setTarget( forwardRenderTarget ); - mForwardClearBuffers = new Qt3DRender::QClearBuffers( mForwardRenderTargetSelector ); - mForwardClearBuffers->setClearColor( QColor::fromRgbF( 0.0, 0.0, 1.0, 1.0 ) ); - mForwardClearBuffers->setBuffers( Qt3DRender::QClearBuffers::ColorDepthBuffer ); - mForwardClearBuffers->setClearDepthValue( 1.0f ); + Qt3DRender::QLayerFilter *opaqueObjectsFilter = new Qt3DRender::QLayerFilter( mForwardRenderTargetSelector ); + opaqueObjectsFilter->addLayer( mTransparentObjectsPassLayer ); + opaqueObjectsFilter->setFilterMode( Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers ); - Qt3DRender::QRenderStateSet *forwaredRenderStateSet = new Qt3DRender::QRenderStateSet( mForwardClearBuffers ); + Qt3DRender::QRenderStateSet *forwaredRenderStateSet = new Qt3DRender::QRenderStateSet( opaqueObjectsFilter ); Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest; depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less ); @@ -102,6 +110,38 @@ Qt3DRender::QFrameGraphNode *QgsShadowRenderingFrameGraph::constructForwardRende mFrustumCulling = new Qt3DRender::QFrustumCulling( forwaredRenderStateSet ); + mForwardClearBuffers = new Qt3DRender::QClearBuffers( mFrustumCulling ); + mForwardClearBuffers->setClearColor( QColor::fromRgbF( 0.0, 0.0, 1.0, 1.0 ) ); + mForwardClearBuffers->setBuffers( Qt3DRender::QClearBuffers::ColorDepthBuffer ); + mForwardClearBuffers->setClearDepthValue( 1.0f ); + + Qt3DRender::QLayerFilter *transparentObjectsLayerFilter = new Qt3DRender::QLayerFilter( mForwardRenderTargetSelector ); + transparentObjectsLayerFilter->addLayer( mTransparentObjectsPassLayer ); + transparentObjectsLayerFilter->setFilterMode( Qt3DRender::QLayerFilter::AcceptAnyMatchingLayers ); + + Qt3DRender::QSortPolicy *sortPolicy = new Qt3DRender::QSortPolicy( transparentObjectsLayerFilter ); + QVector sortTypes; + sortTypes.push_back( Qt3DRender::QSortPolicy::BackToFront ); + sortTypes.push_back( Qt3DRender::QSortPolicy::Material ); + sortTypes.push_back( Qt3DRender::QSortPolicy::StateChangeCost ); + sortTypes.push_back( Qt3DRender::QSortPolicy::FrontToBack ); + sortPolicy->setSortTypes( sortTypes ); + + Qt3DRender::QRenderStateSet *transparentObjectsRenderStateSet = new Qt3DRender::QRenderStateSet( sortPolicy ); + { + Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest; + depthTest->setDepthFunction( Qt3DRender::QDepthTest::Less ); + transparentObjectsRenderStateSet->addRenderState( depthTest ); + + Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace; + cullFace->setMode( Qt3DRender::QCullFace::CullingMode::NoCulling ); + transparentObjectsRenderStateSet->addRenderState( cullFace ); + + Qt3DRender::QBlendEquation *blendEquation = new Qt3DRender::QBlendEquation; + blendEquation->setBlendFunction( Qt3DRender::QBlendEquation::Subtract ); + transparentObjectsRenderStateSet->addRenderState( blendEquation ); + } + return mMainCameraSelector; } @@ -352,13 +392,14 @@ QgsShadowRenderingFrameGraph::QgsShadowRenderingFrameGraph( QSurface *surface, Q mCastShadowsLayer = new Qt3DRender::QLayer; mForwardRenderLayer = new Qt3DRender::QLayer; mDepthRenderPassLayer = new Qt3DRender::QLayer; - + mTransparentObjectsPassLayer = new Qt3DRender::QLayer; mPostprocessPassLayer->setRecursive( true ); mPreviewLayer->setRecursive( true ); mCastShadowsLayer->setRecursive( true ); mForwardRenderLayer->setRecursive( true ); mDepthRenderPassLayer->setRecursive( true ); + mTransparentObjectsPassLayer->setRecursive( true ); mRenderSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector; diff --git a/src/3d/qgsshadowrenderingframegraph.h b/src/3d/qgsshadowrenderingframegraph.h index 15d52959470..d7ae64a63d2 100644 --- a/src/3d/qgsshadowrenderingframegraph.h +++ b/src/3d/qgsshadowrenderingframegraph.h @@ -78,6 +78,12 @@ class QgsShadowRenderingFrameGraph : public Qt3DCore::QEntity //! Returns a layer object used to indicate that an entity will be rendered during the forward rendering pass Qt3DRender::QLayer *forwardRenderLayer() { return mForwardRenderLayer; } + /** + * Returns a layer object used to indicate that the object is transparent + * \since QGIS 3.26 + */ + Qt3DRender::QLayer *transparentObjectLayer() { return mTransparentObjectsPassLayer; } + //! Returns the main camera Qt3DRender::QCamera *mainCamera() { return mMainCamera; } //! Returns the light camera @@ -220,6 +226,7 @@ class QgsShadowRenderingFrameGraph : public Qt3DCore::QEntity Qt3DRender::QLayer *mForwardRenderLayer = nullptr; Qt3DRender::QLayer *mCastShadowsLayer = nullptr; Qt3DRender::QLayer *mDepthRenderPassLayer = nullptr; + Qt3DRender::QLayer *mTransparentObjectsPassLayer = nullptr; QgsPostprocessingEntity *mPostprocessingEntity = nullptr; diff --git a/src/app/3d/qgsphongmaterialwidget.cpp b/src/app/3d/qgsphongmaterialwidget.cpp index 667e288d72b..1a135c3cd3c 100644 --- a/src/app/3d/qgsphongmaterialwidget.cpp +++ b/src/app/3d/qgsphongmaterialwidget.cpp @@ -33,6 +33,11 @@ QgsPhongMaterialWidget::QgsPhongMaterialWidget( QWidget *parent ) connect( mAmbientDataDefinedButton, &QgsPropertyOverrideButton::changed, this, &QgsPhongMaterialWidget::changed ); connect( mDiffuseDataDefinedButton, &QgsPropertyOverrideButton::changed, this, &QgsPhongMaterialWidget::changed ); connect( mSpecularDataDefinedButton, &QgsPropertyOverrideButton::changed, this, &QgsPhongMaterialWidget::changed ); + connect( mOpacitySlider, &QSlider::valueChanged, this, &QgsPhongMaterialWidget::changed ); + connect( mOpacitySlider, &QSlider::valueChanged, this, [&]( int value ) + { + mOpacityPercentageLabel->setText( QStringLiteral( "%1%" ).arg( value ) ); + } ); } QgsMaterialSettingsWidget *QgsPhongMaterialWidget::create() @@ -100,6 +105,7 @@ void QgsPhongMaterialWidget::setSettings( const QgsAbstractMaterialSettings *set btnAmbient->setColor( phongMaterial->ambient() ); btnSpecular->setColor( phongMaterial->specular() ); spinShininess->setValue( phongMaterial->shininess() ); + mOpacitySlider->setValue( phongMaterial->opacity() * 100.0 ); mPropertyCollection = settings->dataDefinedProperties(); @@ -115,6 +121,7 @@ QgsAbstractMaterialSettings *QgsPhongMaterialWidget::settings() m->setAmbient( btnAmbient->color() ); m->setSpecular( btnSpecular->color() ); m->setShininess( spinShininess->value() ); + m->setOpacity( mOpacitySlider->value() / 100.0 ); mPropertyCollection.setProperty( QgsAbstractMaterialSettings::Diffuse, mDiffuseDataDefinedButton->toProperty() ); mPropertyCollection.setProperty( QgsAbstractMaterialSettings::Ambient, mAmbientDataDefinedButton->toProperty() ); diff --git a/src/ui/3d/phongmaterialwidget.ui b/src/ui/3d/phongmaterialwidget.ui index 0693b4d942c..b54488d857d 100644 --- a/src/ui/3d/phongmaterialwidget.ui +++ b/src/ui/3d/phongmaterialwidget.ui @@ -14,13 +14,20 @@ Form - - + + + + ... + + + + + - How shiny smooth surfaces are. + Color of light reflected from rough surfaces. - Shininess + Diffuse @@ -56,6 +63,37 @@ + + + + 1000.000000000000000 + + + + + + + ... + + + + + + + How shiny smooth surfaces are. + + + Shininess + + + + + + + ... + + + @@ -66,23 +104,6 @@ - - - - Color of light reflected from rough surfaces. - - - Diffuse - - - - - - - 1000.000000000000000 - - - @@ -109,24 +130,30 @@ - - - - ... + + + + 100 + + + 100 + + + Qt::Horizontal - - + + - ... + Opacity - - + + - ... + 100% diff --git a/src/ui/3d/phongtexturedmaterialwidgetbase.ui b/src/ui/3d/phongtexturedmaterialwidgetbase.ui index a96e778356e..f68b3b53fbe 100644 --- a/src/ui/3d/phongtexturedmaterialwidgetbase.ui +++ b/src/ui/3d/phongtexturedmaterialwidgetbase.ui @@ -15,18 +15,21 @@ - + - ° + % - -360.000000000000000 + 0.010000000000000 - 360.000000000000000 + 100000.000000000000000 - 0.500000000000000 + 1.000000000000000 + + + 100.000000000000000 @@ -37,16 +40,6 @@ - - - - Color of light reflecting from smooth surfaces. - - - Specular - - - @@ -63,29 +56,23 @@ - - + + + + + + + Color of light reflecting from smooth surfaces. + - Texture scale + Specular - - - - % - - - 0.010000000000000 - - - 100000.000000000000000 - - - 1.000000000000000 - - - 100.000000000000000 + + + + Texture rotation @@ -99,6 +86,23 @@ + + + + Texture scale + + + + + + + How shiny smooth surfaces are. + + + Shininess + + + @@ -115,30 +119,46 @@ - - + + - Texture rotation + Diffuse texture - - - - How shiny smooth surfaces are. + + + + ° + + -360.000000000000000 + + + 360.000000000000000 + + + 0.500000000000000 + + + + + - Shininess + Opacity - - - - - - Diffuse texture + + + 100 + + + 100 + + + Qt::Horizontal