4#include <QtQuick3DRuntimeRender/private/qssgrenderreflectionprobe_p.h>
5#include <QtQuick3DRuntimeRender/private/qssgrenderlayer_p.h>
6#include <QtQuick3DRuntimeRender/private/qssglayerrenderdata_p.h>
14 : m_context(inContext)
26 entry.destroyRhiResources();
28 m_reflectionMapList.clear();
34 QRhiTexture::Flags
flags = {})
38 qWarning(
"Failed to create reflection map texture of size %dx%d",
size.width(),
size.height());
47 if (!renderBuffer->create())
48 qWarning(
"Failed to build depth-stencil buffer of size %dx%d",
size.width(),
size.height());
65 QSize pixelSize(mapRes, mapRes);
76 pEntry = &m_reflectionMapList.back();
80 pEntry->m_needsRender =
true;
83 pEntry->m_rendered =
false;
85 if (!pEntry->m_rhiDepthStencil || mapRes != pEntry->m_rhiCube->pixelSize().width()) {
86 pEntry->destroyRhiResources();
95 if (pEntry->m_rhiRenderTargets.isEmpty()) {
96 pEntry->m_rhiRenderTargets.resize(6);
97 for (
int i = 0;
i < 6; ++
i)
98 pEntry->m_rhiRenderTargets[
i] =
nullptr;
100 Q_ASSERT(pEntry->m_rhiRenderTargets.size() == 6);
102 if (pEntry->m_skyBoxSrbs.isEmpty()) {
103 pEntry->m_skyBoxSrbs.resize(6);
104 for (
int i = 0;
i < 6; ++
i)
105 pEntry->m_skyBoxSrbs[
i] =
nullptr;
116 rtDesc.setDepthStencilBuffer(pEntry->m_rhiDepthStencil);
119 if (!pEntry->m_rhiRenderPassDesc)
123 qWarning(
"Failed to build reflection map render target");
128 if (!pEntry->m_prefilterPipeline) {
129 const QSize mapSize = pEntry->m_rhiCube->pixelSize();
132 mipmapCount =
qMin(mipmapCount, 6);
135 for (
int mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) {
136 const QSize levelSize =
QSize(mapSize.
width() * std::pow(0.5, mipLevel),
137 mapSize.
height() * std::pow(0.5, mipLevel));
138 pEntry->m_prefilterMipLevelSizes.insert(mipLevel, levelSize);
140 QVarLengthArray<QRhiTextureRenderTarget *, 6> renderTargets;
150 renderTarget->setDescription(rtDesc);
151 if (!pEntry->m_rhiPrefilterRenderPassDesc)
152 pEntry->m_rhiPrefilterRenderPassDesc = renderTarget->newCompatibleRenderPassDescriptor();
153 renderTarget->setRenderPassDescriptor(pEntry->m_rhiPrefilterRenderPassDesc);
154 if (!renderTarget->create())
155 qWarning(
"Failed to build prefilter cube map render target");
156 renderTargets << renderTarget;
158 pEntry->m_rhiPrefilterRenderTargetsMap.insert(mipLevel, renderTargets);
161 const auto &prefilterShaderStages =
m_context.
shaderCache()->getBuiltInRhiShaders().getRhiReflectionprobePreFilterShader();
186 { 3 *
sizeof(float) }
194 pEntry->m_prefilterVertBuffer->
create();
197 int uBufSamplesElementSize = rhi->
ubufAligned(uBufSamplesSize);
199 pEntry->m_prefilterFragBuffer->
create();
205 pEntry->m_prefilterPipeline->setShaderStages({
206 *prefilterShaderStages->vertexStage(),
207 *prefilterShaderStages->fragmentStage()
216 pEntry->m_prefilterSrb->create();
218 pEntry->m_prefilterPipeline->setVertexInputLayout(inputLayout);
219 pEntry->m_prefilterPipeline->setShaderResourceBindings(pEntry->m_prefilterSrb);
220 pEntry->m_prefilterPipeline->setRenderPassDescriptor(pEntry->m_rhiPrefilterRenderPassDesc);
221 if (!pEntry->m_prefilterPipeline->create())
222 qWarning(
"failed to create pre-filter reflection map pipeline state");
224 const auto &irradianceShaderStages =
m_context.
shaderCache()->getBuiltInRhiShaders().getRhienvironmentmapPreFilterShader(
false );
230 pEntry->m_irradiancePipeline->setShaderStages({
231 *irradianceShaderStages->vertexStage(),
232 *irradianceShaderStages->fragmentStage()
237 pEntry->m_irradianceFragBuffer->
create();
245 pEntry->m_irradianceSrb->create();
247 pEntry->m_irradiancePipeline->setShaderResourceBindings(pEntry->m_irradianceSrb);
248 pEntry->m_irradiancePipeline->setVertexInputLayout(inputLayout);
249 pEntry->m_irradiancePipeline->setRenderPassDescriptor(pEntry->m_rhiPrefilterRenderPassDesc);
250 if (!pEntry->m_irradiancePipeline->create())
251 qWarning(
"failed to create irradiance reflection map pipeline state");
255 pEntry->m_probeIndex = probeIdx;
265 if (probeTexture.m_texture)
270 if (pEntry->m_rhiDepthStencil)
271 pEntry->destroyRhiResources();
272 if (probeTexture.m_texture)
273 pEntry->m_rhiPrefilteredCube = probeTexture.m_texture;
281 for (
int i = 0;
i < m_reflectionMapList.size();
i++) {
283 if (pEntry->m_probeIndex ==
quint32(probeIdx))
291 : m_probeIndex(
std::numeric_limits<
quint32>::max())
385 bits = ((
bits & 0x55555555u) << 1u) | ((
bits & 0xAAAAAAAAu) >> 1u);
386 bits = ((
bits & 0x33333333u) << 2u) | ((
bits & 0xCCCCCCCCu) >> 2u);
387 bits = ((
bits & 0x0F0F0F0Fu) << 4u) | ((
bits & 0xF0F0F0F0u) >> 4u);
388 bits = ((
bits & 0x00FF00FFu) << 8u) | ((
bits & 0xFF00FF00u) >> 8u);
389 return float(
bits) * 2.3283064365386963e-10;
399 float a = roughness*roughness;
401 float phi = 2.0f *
M_PI * xi.
x();
402 float cosTheta = sqrt((1.0f - xi.
y()) / (1.0f + (
a*
a - 1.0f) * xi.
y()));
403 float sinTheta = sqrt(1.0f - cosTheta * cosTheta);
406 return QVector3D(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
411 float a = roughness * roughness;
413 float nDotH2 = nDotH * nDotH;
416 float denom = nDotH2 * (
a2 - 1.0f) + 1.0f;
417 denom =
M_PI * denom * denom;
423 QVarLengthArray<QVector4D, prefilterSampleCount> &sampleDirections,
424 float &invTotalWeight,
uint &sampleCount)
432 const float pdf = D * half.z() / (4.0f * half.z()) + 0.0001f;
433 const float saTexel = 4.0f *
M_PI / (6.0f * resolution * resolution);
435 float mipLevel = roughness == 0.0f ? 0.0f : 0.5f *
log2(saSample / saTexel);
437 sampleDirections.append(
QVector4D(light, mipLevel));
438 invTotalWeight += light.
z();
444 invTotalWeight = 1.0f / invTotalWeight;
449 auto *rhi = rhiCtx->
rhi();
457 rub->uploadStaticBuffer(vertexBuffer,
cube);
458 cb->resourceUpdate(rub);
465 int uBufSamplesElementSize = rhi->
ubufAligned(uBufSamplesSize);
466 int uBufIrradianceElementSize = rhi->
ubufAligned(20);
474 viewMatrix.
lookAt(eye, center, up);
477 QVarLengthArray<QMatrix4x4, 6> views;
499 mipmapCount =
qMin(mipmapCount, 6);
501 const float resolution = mapSize.
width();
502 QVarLengthArray<QVector4D, prefilterSampleCount> sampleDirections;
505 for (
int mipLevel = 0; mipLevel < mipmapCount - 1; ++mipLevel) {
507 const float roughness = float(mipLevel) / float(mipmapCount - 2);
508 float invTotalWeight = 0.0f;
509 uint sampleCount = 0;
511 sampleDirections.clear();
519 const float roughness = 0.0f;
520 const float lodBias = 0.0f;
521 const int distribution = 0;
522 const int sampleCount = resolution / 4;
531 cb->resourceUpdate(rub);
534 for (
int mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) {
545 if (mipLevel < mipmapCount - 1) {
548 cb->setVertexInput(0, 1, &vbufBinding);
550 QVector<QPair<int, quint32>> dynamicOffsets = {
552 { 2,
quint32(uBufSamplesElementSize * mipLevel) }
558 cb->setVertexInput(0, 1, &vbufBinding);
560 QVector<QPair<int, quint32>> dynamicOffsets = {
562 { 2,
quint32(uBufIrradianceElementSize) }
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
The QColor class provides colors based on RGB, HSV or CMYK values.
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.
virtual bool create()=0
Creates the corresponding native graphics resources.
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.
Type
Specifies the type of the renderbuffer.
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
Sets the QRhiRenderPassDescriptor desc for use with this render target.
void generateMips(QRhiTexture *tex)
Enqueues a mipmap generation operation for the specified texture tex.
void updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Enqueues updating a region of a QRhiBuffer buf created with the type QRhiBuffer::Dynamic.
void setName(const QByteArray &name)
Sets a name for the object.
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.
void setColorAttachments(std::initializer_list< QRhiColorAttachment > list)
Sets the list of color attachments.
void setDescription(const QRhiTextureRenderTargetDescription &desc)
Sets the render target description desc.
virtual QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor()=0
virtual bool create()=0
Creates the corresponding native graphics resources.
Format
Specifies the texture format.
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
int ubufAligned(int v) const
QMatrix4x4 clipSpaceCorrMatrix() const
bool isYUpInFramebuffer() const
QRhiShaderResourceBindings * newShaderResourceBindings()
QRhiRenderBuffer * newRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount=1, QRhiRenderBuffer::Flags flags={}, QRhiTexture::Format backingFormatHint=QRhiTexture::UnknownFormat)
static int mipLevelsForSize(const QSize &size)
QRhiTextureRenderTarget * newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags={})
QRhiGraphicsPipeline * newGraphicsPipeline()
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
QRhiResourceUpdateBatch * nextResourceUpdateBatch()
static const char * displayName(QSSGRenderTextureCubeFace face)
@ MipModeFollowRenderImage
const std::unique_ptr< QSSGRhiContext > & rhiContext() const
const std::unique_ptr< QSSGBufferManager > & bufferManager() const
const std::unique_ptr< QSSGShaderCache > & shaderCache() const
~QSSGRenderReflectionMap()
QSSGReflectionMapEntry * reflectionMapEntry(int probeIdx)
void releaseCachedResources()
void addTexturedReflectionMapEntry(qint32 probeIdx, const QSSGRenderReflectionProbe &probe)
const QSSGRenderContextInterface & m_context
QSSGRenderReflectionMap(const QSSGRenderContextInterface &inContext)
void addReflectionMapEntry(qint32 probeIdx, const QSSGRenderReflectionProbe &probe)
QRhiCommandBuffer * commandBuffer() const
QRhiCommandBuffer::BeginPassFlags commonPassFlags() const
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
QByteArray toLatin1() const &
The QVector2D class represents a vector or vertex in 2D space.
constexpr float y() const noexcept
Returns the y coordinate of this point.
constexpr float x() const noexcept
Returns the x coordinate of this point.
The QVector3D class represents a vector or vertex in 3D space.
void normalize() noexcept
Normalizes the current vector in place.
constexpr float z() const noexcept
Returns the z coordinate of this point.
The QVector4D class represents a vector or vertex in 4D space.
QMap< QString, QString > map
[6]
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
#define QByteArrayLiteral(str)
constexpr const T & qMin(const T &a, const T &b)
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum format
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
#define Q_QUICK3D_PROFILE_START(Type)
#define Q_QUICK3D_PROFILE_END_WITH_ID(Type, Payload, POID)
#define QSSG_RENDERPASS_NAME(passName, level, face)
#define Q_QUICK3D_PROFILE_END_WITH_STRING(Type, Payload, Str)
#define Q_QUICK3D_PROFILE_ASSIGN_ID(bgnode, obj)
static constexpr QSSGRenderTextureCubeFace QSSGRenderTextureCubeFaces[]
float distributionGGX(float nDotH, float roughness)
static QRhiRenderBuffer * allocateRhiReflectionRenderBuffer(QRhi *rhi, QRhiRenderBuffer::Type type, const QSize &size)
QT_BEGIN_NAMESPACE const int prefilterSampleCount
static QRhiTexture * allocateRhiReflectionTexture(QRhi *rhi, QRhiTexture::Format format, const QSize &size, QRhiTexture::Flags flags={})
void fillPrefilterValues(float roughness, float resolution, QVarLengthArray< QVector4D, prefilterSampleCount > &sampleDirections, float &invTotalWeight, uint &sampleCount)
float radicalInverseVdC(uint bits)
static const float cube[]
QVector3D importanceSampleGGX(QVector2D xi, float roughness)
QVector2D hammersley(uint i, uint N)
#define QSSGRHICTX_STAT(ctx, f)
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
myFilter draw(painter, QPoint(0, 0), originalPixmap)
QVarLengthArray< QRhiTextureRenderTarget *, 6 > m_rhiRenderTargets
QSSGRenderReflectionProbe::ReflectionTimeSlicing m_timeSlicing
static QSSGReflectionMapEntry withRhiTexturedCubeMap(quint32 probeIdx, QRhiTexture *preFiltered)
QRhiRenderPassDescriptor * m_rhiRenderPassDesc
static QSSGReflectionMapEntry withRhiCubeMap(quint32 probeIdx, QRhiTexture *cube, QRhiTexture *prefiltered, QRhiRenderBuffer *depthStencil)
QRhiShaderResourceBindings * m_irradianceSrb
QRhiShaderResourceBindings * m_prefilterSrb
QMap< int, QSize > m_prefilterMipLevelSizes
void destroyRhiResources()
QRhiTexture * m_rhiPrefilteredCube
QRhiRenderPassDescriptor * m_rhiPrefilterRenderPassDesc
QRhiBuffer * m_prefilterFragBuffer
QRhiBuffer * m_prefilterVertBuffer
QRhiGraphicsPipeline * m_irradiancePipeline
QRhiBuffer * m_irradianceFragBuffer
QRhiGraphicsPipeline * m_prefilterPipeline
QMap< int, QVarLengthArray< QRhiTextureRenderTarget *, 6 > > m_rhiPrefilterRenderTargetsMap
void renderMips(QSSGRhiContext *rhiCtx)
QRhiRenderBuffer * m_rhiDepthStencil
QSSGRenderTextureCubeFace m_timeSliceFace
QSSGRenderImage * texture
ReflectionTimeSlicing timeSlicing
\variable QSSGRhiGraphicsPipelineState::depthFunc