9#include <QtQuick3DRuntimeRender/private/qssgrhicontext_p.h>
10#include <QtQuick3DRuntimeRender/private/qssgrenderloadedtexture_p.h>
11#include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h>
14#include <QOffscreenSurface>
15#include <QOpenGLContext>
20#define GL_FLOAT 0x1406
21#define GL_HALF_FLOAT 0x140B
22#define GL_UNSIGNED_BYTE 0x1401
24#define GL_RGBA8 0x8058
25#define GL_RGBA16F 0x881A
26#define GL_RGBA32F 0x8814
62static const float cube[] = {
64 -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
67 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f,
70 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
73 -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
76 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f,
79 -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
82 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
85 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
88 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
91 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
94 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
97 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
105 QFile ktxOutputFile(outPath);
114 qDebug() << rhi->driverInfo();
117 rhi->beginOffscreenFrame(&
cb);
119 const auto rhiContext = std::make_unique<QSSGRhiContext>();
120 rhiContext->initialize(rhi.
get());
121 rhiContext->setCommandBuffer(
cb);
127 auto shaderCache = std::make_unique<QSSGShaderCache>(*rhiContext);
155 const int suggestedSize =
qMax(512.f, inImage->height * 0.5f);
156 const QSize environmentMapSize(suggestedSize, suggestedSize);
158 const int colorSpace = inImage->isSRGB ? 1 : 0;
166 if (!envCubeMap->
create()) {
173 if (!envMapRenderBuffer->
create()) {
174 return QStringLiteral(
"Failed to create Environment Map Render Buffer");
186 auto renderTarget = rhi->newTextureRenderTarget(rtDesc);
187 renderTarget->setDescription(rtDesc);
190 renderTarget->setRenderPassDescriptor(renderPassDesc);
191 if (!renderTarget->create()) {
194 renderTarget->deleteLater();
195 renderTargets << renderTarget;
200 QSize size(inImage->width, inImage->height);
209 if (inImage->textureFileData.isValid()) {
212 { inImage->textureFileData.
data().constData() + inImage->textureFileData.dataOffset(0),
213 quint32(inImage->textureFileData.dataLength(0)) } } };
215 desc = { { 0, 0, { inImage->
data, inImage->dataSizeInBytes } } };
217 auto *rub = rhi->nextResourceUpdateBatch();
226 const auto &envMapShaderStages = shaderCache->loadBuiltinForRhi(
"environmentmap");
232 rub->uploadStaticBuffer(vertexBuffer,
cube);
235 int ubufElementSize = rhi->ubufAligned(128);
240 int ubufEnvMapElementSize = rhi->ubufAligned(4);
258 envMapPipeline->
setShaderStages({ *envMapShaderStages->vertexStage(), *envMapShaderStages->fragmentStage() });
261 inputLayout.
setBindings({ { 3 *
sizeof(float) } });
267 if (!envMapPipeline->
create()) {
268 return QStringLiteral(
"Failed to create source env map pipeline state");
273 cb->debugMarkBegin(
"Environment Cubemap Generation");
282 viewMatrix.
lookAt(eye, center, up);
288 if (rhi->isYUpInFramebuffer()) {
298 rub->updateDynamicBuffer(uBuf,
face * ubufElementSize, 64, mvp.
constData());
299 rub->updateDynamicBuffer(uBuf,
face * ubufElementSize + 64, 64, views[
face].constData());
300 rub->updateDynamicBuffer(uBufEnvMap,
face * ubufEnvMapElementSize, 4, &colorSpace);
302 cb->resourceUpdate(rub);
308 cb->setGraphicsPipeline(envMapPipeline);
309 cb->setVertexInput(0, 1, &vbufBinding);
315 cb->setShaderResources(envMapSrb, 2, dynamicOffset.
constData());
324 rub = rhi->nextResourceUpdateBatch();
325 rub->generateMips(envCubeMap);
326 cb->resourceUpdate(rub);
330 cb->debugMarkBegin(
"Pre-filtered Environment Cubemap Generation");
335 if (!preFilteredEnvCubeMap->
create())
336 qWarning(
"Failed to create Pre-filtered Environment Cube Map");
337 int mipmapCount = rhi->mipLevelsForSize(environmentMapSize);
338 mipmapCount =
qMin(mipmapCount, 6);
344 for (
int mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) {
345 const QSize levelSize =
QSize(environmentMapSize.
width() * std::pow(0.5, mipLevel),
346 environmentMapSize.
height() * std::pow(0.5, mipLevel));
347 mipLevelSizes.
insert(mipLevel, levelSize);
356 auto renderTarget = rhi->newTextureRenderTarget(rtDesc);
357 renderTarget->setDescription(rtDesc);
358 if (!renderPassDescriptorPhase2)
360 renderTarget->setRenderPassDescriptor(renderPassDescriptorPhase2);
361 if (!renderTarget->create())
362 qWarning(
"Failed to build prefilter env map render target");
363 renderTarget->deleteLater();
364 renderTargets << renderTarget;
366 renderTargetsMap.
insert(mipLevel, renderTargets);
373 prefilterShaderStages = shaderCache->loadBuiltinForRhi(
"environmentmapprefilter_rgbe");
375 prefilterShaderStages = shaderCache->loadBuiltinForRhi(
"environmentmapprefilter");
385 envMapCubeSampler = rhiContext->sampler(samplerMipMapDesc);
399 int ubufPrefilterElementSize = rhi->ubufAligned(20);
420 *prefilterShaderStages->vertexStage(),
421 *prefilterShaderStages->fragmentStage()
427 if (!prefilterPipeline->
create())
428 return QStringLiteral(
"Failed to create pre-filter env map pipeline state");
433 rub = rhi->nextResourceUpdateBatch();
434 const float resolution = environmentMapSize.
width();
435 const float lodBias = 0.0f;
436 const int sampleCount = 1024;
437 for (
int mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) {
439 const float roughness = float(mipLevel) / float(mipmapCount - 2);
440 const int distribution = mipLevel == (mipmapCount - 1) ? 0 : 1;
441 rub->updateDynamicBuffer(uBufPrefilter, mipLevel * ubufPrefilterElementSize, 4, &roughness);
442 rub->updateDynamicBuffer(uBufPrefilter, mipLevel * ubufPrefilterElementSize + 4, 4, &resolution);
443 rub->updateDynamicBuffer(uBufPrefilter, mipLevel * ubufPrefilterElementSize + 4 + 4, 4, &lodBias);
444 rub->updateDynamicBuffer(uBufPrefilter, mipLevel * ubufPrefilterElementSize + 4 + 4 + 4, 4, &sampleCount);
445 rub->updateDynamicBuffer(uBufPrefilter, mipLevel * ubufPrefilterElementSize + 4 + 4 + 4 + 4, 4, &distribution);
448 cb->resourceUpdate(rub);
451 for (
int mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) {
454 cb->setGraphicsPipeline(prefilterPipeline);
455 cb->setVertexInput(0, 1, &vbufBinding);
459 { 2,
quint32(ubufPrefilterElementSize * mipLevel) }
461 cb->setShaderResources(preFilterSrb, 2, dynamicOffsets.
constData());
470 const quint32 numberOfMipmapLevels = renderTargetsMap.
size();
471 const quint32 numberOfFaces = 6;
475 '1',
'\xBB',
'\r',
'\n',
'\x1A',
'\n' };
482 static const char key[] =
"QT_IBL_BAKER_VERSION";
483 static const char value[] =
"1";
485 constexpr size_t keyAndValueByteSize =
sizeof(
key) +
sizeof(
value);
486 appendBinaryVector(keyValueData, keyAndValueByteSize);
487 appendBinaryVector(keyValueData,
key);
488 appendBinaryVector(keyValueData,
value);
491 const size_t padding = 3 - ((keyAndValueByteSize + 3) % 4);
492 keyValueData.
resize(keyValueData.
size() + padding);
519 writeUInt32(ktxOutputFile,
quint32(environmentMapSize.
width()));
522 writeUInt32(ktxOutputFile,
quint32(environmentMapSize.
height()));
525 writeUInt32(ktxOutputFile,
quint32(0));
528 writeUInt32(ktxOutputFile,
quint32(0));
531 writeUInt32(ktxOutputFile,
quint32(numberOfFaces));
534 writeUInt32(ktxOutputFile,
quint32(numberOfMipmapLevels));
537 writeUInt32(ktxOutputFile,
quint32(keyValueData.
size()));
540 ktxOutputFile.
write(keyValueData.
data(), keyValueData.
size());
543 for (
quint32 mipmap_level = 0; mipmap_level < numberOfMipmapLevels; mipmap_level++) {
556 readbackDesc.
setLevel(mipmap_level);
561 cb->resourceUpdate(resourceUpdates);
574 ktxOutputFile.
close();
578 rhi->endOffscreenFrame();
586#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
595 qDebug(
"Metal does not seem to be supported. Falling back to OpenGL.");
626 qWarning(
"Unknown key \"%s\" for QSG_RHI_BACKEND, falling back to default backend.", rhiBackend.
constData());
630#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS)
632#elif QT_CONFIG(opengl)
641 return implementation;
654 params.format.setVersion(3, 2);
657 params.format.setVersion(3, 0);
659 params.fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
667 vulkanInstance.create();
669 params.inst = &vulkanInstance;
679 QRhiD3D12InitParams
params;
684#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
696 qDebug() <<
"IBL lightprobe baker" << sourceFile;
701 if (!
error.isEmpty())
704 m_generatedFiles.append(outFileName);
707 *generatedFiles = m_generatedFiles;
IOBluetoothDevice * device
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
The QColor class provides colors based on RGB, HSV or CMYK values.
QString absoluteFilePath(const QString &fileName) const
Returns the absolute path name of a file in the directory.
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore \reentrant
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
\inmodule QtCore \reentrant
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
qsizetype size() const noexcept
const_pointer constData() const noexcept
void resize(qsizetype size)
iterator insert(const Key &key, const T &value)
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
void lookAt(const QVector3D &eye, const QVector3D ¢er, const QVector3D &up)
Multiplies this matrix by a viewing matrix derived from an eye point.
void perspective(float verticalAngle, float aspectRatio, float nearPlane, float farPlane)
Multiplies this matrix by another that applies a perspective projection.
const float * constData() const
Returns a constant pointer to the raw data of this matrix.
static OpenGLModuleType openGLModuleType()
Returns the underlying OpenGL implementation type.
virtual bool create()=0
Creates the corresponding native graphics resources.
QRhiTexture * texture() const
void setLevel(int level)
Sets the mip level.
void setLayer(int layer)
Sets the layer index.
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
void setCullMode(CullMode mode)
Sets the specified face culling mode.
void setFrontFace(FrontFace f)
Sets the front face mode f.
void setShaderResourceBindings(QRhiShaderResourceBindings *srb)
Associates with srb describing the resource binding layout and the resources (QRhiBuffer,...
void setDepthOp(CompareOp op)
Sets the depth comparison function op.
void setVertexInputLayout(const QRhiVertexInputLayout &layout)
Specifies the vertex input layout.
void setShaderStages(std::initializer_list< QRhiShaderStage > list)
Sets the list of shader stages.
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
Associates with the specified QRhiRenderPassDescriptor desc.
virtual bool create()=0
Creates the corresponding native graphics resources.
void setLayer(int layer)
Sets the array layer to read back.
void setLevel(int level)
Sets the mip level to read back.
virtual bool create()=0
Creates the corresponding native graphics resources.
virtual QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() const =0
void readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
Enqueues a texture-to-host copy operation as described by rb.
void deleteLater()
When called without a frame being recorded, this function is equivalent to deleting the object.
static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
void setBindings(std::initializer_list< QRhiShaderResourceBinding > list)
Sets the list of bindings.
const QRhiColorAttachment * cbeginColorAttachments() const
void setColorAttachments(std::initializer_list< QRhiColorAttachment > list)
Sets the list of color attachments.
QRhiTextureRenderTargetDescription description() const
virtual bool create()=0
Creates the corresponding native graphics resources.
Implementation
Describes which graphics API-specific backend gets used by a QRhi instance.
static QRhi * create(Implementation impl, QRhiInitParams *params, Flags flags={}, QRhiNativeHandles *importDevice=nullptr)
const QString import(const QString &sourceFile, const QDir &savePath, QStringList *generatedFiles)
const QString outputExtension() const
const QStringList inputExtensions() const
static QRhiCommandBuffer::BeginPassFlags commonPassFlags()
T * data() const noexcept
Returns the value of the pointer referenced by this object.
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
\macro QT_RESTRICTED_CAST_FROM_ASCII
The QVector3D class represents a vector or vertex in 3D space.
The QVulkanInstance class represents a native Vulkan instance, enabling Vulkan rendering onto a QSurf...
Combined button and popup list for selecting options.
#define QByteArrayLiteral(str)
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static const quint32 platformEndianIdentifier
#define KTX_IDENTIFIER_LENGTH
static const char ktxIdentifier[KTX_IDENTIFIER_LENGTH]
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei imageSize
void adjustToPlatformQuirks(QRhi::Implementation &impl)
QRhi::Implementation getRhiImplementation()
QString renderToKTXFile(const QString &inPath, const QString &outPath)
QString renderToKTXFileInternal(const char *name, const QString &inPath, const QString &outPath, QRhi::Implementation impl, QRhiInitParams *initParams)
static constexpr QSSGRenderTextureFormat FORMAT(QSSGRenderTextureFormat::RGBA16F)
static const float cube[]
std::shared_ptr< QSSGRhiShaderPipeline > QSSGRhiShaderPipelinePtr
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define QStringLiteral(str)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
static QSSGLoadedTexture * loadHdrImage(const QSharedPointer< QIODevice > &source, const QSSGRenderTextureFormat &inFormat)
qint32 getNumberOfComponent() const
qint32 getSizeofFormat() const