mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-08 00:05:09 -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;
|
||||
%Docstring
|
||||
Returns the texture rotation, in degrees.
|
||||
%End
|
||||
|
||||
float opacity() const;
|
||||
%Docstring
|
||||
Returns the opacity of the surface
|
||||
|
||||
.. versionadded:: 3.28
|
||||
%End
|
||||
|
||||
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 );
|
||||
%Docstring
|
||||
Sets the texture rotation in degrees
|
||||
%End
|
||||
|
||||
void setOpacity( float opacity );
|
||||
%Docstring
|
||||
Sets opacity of the surface.
|
||||
|
||||
.. versionadded:: 3.28
|
||||
%End
|
||||
|
||||
virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
|
||||
|
@ -20,11 +20,12 @@
|
||||
#include "qgsimagecache.h"
|
||||
#include "qgsimagetexture.h"
|
||||
#include "qgsphongmaterialsettings.h"
|
||||
#include <Qt3DExtras/QDiffuseSpecularMaterial>
|
||||
#include <Qt3DRender/QPaintedTextureImage>
|
||||
#include <Qt3DRender/QTexture>
|
||||
#include <Qt3DRender/QParameter>
|
||||
#include <Qt3DRender/QEffect>
|
||||
#include <Qt3DRender/QTechnique>
|
||||
#include <Qt3DRender/QGraphicsApiFilter>
|
||||
#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" ) ) );
|
||||
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();
|
||||
mDiffuseTexturePath = elem.attribute( QStringLiteral( "diffuse_texture_path" ), QString() );
|
||||
mTextureScale = elem.attribute( QStringLiteral( "texture_scale" ), QString( "1.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( "specular" ), QgsSymbolLayerUtils::encodeColor( mSpecular ) );
|
||||
elem.setAttribute( QStringLiteral( "shininess" ), mShininess );
|
||||
elem.setAttribute( QStringLiteral( "opacity" ), mOpacity );
|
||||
elem.setAttribute( QStringLiteral( "diffuse_texture_path" ), mDiffuseTexturePath );
|
||||
elem.setAttribute( QStringLiteral( "texture_scale" ), mTextureScale );
|
||||
elem.setAttribute( QStringLiteral( "texture-rotation" ), mTextureRotation );
|
||||
@ -113,16 +116,50 @@ Qt3DRender::QMaterial *QgsPhongTexturedMaterialSettings::toMaterial( QgsMaterial
|
||||
QgsPhongMaterialSettings phongSettings = QgsPhongMaterialSettings();
|
||||
phongSettings.setAmbient( mAmbient );
|
||||
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.setSpecular( mSpecular );
|
||||
Qt3DRender::QMaterial *material = phongSettings.toMaterial( technique, context );
|
||||
return material;
|
||||
}
|
||||
|
||||
QgsImageTexture *textureImage = new QgsImageTexture( textureSourceImage );
|
||||
Qt3DExtras::QDiffuseSpecularMaterial *material = new Qt3DExtras::QDiffuseSpecularMaterial;
|
||||
// Use a custom material because Qt3DRender::QTexture2D does not handle opacity.
|
||||
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();
|
||||
texture->addTextureImage( textureImage );
|
||||
|
||||
@ -136,21 +173,11 @@ Qt3DRender::QMaterial *QgsPhongTexturedMaterialSettings::toMaterial( QgsMaterial
|
||||
texture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
|
||||
texture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
|
||||
|
||||
material->setDiffuse( QVariant::fromValue( texture ) );
|
||||
|
||||
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->addParameter( new Qt3DRender::QParameter( QStringLiteral( "diffuseTexture" ), QVariant::fromValue( texture ) ) );
|
||||
effect->addParameter( new Qt3DRender::QParameter( QStringLiteral( "texCoordScale" ), mTextureScale ) );
|
||||
|
||||
effect->addTechnique( technique );
|
||||
material->setEffect( effect );
|
||||
return material;
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,12 @@ class _3D_EXPORT QgsPhongTexturedMaterialSettings : public QgsAbstractMaterialSe
|
||||
*/
|
||||
float textureRotation() const;
|
||||
|
||||
/**
|
||||
* Returns the opacity of the surface
|
||||
* \since QGIS 3.28
|
||||
*/
|
||||
float opacity() const { return mOpacity; }
|
||||
|
||||
//! Sets ambient color component
|
||||
void setAmbient( const QColor &ambient ) { mAmbient = ambient; }
|
||||
|
||||
@ -113,6 +119,12 @@ class _3D_EXPORT QgsPhongTexturedMaterialSettings : public QgsAbstractMaterialSe
|
||||
//! Sets the texture rotation in degrees
|
||||
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 writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
|
||||
#ifndef SIP_RUN
|
||||
@ -126,6 +138,7 @@ class _3D_EXPORT QgsPhongTexturedMaterialSettings : public QgsAbstractMaterialSe
|
||||
return mAmbient == other.mAmbient &&
|
||||
mSpecular == other.mSpecular &&
|
||||
mShininess == other.mShininess &&
|
||||
mOpacity == other.mOpacity &&
|
||||
mDiffuseTexturePath == other.mDiffuseTexturePath &&
|
||||
mTextureScale == other.mTextureScale &&
|
||||
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 mSpecular{ QColor::fromRgbF( 1.0f, 1.0f, 1.0f, 1.0f ) };
|
||||
float mShininess = 0.0f;
|
||||
float mOpacity = 1.0f;
|
||||
QString mDiffuseTexturePath;
|
||||
float mTextureScale{ 1.0f };
|
||||
float mTextureRotation{ 0.0f };
|
||||
|
@ -943,7 +943,7 @@ void Qgs3DMapScene::finalizeNewEntity( Qt3DCore::QEntity *newEntity )
|
||||
}
|
||||
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();
|
||||
if ( effect )
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>shaders/diffuseSpecular.frag</file>
|
||||
<file>shaders/diffuseSpecular.vert</file>
|
||||
<file>shaders/instanced.frag</file>
|
||||
<file>shaders/instanced.vert</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