QGIS API Documentation 4.1.0-Master (31622b25bb0)
Loading...
Searching...
No Matches
qgsmetalroughtexturedmaterialsettings.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmetalroughtexturedmaterialsettings.cpp
3 --------------------------------------
4 Date : April 2026
5 Copyright : (C) 2026 by Nyall Dawson
6 Email : nyall dot dawson at gmail 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 "qgsapplication.h"
19#include "qgsimagecache.h"
20#include "qgssymbollayerutils.h"
21
22#include <QString>
23
24using namespace Qt::StringLiterals;
25
27{
28 return u"metalroughtextured"_s;
29}
30
49
54
59
61{
62 const QgsMetalRoughTexturedMaterialSettings *otherMetal = dynamic_cast<const QgsMetalRoughTexturedMaterialSettings *>( other );
63 if ( !otherMetal )
64 return false;
65
66 return *this == *otherMetal;
67}
68
73
75{
76 return !mNormalTexturePath.isEmpty() || !mHeightTexturePath.isEmpty();
77}
78
79QColor QgsMetalRoughTexturedMaterialSettings::textureAverageColor( const QString &texturePath ) const
80{
81 bool fitsInCache = false;
82 QImage texture = QgsApplication::imageCache()->pathAsImage( texturePath, QSize(), true, 1.0, fitsInCache );
83 if ( texture.isNull() )
84 {
85 return QColor( 127, 127, 127 );
86 }
87
88 if ( texture.format() != QImage::Format_ARGB32 )
89 {
90 texture = texture.convertToFormat( QImage::Format_ARGB32 );
91 }
92
93 unsigned long long red = 0;
94 unsigned long long green = 0;
95 unsigned long long blue = 0;
96 unsigned long long pixelCount = 0;
97
98 // downsampling to ensure a fast computation
99 const int sampleStep = std::min( texture.width() / 5, texture.height() / 5 );
100 const int width = texture.width();
101 const int height = texture.height();
102 for ( int y = 0; y < height; y += sampleStep )
103 {
104 const QRgb *line = reinterpret_cast< const QRgb * >( texture.constScanLine( y ) );
105 for ( int x = 0; x < width; x += sampleStep )
106 {
107 const QRgb pixel = line[x];
108 red += qRed( pixel );
109 green += qGreen( pixel );
110 blue += qBlue( pixel );
111 pixelCount++;
112 }
113 }
114
115 return QColor( static_cast<int>( red / pixelCount ), static_cast<int>( green / pixelCount ), static_cast<int>( blue / pixelCount ) );
116}
117
119{
120 if ( mAverageColor.has_value() )
121 {
122 return *mAverageColor;
123 }
124
125 mAverageColor = textureAverageColor( mBaseColorTexturePath );
126 if ( !mEmissionTexturePath.isEmpty() )
127 {
128 const QColor emission = textureAverageColor( mEmissionTexturePath );
129
130 const double red = std::clamp( mAverageColor->redF() + emission.redF() * mEmissionFactor, 0.0, 1.0 );
131 const double green = std::clamp( mAverageColor->greenF() + emission.greenF() * mEmissionFactor, 0.0, 1.0 );
132 const double blue = std::clamp( mAverageColor->blueF() + emission.blueF() * mEmissionFactor, 0.0, 1.0 );
133
134 mAverageColor = QColor::fromRgbF( static_cast<float>( red ), static_cast<float>( green ), static_cast<float>( blue ) );
135 }
136
137 return *mAverageColor;
138}
139
141{
142 Q_UNUSED( baseColor );
143 QgsDebugMsgLevel( u"setColorsFromBase() has no effect for textured PBR materials"_s, 2 );
144}
145
146void QgsMetalRoughTexturedMaterialSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
147{
148 mBaseColorTexturePath = elem.attribute( u"base_color_texture_path"_s, QString() );
149 mMetalnessTexturePath = elem.attribute( u"metalness_texture_path"_s, QString() );
150 mRoughnessTexturePath = elem.attribute( u"roughness_texture_path"_s, QString() );
151 mNormalTexturePath = elem.attribute( u"normal_texture_path"_s, QString() );
152 mHeightTexturePath = elem.attribute( u"height_texture_path"_s, QString() );
153 mAmbientOcclusionTexturePath = elem.attribute( u"ambient_occlusion_texture_path"_s, QString() );
154 mEmissionTexturePath = elem.attribute( u"emission_texture_path"_s, QString() );
155 mEmissionFactor = elem.attribute( u"emission_factor"_s, QString( "1.0" ) ).toDouble();
156 mParallaxScale = elem.attribute( u"parallax_scale"_s, QString( "0.1" ) ).toDouble();
157 mTextureScale = elem.attribute( u"texture_scale"_s, QString( "1.0" ) ).toDouble();
158 mTextureRotation = elem.attribute( u"texture_rotation"_s, QString( "0.0" ) ).toDouble();
159 mOpacity = elem.attribute( u"opacity"_s, u"1.0"_s ).toDouble();
160
162}
163
164void QgsMetalRoughTexturedMaterialSettings::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
165{
166 elem.setAttribute( u"base_color_texture_path"_s, mBaseColorTexturePath );
167 elem.setAttribute( u"metalness_texture_path"_s, mMetalnessTexturePath );
168 elem.setAttribute( u"roughness_texture_path"_s, mRoughnessTexturePath );
169 elem.setAttribute( u"normal_texture_path"_s, mNormalTexturePath );
170 elem.setAttribute( u"parallax_scale"_s, mParallaxScale );
171 elem.setAttribute( u"height_texture_path"_s, mHeightTexturePath );
172 elem.setAttribute( u"emission_texture_path"_s, mEmissionTexturePath );
173 elem.setAttribute( u"ambient_occlusion_texture_path"_s, mAmbientOcclusionTexturePath );
174 if ( !qgsDoubleNear( mEmissionFactor, 1.0 ) )
175 elem.setAttribute( u"emission_factor"_s, mEmissionFactor );
176 elem.setAttribute( u"texture_scale"_s, mTextureScale );
177 elem.setAttribute( u"texture_rotation"_s, mTextureRotation );
178 if ( !qgsDoubleNear( mOpacity, 1 ) )
179 elem.setAttribute( u"opacity"_s, mOpacity );
180
182}
MaterialRenderingTechnique
Material rendering techniques.
Definition qgis.h:4342
@ Points
Point based rendering, requires point data.
Definition qgis.h:4346
@ Triangles
Triangle based rendering (default).
Definition qgis.h:4343
@ TrianglesFromModel
Triangle based rendering, using a model object source.
Definition qgis.h:4348
@ Lines
Line based rendering, requires line data.
Definition qgis.h:4344
@ Billboards
Flat billboard rendering.
Definition qgis.h:4350
@ TrianglesDataDefined
Triangle based rendering with possibility of datadefined color.
Definition qgis.h:4349
@ InstancedPoints
Instanced based rendering, requiring triangles and point data.
Definition qgis.h:4345
@ TrianglesWithFixedTexture
Triangle based rendering, using a fixed, non-user-configurable texture (e.g. for terrain rendering).
Definition qgis.h:4347
Abstract base class for material settings.
virtual void writeXml(QDomElement &element, const QgsReadWriteContext &) const
Writes settings to a DOM element.
virtual void readXml(const QDomElement &element, const QgsReadWriteContext &)
Reads settings from a DOM element.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
bool requiresTangents() const override
Returns true if the material requires tangents generated during triangulation.
QString type() const override
Returns the unique type name for the material.
QgsMetalRoughTexturedMaterialSettings * clone() const override
Clones the material settings.
static QgsAbstractMaterialSettings * create()
Returns a new instance of QgsMetalRoughTexturedMaterialSettings.
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const override
Writes settings to a DOM element.
QColor averageColor() const override
Returns an approximate color representing the blended material color.
void setColorsFromBase(const QColor &baseColor) override
Decomposes a base color into the material's color components, and sets the material's colors accordin...
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads settings from a DOM element.
bool equals(const QgsAbstractMaterialSettings *other) const override
Returns true if this settings exactly matches an other settings.
bool requiresTextureCoordinates() const override
Returns true if the material requires texture coordinates to be generated during triangulation.
static bool supportsTechnique(Qgis::MaterialRenderingTechnique technique)
Returns true if the specified technique is supported by the metal rough material.
A container for the context for various read/write operations on objects.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:7222
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63