Skip to content

Commit

Permalink
[3d][FEATURE] Add CAD style ("Gooch") material for polygons/extruded …
Browse files Browse the repository at this point in the history
…lines

From the qt docs:

"The Gooch lighting model uses both color and brightness to help show the
curvature of 3D surfaces. This is often better than models such as Phong
that rely purely upon changes in brightness. In situations such as in CAD
and CAM applications where photorealism is not a goal, the Gooch shading
model in conjunction with some kind of silhouette edge inking is a popular
solution.

The Gooch lighting model is explained fully in the original Gooch paper.
The Gooch model mixes a diffuse object color with a user-provided cool
color and warm color to produce the end points of a color ramp that is
used to shade the object based upon the cosine of the angle between the
vector from the fragment to the light source and the fragment's normal
vector. Optionally, a specular highlight can be added on top. The
relative contributions to the cool and warm colors by the diffuse color
are controlled by the alpha and beta properties respecitvely."""

The TLDR: the shader works well for revealing 3d details of objects
which may otherwise be hidden due to the scene's lighting. Ultimately,
it's an easier material to work with as you don't need to worry
about setting up appropriate scene lighting in order to visualise features.
  • Loading branch information
nyalldawson committed Aug 3, 2020
1 parent d9af7f7 commit 51cde6f
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 76 deletions.
1 change: 1 addition & 0 deletions images/images.qrc
Expand Up @@ -881,6 +881,7 @@
<file>themes/default/mIconAlignTop.svg</file>
<file>themes/default/mIconAlignVCenter.svg</file>
<file>themes/default/mIconPhongMaterial.svg</file>
<file>themes/default/mIconGoochMaterial.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
Expand Down
85 changes: 85 additions & 0 deletions images/themes/default/mIconGoochMaterial.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions python/3d/auto_generated/qgsphongmaterialsettings.sip.in
Expand Up @@ -36,7 +36,11 @@ Constructor for QgsPhongMaterialSettings.

virtual QString type() const;


static bool supportsTechnique( QgsMaterialSettingsRenderingTechnique technique );
%Docstring
Returns ``True`` if the specified ``technique`` is suppored by the Phong material.
%End

static QgsAbstractMaterialSettings *create() /Factory/;
%Docstring
Expand Down
2 changes: 1 addition & 1 deletion src/3d/qgs3d.cpp
Expand Up @@ -69,7 +69,7 @@ void Qgs3D::initialize()
instance()->materialRegistry()->addMaterialSettingsType( new QgsMaterialSettingsMetadata( QStringLiteral( "phong" ), QObject::tr( "Realistic (Phong)" ),
QgsPhongMaterialSettings::create, QgsPhongMaterialSettings::supportsTechnique, nullptr, QgsApplication::getThemeIcon( QStringLiteral( "/mIconPhongMaterial.svg" ) ) ) );
instance()->materialRegistry()->addMaterialSettingsType( new QgsMaterialSettingsMetadata( QStringLiteral( "gooch" ), QObject::tr( "CAD (Gooch)" ),
QgsGoochMaterialSettings::create, nullptr ) );
QgsGoochMaterialSettings::create, QgsGoochMaterialSettings::supportsTechnique, nullptr, QgsApplication::getThemeIcon( QStringLiteral( "/mIconGoochMaterial.svg" ) ) ) );

// because we are usually populating the 3d registry AFTER QgsApplication initialisation, we need to defer creation
// of 3d symbols in the default style until now
Expand Down
71 changes: 46 additions & 25 deletions src/3d/qgsgoochmaterialsettings.cpp
Expand Up @@ -29,6 +29,21 @@ QgsAbstractMaterialSettings *QgsGoochMaterialSettings::create()
return new QgsGoochMaterialSettings();
}

bool QgsGoochMaterialSettings::supportsTechnique( QgsMaterialSettingsRenderingTechnique technique )
{
switch ( technique )
{
case QgsMaterialSettingsRenderingTechnique::Triangles:
return true;

case QgsMaterialSettingsRenderingTechnique::Lines:
case QgsMaterialSettingsRenderingTechnique::InstancedPoints:
case QgsMaterialSettingsRenderingTechnique::Points:
return false;
}
return false;
}

QgsGoochMaterialSettings *QgsGoochMaterialSettings::clone() const
{
return new QgsGoochMaterialSettings( *this );
Expand All @@ -40,7 +55,9 @@ void QgsGoochMaterialSettings::readXml( const QDomElement &elem, const QgsReadWr
mCool = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "cool" ), QStringLiteral( "255,130,0" ) ) );
mDiffuse = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "diffuse" ), QStringLiteral( "178,178,178" ) ) );
mSpecular = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "specular" ) ) );
mShininess = elem.attribute( QStringLiteral( "shininess" ) ).toFloat();
mShininess = elem.attribute( QStringLiteral( "shininess2" ), QStringLiteral( "100" ) ).toFloat();
mAlpha = elem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "0.25" ) ).toFloat();
mBeta = elem.attribute( QStringLiteral( "beta" ), QStringLiteral( "0.5" ) ).toFloat();
}

void QgsGoochMaterialSettings::writeXml( QDomElement &elem, const QgsReadWriteContext & ) const
Expand All @@ -49,37 +66,41 @@ void QgsGoochMaterialSettings::writeXml( QDomElement &elem, const QgsReadWriteCo
elem.setAttribute( QStringLiteral( "cool" ), QgsSymbolLayerUtils::encodeColor( mCool ) );
elem.setAttribute( QStringLiteral( "diffuse" ), QgsSymbolLayerUtils::encodeColor( mDiffuse ) );
elem.setAttribute( QStringLiteral( "specular" ), QgsSymbolLayerUtils::encodeColor( mSpecular ) );
elem.setAttribute( QStringLiteral( "shininess" ), mShininess );
elem.setAttribute( QStringLiteral( "shininess2" ), mShininess );
elem.setAttribute( QStringLiteral( "alpha" ), mAlpha );
elem.setAttribute( QStringLiteral( "beta" ), mBeta );
}

Qt3DRender::QMaterial *QgsGoochMaterialSettings::toMaterial( const QgsMaterialContext &context ) const
Qt3DRender::QMaterial *QgsGoochMaterialSettings::toMaterial( QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context ) const
{
Qt3DExtras::QGoochMaterial *material = new Qt3DExtras::QGoochMaterial;
material->setDiffuse( mDiffuse );
material->setWarm( mWarm );
material->setCool( mCool );
switch ( technique )
{
case QgsMaterialSettingsRenderingTechnique::Triangles:
{
Qt3DExtras::QGoochMaterial *material = new Qt3DExtras::QGoochMaterial;
material->setDiffuse( mDiffuse );
material->setWarm( mWarm );
material->setCool( mCool );

material->setSpecular( mSpecular );
material->setShininess( mShininess );
material->setSpecular( mSpecular );
material->setShininess( mShininess );
material->setAlpha( mAlpha );
material->setBeta( mBeta );

if ( context.isSelected() )
{
// update the material with selection colors
material->setDiffuse( context.selectionColor() );
}
return material;
}
if ( context.isSelected() )
{
// update the material with selection colors
material->setDiffuse( context.selectionColor() );
}
return material;
}

QgsLineMaterial *QgsGoochMaterialSettings::toLineMaterial( const QgsMaterialContext &context ) const
{
QgsLineMaterial *mat = new QgsLineMaterial;
mat->setLineColor( mDiffuse );
if ( context.isSelected() )
{
// update the material with selection colors
mat->setLineColor( context.selectionColor() );
case QgsMaterialSettingsRenderingTechnique::Lines:
case QgsMaterialSettingsRenderingTechnique::InstancedPoints:
case QgsMaterialSettingsRenderingTechnique::Points:
return nullptr;
}
return mat;
return nullptr;
}

void QgsGoochMaterialSettings::addParametersToEffect( Qt3DRender::QEffect * ) const
Expand Down
32 changes: 26 additions & 6 deletions src/3d/qgsgoochmaterialsettings.h
Expand Up @@ -49,6 +49,11 @@ class _3D_EXPORT QgsGoochMaterialSettings : public QgsAbstractMaterialSettings
*/
static QgsAbstractMaterialSettings *create() SIP_FACTORY;

/**
* Returns TRUE if the specified \a technique is suppored by the Gooch material.
*/
static bool supportsTechnique( QgsMaterialSettingsRenderingTechnique technique );

QgsGoochMaterialSettings *clone() const override SIP_FACTORY;

//! Returns warm color component
Expand All @@ -64,6 +69,12 @@ class _3D_EXPORT QgsGoochMaterialSettings : public QgsAbstractMaterialSettings
//! Returns shininess of the surface
float shininess() const { return mShininess; }

//! Returns the alpha value
float alpha() const { return mAlpha; }

//! Returns the beta value
float beta() const { return mBeta; }

//! Sets warm color component
void setWarm( const QColor &warm ) { mWarm = warm; }

Expand All @@ -77,11 +88,16 @@ class _3D_EXPORT QgsGoochMaterialSettings : public QgsAbstractMaterialSettings
//! Sets shininess of the surface
void setShininess( float shininess ) { mShininess = shininess; }

//! Sets alpha value
void setAlpha( float alpha ) { mAlpha = alpha; }

//! Sets beta value
void setBeta( float beta ) { mBeta = beta; }

void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override;
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
#ifndef SIP_RUN
Qt3DRender::QMaterial *toMaterial( const QgsMaterialContext &context ) const override SIP_FACTORY;
QgsLineMaterial *toLineMaterial( const QgsMaterialContext &context ) const override SIP_FACTORY;
Qt3DRender::QMaterial *toMaterial( QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context ) const override;
void addParametersToEffect( Qt3DRender::QEffect *effect ) const override;
#endif

Expand All @@ -91,15 +107,19 @@ class _3D_EXPORT QgsGoochMaterialSettings : public QgsAbstractMaterialSettings
mSpecular == other.mSpecular &&
mWarm == other.mWarm &&
mCool == other.mCool &&
mShininess == other.mShininess;
mShininess == other.mShininess &&
mAlpha == other.mAlpha &&
mBeta == other.mBeta;
}

private:
QColor mDiffuse{ QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) };
QColor mSpecular{ QColor::fromRgbF( 1.0f, 1.0f, 1.0f, 1.0f ) };
QColor mWarm { QColor( 107, 0, 107 )};
QColor mCool { QColor( 255, 130, 0 )};
float mShininess = 0.0f;
QColor mWarm {QColor( 107, 0, 107 ) };
QColor mCool {QColor( 255, 130, 0 )};
float mShininess = 100.0f;
float mAlpha = 0.25f;
float mBeta = 0.5f;
};


Expand Down
4 changes: 4 additions & 0 deletions src/3d/qgsphongmaterialsettings.h
Expand Up @@ -43,6 +43,10 @@ class _3D_EXPORT QgsPhongMaterialSettings : public QgsAbstractMaterialSettings
QgsPhongMaterialSettings() = default;

QString type() const override;

/**
* Returns TRUE if the specified \a technique is suppored by the Phong material.
*/
static bool supportsTechnique( QgsMaterialSettingsRenderingTechnique technique );

/**
Expand Down
24 changes: 13 additions & 11 deletions src/app/3d/qgsgoochmaterialwidget.cpp
Expand Up @@ -26,29 +26,27 @@ QgsGoochMaterialWidget::QgsGoochMaterialWidget( QWidget *parent )
QgsGoochMaterialSettings defaultMaterial;
setSettings( &defaultMaterial, nullptr );

spinShininess->setClearValue( 100 );
spinAlpha->setClearValue( 0.25 );
spinBeta->setClearValue( 0.5 );

btnWarm->setDefaultColor( QColor( 107, 0, 107 ) );
btnCool->setDefaultColor( QColor( 255, 130, 0 ) );

connect( btnDiffuse, &QgsColorButton::colorChanged, this, &QgsGoochMaterialWidget::changed );
connect( btnWarm, &QgsColorButton::colorChanged, this, &QgsGoochMaterialWidget::changed );
connect( btnCool, &QgsColorButton::colorChanged, this, &QgsGoochMaterialWidget::changed );
connect( btnSpecular, &QgsColorButton::colorChanged, this, &QgsGoochMaterialWidget::changed );
connect( spinShininess, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGoochMaterialWidget::changed );
connect( spinAlpha, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGoochMaterialWidget::changed );
connect( spinBeta, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGoochMaterialWidget::changed );
}

QgsMaterialSettingsWidget *QgsGoochMaterialWidget::create()
{
return new QgsGoochMaterialWidget();
}

void QgsGoochMaterialWidget::setDiffuseVisible( bool visible )
{
lblDiffuse->setVisible( visible );
btnDiffuse->setVisible( visible );
}

bool QgsGoochMaterialWidget::isDiffuseVisible() const
{
return btnDiffuse->isVisible();
}

void QgsGoochMaterialWidget::setSettings( const QgsAbstractMaterialSettings *settings, QgsVectorLayer * )
{
const QgsGoochMaterialSettings *goochMaterial = dynamic_cast< const QgsGoochMaterialSettings * >( settings );
Expand All @@ -59,6 +57,8 @@ void QgsGoochMaterialWidget::setSettings( const QgsAbstractMaterialSettings *set
btnCool->setColor( goochMaterial->cool() );
btnSpecular->setColor( goochMaterial->specular() );
spinShininess->setValue( goochMaterial->shininess() );
spinAlpha->setValue( goochMaterial->alpha() );
spinBeta->setValue( goochMaterial->beta() );
}

QgsAbstractMaterialSettings *QgsGoochMaterialWidget::settings()
Expand All @@ -69,5 +69,7 @@ QgsAbstractMaterialSettings *QgsGoochMaterialWidget::settings()
m->setCool( btnCool->color() );
m->setSpecular( btnSpecular->color() );
m->setShininess( spinShininess->value() );
m->setAlpha( spinAlpha->value() );
m->setBeta( spinBeta->value() );
return m.release();
}
4 changes: 0 additions & 4 deletions src/app/3d/qgsgoochmaterialwidget.h
Expand Up @@ -31,10 +31,6 @@ class QgsGoochMaterialWidget : public QgsMaterialSettingsWidget, private Ui::Goo
explicit QgsGoochMaterialWidget( QWidget *parent = nullptr );

static QgsMaterialSettingsWidget *create();

void setDiffuseVisible( bool visible );
bool isDiffuseVisible() const;

void setSettings( const QgsAbstractMaterialSettings *settings, QgsVectorLayer *layer ) override;
QgsAbstractMaterialSettings *settings() override;

Expand Down

0 comments on commit 51cde6f

Please sign in to comment.