994void QSSGLayerRenderData::prepareImageForRender(QSSGRenderImage &inImage,
995 QSSGRenderableImage::Type inMapType,
996 QSSGRenderableImage *&ioFirstImage,
997 QSSGRenderableImage *&ioNextImage,
998 QSSGRenderableObjectFlags &ioFlags,
999 QSSGShaderDefaultMaterialKey &inShaderKey,
1000 quint32 inImageIndex,
1001 QSSGRenderDefaultMaterial *inMaterial)
1003 QSSGRenderContextInterface &contextInterface = *renderer->contextInterface();
1004 const auto &bufferManager = contextInterface.bufferManager();
1006 if (inImage.clearDirty())
1007 ioFlags |= QSSGRenderableObjectFlag::Dirty;
1018 const QSSGRenderImageTexture texture = bufferManager->loadRenderImage(&inImage);
1020 if (texture.m_texture) {
1021 if (texture.m_flags.hasTransparency()
1022 && (inMapType == QSSGRenderableImage::Type::Diffuse
1023 || inMapType == QSSGRenderableImage::Type::Opacity
1024 || inMapType == QSSGRenderableImage::Type::Translucency))
1026 ioFlags |= QSSGRenderableObjectFlag::HasTransparency;
1029 QSSGRenderableImage *theImage = RENDER_FRAME_NEW<QSSGRenderableImage>(contextInterface, inMapType, inImage, texture);
1030 QSSGShaderKeyImageMap &theKeyProp = defaultMaterialShaderKeyProperties.m_imageMaps[inImageIndex];
1032 theKeyProp.setEnabled(inShaderKey,
true);
1033 switch (inImage.m_mappingMode) {
1034 case QSSGRenderImage::MappingModes::Normal:
1036 case QSSGRenderImage::MappingModes::Environment:
1037 theKeyProp.setEnvMap(inShaderKey,
true);
1039 case QSSGRenderImage::MappingModes::LightProbe:
1040 theKeyProp.setLightProbe(inShaderKey,
true);
1050 switch (texture.m_texture->format()) {
1051 case QRhiTexture::Format::RED_OR_ALPHA8:
1052 hasA = !renderer->contextInterface()->rhiContext()->rhi()->isFeatureSupported(QRhi::RedOrAlpha8IsRed);
1054 case QRhiTexture::Format::R8:
1064 if (inImage.isImageTransformIdentity())
1065 theKeyProp.setIdentityTransform(inShaderKey,
true);
1067 if (inImage.m_indexUV == 1)
1068 theKeyProp.setUsesUV1(inShaderKey,
true);
1070 if (texture.m_flags.isLinear())
1071 theKeyProp.setLinear(inShaderKey,
true);
1073 if (texture.m_flags.isPreMultipliedAlpha())
1074 theKeyProp.setPreMultipliedAlpha(inShaderKey,
true);
1076 if (ioFirstImage ==
nullptr)
1077 ioFirstImage = theImage;
1079 ioNextImage->m_nextImage = theImage;
1081 ioNextImage = theImage;
1083 if (inMaterial && inImageIndex >= QSSGShaderDefaultMaterialKeyProperties::SingleChannelImagesFirst) {
1084 QSSGRenderDefaultMaterial::TextureChannelMapping value = QSSGRenderDefaultMaterial::R;
1086 const quint32 scIndex = inImageIndex - QSSGShaderDefaultMaterialKeyProperties::SingleChannelImagesFirst;
1087 QSSGShaderKeyTextureChannel &channelKey = defaultMaterialShaderKeyProperties.m_textureChannels[scIndex];
1088 switch (inImageIndex) {
1089 case QSSGShaderDefaultMaterialKeyProperties::OpacityMap:
1090 value = inMaterial->opacityChannel;
1092 case QSSGShaderDefaultMaterialKeyProperties::RoughnessMap:
1093 value = inMaterial->roughnessChannel;
1095 case QSSGShaderDefaultMaterialKeyProperties::MetalnessMap:
1096 value = inMaterial->metalnessChannel;
1098 case QSSGShaderDefaultMaterialKeyProperties::OcclusionMap:
1099 value = inMaterial->occlusionChannel;
1101 case QSSGShaderDefaultMaterialKeyProperties::TranslucencyMap:
1102 value = inMaterial->translucencyChannel;
1104 case QSSGShaderDefaultMaterialKeyProperties::HeightMap:
1105 value = inMaterial->heightChannel;
1107 case QSSGShaderDefaultMaterialKeyProperties::ClearcoatMap:
1108 value = inMaterial->clearcoatChannel;
1110 case QSSGShaderDefaultMaterialKeyProperties::ClearcoatRoughnessMap:
1111 value = inMaterial->clearcoatRoughnessChannel;
1113 case QSSGShaderDefaultMaterialKeyProperties::SheenRoughnessMap:
1114 value = inMaterial->sheenRoughnessChannel;
1116 case QSSGShaderDefaultMaterialKeyProperties::IridescenceMap:
1117 value = inMaterial->iridescenceChannel;
1119 case QSSGShaderDefaultMaterialKeyProperties::IridescenceThicknessMap:
1120 value = inMaterial->iridescenceThicknessChannel;
1122 case QSSGShaderDefaultMaterialKeyProperties::TransmissionMap:
1123 value = inMaterial->transmissionChannel;
1125 case QSSGShaderDefaultMaterialKeyProperties::ThicknessMap:
1126 value = inMaterial->thicknessChannel;
1128 case QSSGShaderDefaultMaterialKeyProperties::BaseColorMap:
1129 value = inMaterial->baseColorChannel;
1131 case QSSGShaderDefaultMaterialKeyProperties::SpecularAmountMap:
1132 value = inMaterial->specularAmountChannel;
1134 case QSSGShaderDefaultMaterialKeyProperties::EmissiveMap:
1135 value = inMaterial->emissiveChannel;
1140 bool useDefault =
false;
1142 case QSSGRenderDefaultMaterial::TextureChannelMapping::G:
1145 case QSSGRenderDefaultMaterial::TextureChannelMapping::B:
1148 case QSSGRenderDefaultMaterial::TextureChannelMapping::A:
1155 value = QSSGRenderDefaultMaterial::R;
1156 channelKey.setTextureChannel(QSSGShaderKeyTextureChannel::TexturChannelBits(value), inShaderKey);
1186QSSGDefaultMaterialPreparationResult QSSGLayerRenderData::prepareDefaultMaterialForRender(
1187 QSSGRenderDefaultMaterial &inMaterial,
1188 QSSGRenderableObjectFlags &inExistingFlags,
1189 float inOpacity,
bool hasAnyLights,
1190 bool anyLightHasShadows,
1191 QSSGLayerRenderPreparationResultFlags &ioFlags)
1193 QSSGRenderDefaultMaterial *theMaterial = &inMaterial;
1194 QSSGDefaultMaterialPreparationResult retval(QSSGShaderDefaultMaterialKey(qHash(features)));
1195 retval.renderableFlags = inExistingFlags;
1196 QSSGRenderableObjectFlags &renderableFlags(retval.renderableFlags);
1197 QSSGShaderDefaultMaterialKey &theGeneratedKey(retval.materialKey);
1198 retval.opacity = inOpacity;
1199 float &subsetOpacity(retval.opacity);
1201 if (theMaterial->isDirty())
1202 renderableFlags |= QSSGRenderableObjectFlag::Dirty;
1204 subsetOpacity *= theMaterial->opacity;
1206 QSSGRenderableImage *firstImage =
nullptr;
1208 const bool lighting = theMaterial->lighting != QSSGRenderDefaultMaterial::MaterialLighting::NoLighting;
1209 defaultMaterialShaderKeyProperties.m_hasLighting.setValue(theGeneratedKey, lighting);
1211 defaultMaterialShaderKeyProperties.m_hasPunctualLights.setValue(theGeneratedKey, hasAnyLights);
1212 defaultMaterialShaderKeyProperties.m_hasShadows.setValue(theGeneratedKey, anyLightHasShadows);
1213 const bool validSky = layer.skyMaterial !=
nullptr && layer.skyMaterial->enableIBL;
1214 defaultMaterialShaderKeyProperties.m_hasIbl.setValue(theGeneratedKey, layer.lightProbe !=
nullptr || validSky);
1217 defaultMaterialShaderKeyProperties.m_specularAAEnabled.setValue(theGeneratedKey, layer.specularAAEnabled);
1220 defaultMaterialShaderKeyProperties.m_isDoubleSided.setValue(theGeneratedKey, theMaterial->cullMode == QSSGCullFaceMode::Disabled);
1223 defaultMaterialShaderKeyProperties.m_overridesPosition.setValue(theGeneratedKey,
false);
1226 defaultMaterialShaderKeyProperties.m_usesProjectionMatrix.setValue(theGeneratedKey,
false);
1227 defaultMaterialShaderKeyProperties.m_usesInverseProjectionMatrix.setValue(theGeneratedKey,
false);
1229 defaultMaterialShaderKeyProperties.m_usesVarColor.setValue(theGeneratedKey,
false);
1232 defaultMaterialShaderKeyProperties.m_alphaMode.setValue(theGeneratedKey, theMaterial->alphaMode);
1235 setVertexInputPresence(renderableFlags, theGeneratedKey);
1238 defaultMaterialShaderKeyProperties.m_usesPointsTopology.setValue(theGeneratedKey, renderableFlags.isPointsTopology());
1241 defaultMaterialShaderKeyProperties.m_lightmapEnabled.setValue(theGeneratedKey, renderableFlags.rendersWithLightmap());
1242 defaultMaterialShaderKeyProperties.m_metallicRoughnessEnabled.setValue(theGeneratedKey, theMaterial->type == QSSGRenderDefaultMaterial::Type::PrincipledMaterial);
1243 defaultMaterialShaderKeyProperties.m_specularGlossyEnabled.setValue(theGeneratedKey, theMaterial->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial);
1247 defaultMaterialShaderKeyProperties.m_debugMode.setValue(theGeneratedKey,
int(layer.debugMode));
1250 defaultMaterialShaderKeyProperties.m_fogEnabled.setValue(theGeneratedKey, layer.fog.enabled);
1253 defaultMaterialShaderKeyProperties.m_viewCount.setValue(theGeneratedKey, layer.viewCount);
1254 defaultMaterialShaderKeyProperties.m_usesViewIndex.setValue(theGeneratedKey, layer.viewCount >= 2);
1256 if (!defaultMaterialShaderKeyProperties.m_hasIbl.getValue(theGeneratedKey) && theMaterial->iblProbe) {
1257 features.set(QSSGShaderFeatures::Feature::LightProbe,
true);
1258 defaultMaterialShaderKeyProperties.m_hasIbl.setValue(theGeneratedKey,
true);
1263 if (subsetOpacity >= QSSGRendererPrivate::minimumRenderOpacity) {
1279 if (theMaterial->blendMode != QSSGRenderDefaultMaterial::MaterialBlendMode::SourceOver
1280 || theMaterial->opacityMap
1281 || theMaterial->alphaMode == QSSGRenderDefaultMaterial::Blend)
1283 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1286 const bool specularEnabled = theMaterial->isSpecularEnabled();
1287 const bool metalnessEnabled = theMaterial->isMetalnessEnabled();
1288 defaultMaterialShaderKeyProperties.m_specularEnabled.setValue(theGeneratedKey, specularEnabled || metalnessEnabled);
1289 defaultMaterialShaderKeyProperties.m_specularModel.setSpecularModel(theGeneratedKey, theMaterial->specularModel);
1290 defaultMaterialShaderKeyProperties.m_diffuseModel.setDiffuseModel(theGeneratedKey, theMaterial->diffuseModel);
1291 defaultMaterialShaderKeyProperties.m_fresnelScaleBiasEnabled.setValue(theGeneratedKey, theMaterial->isFresnelScaleBiasEnabled());
1292 defaultMaterialShaderKeyProperties.m_clearcoatFresnelScaleBiasEnabled.setValue(theGeneratedKey, theMaterial->isClearcoatFresnelScaleBiasEnabled());
1293 defaultMaterialShaderKeyProperties.m_fresnelEnabled.setValue(theGeneratedKey, theMaterial->isFresnelEnabled());
1294 defaultMaterialShaderKeyProperties.m_baseColorSingleChannelEnabled.setValue(theGeneratedKey, theMaterial->isBaseColorSingleChannelEnabled());
1295 defaultMaterialShaderKeyProperties.m_specularSingleChannelEnabled.setValue(theGeneratedKey, theMaterial->isSpecularAmountSingleChannelEnabled());
1296 defaultMaterialShaderKeyProperties.m_emissiveSingleChannelEnabled.setValue(theGeneratedKey, theMaterial->isEmissiveSingleChannelEnabled());
1297 defaultMaterialShaderKeyProperties.m_invertOpacityMapValue.setValue(theGeneratedKey, theMaterial->isInvertOpacityMapValue());
1298 defaultMaterialShaderKeyProperties.m_vertexColorsEnabled.setValue(theGeneratedKey, theMaterial->isVertexColorsEnabled());
1299 defaultMaterialShaderKeyProperties.m_vertexColorsMaskEnabled.setValue(theGeneratedKey, theMaterial->isVertexColorsMaskEnabled());
1300 defaultMaterialShaderKeyProperties.m_vertexColorRedMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorRedMask.toInt()));
1301 defaultMaterialShaderKeyProperties.m_vertexColorGreenMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorGreenMask.toInt()));
1302 defaultMaterialShaderKeyProperties.m_vertexColorBlueMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorBlueMask.toInt()));
1303 defaultMaterialShaderKeyProperties.m_vertexColorAlphaMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorAlphaMask.toInt()));
1304 defaultMaterialShaderKeyProperties.m_clearcoatEnabled.setValue(theGeneratedKey, theMaterial->isClearcoatEnabled());
1305 defaultMaterialShaderKeyProperties.m_sheenEnabled.setValue(theGeneratedKey, theMaterial->isSheenEnabled());
1306 defaultMaterialShaderKeyProperties.m_anisotropyEnabled.setValue(theGeneratedKey, theMaterial->isAnisotropyEnabled());
1307 defaultMaterialShaderKeyProperties.m_iridescenceEnabled.setValue(theGeneratedKey, theMaterial->isIridescenceEnabled());
1308 defaultMaterialShaderKeyProperties.m_dispersionEnabled.setValue(theGeneratedKey, theMaterial->isDispersionEnabled());
1309 defaultMaterialShaderKeyProperties.m_transmissionEnabled.setValue(theGeneratedKey, theMaterial->isTransmissionEnabled());
1314 QSSGRenderableImage *nextImage =
nullptr;
1315#define CHECK_IMAGE_AND_PREPARE(img, imgtype, shadercomponent)
1317 prepareImageForRender(*(img), imgtype, firstImage, nextImage, renderableFlags,
1318 theGeneratedKey, shadercomponent, &inMaterial)
1320 if (theMaterial->type == QSSGRenderGraphObject::Type::PrincipledMaterial ||
1321 theMaterial->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial) {
1323 QSSGRenderableImage::Type::BaseColor,
1324 QSSGShaderDefaultMaterialKeyProperties::BaseColorMap);
1326 QSSGRenderableImage::Type::Occlusion,
1327 QSSGShaderDefaultMaterialKeyProperties::OcclusionMap);
1329 QSSGRenderableImage::Type::Height,
1330 QSSGShaderDefaultMaterialKeyProperties::HeightMap);
1332 QSSGRenderableImage::Type::Clearcoat,
1333 QSSGShaderDefaultMaterialKeyProperties::ClearcoatMap);
1335 QSSGRenderableImage::Type::ClearcoatRoughness,
1336 QSSGShaderDefaultMaterialKeyProperties::ClearcoatRoughnessMap);
1338 QSSGRenderableImage::Type::ClearcoatNormal,
1339 QSSGShaderDefaultMaterialKeyProperties::ClearcoatNormalMap);
1341 QSSGRenderableImage::Type::SheenColor,
1342 QSSGShaderDefaultMaterialKeyProperties::SheenColorMap);
1344 QSSGRenderableImage::Type::SheenRoughness,
1345 QSSGShaderDefaultMaterialKeyProperties::SheenRoughnessMap);
1347 QSSGRenderableImage::Type::Anisotropy,
1348 QSSGShaderDefaultMaterialKeyProperties::AnisotropyMap);
1350 QSSGRenderableImage::Type::Iridescence,
1351 QSSGShaderDefaultMaterialKeyProperties::IridescenceMap);
1353 QSSGRenderableImage::Type::IridescenceThickness,
1354 QSSGShaderDefaultMaterialKeyProperties::IridescenceThicknessMap);
1356 QSSGRenderableImage::Type::Transmission,
1357 QSSGShaderDefaultMaterialKeyProperties::TransmissionMap);
1359 QSSGRenderableImage::Type::Thickness,
1360 QSSGShaderDefaultMaterialKeyProperties::ThicknessMap);
1361 if (theMaterial->type == QSSGRenderGraphObject::Type::PrincipledMaterial) {
1363 QSSGRenderableImage::Type::Metalness,
1364 QSSGShaderDefaultMaterialKeyProperties::MetalnessMap);
1368 QSSGRenderableImage::Type::Diffuse,
1369 QSSGShaderDefaultMaterialKeyProperties::DiffuseMap);
1371 CHECK_IMAGE_AND_PREPARE(theMaterial->emissiveMap, QSSGRenderableImage::Type::Emissive, QSSGShaderDefaultMaterialKeyProperties::EmissiveMap);
1373 QSSGRenderableImage::Type::Specular,
1374 QSSGShaderDefaultMaterialKeyProperties::SpecularMap);
1376 QSSGRenderableImage::Type::Roughness,
1377 QSSGShaderDefaultMaterialKeyProperties::RoughnessMap);
1378 CHECK_IMAGE_AND_PREPARE(theMaterial->opacityMap, QSSGRenderableImage::Type::Opacity, QSSGShaderDefaultMaterialKeyProperties::OpacityMap);
1379 CHECK_IMAGE_AND_PREPARE(theMaterial->bumpMap, QSSGRenderableImage::Type::Bump, QSSGShaderDefaultMaterialKeyProperties::BumpMap);
1381 QSSGRenderableImage::Type::SpecularAmountMap,
1382 QSSGShaderDefaultMaterialKeyProperties::SpecularAmountMap);
1383 CHECK_IMAGE_AND_PREPARE(theMaterial->normalMap, QSSGRenderableImage::Type::Normal, QSSGShaderDefaultMaterialKeyProperties::NormalMap);
1385 QSSGRenderableImage::Type::Translucency,
1386 QSSGShaderDefaultMaterialKeyProperties::TranslucencyMap);
1388#undef CHECK_IMAGE_AND_PREPARE
1390 if (subsetOpacity < QSSGRendererPrivate::minimumRenderOpacity) {
1391 subsetOpacity = 0.0f;
1395 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1396 renderableFlags |= QSSGRenderableObjectFlag::CompletelyTransparent;
1399 if (subsetOpacity > 1.f - QSSGRendererPrivate::minimumRenderOpacity)
1400 subsetOpacity = 1.f;
1402 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1404 if (inMaterial.isTransmissionEnabled()) {
1405 ioFlags.setRequiresScreenTexture(
true);
1406 ioFlags.setRequiresMipmapsForScreenTexture(
true);
1407 renderableFlags |= QSSGRenderableObjectFlag::RequiresScreenTexture;
1410 if (renderableFlags.hasTransparency()) {
1411 if (orderIndependentTransparencyEnabled)
1412 defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(layer.oitMethod));
1413 if (layer.oitMethodDirty)
1414 renderableFlags |= QSSGRenderableObjectFlag::Dirty;
1417 retval.firstImage = firstImage;
1418 if (retval.renderableFlags.isDirty())
1419 retval.dirty =
true;
1421 renderer->addMaterialDirtyClear(&inMaterial);
1425QSSGDefaultMaterialPreparationResult QSSGLayerRenderData::prepareCustomMaterialForRender(
1426 QSSGRenderCustomMaterial &inMaterial, QSSGRenderableObjectFlags &inExistingFlags,
1427 float inOpacity,
bool alreadyDirty,
bool hasAnyLights,
bool anyLightHasShadows,
1428 QSSGLayerRenderPreparationResultFlags &ioFlags)
1430 QSSGDefaultMaterialPreparationResult retval(QSSGShaderDefaultMaterialKey(qHash(features)));
1431 retval.renderableFlags = inExistingFlags;
1432 QSSGRenderableObjectFlags &renderableFlags(retval.renderableFlags);
1433 QSSGShaderDefaultMaterialKey &theGeneratedKey(retval.materialKey);
1434 retval.opacity = inOpacity;
1435 float &subsetOpacity(retval.opacity);
1437 if (subsetOpacity < QSSGRendererPrivate::minimumRenderOpacity) {
1438 subsetOpacity = 0.0f;
1442 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1443 renderableFlags |= QSSGRenderableObjectFlag::CompletelyTransparent;
1446 if (subsetOpacity > 1.f - QSSGRendererPrivate::minimumRenderOpacity)
1447 subsetOpacity = 1.f;
1449 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1451 defaultMaterialShaderKeyProperties.m_hasLighting.setValue(theGeneratedKey,
true);
1452 defaultMaterialShaderKeyProperties.m_hasPunctualLights.setValue(theGeneratedKey, hasAnyLights);
1453 defaultMaterialShaderKeyProperties.m_hasShadows.setValue(theGeneratedKey, anyLightHasShadows);
1454 defaultMaterialShaderKeyProperties.m_hasIbl.setValue(theGeneratedKey, layer.lightProbe !=
nullptr || layer.skyMaterial !=
nullptr);
1455 defaultMaterialShaderKeyProperties.m_specularEnabled.setValue(theGeneratedKey,
true);
1457 defaultMaterialShaderKeyProperties.m_specularAAEnabled.setValue(theGeneratedKey, layer.specularAAEnabled);
1460 defaultMaterialShaderKeyProperties.m_isDoubleSided.setValue(theGeneratedKey, inMaterial.m_cullMode == QSSGCullFaceMode::Disabled);
1463 defaultMaterialShaderKeyProperties.m_metallicRoughnessEnabled.setValue(theGeneratedKey,
true);
1466 const bool overridesPosition = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::OverridesPosition);
1467 defaultMaterialShaderKeyProperties.m_overridesPosition.setValue(theGeneratedKey, overridesPosition);
1470 const bool usesProjectionMatrix = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ProjectionMatrix);
1471 defaultMaterialShaderKeyProperties.m_usesProjectionMatrix.setValue(theGeneratedKey, usesProjectionMatrix);
1472 const bool usesInvProjectionMatrix = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::InverseProjectionMatrix);
1473 defaultMaterialShaderKeyProperties.m_usesInverseProjectionMatrix.setValue(theGeneratedKey, usesInvProjectionMatrix);
1476 setVertexInputPresence(renderableFlags, theGeneratedKey);
1479 defaultMaterialShaderKeyProperties.m_usesPointsTopology.setValue(theGeneratedKey, renderableFlags.isPointsTopology());
1482 defaultMaterialShaderKeyProperties.m_lightmapEnabled.setValue(theGeneratedKey, renderableFlags.rendersWithLightmap());
1485 defaultMaterialShaderKeyProperties.m_debugMode.setValue(theGeneratedKey,
int(layer.debugMode));
1488 defaultMaterialShaderKeyProperties.m_fogEnabled.setValue(theGeneratedKey, layer.fog.enabled);
1491 defaultMaterialShaderKeyProperties.m_viewCount.setValue(theGeneratedKey, layer.viewCount);
1492 defaultMaterialShaderKeyProperties.m_usesViewIndex.setValue(theGeneratedKey,
1493 inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ViewIndex));
1498 const bool usesVarColor = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::VarColor);
1499 defaultMaterialShaderKeyProperties.m_usesVarColor.setValue(theGeneratedKey, usesVarColor);
1501 const bool usesClearcoat = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Clearcoat);
1502 defaultMaterialShaderKeyProperties.m_clearcoatEnabled.setValue(theGeneratedKey, usesClearcoat);
1504 const bool usesSheen = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Sheen);
1505 defaultMaterialShaderKeyProperties.m_sheenEnabled.setValue(theGeneratedKey, usesSheen);
1507 const bool usesAnisotropy = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Anisotropy);
1508 defaultMaterialShaderKeyProperties.m_anisotropyEnabled.setValue(theGeneratedKey, usesAnisotropy);
1510 const bool usesIridescence = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Iridescence);
1511 defaultMaterialShaderKeyProperties.m_iridescenceEnabled.setValue(theGeneratedKey, usesIridescence);
1513 const bool usesDispersion = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Dispersion);
1514 defaultMaterialShaderKeyProperties.m_dispersionEnabled.setValue(theGeneratedKey, usesDispersion);
1516 const bool usesClearcoatFresnelScaleBias = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ClearcoatFresnelScaleBias);
1517 defaultMaterialShaderKeyProperties.m_clearcoatFresnelScaleBiasEnabled.setValue(theGeneratedKey, usesClearcoatFresnelScaleBias);
1519 const bool usesFresnelScaleBias = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::FresnelScaleBias);
1520 defaultMaterialShaderKeyProperties.m_fresnelScaleBiasEnabled.setValue(theGeneratedKey, usesFresnelScaleBias);
1522 const bool usesTransmission = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Transmission);
1523 defaultMaterialShaderKeyProperties.m_transmissionEnabled.setValue(theGeneratedKey, usesTransmission);
1525 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Blending))
1526 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1528 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ScreenTexture)) {
1529 ioFlags.setRequiresScreenTexture(
true);
1530 renderableFlags |= QSSGRenderableObjectFlag::RequiresScreenTexture;
1533 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ScreenMipTexture)) {
1534 ioFlags.setRequiresScreenTexture(
true);
1535 ioFlags.setRequiresMipmapsForScreenTexture(
true);
1536 renderableFlags |= QSSGRenderableObjectFlag::RequiresScreenTexture;
1539 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::DepthTexture))
1540 ioFlags.setRequiresDepthTexture(
true);
1542 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::NormalTexture)) {
1543 ioFlags.setRequiresNormalTexture(
true);
1544 renderableFlags |= QSSGRenderableObjectFlag::RequiresNormalTexture;
1547 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::AoTexture)) {
1548 ioFlags.setRequiresDepthTexture(
true);
1549 ioFlags.setRequiresSsaoPass(
true);
1551 if (orderIndependentTransparencyEnabled && renderableFlags.hasTransparency())
1552 defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(layer.oitMethod));
1554 retval.firstImage =
nullptr;
1556 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::MotionVectorTexture))
1557 ioFlags.setRequiresMotionVectorPass(
true);
1559 if (retval.dirty || alreadyDirty)
1560 renderer->addMaterialDirtyClear(&inMaterial);
1618bool QSSGLayerRenderData::prepareModelsForRender(QSSGRenderContextInterface &contextInterface,
1619 const RenderableNodeEntries &renderableModels,
1620 QSSGLayerRenderPreparationResultFlags &ioFlags,
1621 const QSSGRenderCameraList &allCameras,
1622 const QSSGRenderCameraDataList &allCameraData,
1623 TModelContextPtrList &modelContexts,
1624 QSSGRenderableObjectList &opaqueObjects,
1625 QSSGRenderableObjectList &transparentObjects,
1626 QSSGRenderableObjectList &screenTextureObjects,
1629 const auto &rhiCtx = contextInterface.rhiContext();
1630 const auto &bufferManager = contextInterface.bufferManager();
1632 const auto &debugDrawSystem = contextInterface.debugDrawSystem();
1633 const bool maybeDebugDraw = debugDrawSystem && debugDrawSystem->isEnabled();
1635 bool wasDirty =
false;
1637 for (
const QSSGRenderableNodeEntry &renderable : renderableModels) {
1638 if ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::Disabled) != 0)
1641 const QSSGRenderModel &model = *
static_cast<QSSGRenderModel *>(renderable.node);
1642 const auto &lights = renderable.lights;
1643 QSSGRenderMesh *theMesh = modelData->getMesh(model);
1647 const bool altGlobalTransform = ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::GlobalTransform) != 0);
1648 const auto &globalTransform = altGlobalTransform ? renderable.extOverrides.globalTransform : getGlobalTransform(model);
1649 QMatrix3x3 normalMatrix { Qt::Uninitialized };
1650 QSSGLayerRenderData::ModelViewProjections mvps;
1651 if (altGlobalTransform) {
1652 QSSGRenderNode::calculateNormalMatrix(globalTransform, normalMatrix);
1653 size_t mvpCount = 0;
1654 for (
const auto &cameraData : allCameraData) {
1655 QSSGRenderNode::calculateMVPAndNormalMatrix(globalTransform, cameraData.viewProjection, mvps[mvpCount++], normalMatrix);
1658 if (model.usesBoneTexture()) {
1662 size_t mvpCount = 0;
1663 for (
const QSSGRenderCameraData &cameraData : allCameraData) {
1664 mvps[mvpCount++] = cameraData.viewProjection;
1665 normalMatrix = QMatrix3x3();
1668 normalMatrix = getNormalMatrix(model);
1669 mvps = getModelMvps(model);
1672 const bool altModelOpacity = ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::GlobalOpacity) != 0);
1673 const float modelGlobalOpacity = altModelOpacity ? renderable.extOverrides.globalOpacity : getGlobalOpacity(model);
1674 QSSGModelContext &theModelContext = *RENDER_FRAME_NEW<QSSGModelContext>(contextInterface, model, globalTransform, normalMatrix, mvps);
1675 modelContexts.push_back(&theModelContext);
1678 const auto &meshSubsets = theMesh->subsets;
1679 const auto meshSubsetCount = meshSubsets.size();
1680 theModelContext.subsets = RENDER_FRAME_NEW_BUFFER<QSSGSubsetRenderable>(contextInterface, meshSubsetCount);
1684 auto boneTexture = bufferManager->loadSkinmap(model.skin);
1685 setBonemapTexture(theModelContext, boneTexture.m_texture);
1686 }
else if (model.skeleton) {
1687 auto boneTexture = bufferManager->loadSkinmap(&(model.skeleton->boneTexData));
1688 setBonemapTexture(theModelContext, boneTexture.m_texture);
1692 QSSGRenderableObjectFlags renderableFlagsForModel;
1694 bool usesBlendParticles = particlesEnabled && theModelContext.model.particleBuffer !=
nullptr
1695 && model.particleBuffer->particleCount();
1697 if (meshSubsetCount > 0) {
1698 const QSSGRenderSubset &theSubset = meshSubsets.at(0);
1700 renderableFlagsForModel.setMotionVectorParticipant(model.motionVectorEnabled && !usesBlendParticles);
1701 renderableFlagsForModel.setCastsShadows(model.castsShadows);
1702 renderableFlagsForModel.setReceivesShadows(model.receivesShadows);
1703 renderableFlagsForModel.setReceivesReflections(model.receivesReflections);
1704 renderableFlagsForModel.setCastsReflections(model.castsReflections);
1706 renderableFlagsForModel.setUsedInBakedLighting(model.usedInBakedLighting);
1707 if (model.hasLightmap()) {
1708 QSSGRenderImageTexture lmImageTexture = bufferManager->loadLightmap(model);
1709 if (lmImageTexture.m_texture) {
1710 renderableFlagsForModel.setRendersWithLightmap(
true);
1711 setLightmapTexture(theModelContext, lmImageTexture.m_texture);
1720 bool hasJoint =
false;
1721 bool hasWeight =
false;
1722 bool hasMorphTarget = theSubset.rhi.targetsTexture !=
nullptr;
1723 for (
const QSSGRhiInputAssemblerState::InputSemantic &sem : std::as_const(theSubset.rhi.ia.inputs)) {
1724 if (sem == QSSGRhiInputAssemblerState::PositionSemantic) {
1725 renderableFlagsForModel.setHasAttributePosition(
true);
1726 }
else if (sem == QSSGRhiInputAssemblerState::NormalSemantic) {
1727 renderableFlagsForModel.setHasAttributeNormal(
true);
1728 }
else if (sem == QSSGRhiInputAssemblerState::TexCoord0Semantic) {
1729 renderableFlagsForModel.setHasAttributeTexCoord0(
true);
1730 }
else if (sem == QSSGRhiInputAssemblerState::TexCoord1Semantic) {
1731 renderableFlagsForModel.setHasAttributeTexCoord1(
true);
1732 }
else if (sem == QSSGRhiInputAssemblerState::TexCoordLightmapSemantic) {
1733 renderableFlagsForModel.setHasAttributeTexCoordLightmap(
true);
1734 }
else if (sem == QSSGRhiInputAssemblerState::TangentSemantic) {
1735 renderableFlagsForModel.setHasAttributeTangent(
true);
1736 }
else if (sem == QSSGRhiInputAssemblerState::BinormalSemantic) {
1737 renderableFlagsForModel.setHasAttributeBinormal(
true);
1738 }
else if (sem == QSSGRhiInputAssemblerState::ColorSemantic) {
1739 renderableFlagsForModel.setHasAttributeColor(
true);
1742 }
else if (sem == QSSGRhiInputAssemblerState::JointSemantic) {
1744 }
else if (sem == QSSGRhiInputAssemblerState::WeightSemantic) {
1748 renderableFlagsForModel.setHasAttributeJointAndWeight(hasJoint && hasWeight);
1749 renderableFlagsForModel.setHasAttributeMorphTarget(hasMorphTarget);
1752 QSSGRenderableObjectList bakedLightingObjects;
1753 const bool anyLightHasShadows = std::find_if(lights.begin(),
1755 [](
const QSSGShaderLight &light) {
return light.shadows; })
1757 const bool hasAnyLights = !lights.isEmpty();
1758 QSSGRenderLight::SoftShadowQuality maxSoftShadowQuality = QSSGRenderLight::SoftShadowQuality::Hard;
1759 if (anyLightHasShadows) {
1761 for (
const QSSGShaderLight &light : lights) {
1762 if (light.shadows && light.light->m_softShadowQuality > maxSoftShadowQuality)
1763 maxSoftShadowQuality = light.light->m_softShadowQuality;
1769 auto &renderableSubsets = theModelContext.subsets;
1770 const bool hasMaterialOverrides = ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::Materials) != 0);
1771 const auto &materials = hasMaterialOverrides ? renderable.extOverrides.materials : modelData->getMaterials(model);
1772 const auto materialCount = materials.size();
1773 QSSGRenderGraphObject *lastMaterial = !materials.isEmpty() ? materials.last() :
nullptr;
1774 int idx = 0, subsetIdx = 0;
1775 for (; idx < meshSubsetCount; ++idx) {
1777 QSSGRenderGraphObject *theMaterialObject = (idx >= materialCount) ? lastMaterial : materials[idx];
1778 if (!theMaterialObject)
1781 const QSSGRenderSubset &theSubset = meshSubsets.at(idx);
1782 QSSGRenderableObjectFlags renderableFlags = renderableFlagsForModel;
1783 float subsetOpacity = modelGlobalOpacity;
1785 renderableFlags.setPointsTopology(theSubset.rhi.ia.topology == QRhiGraphicsPipeline::Points);
1786 QSSGRenderableObject *theRenderableObject = &renderableSubsets[subsetIdx++];
1788 const bool usesInstancing = theModelContext.model.instancing()
1789 && rhiCtx->rhi()->isFeatureSupported(QRhi::Instancing);
1790 if (usesInstancing && theModelContext.model.instanceTable->hasTransparency())
1791 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1792 if (theModelContext.model.hasTransparency)
1793 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1796 quint32 subsetLevelOfDetail = 0;
1797 if (!theSubset.lods.isEmpty() && lodThreshold > 0.0f) {
1799 float lodDistanceMultiplier = camerasView[0]->getLevelOfDetailMultiplier();
1800 float distanceThreshold = 0.0f;
1801 const auto scale = QSSGUtils::mat44::getScale(globalTransform);
1802 float modelScale = qMax(scale.x(), qMax(scale.y(), scale.z()));
1803 QSSGBounds3 transformedBounds = theSubset.bounds;
1804 if (camerasView[0]->type != QSSGRenderGraphObject::Type::OrthographicCamera) {
1805 transformedBounds.transform(globalTransform);
1806 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1807 debugDrawSystem->drawBounds(transformedBounds, QColor(Qt::red));
1808 const QMatrix4x4 cameraGlobalTranform = getGlobalTransform(*camerasView[0]);
1809 const QVector3D cameraNormal = QSSGRenderNode::getScalingCorrectDirection(cameraGlobalTranform);
1810 const QVector3D cameraPosition = QSSGRenderNode::getGlobalPos(cameraGlobalTranform);
1811 const QSSGPlane cameraPlane = QSSGPlane(cameraPosition, cameraNormal);
1812 const QVector3D lodSupportMin = transformedBounds.getSupport(-cameraNormal);
1813 const QVector3D lodSupportMax = transformedBounds.getSupport(cameraNormal);
1814 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1815 debugDrawSystem->drawPoint(lodSupportMin, QColor(
"orange"));
1817 const float distanceMin = cameraPlane.distance(lodSupportMin);
1818 const float distanceMax = cameraPlane.distance(lodSupportMax);
1820 if (distanceMin * distanceMax < 0.0)
1821 distanceThreshold = 0.0;
1822 else if (distanceMin >= 0.0)
1823 distanceThreshold = distanceMin;
1824 else if (distanceMax <= 0.0)
1825 distanceThreshold = -distanceMax;
1829 distanceThreshold = 1.0;
1832 int currentLod = -1;
1833 if (model.levelOfDetailBias > 0.0f) {
1839 int lodsCount = theSubset.lods.size();
1840 if (model.instanceTable && lodsCount) {
1841 currentLod = qRound(lodsCount * qBound(0.f, model.instancingLodFactor, 1.f)) - 1;
1843 const float threshold = distanceThreshold * lodDistanceMultiplier;
1844 const float modelBias = 1 / model.levelOfDetailBias;
1845 for (qsizetype i = 0; i < lodsCount; ++i) {
1846 float subsetDistance = theSubset.lods[i].distance * modelScale * modelBias;
1847 float screenSize = subsetDistance / threshold;
1848 if (screenSize > lodThreshold)
1855 if (currentLod == -1)
1856 subsetLevelOfDetail = 0;
1858 subsetLevelOfDetail = currentLod + 1;
1859 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1860 debugDrawSystem->drawBounds(transformedBounds, QSSGDebugDrawSystem::levelOfDetailColor(subsetLevelOfDetail));
1863 QVector3D theModelCenter(theSubset.bounds.center());
1864 theModelCenter = QSSGUtils::mat44::transform(globalTransform, theModelCenter);
1865 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLodNormal)) {
1866 const QMatrix4x4 allCamera0GlobalTransform = getGlobalTransform(*allCameras[0]);
1867 debugDrawSystem->debugNormals(*bufferManager, theModelContext, theSubset, subsetLevelOfDetail, (theModelCenter - QSSGRenderNode::getGlobalPos(allCamera0GlobalTransform)).length() * 0.01);
1870 auto checkF32TypeIndex = [&rhiCtx](QRhiVertexInputAttribute::Format f) {
1871 if ((f == QRhiVertexInputAttribute::Format::Float4)
1872 || (f == QRhiVertexInputAttribute::Format::Float3)
1873 || (f == QRhiVertexInputAttribute::Format::Float2)
1874 || (f == QRhiVertexInputAttribute::Format::Float)) {
1877 if (!rhiCtx->rhi()->isFeatureSupported(QRhi::IntAttributes))
1878 qWarning() <<
"WARN: Model has non-integer type indices for skinning but current RHI backend doesn't support it!";
1882 if (theMaterialObject->type == QSSGRenderGraphObject::Type::DefaultMaterial ||
1883 theMaterialObject->type == QSSGRenderGraphObject::Type::PrincipledMaterial ||
1884 theMaterialObject->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial) {
1885 QSSGRenderDefaultMaterial &theMaterial(
static_cast<QSSGRenderDefaultMaterial &>(*theMaterialObject));
1886 QSSGDefaultMaterialPreparationResult theMaterialPrepResult(prepareDefaultMaterialForRender(theMaterial, renderableFlags, subsetOpacity, hasAnyLights, anyLightHasShadows, ioFlags));
1887 QSSGShaderDefaultMaterialKey &theGeneratedKey(theMaterialPrepResult.materialKey);
1888 subsetOpacity = theMaterialPrepResult.opacity;
1889 QSSGRenderableImage *firstImage(theMaterialPrepResult.firstImage);
1890 wasDirty |= theMaterialPrepResult.dirty;
1891 renderableFlags = theMaterialPrepResult.renderableFlags;
1892 if (renderableFlags.hasTransparency())
1893 ioFlags.setHasCustomBlendMode(theMaterial.blendMode != QSSGRenderDefaultMaterial::MaterialBlendMode::SourceOver);
1896 defaultMaterialShaderKeyProperties.m_blendParticles.setValue(theGeneratedKey, usesBlendParticles);
1898 if (defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.getValue(theGeneratedKey) ==
int(QSSGRenderLayer::OITMethod::LinkedList))
1899 defaultMaterialShaderKeyProperties.m_oitMSAA.setValue(theGeneratedKey, rhiCtx->mainPassSampleCount() > 1);
1902 const auto boneCount = model.skin ? model.skin->boneCount :
1903 model.skeleton ? model.skeleton->boneCount : 0;
1904 defaultMaterialShaderKeyProperties.m_boneCount.setValue(theGeneratedKey, boneCount);
1905 if (
auto idJoint = theSubset.rhi.ia.inputs.indexOf(QSSGRhiInputAssemblerState::JointSemantic); idJoint != -1) {
1906 const auto attr = theSubset.rhi.ia.inputLayout.attributeAt(idJoint);
1907 defaultMaterialShaderKeyProperties.m_usesFloatJointIndices.setValue(theGeneratedKey, checkF32TypeIndex(attr->format()));
1911 defaultMaterialShaderKeyProperties.m_shadowSoftness.setShadowSoftness(theGeneratedKey, maxSoftShadowQuality);
1914 defaultMaterialShaderKeyProperties.m_usesInstancing.setValue(theGeneratedKey, usesInstancing);
1916 defaultMaterialShaderKeyProperties.m_targetCount.setValue(theGeneratedKey,
1917 theSubset.rhi.ia.targetCount);
1918 defaultMaterialShaderKeyProperties.m_targetPositionOffset.setValue(theGeneratedKey,
1919 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::PositionSemantic]);
1920 defaultMaterialShaderKeyProperties.m_targetNormalOffset.setValue(theGeneratedKey,
1921 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::NormalSemantic]);
1922 defaultMaterialShaderKeyProperties.m_targetTangentOffset.setValue(theGeneratedKey,
1923 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TangentSemantic]);
1924 defaultMaterialShaderKeyProperties.m_targetBinormalOffset.setValue(theGeneratedKey,
1925 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::BinormalSemantic]);
1926 defaultMaterialShaderKeyProperties.m_targetTexCoord0Offset.setValue(theGeneratedKey,
1927 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord0Semantic]);
1928 defaultMaterialShaderKeyProperties.m_targetTexCoord1Offset.setValue(theGeneratedKey,
1929 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord1Semantic]);
1930 defaultMaterialShaderKeyProperties.m_targetColorOffset.setValue(theGeneratedKey,
1931 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::ColorSemantic]);
1933 new (theRenderableObject) QSSGSubsetRenderable(QSSGSubsetRenderable::Type::DefaultMaterialMeshSubset,
1940 subsetLevelOfDetail,
1945 anyLightHasShadows);
1946 wasDirty = wasDirty || renderableFlags.isDirty();
1947 }
else if (theMaterialObject->type == QSSGRenderGraphObject::Type::CustomMaterial) {
1948 QSSGRenderCustomMaterial &theMaterial(
static_cast<QSSGRenderCustomMaterial &>(*theMaterialObject));
1950 const auto &theMaterialSystem(contextInterface.customMaterialSystem());
1951 wasDirty |= theMaterialSystem->prepareForRender(theModelContext.model, theSubset, theMaterial);
1953 if (theMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Blending))
1954 ioFlags.setHasCustomBlendMode(!hasCustomBlendMode(theMaterial));
1956 QSSGDefaultMaterialPreparationResult theMaterialPrepResult(
1957 prepareCustomMaterialForRender(theMaterial, renderableFlags, subsetOpacity, wasDirty,
1958 hasAnyLights, anyLightHasShadows, ioFlags));
1959 QSSGShaderDefaultMaterialKey &theGeneratedKey(theMaterialPrepResult.materialKey);
1960 subsetOpacity = theMaterialPrepResult.opacity;
1961 QSSGRenderableImage *firstImage(theMaterialPrepResult.firstImage);
1962 renderableFlags = theMaterialPrepResult.renderableFlags;
1964 if (model.particleBuffer && model.particleBuffer->particleCount())
1965 defaultMaterialShaderKeyProperties.m_blendParticles.setValue(theGeneratedKey,
true);
1967 defaultMaterialShaderKeyProperties.m_blendParticles.setValue(theGeneratedKey,
false);
1969 if (defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.getValue(theGeneratedKey) ==
int(QSSGRenderLayer::OITMethod::LinkedList))
1970 defaultMaterialShaderKeyProperties.m_oitMSAA.setValue(theGeneratedKey, rhiCtx->mainPassSampleCount() > 1);
1973 defaultMaterialShaderKeyProperties.m_shadowSoftness.setShadowSoftness(theGeneratedKey, maxSoftShadowQuality);
1976 const auto boneCount = model.skin ? model.skin->boneCount :
1977 model.skeleton ? model.skeleton->boneCount : 0;
1978 defaultMaterialShaderKeyProperties.m_boneCount.setValue(theGeneratedKey, boneCount);
1979 if (
auto idJoint = theSubset.rhi.ia.inputs.indexOf(QSSGRhiInputAssemblerState::JointSemantic); idJoint != -1) {
1980 const auto attr = theSubset.rhi.ia.inputLayout.attributeAt(idJoint);
1981 defaultMaterialShaderKeyProperties.m_usesFloatJointIndices.setValue(theGeneratedKey, checkF32TypeIndex(attr->format()));
1985 bool usesInstancing = theModelContext.model.instancing()
1986 && rhiCtx->rhi()->isFeatureSupported(QRhi::Instancing);
1987 defaultMaterialShaderKeyProperties.m_usesInstancing.setValue(theGeneratedKey, usesInstancing);
1989 defaultMaterialShaderKeyProperties.m_targetCount.setValue(theGeneratedKey,
1990 theSubset.rhi.ia.targetCount);
1991 defaultMaterialShaderKeyProperties.m_targetPositionOffset.setValue(theGeneratedKey,
1992 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::PositionSemantic]);
1993 defaultMaterialShaderKeyProperties.m_targetNormalOffset.setValue(theGeneratedKey,
1994 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::NormalSemantic]);
1995 defaultMaterialShaderKeyProperties.m_targetTangentOffset.setValue(theGeneratedKey,
1996 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TangentSemantic]);
1997 defaultMaterialShaderKeyProperties.m_targetBinormalOffset.setValue(theGeneratedKey,
1998 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::BinormalSemantic]);
1999 defaultMaterialShaderKeyProperties.m_targetTexCoord0Offset.setValue(theGeneratedKey,
2000 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord0Semantic]);
2001 defaultMaterialShaderKeyProperties.m_targetTexCoord1Offset.setValue(theGeneratedKey,
2002 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord1Semantic]);
2003 defaultMaterialShaderKeyProperties.m_targetColorOffset.setValue(theGeneratedKey,
2004 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::ColorSemantic]);
2006 if (theMaterial.m_iblProbe)
2007 theMaterial.m_iblProbe->clearDirty();
2009 new (theRenderableObject) QSSGSubsetRenderable(QSSGSubsetRenderable::Type::CustomMaterialMeshSubset,
2016 subsetLevelOfDetail,
2021 anyLightHasShadows);
2023 if (theRenderableObject)
2024 theRenderableObject->camdistSq = getCameraDistanceSq(*theRenderableObject, allCameraData[0]);
2028 if (Q_UNLIKELY(idx != subsetIdx))
2029 renderableSubsets.mSize = subsetIdx;
2031 for (
auto &ro : renderableSubsets) {
2032 const auto depthMode = ro.depthWriteMode;
2033 hasDepthWriteObjects |= (depthMode == QSSGDepthDrawMode::Always || depthMode == QSSGDepthDrawMode::OpaqueOnly);
2034 enum ObjectType : quint8 { ScreenTexture, Transparent, Opaque };
2035 static constexpr DepthPrepassObject ppState[][2] = { {DepthPrepassObject::None, DepthPrepassObject::ScreenTexture},
2036 {DepthPrepassObject::None, DepthPrepassObject::Transparent},
2037 {DepthPrepassObject::None, DepthPrepassObject::Opaque} };
2039 if (ro.renderableFlags.requiresScreenTexture()) {
2040 depthPrepassObjectsState |= DepthPrepassObjectStateT(ppState[ObjectType::ScreenTexture][size_t(depthMode == QSSGDepthDrawMode::OpaquePrePass)]);
2041 screenTextureObjects.push_back({&ro, ro.camdistSq, model.tag});
2042 }
else if (ro.renderableFlags.hasTransparency()) {
2043 depthPrepassObjectsState |= DepthPrepassObjectStateT(ppState[ObjectType::Transparent][size_t(depthMode == QSSGDepthDrawMode::OpaquePrePass)]);
2044 transparentObjects.push_back({&ro, ro.camdistSq, model.tag});
2046 depthPrepassObjectsState |= DepthPrepassObjectStateT(ppState[ObjectType::Opaque][size_t(depthMode == QSSGDepthDrawMode::OpaquePrePass)]);
2047 opaqueObjects.push_back({&ro, ro.camdistSq, model.tag});
2050 if (ro.renderableFlags.usedInBakedLighting())
2051 bakedLightingObjects.push_back({&ro, ro.camdistSq, model.tag});
2054 if (!bakedLightingObjects.isEmpty())
2055 bakedLightingModels.push_back(QSSGBakedLightingModel(&model, bakedLightingObjects));
2061bool QSSGLayerRenderData::prepareParticlesForRender(
const RenderableNodeEntries &renderableParticles,
const QSSGRenderCameraData &cameraData, QSSGLayerRenderPreparationResultFlags &ioFlags)
2063 QSSG_ASSERT(particlesEnabled,
return false);
2065 QSSGRenderContextInterface &contextInterface = *renderer->contextInterface();
2070 auto &opaqueObjects = opaqueObjectStore[0];
2071 auto &transparentObjects = transparentObjectStore[0];
2072 auto &screenTextureObjects = screenTextureObjectStore[0];
2074 for (
auto &renderable : renderableParticles) {
2075 QSSGShaderParticleMaterialKeyProperties &properties = particleMaterialShaderKeyProperties;
2077 QSSGRenderParticles &particles = *
static_cast<QSSGRenderParticles *>(renderable.node);
2078 QSSGShaderParticleMaterialKey &theGeneratedKey(particles.materialKey);
2079 const auto &lights = renderable.lights;
2081 QSSGRenderableObjectFlags renderableFlags;
2082 renderableFlags.setCastsShadows(
false);
2083 renderableFlags.setReceivesShadows(
false);
2084 renderableFlags.setHasAttributePosition(
true);
2085 renderableFlags.setHasAttributeNormal(
true);
2086 renderableFlags.setHasAttributeTexCoord0(
true);
2087 renderableFlags.setHasAttributeColor(
true);
2088 renderableFlags.setHasTransparency(particles.m_hasTransparency);
2089 renderableFlags.setCastsReflections(particles.m_castsReflections);
2090 if (particles.m_hasTransparency && particles.m_blendMode != QSSGRenderParticles::BlendMode::SourceOver)
2091 ioFlags.setHasCustomBlendMode(
true);
2093 properties.m_isLineParticle.setValue(theGeneratedKey, particles.m_featureLevel >= QSSGRenderParticles::FeatureLevel::Line);
2094 const bool animated = particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineAnimated
2095 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::Animated
2096 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::AnimatedVLight
2097 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineAnimatedVLight;
2098 const bool mapped = particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineMapped
2099 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::Mapped
2100 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::MappedVLight
2101 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineMappedVLight;
2102 const bool lit = particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineVLight
2103 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::AnimatedVLight
2104 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::MappedVLight
2105 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineMappedVLight
2106 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineAnimatedVLight
2107 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::SimpleVLight;
2108 properties.m_isAnimated.setValue(theGeneratedKey, animated);
2109 properties.m_isMapped.setValue(theGeneratedKey, mapped);
2110 properties.m_hasLighting.setValue(theGeneratedKey, lit);
2111 properties.m_viewCount.setValue(theGeneratedKey, layer.viewCount);
2112 if (renderableFlags.hasTransparency() && orderIndependentTransparencyEnabled) {
2113 properties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(layer.oitMethod));
2114 if (layer.oitMethod == QSSGRenderLayer::OITMethod::LinkedList)
2115 properties.m_oitMSAA.setValue(theGeneratedKey, contextInterface.rhiContext()->mainPassSampleCount() > 1);
2117 properties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(0));
2120 float opacity = getGlobalOpacity(particles);
2121 const QMatrix4x4 globalTransform = getGlobalTransform(particles);
2122 QVector3D center(particles.m_particleBuffer.bounds().center());
2123 center = QSSGUtils::mat44::transform(globalTransform, center);
2125 QSSGRenderableImage *firstImage =
nullptr;
2126 if (particles.m_sprite) {
2127 const auto &bufferManager = contextInterface.bufferManager();
2129 if (particles.m_sprite->clearDirty())
2132 const QSSGRenderImageTexture texture = bufferManager->loadRenderImage(particles.m_sprite);
2133 QSSGRenderableImage *theImage = RENDER_FRAME_NEW<QSSGRenderableImage>(contextInterface, QSSGRenderableImage::Type::Diffuse, *particles.m_sprite, texture);
2134 firstImage = theImage;
2135 properties.m_isSpriteLinear.setValue(theGeneratedKey, texture.m_flags.isLinear());
2138 QSSGRenderableImage *colorTable =
nullptr;
2139 if (particles.m_colorTable) {
2140 const auto &bufferManager = contextInterface.bufferManager();
2142 if (particles.m_colorTable->clearDirty())
2145 const QSSGRenderImageTexture texture = bufferManager->loadRenderImage(particles.m_colorTable);
2147 QSSGRenderableImage *theImage = RENDER_FRAME_NEW<QSSGRenderableImage>(contextInterface, QSSGRenderableImage::Type::Diffuse, *particles.m_colorTable, texture);
2148 colorTable = theImage;
2149 properties.m_isColorTableLinear.setValue(theGeneratedKey, texture.m_flags.isLinear());
2152 if (opacity > 0.0f && particles.m_particleBuffer.particleCount()) {
2153 auto *theRenderableObject = RENDER_FRAME_NEW<QSSGParticlesRenderable>(contextInterface,
2164 if (theRenderableObject) {
2165 if (theRenderableObject->renderableFlags.requiresScreenTexture())
2166 screenTextureObjects.push_back({theRenderableObject, getCameraDistanceSq(*theRenderableObject, cameraData), particles.tag});
2167 else if (theRenderableObject->renderableFlags.hasTransparency())
2168 transparentObjects.push_back({theRenderableObject, getCameraDistanceSq(*theRenderableObject, cameraData), particles.tag});
2170 opaqueObjects.push_back({theRenderableObject, getCameraDistanceSq(*theRenderableObject, cameraData), particles.tag});
2457void QSSGLayerRenderData::prepareForRender()
2459 QSSG_ASSERT_X(layerPrepResult.isNull(),
"Prep-result was not reset for render!", layerPrepResult = {});
2461 QRect theViewport(renderer->viewport());
2465 frameData.m_ctx = renderer->contextInterface();
2470 ps.viewport = {
float(theViewport.x()),
float(theViewport.y()),
float(theViewport.width()),
float(theViewport.height()), 0.0f, 1.0f };
2471 if (layer.scissorRect.isValid()) {
2472 ps.flags |= QSSGRhiGraphicsPipelineState::Flag::UsesScissor;
2473 ps.scissor = { layer.scissorRect.x(),
2474 theViewport.height() - (layer.scissorRect.y() + layer.scissorRect.height()),
2475 layer.scissorRect.width(),
2476 layer.scissorRect.height() };
2479 ps.depthFunc = QRhiGraphicsPipeline::LessOrEqual;
2480 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
false);
2483 ps.polygonMode = layer.wireframeMode ? QRhiGraphicsPipeline::Line : QRhiGraphicsPipeline::Fill;
2485 bool wasDirty =
false;
2486 bool wasDataDirty =
false;
2487 wasDirty = layer.isDirty();
2489 const bool shouldDisableInternalPasses = (layer.renderOverrides & size_t(QSSGRenderLayer::RenderOverrides::DisableInternalPasses)) != 0;
2490 wasDirty |= (shouldDisableInternalPasses != disableMainPasses);
2491 disableMainPasses = shouldDisableInternalPasses;
2494 layerPrepResult = { theViewport, layer };
2497 const bool SSAOEnabled = layer.ssaoEnabled();
2498 layerPrepResult.flags.setRequiresSsaoPass(SSAOEnabled);
2499 features.set(QSSGShaderFeatures::Feature::Ssao, SSAOEnabled);
2502 bool requiresDepthTexture = SSAOEnabled;
2503 bool requiresNormalTexture =
false;
2504 bool requiresMotionVectorTexture =
false;
2505 for (QSSGRenderEffect *theEffect = layer.firstEffect; theEffect; theEffect = theEffect->m_nextEffect) {
2506 if (theEffect->isDirty()) {
2508 theEffect->clearDirty();
2510 if (theEffect->testFlag(QSSGRenderEffect::Flags::UsesDepthTexture))
2511 requiresDepthTexture =
true;
2512 if (theEffect->testFlag(QSSGRenderEffect::Flags::UsesNormalTexture))
2513 requiresNormalTexture =
true;
2514 if (theEffect->testFlag(QSSGRenderEffect::Flags::UsesMotionVectorTexture))
2515 requiresMotionVectorTexture =
true;
2518 const auto &rhiCtx = renderer->contextInterface()->rhiContext();
2519 orderIndependentTransparencyEnabled = (layer.oitMethod != QSSGRenderLayer::OITMethod::None);
2520 if (layer.oitMethod == QSSGRenderLayer::OITMethod::WeightedBlended) {
2521 orderIndependentTransparencyEnabled = rhiCtx->rhi()->isFeatureSupported(QRhi::PerRenderTargetBlending);
2522 if (rhiCtx->mainPassSampleCount() > 1)
2523 orderIndependentTransparencyEnabled &= rhiCtx->rhi()->isFeatureSupported(QRhi::TexelFetch) && rhiCtx->rhi()->isFeatureSupported(QRhi::SampleVariables);
2524 if (!orderIndependentTransparencyEnabled && !oitWarningUnsupportedShown) {
2525 qCWarning(lcQuick3DRender) <<
"WeightedBlended OIT is requested, but it is not supported.";
2526 oitWarningUnsupportedShown =
true;
2528 }
else if (layer.oitMethod == QSSGRenderLayer::OITMethod::LinkedList) {
2529 orderIndependentTransparencyEnabled = rhiCtx->rhi()->isTextureFormatSupported(QRhiTexture::RGBA32UI, QRhiTexture::UsedWithLoadStore);
2530 if (rhiCtx->mainPassSampleCount() > 1)
2531 orderIndependentTransparencyEnabled &= rhiCtx->rhi()->isFeatureSupported(QRhi::SampleVariables);
2532 if (!orderIndependentTransparencyEnabled && !oitWarningUnsupportedShown) {
2533 qCWarning(lcQuick3DRender) <<
"LinkedList OIT is requested, but it is not supported.";
2534 oitWarningUnsupportedShown =
true;
2537 if (layer.oitMethodDirty) {
2538 oitRenderContext.reset();
2539 for (
auto &renderResult : renderResults)
2540 renderResult.reset();
2543 layerPrepResult.flags.setRequiresDepthTexture(requiresDepthTexture);
2545 layerPrepResult.flags.setRequiresNormalTexture(requiresNormalTexture);
2547 layerPrepResult.flags.setRequiresMotionVectorPass(requiresMotionVectorTexture);
2551 if (!layer.firstEffect)
2552 QSSGLayerRenderData::setTonemapFeatures(features, layer.tonemapMode);
2559 if (rhiCtx->rhi()->resourceLimit(QRhi::MaxUniformBufferRange) < REDUCED_MAX_LIGHT_COUNT_THRESHOLD_BYTES) {
2560 features.set(QSSGShaderFeatures::Feature::ReduceMaxNumLights,
true);
2561 static bool notified =
false;
2564 qCDebug(lcQuick3DRender,
"Qt Quick 3D maximum number of lights has been reduced from %d to %d due to the graphics driver's limitations",
2565 QSSG_MAX_NUM_LIGHTS, QSSG_REDUCED_MAX_NUM_LIGHTS);
2570 const auto &lightProbeSettings = layer.lightProbeSettings;
2571 if (layer.lightProbe) {
2572 if (layer.lightProbe->m_format == QSSGRenderTextureFormat::Unknown) {
2575 if (renderer->contextInterface()->rhiContext()->rhi()->isTextureFormatSupported(QRhiTexture::RGBA16F))
2576 layer.lightProbe->m_format = QSSGRenderTextureFormat::RGBA16F;
2578 layer.lightProbe->m_format = QSSGRenderTextureFormat::RGBE8;
2581 if (layer.lightProbe->clearDirty())
2582 wasDataDirty =
true;
2584 features.set(QSSGShaderFeatures::Feature::LightProbe,
true);
2585 features.set(QSSGShaderFeatures::Feature::IblOrientation, !lightProbeSettings.probeOrientation.isIdentity());
2586 if (layer.lightProbe->m_format.format == QSSGRenderTextureFormat::Format::RGBE8)
2587 features.set(QSSGShaderFeatures::Feature::RGBELightProbe,
true);
2589 }
else if (layer.skyMaterial) {
2590 if (layer.skyMaterial->enableIBL) {
2591 features.set(QSSGShaderFeatures::Feature::LightProbe,
true);
2592 features.set(QSSGShaderFeatures::Feature::IblOrientation, !lightProbeSettings.probeOrientation.isIdentity());
2594 layerPrepResult.flags.setRequiresSkyMaterialPass(
true);
2597 const bool forceIblExposureValues = (features.isSet(QSSGShaderFeatures::Feature::LightProbe)
2598 && layer.tonemapMode == QSSGRenderLayer::TonemapMode::Custom);
2599 features.set(QSSGShaderFeatures::Feature::ForceIblExposure, forceIblExposureValues);
2601 frameData.m_ctx->bufferManager()->setLightmapSource(layer.lightmapSource);
2605 version = nodeData->version();
2610 auto &globalTransforms = nodeData->globalTransforms;
2611 auto &globalOpacities = nodeData->globalOpacities;
2612 auto &instanceTransforms = nodeData->instanceTransforms;
2615 QSSGRenderDataHelpers::GlobalStateResultT globalStateResult = QSSGRenderDataHelpers::GlobalStateResult::None;
2617 const bool layerTreeWasDirty = layer.isDirty(QSSGRenderLayer::DirtyFlag::TreeDirty);
2618 layer.clearDirty(QSSGRenderLayer::DirtyFlag::TreeDirty);
2619 if (layerTreeWasDirty) {
2620 wasDataDirty =
true;
2621 layerNodes = nodeData->getLayerNodeView(layer);
2623 using GlobalStateResult = QSSGRenderDataHelpers::GlobalStateResult;
2625 constexpr QSSGRenderDataHelpers::GlobalStateResultT FilterAffectingChanges = GlobalStateResult::ActiveChanged
2626 | GlobalStateResult::TagChanged;
2627 bool sharedStateChanged =
false;
2628 for (
auto &node : layerNodes) {
2629 const auto result = QSSGRenderDataHelpers::updateGlobalNodeState(node, version);
2630 globalStateResult |= result;
2634 const bool affectsFilter = ((result & FilterAffectingChanges) != 0);
2635 const bool isShared = node->getGlobalState(QSSGRenderNode::GlobalState::Imported);
2636 sharedStateChanged |= (affectsFilter && isShared);
2639 if (sharedStateChanged)
2640 nodeData->bumpStateGeneration();
2642 bool transformAndOpacityDirty =
false;
2643 for (
auto &node : layerNodes)
2644 transformAndOpacityDirty |= QSSGRenderDataHelpers::calcGlobalNodeData<QSSGRenderDataHelpers::Strategy::Update>(node, version, globalTransforms, globalOpacities);
2647 if (transformAndOpacityDirty) {
2648 for (
const auto &node : layerNodes)
2649 wasDataDirty |= QSSGRenderDataHelpers::calcInstanceTransforms(node, version, globalTransforms, instanceTransforms);
2652 wasDataDirty |= transformAndOpacityDirty;
2659 const bool viewportVisibilityDirty = layer.isDirty(QSSGRenderLayer::DirtyFlag::VisibilityDirty);
2660 layer.clearDirty(QSSGRenderLayer::DirtyFlag::VisibilityDirty);
2661 if (viewportVisibilityDirty)
2662 wasDataDirty =
true;
2667 const bool hasExplicitCamera = (layer.explicitCameras.size() != 0);
2668 bool cameraLayerMaskDirty =
false;
2669 quint32 layerMask = QSSGRenderCamera::LayerMaskAll;
2670 if (hasExplicitCamera) {
2671 QSSGRenderCamera *explicitCamera = layer.explicitCameras[0];
2674 layerMask = explicitCamera->tag.value() | QSSGRenderCamera::ReservedLayerMask;
2675 cameraLayerMaskDirty = explicitCamera->isDirty(QSSGRenderCamera::DirtyFlag::LayerMaskDirty);
2676 explicitCamera->clearDirty(QSSGRenderCamera::DirtyFlag::LayerMaskDirty);
2680 const bool sharedStateDirty = (stateGeneration != nodeData->stateGeneration());
2681 stateGeneration = nodeData->stateGeneration();
2683 const bool restatNodes = (layerTreeWasDirty
2684 || (globalStateResult & (QSSGRenderDataHelpers::GlobalStateResult::ActiveChanged | QSSGRenderDataHelpers::GlobalStateResult::TagChanged))
2685 || cameraLayerMaskDirty
2686 || sharedStateDirty);
2689 updateFilteredLayerNodes(layerMask);
2695 QSSGRenderCamera::Configuration cameraConfig { renderer->dpr(), layer.isSsaaEnabled() ? layer.ssaaMultiplier : 1.0f };
2696 renderedCameras.clear();
2697 if (!layer.explicitCameras.isEmpty()) {
2698 for (QSSGRenderCamera *cam : std::as_const(layer.explicitCameras)) {
2700 if (cam->getGlobalState(QSSGRenderCamera::GlobalState::Active)) {
2701 const bool computeFrustumSucceeded = cam->calculateProjection(theViewport, cameraConfig);
2702 if (Q_LIKELY(computeFrustumSucceeded))
2703 renderedCameras.append(cam);
2705 qCCritical(INTERNAL_ERROR,
"Failed to calculate camera frustum");
2709 }
else if (QSSG_GUARD_X(layer.viewCount == 1,
"Multiview rendering requires explicit cameras to be set!.")) {
2714 for (
auto iter = camerasView.begin(); renderedCameras.isEmpty() && iter != camerasView.end(); iter++) {
2715 QSSGRenderCamera *theCamera = *iter;
2716 if (theCamera->getGlobalState(QSSGRenderCamera::GlobalState::Active)) {
2717 const bool computeFrustumSucceeded = theCamera->calculateProjection(theViewport, cameraConfig);
2718 if (Q_LIKELY(computeFrustumSucceeded))
2719 renderedCameras.append(theCamera);
2721 qCCritical(INTERNAL_ERROR,
"Failed to calculate camera frustum");
2729 if (renderedCameras.size() > 0 && (renderedCameras[0]->layerMask & QSSGRenderCamera::LayerMaskUserAll) != QSSGRenderCamera::LayerMaskUserAll) {
2730 if (!nonExplicitCameraWithLayerMaskWarningShown) {
2731 nonExplicitCameraWithLayerMaskWarningShown =
true;
2732 qWarning() <<
"Scenes with non-explicit cameras with a layer detected!"
2733 " Set the camera explicitly to avoid unnecessary evaluation of scene nodes!";
2737 layerMask = renderedCameras[0]->layerMask;
2738 updateFilteredLayerNodes(layerMask);
2742 float meshLodThreshold = 1.0f;
2743 if (!renderedCameras.isEmpty())
2744 meshLodThreshold = renderedCameras[0]->levelOfDetailPixelThreshold / theViewport.width();
2746 layer.renderedCamerasMutex.lock();
2747 layer.renderedCameras = renderedCameras;
2748 layer.renderedCamerasMutex.unlock();
2751 const QSSGRenderCameraDataList &renderCameraData = getCachedCameraDatas();
2752 modelData->updateModelData(modelsView, renderer, renderCameraData);
2755 item2DData->updateItem2DData(item2DsView, renderer, renderCameraData);
2758 prepareResourceLoaders();
2761 updateDirtySkeletons(*
this, modelsView);
2764 int directionalLightsCount = 0;
2765 int positionalLightsCount = 0;
2766 const int maxLightCount = effectiveMaxLightCount(features);
2767 const int maxDirectionalLights = effectiveMaxDirectionalLightCount(features);
2768 QSSGShaderLightList renderableLights;
2769 int shadowMapCount = 0;
2770 bool hasScopedLights =
false;
2776 auto it = std::make_reverse_iterator(lightsView.end());
2777 const auto end = it + qMin(maxLightCount, lightsView.size());
2778 for (; it != end; ++it) {
2779 QSSGRenderLight *renderLight = (*it);
2780 QMatrix4x4 renderLightTransform = getGlobalTransform(*renderLight);
2781 if (renderLight->type == QSSGRenderGraphObject::Type::DirectionalLight)
2782 directionalLightsCount++;
2784 positionalLightsCount++;
2786 if (positionalLightsCount > maxLightCount)
2788 if (directionalLightsCount > maxDirectionalLights)
2792 hasScopedLights |= (renderLight->m_scope !=
nullptr);
2793 const bool castShadows = renderLight->m_castShadow && !renderLight->m_fullyBaked;
2794 shadowMapCount +=
int(castShadows);
2795 const auto &direction = renderLight->getScalingCorrectDirection(renderLightTransform);
2796 renderableLights.push_back(QSSGShaderLight{ renderLight, castShadows, direction });
2800 const bool showLightCountWarning = !tooManyLightsWarningShown && (positionalLightsCount > maxLightCount);
2801 if (showLightCountWarning) {
2802 qWarning(
"Too many lights in scene, maximum is %d", maxLightCount);
2803 tooManyLightsWarningShown =
true;
2806 const bool showDirectionalLightCountWarning = !tooManyDirectionalLightsWarningShown && (directionalLightsCount > maxDirectionalLights);
2807 if (showDirectionalLightCountWarning) {
2808 qWarning(
"Too many directional lights in scene, maximum is %d", maxDirectionalLights);
2809 tooManyDirectionalLightsWarningShown =
true;
2812 if (shadowMapCount > 0) {
2813 requestShadowMapManager();
2814 layerPrepResult.flags.setRequiresShadowMapPass(
true);
2819 features.set(QSSGShaderFeatures::Feature::Ssm,
true);
2820 shadowMapManager->addShadowMaps(renderableLights);
2821 }
else if (shadowMapManager) {
2823 shadowMapManager->releaseCachedResources();
2829 QSSG_ASSERT(globalLights.isEmpty(), globalLights.clear());
2830 if (hasScopedLights) {
2831 for (
const auto &shaderLight : std::as_const(renderableLights)) {
2832 if (!shaderLight.light->m_scope)
2833 globalLights.push_back(shaderLight);
2836 const auto prepareLightsWithScopedLights = [&renderableLights,
this](QVector<QSSGRenderableNodeEntry> &renderableNodes) {
2837 for (qint32 idx = 0, end = renderableNodes.size(); idx < end; ++idx) {
2838 QSSGRenderableNodeEntry &theNodeEntry(renderableNodes[idx]);
2839 QSSGShaderLightList filteredLights;
2840 for (
const auto &light : std::as_const(renderableLights)) {
2841 if (light.light->m_scope && !scopeLight(theNodeEntry.node, light.light->m_scope))
2843 filteredLights.push_back(light);
2846 if (filteredLights.isEmpty()) {
2847 theNodeEntry.lights = QSSGDataView(globalLights);
2852 auto customLightList = RENDER_FRAME_NEW_BUFFER<QSSGShaderLight>(*renderer->contextInterface(), filteredLights.size());
2853 std::copy(filteredLights.cbegin(), filteredLights.cend(), customLightList.begin());
2854 theNodeEntry.lights = customLightList;
2859 prepareLightsWithScopedLights(renderableModels);
2860 prepareLightsWithScopedLights(renderableParticles);
2862 globalLights = renderableLights;
2864 const auto prepareLights = [
this](QVector<QSSGRenderableNodeEntry> &renderableNodes) {
2865 for (qint32 idx = 0, end = renderableNodes.size(); idx < end; ++idx) {
2866 QSSGRenderableNodeEntry &theNodeEntry(renderableNodes[idx]);
2867 theNodeEntry.lights = QSSGDataView(globalLights);
2871 prepareLights(renderableModels);
2872 prepareLights(renderableParticles);
2878 Q_STATIC_ASSERT(USERPASSES == size_t(QSSGRenderLayer::RenderExtensionStage::Count));
2879 for (size_t i = 0; i != size_t(QSSGRenderLayer::RenderExtensionStage::Count); ++i) {
2880 const auto &renderExtensions = layer.renderExtensions[i];
2881 auto &userPass = userPasses[i];
2882 for (
auto rit = renderExtensions.crbegin(), rend = renderExtensions.crend(); rit != rend; ++rit) {
2883 if ((*rit)->prepareData(frameData)) {
2885 userPass.extensions.push_back(*rit);
2893 const auto &userRenderPassManager = requestUserRenderPassManager();
2894 userRenderPassManager->updateUserPassOrder(layerTreeWasDirty);
2895 userRenderPasses.userPasses = userRenderPassManager->scheduledUserPasses();
2898 auto &opaqueObjects = opaqueObjectStore[0];
2899 auto &transparentObjects = transparentObjectStore[0];
2900 auto &screenTextureObjects = screenTextureObjectStore[0];
2902 if (!renderedCameras.isEmpty()) {
2903 wasDirty |= prepareModelsForRender(*renderer->contextInterface(), renderableModels, layerPrepResult.flags, renderedCameras, getCachedCameraDatas(), modelContexts, opaqueObjects, transparentObjects, screenTextureObjects, meshLodThreshold);
2904 if (particlesEnabled) {
2905 const auto &cameraDatas = getCachedCameraDatas();
2906 wasDirty |= prepareParticlesForRender(renderableParticles, cameraDatas[0], layerPrepResult.flags);
2909 wasDirty |= (item2DsView.size() != 0);
2911 if (orderIndependentTransparencyEnabled) {
2913 if (transparentObjects.size() > 0 && !layerPrepResult.flags.hasCustomBlendMode()) {
2914 if (layer.oitMethod == QSSGRenderLayer::OITMethod::WeightedBlended) {
2915 if (rhiCtx->mainPassSampleCount() > 1)
2916 layerPrepResult.flags.setRequiresDepthTextureMS(
true);
2918 layerPrepResult.flags.setRequiresDepthTexture(
true);
2921 orderIndependentTransparencyEnabled =
false;
2922 if (!oitWarningInvalidBlendModeShown) {
2923 qCWarning(lcQuick3DRender) <<
"Order Independent Transparency requested, but disabled due to invalid blend modes.";
2924 qCWarning(lcQuick3DRender) <<
"Use SourceOver blend mode for Order Independent Transparency.";
2925 oitWarningInvalidBlendModeShown =
true;
2929 layer.oitMethodDirty =
false;
2931 prepareReflectionProbesForRender();
2933 wasDirty = wasDirty || wasDataDirty;
2934 layerPrepResult.flags.setWasDirty(wasDirty);
2935 layerPrepResult.flags.setLayerDataDirty(wasDataDirty);
2938 const bool animating = wasDirty;
2940 layer.progAAPassIndex = 0;
2942 const bool progressiveAA = layer.isProgressiveAAEnabled() && !animating;
2943 layer.progressiveAAIsActive = progressiveAA;
2944 const bool temporalAA = layer.isTemporalAAEnabled() && !progressiveAA;
2946 layer.temporalAAIsActive = temporalAA;
2948 QVector2D vertexOffsetsAA;
2950 if (progressiveAA && layer.progAAPassIndex > 0 && layer.progAAPassIndex < quint32(layer.antialiasingQuality)) {
2951 int idx = layer.progAAPassIndex - 1;
2952 vertexOffsetsAA = s_ProgressiveAAVertexOffsets[idx] / QVector2D{
float(theViewport.width()/2.0),
float(theViewport.height()/2.0) };
2956 if (layer.temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector && layer.tempAAPassIndex > 0) {
2957 if (layer.tempAAPassIndex >= quint32(MAX_AA_LEVELS) + 1)
2958 layer.tempAAPassIndex = 1;
2959 int idx = layer.tempAAPassIndex - 1;
2960 vertexOffsetsAA = s_ProgressiveAAVertexOffsets[idx] / QVector2D{
float(theViewport.width()/2.0),
float(theViewport.height()/2.0) };
2961 layer.currentAndLastJitter = QVector4D(vertexOffsetsAA, layer.currentAndLastJitter.x(), layer.currentAndLastJitter.y());
2962 layerPrepResult.flags.setRequiresMotionVectorPass(
true);
2963 layerPrepResult.flags.setRequiresDepthTexture(
true);
2965 const int t = 1 - 2 * (layer.tempAAPassIndex % 2);
2966 const float f = t * layer.temporalAAStrength;
2967 vertexOffsetsAA = { f /
float(theViewport.width()/2.0), f /
float(theViewport.height()/2.0) };
2971 if (!renderedCameras.isEmpty()) {
2972 if (temporalAA || progressiveAA ) {
2973 QMatrix4x4 offsetProjection = renderedCameras[0]->projection;
2974 QMatrix4x4 invProjection = renderedCameras[0]->projection.inverted();
2975 if (renderedCameras[0]->type == QSSGRenderCamera::Type::OrthographicCamera) {
2976 offsetProjection(0, 3) -= vertexOffsetsAA.x();
2977 offsetProjection(1, 3) -= vertexOffsetsAA.y();
2978 }
else if (renderedCameras[0]->type == QSSGRenderCamera::Type::PerspectiveCamera) {
2979 offsetProjection(0, 2) += vertexOffsetsAA.x();
2980 offsetProjection(1, 2) += vertexOffsetsAA.y();
2982 for (
auto &modelContext : std::as_const(modelContexts)) {
2983 for (
int mvpIdx = 0; mvpIdx < renderedCameras.count(); ++mvpIdx)
2984 modelContext->modelViewProjections[mvpIdx] = offsetProjection * invProjection * modelContext->modelViewProjections[mvpIdx];
2989 const bool hasItem2Ds = (item2DsView.size() > 0);
2990 const bool layerEnableDepthTest = layer.layerFlags.testFlag(QSSGRenderLayer::LayerFlag::EnableDepthTest);
2991 const bool layerEnabledDepthPrePass = layer.layerFlags.testFlag(QSSGRenderLayer::LayerFlag::EnableDepthPrePass);
2992 const bool depthTestEnableDefault = layerEnableDepthTest && (!opaqueObjects.isEmpty() || depthPrepassObjectsState || hasDepthWriteObjects);
2993 const bool zPrePassForced = (depthPrepassObjectsState != 0);
2994 zPrePassActive = zPrePassForced || (layerEnabledDepthPrePass && layerEnableDepthTest && (hasDepthWriteObjects || hasItem2Ds));
2995 const bool depthWriteEnableDefault = depthTestEnableDefault && (!layerEnabledDepthPrePass || !zPrePassActive);
2997 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, depthTestEnableDefault);
2998 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled, depthWriteEnableDefault);
3002 layerPrepResult.setState(QSSGLayerRenderPreparationResult::State::Done);
3005 QSSG_ASSERT(activePasses.isEmpty(), activePasses.clear());
3009 if (layerPrepResult.flags.requiresDepthTexture())
3010 activePasses.push_back(&depthMapPass);
3011 if (layerPrepResult.flags.requiresDepthTextureMS())
3012 activePasses.push_back(&depthMapPassMS);
3014 if (layerPrepResult.flags.requiresNormalTexture())
3015 activePasses.push_back(&normalPass);
3018 if (layerPrepResult.flags.requiresSsaoPass())
3019 activePasses.push_back(&ssaoMapPass);
3022 if (layerPrepResult.flags.requiresShadowMapPass())
3023 activePasses.push_back(&shadowMapPass);
3025 if (zPrePassActive && !disableMainPasses)
3026 activePasses.push_back(&zPrePassPass);
3029 if (layerPrepResult.flags.requiresScreenTexture())
3030 activePasses.push_back(&screenMapPass);
3033 if (layerPrepResult.flags.requiresSkyMaterialPass())
3034 activePasses.push_back(&skyMaterialPass);
3037 if (reflectionProbesView.size() != 0)
3038 activePasses.push_back(&reflectionMapPass);
3040 auto &textureExtensionPass = userPasses[size_t(QSSGRenderLayer::RenderExtensionStage::TextureProviders)];
3041 if (textureExtensionPass.hasData())
3042 activePasses.push_back(&textureExtensionPass);
3044 auto &underlayPass = userPasses[size_t(QSSGRenderLayer::RenderExtensionStage::Underlay)];
3045 if (underlayPass.hasData())
3046 activePasses.push_back(&underlayPass);
3049 if (userRenderPasses.hasData())
3050 activePasses.push_back(&userRenderPasses);
3052 const bool hasOpaqueObjects = (opaqueObjects.size() > 0);
3054 if (hasOpaqueObjects && !disableMainPasses)
3055 activePasses.push_back(&opaquePass);
3058 if (layerPrepResult.flags.requiresMotionVectorPass())
3059 activePasses.push_back(&motionVectorMapPass);
3063 if (renderer->contextInterface()->rhiContext()->rhi()->isFeatureSupported(QRhi::TexelFetch)) {
3064 if (layer.background == QSSGRenderLayer::Background::SkyBoxCubeMap && layer.skyBoxCubeMap && !disableMainPasses)
3065 activePasses.push_back(&skyboxCubeMapPass);
3066 else if (layer.background == QSSGRenderLayer::Background::SkyBox && layer.lightProbe && !disableMainPasses)
3067 activePasses.push_back(&skyboxPass);
3068 else if (layer.background == QSSGRenderLayer::Background::SkyMaterial && layer.skyMaterial && !disableMainPasses) {
3069 if (layer.skyMaterial->skyboxMode != QSSGRenderSkyMaterial::SkyboxMode::Cubemap)
3070 activePasses.push_back(&skyMaterialBackgroundPass);
3072 activePasses.push_back(&skyboxPass);
3076 if (hasItem2Ds && !disableMainPasses)
3077 activePasses.push_back(&item2DPass);
3079 if (layerPrepResult.flags.requiresScreenTexture())
3080 activePasses.push_back(&reflectionPass);
3083 if ((transparentObjects.size() > 0 || (!layerEnableDepthTest && hasOpaqueObjects)) && !disableMainPasses) {
3084 if (orderIndependentTransparencyEnabled) {
3085 activePasses.push_back(&oitRenderPass);
3086 activePasses.push_back(&oitCompositePass);
3087 oitRenderPass.setMethod(layer.oitMethod);
3088 oitCompositePass.setMethod(layer.oitMethod);
3090 activePasses.push_back(&transparentPass);
3094 auto &overlayPass = userPasses[size_t(QSSGRenderLayer::RenderExtensionStage::Overlay)];
3095 if (overlayPass.hasData())
3096 activePasses.push_back(&overlayPass);
3098 if (layer.gridEnabled)
3099 activePasses.push_back(&infiniteGridPass);
3101 if (
const auto &dbgDrawSystem = renderer->contextInterface()->debugDrawSystem(); dbgDrawSystem && dbgDrawSystem->isEnabled() && !disableMainPasses)
3102 activePasses.push_back(&debugDrawPass);