Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qssgrenderreflectionmap.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtQuick3DRuntimeRender/private/qssgrenderreflectionprobe_p.h>
5#include <QtQuick3DRuntimeRender/private/qssgrenderlayer_p.h>
6#include <QtQuick3DRuntimeRender/private/qssglayerrenderdata_p.h>
8
10
11const int prefilterSampleCount = 16;
12
14 : m_context(inContext)
15{
16}
17
22
24{
25 for (QSSGReflectionMapEntry &entry : m_reflectionMapList)
26 entry.destroyRhiResources();
27
28 m_reflectionMapList.clear();
29}
30
33 const QSize &size,
34 QRhiTexture::Flags flags = {})
35{
36 auto texture = rhi->newTexture(format, size, 1, flags);
37 if (!texture->create())
38 qWarning("Failed to create reflection map texture of size %dx%d", size.width(), size.height());
39 return texture;
40}
41
44 const QSize &size)
45{
46 auto renderBuffer = rhi->newRenderBuffer(type, size, 1);
47 if (!renderBuffer->create())
48 qWarning("Failed to build depth-stencil buffer of size %dx%d", size.width(), size.height());
49 return renderBuffer;
50}
51
52
54{
55 QRhi *rhi = m_context.rhiContext()->rhi();
56 // Bail out if there is no QRhi, since we can't add entries without it
57 if (!rhi)
58 return;
59
61
62 const QByteArray rtName = probe.debugObjectName.toLatin1();
63
64 const int mapRes = 1 << probe.reflectionMapRes;
65 QSize pixelSize(mapRes, mapRes);
67
68 if (!pEntry) {
74 m_reflectionMapList.push_back(QSSGReflectionMapEntry::withRhiCubeMap(probeIdx, map, prefiltered, depthStencil));
75
76 pEntry = &m_reflectionMapList.back();
77 }
78
79 if (pEntry) {
80 pEntry->m_needsRender = true;
81
82 if (probe.hasScheduledUpdate)
83 pEntry->m_rendered = false;
84
85 if (!pEntry->m_rhiDepthStencil || mapRes != pEntry->m_rhiCube->pixelSize().width()) {
86 pEntry->destroyRhiResources();
87 pEntry->m_rhiDepthStencil = allocateRhiReflectionRenderBuffer(rhi, QRhiRenderBuffer::DepthStencil, pixelSize);
88 pEntry->m_rhiCube = allocateRhiReflectionTexture(rhi, rhiFormat, pixelSize, QRhiTexture::RenderTarget | QRhiTexture::CubeMap
90 pEntry->m_rhiPrefilteredCube = allocateRhiReflectionTexture(rhi, rhiFormat, pixelSize, QRhiTexture::RenderTarget | QRhiTexture::CubeMap
92 }
93
94 // Additional graphics resources: samplers, render targets.
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;
99 }
100 Q_ASSERT(pEntry->m_rhiRenderTargets.size() == 6);
101
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;
106 }
107
108
109 for (const auto face : QSSGRenderTextureCubeFaces) {
110 QRhiTextureRenderTarget *&rt(pEntry->m_rhiRenderTargets[quint8(face)]);
111 if (!rt) {
112 QRhiColorAttachment att(pEntry->m_rhiCube);
113 att.setLayer(quint8(face)); // 6 render targets, each referencing one face of the cubemap
115 rtDesc.setColorAttachments({ att });
116 rtDesc.setDepthStencilBuffer(pEntry->m_rhiDepthStencil);
117 rt = rhi->newTextureRenderTarget(rtDesc);
118 rt->setDescription(rtDesc);
119 if (!pEntry->m_rhiRenderPassDesc)
120 pEntry->m_rhiRenderPassDesc = rt->newCompatibleRenderPassDescriptor();
121 rt->setRenderPassDescriptor(pEntry->m_rhiRenderPassDesc);
122 if (!rt->create())
123 qWarning("Failed to build reflection map render target");
124 }
125 rt->setName(rtName + QByteArrayLiteral(" reflection cube face: ") + QSSGBaseTypeHelpers::displayName(face));
126 }
127
128 if (!pEntry->m_prefilterPipeline) {
129 const QSize mapSize = pEntry->m_rhiCube->pixelSize();
130
131 int mipmapCount = rhi->mipLevelsForSize(mapSize);
132 mipmapCount = qMin(mipmapCount, 6); // don't create more than 6 mip levels
133
134 // Create a renderbuffer for each mip level
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);
139 // Setup Render targets (6 * mipmapCount)
140 QVarLengthArray<QRhiTextureRenderTarget *, 6> renderTargets;
141 for (const auto face : QSSGRenderTextureCubeFaces) {
142 QRhiColorAttachment att(pEntry->m_rhiPrefilteredCube);
143 att.setLayer(quint8(face));
144 att.setLevel(mipLevel);
146 rtDesc.setColorAttachments({att});
147 auto renderTarget = rhi->newTextureRenderTarget(rtDesc);
148 renderTarget->setName(rtName + QByteArrayLiteral(" reflection prefilter mip/face ")
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;
157 }
158 pEntry->m_rhiPrefilterRenderTargetsMap.insert(mipLevel, renderTargets);
159 }
160
161 const auto &prefilterShaderStages = m_context.shaderCache()->getBuiltInRhiShaders().getRhiReflectionprobePreFilterShader();
162
163 const QSSGRhiSamplerDescription samplerMipMapDesc {
170 };
171
172 const QSSGRhiSamplerDescription samplerDesc {
179 };
180
181 QRhiSampler *sampler = m_context.rhiContext()->sampler(samplerDesc);
182 QRhiSampler *cubeSampler = m_context.rhiContext()->sampler(samplerMipMapDesc);
183
184 QRhiVertexInputLayout inputLayout;
185 inputLayout.setBindings({
186 { 3 * sizeof(float) }
187 });
188 inputLayout.setAttributes({
190 });
191
192 int ubufElementSize = rhi->ubufAligned(128);
193 pEntry->m_prefilterVertBuffer = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, ubufElementSize * 6);
194 pEntry->m_prefilterVertBuffer->create();
195
196 const int uBufSamplesSize = 16 * prefilterSampleCount + 8;
197 int uBufSamplesElementSize = rhi->ubufAligned(uBufSamplesSize);
198 pEntry->m_prefilterFragBuffer = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, uBufSamplesElementSize * mipmapCount);
199 pEntry->m_prefilterFragBuffer->create();
200
201 pEntry->m_prefilterPipeline = rhi->newGraphicsPipeline();
202 pEntry->m_prefilterPipeline->setCullMode(QRhiGraphicsPipeline::Front);
203 pEntry->m_prefilterPipeline->setFrontFace(QRhiGraphicsPipeline::CCW);
204 pEntry->m_prefilterPipeline->setDepthOp(QRhiGraphicsPipeline::LessOrEqual);
205 pEntry->m_prefilterPipeline->setShaderStages({
206 *prefilterShaderStages->vertexStage(),
207 *prefilterShaderStages->fragmentStage()
208 });
209
210 pEntry->m_prefilterSrb = rhi->newShaderResourceBindings();
211 pEntry->m_prefilterSrb->setBindings({
215 });
216 pEntry->m_prefilterSrb->create();
217
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");
223
224 const auto &irradianceShaderStages = m_context.shaderCache()->getBuiltInRhiShaders().getRhienvironmentmapPreFilterShader(false /* isRGBE */);
225
226 pEntry->m_irradiancePipeline = rhi->newGraphicsPipeline();
227 pEntry->m_irradiancePipeline->setCullMode(QRhiGraphicsPipeline::Front);
228 pEntry->m_irradiancePipeline->setFrontFace(QRhiGraphicsPipeline::CCW);
229 pEntry->m_irradiancePipeline->setDepthOp(QRhiGraphicsPipeline::LessOrEqual);
230 pEntry->m_irradiancePipeline->setShaderStages({
231 *irradianceShaderStages->vertexStage(),
232 *irradianceShaderStages->fragmentStage()
233 });
234
235 int ubufIrradianceSize = rhi->ubufAligned(20);
236 pEntry->m_irradianceFragBuffer = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, ubufIrradianceSize);
237 pEntry->m_irradianceFragBuffer->create();
238
239 pEntry->m_irradianceSrb = rhi->newShaderResourceBindings();
240 pEntry->m_irradianceSrb->setBindings({
244 });
245 pEntry->m_irradianceSrb->create();
246
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");
252 }
253
254 pEntry->m_timeSlicing = probe.timeSlicing;
255 pEntry->m_probeIndex = probeIdx;
256 Q_QUICK3D_PROFILE_ASSIGN_ID(&probe, pEntry);
257 }
258}
259
261{
262 QSSGReflectionMapEntry *pEntry = reflectionMapEntry(probeIdx);
264 if (!pEntry) {
265 if (probeTexture.m_texture)
266 m_reflectionMapList.push_back(QSSGReflectionMapEntry::withRhiTexturedCubeMap(probeIdx, probeTexture.m_texture));
267 else
268 addReflectionMapEntry(probeIdx, probe);
269 } else {
270 if (pEntry->m_rhiDepthStencil)
271 pEntry->destroyRhiResources();
272 if (probeTexture.m_texture)
273 pEntry->m_rhiPrefilteredCube = probeTexture.m_texture;
274 }
275}
276
278{
279 Q_ASSERT(probeIdx >= 0);
280
281 for (int i = 0; i < m_reflectionMapList.size(); i++) {
282 QSSGReflectionMapEntry *pEntry = &m_reflectionMapList[i];
283 if (pEntry->m_probeIndex == quint32(probeIdx))
284 return pEntry;
285 }
286
287 return nullptr;
288}
289
291 : m_probeIndex(std::numeric_limits<quint32>::max())
292{
293}
294
295// Vertex data for rendering reflection cube map
296static const float cube[] = {
297 -1.0f,-1.0f,-1.0f, // -X side
298 -1.0f,-1.0f, 1.0f,
299 -1.0f, 1.0f, 1.0f,
300 -1.0f, 1.0f, 1.0f,
301 -1.0f, 1.0f,-1.0f,
302 -1.0f,-1.0f,-1.0f,
303
304 -1.0f,-1.0f,-1.0f, // -Z side
305 1.0f, 1.0f,-1.0f,
306 1.0f,-1.0f,-1.0f,
307 -1.0f,-1.0f,-1.0f,
308 -1.0f, 1.0f,-1.0f,
309 1.0f, 1.0f,-1.0f,
310
311 -1.0f,-1.0f,-1.0f, // -Y side
312 1.0f,-1.0f,-1.0f,
313 1.0f,-1.0f, 1.0f,
314 -1.0f,-1.0f,-1.0f,
315 1.0f,-1.0f, 1.0f,
316 -1.0f,-1.0f, 1.0f,
317
318 -1.0f, 1.0f,-1.0f, // +Y side
319 -1.0f, 1.0f, 1.0f,
320 1.0f, 1.0f, 1.0f,
321 -1.0f, 1.0f,-1.0f,
322 1.0f, 1.0f, 1.0f,
323 1.0f, 1.0f,-1.0f,
324
325 1.0f, 1.0f,-1.0f, // +X side
326 1.0f, 1.0f, 1.0f,
327 1.0f,-1.0f, 1.0f,
328 1.0f,-1.0f, 1.0f,
329 1.0f,-1.0f,-1.0f,
330 1.0f, 1.0f,-1.0f,
331
332 -1.0f, 1.0f, 1.0f, // +Z side
333 -1.0f,-1.0f, 1.0f,
334 1.0f, 1.0f, 1.0f,
335 -1.0f,-1.0f, 1.0f,
336 1.0f,-1.0f, 1.0f,
337 1.0f, 1.0f, 1.0f,
338
339 0.0f, 1.0f, // -X side
340 1.0f, 1.0f,
341 1.0f, 0.0f,
342 1.0f, 0.0f,
343 0.0f, 0.0f,
344 0.0f, 1.0f,
345
346 1.0f, 1.0f, // -Z side
347 0.0f, 0.0f,
348 0.0f, 1.0f,
349 1.0f, 1.0f,
350 1.0f, 0.0f,
351 0.0f, 0.0f,
352
353 1.0f, 0.0f, // -Y side
354 1.0f, 1.0f,
355 0.0f, 1.0f,
356 1.0f, 0.0f,
357 0.0f, 1.0f,
358 0.0f, 0.0f,
359
360 1.0f, 0.0f, // +Y side
361 0.0f, 0.0f,
362 0.0f, 1.0f,
363 1.0f, 0.0f,
364 0.0f, 1.0f,
365 1.0f, 1.0f,
366
367 1.0f, 0.0f, // +X side
368 0.0f, 0.0f,
369 0.0f, 1.0f,
370 0.0f, 1.0f,
371 1.0f, 1.0f,
372 1.0f, 0.0f,
373
374 0.0f, 0.0f, // +Z side
375 0.0f, 1.0f,
376 1.0f, 0.0f,
377 0.0f, 1.0f,
378 1.0f, 1.0f,
379 1.0f, 0.0f,
380};
381
383{
384 bits = (bits << 16u) | (bits >> 16u);
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; // / 0x100000000
390}
391
393{
394 return QVector2D(float(i) / float(N), radicalInverseVdC(i));
395}
396
398{
399 float a = roughness*roughness;
400
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);
404
405 // from spherical coordinates to cartesian coordinates
406 return QVector3D(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
407}
408
409float distributionGGX(float nDotH, float roughness)
410{
411 float a = roughness * roughness;
412 float a2 = a * a;
413 float nDotH2 = nDotH * nDotH;
414
415 float nom = a2;
416 float denom = nDotH2 * (a2 - 1.0f) + 1.0f;
417 denom = M_PI * denom * denom;
418
419 return nom / denom;
420}
421
422void fillPrefilterValues(float roughness, float resolution,
423 QVarLengthArray<QVector4D, prefilterSampleCount> &sampleDirections,
424 float &invTotalWeight, uint &sampleCount)
425{
426 for (int i = 0; i < prefilterSampleCount * 8; ++i) {
428 const QVector3D half = importanceSampleGGX(xi, roughness);
429 QVector3D light = 2.0f * half.z() * half - QVector3D(0, 0, 1);
430 light.normalize();
431 const float D = distributionGGX(half.z(), roughness);
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);
434 const float saSample = 1.0f / (float(prefilterSampleCount) * pdf + 0.0001f);
435 float mipLevel = roughness == 0.0f ? 0.0f : 0.5f * log2(saSample / saTexel);
436 if (light.z() > 0) {
437 sampleDirections.append(QVector4D(light, mipLevel));
438 invTotalWeight += light.z();
439 sampleCount++;
440 if (sampleCount >= prefilterSampleCount)
441 break;
442 }
443 }
444 invTotalWeight = 1.0f / invTotalWeight;
445}
446
448{
449 auto *rhi = rhiCtx->rhi();
450 auto *cb = rhiCtx->commandBuffer();
451
452 auto *rub = rhi->nextResourceUpdateBatch();
455 vertexBuffer->create();
456 vertexBuffer->deleteLater();
457 rub->uploadStaticBuffer(vertexBuffer, cube);
458 cb->resourceUpdate(rub);
459
460 const QRhiCommandBuffer::VertexInput vbufBinding(vertexBuffer, 0);
461
462 int ubufElementSize = rhi->ubufAligned(128);
463
464 const int uBufSamplesSize = 16 * prefilterSampleCount + 8;
465 int uBufSamplesElementSize = rhi->ubufAligned(uBufSamplesSize);
466 int uBufIrradianceElementSize = rhi->ubufAligned(20);
467
468 // Uniform Data
469 QMatrix4x4 mvp = rhi->clipSpaceCorrMatrix();
470 mvp.perspective(90.0f, 1.0f, 0.1f, 10.0f);
471
472 auto lookAt = [](const QVector3D &eye, const QVector3D &center, const QVector3D &up) {
473 QMatrix4x4 viewMatrix;
474 viewMatrix.lookAt(eye, center, up);
475 return viewMatrix;
476 };
477 QVarLengthArray<QMatrix4x4, 6> views;
478 views.append(lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(1.0, 0.0, 0.0), QVector3D(0.0f, -1.0f, 0.0f)));
479 views.append(lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(-1.0, 0.0, 0.0), QVector3D(0.0f, -1.0f, 0.0f)));
480 if (rhi->isYUpInFramebuffer()) {
481 views.append(lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0, 1.0, 0.0), QVector3D(0.0f, 0.0f, 1.0f)));
482 views.append(lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0, -1.0, 0.0), QVector3D(0.0f, 0.0f, -1.0f)));
483 } else {
484 views.append(lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0, -1.0, 0.0), QVector3D(0.0f, 0.0f, -1.0f)));
485 views.append(lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0, 1.0, 0.0), QVector3D(0.0f, 0.0f, 1.0f)));
486 }
487 views.append(lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0, 0.0, 1.0), QVector3D(0.0f, -1.0f, 0.0f)));
488 views.append(lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0, 0.0, -1.0), QVector3D(0.0f, -1.0f, 0.0f)));
489
490 rub = rhi->nextResourceUpdateBatch();
491 for (const auto face : QSSGRenderTextureCubeFaces) {
492 rub->updateDynamicBuffer(m_prefilterVertBuffer, quint8(face) * ubufElementSize, 64, mvp.constData());
493 rub->updateDynamicBuffer(m_prefilterVertBuffer, quint8(face) * ubufElementSize + 64, 64, views[quint8(face)].constData());
494 }
495
496 const QSize mapSize = m_rhiCube->pixelSize();
497
498 int mipmapCount = rhi->mipLevelsForSize(mapSize);
499 mipmapCount = qMin(mipmapCount, 6);
500
501 const float resolution = mapSize.width();
502 QVarLengthArray<QVector4D, prefilterSampleCount> sampleDirections;
503
504 // set the samples uniform buffer data
505 for (int mipLevel = 0; mipLevel < mipmapCount - 1; ++mipLevel) {
506 Q_ASSERT(mipmapCount - 2);
507 const float roughness = float(mipLevel) / float(mipmapCount - 2);
508 float invTotalWeight = 0.0f;
509 uint sampleCount = 0;
510
511 sampleDirections.clear();
512 fillPrefilterValues(roughness, resolution, sampleDirections, invTotalWeight, sampleCount);
513
514 rub->updateDynamicBuffer(m_prefilterFragBuffer, mipLevel * uBufSamplesElementSize, 16 * prefilterSampleCount, sampleDirections.constData());
515 rub->updateDynamicBuffer(m_prefilterFragBuffer, mipLevel * uBufSamplesElementSize + 16 * prefilterSampleCount, 4, &invTotalWeight);
516 rub->updateDynamicBuffer(m_prefilterFragBuffer, mipLevel * uBufSamplesElementSize + 16 * prefilterSampleCount + 4, 4, &sampleCount);
517 }
518 {
519 const float roughness = 0.0f; // doesn't matter for irradiance
520 const float lodBias = 0.0f;
521 const int distribution = 0;
522 const int sampleCount = resolution / 4;
523
524 rub->updateDynamicBuffer(m_irradianceFragBuffer, 0, 4, &roughness);
525 rub->updateDynamicBuffer(m_irradianceFragBuffer, 4, 4, &resolution);
526 rub->updateDynamicBuffer(m_irradianceFragBuffer, 4 + 4, 4, &lodBias);
527 rub->updateDynamicBuffer(m_irradianceFragBuffer, 4 + 4 + 4, 4, &sampleCount);
528 rub->updateDynamicBuffer(m_irradianceFragBuffer, 4 + 4 + 4 + 4, 4, &distribution);
529 }
530
531 cb->resourceUpdate(rub);
532
533 // Render
534 for (int mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) {
536 mipLevel = m_timeSliceFrame;
537
538 for (auto face : QSSGRenderTextureCubeFaces) {
541
542 cb->beginPass(m_rhiPrefilterRenderTargetsMap[mipLevel][quint8(face)], QColor(0, 0, 0, 1), { 1.0f, 0 }, nullptr, rhiCtx->commonPassFlags());
543 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(m_rhiPrefilterRenderTargetsMap[mipLevel][quint8(face)]));
544 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
545 if (mipLevel < mipmapCount - 1) {
546 // Specular pre-filtered Cube Map levels
547 cb->setGraphicsPipeline(m_prefilterPipeline);
548 cb->setVertexInput(0, 1, &vbufBinding);
549 cb->setViewport(QRhiViewport(0, 0, m_prefilterMipLevelSizes[mipLevel].width(), m_prefilterMipLevelSizes[mipLevel].height()));
550 QVector<QPair<int, quint32>> dynamicOffsets = {
551 { 0, quint32(ubufElementSize * quint8(face)) },
552 { 2, quint32(uBufSamplesElementSize * mipLevel) }
553 };
554 cb->setShaderResources(m_prefilterSrb, 2, dynamicOffsets.constData());
555 } else {
556 // Diffuse Irradiance
557 cb->setGraphicsPipeline(m_irradiancePipeline);
558 cb->setVertexInput(0, 1, &vbufBinding);
559 cb->setViewport(QRhiViewport(0, 0, m_prefilterMipLevelSizes[mipLevel].width(), m_prefilterMipLevelSizes[mipLevel].height()));
560 QVector<QPair<int, quint32>> dynamicOffsets = {
561 { 0, quint32(ubufElementSize * quint8(face)) },
562 { 2, quint32(uBufIrradianceElementSize) }
563 };
564 cb->setShaderResources(m_irradianceSrb, 1, dynamicOffsets.constData());
565 }
566 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderCall);
567 cb->draw(36);
568 QSSGRHICTX_STAT(rhiCtx, draw(36, 1));
569 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DRenderCall, 36llu | (1llu << 32), profilingId);
570 cb->endPass();
571 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
572 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QSSG_RENDERPASS_NAME("reflection_map", mipLevel, face));
573
575 break;
576 }
577
580 if (m_timeSliceFrame >= mipmapCount)
582 break;
583 }
584 }
585 cb->debugMarkEnd();
586}
587
589{
591 e.m_probeIndex = probeIdx;
592 e.m_rhiPrefilteredCube = prefiltered;
593 return e;
594}
595
598 QRhiTexture *prefiltered,
599 QRhiRenderBuffer *depthStencil)
600{
602 e.m_probeIndex = probeIdx;
603 e.m_rhiCube = cube;
604 e.m_rhiPrefilteredCube = prefiltered;
605 e.m_rhiDepthStencil = depthStencil;
606 return e;
607}
608
610{
611 delete m_rhiCube;
612 m_rhiCube = nullptr;
613 // Without depth stencil the prefiltered cubemap is assumed to be not owned here and shouldn't be deleted
616 m_rhiPrefilteredCube = nullptr;
617 delete m_rhiDepthStencil;
618 m_rhiDepthStencil = nullptr;
619
622 delete m_rhiRenderPassDesc;
623 m_rhiRenderPassDesc = nullptr;
624
625 delete m_prefilterPipeline;
626 m_prefilterPipeline = nullptr;
628 m_irradiancePipeline = nullptr;
629 delete m_prefilterSrb;
630 m_prefilterSrb = nullptr;
631 delete m_irradianceSrb;
632 m_irradianceSrb = nullptr;
634 m_prefilterVertBuffer = nullptr;
636 m_prefilterFragBuffer = nullptr;
638 m_irradianceFragBuffer = nullptr;
641 for (const auto &e : std::as_const(m_rhiPrefilterRenderTargetsMap))
642 qDeleteAll(e);
645}
646
\inmodule QtCore
Definition qbytearray.h:57
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.
Definition qcolor.h:31
void clear()
Definition qmap.h:289
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
void lookAt(const QVector3D &eye, const QVector3D &center, 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.
\inmodule QtGui
Definition qrhi.h:846
@ Immutable
Definition qrhi.h:849
@ Dynamic
Definition qrhi.h:851
@ VertexBuffer
Definition qrhi.h:855
@ UniformBuffer
Definition qrhi.h:857
virtual bool create()=0
Creates the corresponding native graphics resources.
\inmodule QtGui
Definition qrhi.h:576
void setLevel(int level)
Sets the mip level.
Definition qrhi.h:592
void setLayer(int layer)
Sets the layer index.
Definition qrhi.h:589
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
Definition qrhi.h:1680
void setCullMode(CullMode mode)
Sets the specified face culling mode.
Definition qrhi.h:1393
\inmodule QtGui
Definition qrhi.h:1094
Type
Specifies the type of the renderbuffer.
Definition qrhi.h:1096
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
Sets the QRhiRenderPassDescriptor desc for use with this render target.
Definition qrhi.h:1165
void generateMips(QRhiTexture *tex)
Enqueues a mipmap generation operation for the specified texture tex.
Definition qrhi.cpp:9210
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.
Definition qrhi.cpp:8991
void setName(const QByteArray &name)
Sets a name for the object.
Definition qrhi.cpp:3581
void deleteLater()
When called without a frame being recorded, this function is equivalent to deleting the object.
Definition qrhi.cpp:3545
\inmodule QtGui
Definition qrhi.h:1030
@ ClampToEdge
Definition qrhi.h:1040
static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
Definition qrhi.cpp:5640
static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
Definition qrhi.cpp:5600
void setBindings(std::initializer_list< QRhiShaderResourceBinding > list)
Sets the list of bindings.
Definition qrhi.h:1218
void setColorAttachments(std::initializer_list< QRhiColorAttachment > list)
Sets the list of color attachments.
Definition qrhi.h:627
\inmodule QtGui
Definition qrhi.h:1184
void setDescription(const QRhiTextureRenderTargetDescription &desc)
Sets the render target description desc.
Definition qrhi.h:1196
virtual QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor()=0
virtual bool create()=0
Creates the corresponding native graphics resources.
\inmodule QtGui
Definition qrhi.h:895
@ UsedWithGenerateMips
Definition qrhi.h:903
@ MipMapped
Definition qrhi.h:900
@ RenderTarget
Definition qrhi.h:898
@ CubeMap
Definition qrhi.h:899
Format
Specifies the texture format.
Definition qrhi.h:914
@ RGBA16F
Definition qrhi.h:925
QSize pixelSize() const
Definition qrhi.h:975
\inmodule QtGui
Definition qrhi.h:321
void setBindings(std::initializer_list< QRhiVertexInputBinding > list)
Sets the bindings from the specified list.
Definition qrhi.h:325
void setAttributes(std::initializer_list< QRhiVertexInputAttribute > list)
Sets the attributes from the specified list.
Definition qrhi.h:337
\inmodule QtGui
Definition qrhi.h:85
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1804
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
Definition qrhi.cpp:10508
int ubufAligned(int v) const
Definition qrhi.cpp:9999
QMatrix4x4 clipSpaceCorrMatrix() const
Definition qrhi.cpp:10091
bool isYUpInFramebuffer() const
Definition qrhi.cpp:10030
QRhiShaderResourceBindings * newShaderResourceBindings()
Definition qrhi.cpp:10489
QRhiRenderBuffer * newRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount=1, QRhiRenderBuffer::Flags flags={}, QRhiTexture::Format backingFormatHint=QRhiTexture::UnknownFormat)
Definition qrhi.cpp:10535
static int mipLevelsForSize(const QSize &size)
Definition qrhi.cpp:10008
QRhiTextureRenderTarget * newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags={})
Definition qrhi.cpp:10682
QRhiGraphicsPipeline * newGraphicsPipeline()
Definition qrhi.cpp:10466
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
Definition qrhi.cpp:10562
QRhiResourceUpdateBatch * nextResourceUpdateBatch()
Definition qrhi.cpp:9252
static const char * displayName(QSSGRenderTextureCubeFace face)
const std::unique_ptr< QSSGRhiContext > & rhiContext() const
const std::unique_ptr< QSSGBufferManager > & bufferManager() const
const std::unique_ptr< QSSGShaderCache > & shaderCache() const
QSSGReflectionMapEntry * reflectionMapEntry(int probeIdx)
void addTexturedReflectionMapEntry(qint32 probeIdx, const QSSGRenderReflectionProbe &probe)
const QSSGRenderContextInterface & m_context
QSSGRenderReflectionMap(const QSSGRenderContextInterface &inContext)
void addReflectionMapEntry(qint32 probeIdx, const QSSGRenderReflectionProbe &probe)
\inmodule QtQuick3D
QRhiCommandBuffer * commandBuffer() const
QRhiCommandBuffer::BeginPassFlags commonPassFlags() const
QRhi * rhi() const
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
QByteArray toLatin1() const &
Definition qstring.h:630
The QVector2D class represents a vector or vertex in 2D space.
Definition qvectornd.h:31
constexpr float y() const noexcept
Returns the y coordinate of this point.
Definition qvectornd.h:502
constexpr float x() const noexcept
Returns the x coordinate of this point.
Definition qvectornd.h:501
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
void normalize() noexcept
Normalizes the current vector in place.
Definition qvectornd.h:702
constexpr float z() const noexcept
Returns the z coordinate of this point.
Definition qvectornd.h:672
The QVector4D class represents a vector or vertex in 4D space.
Definition qvectornd.h:330
QMap< QString, QString > map
[6]
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
#define qWarning
Definition qlogging.h:166
#define M_PI
Definition qmath.h:209
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint sampler
GLenum face
GLint GLsizei width
GLenum type
GLbitfield flags
GLenum GLuint texture
GLint GLsizei GLsizei GLenum format
GLuint entry
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
static int log2(uint i)
#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)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
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)
#define a2
unsigned int quint32
Definition qtypes.h:50
int qint32
Definition qtypes.h:49
unsigned int uint
Definition qtypes.h:34
unsigned char quint8
Definition qtypes.h:46
myFilter draw(painter, QPoint(0, 0), originalPixmap)
QJSValue cube
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
QRhiRenderPassDescriptor * m_rhiPrefilterRenderPassDesc
QRhiGraphicsPipeline * m_irradiancePipeline
QRhiGraphicsPipeline * m_prefilterPipeline
QMap< int, QVarLengthArray< QRhiTextureRenderTarget *, 6 > > m_rhiPrefilterRenderTargetsMap
void renderMips(QSSGRhiContext *rhiCtx)
QSSGRenderTextureCubeFace m_timeSliceFace
\variable QSSGRhiGraphicsPipelineState::depthFunc