24#include <Qt3DCore/QEntity>
25#include <Qt3DExtras/QCuboidMesh>
26#include <Qt3DRender/QCullFace>
27#include <Qt3DRender/QDepthTest>
28#include <Qt3DRender/QEffect>
29#include <Qt3DRender/QFilterKey>
30#include <Qt3DRender/QGraphicsApiFilter>
31#include <Qt3DRender/QMaterial>
32#include <Qt3DRender/QParameter>
33#include <Qt3DRender/QRenderPass>
34#include <Qt3DRender/QSeamlessCubemap>
35#include <Qt3DRender/QShaderProgram>
36#include <Qt3DRender/QTechnique>
37#include <Qt3DRender/QTextureImage>
39#include "moc_qgsskyboxentity.cpp"
41using namespace Qt::StringLiterals;
54 mGl3Technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
57 mGl3Technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
65 Qt3DRender::QCullFace *cullFront =
new Qt3DRender::QCullFace();
66 cullFront->setMode( Qt3DRender::QCullFace::Front );
67 Qt3DRender::QDepthTest *depthTest =
new Qt3DRender::QDepthTest();
68 depthTest->setDepthFunction( Qt3DRender::QDepthTest::LessOrEqual );
69 Qt3DRender::QSeamlessCubemap *seamlessCubemap =
new Qt3DRender::QSeamlessCubemap();
83 mMesh->setXYMeshResolution( QSize( 2, 2 ) );
84 mMesh->setXZMeshResolution( QSize( 2, 2 ) );
85 mMesh->setYZMeshResolution( QSize( 2, 2 ) );
87 addComponent(
mMesh );
91#if ENABLE_PANORAMIC_SKYBOX
94QgsPanoramicSkyboxEntity::QgsPanoramicSkyboxEntity(
const QString &texturePath, QNode *parent )
96 , mTexturePath( texturePath )
97 , mLoadedTexture( new
Qt3DRender::QTextureLoader( parent ) )
98 , mGlShader( new
Qt3DRender::QShaderProgram( this ) )
100 mLoadedTexture->setGenerateMipMaps(
false );
101 mGlShader->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( u
"qrc:/shaders/skybox.vert"_s ) ) );
102 mGlShader->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( u
"qrc:/shaders/hdr_skybox.frag"_s ) ) );
111void QgsPanoramicSkyboxEntity::reloadTexture()
113 mLoadedTexture->setSource( QUrl::fromUserInput( mTexturePath ) );
121 Qgis::SkyboxCubeMapping mapping,
const QString &posX,
const QString &posY,
const QString &posZ,
const QString &negX,
const QString &negY,
const QString &negZ, Qt3DCore::QNode *parent
124 , mMappingType( mapping )
125 , mSourcePosX( posX )
126 , mSourcePosY( posY )
127 , mSourcePosZ( posZ )
128 , mSourceNegX( negX )
129 , mSourceNegY( negY )
130 , mSourceNegZ( negZ )
131 , mGlShader( new
Qt3DRender::QShaderProgram() )
142void QgsCubeFacesSkyboxEntity::init()
144 mGlShader->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( u
"qrc:/shaders/skybox.vert"_s ) ) );
145 mGlShader->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( u
"qrc:/shaders/skybox.frag"_s ) ) );
151void QgsCubeFacesSkyboxEntity::reloadTexture()
153 auto *newCubeMap =
new Qt3DRender::QTextureCubeMap(
this );
154 newCubeMap->setMagnificationFilter( Qt3DRender::QTextureCubeMap::Linear );
155 newCubeMap->setMinificationFilter( Qt3DRender::QTextureCubeMap::Linear );
156 newCubeMap->setGenerateMipMaps(
false );
157 newCubeMap->setWrapMode( Qt3DRender::QTextureWrapMode( Qt3DRender::QTextureWrapMode::Repeat ) );
158 newCubeMap->setFormat( Qt3DRender::QAbstractTexture::SRGB8_Alpha8 );
162 for (
const QString &texturePath : { mSourcePosX, mSourcePosY, mSourcePosZ, mSourceNegX, mSourceNegY, mSourceNegZ } )
165 maxSize = std::max( maxSize, std::max( size.width(), size.height() ) );
168 QList<Qt3DRender::QAbstractTextureImage *> newFaces;
169 const QMap<Qt3DRender::QTextureCubeMap::CubeMapFace, FaceTransformation> faceConfigs = generateFaceTransformation();
170 const QSize faceSize( maxSize, maxSize );
171 for (
auto it = faceConfigs.begin(); it != faceConfigs.end(); ++it )
173 const Qt3DRender::QTextureCubeMap::CubeMapFace face = it.key();
174 const FaceTransformation &config = it.value();
176 bool fitsInCache =
false;
178 ( void ) fitsInCache;
179 QImage finalImage = textureSourceImage;
180 if ( finalImage.isNull() )
182 finalImage = QImage( faceSize.width(), faceSize.height(), QImage::Format_RGB32 );
183 finalImage.fill( Qt::white );
185 p.begin( &finalImage );
187 uchar pixDataRGB[] = { 150, 150, 150, 255, 100, 100, 100, 255, 100, 100, 100, 255, 150, 150, 150, 255 };
188 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
189 const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
191 checkerBrush.setTexture( pix );
192 p.fillRect( finalImage.rect(), checkerBrush );
195 else if ( config.mirrorHorizontal || config.mirrorVertical )
197 finalImage = finalImage.mirrored( config.mirrorHorizontal, config.mirrorVertical );
200 auto textureImage =
new QgsImageTexture( finalImage, newCubeMap );
201 textureImage->setFace( face );
202 newCubeMap->addTextureImage( textureImage );
203 newFaces.push_back( textureImage );
210 mCubeMap->deleteLater();
212 mCubeMap = newCubeMap;
213 mFacesTextureImages = newFaces;
216QMap<Qt3DRender::QAbstractTexture::CubeMapFace, QgsCubeFacesSkyboxEntity::FaceTransformation> QgsCubeFacesSkyboxEntity::generateFaceTransformation()
const
218 QMap<Qt3DRender::QTextureCubeMap::CubeMapFace, FaceTransformation> faceConfigs;
219 switch ( mMappingType )
222 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveX] = { mSourcePosX,
false,
false };
223 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeX] = { mSourceNegX,
false,
false };
224 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveY] = { mSourcePosY,
false,
false };
225 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeY] = { mSourceNegY,
false,
false };
226 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveZ] = { mSourcePosZ,
false,
false };
227 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeZ] = { mSourceNegZ,
false,
false };
231 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveX] = { mSourcePosX,
false,
false };
232 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeX] = { mSourceNegX,
false,
false };
233 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveY] = { mSourceNegZ,
false,
false };
234 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeY] = { mSourcePosZ,
false,
false };
235 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveZ] = { mSourcePosY,
false,
false };
236 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeZ] = { mSourceNegY,
false,
false };
240 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveX] = { mSourcePosX,
false,
true };
241 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeX] = { mSourceNegX,
false,
true };
242 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveY] = { mSourceNegZ,
false,
true };
243 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeY] = { mSourcePosZ,
false,
true };
244 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveZ] = { mSourcePosY,
false,
true };
245 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeZ] = { mSourceNegY,
false,
true };
249 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveX] = { mSourcePosY,
true,
false };
250 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeX] = { mSourceNegY,
true,
false };
251 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveY] = { mSourcePosX,
true,
false };
252 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeY] = { mSourceNegX,
true,
false };
253 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveZ] = { mSourcePosZ,
true,
false };
254 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeZ] = { mSourceNegZ,
true,
false };
258 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveX] = { mSourcePosX,
true,
false };
259 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeX] = { mSourceNegX,
true,
false };
260 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveY] = { mSourcePosZ,
true,
false };
261 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeY] = { mSourceNegZ,
true,
false };
262 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapPositiveZ] = { mSourcePosY,
true,
false };
263 faceConfigs[Qt3DRender::QTextureCubeMap::CubeMapNegativeZ] = { mSourceNegY,
true,
false };
SkyboxCubeMapping
Skybox texture cube mapping for distinct texture skyboxes.
@ UnrealEngineZUp
Unreal engine standard (+X Forward, +Y Right, +Z Up, Left-handed).
@ NativeZUp
Textures exported for Z-up (+X Right, +Y Forward, +Z Up).
@ LeftHandedYUpMirrored
Left-Handed, Y-Up coordinate systems (e.g., Unity convention +X Right, +Y Top, +Z Forward,...
@ GodotYUp
Godot standard (+X Right, +Y Top, -Z Forward, with vertical flip).
@ OpenGLYUp
Standard OpenGL/WebGL standard (+X Right, +Y Top, -Z Forward).
SkyboxType
Skybox types for 3D scenes.
@ DistinctTextures
Cube map built from distinct textures.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
Qgis::SkyboxType type() const override
Returns the type of the skybox.
QgsCubeFacesSkyboxEntity(Qgis::SkyboxCubeMapping mapping, const QString &posX, const QString &posY, const QString &posZ, const QString &negX, const QString &negY, const QString &negZ, Qt3DCore::QNode *parent=nullptr)
Constructs a skybox from 6 different images.
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path.
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.
Base class for all skybox types.
QgsSkyboxEntity(QNode *parent=nullptr)
Constructor.
Qt3DRender::QRenderPass * mGl3RenderPass
Qt3DRender::QParameter * mGammaStrengthParameter
Qt3DRender::QFilterKey * mFilterKey
Qt3DRender::QEffect * mEffect
Qt3DExtras::QCuboidMesh * mMesh
Qt3DRender::QParameter * mTextureParameter
Qt3DRender::QMaterial * mMaterial
Qt3DRender::QTechnique * mGl3Technique