7#include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h>
8#include <QtQuick3DRuntimeRender/private/qssgrenderlight_p.h>
9#include <QtQuick3DRuntimeRender/private/qssgrhicustommaterialsystem_p.h>
10#include <QtQuick3DRuntimeRender/private/qssgrhiquadrenderer_p.h>
11#include <QtQuick3DRuntimeRender/private/qssgrhiparticles_p.h>
12#include <QtQuick3DRuntimeRender/private/qssgrenderlayer_p.h>
13#include <QtQuick3DRuntimeRender/private/qssgrendereffect_p.h>
14#include <QtQuick3DRuntimeRender/private/qssgrendercamera_p.h>
15#include <QtQuick3DRuntimeRender/private/qssgrenderskeleton_p.h>
16#include <QtQuick3DRuntimeRender/private/qssgrenderjoint_p.h>
17#include <QtQuick3DRuntimeRender/private/qssgrendermorphtarget_p.h>
18#include <QtQuick3DRuntimeRender/private/qssgrenderparticles_p.h>
20#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
21#include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h>
22#include <QtQuick3DRuntimeRender/private/qssgperframeallocator_p.h>
23#include <QtQuick3DRuntimeRender/private/qssgruntimerenderlogging_p.h>
24#include <QtQuick3DRuntimeRender/private/qssglightmapper_p.h>
25#include <QtQuick3DRuntimeRender/private/qssgdebugdrawsystem_p.h>
27#include <QtQuick3DUtils/private/qssgutils_p.h>
28#include <QtQuick3DUtils/private/qssgassert_p.h>
30#include <QtQuick/private/qsgtexture_p.h>
31#include <QtQuick/private/qsgrenderer_p.h>
33#include <QtCore/QCoreApplication>
34#include <QtCore/QBitArray>
44#define POS4BONETRANS(x) (sizeof(float) * 16 * (x) * 2)
45#define POS4BONENORM(x) (sizeof(float) * 16 * ((x) * 2 + 1))
46#define BONEDATASIZE4ID(x) POS4BONETRANS(x + 1)
55 if (!supportRgba32f && !supportRgba16f) {
56 static bool warningShown =
false;
58 qWarning () <<
"Particles not supported due to missing RGBA32F and RGBA16F texture format support";
82 QSSG_ASSERT(visibleRenderables.isEmpty(), visibleRenderables.clear());
83 visibleRenderables.reserve(renderables.
size());
86 const auto &
b =
handle.obj->globalBounds;
87 if (clipFrustum.intersectsWith(
b))
88 visibleRenderables.push_back(
handle);
91 return visibleRenderables.size();
100 while (front <= back) {
101 const auto &
b = renderables.
at(front).obj->globalBounds;
102 if (clipFrustum.intersectsWith(
b))
113 return lhs.cameraDistanceSq < rhs.cameraDistanceSq;
118 return lhs.cameraDistanceSq > rhs.cameraDistanceSq;
123 if (node->
type == QSSGRenderGraphObject::Type::Joint) {
126 QMatrix4x4 globalTrans = jointNode->globalTransform;
128 if (poses.size() > jointNode->index)
129 globalTrans *= poses[jointNode->index];
130 memcpy(skeletonNode->boneData.data() +
POS4BONETRANS(jointNode->index),
131 reinterpret_cast<const void *
>(globalTrans.constData()),
134 memcpy(skeletonNode->boneData.data() +
POS4BONENORM(jointNode->index),
138 skeletonNode->containsNonJointNodes =
true;
150 bool dirtyNonJoint = ((node->
type != QSSGRenderGraphObject::Type::Joint)
154 if (node->
type == QSSGRenderGraphObject::Type::Joint)
155 hasChildJoints =
true;
156 bool nodeHasChildJoints =
false;
160 hasChildJoints |= nodeHasChildJoints;
161 if (
ret && nodeHasChildJoints)
165 hasChildJoints |= nodeHasChildJoints;
166 return dirtyNonJoint && nodeHasChildJoints;
169template<
typename T,
typename V>
172 if (dstPos <
dst.size())
179template <
typename T,
typename V>
182 if (dstPos <
dst.size())
183 dst[
dst.size() - dstPos - 1] = node;
185 dst.push_front(node);
190#define MAX_MORPH_TARGET 8
191#define MAX_MORPH_TARGET_INDEX_SUPPORTS_NORMALS 3
192#define MAX_MORPH_TARGET_INDEX_SUPPORTS_TANGENTS 1
195 QVector<QSSGRenderableNodeEntry> &outRenderableModels,
196 int &ioRenderableModelsCount,
197 QVector<QSSGRenderableNodeEntry> &outRenderableParticles,
198 int &ioRenderableParticlesCount,
199 QVector<QSSGRenderItem2D *> &outRenderableItem2Ds,
200 int &ioRenderableItem2DsCount,
201 QVector<QSSGRenderCamera *> &outCameras,
203 QVector<QSSGRenderLight *> &outLights,
205 QVector<QSSGRenderReflectionProbe *> &outReflectionProbes,
206 int &ioReflectionProbeCount,
212 inNode.dfsIndex = ioDFSIndex;
214 if (inNode.type == QSSGRenderNode::Type::Model)
216 else if (inNode.type == QSSGRenderNode::Type::Particles)
218 else if (inNode.type == QSSGRenderNode::Type::Item2D)
225 }
else if (inNode.type == QSSGRenderGraphObject::Type::ReflectionProbe) {
229 for (
auto &theChild : inNode.children)
232 ioRenderableModelsCount,
233 outRenderableParticles,
234 ioRenderableParticlesCount,
235 outRenderableItem2Ds,
236 ioRenderableItem2DsCount,
242 ioReflectionProbeCount,
249 : firstImage(
nullptr), opacity(1.0f), materialKey(inKey), dirty(
false)
259 camera->calculateViewProjectionMatrix(viewProjection);
260 std::optional<QSSGClippingFrustum> clippingFrustum;
261 if (
camera->enableFrustumClipping) {
266 nearPlane.normal =
dir;
273 ret = { viewProjection, clippingFrustum,
camera->getScalingCorrectDirection(),
camera->getGlobalPos() };
282 ensureCachedCameraDatas();
286void QSSGLayerRenderData::ensureCachedCameraDatas()
308 auto &sortedOpaqueObjects = sortedOpaqueObjectCache[
index][&
camera];
309 if (!sortedOpaqueObjects.empty())
310 return sortedOpaqueObjects;
313 sortedOpaqueObjects = std::as_const(opaqueObjectStore)[
index];
316 if (clippingFrustum.has_value()) {
318 sortedOpaqueObjects.resize(visibleObjects);
324 return sortedOpaqueObjects;
331 auto &sortedTransparentObjects = sortedTransparentObjectCache[
index][&
camera];
333 if (!sortedTransparentObjects.empty())
334 return sortedTransparentObjects;
336 sortedTransparentObjects = std::as_const(transparentObjectStore)[
index];
339 const auto &opaqueObjects = std::as_const(opaqueObjectStore)[
index];
340 sortedTransparentObjects.append(opaqueObjects);
344 if (clippingFrustum.has_value()) {
346 sortedTransparentObjects.resize(visibleObjects);
352 return sortedTransparentObjects;
358 const auto &screenTextureObjects = std::as_const(screenTextureObjectStore)[
index];
359 auto &renderedScreenTextureObjects = sortedScreenTextureObjectCache[
index][&
camera];
361 if (!renderedScreenTextureObjects.empty())
362 return renderedScreenTextureObjects;
363 renderedScreenTextureObjects = screenTextureObjects;
364 if (!renderedScreenTextureObjects.empty()) {
368 return renderedScreenTextureObjects;
396 const QVector3D &cameraDirection = cameraDirectionAndPosition.direction;
397 const QVector3D &cameraPosition = cameraDirectionAndPosition.position;
399 const auto isItemNodeDistanceGreatThan = [cameraDirection, cameraPosition]
401 if (!lhs->parent || !rhs->parent)
403 const QVector3D lhsDifference = lhs->parent->getGlobalPos() - cameraPosition;
405 const QVector3D rhsDifference = rhs->parent->getGlobalPos() - cameraPosition;
407 return lhsCameraDistanceSq > rhsCameraDistanceSq;
410 const auto isItemZOrderLessThan = []
412 if (lhs->parent && rhs->parent && lhs->parent == rhs->parent) {
414 return lhs->zOrder < rhs->zOrder;
432 auto &depthWriteObjects = sortedDepthWriteCache[
index][&
camera];
433 auto &depthPrepassObjects = sortedOpaqueDepthPrepassCache[
index][&
camera];
435 if (!depthWriteObjects.isEmpty() || !depthPrepassObjects.isEmpty())
439 if (hasDepthWriteObjects || (depthPrepassObjectsState & DepthPrepassObjectStateT(DepthPrepassObject::Opaque)) != 0) {
441 for (
const auto &opaqueObject : sortedOpaqueObjects) {
442 const auto depthMode = opaqueObject.obj->depthWriteMode;
444 depthWriteObjects.append(opaqueObject);
446 depthPrepassObjects.append(opaqueObject);
449 if (hasDepthWriteObjects || (depthPrepassObjectsState & DepthPrepassObjectStateT(DepthPrepassObject::Transparent)) != 0) {
451 for (
const auto &transparentObject : sortedTransparentObjects) {
452 const auto depthMode = transparentObject.obj->depthWriteMode;
454 depthWriteObjects.append(transparentObject);
456 depthPrepassObjects.append(transparentObject);
459 if (hasDepthWriteObjects || (depthPrepassObjectsState & DepthPrepassObjectStateT(DepthPrepassObject::ScreenTexture)) != 0) {
461 for (
const auto &screenTextureObject : sortedScreenTextureObjects) {
462 const auto depthMode = screenTextureObject.obj->depthWriteMode;
464 depthWriteObjects.append(screenTextureObject);
466 depthPrepassObjects.append(screenTextureObject);
474 return ctx.perFrameAllocator();
485 const auto index = extContexts.size();
488 auto it = std::find_if(extContexts.cbegin(), extContexts.cend(), [&ext, slot](
const ExtensionContext &e){ return (e.owner == &ext) && (e.slot == slot); });
489 if (
it == extContexts.cend()) {
490 extContexts.push_back({ &ext,
camera, {}, {},
index, slot });
491 it = extContexts.cbegin() +
index;
492 renderableModelStore.emplace_back();
493 modelContextStore.emplace_back();
494 renderableObjectStore.emplace_back();
495 screenTextureObjectStore.emplace_back();
496 opaqueObjectStore.emplace_back();
497 transparentObjectStore.emplace_back();
498 sortedOpaqueObjectCache.emplace_back();
499 sortedTransparentObjectCache.emplace_back();
500 sortedScreenTextureObjectCache.emplace_back();
501 sortedOpaqueDepthPrepassCache.emplace_back();
502 sortedDepthWriteCache.emplace_back();
503 QSSG_ASSERT(renderableModelStore.size() == extContexts.size(), renderableModelStore.resize(extContexts.size()));
504 QSSG_ASSERT(modelContextStore.size() == extContexts.size(), modelContextStore.resize(extContexts.size()));
505 QSSG_ASSERT(renderableObjectStore.size() == extContexts.size(), renderableObjectStore.resize(extContexts.size()));
506 QSSG_ASSERT(screenTextureObjectStore.size() == extContexts.size(), screenTextureObjectStore.resize(extContexts.size()));
507 QSSG_ASSERT(opaqueObjectStore.size() == extContexts.size(), opaqueObjectStore.resize(extContexts.size()));
508 QSSG_ASSERT(transparentObjectStore.size() == extContexts.size(), transparentObjectStore.resize(extContexts.size()));
509 QSSG_ASSERT(sortedOpaqueObjectCache.size() == extContexts.size(), sortedOpaqueObjectCache.resize(extContexts.size()));
510 QSSG_ASSERT(sortedTransparentObjectCache.size() == extContexts.size(), sortedTransparentObjectCache.resize(extContexts.size()));
511 QSSG_ASSERT(sortedScreenTextureObjectCache.size() == extContexts.size(), sortedScreenTextureObjectCache.resize(extContexts.size()));
512 QSSG_ASSERT(sortedOpaqueDepthPrepassCache.size() == extContexts.size(), sortedOpaqueDepthPrepassCache.resize(extContexts.size()));
513 QSSG_ASSERT(sortedDepthWriteCache.size() == extContexts.size(), sortedDepthWriteCache.resize(extContexts.size()));
522 for (
auto &chld : children) {
523 if (chld.type == QSSGRenderGraphObject::Type::Model) {
525 auto &renderableModels =
layer.renderableModels;
526 if (
auto it = std::find_if(renderableModels.cbegin(), renderableModels.cend(), [&renderModel](
const QSSGRenderableNodeEntry &e) {
return (e.node == &renderModel); });
it != renderableModels.
cend()) {
529 renderableModels.erase(
it);
544 auto &renderables = renderableModelStore[
index];
545 if (renderables.size() != 0) {
546 qWarning() <<
"Renderables already created for this context - Previous renderables will be overwritten";
550 renderables.reserve(nodes.size());
555 for (
const auto &nodeId : nodes) {
556 auto *node = QSSGRenderGraphObjectUtils::getNode<QSSGRenderNode>(nodeId);
557 if (node && node->type == QSSGRenderGraphObject::Type::Model) {
561 auto &inserted = renderables.emplace_back(*
it);
562 inserted.overridden = {};
566 renderables.emplace_back(*renderModel);
571 const auto &children = node->children;
584 QSSG_ASSERT_X(
index < renderableModelStore.size(),
"Missing call to createRenderables()?",
return);
586 auto &renderables = renderableModelStore[
index];
588 if (
it != renderables.
cend()) {
589 it->globalTransform = globalTransform;
598 QSSG_ASSERT_X(
index < renderableModelStore.size(),
"Missing call to createRenderables()?",
return {});
601 auto &renderables = renderableModelStore[
index];
604 ret =
it->globalTransform;
614 QSSG_ASSERT_X(
index < renderableModelStore.size(),
"Missing call to createRenderables()?",
return);
616 auto &renderables = renderableModelStore[
index];
618 if (
it != renderables.
cend()) {
619 it->globalOpacity = opacity;
628 QSSG_ASSERT_X(
index < renderableModelStore.size(),
"Missing call to createRenderables()?",
return {});
631 auto &renderables = renderableModelStore[
index];
634 ret =
it->globalOpacity;
650 auto &renderables = renderableModelStore[
index];
652 if (
it != renderables.
cend()) {
653 it->materials.resize(materials.size());
667 auto &renderables = renderableModelStore[
index];
668 for (
auto &renderable : renderables) {
669 auto &renderableMaterials = renderable.materials;
670 renderableMaterials.resize(materials.size());
671 std::memcpy(renderableMaterials.data(), materials.data(), renderableMaterials.size() *
sizeof(
QSSGRenderGraphObject *));
686 const auto &extContext = extContexts.at(
index);
688 QSSG_ASSERT_X(extContext.camera !=
nullptr,
"No camera set!",
return {});
691 extContext.camera->calculateGlobalVariables(vp);
693 auto &renderables = renderableModelStore[
index];
695 prepareModelMaterials(renderables,
true );
706 auto &renderableObjects = renderableObjectStore[
index];
707 QSSG_ASSERT(renderableObjects.isEmpty(), renderableObjects.clear());
709 auto &opaqueObjects = opaqueObjectStore[
index];
710 QSSG_ASSERT(opaqueObjects.isEmpty(), opaqueObjects.clear());
712 auto &transparentObjects = transparentObjectStore[
index];
713 QSSG_ASSERT(transparentObjects.isEmpty(), transparentObjects.clear());
715 auto &screenTextureObjects = screenTextureObjectStore[
index];
716 QSSG_ASSERT(screenTextureObjects.isEmpty(), screenTextureObjects.clear());
726 screenTextureObjects,
745 Q_UNREACHABLE_RETURN(0);
752 QSSGRenderablesFilters
filter)
758 auto &extCtx = extContexts[
index];
773 OpaquePass::prep(
ctx, *
this, passKey, psCpy, featureSet, renderPassDescriptor, sortedRenderables);
775 extCtx.ps[psIndex] = psCpy;
788 extCtx.ps[psIndex] = psCpy;
798 const auto &extCtx = extContexts.at(
index);
799 const auto filter = extCtx.filter;
803 const auto &ps = extCtx.ps[psIndex];
810 const auto &ps = extCtx.ps[psIndex];
825 return sortedOpaqueDepthPrepassCache[
index][&
camera];;
832template <
typename T,
typename... Args>
835 static_assert(std::is_trivially_destructible_v<T>,
"Objects allocated using the per-frame allocator needs to be trivially destructible!");
842 static_assert(std::is_trivially_destructible_v<T>,
"Objects allocated using the per-frame allocator needs to be trivially destructible!");
843 const size_t asize =
sizeof(T) *
count;
860 int shadowMapCount = 0;
861 for (
int lightIdx = 0, lightEnd =
lights.size(); lightIdx < lightEnd; ++lightIdx) {
863 const bool isDirectional = theLight->type == QSSGRenderLight::Type::DirectionalLight;
864 const bool isSpot = theLight->type == QSSGRenderLight::Type::SpotLight;
865 const bool castsShadows = theLight->m_castShadow
866 && !theLight->m_fullyBaked
872 defaultMaterialShaderKeyProperties.
m_lightFlags[lightIdx].
setValue(theGeneratedKey, !isDirectional);
877 return theGeneratedKey;
892 if (inImage.clearDirty())
907 if (
texture.m_flags.hasTransparency()
908 && (inMapType == QSSGRenderableImage::Type::Diffuse
909 || inMapType == QSSGRenderableImage::Type::Opacity
910 || inMapType == QSSGRenderableImage::Type::Translucency))
919 switch (inImage.m_mappingMode) {
923 theKeyProp.setEnvMap(inShaderKey,
true);
926 theKeyProp.setLightProbe(inShaderKey,
true);
936 switch (
texture.m_texture->format()) {
950 if (inImage.isImageTransformIdentity())
951 theKeyProp.setIdentityTransform(inShaderKey,
true);
953 if (inImage.m_indexUV == 1)
954 theKeyProp.setUsesUV1(inShaderKey,
true);
956 if (
texture.m_flags.isLinear())
957 theKeyProp.setLinear(inShaderKey,
true);
959 if (ioFirstImage ==
nullptr)
960 ioFirstImage = theImage;
962 ioNextImage->m_nextImage = theImage;
964 ioNextImage = theImage;
971 switch (inImageIndex) {
973 value = inMaterial->opacityChannel;
976 value = inMaterial->roughnessChannel;
979 value = inMaterial->metalnessChannel;
982 value = inMaterial->occlusionChannel;
985 value = inMaterial->translucencyChannel;
988 value = inMaterial->heightChannel;
991 value = inMaterial->clearcoatChannel;
994 value = inMaterial->clearcoatRoughnessChannel;
997 value = inMaterial->transmissionChannel;
1000 value = inMaterial->thicknessChannel;
1003 value = inMaterial->baseColorChannel;
1006 value = inMaterial->specularAmountChannel;
1009 value = inMaterial->emissiveChannel;
1014 bool useDefault =
false;
1069 retval.renderableFlags = inExistingFlags;
1072 retval.opacity = inOpacity;
1073 float &subsetOpacity(retval.opacity);
1075 if (theMaterial->isDirty())
1078 subsetOpacity *= theMaterial->opacity;
1097 defaultMaterialShaderKeyProperties.
m_alphaMode.
setValue(theGeneratedKey, theMaterial->alphaMode);
1108 defaultMaterialShaderKeyProperties.
m_specularGlossyEnabled.
setValue(theGeneratedKey, theMaterial->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial);
1118 defaultMaterialShaderKeyProperties.
m_viewCount.
setValue(theGeneratedKey, rhiCtx->mainPassViewCount());
1119 defaultMaterialShaderKeyProperties.
m_usesViewIndex.
setValue(theGeneratedKey, rhiCtx->mainPassViewCount() >= 2);
1121 if (!defaultMaterialShaderKeyProperties.
m_hasIbl.
getValue(theGeneratedKey) && theMaterial->iblProbe) {
1123 defaultMaterialShaderKeyProperties.
m_hasIbl.
setValue(theGeneratedKey,
true);
1145 || theMaterial->opacityMap
1151 const bool specularEnabled = theMaterial->isSpecularEnabled();
1152 const bool metalnessEnabled = theMaterial->isMetalnessEnabled();
1154 if (specularEnabled || metalnessEnabled)
1166 theMaterial->isBaseColorSingleChannelEnabled());
1168 theMaterial->isSpecularAmountSingleChannelEnabled());
1170 theMaterial->isEmissiveSingleChannelEnabled());
1172 theMaterial->isInvertOpacityMapValue());
1174 theMaterial->isVertexColorsEnabled());
1176 theMaterial->isVertexColorsMaskEnabled());
1178 theMaterial->vertexColorRedMask.toInt());
1180 quint16(theMaterial->vertexColorGreenMask.toInt()));
1182 quint16(theMaterial->vertexColorBlueMask.toInt()));
1184 quint16(theMaterial->vertexColorAlphaMask.toInt()));
1187 theMaterial->isClearcoatEnabled());
1189 theMaterial->isTransmissionEnabled());
1195#define CHECK_IMAGE_AND_PREPARE(img, imgtype, shadercomponent) \
1197 prepareImageForRender(*(img), imgtype, firstImage, nextImage, renderableFlags, \
1198 theGeneratedKey, shadercomponent, &inMaterial)
1200 if (theMaterial->type == QSSGRenderGraphObject::Type::PrincipledMaterial ||
1201 theMaterial->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial) {
1203 QSSGRenderableImage::Type::BaseColor,
1206 QSSGRenderableImage::Type::Occlusion,
1209 QSSGRenderableImage::Type::Height,
1212 QSSGRenderableImage::Type::Clearcoat,
1215 QSSGRenderableImage::Type::ClearcoatRoughness,
1218 QSSGRenderableImage::Type::ClearcoatNormal,
1221 QSSGRenderableImage::Type::Transmission,
1224 QSSGRenderableImage::Type::Thickness,
1226 if (theMaterial->type == QSSGRenderGraphObject::Type::PrincipledMaterial) {
1228 QSSGRenderableImage::Type::Metalness,
1233 QSSGRenderableImage::Type::Diffuse,
1238 QSSGRenderableImage::Type::Specular,
1241 QSSGRenderableImage::Type::Roughness,
1246 QSSGRenderableImage::Type::SpecularAmountMap,
1250 QSSGRenderableImage::Type::Translucency,
1253#undef CHECK_IMAGE_AND_PREPARE
1256 subsetOpacity = 0.0f;
1265 subsetOpacity = 1.f;
1269 if (inMaterial.isTransmissionEnabled()) {
1270 ioFlags.setRequiresScreenTexture(
true);
1271 ioFlags.setRequiresMipmapsForScreenTexture(
true);
1275 retval.firstImage = firstImage;
1276 if (retval.renderableFlags.isDirty())
1277 retval.dirty =
true;
1279 renderer->addMaterialDirtyClear(&inMaterial);
1290 lights, inExistingFlags.receivesShadows()));
1291 retval.renderableFlags = inExistingFlags;
1294 retval.opacity = inOpacity;
1295 float &subsetOpacity(retval.opacity);
1298 subsetOpacity = 0.0f;
1307 subsetOpacity = 1.f;
1344 defaultMaterialShaderKeyProperties.
m_viewCount.
setValue(theGeneratedKey, rhiCtx->mainPassViewCount());
1358 ioFlags.setRequiresScreenTexture(
true);
1363 ioFlags.setRequiresScreenTexture(
true);
1364 ioFlags.setRequiresMipmapsForScreenTexture(
true);
1369 ioFlags.setRequiresDepthTexture(
true);
1372 ioFlags.setRequiresDepthTexture(
true);
1373 ioFlags.setRequiresSsaoPass(
true);
1376 retval.firstImage =
nullptr;
1378 if (retval.dirty || alreadyDirty)
1379 renderer->addMaterialDirtyClear(&inMaterial);
1384template <CullUnrenderables cull = CullUnrenderables::On>
1387 const auto originalModelCount = renderableModels.
size();
1388 auto end = originalModelCount;
1390 for (
int idx = 0; idx <
end; ++idx) {
1391 const auto &renderable = renderableModels.
at(idx);
1399 if (isDisabled || renderable.materials.isEmpty()) {
1410 if (
end != originalModelCount)
1415void QSSGLayerRenderData::prepareModelMaterials(RenderableNodeEntries &renderableModels,
bool cullUnrenderables)
1417 if (cullUnrenderables)
1424 RenderableNodeEntries &renderableModels,
1425 bool globalPickingEnabled)
1430 auto end = originalModelCount;
1432 for (
int idx = 0; idx <
end; ++idx) {
1443 if (
auto *theMesh = bufferManager->loadMesh(&
model)) {
1444 renderable.mesh = theMesh;
1449 && (globalPickingEnabled
1451 if (canModelBePickable) {
1453 if (!theMesh->bvh) {
1454 if (!
model.meshPath.isNull())
1455 theMesh->bvh = bufferManager->loadMeshBVH(
model.meshPath);
1456 else if (
model.geometry)
1457 theMesh->bvh = bufferManager->loadMeshBVH(
model.geometry);
1460 const auto &roots = theMesh->bvh->roots();
1462 theMesh->subsets[
i].bvhRoot = roots[
i];
1475 if (
end != originalModelCount)
1482 bufferManager->commitBufferResourceUpdates();
1487 lightmapTextures[&modelContext] = lightmapTexture;
1494 const auto it = lightmapTextures.
constFind(&modelContext);
1495 ret = (
it != lightmapTextures.
cend()) ? *
it :
nullptr;
1503 bonemapTextures[&modelContext] = bonemapTexture;
1510 const auto it = bonemapTextures.
constFind(&modelContext);
1511 ret = (
it != bonemapTextures.
cend()) ? *
it :
nullptr;
1536 const bool maybeDebugDraw = debugDrawSystem && debugDrawSystem->isEnabled();
1538 bool wasDirty =
false;
1545 const auto &
lights = renderable.lights;
1548 QSSG_ASSERT_X(theMesh !=
nullptr,
"Only renderables with a mesh will be processed!",
continue);
1551 const auto &globalTransform = altGlobalTransform ? renderable.globalTransform :
model.globalTransform;
1556 const auto &meshSubsets = theMesh->subsets;
1557 const auto meshSubsetCount = meshSubsets.size();
1558 theModelContext.subsets = RENDER_FRAME_NEW_BUFFER<QSSGSubsetRenderable>(
contextInterface, meshSubsetCount);
1562 auto boneTexture = bufferManager->loadSkinmap(
model.skin);
1564 }
else if (
model.skeleton) {
1565 auto boneTexture = bufferManager->loadSkinmap(&(
model.skeleton->boneTexData));
1574 if (meshSubsetCount > 0) {
1577 renderableFlagsForModel.setCastsShadows(
model.castsShadows);
1578 renderableFlagsForModel.setReceivesShadows(
model.receivesShadows);
1579 renderableFlagsForModel.setReceivesReflections(
model.receivesReflections);
1580 renderableFlagsForModel.setCastsReflections(
model.castsReflections);
1582 renderableFlagsForModel.setUsedInBakedLighting(
model.usedInBakedLighting);
1583 if (
model.hasLightmap()) {
1585 if (lmImageTexture.m_texture) {
1586 renderableFlagsForModel.setRendersWithLightmap(
true);
1596 bool hasJoint =
false;
1597 bool hasWeight =
false;
1598 bool hasMorphTarget = theSubset.rhi.targetsTexture !=
nullptr;
1599 for (
const QSSGRhiInputAssemblerState::InputSemantic &
sem : std::as_const(theSubset.rhi.ia.inputs)) {
1600 if (
sem == QSSGRhiInputAssemblerState::PositionSemantic) {
1601 renderableFlagsForModel.setHasAttributePosition(
true);
1602 }
else if (
sem == QSSGRhiInputAssemblerState::NormalSemantic) {
1603 renderableFlagsForModel.setHasAttributeNormal(
true);
1604 }
else if (
sem == QSSGRhiInputAssemblerState::TexCoord0Semantic) {
1605 renderableFlagsForModel.setHasAttributeTexCoord0(
true);
1606 }
else if (
sem == QSSGRhiInputAssemblerState::TexCoord1Semantic) {
1607 renderableFlagsForModel.setHasAttributeTexCoord1(
true);
1608 }
else if (
sem == QSSGRhiInputAssemblerState::TexCoordLightmapSemantic) {
1609 renderableFlagsForModel.setHasAttributeTexCoordLightmap(
true);
1610 }
else if (
sem == QSSGRhiInputAssemblerState::TangentSemantic) {
1611 renderableFlagsForModel.setHasAttributeTangent(
true);
1612 }
else if (
sem == QSSGRhiInputAssemblerState::BinormalSemantic) {
1613 renderableFlagsForModel.setHasAttributeBinormal(
true);
1614 }
else if (
sem == QSSGRhiInputAssemblerState::ColorSemantic) {
1615 renderableFlagsForModel.setHasAttributeColor(
true);
1618 }
else if (
sem == QSSGRhiInputAssemblerState::JointSemantic) {
1620 }
else if (
sem == QSSGRhiInputAssemblerState::WeightSemantic) {
1624 renderableFlagsForModel.setHasAttributeJointAndWeight(hasJoint && hasWeight);
1625 renderableFlagsForModel.setHasAttributeMorphTarget(hasMorphTarget);
1629 bool usesBlendParticles = particlesEnabled && theModelContext.model.particleBuffer !=
nullptr
1630 &&
model.particleBuffer->particleCount();
1633 auto &renderableSubsets = theModelContext.subsets;
1634 const auto &materials = renderable.materials;
1635 const auto materialCount = materials.size();
1637 const float modelOpacity = altModelOpacity ? renderable.globalOpacity :
model.globalOpacity;
1639 int idx = 0, subsetIdx = 0;
1640 for (; idx < meshSubsetCount; ++idx) {
1643 QSSG_ASSERT_X(theMaterialObject !=
nullptr,
"No material found for model!",
continue);
1647 float subsetOpacity = modelOpacity;
1652 bool usesInstancing = theModelContext.model.instancing()
1654 if (usesInstancing && theModelContext.model.instanceTable->hasTransparency())
1656 if (theModelContext.model.hasTransparency)
1660 quint32 subsetLevelOfDetail = 0;
1661 if (!theSubset.lods.isEmpty() && lodThreshold > 0.0f) {
1663 float lodDistanceMultiplier =
cameras[0]->getLevelOfDetailMultiplier();
1664 float distanceThreshold = 0.0f;
1668 if (
cameras[0]->
type != QSSGRenderGraphObject::Type::OrthographicCamera) {
1670 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1671 debugDrawSystem->drawBounds(transformedBounds,
QColor(
Qt::red));
1677 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1678 debugDrawSystem->drawPoint(lodSupportMin,
QColor(
"orange"));
1680 const float distanceMin = cameraPlane.distance(lodSupportMin);
1681 const float distanceMax = cameraPlane.distance(lodSupportMax);
1683 if (distanceMin * distanceMax < 0.0)
1684 distanceThreshold = 0.0;
1685 else if (distanceMin >= 0.0)
1686 distanceThreshold = distanceMin;
1687 else if (distanceMax <= 0.0)
1688 distanceThreshold = -distanceMax;
1692 distanceThreshold = 1.0;
1695 int currentLod = -1;
1696 if (
model.levelOfDetailBias > 0.0f) {
1697 const float threshold = distanceThreshold * lodDistanceMultiplier;
1698 const float modelBias = 1 /
model.levelOfDetailBias;
1699 for (
qsizetype i = 0;
i < theSubset.lods.count(); ++
i) {
1700 float subsetDistance = theSubset.lods[
i].distance * modelScale * modelBias;
1701 float screenSize = subsetDistance / threshold;
1702 if (screenSize > lodThreshold)
1707 if (currentLod == -1)
1708 subsetLevelOfDetail = 0;
1710 subsetLevelOfDetail = currentLod + 1;
1711 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1712 debugDrawSystem->drawBounds(transformedBounds, QSSGDebugDrawSystem::levelOfDetailColor(subsetLevelOfDetail));
1715 QVector3D theModelCenter(theSubset.bounds.center());
1717 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLodNormal))
1718 debugDrawSystem->debugNormals(*bufferManager, theModelContext, theSubset, subsetLevelOfDetail, (theModelCenter - allCameras[0]->getGlobalPos()).
length() * 0.01);
1728 qWarning() <<
"WARN: Model has non-integer type indices for skinning but current RHI backend doesn't support it!";
1732 if (theMaterialObject->type == QSSGRenderGraphObject::Type::DefaultMaterial ||
1733 theMaterialObject->type == QSSGRenderGraphObject::Type::PrincipledMaterial ||
1734 theMaterialObject->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial) {
1738 subsetOpacity = theMaterialPrepResult.opacity;
1740 wasDirty |= theMaterialPrepResult.dirty;
1741 renderableFlags = theMaterialPrepResult.renderableFlags;
1747 const auto boneCount =
model.skin ?
model.skin->boneCount :
1748 model.skeleton ?
model.skeleton->boneCount : 0;
1750 if (
auto idJoint = theSubset.rhi.ia.inputs.indexOf(QSSGRhiInputAssemblerState::JointSemantic); idJoint != -1) {
1751 const auto attr = theSubset.rhi.ia.inputLayout.attributeAt(idJoint);
1759 theSubset.rhi.ia.targetCount);
1761 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::PositionSemantic]);
1763 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::NormalSemantic]);
1765 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TangentSemantic]);
1767 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::BinormalSemantic]);
1769 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord0Semantic]);
1771 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord1Semantic]);
1773 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::ColorSemantic]);
1775 new (theRenderableObject)
QSSGSubsetRenderable(QSSGSubsetRenderable::Type::DefaultMaterialMeshSubset,
1782 subsetLevelOfDetail,
1787 wasDirty = wasDirty || renderableFlags.
isDirty();
1788 }
else if (theMaterialObject->type == QSSGRenderGraphObject::Type::CustomMaterial) {
1792 wasDirty |= theMaterialSystem->prepareForRender(theModelContext.model, theSubset, theMaterial);
1795 prepareCustomMaterialForRender(theMaterial, renderableFlags, subsetOpacity, wasDirty,
1798 subsetOpacity = theMaterialPrepResult.opacity;
1800 renderableFlags = theMaterialPrepResult.renderableFlags;
1802 if (
model.particleBuffer &&
model.particleBuffer->particleCount())
1808 const auto boneCount =
model.skin ?
model.skin->boneCount :
1809 model.skeleton ?
model.skeleton->boneCount : 0;
1811 if (
auto idJoint = theSubset.rhi.ia.inputs.indexOf(QSSGRhiInputAssemblerState::JointSemantic); idJoint != -1) {
1812 const auto attr = theSubset.rhi.ia.inputLayout.attributeAt(idJoint);
1817 bool usesInstancing = theModelContext.model.instancing()
1822 theSubset.rhi.ia.targetCount);
1824 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::PositionSemantic]);
1826 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::NormalSemantic]);
1828 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TangentSemantic]);
1830 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::BinormalSemantic]);
1832 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord0Semantic]);
1834 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord1Semantic]);
1836 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::ColorSemantic]);
1838 if (theMaterial.m_iblProbe)
1839 theMaterial.m_iblProbe->clearDirty();
1841 new (theRenderableObject)
QSSGSubsetRenderable(QSSGSubsetRenderable::Type::CustomMaterialMeshSubset,
1848 subsetLevelOfDetail,
1854 if (theRenderableObject)
1860 renderableSubsets.mSize = subsetIdx + 1;
1862 for (
auto &ro : renderableSubsets) {
1863 const auto depthMode = ro.depthWriteMode;
1866 static constexpr DepthPrepassObject ppState[][2] = { {DepthPrepassObject::None, DepthPrepassObject::ScreenTexture},
1867 {DepthPrepassObject::None, DepthPrepassObject::Transparent},
1868 {DepthPrepassObject::None, DepthPrepassObject::Opaque} };
1870 if (ro.renderableFlags.requiresScreenTexture()) {
1872 screenTextureObjects.push_back({&ro, ro.camdistSq});
1873 }
else if (ro.renderableFlags.hasTransparency()) {
1875 transparentObjects.push_back({&ro, ro.camdistSq});
1878 opaqueObjects.push_back({&ro, ro.camdistSq});
1881 if (ro.renderableFlags.usedInBakedLighting())
1882 bakedLightingObjects.push_back({&ro, ro.camdistSq});
1885 if (!bakedLightingObjects.isEmpty())
1901 auto &opaqueObjects = opaqueObjectStore[0];
1902 auto &transparentObjects = transparentObjectStore[0];
1903 auto &screenTextureObjects = screenTextureObjectStore[0];
1907 const auto &
lights = renderable.lights;
1932 firstImage = theImage;
1945 colorTable = theImage;
1949 auto *theRenderableObject = RENDER_FRAME_NEW<QSSGParticlesRenderable>(
contextInterface,
1958 if (theRenderableObject) {
1959 if (theRenderableObject->renderableFlags.requiresScreenTexture())
1960 screenTextureObjects.push_back({theRenderableObject,
getCameraDistanceSq(*theRenderableObject, cameraData)});
1961 else if (theRenderableObject->renderableFlags.hasTransparency())
1962 transparentObjects.push_back({theRenderableObject,
getCameraDistanceSq(*theRenderableObject, cameraData)});
1964 opaqueObjects.push_back({theRenderableObject,
getCameraDistanceSq(*theRenderableObject, cameraData)});
1977 const auto &clipSpaceCorrMatrix = ctxIfc.rhiContext()->rhi()->clipSpaceCorrMatrix();
1980 theItem2D->mvps.clear();
1982 QMatrix4x4 mvp = camData.viewProjection * theItem2D->globalTransform;
1983 static const QMatrix4x4 flipMatrix(1.0f, 0.0f, 0.0f, 0.0f,
1984 0.0f, -1.0f, 0.0f, 0.0f,
1985 0.0f, 0.0f, 1.0f, 0.0f,
1986 0.0f, 0.0f, 0.0f, 1.0f);
1987 mvp = clipSpaceCorrMatrix * mvp * flipMatrix;
1988 theItem2D->mvps.append(mvp);
2001 for (
const auto resourceLoader : std::as_const(
layer.resourceLoaders))
2010 for (
int i = 0;
i < probeCount;
i++) {
2013 int reflectionObjectCount = 0;
2019 && !(
handle.obj->type == QSSGRenderableObject::Type::Particles)) {
2024 vmin = renderableObj->globalTransform * vmin;
2025 vmax = renderableObj->globalTransform * vmax;
2026 nodeBound.minimum = vmin.toVector3D();
2027 nodeBound.maximum = vmax.toVector3D();
2028 if (probeBound.intersects(nodeBound)) {
2029 QVector3D nodeBoundCenter = nodeBound.center();
2030 QVector3D probeBoundCenter = probeBound.center();
2032 if (renderableObj->reflectionProbeIndex == -1 || distance < renderableObj->distanceFromReflectionProbe) {
2033 renderableObj->reflectionProbeIndex =
i;
2034 renderableObj->distanceFromReflectionProbe =
distance;
2036 renderableObj->reflectionProbe.probeCubeMapCenter = probe->
getGlobalPos();
2037 renderableObj->reflectionProbe.probeBoxMax = probeBound.maximum;
2038 renderableObj->reflectionProbe.probeBoxMin = probeBound.minimum;
2039 renderableObj->reflectionProbe.enabled =
true;
2040 reflectionObjectCount++;
2046 const auto &transparentObjects = std::as_const(transparentObjectStore[0]);
2047 const auto &opaqueObjects = std::as_const(opaqueObjectStore[0]);
2048 const auto &screenTextureObjects = std::as_const(screenTextureObjectStore[0]);
2050 for (
const auto &
handle : std::as_const(transparentObjects))
2053 for (
const auto &
handle : std::as_const(opaqueObjects))
2056 for (
const auto &
handle : std::as_const(screenTextureObjects))
2060 reflectionMapManager->addTexturedReflectionMapEntry(
i, *probe);
2061 else if (reflectionObjectCount > 0)
2062 reflectionMapManager->addReflectionMapEntry(
i, *probe);
2070 if (node == lightScope)
2091 QSet<QSSGRenderSkeleton *> dirtySkeletons;
2092 for (
const auto &node : std::as_const(renderableNodes)) {
2093 if (node.node->type == QSSGRenderGraphObject::Type::Model) {
2095 auto skeletonNode = modelNode->
skeleton;
2098 const bool dirtySkeleton = dirtySkeletons.contains(skeletonNode);
2099 const bool hasDirtyNonJoints = (skeletonNode->containsNonJointNodes
2102 if (skeletonNode->skinningDirty || hasDirtyNonJoints || dirtyTransform) {
2103 skeletonNode->boneTransformsDirty =
false;
2104 if (hasDirtyNonJoints && !dirtySkeleton)
2105 dirtySkeletons.insert(skeletonNode);
2106 skeletonNode->skinningDirty =
false;
2108 if (skeletonNode->boneData.size() <
dataSize)
2109 skeletonNode->boneData.resize(
dataSize);
2110 skeletonNode->calculateGlobalVariables();
2111 skeletonNode->containsNonJointNodes =
false;
2112 for (
auto &
child : skeletonNode->children)
2115 skeletonNode->boneCount = skeletonNode->boneData.size() / 2 / 4 / 16;
2116 const int boneTexWidth =
qCeil(
qSqrt(skeletonNode->boneCount * 4 * 2));
2117 skeletonNode->boneTexData.setSize(
QSize(boneTexWidth, boneTexWidth));
2118 skeletonNode->boneData.resize(boneTexWidth * boneTexWidth * 16);
2119 skeletonNode->boneTexData.setTextureData(skeletonNode->boneData);
2121 const int numMorphTarget = modelNode->morphTargets.size();
2122 for (
int i = 0;
i < numMorphTarget; ++
i) {
2124 modelNode->morphWeights[
i] = morphTarget->
weight;
2125 modelNode->morphAttributes[
i] = morphTarget->attributes;
2127 modelNode->morphAttributes[
i] &= 0x1;
2129 modelNode->morphAttributes[
i] &= 0x3;
2134 dirtySkeletons.clear();
2150 ps.
viewport = { float(theViewport.x()), float(theViewport.y()), float(theViewport.width()), float(theViewport.height()), 0.0f, 1.0f };
2151 if (
layer.scissorRect.isValid()) {
2154 theViewport.height() - (
layer.scissorRect.y() +
layer.scissorRect.height()),
2155 layer.scissorRect.width(),
2156 layer.scissorRect.height() };
2165 bool wasDirty =
false;
2166 bool wasDataDirty =
false;
2167 wasDirty =
layer.isDirty();
2172 const bool SSAOEnabled =
layer.ssaoEnabled();
2177 bool requiresDepthTexture = SSAOEnabled;
2178 for (
QSSGRenderEffect *theEffect =
layer.firstEffect; theEffect; theEffect = theEffect->m_nextEffect) {
2179 if (theEffect->isDirty()) {
2181 theEffect->clearDirty();
2183 if (theEffect->requiresDepthTexture)
2184 requiresDepthTexture =
true;
2190 if (!
layer.firstEffect)
2201 static bool notified =
false;
2204 qCDebug(lcQuick3DRender,
"Qt Quick 3D maximum number of lights has been reduced from %d to %d due to the graphics driver's limitations",
2211 if (
layer.lightProbe) {
2212 const auto &lightProbeSettings =
layer.lightProbeSettings;
2222 if (
layer.lightProbe->clearDirty())
2223 wasDataDirty =
true;
2237 layer.lightProbe =
nullptr;
2249 int renderableModelsCount = 0;
2250 int renderableParticlesCount = 0;
2251 int renderableItem2DsCount = 0;
2252 int cameraNodeCount = 0;
2253 int lightNodeCount = 0;
2254 int reflectionProbeCount = 0;
2256 for (
auto &theChild :
layer.children)
2259 renderableModelsCount,
2261 renderableParticlesCount,
2263 renderableItem2DsCount,
2269 reflectionProbeCount,
2279 if (
cameras.size() != cameraNodeCount)
2280 cameras.resize(cameraNodeCount);
2281 if (
lights.size() != lightNodeCount)
2282 lights.resize(lightNodeCount);
2291 if (!
layer.explicitCameras.isEmpty()) {
2294 wasDataDirty = wasDataDirty || cam->isDirty();
2296 wasDataDirty = wasDataDirty || theResult.
m_wasDirty;
2297 if (!theResult.m_computeFrustumSucceeded)
2298 qCCritical(INTERNAL_ERROR,
"Failed to calculate camera frustum");
2308 wasDataDirty = wasDataDirty || theCamera->isDirty();
2310 wasDataDirty = wasDataDirty || theResult.
m_wasDirty;
2311 if (!theResult.m_computeFrustumSucceeded)
2312 qCCritical(INTERNAL_ERROR,
"Failed to calculate camera frustum");
2321 float meshLodThreshold = 1.0f;
2323 meshLodThreshold =
renderedCameras[0]->levelOfDetailPixelThreshold / theViewport.width();
2334 int shadowMapCount = 0;
2335 bool hasScopedLights =
false;
2341 if (showLightCountWarning) {
2342 qWarning(
"Too many lights in scene, maximum is %d", maxLightCount);
2355 hasScopedLights |= (renderLight->m_scope !=
nullptr);
2356 const bool mightCastShadows = renderLight->
m_castShadow && !renderLight->m_fullyBaked;
2358 shadowMapCount += int(shadows);
2359 const auto &
direction = renderLight->getScalingCorrectDirection();
2369 if (shadowMapCount > 0) {
2372 for (
int i = 0,
end = renderableLights.size();
i !=
end; ++
i) {
2373 const auto &shaderLight = renderableLights.at(
i);
2374 if (shaderLight.shadows) {
2375 quint32 mapSize = shaderLight.light->m_shadowMapRes;
2376 ShadowMapModes mapMode = (shaderLight.light->type != QSSGRenderLight::Type::DirectionalLight)
2379 shadowMapManager->addShadowMapEntry(
i,
2383 shaderLight.light->debugObjectName);
2398 if (hasScopedLights) {
2399 for (
const auto &shaderLight : std::as_const(renderableLights)) {
2400 if (!shaderLight.light->m_scope)
2404 const auto prepareLightsWithScopedLights = [&renderableLights,
this](QVector<QSSGRenderableNodeEntry> &renderableNodes) {
2405 for (
qint32 idx = 0,
end = renderableNodes.size(); idx <
end; ++idx) {
2408 for (
const auto &light : std::as_const(renderableLights)) {
2409 if (light.light->m_scope && !
scopeLight(theNodeEntry.node, light.light->m_scope))
2414 if (filteredLights.isEmpty()) {
2420 auto customLightList = RENDER_FRAME_NEW_BUFFER<QSSGShaderLight>(*
renderer->
contextInterface(), filteredLights.size());
2421 std::copy(filteredLights.cbegin(), filteredLights.cend(), customLightList.begin());
2422 theNodeEntry.lights = customLightList;
2432 const auto prepareLights = [
this](QVector<QSSGRenderableNodeEntry> &renderableNodes) {
2433 for (
qint32 idx = 0,
end = renderableNodes.size(); idx <
end; ++idx) {
2443 bool hasUserExtensions =
false;
2450 const auto &renderExtensions =
layer.renderExtensions[
i];
2452 for (
auto rit = renderExtensions.crbegin(), rend = renderExtensions.crend(); rit != rend; ++rit) {
2453 hasUserExtensions =
true;
2454 if ((*rit)->prepareData(frameData)) {
2467 auto &opaqueObjects = opaqueObjectStore[0];
2468 auto &transparentObjects = transparentObjectStore[0];
2469 auto &screenTextureObjects = screenTextureObjectStore[0];
2473 if (particlesEnabled) {
2474 const auto &cameraDatas = getCachedCameraDatas();
2482 wasDirty = wasDirty || wasDataDirty;
2487 const bool animating = wasDirty;
2489 layer.progAAPassIndex = 0;
2492 layer.progressiveAAIsActive = progressiveAA;
2495 layer.temporalAAIsActive = temporalAA;
2499 if (progressiveAA &&
layer.progAAPassIndex > 0 &&
layer.progAAPassIndex <
quint32(
layer.antialiasingQuality)) {
2500 int idx =
layer.progAAPassIndex - 1;
2505 const int t = 1 - 2 * (
layer.tempAAPassIndex % 2);
2506 const float f =
t *
layer.temporalAAStrength;
2507 vertexOffsetsAA = {
f / float(theViewport.width()/2.0),
f / float(theViewport.height()/2.0) };
2511 if (temporalAA || progressiveAA ) {
2515 offsetProjection(0, 3) -= vertexOffsetsAA.x();
2516 offsetProjection(1, 3) -= vertexOffsetsAA.y();
2518 offsetProjection(0, 2) += vertexOffsetsAA.x();
2519 offsetProjection(1, 2) += vertexOffsetsAA.y();
2523 modelContext->modelViewProjections[mvpIdx] = offsetProjection * invProjection * modelContext->modelViewProjections[mvpIdx];
2528 const bool hasItem2Ds = (renderableItem2DsCount > 0);
2531 const bool depthTestEnableDefault = layerEnableDepthTest && (!opaqueObjects.isEmpty() || depthPrepassObjectsState || hasDepthWriteObjects);
2532 const bool zPrePassForced = (depthPrepassObjectsState != 0);
2533 zPrePassActive = zPrePassForced || (layerEnabledDepthPrePass && layerEnableDepthTest && (hasDepthWriteObjects || hasItem2Ds));
2534 const bool depthWriteEnableDefault = depthTestEnableDefault && (!layerEnabledDepthPrePass || !zPrePassActive);
2566 if (underlayPass.hasData())
2569 const bool hasOpaqueObjects = (opaqueObjects.size() > 0);
2571 if (hasOpaqueObjects)
2590 if (transparentObjects.size() > 0 || (!layerEnableDepthTest && hasOpaqueObjects))
2594 if (overlayPass.hasData())
2597 if (
layer.gridEnabled)
2607 for (
auto &e :
entry)
2614 pass->resetForFrame();
2623 lightmapTextures.
clear();
2624 bonemapTextures.
clear();
2628 hasDepthWriteObjects =
false;
2629 depthPrepassObjectsState = { DepthPrepassObjectStateT(DepthPrepassObject::None) };
2630 zPrePassActive =
false;
2669 const float horizontalMagnification = inCamera.horizontalMagnification;
2670 const float verticalMagnification = inCamera.verticalMagnification;
2672 inCamera.horizontalMagnification *=
layer->ssaaEnabled ?
layer->ssaaMultiplier : 1.0f;
2673 inCamera.verticalMagnification *=
layer->ssaaEnabled ?
layer->ssaaMultiplier : 1.0f;
2675 inCamera.horizontalMagnification = horizontalMagnification;
2676 inCamera.verticalMagnification = verticalMagnification;
2691 pass->resetForFrame();
2693 for (
auto &renderResult : renderResults)
2694 renderResult.
reset();
2700 sortData.resize(
count);
2721 for (
auto &
s : sortData)
2722 *dest++ = instance[
s.indexOrOffset];
2727 const QVector3D &cameraPosition,
float minThreshold,
float maxThreshold)
2732 const float x = cameraPosition.
x() - instance->
row0.
w();
2733 const float y = cameraPosition.
y() - instance->
row1.
w();
2734 const float z = cameraPosition.
z() - instance->
row2.
w();
2735 const float distanceSq =
x *
x +
y *
y +
z *
z;
2736 if (distanceSq >= minThreshold * minThreshold && (maxThreshold < 0 || distanceSq < maxThreshold * maxThreshold))
2753 auto &modelContext = renderable->modelContext;
2754 auto &instanceBuffer = renderable->instanceBuffer;
2755 if (!modelContext.model.instancing() || instanceBuffer)
2756 return instanceBuffer;
2757 auto *
table = modelContext.model.instanceTable;
2758 bool usesLod = minThreshold >= 0 || maxThreshold >= 0;
2762 bool sortingChanged =
table->isDepthSortingEnabled() != instanceData.
sorting;
2763 bool cameraDirectionChanged = !
qFuzzyCompare(instanceData.sortedCameraDirection, cameraDirection);
2764 bool cameraPositionChanged = !
qFuzzyCompare(instanceData.cameraPosition, cameraPosition);
2765 bool updateInstanceBuffer =
table->serial() != instanceData.serial || sortingChanged || (cameraDirectionChanged &&
table->isDepthSortingEnabled());
2766 bool updateForLod = cameraPositionChanged && usesLod;
2767 if (sortingChanged && !
table->isDepthSortingEnabled()) {
2768 instanceData.sortedData.clear();
2769 instanceData.sortData.clear();
2770 instanceData.sortedCameraDirection = {};
2772 instanceData.sorting =
table->isDepthSortingEnabled();
2773 if (instanceData.buffer && instanceData.buffer->size() < instanceBufferSize) {
2774 updateInstanceBuffer =
true;
2776 instanceData.buffer->setSize(instanceBufferSize);
2777 instanceData.buffer->create();
2779 if (!instanceData.buffer) {
2781 updateInstanceBuffer =
true;
2783 instanceData.buffer->
create();
2785 if (updateInstanceBuffer || updateForLod) {
2786 const void *
data =
nullptr;
2787 if (
table->isDepthSortingEnabled()) {
2788 if (updateInstanceBuffer) {
2790 instanceData.sortedData.resize(
table->dataSize());
2792 instanceData.sortData,
2796 invGlobalTransform.map(cameraDirection).normalized());
2798 data = instanceData.sortedData.constData();
2799 instanceData.sortedCameraDirection = cameraDirection;
2805 if (
table->isDepthSortingEnabled()) {
2806 instanceData.lodData.resize(
table->dataSize());
2807 cullLodInstances(instanceData.lodData, instanceData.sortedData.constData(), instanceData.sortedData.size(), cameraPosition, minThreshold, maxThreshold);
2808 data = instanceData.lodData.constData();
2810 instanceData.lodData.resize(
table->dataSize());
2812 data = instanceData.lodData.constData();
2820 qWarning() <<
"NO DATA IN INSTANCE TABLE";
2822 instanceData.serial =
table->serial();
2823 instanceData.cameraPosition = cameraPosition;
2825 instanceBuffer = instanceData.buffer;
2826 return instanceBuffer;
2832 static bool bakeRequested =
false;
2833 static bool bakeFlagChecked =
false;
2834 if (!bakeFlagChecked) {
2835 bakeFlagChecked =
true;
2838 bakeRequested = cmdLineReq || envReq;
2861 for (
int i = 0, ie = sortedBakedLightingModels.size();
i != ie; ++
i)
2865 cb->debugMarkBegin(
"Quick3D lightmap baking");
2870 qDebug(
"Lightmap baking done, exiting application");
2917 if (
const auto &rhiCtx =
ctx.rhiContext(); rhiCtx->isValid()) {
2918 QRhi *rhi = rhiCtx->rhi();
2931 return shadowMapManager;
2938 return reflectionMapManager;
static void prep(const QSSGRenderContextInterface &ctx, QSSGLayerRenderData &data, QSSGPassKey passKey, QSSGRhiGraphicsPipelineState &ps, QSSGShaderFeatures shaderFeatures, QRhiRenderPassDescriptor *rpDesc, const QSSGRenderableObjectList &sortedOpaqueObjects)
static void render(const QSSGRenderContextInterface &ctx, const QSSGRhiGraphicsPipelineState &ps, const QSSGRenderableObjectList &sortedOpaqueObjects)
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
The QColor class provides colors based on RGB, HSV or CMYK values.
static QStringList arguments()
const_iterator constFind(const Key &key) const noexcept
const_iterator cend() const noexcept
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
qsizetype size() const noexcept
bool isEmpty() const noexcept
reference emplace_back(Args &&... args)
void swapItemsAt(qsizetype i, qsizetype j)
void push_back(parameter_type t)
const_reference at(qsizetype i) const noexcept
void resize(qsizetype size)
const_iterator cend() const noexcept
const_iterator cbegin() const noexcept
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
QMatrix4x4 inverted(bool *invertible=nullptr) const
Returns the inverse of this matrix.
const float * constData() const
Returns a constant pointer to the raw data of this matrix.
\inmodule QtCore\reentrant
constexpr qreal height() const noexcept
Returns the height of the rectangle.
constexpr qreal width() const noexcept
Returns the width of the rectangle.
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
\inmodule QtCore\reentrant
virtual bool create()=0
Creates the corresponding native graphics resources.
void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
Sometimes committing resource updates is necessary or just more convenient without starting a render ...
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.
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
bool isClipDepthZeroToOne() const
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags={}) const
bool isYUpInFramebuffer() const
QRhiResourceUpdateBatch * nextResourceUpdateBatch()
Class representing 3D range or axis aligned bounding box.
static Q_ALWAYS_INLINE QSSGBounds3 centerExtents(const QVector3D ¢er, const QVector3D &extent)
returns the AABB from center and extents vectors.
Q_ALWAYS_INLINE QVector3D center() const
returns the center of this axis aligned box.
QVector3D getSupport(const QVector3D &direction) const
static QSSGBounds3 transform(const QMatrix3x3 &matrix, const QSSGBounds3 &bounds)
gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
QVector< QSSGBakedLightingModel > renderedBakedLightingModels
const QSSGRenderableObjectList & getSortedTransparentRenderableObjects(const QSSGRenderCamera &camera, size_t index=0)
QRhiTexture * getLightmapTexture(const QSSGModelContext &modelContext) const
QSSGLayerRenderPreparationResult layerPrepResult
static qsizetype frustumCullingInline(const QSSGClippingFrustum &clipFrustum, QSSGRenderableObjectList &renderables)
void setVertexInputPresence(const QSSGRenderableObjectFlags &renderableFlags, QSSGShaderDefaultMaterialKey &key)
bool prepareItem2DsForRender(const QSSGRenderContextInterface &ctxIfc, const RenderableItem2DEntries &renderableItem2Ds)
const QSSGRenderableObjectList & getSortedScreenTextureRenderableObjects(const QSSGRenderCamera &camera, size_t index=0)
QSSGLightmapper::Callback lightmapBakingOutputCallback
void prepareResourceLoaders()
QVarLengthArray< QSSGRenderPass *, 16 > activePasses
QMatrix4x4 getGlobalTransform(QSSGPrepContextId prepId, const QSSGRenderModel &model)
QSSGShaderFeatures getShaderFeatures() const
QVector< QSSGBakedLightingModel > bakedLightingModels
QSSGPrepContextId getOrCreateExtensionContext(const QSSGRenderExtension &ext, QSSGRenderCamera *camera=nullptr, quint32 slot=0)
QSSGFrameData & getFrameData()
void prepareReflectionProbesForRender()
void setLightmapTexture(const QSSGModelContext &modelContext, QRhiTexture *lightmapTexture)
InfiniteGridPass infiniteGridPass
DebugDrawPass debugDrawPass
bool tooManyLightsWarningShown
QSSGLayerRenderData(QSSGRenderLayer &inLayer, QSSGRenderer &inRenderer)
void prepareImageForRender(QSSGRenderImage &inImage, QSSGRenderableImage::Type inMapType, QSSGRenderableImage *&ioFirstImage, QSSGRenderableImage *&ioNextImage, QSSGRenderableObjectFlags &ioFlags, QSSGShaderDefaultMaterialKey &ioGeneratedShaderKey, quint32 inImageIndex, QSSGRenderDefaultMaterial *inMaterial=nullptr)
SkyboxCubeMapPass skyboxCubeMapPass
void setGlobalTransform(QSSGRenderablesId renderablesId, const QSSGRenderModel &model, const QMatrix4x4 &mvp)
const QSSGRenderReflectionMapPtr & requestReflectionMapManager()
static void setTonemapFeatures(QSSGShaderFeatures &features, QSSGRenderLayer::TonemapMode tonemapMode)
float getGlobalOpacity(QSSGPrepContextId prepId, const QSSGRenderModel &model)
QSSGLightmapper * m_lightmapper
const QSSGRenderableObjectList & getSortedrenderedOpaqueDepthPrepassObjects(const QSSGRenderCamera &camera, size_t index=0)
QSSGShaderDefaultMaterialKey generateLightingKey(QSSGRenderDefaultMaterial::MaterialLighting inLightingType, const QSSGShaderLightListView &lights, bool receivesShadows=true)
ReflectionMapPass reflectionMapPass
void renderRenderables(QSSGRenderContextInterface &ctx, QSSGPrepResultId prepId)
QSSGRenderablesId createRenderables(QSSGPrepContextId prepId, const QList< QSSGNodeId > &nodes, QSSGRenderHelpers::CreateFlags createFlags)
static GlobalRenderProperties globalRenderProperties(const QSSGRenderContextInterface &ctx)
RenderableNodeEntries renderableModels
const QVector< QSSGBakedLightingModel > & getSortedBakedLightingModels()
bool interactiveLightmapBakingRequested
ScreenReflectionPass reflectionPass
void setModelMaterials(QSSGRenderablesId renderablesId, const QSSGRenderModel &model, const QList< QSSGResourceId > &materials)
bool prepareParticlesForRender(const RenderableNodeEntries &renderableParticles, const QSSGRenderCameraData &cameraData)
bool tooManyShadowLightsWarningShown
const RenderableItem2DEntries & getRenderableItem2Ds()
QRhiTexture * getBonemapTexture(const QSSGModelContext &modelContext) const
static qsizetype frustumCulling(const QSSGClippingFrustum &clipFrustum, const QSSGRenderableObjectList &renderables, QSSGRenderableObjectList &visibleRenderables)
static bool prepareInstancing(QSSGRhiContext *rhiCtx, QSSGSubsetRenderable *renderable, const QVector3D &cameraDirection, const QVector3D &cameraPosition, float minThreshold, float maxThreshold)
ZPrePassPass zPrePassPass
RenderableItem2DEntries renderedItem2Ds
ShadowMapPass shadowMapPass
QSSGRenderContextInterface * contextInterface() const
void setGlobalOpacity(QSSGRenderablesId renderablesId, const QSSGRenderModel &model, float opacity)
const QSSGRenderableObjectList & getSortedRenderedDepthWriteObjects(const QSSGRenderCamera &camera, size_t index=0)
ScreenMapPass screenMapPass
QSSGRenderCameraData getCameraRenderData(const QSSGRenderCamera *camera)
void setBonemapTexture(const QSSGModelContext &modelContext, QRhiTexture *bonemapTexture)
DepthMapPass depthMapPass
const QSSGRenderShadowMapPtr & requestShadowMapManager()
QVector< QSSGRenderLight * > lights
UserPass userPasses[USERPASSES]
QVector< QSSGRenderItem2D * > renderableItem2Ds
bool prepareModelsForRender(QSSGRenderContextInterface &ctx, const RenderableNodeEntries &renderableModels, QSSGLayerRenderPreparationResultFlags &ioFlags, const QSSGRenderCameraList &allCameras, const QSSGRenderCameraDataList &allCameraData, TModelContextPtrList &modelContexts, QSSGRenderableObjectList &opaqueObjects, QSSGRenderableObjectList &transparentObjects, QSSGRenderableObjectList &screenTextureObjects, float lodThreshold=0.0f)
QVector< QSSGRenderReflectionProbe * > reflectionProbes
QVector< QSSGRenderCamera * > cameras
void prepareRenderables(QSSGRenderContextInterface &ctx, QSSGPrepResultId prepId, QRhiRenderPassDescriptor *renderPassDescriptor, const QSSGRhiGraphicsPipelineState &ps, QSSGRenderablesFilters filter)
QSSGShaderLightList globalLights
QSSGRenderGraphObject * getCamera(QSSGCameraId id) const
const QSSGRenderableObjectList & getSortedOpaqueRenderableObjects(const QSSGRenderCamera &camera, size_t index=0)
TModelContextPtrList modelContexts
static constexpr size_t USERPASSES
RenderableNodeEntries renderableParticles
QSSGRenderCameraList renderedCameras
std::optional< QSSGRenderCameraDataList > renderedCameraData
static const std::unique_ptr< QSSGPerFrameAllocator > & perFrameAllocator(QSSGRenderContextInterface &ctx)
TransparentPass transparentPass
qsizetype add(const QSSGBakedLightingModel &model)
void setOptions(const QSSGLightmapperOptions &options)
void setOutputCallback(Callback callback)
Representation of a plane.
const std::unique_ptr< QSSGRhiContext > & rhiContext() const
const std::unique_ptr< QSSGDebugDrawSystem > & debugDrawSystem() const
const std::unique_ptr< QSSGCustomMaterialSystem > & customMaterialSystem() const
const std::unique_ptr< QSSGBufferManager > & bufferManager() const
const std::unique_ptr< QSSGRenderer > & renderer() const
static constexpr bool isCamera(Type type) noexcept
static constexpr bool isRenderable(Type type) noexcept
static constexpr bool isMaterial(Type type) noexcept
static constexpr bool isLight(Type type) noexcept
static bool isGlobalPickingEnabled(const QSSGRenderer &renderer)
constexpr quint32 frameCount() const
QSSGRenderContextInterface * contextInterface() const
static QSSGRhiContextPrivate * get(QSSGRhiContext *q)
QRhiCommandBuffer * commandBuffer() const
QRhiGraphicsPipeline::PolygonMode polygonMode
QRhiGraphicsPipeline::CompareOp depthFunc
const_iterator cend() const noexcept
void push_back(const T &t)
The QVector2D class represents a vector or vertex in 2D space.
The QVector3D class represents a vector or vertex in 3D space.
QT_WARNING_POP float distanceToPoint(QVector3D point) const noexcept
constexpr float y() const noexcept
Returns the y coordinate of this point.
constexpr float x() const noexcept
Returns the x coordinate of this point.
static constexpr float dotProduct(QVector3D v1, QVector3D v2) noexcept
Returns the dot product of v1 and v2.
constexpr float z() const noexcept
Returns the z coordinate of this point.
The QVector4D class represents a vector or vertex in 4D space.
constexpr float w() const noexcept
Returns the w coordinate of this point.
static void render(const QSSGRenderContextInterface &ctx, const QSSGRhiGraphicsPipelineState &ps, const QSSGRenderableObjectList &sortedTransparentObjects)
static void prep(const QSSGRenderContextInterface &ctx, QSSGLayerRenderData &data, QSSGPassKey passKey, QSSGRhiGraphicsPipelineState &ps, QSSGShaderFeatures shaderFeatures, QRhiRenderPassDescriptor *rpDesc, const QSSGRenderableObjectList &sortedTransparentObjects)
QList< QSSGRenderExtension * > extensions
list append(new Employee("Blackpool", "Stephen"))
QSet< QString >::iterator it
T * getResource(QSSGResourceId resId)
constexpr quint32 nextMultipleOf4(quint32 value)
QVector3D Q_QUICK3DUTILS_EXPORT transform(const QMatrix3x3 &m, const QVector3D &v)
QVector3D Q_QUICK3DUTILS_EXPORT transform(const QMatrix4x4 &m, const QVector3D &v)
QVector3D Q_QUICK3DUTILS_EXPORT getScale(const QMatrix4x4 &m)
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
#define Q_STATIC_ASSERT(Condition)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
size_t qHash(const QFileSystemWatcherPathKey &key, size_t seed=0)
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
qfloat16 qSqrt(qfloat16 f)
#define Q_LOGGING_CATEGORY(name,...)
#define qCCritical(category,...)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLuint64 GLenum void * handle
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
const void GLsizei GLsizei stride
GLsizei GLsizei GLfloat distance
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLenum GLuint GLsizei const GLenum * props
GLenum GLenum GLenum GLenum GLenum scale
GLenum GLenum GLsizei void * table
static QT_BEGIN_NAMESPACE qreal dpr(const QWindow *w)
#define QSSG_ASSERT_X(cond, msg, action)
#define QSSG_ASSERT(cond, action)
void updateDirtySkeletons(const QVector< QSSGRenderableNodeEntry > &renderableNodes)
static constexpr size_t getPrepContextIndex(QSSGPrepContextId id)
static bool scopeLight(QSSGRenderNode *node, QSSGRenderNode *lightScope)
static void collectNodeFront(V node, QVector< T > &dst, int &dstPos)
static constexpr bool furthestToNearestCompare(const QSSGRenderableObjectHandle &lhs, const QSSGRenderableObjectHandle &rhs) noexcept
static constexpr bool verifyPrepContext(QSSGPrepContextId id, const QSSGRenderer &renderer)
#define MAX_MORPH_TARGET_INDEX_SUPPORTS_NORMALS
static void clearTable(std::vector< T > &entry)
#define MAX_MORPH_TARGET_INDEX_SUPPORTS_TANGENTS
static const QVector2D s_ProgressiveAAVertexOffsets[QSSGLayerRenderData::MAX_AA_LEVELS]
static constexpr quint16 PREP_CTX_INDEX_MASK
static const int REDUCED_MAX_LIGHT_COUNT_THRESHOLD_BYTES
static bool checkParticleSupport(QRhi *rhi)
#define BONEDATASIZE4ID(x)
static void sortInstances(QByteArray &sortedData, QList< QSSGRhiSortData > &sortData, const void *instances, int stride, int count, const QVector3D &cameraDirection)
#define CHECK_IMAGE_AND_PREPARE(img, imgtype, shadercomponent)
static constexpr bool nearestToFurthestCompare(const QSSGRenderableObjectHandle &lhs, const QSSGRenderableObjectHandle &rhs) noexcept
static constexpr size_t pipelineStateIndex(QSSGRenderablesFilter filter)
static void cullLodInstances(QByteArray &lodData, const void *instances, int count, const QVector3D &cameraPosition, float minThreshold, float maxThreshold)
QSSGDataRef< T > RENDER_FRAME_NEW_BUFFER(QSSGRenderContextInterface &ctx, size_t count)
static void prepareModelMaterialsImpl(QSSGLayerRenderData::RenderableNodeEntries &renderableModels)
static void collectBoneTransforms(QSSGRenderNode *node, QSSGRenderSkeleton *skeletonNode, const QVector< QMatrix4x4 > &poses)
static bool hasDirtyNonJointNodes(QSSGRenderNode *node, bool &hasChildJoints)
static int effectiveMaxLightCount(const QSSGShaderFeatures &features)
static QSSGRenderCameraData getCameraDataImpl(const QSSGRenderCamera *camera)
static bool maybeQueueNodeForRender(QSSGRenderNode &inNode, QVector< QSSGRenderableNodeEntry > &outRenderableModels, int &ioRenderableModelsCount, QVector< QSSGRenderableNodeEntry > &outRenderableParticles, int &ioRenderableParticlesCount, QVector< QSSGRenderItem2D * > &outRenderableItem2Ds, int &ioRenderableItem2DsCount, QVector< QSSGRenderCamera * > &outCameras, int &ioCameraCount, QVector< QSSGRenderLight * > &outLights, int &ioLightCount, QVector< QSSGRenderReflectionProbe * > &outReflectionProbes, int &ioReflectionProbeCount, quint32 &ioDFSIndex)
static constexpr QSSGPrepContextId createPrepId(size_t index, quint32 frame)
T * RENDER_FRAME_NEW(QSSGRenderContextInterface &ctx, Args &&... args)
void collectNode(V node, QVector< T > &dst, int &dstPos)
static float getCameraDistanceSq(const QSSGRenderableObject &obj, const QSSGRenderCameraData &camera) noexcept
static void createRenderablesHelper(QSSGLayerRenderData &layer, const QSSGRenderNode::ChildList &children, QSSGLayerRenderData::RenderableNodeEntries &renderables, QSSGRenderHelpers::CreateFlags createFlags)
#define QSSG_RENDER_MINIMUM_RENDER_OPACITY
std::shared_ptr< QSSGRenderReflectionMap > QSSGRenderReflectionMapPtr
std::shared_ptr< QSSGRenderShadowMap > QSSGRenderShadowMapPtr
@ VSM
variance shadow mapping
@ CUBE
cubemap omnidirectional shadows
#define QSSG_REDUCED_MAX_NUM_LIGHTS
#define QSSG_MAX_NUM_LIGHTS
#define QSSG_MAX_NUM_SHADOW_MAPS
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 int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
unsigned long long quint64
QSqlQueryModel * model
[16]
QSvgRenderer * renderer
[0]
QSSGDefaultMaterialPreparationResult(QSSGShaderDefaultMaterialKey inMaterialKey)
void setRequiresSsaoPass(bool inValue)
bool requiresDepthTexture() const
void setLayerDataDirty(bool inValue)
void setWasDirty(bool inValue)
bool requiresScreenTexture() const
bool requiresShadowMapPass() const
void setRequiresDepthTexture(bool inValue)
bool requiresSsaoPass() const
void setRequiresShadowMapPass(bool inValue)
bool isLayerVisible() const
QSSGLayerRenderPreparationResultFlags flags
QSize textureDimensions() const
QSSGCameraGlobalCalculationResult setupCameraForRender(QSSGRenderCamera &inCamera, float dpr=1.0f)
QSSGLayerRenderPreparationResult()=default
const QSSGRenderModel & model
int particleCount() const
QSSGBounds3 bounds() const
std::optional< QSSGClippingFrustum > clippingFrustum
@ InverseProjectionMatrix
QSSGRenderImageTextureFlags m_flags
@ EnableDepthPrePass
True when we render a depth pass before.
QSSGRenderSkeleton * skeleton
bool usesBoneTexture() const
QVector< QSSGRenderGraphObject * > materials
bool calculateGlobalVariables()
QMatrix4x4 globalTransform
QVector3D getGlobalPos() const
constexpr bool isDirty(DirtyFlag dirtyFlag=DirtyFlag::DirtyMask) const
QSSGRenderImage * m_colorTable
QSSGRenderImage * m_sprite
QSSGParticleBuffer m_particleBuffer
QSSGRenderImage * texture
void setPointsTopology(bool v)
bool hasAttributeTexCoordLightmap() const
void setHasAttributePosition(bool b)
bool hasAttributePosition() const
void setHasAttributeNormal(bool b)
void setHasAttributeColor(bool b)
bool hasAttributeNormal() const
void setHasAttributeTexCoord0(bool b)
bool hasAttributeBinormal() const
void setCastsReflections(bool inCastsReflections)
void setCastsShadows(bool inCastsShadows)
bool hasAttributeJointAndWeight() const
bool hasAttributeColor() const
bool hasAttributeTangent() const
bool hasAttributeTexCoord1() const
bool hasAttributeTexCoord0() const
void setHasTransparency(bool inHasTransparency)
void setReceivesShadows(bool inReceivesShadows)
QSSGShaderKeyBoolean m_usesInverseProjectionMatrix
QSSGShaderKeyUnsigned< 4 > m_debugMode
QSSGShaderKeyBoolean m_usesProjectionMatrix
QSSGShaderKeyUnsigned< 8 > m_targetTexCoord1Offset
QSSGShaderKeyBoolean m_vertexColorsMaskEnabled
QSSGShaderKeyBoolean m_lightSpotFlags[LightCount]
QSSGShaderKeyUnsigned< 4 > m_lightCount
QSSGShaderKeyBoolean m_baseColorSingleChannelEnabled
QSSGShaderKeyBoolean m_fogEnabled
QSSGShaderKeyBoolean m_usesInstancing
QSSGShaderKeyBoolean m_blendParticles
QSSGShaderKeyBoolean m_hasLighting
@ SingleChannelImagesFirst
QSSGShaderKeyTextureChannel m_textureChannels[SingleChannelImageCount]
QSSGShaderKeyBoolean m_clearcoatEnabled
QSSGShaderKeyUnsigned< 16 > m_vertexColorAlphaMask
QSSGShaderKeyBoolean m_transmissionEnabled
QSSGShaderKeyBoolean m_lightmapEnabled
QSSGShaderKeyBoolean m_usesVarColor
QSSGShaderKeyBoolean m_overridesPosition
QSSGShaderKeyBoolean m_isDoubleSided
QSSGShaderKeyImageMap m_imageMaps[ImageMapCount]
QSSGShaderKeySpecularModel m_specularModel
QSSGShaderKeyBoolean m_usesFloatJointIndices
QSSGShaderKeyBoolean m_specularEnabled
QSSGShaderKeyBoolean m_usesViewIndex
QSSGShaderKeyUnsigned< 8 > m_targetPositionOffset
QSSGShaderKeyUnsigned< 16 > m_boneCount
QSSGShaderKeyBoolean m_hasIbl
QSSGShaderKeyUnsigned< 8 > m_targetTangentOffset
QSSGShaderKeyUnsigned< 8 > m_targetTexCoord0Offset
QSSGShaderKeyUnsigned< 16 > m_vertexColorBlueMask
QSSGShaderKeyUnsigned< 8 > m_targetColorOffset
QSSGShaderKeyBoolean m_emissiveSingleChannelEnabled
QSSGShaderKeyBoolean m_vertexColorsEnabled
QSSGShaderKeyVertexAttribute m_vertexAttributes
QSSGShaderKeyUnsigned< 8 > m_targetNormalOffset
QSSGShaderKeyBoolean m_fresnelEnabled
QSSGShaderKeyBoolean m_lightFlags[LightCount]
QSSGShaderKeyUnsigned< 8 > m_targetBinormalOffset
QSSGShaderKeyBoolean m_fresnelScaleBiasEnabled
QSSGShaderKeyUnsigned< 16 > m_vertexColorGreenMask
QSSGShaderKeyBoolean m_clearcoatFresnelScaleBiasEnabled
QSSGShaderKeyUnsigned< 3 > m_viewCount
QSSGShaderKeyAlphaMode m_alphaMode
QSSGShaderKeyBoolean m_specularSingleChannelEnabled
QSSGShaderKeyUnsigned< 8 > m_targetCount
QSSGShaderKeyBoolean m_specularGlossyEnabled
QSSGShaderKeyBoolean m_lightShadowFlags[LightCount]
QSSGShaderKeyBoolean m_usesPointsTopology
QSSGShaderKeyBoolean m_invertOpacityMapValue
QSSGShaderKeyUnsigned< 16 > m_vertexColorRedMask
QSSGShaderKeyBoolean m_specularAAEnabled
constexpr bool isSet(Feature feature) const
void set(Feature feature, bool val)
void setValue(QSSGDataRef< quint32 > inDataStore, bool inValue) const
bool getValue(QSSGDataView< quint32 > inDataStore) const
void setEnabled(QSSGDataRef< quint32 > inKeySet, bool val)
void setSpecularModel(QSSGDataRef< quint32 > inKeySet, QSSGRenderDefaultMaterial::MaterialSpecularModel inModel)
void setTextureChannel(TexturChannelBits channel, QSSGDataRef< quint32 > inKeySet)
void setValue(QSSGDataRef< quint32 > inDataStore, quint32 inValue) const