mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-09 00:08:52 -04:00
qgsphongtexturedmaterialsettings: Add support for opacity
Qt3DRender::QTexture2D does not handle opacity. Therefore, it is not possible to use the default Qt3DExtras::QDiffuseSpecularMaterial implementation. This problem is solved by using Qt3DRender::QMaterial and copying the Qt3DExtras::QDiffuseSpecularMaterial shaders from Qt3D source code. Then, the texture color needs to be changed to set the correct opacity. This is achieved in the fragement shader: ``` vec4 diffuseTextureColor = vec4(texture(diffuseTexture, texCoord).rgb, opacity); ``` instead of the default: ``` vec4 diffuseTextureColor = vec4(texture(diffuseTexture, texCoord)); ``` As far as the FrameGraph is concerned, this is already handled in Qgs3DMapScene::finalizeNewEntity which checks for all material which have an effect with an opacity parameter.
This commit is contained in:
parent
20325a565b
commit
b69feb0817
@ -88,6 +88,13 @@ during triangulation.quiresTextureCoordinates
|
|||||||
float textureRotation() const;
|
float textureRotation() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns the texture rotation, in degrees.
|
Returns the texture rotation, in degrees.
|
||||||
|
%End
|
||||||
|
|
||||||
|
float opacity() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the opacity of the surface
|
||||||
|
|
||||||
|
.. versionadded:: 3.28
|
||||||
%End
|
%End
|
||||||
|
|
||||||
void setAmbient( const QColor &ambient );
|
void setAmbient( const QColor &ambient );
|
||||||
@ -121,6 +128,13 @@ If the texture scale is less than 1 the texture will be stretched
|
|||||||
void setTextureRotation( float rotation );
|
void setTextureRotation( float rotation );
|
||||||
%Docstring
|
%Docstring
|
||||||
Sets the texture rotation in degrees
|
Sets the texture rotation in degrees
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setOpacity( float opacity );
|
||||||
|
%Docstring
|
||||||
|
Sets opacity of the surface.
|
||||||
|
|
||||||
|
.. versionadded:: 3.28
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
|
virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
|
||||||
|
@ -20,11 +20,12 @@
|
|||||||
#include "qgsimagecache.h"
|
#include "qgsimagecache.h"
|
||||||
#include "qgsimagetexture.h"
|
#include "qgsimagetexture.h"
|
||||||
#include "qgsphongmaterialsettings.h"
|
#include "qgsphongmaterialsettings.h"
|
||||||
#include <Qt3DExtras/QDiffuseSpecularMaterial>
|
|
||||||
#include <Qt3DRender/QPaintedTextureImage>
|
#include <Qt3DRender/QPaintedTextureImage>
|
||||||
#include <Qt3DRender/QTexture>
|
#include <Qt3DRender/QTexture>
|
||||||
#include <Qt3DRender/QParameter>
|
#include <Qt3DRender/QParameter>
|
||||||
#include <Qt3DRender/QEffect>
|
#include <Qt3DRender/QEffect>
|
||||||
|
#include <Qt3DRender/QTechnique>
|
||||||
|
#include <Qt3DRender/QGraphicsApiFilter>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
|
|
||||||
@ -71,6 +72,7 @@ void QgsPhongTexturedMaterialSettings::readXml( const QDomElement &elem, const Q
|
|||||||
mAmbient = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "ambient" ), QStringLiteral( "25,25,25" ) ) );
|
mAmbient = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "ambient" ), QStringLiteral( "25,25,25" ) ) );
|
||||||
mSpecular = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "specular" ), QStringLiteral( "255,255,255" ) ) );
|
mSpecular = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "specular" ), QStringLiteral( "255,255,255" ) ) );
|
||||||
mShininess = elem.attribute( QStringLiteral( "shininess" ) ).toFloat();
|
mShininess = elem.attribute( QStringLiteral( "shininess" ) ).toFloat();
|
||||||
|
mOpacity = elem.attribute( QStringLiteral( "opacity" ), QStringLiteral( "1.0" ) ).toFloat();
|
||||||
mDiffuseTexturePath = elem.attribute( QStringLiteral( "diffuse_texture_path" ), QString() );
|
mDiffuseTexturePath = elem.attribute( QStringLiteral( "diffuse_texture_path" ), QString() );
|
||||||
mTextureScale = elem.attribute( QStringLiteral( "texture_scale" ), QString( "1.0" ) ).toFloat();
|
mTextureScale = elem.attribute( QStringLiteral( "texture_scale" ), QString( "1.0" ) ).toFloat();
|
||||||
mTextureRotation = elem.attribute( QStringLiteral( "texture-rotation" ), QString( "0.0" ) ).toFloat();
|
mTextureRotation = elem.attribute( QStringLiteral( "texture-rotation" ), QString( "0.0" ) ).toFloat();
|
||||||
@ -83,6 +85,7 @@ void QgsPhongTexturedMaterialSettings::writeXml( QDomElement &elem, const QgsRea
|
|||||||
elem.setAttribute( QStringLiteral( "ambient" ), QgsSymbolLayerUtils::encodeColor( mAmbient ) );
|
elem.setAttribute( QStringLiteral( "ambient" ), QgsSymbolLayerUtils::encodeColor( mAmbient ) );
|
||||||
elem.setAttribute( QStringLiteral( "specular" ), QgsSymbolLayerUtils::encodeColor( mSpecular ) );
|
elem.setAttribute( QStringLiteral( "specular" ), QgsSymbolLayerUtils::encodeColor( mSpecular ) );
|
||||||
elem.setAttribute( QStringLiteral( "shininess" ), mShininess );
|
elem.setAttribute( QStringLiteral( "shininess" ), mShininess );
|
||||||
|
elem.setAttribute( QStringLiteral( "opacity" ), mOpacity );
|
||||||
elem.setAttribute( QStringLiteral( "diffuse_texture_path" ), mDiffuseTexturePath );
|
elem.setAttribute( QStringLiteral( "diffuse_texture_path" ), mDiffuseTexturePath );
|
||||||
elem.setAttribute( QStringLiteral( "texture_scale" ), mTextureScale );
|
elem.setAttribute( QStringLiteral( "texture_scale" ), mTextureScale );
|
||||||
elem.setAttribute( QStringLiteral( "texture-rotation" ), mTextureRotation );
|
elem.setAttribute( QStringLiteral( "texture-rotation" ), mTextureRotation );
|
||||||
@ -113,16 +116,50 @@ Qt3DRender::QMaterial *QgsPhongTexturedMaterialSettings::toMaterial( QgsMaterial
|
|||||||
QgsPhongMaterialSettings phongSettings = QgsPhongMaterialSettings();
|
QgsPhongMaterialSettings phongSettings = QgsPhongMaterialSettings();
|
||||||
phongSettings.setAmbient( mAmbient );
|
phongSettings.setAmbient( mAmbient );
|
||||||
phongSettings.setDiffuse( QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) ); // default diffuse color from QDiffuseSpecularMaterial
|
phongSettings.setDiffuse( QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) ); // default diffuse color from QDiffuseSpecularMaterial
|
||||||
phongSettings.setOpacity( 1.0 ); // QgsPhongTexturedMaterialSettings does not handle opacity
|
phongSettings.setOpacity( mOpacity );
|
||||||
phongSettings.setShininess( mShininess );
|
phongSettings.setShininess( mShininess );
|
||||||
phongSettings.setSpecular( mSpecular );
|
phongSettings.setSpecular( mSpecular );
|
||||||
Qt3DRender::QMaterial *material = phongSettings.toMaterial( technique, context );
|
Qt3DRender::QMaterial *material = phongSettings.toMaterial( technique, context );
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsImageTexture *textureImage = new QgsImageTexture( textureSourceImage );
|
// Use a custom material because Qt3DRender::QTexture2D does not handle opacity.
|
||||||
Qt3DExtras::QDiffuseSpecularMaterial *material = new Qt3DExtras::QDiffuseSpecularMaterial;
|
Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
|
||||||
|
|
||||||
|
Qt3DRender::QEffect *effect = new Qt3DRender::QEffect( material );
|
||||||
|
|
||||||
|
Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
|
||||||
|
technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
|
||||||
|
technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
|
||||||
|
technique->graphicsApiFilter()->setMajorVersion( 3 );
|
||||||
|
technique->graphicsApiFilter()->setMinorVersion( 3 );
|
||||||
|
Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey();
|
||||||
|
filterKey->setName( QStringLiteral( "renderingStyle" ) );
|
||||||
|
filterKey->setValue( QStringLiteral( "forward" ) );
|
||||||
|
technique->addFilterKey( filterKey );
|
||||||
|
|
||||||
|
Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass();
|
||||||
|
Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram();
|
||||||
|
|
||||||
|
//Load shader programs
|
||||||
|
const QUrl urlVert( QStringLiteral( "qrc:/shaders/diffuseSpecular.vert" ) );
|
||||||
|
shaderProgram->setShaderCode( Qt3DRender::QShaderProgram::Vertex, Qt3DRender::QShaderProgram::loadSource( urlVert ) );
|
||||||
|
const QUrl urlFrag( QStringLiteral( "qrc:/shaders/diffuseSpecular.frag" ) );
|
||||||
|
shaderProgram->setShaderCode( Qt3DRender::QShaderProgram::Fragment, Qt3DRender::QShaderProgram::loadSource( urlFrag ) );
|
||||||
|
|
||||||
|
renderPass->setShaderProgram( shaderProgram );
|
||||||
|
technique->addRenderPass( renderPass );
|
||||||
|
|
||||||
|
int opacity = mOpacity * 255;
|
||||||
|
QColor ambient = context.isSelected() ? context.selectionColor().darker() : mAmbient;
|
||||||
|
effect->addParameter( new Qt3DRender::QParameter( QStringLiteral( "ka" ), QColor( ambient.red(), ambient.green(), ambient.blue(), opacity ) ) );
|
||||||
|
effect->addParameter( new Qt3DRender::QParameter( QStringLiteral( "ks" ), QColor( mSpecular.red(), mSpecular.green(), mSpecular.blue(), opacity ) ) );
|
||||||
|
effect->addParameter( new Qt3DRender::QParameter( QStringLiteral( "shininess" ), mShininess ) );
|
||||||
|
effect->addParameter( new Qt3DRender::QParameter( QStringLiteral( "opacity" ), mOpacity ) );
|
||||||
|
|
||||||
|
// TODO : if ( context.isSelected() ) dampen the color of diffuse texture
|
||||||
|
// with context.map().selectionColor()
|
||||||
|
QgsImageTexture *textureImage = new QgsImageTexture( textureSourceImage );
|
||||||
Qt3DRender::QTexture2D *texture = new Qt3DRender::QTexture2D();
|
Qt3DRender::QTexture2D *texture = new Qt3DRender::QTexture2D();
|
||||||
texture->addTextureImage( textureImage );
|
texture->addTextureImage( textureImage );
|
||||||
|
|
||||||
@ -136,21 +173,11 @@ Qt3DRender::QMaterial *QgsPhongTexturedMaterialSettings::toMaterial( QgsMaterial
|
|||||||
texture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
|
texture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
|
||||||
texture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
|
texture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
|
||||||
|
|
||||||
material->setDiffuse( QVariant::fromValue( texture ) );
|
effect->addParameter( new Qt3DRender::QParameter( QStringLiteral( "diffuseTexture" ), QVariant::fromValue( texture ) ) );
|
||||||
|
effect->addParameter( new Qt3DRender::QParameter( QStringLiteral( "texCoordScale" ), mTextureScale ) );
|
||||||
material->setSpecular( mSpecular );
|
|
||||||
material->setAmbient( mAmbient );
|
|
||||||
material->setShininess( mShininess );
|
|
||||||
material->setTextureScale( mTextureScale );
|
|
||||||
|
|
||||||
if ( context.isSelected() )
|
|
||||||
{
|
|
||||||
// update the material with selection colors
|
|
||||||
// TODO : dampen the color of diffuse texture
|
|
||||||
// mat->setDiffuse( context.map().selectionColor() );
|
|
||||||
material->setAmbient( context.selectionColor().darker() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
effect->addTechnique( technique );
|
||||||
|
material->setEffect( effect );
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +89,12 @@ class _3D_EXPORT QgsPhongTexturedMaterialSettings : public QgsAbstractMaterialSe
|
|||||||
*/
|
*/
|
||||||
float textureRotation() const;
|
float textureRotation() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the opacity of the surface
|
||||||
|
* \since QGIS 3.28
|
||||||
|
*/
|
||||||
|
float opacity() const { return mOpacity; }
|
||||||
|
|
||||||
//! Sets ambient color component
|
//! Sets ambient color component
|
||||||
void setAmbient( const QColor &ambient ) { mAmbient = ambient; }
|
void setAmbient( const QColor &ambient ) { mAmbient = ambient; }
|
||||||
|
|
||||||
@ -113,6 +119,12 @@ class _3D_EXPORT QgsPhongTexturedMaterialSettings : public QgsAbstractMaterialSe
|
|||||||
//! Sets the texture rotation in degrees
|
//! Sets the texture rotation in degrees
|
||||||
void setTextureRotation( float rotation ) { mTextureRotation = rotation; }
|
void setTextureRotation( float rotation ) { mTextureRotation = rotation; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets opacity of the surface.
|
||||||
|
* \since QGIS 3.28
|
||||||
|
*/
|
||||||
|
void setOpacity( float opacity ) { mOpacity = opacity; }
|
||||||
|
|
||||||
void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override;
|
void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override;
|
||||||
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
|
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
|
||||||
#ifndef SIP_RUN
|
#ifndef SIP_RUN
|
||||||
@ -126,6 +138,7 @@ class _3D_EXPORT QgsPhongTexturedMaterialSettings : public QgsAbstractMaterialSe
|
|||||||
return mAmbient == other.mAmbient &&
|
return mAmbient == other.mAmbient &&
|
||||||
mSpecular == other.mSpecular &&
|
mSpecular == other.mSpecular &&
|
||||||
mShininess == other.mShininess &&
|
mShininess == other.mShininess &&
|
||||||
|
mOpacity == other.mOpacity &&
|
||||||
mDiffuseTexturePath == other.mDiffuseTexturePath &&
|
mDiffuseTexturePath == other.mDiffuseTexturePath &&
|
||||||
mTextureScale == other.mTextureScale &&
|
mTextureScale == other.mTextureScale &&
|
||||||
mTextureRotation == other.mTextureRotation;
|
mTextureRotation == other.mTextureRotation;
|
||||||
@ -135,6 +148,7 @@ class _3D_EXPORT QgsPhongTexturedMaterialSettings : public QgsAbstractMaterialSe
|
|||||||
QColor mAmbient{ QColor::fromRgbF( 0.1f, 0.1f, 0.1f, 1.0f ) };
|
QColor mAmbient{ QColor::fromRgbF( 0.1f, 0.1f, 0.1f, 1.0f ) };
|
||||||
QColor mSpecular{ QColor::fromRgbF( 1.0f, 1.0f, 1.0f, 1.0f ) };
|
QColor mSpecular{ QColor::fromRgbF( 1.0f, 1.0f, 1.0f, 1.0f ) };
|
||||||
float mShininess = 0.0f;
|
float mShininess = 0.0f;
|
||||||
|
float mOpacity = 1.0f;
|
||||||
QString mDiffuseTexturePath;
|
QString mDiffuseTexturePath;
|
||||||
float mTextureScale{ 1.0f };
|
float mTextureScale{ 1.0f };
|
||||||
float mTextureRotation{ 0.0f };
|
float mTextureRotation{ 0.0f };
|
||||||
|
@ -943,7 +943,7 @@ void Qgs3DMapScene::finalizeNewEntity( Qt3DCore::QEntity *newEntity )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This handles the phong material with data defined properties.
|
// This handles the phong material with data defined properties and the textured case.
|
||||||
Qt3DRender::QEffect *effect = material->effect();
|
Qt3DRender::QEffect *effect = material->effect();
|
||||||
if ( effect )
|
if ( effect )
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
|
<file>shaders/diffuseSpecular.frag</file>
|
||||||
|
<file>shaders/diffuseSpecular.vert</file>
|
||||||
<file>shaders/instanced.frag</file>
|
<file>shaders/instanced.frag</file>
|
||||||
<file>shaders/instanced.vert</file>
|
<file>shaders/instanced.vert</file>
|
||||||
<file>shaders/light.inc.frag</file>
|
<file>shaders/light.inc.frag</file>
|
||||||
|
23
src/3d/shaders/diffuseSpecular.frag
Normal file
23
src/3d/shaders/diffuseSpecular.frag
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#version 330
|
||||||
|
|
||||||
|
in vec3 worldPosition;
|
||||||
|
in vec3 worldNormal;
|
||||||
|
in vec2 texCoord;
|
||||||
|
|
||||||
|
uniform vec3 eyePosition;
|
||||||
|
uniform vec4 ka;
|
||||||
|
uniform vec4 ks;
|
||||||
|
uniform float shininess;
|
||||||
|
uniform sampler2D diffuseTexture;
|
||||||
|
uniform float opacity;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
#pragma include phong.inc.frag
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec4 diffuseTextureColor = vec4(texture(diffuseTexture, texCoord).rgb, opacity);
|
||||||
|
vec3 worldView = normalize(eyePosition - worldPosition);
|
||||||
|
fragColor = phongFunction(ka, diffuseTextureColor, ks, shininess, worldPosition, worldView, worldNormal);
|
||||||
|
}
|
30
src/3d/shaders/diffuseSpecular.vert
Normal file
30
src/3d/shaders/diffuseSpecular.vert
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// copied from qt3d/src/extras/shaders/gl3/default.vert
|
||||||
|
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
in vec3 vertexPosition;
|
||||||
|
in vec3 vertexNormal;
|
||||||
|
in vec2 vertexTexCoord;
|
||||||
|
|
||||||
|
out vec3 worldPosition;
|
||||||
|
out vec3 worldNormal;
|
||||||
|
out vec2 texCoord;
|
||||||
|
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
uniform mat3 modelNormalMatrix;
|
||||||
|
uniform mat4 modelViewProjection;
|
||||||
|
|
||||||
|
uniform float texCoordScale;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
// Pass through scaled texture coordinates
|
||||||
|
texCoord = vertexTexCoord * texCoordScale;
|
||||||
|
|
||||||
|
// Transform position and normal to world space
|
||||||
|
worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0));
|
||||||
|
worldNormal = normalize(modelNormalMatrix * vertexNormal);
|
||||||
|
|
||||||
|
// Calculate vertex position in clip coordinates
|
||||||
|
gl_Position = modelViewProjection * vec4(vertexPosition, 1.0);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user