975void QSSGLayerRenderData::prepareImageForRender(QSSGRenderImage &inImage,
976 QSSGRenderableImage::Type inMapType,
977 QSSGRenderableImage *&ioFirstImage,
978 QSSGRenderableImage *&ioNextImage,
979 QSSGRenderableObjectFlags &ioFlags,
980 QSSGShaderDefaultMaterialKey &inShaderKey,
981 quint32 inImageIndex,
982 QSSGRenderDefaultMaterial *inMaterial)
984 QSSGRenderContextInterface &contextInterface = *renderer->contextInterface();
985 const auto &bufferManager = contextInterface.bufferManager();
987 if (inImage.clearDirty())
988 ioFlags |= QSSGRenderableObjectFlag::Dirty;
999 const QSSGRenderImageTexture texture = bufferManager->loadRenderImage(&inImage);
1001 if (texture.m_texture) {
1002 if (texture.m_flags.hasTransparency()
1003 && (inMapType == QSSGRenderableImage::Type::Diffuse
1004 || inMapType == QSSGRenderableImage::Type::Opacity
1005 || inMapType == QSSGRenderableImage::Type::Translucency))
1007 ioFlags |= QSSGRenderableObjectFlag::HasTransparency;
1010 QSSGRenderableImage *theImage = RENDER_FRAME_NEW<QSSGRenderableImage>(contextInterface, inMapType, inImage, texture);
1011 QSSGShaderKeyImageMap &theKeyProp = defaultMaterialShaderKeyProperties.m_imageMaps[inImageIndex];
1013 theKeyProp.setEnabled(inShaderKey,
true);
1014 switch (inImage.m_mappingMode) {
1015 case QSSGRenderImage::MappingModes::Normal:
1017 case QSSGRenderImage::MappingModes::Environment:
1018 theKeyProp.setEnvMap(inShaderKey,
true);
1020 case QSSGRenderImage::MappingModes::LightProbe:
1021 theKeyProp.setLightProbe(inShaderKey,
true);
1031 switch (texture.m_texture->format()) {
1032 case QRhiTexture::Format::RED_OR_ALPHA8:
1033 hasA = !renderer->contextInterface()->rhiContext()->rhi()->isFeatureSupported(QRhi::RedOrAlpha8IsRed);
1035 case QRhiTexture::Format::R8:
1045 if (inImage.isImageTransformIdentity())
1046 theKeyProp.setIdentityTransform(inShaderKey,
true);
1048 if (inImage.m_indexUV == 1)
1049 theKeyProp.setUsesUV1(inShaderKey,
true);
1051 if (texture.m_flags.isLinear())
1052 theKeyProp.setLinear(inShaderKey,
true);
1054 if (texture.m_flags.isPreMultipliedAlpha())
1055 theKeyProp.setPreMultipliedAlpha(inShaderKey,
true);
1057 if (ioFirstImage ==
nullptr)
1058 ioFirstImage = theImage;
1060 ioNextImage->m_nextImage = theImage;
1062 ioNextImage = theImage;
1064 if (inMaterial && inImageIndex >= QSSGShaderDefaultMaterialKeyProperties::SingleChannelImagesFirst) {
1065 QSSGRenderDefaultMaterial::TextureChannelMapping value = QSSGRenderDefaultMaterial::R;
1067 const quint32 scIndex = inImageIndex - QSSGShaderDefaultMaterialKeyProperties::SingleChannelImagesFirst;
1068 QSSGShaderKeyTextureChannel &channelKey = defaultMaterialShaderKeyProperties.m_textureChannels[scIndex];
1069 switch (inImageIndex) {
1070 case QSSGShaderDefaultMaterialKeyProperties::OpacityMap:
1071 value = inMaterial->opacityChannel;
1073 case QSSGShaderDefaultMaterialKeyProperties::RoughnessMap:
1074 value = inMaterial->roughnessChannel;
1076 case QSSGShaderDefaultMaterialKeyProperties::MetalnessMap:
1077 value = inMaterial->metalnessChannel;
1079 case QSSGShaderDefaultMaterialKeyProperties::OcclusionMap:
1080 value = inMaterial->occlusionChannel;
1082 case QSSGShaderDefaultMaterialKeyProperties::TranslucencyMap:
1083 value = inMaterial->translucencyChannel;
1085 case QSSGShaderDefaultMaterialKeyProperties::HeightMap:
1086 value = inMaterial->heightChannel;
1088 case QSSGShaderDefaultMaterialKeyProperties::ClearcoatMap:
1089 value = inMaterial->clearcoatChannel;
1091 case QSSGShaderDefaultMaterialKeyProperties::ClearcoatRoughnessMap:
1092 value = inMaterial->clearcoatRoughnessChannel;
1094 case QSSGShaderDefaultMaterialKeyProperties::TransmissionMap:
1095 value = inMaterial->transmissionChannel;
1097 case QSSGShaderDefaultMaterialKeyProperties::ThicknessMap:
1098 value = inMaterial->thicknessChannel;
1100 case QSSGShaderDefaultMaterialKeyProperties::BaseColorMap:
1101 value = inMaterial->baseColorChannel;
1103 case QSSGShaderDefaultMaterialKeyProperties::SpecularAmountMap:
1104 value = inMaterial->specularAmountChannel;
1106 case QSSGShaderDefaultMaterialKeyProperties::EmissiveMap:
1107 value = inMaterial->emissiveChannel;
1112 bool useDefault =
false;
1114 case QSSGRenderDefaultMaterial::TextureChannelMapping::G:
1117 case QSSGRenderDefaultMaterial::TextureChannelMapping::B:
1120 case QSSGRenderDefaultMaterial::TextureChannelMapping::A:
1127 value = QSSGRenderDefaultMaterial::R;
1128 channelKey.setTextureChannel(QSSGShaderKeyTextureChannel::TexturChannelBits(value), inShaderKey);
1158QSSGDefaultMaterialPreparationResult QSSGLayerRenderData::prepareDefaultMaterialForRender(
1159 QSSGRenderDefaultMaterial &inMaterial,
1160 QSSGRenderableObjectFlags &inExistingFlags,
1161 float inOpacity,
bool hasAnyLights,
1162 bool anyLightHasShadows,
1163 QSSGLayerRenderPreparationResultFlags &ioFlags)
1165 QSSGRenderDefaultMaterial *theMaterial = &inMaterial;
1166 QSSGDefaultMaterialPreparationResult retval(QSSGShaderDefaultMaterialKey(qHash(features)));
1167 retval.renderableFlags = inExistingFlags;
1168 QSSGRenderableObjectFlags &renderableFlags(retval.renderableFlags);
1169 QSSGShaderDefaultMaterialKey &theGeneratedKey(retval.materialKey);
1170 retval.opacity = inOpacity;
1171 float &subsetOpacity(retval.opacity);
1173 if (theMaterial->isDirty())
1174 renderableFlags |= QSSGRenderableObjectFlag::Dirty;
1176 subsetOpacity *= theMaterial->opacity;
1178 QSSGRenderableImage *firstImage =
nullptr;
1180 const bool lighting = theMaterial->lighting != QSSGRenderDefaultMaterial::MaterialLighting::NoLighting;
1181 defaultMaterialShaderKeyProperties.m_hasLighting.setValue(theGeneratedKey, lighting);
1183 defaultMaterialShaderKeyProperties.m_hasPunctualLights.setValue(theGeneratedKey, hasAnyLights);
1184 defaultMaterialShaderKeyProperties.m_hasShadows.setValue(theGeneratedKey, anyLightHasShadows);
1185 const bool validSky = layer.skyMaterial !=
nullptr && layer.skyMaterial->enableIBL;
1186 defaultMaterialShaderKeyProperties.m_hasIbl.setValue(theGeneratedKey, layer.lightProbe !=
nullptr || validSky);
1189 defaultMaterialShaderKeyProperties.m_specularAAEnabled.setValue(theGeneratedKey, layer.specularAAEnabled);
1192 defaultMaterialShaderKeyProperties.m_isDoubleSided.setValue(theGeneratedKey, theMaterial->cullMode == QSSGCullFaceMode::Disabled);
1195 defaultMaterialShaderKeyProperties.m_overridesPosition.setValue(theGeneratedKey,
false);
1198 defaultMaterialShaderKeyProperties.m_usesProjectionMatrix.setValue(theGeneratedKey,
false);
1199 defaultMaterialShaderKeyProperties.m_usesInverseProjectionMatrix.setValue(theGeneratedKey,
false);
1201 defaultMaterialShaderKeyProperties.m_usesVarColor.setValue(theGeneratedKey,
false);
1204 defaultMaterialShaderKeyProperties.m_alphaMode.setValue(theGeneratedKey, theMaterial->alphaMode);
1207 setVertexInputPresence(renderableFlags, theGeneratedKey);
1210 defaultMaterialShaderKeyProperties.m_usesPointsTopology.setValue(theGeneratedKey, renderableFlags.isPointsTopology());
1213 defaultMaterialShaderKeyProperties.m_lightmapEnabled.setValue(theGeneratedKey, renderableFlags.rendersWithLightmap());
1214 defaultMaterialShaderKeyProperties.m_metallicRoughnessEnabled.setValue(theGeneratedKey, theMaterial->type == QSSGRenderDefaultMaterial::Type::PrincipledMaterial);
1215 defaultMaterialShaderKeyProperties.m_specularGlossyEnabled.setValue(theGeneratedKey, theMaterial->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial);
1219 defaultMaterialShaderKeyProperties.m_debugMode.setValue(theGeneratedKey,
int(layer.debugMode));
1222 defaultMaterialShaderKeyProperties.m_fogEnabled.setValue(theGeneratedKey, layer.fog.enabled);
1225 defaultMaterialShaderKeyProperties.m_viewCount.setValue(theGeneratedKey, layer.viewCount);
1226 defaultMaterialShaderKeyProperties.m_usesViewIndex.setValue(theGeneratedKey, layer.viewCount >= 2);
1228 if (!defaultMaterialShaderKeyProperties.m_hasIbl.getValue(theGeneratedKey) && theMaterial->iblProbe) {
1229 features.set(QSSGShaderFeatures::Feature::LightProbe,
true);
1230 defaultMaterialShaderKeyProperties.m_hasIbl.setValue(theGeneratedKey,
true);
1235 if (subsetOpacity >= QSSGRendererPrivate::minimumRenderOpacity) {
1251 if (theMaterial->blendMode != QSSGRenderDefaultMaterial::MaterialBlendMode::SourceOver
1252 || theMaterial->opacityMap
1253 || theMaterial->alphaMode == QSSGRenderDefaultMaterial::Blend)
1255 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1258 const bool specularEnabled = theMaterial->isSpecularEnabled();
1259 const bool metalnessEnabled = theMaterial->isMetalnessEnabled();
1260 defaultMaterialShaderKeyProperties.m_specularEnabled.setValue(theGeneratedKey, specularEnabled || metalnessEnabled);
1261 defaultMaterialShaderKeyProperties.m_specularModel.setSpecularModel(theGeneratedKey, theMaterial->specularModel);
1262 defaultMaterialShaderKeyProperties.m_diffuseModel.setDiffuseModel(theGeneratedKey, theMaterial->diffuseModel);
1263 defaultMaterialShaderKeyProperties.m_fresnelScaleBiasEnabled.setValue(theGeneratedKey, theMaterial->isFresnelScaleBiasEnabled());
1264 defaultMaterialShaderKeyProperties.m_clearcoatFresnelScaleBiasEnabled.setValue(theGeneratedKey, theMaterial->isClearcoatFresnelScaleBiasEnabled());
1265 defaultMaterialShaderKeyProperties.m_fresnelEnabled.setValue(theGeneratedKey, theMaterial->isFresnelEnabled());
1266 defaultMaterialShaderKeyProperties.m_baseColorSingleChannelEnabled.setValue(theGeneratedKey, theMaterial->isBaseColorSingleChannelEnabled());
1267 defaultMaterialShaderKeyProperties.m_specularSingleChannelEnabled.setValue(theGeneratedKey, theMaterial->isSpecularAmountSingleChannelEnabled());
1268 defaultMaterialShaderKeyProperties.m_emissiveSingleChannelEnabled.setValue(theGeneratedKey, theMaterial->isEmissiveSingleChannelEnabled());
1269 defaultMaterialShaderKeyProperties.m_invertOpacityMapValue.setValue(theGeneratedKey, theMaterial->isInvertOpacityMapValue());
1270 defaultMaterialShaderKeyProperties.m_vertexColorsEnabled.setValue(theGeneratedKey, theMaterial->isVertexColorsEnabled());
1271 defaultMaterialShaderKeyProperties.m_vertexColorsMaskEnabled.setValue(theGeneratedKey, theMaterial->isVertexColorsMaskEnabled());
1272 defaultMaterialShaderKeyProperties.m_vertexColorRedMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorRedMask.toInt()));
1273 defaultMaterialShaderKeyProperties.m_vertexColorGreenMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorGreenMask.toInt()));
1274 defaultMaterialShaderKeyProperties.m_vertexColorBlueMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorBlueMask.toInt()));
1275 defaultMaterialShaderKeyProperties.m_vertexColorAlphaMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorAlphaMask.toInt()));
1276 defaultMaterialShaderKeyProperties.m_clearcoatEnabled.setValue(theGeneratedKey, theMaterial->isClearcoatEnabled());
1277 defaultMaterialShaderKeyProperties.m_transmissionEnabled.setValue(theGeneratedKey, theMaterial->isTransmissionEnabled());
1282 QSSGRenderableImage *nextImage =
nullptr;
1283#define CHECK_IMAGE_AND_PREPARE(img, imgtype, shadercomponent)
1285 prepareImageForRender(*(img), imgtype, firstImage, nextImage, renderableFlags,
1286 theGeneratedKey, shadercomponent, &inMaterial)
1288 if (theMaterial->type == QSSGRenderGraphObject::Type::PrincipledMaterial ||
1289 theMaterial->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial) {
1291 QSSGRenderableImage::Type::BaseColor,
1292 QSSGShaderDefaultMaterialKeyProperties::BaseColorMap);
1294 QSSGRenderableImage::Type::Occlusion,
1295 QSSGShaderDefaultMaterialKeyProperties::OcclusionMap);
1297 QSSGRenderableImage::Type::Height,
1298 QSSGShaderDefaultMaterialKeyProperties::HeightMap);
1300 QSSGRenderableImage::Type::Clearcoat,
1301 QSSGShaderDefaultMaterialKeyProperties::ClearcoatMap);
1303 QSSGRenderableImage::Type::ClearcoatRoughness,
1304 QSSGShaderDefaultMaterialKeyProperties::ClearcoatRoughnessMap);
1306 QSSGRenderableImage::Type::ClearcoatNormal,
1307 QSSGShaderDefaultMaterialKeyProperties::ClearcoatNormalMap);
1309 QSSGRenderableImage::Type::Transmission,
1310 QSSGShaderDefaultMaterialKeyProperties::TransmissionMap);
1312 QSSGRenderableImage::Type::Thickness,
1313 QSSGShaderDefaultMaterialKeyProperties::ThicknessMap);
1314 if (theMaterial->type == QSSGRenderGraphObject::Type::PrincipledMaterial) {
1316 QSSGRenderableImage::Type::Metalness,
1317 QSSGShaderDefaultMaterialKeyProperties::MetalnessMap);
1321 QSSGRenderableImage::Type::Diffuse,
1322 QSSGShaderDefaultMaterialKeyProperties::DiffuseMap);
1324 CHECK_IMAGE_AND_PREPARE(theMaterial->emissiveMap, QSSGRenderableImage::Type::Emissive, QSSGShaderDefaultMaterialKeyProperties::EmissiveMap);
1326 QSSGRenderableImage::Type::Specular,
1327 QSSGShaderDefaultMaterialKeyProperties::SpecularMap);
1329 QSSGRenderableImage::Type::Roughness,
1330 QSSGShaderDefaultMaterialKeyProperties::RoughnessMap);
1331 CHECK_IMAGE_AND_PREPARE(theMaterial->opacityMap, QSSGRenderableImage::Type::Opacity, QSSGShaderDefaultMaterialKeyProperties::OpacityMap);
1332 CHECK_IMAGE_AND_PREPARE(theMaterial->bumpMap, QSSGRenderableImage::Type::Bump, QSSGShaderDefaultMaterialKeyProperties::BumpMap);
1334 QSSGRenderableImage::Type::SpecularAmountMap,
1335 QSSGShaderDefaultMaterialKeyProperties::SpecularAmountMap);
1336 CHECK_IMAGE_AND_PREPARE(theMaterial->normalMap, QSSGRenderableImage::Type::Normal, QSSGShaderDefaultMaterialKeyProperties::NormalMap);
1338 QSSGRenderableImage::Type::Translucency,
1339 QSSGShaderDefaultMaterialKeyProperties::TranslucencyMap);
1341#undef CHECK_IMAGE_AND_PREPARE
1343 if (subsetOpacity < QSSGRendererPrivate::minimumRenderOpacity) {
1344 subsetOpacity = 0.0f;
1348 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1349 renderableFlags |= QSSGRenderableObjectFlag::CompletelyTransparent;
1352 if (subsetOpacity > 1.f - QSSGRendererPrivate::minimumRenderOpacity)
1353 subsetOpacity = 1.f;
1355 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1357 if (inMaterial.isTransmissionEnabled()) {
1358 ioFlags.setRequiresScreenTexture(
true);
1359 ioFlags.setRequiresMipmapsForScreenTexture(
true);
1360 renderableFlags |= QSSGRenderableObjectFlag::RequiresScreenTexture;
1363 if (renderableFlags.hasTransparency()) {
1364 if (orderIndependentTransparencyEnabled)
1365 defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(layer.oitMethod));
1366 if (layer.oitMethodDirty)
1367 renderableFlags |= QSSGRenderableObjectFlag::Dirty;
1370 retval.firstImage = firstImage;
1371 if (retval.renderableFlags.isDirty())
1372 retval.dirty =
true;
1374 renderer->addMaterialDirtyClear(&inMaterial);
1378QSSGDefaultMaterialPreparationResult QSSGLayerRenderData::prepareCustomMaterialForRender(
1379 QSSGRenderCustomMaterial &inMaterial, QSSGRenderableObjectFlags &inExistingFlags,
1380 float inOpacity,
bool alreadyDirty,
bool hasAnyLights,
bool anyLightHasShadows,
1381 QSSGLayerRenderPreparationResultFlags &ioFlags)
1383 QSSGDefaultMaterialPreparationResult retval(QSSGShaderDefaultMaterialKey(qHash(features)));
1384 retval.renderableFlags = inExistingFlags;
1385 QSSGRenderableObjectFlags &renderableFlags(retval.renderableFlags);
1386 QSSGShaderDefaultMaterialKey &theGeneratedKey(retval.materialKey);
1387 retval.opacity = inOpacity;
1388 float &subsetOpacity(retval.opacity);
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 defaultMaterialShaderKeyProperties.m_hasLighting.setValue(theGeneratedKey,
true);
1405 defaultMaterialShaderKeyProperties.m_hasPunctualLights.setValue(theGeneratedKey, hasAnyLights);
1406 defaultMaterialShaderKeyProperties.m_hasShadows.setValue(theGeneratedKey, anyLightHasShadows);
1407 defaultMaterialShaderKeyProperties.m_hasIbl.setValue(theGeneratedKey, layer.lightProbe !=
nullptr || layer.skyMaterial !=
nullptr);
1408 defaultMaterialShaderKeyProperties.m_specularEnabled.setValue(theGeneratedKey,
true);
1410 defaultMaterialShaderKeyProperties.m_specularAAEnabled.setValue(theGeneratedKey, layer.specularAAEnabled);
1413 defaultMaterialShaderKeyProperties.m_isDoubleSided.setValue(theGeneratedKey, inMaterial.m_cullMode == QSSGCullFaceMode::Disabled);
1416 defaultMaterialShaderKeyProperties.m_metallicRoughnessEnabled.setValue(theGeneratedKey,
true);
1419 const bool overridesPosition = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::OverridesPosition);
1420 defaultMaterialShaderKeyProperties.m_overridesPosition.setValue(theGeneratedKey, overridesPosition);
1423 const bool usesProjectionMatrix = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ProjectionMatrix);
1424 defaultMaterialShaderKeyProperties.m_usesProjectionMatrix.setValue(theGeneratedKey, usesProjectionMatrix);
1425 const bool usesInvProjectionMatrix = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::InverseProjectionMatrix);
1426 defaultMaterialShaderKeyProperties.m_usesInverseProjectionMatrix.setValue(theGeneratedKey, usesInvProjectionMatrix);
1429 setVertexInputPresence(renderableFlags, theGeneratedKey);
1432 defaultMaterialShaderKeyProperties.m_usesPointsTopology.setValue(theGeneratedKey, renderableFlags.isPointsTopology());
1435 defaultMaterialShaderKeyProperties.m_lightmapEnabled.setValue(theGeneratedKey, renderableFlags.rendersWithLightmap());
1438 defaultMaterialShaderKeyProperties.m_debugMode.setValue(theGeneratedKey,
int(layer.debugMode));
1441 defaultMaterialShaderKeyProperties.m_fogEnabled.setValue(theGeneratedKey, layer.fog.enabled);
1444 defaultMaterialShaderKeyProperties.m_viewCount.setValue(theGeneratedKey, layer.viewCount);
1445 defaultMaterialShaderKeyProperties.m_usesViewIndex.setValue(theGeneratedKey,
1446 inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ViewIndex));
1451 const bool usesVarColor = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::VarColor);
1452 defaultMaterialShaderKeyProperties.m_usesVarColor.setValue(theGeneratedKey, usesVarColor);
1454 const bool usesClearcoat = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Clearcoat);
1455 defaultMaterialShaderKeyProperties.m_clearcoatEnabled.setValue(theGeneratedKey, usesClearcoat);
1457 const bool usesClearcoatFresnelScaleBias = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ClearcoatFresnelScaleBias);
1458 defaultMaterialShaderKeyProperties.m_clearcoatFresnelScaleBiasEnabled.setValue(theGeneratedKey, usesClearcoatFresnelScaleBias);
1460 const bool usesFresnelScaleBias = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::FresnelScaleBias);
1461 defaultMaterialShaderKeyProperties.m_fresnelScaleBiasEnabled.setValue(theGeneratedKey, usesFresnelScaleBias);
1463 const bool usesTransmission = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Transmission);
1464 defaultMaterialShaderKeyProperties.m_transmissionEnabled.setValue(theGeneratedKey, usesTransmission);
1466 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Blending))
1467 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1469 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ScreenTexture)) {
1470 ioFlags.setRequiresScreenTexture(
true);
1471 renderableFlags |= QSSGRenderableObjectFlag::RequiresScreenTexture;
1474 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ScreenMipTexture)) {
1475 ioFlags.setRequiresScreenTexture(
true);
1476 ioFlags.setRequiresMipmapsForScreenTexture(
true);
1477 renderableFlags |= QSSGRenderableObjectFlag::RequiresScreenTexture;
1480 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::DepthTexture))
1481 ioFlags.setRequiresDepthTexture(
true);
1483 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::NormalTexture)) {
1484 ioFlags.setRequiresNormalTexture(
true);
1485 renderableFlags |= QSSGRenderableObjectFlag::RequiresNormalTexture;
1488 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::AoTexture)) {
1489 ioFlags.setRequiresDepthTexture(
true);
1490 ioFlags.setRequiresSsaoPass(
true);
1492 if (orderIndependentTransparencyEnabled && renderableFlags.hasTransparency())
1493 defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(layer.oitMethod));
1495 retval.firstImage =
nullptr;
1497 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::MotionVectorTexture))
1498 ioFlags.setRequiresMotionVectorPass(
true);
1500 if (retval.dirty || alreadyDirty)
1501 renderer->addMaterialDirtyClear(&inMaterial);
1559bool QSSGLayerRenderData::prepareModelsForRender(QSSGRenderContextInterface &contextInterface,
1560 const RenderableNodeEntries &renderableModels,
1561 QSSGLayerRenderPreparationResultFlags &ioFlags,
1562 const QSSGRenderCameraList &allCameras,
1563 const QSSGRenderCameraDataList &allCameraData,
1564 TModelContextPtrList &modelContexts,
1565 QSSGRenderableObjectList &opaqueObjects,
1566 QSSGRenderableObjectList &transparentObjects,
1567 QSSGRenderableObjectList &screenTextureObjects,
1570 const auto &rhiCtx = contextInterface.rhiContext();
1571 const auto &bufferManager = contextInterface.bufferManager();
1573 const auto &debugDrawSystem = contextInterface.debugDrawSystem();
1574 const bool maybeDebugDraw = debugDrawSystem && debugDrawSystem->isEnabled();
1576 bool wasDirty =
false;
1578 for (
const QSSGRenderableNodeEntry &renderable : renderableModels) {
1579 if ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::Disabled) != 0)
1582 const QSSGRenderModel &model = *
static_cast<QSSGRenderModel *>(renderable.node);
1583 const auto &lights = renderable.lights;
1584 QSSGRenderMesh *theMesh = modelData->getMesh(model);
1588 const bool altGlobalTransform = ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::GlobalTransform) != 0);
1589 const auto &globalTransform = altGlobalTransform ? renderable.extOverrides.globalTransform : getGlobalTransform(model);
1590 QMatrix3x3 normalMatrix { Qt::Uninitialized };
1591 QSSGLayerRenderData::ModelViewProjections mvps;
1592 if (altGlobalTransform) {
1593 QSSGRenderNode::calculateNormalMatrix(globalTransform, normalMatrix);
1594 size_t mvpCount = 0;
1595 for (
const auto &cameraData : allCameraData) {
1596 QSSGRenderNode::calculateMVPAndNormalMatrix(globalTransform, cameraData.viewProjection, mvps[mvpCount++], normalMatrix);
1599 if (model.usesBoneTexture()) {
1603 size_t mvpCount = 0;
1604 for (
const QSSGRenderCameraData &cameraData : allCameraData) {
1605 mvps[mvpCount++] = cameraData.viewProjection;
1606 normalMatrix = QMatrix3x3();
1609 normalMatrix = getNormalMatrix(model);
1610 mvps = getModelMvps(model);
1613 const bool altModelOpacity = ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::GlobalOpacity) != 0);
1614 const float modelGlobalOpacity = altModelOpacity ? renderable.extOverrides.globalOpacity : getGlobalOpacity(model);
1615 QSSGModelContext &theModelContext = *RENDER_FRAME_NEW<QSSGModelContext>(contextInterface, model, globalTransform, normalMatrix, mvps);
1616 modelContexts.push_back(&theModelContext);
1619 const auto &meshSubsets = theMesh->subsets;
1620 const auto meshSubsetCount = meshSubsets.size();
1621 theModelContext.subsets = RENDER_FRAME_NEW_BUFFER<QSSGSubsetRenderable>(contextInterface, meshSubsetCount);
1625 auto boneTexture = bufferManager->loadSkinmap(model.skin);
1626 setBonemapTexture(theModelContext, boneTexture.m_texture);
1627 }
else if (model.skeleton) {
1628 auto boneTexture = bufferManager->loadSkinmap(&(model.skeleton->boneTexData));
1629 setBonemapTexture(theModelContext, boneTexture.m_texture);
1633 QSSGRenderableObjectFlags renderableFlagsForModel;
1635 if (meshSubsetCount > 0) {
1636 const QSSGRenderSubset &theSubset = meshSubsets.at(0);
1638 renderableFlagsForModel.setMotionVectorParticipant(model.motionVectorEnabled);
1640 renderableFlagsForModel.setCastsShadows(model.castsShadows);
1641 renderableFlagsForModel.setReceivesShadows(model.receivesShadows);
1642 renderableFlagsForModel.setReceivesReflections(model.receivesReflections);
1643 renderableFlagsForModel.setCastsReflections(model.castsReflections);
1645 renderableFlagsForModel.setUsedInBakedLighting(model.usedInBakedLighting);
1646 if (model.hasLightmap()) {
1647 QSSGRenderImageTexture lmImageTexture = bufferManager->loadLightmap(model);
1648 if (lmImageTexture.m_texture) {
1649 renderableFlagsForModel.setRendersWithLightmap(
true);
1650 setLightmapTexture(theModelContext, lmImageTexture.m_texture);
1659 bool hasJoint =
false;
1660 bool hasWeight =
false;
1661 bool hasMorphTarget = theSubset.rhi.targetsTexture !=
nullptr;
1662 for (
const QSSGRhiInputAssemblerState::InputSemantic &sem : std::as_const(theSubset.rhi.ia.inputs)) {
1663 if (sem == QSSGRhiInputAssemblerState::PositionSemantic) {
1664 renderableFlagsForModel.setHasAttributePosition(
true);
1665 }
else if (sem == QSSGRhiInputAssemblerState::NormalSemantic) {
1666 renderableFlagsForModel.setHasAttributeNormal(
true);
1667 }
else if (sem == QSSGRhiInputAssemblerState::TexCoord0Semantic) {
1668 renderableFlagsForModel.setHasAttributeTexCoord0(
true);
1669 }
else if (sem == QSSGRhiInputAssemblerState::TexCoord1Semantic) {
1670 renderableFlagsForModel.setHasAttributeTexCoord1(
true);
1671 }
else if (sem == QSSGRhiInputAssemblerState::TexCoordLightmapSemantic) {
1672 renderableFlagsForModel.setHasAttributeTexCoordLightmap(
true);
1673 }
else if (sem == QSSGRhiInputAssemblerState::TangentSemantic) {
1674 renderableFlagsForModel.setHasAttributeTangent(
true);
1675 }
else if (sem == QSSGRhiInputAssemblerState::BinormalSemantic) {
1676 renderableFlagsForModel.setHasAttributeBinormal(
true);
1677 }
else if (sem == QSSGRhiInputAssemblerState::ColorSemantic) {
1678 renderableFlagsForModel.setHasAttributeColor(
true);
1681 }
else if (sem == QSSGRhiInputAssemblerState::JointSemantic) {
1683 }
else if (sem == QSSGRhiInputAssemblerState::WeightSemantic) {
1687 renderableFlagsForModel.setHasAttributeJointAndWeight(hasJoint && hasWeight);
1688 renderableFlagsForModel.setHasAttributeMorphTarget(hasMorphTarget);
1691 QSSGRenderableObjectList bakedLightingObjects;
1692 bool usesBlendParticles = particlesEnabled && theModelContext.model.particleBuffer !=
nullptr
1693 && model.particleBuffer->particleCount();
1694 const bool anyLightHasShadows = std::find_if(lights.begin(),
1696 [](
const QSSGShaderLight &light) {
return light.shadows; })
1698 const bool hasAnyLights = !lights.isEmpty();
1699 QSSGRenderLight::SoftShadowQuality maxSoftShadowQuality = QSSGRenderLight::SoftShadowQuality::Hard;
1700 if (anyLightHasShadows) {
1702 for (
const QSSGShaderLight &light : lights) {
1703 if (light.shadows && light.light->m_softShadowQuality > maxSoftShadowQuality)
1704 maxSoftShadowQuality = light.light->m_softShadowQuality;
1710 auto &renderableSubsets = theModelContext.subsets;
1711 const bool hasMaterialOverrides = ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::Materials) != 0);
1712 const auto &materials = hasMaterialOverrides ? renderable.extOverrides.materials : modelData->getMaterials(model);
1713 const auto materialCount = materials.size();
1714 QSSGRenderGraphObject *lastMaterial = !materials.isEmpty() ? materials.last() :
nullptr;
1715 int idx = 0, subsetIdx = 0;
1716 for (; idx < meshSubsetCount; ++idx) {
1718 QSSGRenderGraphObject *theMaterialObject = (idx >= materialCount) ? lastMaterial : materials[idx];
1719 if (!theMaterialObject)
1722 const QSSGRenderSubset &theSubset = meshSubsets.at(idx);
1723 QSSGRenderableObjectFlags renderableFlags = renderableFlagsForModel;
1724 float subsetOpacity = modelGlobalOpacity;
1726 renderableFlags.setPointsTopology(theSubset.rhi.ia.topology == QRhiGraphicsPipeline::Points);
1727 QSSGRenderableObject *theRenderableObject = &renderableSubsets[subsetIdx++];
1729 const bool usesInstancing = theModelContext.model.instancing()
1730 && rhiCtx->rhi()->isFeatureSupported(QRhi::Instancing);
1731 if (usesInstancing && theModelContext.model.instanceTable->hasTransparency())
1732 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1733 if (theModelContext.model.hasTransparency)
1734 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1737 quint32 subsetLevelOfDetail = 0;
1738 if (!theSubset.lods.isEmpty() && lodThreshold > 0.0f) {
1740 float lodDistanceMultiplier = camerasView[0]->getLevelOfDetailMultiplier();
1741 float distanceThreshold = 0.0f;
1742 const auto scale = QSSGUtils::mat44::getScale(globalTransform);
1743 float modelScale = qMax(scale.x(), qMax(scale.y(), scale.z()));
1744 QSSGBounds3 transformedBounds = theSubset.bounds;
1745 if (camerasView[0]->type != QSSGRenderGraphObject::Type::OrthographicCamera) {
1746 transformedBounds.transform(globalTransform);
1747 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1748 debugDrawSystem->drawBounds(transformedBounds, QColor(Qt::red));
1749 const QMatrix4x4 cameraGlobalTranform = getGlobalTransform(*camerasView[0]);
1750 const QVector3D cameraNormal = QSSGRenderNode::getScalingCorrectDirection(cameraGlobalTranform);
1751 const QVector3D cameraPosition = QSSGRenderNode::getGlobalPos(cameraGlobalTranform);
1752 const QSSGPlane cameraPlane = QSSGPlane(cameraPosition, cameraNormal);
1753 const QVector3D lodSupportMin = transformedBounds.getSupport(-cameraNormal);
1754 const QVector3D lodSupportMax = transformedBounds.getSupport(cameraNormal);
1755 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1756 debugDrawSystem->drawPoint(lodSupportMin, QColor(
"orange"));
1758 const float distanceMin = cameraPlane.distance(lodSupportMin);
1759 const float distanceMax = cameraPlane.distance(lodSupportMax);
1761 if (distanceMin * distanceMax < 0.0)
1762 distanceThreshold = 0.0;
1763 else if (distanceMin >= 0.0)
1764 distanceThreshold = distanceMin;
1765 else if (distanceMax <= 0.0)
1766 distanceThreshold = -distanceMax;
1770 distanceThreshold = 1.0;
1773 int currentLod = -1;
1774 if (model.levelOfDetailBias > 0.0f) {
1778 int lodsCount = theSubset.lods.size();
1779 if (model.instanceTable && lodsCount) {
1780 currentLod = qRound((lodsCount - 1) * qBound(0.f, model.instancingLodFactor, 1.f));
1782 const float threshold = distanceThreshold * lodDistanceMultiplier;
1783 const float modelBias = 1 / model.levelOfDetailBias;
1784 for (qsizetype i = 0; i < lodsCount; ++i) {
1785 float subsetDistance = theSubset.lods[i].distance * modelScale * modelBias;
1786 float screenSize = subsetDistance / threshold;
1787 if (screenSize > lodThreshold)
1794 if (currentLod == -1)
1795 subsetLevelOfDetail = 0;
1797 subsetLevelOfDetail = currentLod + 1;
1798 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1799 debugDrawSystem->drawBounds(transformedBounds, QSSGDebugDrawSystem::levelOfDetailColor(subsetLevelOfDetail));
1802 QVector3D theModelCenter(theSubset.bounds.center());
1803 theModelCenter = QSSGUtils::mat44::transform(globalTransform, theModelCenter);
1804 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLodNormal)) {
1805 const QMatrix4x4 allCamera0GlobalTransform = getGlobalTransform(*allCameras[0]);
1806 debugDrawSystem->debugNormals(*bufferManager, theModelContext, theSubset, subsetLevelOfDetail, (theModelCenter - QSSGRenderNode::getGlobalPos(allCamera0GlobalTransform)).length() * 0.01);
1809 auto checkF32TypeIndex = [&rhiCtx](QRhiVertexInputAttribute::Format f) {
1810 if ((f == QRhiVertexInputAttribute::Format::Float4)
1811 || (f == QRhiVertexInputAttribute::Format::Float3)
1812 || (f == QRhiVertexInputAttribute::Format::Float2)
1813 || (f == QRhiVertexInputAttribute::Format::Float)) {
1816 if (!rhiCtx->rhi()->isFeatureSupported(QRhi::IntAttributes))
1817 qWarning() <<
"WARN: Model has non-integer type indices for skinning but current RHI backend doesn't support it!";
1821 if (theMaterialObject->type == QSSGRenderGraphObject::Type::DefaultMaterial ||
1822 theMaterialObject->type == QSSGRenderGraphObject::Type::PrincipledMaterial ||
1823 theMaterialObject->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial) {
1824 QSSGRenderDefaultMaterial &theMaterial(
static_cast<QSSGRenderDefaultMaterial &>(*theMaterialObject));
1825 QSSGDefaultMaterialPreparationResult theMaterialPrepResult(prepareDefaultMaterialForRender(theMaterial, renderableFlags, subsetOpacity, hasAnyLights, anyLightHasShadows, ioFlags));
1826 QSSGShaderDefaultMaterialKey &theGeneratedKey(theMaterialPrepResult.materialKey);
1827 subsetOpacity = theMaterialPrepResult.opacity;
1828 QSSGRenderableImage *firstImage(theMaterialPrepResult.firstImage);
1829 wasDirty |= theMaterialPrepResult.dirty;
1830 renderableFlags = theMaterialPrepResult.renderableFlags;
1831 if (renderableFlags.hasTransparency())
1832 ioFlags.setHasCustomBlendMode(theMaterial.blendMode != QSSGRenderDefaultMaterial::MaterialBlendMode::SourceOver);
1835 defaultMaterialShaderKeyProperties.m_blendParticles.setValue(theGeneratedKey, usesBlendParticles);
1837 if (defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.getValue(theGeneratedKey) ==
int(QSSGRenderLayer::OITMethod::LinkedList))
1838 defaultMaterialShaderKeyProperties.m_oitMSAA.setValue(theGeneratedKey, rhiCtx->mainPassSampleCount() > 1);
1841 const auto boneCount = model.skin ? model.skin->boneCount :
1842 model.skeleton ? model.skeleton->boneCount : 0;
1843 defaultMaterialShaderKeyProperties.m_boneCount.setValue(theGeneratedKey, boneCount);
1844 if (
auto idJoint = theSubset.rhi.ia.inputs.indexOf(QSSGRhiInputAssemblerState::JointSemantic); idJoint != -1) {
1845 const auto attr = theSubset.rhi.ia.inputLayout.attributeAt(idJoint);
1846 defaultMaterialShaderKeyProperties.m_usesFloatJointIndices.setValue(theGeneratedKey, checkF32TypeIndex(attr->format()));
1850 defaultMaterialShaderKeyProperties.m_shadowSoftness.setShadowSoftness(theGeneratedKey, maxSoftShadowQuality);
1853 defaultMaterialShaderKeyProperties.m_usesInstancing.setValue(theGeneratedKey, usesInstancing);
1855 defaultMaterialShaderKeyProperties.m_targetCount.setValue(theGeneratedKey,
1856 theSubset.rhi.ia.targetCount);
1857 defaultMaterialShaderKeyProperties.m_targetPositionOffset.setValue(theGeneratedKey,
1858 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::PositionSemantic]);
1859 defaultMaterialShaderKeyProperties.m_targetNormalOffset.setValue(theGeneratedKey,
1860 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::NormalSemantic]);
1861 defaultMaterialShaderKeyProperties.m_targetTangentOffset.setValue(theGeneratedKey,
1862 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TangentSemantic]);
1863 defaultMaterialShaderKeyProperties.m_targetBinormalOffset.setValue(theGeneratedKey,
1864 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::BinormalSemantic]);
1865 defaultMaterialShaderKeyProperties.m_targetTexCoord0Offset.setValue(theGeneratedKey,
1866 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord0Semantic]);
1867 defaultMaterialShaderKeyProperties.m_targetTexCoord1Offset.setValue(theGeneratedKey,
1868 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord1Semantic]);
1869 defaultMaterialShaderKeyProperties.m_targetColorOffset.setValue(theGeneratedKey,
1870 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::ColorSemantic]);
1872 new (theRenderableObject) QSSGSubsetRenderable(QSSGSubsetRenderable::Type::DefaultMaterialMeshSubset,
1879 subsetLevelOfDetail,
1884 anyLightHasShadows);
1885 wasDirty = wasDirty || renderableFlags.isDirty();
1886 }
else if (theMaterialObject->type == QSSGRenderGraphObject::Type::CustomMaterial) {
1887 QSSGRenderCustomMaterial &theMaterial(
static_cast<QSSGRenderCustomMaterial &>(*theMaterialObject));
1889 const auto &theMaterialSystem(contextInterface.customMaterialSystem());
1890 wasDirty |= theMaterialSystem->prepareForRender(theModelContext.model, theSubset, theMaterial);
1892 if (theMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Blending))
1893 ioFlags.setHasCustomBlendMode(!hasCustomBlendMode(theMaterial));
1895 QSSGDefaultMaterialPreparationResult theMaterialPrepResult(
1896 prepareCustomMaterialForRender(theMaterial, renderableFlags, subsetOpacity, wasDirty,
1897 hasAnyLights, anyLightHasShadows, ioFlags));
1898 QSSGShaderDefaultMaterialKey &theGeneratedKey(theMaterialPrepResult.materialKey);
1899 subsetOpacity = theMaterialPrepResult.opacity;
1900 QSSGRenderableImage *firstImage(theMaterialPrepResult.firstImage);
1901 renderableFlags = theMaterialPrepResult.renderableFlags;
1903 if (model.particleBuffer && model.particleBuffer->particleCount())
1904 defaultMaterialShaderKeyProperties.m_blendParticles.setValue(theGeneratedKey,
true);
1906 defaultMaterialShaderKeyProperties.m_blendParticles.setValue(theGeneratedKey,
false);
1908 if (defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.getValue(theGeneratedKey) ==
int(QSSGRenderLayer::OITMethod::LinkedList))
1909 defaultMaterialShaderKeyProperties.m_oitMSAA.setValue(theGeneratedKey, rhiCtx->mainPassSampleCount() > 1);
1912 defaultMaterialShaderKeyProperties.m_shadowSoftness.setShadowSoftness(theGeneratedKey, maxSoftShadowQuality);
1915 const auto boneCount = model.skin ? model.skin->boneCount :
1916 model.skeleton ? model.skeleton->boneCount : 0;
1917 defaultMaterialShaderKeyProperties.m_boneCount.setValue(theGeneratedKey, boneCount);
1918 if (
auto idJoint = theSubset.rhi.ia.inputs.indexOf(QSSGRhiInputAssemblerState::JointSemantic); idJoint != -1) {
1919 const auto attr = theSubset.rhi.ia.inputLayout.attributeAt(idJoint);
1920 defaultMaterialShaderKeyProperties.m_usesFloatJointIndices.setValue(theGeneratedKey, checkF32TypeIndex(attr->format()));
1924 bool usesInstancing = theModelContext.model.instancing()
1925 && rhiCtx->rhi()->isFeatureSupported(QRhi::Instancing);
1926 defaultMaterialShaderKeyProperties.m_usesInstancing.setValue(theGeneratedKey, usesInstancing);
1928 defaultMaterialShaderKeyProperties.m_targetCount.setValue(theGeneratedKey,
1929 theSubset.rhi.ia.targetCount);
1930 defaultMaterialShaderKeyProperties.m_targetPositionOffset.setValue(theGeneratedKey,
1931 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::PositionSemantic]);
1932 defaultMaterialShaderKeyProperties.m_targetNormalOffset.setValue(theGeneratedKey,
1933 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::NormalSemantic]);
1934 defaultMaterialShaderKeyProperties.m_targetTangentOffset.setValue(theGeneratedKey,
1935 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TangentSemantic]);
1936 defaultMaterialShaderKeyProperties.m_targetBinormalOffset.setValue(theGeneratedKey,
1937 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::BinormalSemantic]);
1938 defaultMaterialShaderKeyProperties.m_targetTexCoord0Offset.setValue(theGeneratedKey,
1939 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord0Semantic]);
1940 defaultMaterialShaderKeyProperties.m_targetTexCoord1Offset.setValue(theGeneratedKey,
1941 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord1Semantic]);
1942 defaultMaterialShaderKeyProperties.m_targetColorOffset.setValue(theGeneratedKey,
1943 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::ColorSemantic]);
1945 if (theMaterial.m_iblProbe)
1946 theMaterial.m_iblProbe->clearDirty();
1948 new (theRenderableObject) QSSGSubsetRenderable(QSSGSubsetRenderable::Type::CustomMaterialMeshSubset,
1955 subsetLevelOfDetail,
1960 anyLightHasShadows);
1962 if (theRenderableObject)
1963 theRenderableObject->camdistSq = getCameraDistanceSq(*theRenderableObject, allCameraData[0]);
1967 if (Q_UNLIKELY(idx != subsetIdx))
1968 renderableSubsets.mSize = subsetIdx;
1970 for (
auto &ro : renderableSubsets) {
1971 const auto depthMode = ro.depthWriteMode;
1972 hasDepthWriteObjects |= (depthMode == QSSGDepthDrawMode::Always || depthMode == QSSGDepthDrawMode::OpaqueOnly);
1973 enum ObjectType : quint8 { ScreenTexture, Transparent, Opaque };
1974 static constexpr DepthPrepassObject ppState[][2] = { {DepthPrepassObject::None, DepthPrepassObject::ScreenTexture},
1975 {DepthPrepassObject::None, DepthPrepassObject::Transparent},
1976 {DepthPrepassObject::None, DepthPrepassObject::Opaque} };
1978 if (ro.renderableFlags.requiresScreenTexture()) {
1979 depthPrepassObjectsState |= DepthPrepassObjectStateT(ppState[ObjectType::ScreenTexture][size_t(depthMode == QSSGDepthDrawMode::OpaquePrePass)]);
1980 screenTextureObjects.push_back({&ro, ro.camdistSq, model.tag});
1981 }
else if (ro.renderableFlags.hasTransparency()) {
1982 depthPrepassObjectsState |= DepthPrepassObjectStateT(ppState[ObjectType::Transparent][size_t(depthMode == QSSGDepthDrawMode::OpaquePrePass)]);
1983 transparentObjects.push_back({&ro, ro.camdistSq, model.tag});
1985 depthPrepassObjectsState |= DepthPrepassObjectStateT(ppState[ObjectType::Opaque][size_t(depthMode == QSSGDepthDrawMode::OpaquePrePass)]);
1986 opaqueObjects.push_back({&ro, ro.camdistSq, model.tag});
1989 if (ro.renderableFlags.usedInBakedLighting())
1990 bakedLightingObjects.push_back({&ro, ro.camdistSq, model.tag});
1993 if (!bakedLightingObjects.isEmpty())
1994 bakedLightingModels.push_back(QSSGBakedLightingModel(&model, bakedLightingObjects));
2000bool QSSGLayerRenderData::prepareParticlesForRender(
const RenderableNodeEntries &renderableParticles,
const QSSGRenderCameraData &cameraData, QSSGLayerRenderPreparationResultFlags &ioFlags)
2002 QSSG_ASSERT(particlesEnabled,
return false);
2004 QSSGRenderContextInterface &contextInterface = *renderer->contextInterface();
2009 auto &opaqueObjects = opaqueObjectStore[0];
2010 auto &transparentObjects = transparentObjectStore[0];
2011 auto &screenTextureObjects = screenTextureObjectStore[0];
2013 for (
auto &renderable : renderableParticles) {
2014 QSSGShaderParticleMaterialKeyProperties &properties = particleMaterialShaderKeyProperties;
2016 QSSGRenderParticles &particles = *
static_cast<QSSGRenderParticles *>(renderable.node);
2017 QSSGShaderParticleMaterialKey &theGeneratedKey(particles.materialKey);
2018 const auto &lights = renderable.lights;
2020 QSSGRenderableObjectFlags renderableFlags;
2021 renderableFlags.setCastsShadows(
false);
2022 renderableFlags.setReceivesShadows(
false);
2023 renderableFlags.setHasAttributePosition(
true);
2024 renderableFlags.setHasAttributeNormal(
true);
2025 renderableFlags.setHasAttributeTexCoord0(
true);
2026 renderableFlags.setHasAttributeColor(
true);
2027 renderableFlags.setHasTransparency(particles.m_hasTransparency);
2028 renderableFlags.setCastsReflections(particles.m_castsReflections);
2029 if (particles.m_hasTransparency && particles.m_blendMode != QSSGRenderParticles::BlendMode::SourceOver)
2030 ioFlags.setHasCustomBlendMode(
true);
2032 properties.m_isLineParticle.setValue(theGeneratedKey, particles.m_featureLevel >= QSSGRenderParticles::FeatureLevel::Line);
2033 const bool animated = particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineAnimated
2034 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::Animated
2035 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::AnimatedVLight
2036 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineAnimatedVLight;
2037 const bool mapped = particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineMapped
2038 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::Mapped
2039 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::MappedVLight
2040 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineMappedVLight;
2041 const bool lit = particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineVLight
2042 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::AnimatedVLight
2043 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::MappedVLight
2044 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineMappedVLight
2045 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineAnimatedVLight
2046 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::SimpleVLight;
2047 properties.m_isAnimated.setValue(theGeneratedKey, animated);
2048 properties.m_isMapped.setValue(theGeneratedKey, mapped);
2049 properties.m_hasLighting.setValue(theGeneratedKey, lit);
2050 properties.m_viewCount.setValue(theGeneratedKey, layer.viewCount);
2051 if (renderableFlags.hasTransparency() && orderIndependentTransparencyEnabled) {
2052 properties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(layer.oitMethod));
2053 if (layer.oitMethod == QSSGRenderLayer::OITMethod::LinkedList)
2054 properties.m_oitMSAA.setValue(theGeneratedKey, contextInterface.rhiContext()->mainPassSampleCount() > 1);
2056 properties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(0));
2059 float opacity = getGlobalOpacity(particles);
2060 const QMatrix4x4 globalTransform = getGlobalTransform(particles);
2061 QVector3D center(particles.m_particleBuffer.bounds().center());
2062 center = QSSGUtils::mat44::transform(globalTransform, center);
2064 QSSGRenderableImage *firstImage =
nullptr;
2065 if (particles.m_sprite) {
2066 const auto &bufferManager = contextInterface.bufferManager();
2068 if (particles.m_sprite->clearDirty())
2071 const QSSGRenderImageTexture texture = bufferManager->loadRenderImage(particles.m_sprite);
2072 QSSGRenderableImage *theImage = RENDER_FRAME_NEW<QSSGRenderableImage>(contextInterface, QSSGRenderableImage::Type::Diffuse, *particles.m_sprite, texture);
2073 firstImage = theImage;
2074 properties.m_isSpriteLinear.setValue(theGeneratedKey, texture.m_flags.isLinear());
2077 QSSGRenderableImage *colorTable =
nullptr;
2078 if (particles.m_colorTable) {
2079 const auto &bufferManager = contextInterface.bufferManager();
2081 if (particles.m_colorTable->clearDirty())
2084 const QSSGRenderImageTexture texture = bufferManager->loadRenderImage(particles.m_colorTable);
2086 QSSGRenderableImage *theImage = RENDER_FRAME_NEW<QSSGRenderableImage>(contextInterface, QSSGRenderableImage::Type::Diffuse, *particles.m_colorTable, texture);
2087 colorTable = theImage;
2088 properties.m_isColorTableLinear.setValue(theGeneratedKey, texture.m_flags.isLinear());
2091 if (opacity > 0.0f && particles.m_particleBuffer.particleCount()) {
2092 auto *theRenderableObject = RENDER_FRAME_NEW<QSSGParticlesRenderable>(contextInterface,
2103 if (theRenderableObject) {
2104 if (theRenderableObject->renderableFlags.requiresScreenTexture())
2105 screenTextureObjects.push_back({theRenderableObject, getCameraDistanceSq(*theRenderableObject, cameraData), particles.tag});
2106 else if (theRenderableObject->renderableFlags.hasTransparency())
2107 transparentObjects.push_back({theRenderableObject, getCameraDistanceSq(*theRenderableObject, cameraData), particles.tag});
2109 opaqueObjects.push_back({theRenderableObject, getCameraDistanceSq(*theRenderableObject, cameraData), particles.tag});
2396void QSSGLayerRenderData::prepareForRender()
2398 QSSG_ASSERT_X(layerPrepResult.isNull(),
"Prep-result was not reset for render!", layerPrepResult = {});
2400 QRect theViewport(renderer->viewport());
2404 frameData.m_ctx = renderer->contextInterface();
2409 ps.viewport = {
float(theViewport.x()),
float(theViewport.y()),
float(theViewport.width()),
float(theViewport.height()), 0.0f, 1.0f };
2410 if (layer.scissorRect.isValid()) {
2411 ps.flags |= QSSGRhiGraphicsPipelineState::Flag::UsesScissor;
2412 ps.scissor = { layer.scissorRect.x(),
2413 theViewport.height() - (layer.scissorRect.y() + layer.scissorRect.height()),
2414 layer.scissorRect.width(),
2415 layer.scissorRect.height() };
2418 ps.depthFunc = QRhiGraphicsPipeline::LessOrEqual;
2419 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
false);
2422 ps.polygonMode = layer.wireframeMode ? QRhiGraphicsPipeline::Line : QRhiGraphicsPipeline::Fill;
2424 bool wasDirty =
false;
2425 bool wasDataDirty =
false;
2426 wasDirty = layer.isDirty();
2428 const bool shouldDisableInternalPasses = (layer.renderOverrides & size_t(QSSGRenderLayer::RenderOverrides::DisableInternalPasses)) != 0;
2429 wasDirty |= (shouldDisableInternalPasses != disableMainPasses);
2430 disableMainPasses = shouldDisableInternalPasses;
2433 layerPrepResult = { theViewport, layer };
2436 const bool SSAOEnabled = layer.ssaoEnabled();
2437 layerPrepResult.flags.setRequiresSsaoPass(SSAOEnabled);
2438 features.set(QSSGShaderFeatures::Feature::Ssao, SSAOEnabled);
2441 bool requiresDepthTexture = SSAOEnabled;
2442 bool requiresNormalTexture =
false;
2443 bool requiresMotionVectorTexture =
false;
2444 for (QSSGRenderEffect *theEffect = layer.firstEffect; theEffect; theEffect = theEffect->m_nextEffect) {
2445 if (theEffect->isDirty()) {
2447 theEffect->clearDirty();
2449 if (theEffect->testFlag(QSSGRenderEffect::Flags::UsesDepthTexture))
2450 requiresDepthTexture =
true;
2451 if (theEffect->testFlag(QSSGRenderEffect::Flags::UsesNormalTexture))
2452 requiresNormalTexture =
true;
2453 if (theEffect->testFlag(QSSGRenderEffect::Flags::UsesMotionVectorTexture))
2454 requiresMotionVectorTexture =
true;
2457 const auto &rhiCtx = renderer->contextInterface()->rhiContext();
2458 orderIndependentTransparencyEnabled = (layer.oitMethod != QSSGRenderLayer::OITMethod::None);
2459 if (layer.oitMethod == QSSGRenderLayer::OITMethod::WeightedBlended) {
2460 orderIndependentTransparencyEnabled = rhiCtx->rhi()->isFeatureSupported(QRhi::PerRenderTargetBlending);
2461 if (rhiCtx->mainPassSampleCount() > 1)
2462 orderIndependentTransparencyEnabled &= rhiCtx->rhi()->isFeatureSupported(QRhi::TexelFetch) && rhiCtx->rhi()->isFeatureSupported(QRhi::SampleVariables);
2463 if (!orderIndependentTransparencyEnabled && !oitWarningUnsupportedShown) {
2464 qCWarning(lcQuick3DRender) <<
"WeightedBlended OIT is requested, but it is not supported.";
2465 oitWarningUnsupportedShown =
true;
2467 }
else if (layer.oitMethod == QSSGRenderLayer::OITMethod::LinkedList) {
2468 orderIndependentTransparencyEnabled = rhiCtx->rhi()->isTextureFormatSupported(QRhiTexture::RGBA32UI, QRhiTexture::UsedWithLoadStore);
2469 if (rhiCtx->mainPassSampleCount() > 1)
2470 orderIndependentTransparencyEnabled &= rhiCtx->rhi()->isFeatureSupported(QRhi::SampleVariables);
2471 if (!orderIndependentTransparencyEnabled && !oitWarningUnsupportedShown) {
2472 qCWarning(lcQuick3DRender) <<
"LinkedList OIT is requested, but it is not supported.";
2473 oitWarningUnsupportedShown =
true;
2476 if (layer.oitMethodDirty) {
2477 oitRenderContext.reset();
2478 for (
auto &renderResult : renderResults)
2479 renderResult.reset();
2482 layerPrepResult.flags.setRequiresDepthTexture(requiresDepthTexture);
2484 layerPrepResult.flags.setRequiresNormalTexture(requiresNormalTexture);
2486 layerPrepResult.flags.setRequiresMotionVectorPass(requiresMotionVectorTexture);
2490 if (!layer.firstEffect)
2491 QSSGLayerRenderData::setTonemapFeatures(features, layer.tonemapMode);
2498 if (rhiCtx->rhi()->resourceLimit(QRhi::MaxUniformBufferRange) < REDUCED_MAX_LIGHT_COUNT_THRESHOLD_BYTES) {
2499 features.set(QSSGShaderFeatures::Feature::ReduceMaxNumLights,
true);
2500 static bool notified =
false;
2503 qCDebug(lcQuick3DRender,
"Qt Quick 3D maximum number of lights has been reduced from %d to %d due to the graphics driver's limitations",
2504 QSSG_MAX_NUM_LIGHTS, QSSG_REDUCED_MAX_NUM_LIGHTS);
2509 const auto &lightProbeSettings = layer.lightProbeSettings;
2510 if (layer.lightProbe) {
2511 if (layer.lightProbe->m_format == QSSGRenderTextureFormat::Unknown) {
2514 if (renderer->contextInterface()->rhiContext()->rhi()->isTextureFormatSupported(QRhiTexture::RGBA16F))
2515 layer.lightProbe->m_format = QSSGRenderTextureFormat::RGBA16F;
2517 layer.lightProbe->m_format = QSSGRenderTextureFormat::RGBE8;
2520 if (layer.lightProbe->clearDirty())
2521 wasDataDirty =
true;
2523 features.set(QSSGShaderFeatures::Feature::LightProbe,
true);
2524 features.set(QSSGShaderFeatures::Feature::IblOrientation, !lightProbeSettings.probeOrientation.isIdentity());
2525 if (layer.lightProbe->m_format.format == QSSGRenderTextureFormat::Format::RGBE8)
2526 features.set(QSSGShaderFeatures::Feature::RGBELightProbe,
true);
2528 }
else if (layer.skyMaterial) {
2529 if (layer.skyMaterial->enableIBL) {
2530 features.set(QSSGShaderFeatures::Feature::LightProbe,
true);
2531 features.set(QSSGShaderFeatures::Feature::IblOrientation, !lightProbeSettings.probeOrientation.isIdentity());
2533 layerPrepResult.flags.setRequiresSkyMaterialPass(
true);
2536 const bool forceIblExposureValues = (features.isSet(QSSGShaderFeatures::Feature::LightProbe)
2537 && layer.tonemapMode == QSSGRenderLayer::TonemapMode::Custom);
2538 features.set(QSSGShaderFeatures::Feature::ForceIblExposure, forceIblExposureValues);
2540 frameData.m_ctx->bufferManager()->setLightmapSource(layer.lightmapSource);
2544 version = nodeData->version();
2549 auto &globalTransforms = nodeData->globalTransforms;
2550 auto &globalOpacities = nodeData->globalOpacities;
2551 auto &instanceTransforms = nodeData->instanceTransforms;
2554 QSSGRenderDataHelpers::GlobalStateResultT globalStateResult = QSSGRenderDataHelpers::GlobalStateResult::None;
2556 const bool layerTreeWasDirty = layer.isDirty(QSSGRenderLayer::DirtyFlag::TreeDirty);
2557 layer.clearDirty(QSSGRenderLayer::DirtyFlag::TreeDirty);
2558 if (layerTreeWasDirty) {
2559 wasDataDirty =
true;
2560 layerNodes = nodeData->getLayerNodeView(layer);
2562 for (
auto &node : layerNodes)
2563 globalStateResult |= QSSGRenderDataHelpers::updateGlobalNodeState(node, version);
2565 bool transformAndOpacityDirty =
false;
2566 for (
auto &node : layerNodes)
2567 transformAndOpacityDirty |= QSSGRenderDataHelpers::calcGlobalNodeData<QSSGRenderDataHelpers::Strategy::Update>(node, version, globalTransforms, globalOpacities);
2570 if (transformAndOpacityDirty) {
2571 for (
const auto &node : layerNodes)
2572 wasDataDirty |= QSSGRenderDataHelpers::calcInstanceTransforms(node, version, globalTransforms, instanceTransforms);
2575 wasDataDirty |= transformAndOpacityDirty;
2582 const bool viewportVisibilityDirty = layer.isDirty(QSSGRenderLayer::DirtyFlag::VisibilityDirty);
2583 layer.clearDirty(QSSGRenderLayer::DirtyFlag::VisibilityDirty);
2584 if (viewportVisibilityDirty)
2585 wasDataDirty =
true;
2590 const bool hasExplicitCamera = (layer.explicitCameras.size() != 0);
2591 bool cameraLayerMaskDirty =
false;
2592 quint32 layerMask = QSSGRenderCamera::LayerMaskAll;
2593 if (hasExplicitCamera) {
2594 QSSGRenderCamera *explicitCamera = layer.explicitCameras[0];
2597 layerMask = explicitCamera->tag.value() | QSSGRenderCamera::ReservedLayerMask;
2598 cameraLayerMaskDirty = explicitCamera->isDirty(QSSGRenderCamera::DirtyFlag::LayerMaskDirty);
2599 explicitCamera->clearDirty(QSSGRenderCamera::DirtyFlag::LayerMaskDirty);
2602 const bool restatNodes = (layerTreeWasDirty || (globalStateResult & QSSGRenderDataHelpers::GlobalStateResult::ActiveChanged) || cameraLayerMaskDirty);
2605 updateFilteredLayerNodes(layerMask);
2611 QSSGRenderCamera::Configuration cameraConfig { renderer->dpr(), layer.isSsaaEnabled() ? layer.ssaaMultiplier : 1.0f };
2612 renderedCameras.clear();
2613 if (!layer.explicitCameras.isEmpty()) {
2614 for (QSSGRenderCamera *cam : std::as_const(layer.explicitCameras)) {
2616 if (cam->getGlobalState(QSSGRenderCamera::GlobalState::Active)) {
2617 const bool computeFrustumSucceeded = cam->calculateProjection(theViewport, cameraConfig);
2618 if (Q_LIKELY(computeFrustumSucceeded))
2619 renderedCameras.append(cam);
2621 qCCritical(INTERNAL_ERROR,
"Failed to calculate camera frustum");
2625 }
else if (QSSG_GUARD_X(layer.viewCount == 1,
"Multiview rendering requires explicit cameras to be set!.")) {
2630 for (
auto iter = camerasView.begin(); renderedCameras.isEmpty() && iter != camerasView.end(); iter++) {
2631 QSSGRenderCamera *theCamera = *iter;
2632 if (theCamera->getGlobalState(QSSGRenderCamera::GlobalState::Active)) {
2633 const bool computeFrustumSucceeded = theCamera->calculateProjection(theViewport, cameraConfig);
2634 if (Q_LIKELY(computeFrustumSucceeded))
2635 renderedCameras.append(theCamera);
2637 qCCritical(INTERNAL_ERROR,
"Failed to calculate camera frustum");
2645 if (renderedCameras.size() > 0 && (renderedCameras[0]->layerMask & QSSGRenderCamera::LayerMaskUserAll) != QSSGRenderCamera::LayerMaskUserAll) {
2646 if (!nonExplicitCameraWithLayerMaskWarningShown) {
2647 nonExplicitCameraWithLayerMaskWarningShown =
true;
2648 qWarning() <<
"Scenes with non-explicit cameras with a layer detected!"
2649 " Set the camera explicitly to avoid unnecessary evaluation of scene nodes!";
2653 layerMask = renderedCameras[0]->layerMask;
2654 updateFilteredLayerNodes(layerMask);
2658 float meshLodThreshold = 1.0f;
2659 if (!renderedCameras.isEmpty())
2660 meshLodThreshold = renderedCameras[0]->levelOfDetailPixelThreshold / theViewport.width();
2662 layer.renderedCamerasMutex.lock();
2663 layer.renderedCameras = renderedCameras;
2664 layer.renderedCamerasMutex.unlock();
2667 const QSSGRenderCameraDataList &renderCameraData = getCachedCameraDatas();
2668 modelData->updateModelData(modelsView, renderer, renderCameraData);
2671 item2DData->updateItem2DData(item2DsView, renderer, renderCameraData);
2674 prepareResourceLoaders();
2677 updateDirtySkeletons(*
this, modelsView);
2680 int directionalLightsCount = 0;
2681 int positionalLightsCount = 0;
2682 const int maxLightCount = effectiveMaxLightCount(features);
2683 const int maxDirectionalLights = effectiveMaxDirectionalLightCount(features);
2684 QSSGShaderLightList renderableLights;
2685 int shadowMapCount = 0;
2686 bool hasScopedLights =
false;
2692 auto it = std::make_reverse_iterator(lightsView.end());
2693 const auto end = it + qMin(maxLightCount, lightsView.size());
2694 for (; it != end; ++it) {
2695 QSSGRenderLight *renderLight = (*it);
2696 QMatrix4x4 renderLightTransform = getGlobalTransform(*renderLight);
2697 if (renderLight->type == QSSGRenderGraphObject::Type::DirectionalLight)
2698 directionalLightsCount++;
2700 positionalLightsCount++;
2702 if (positionalLightsCount > maxLightCount)
2704 if (directionalLightsCount > maxDirectionalLights)
2708 hasScopedLights |= (renderLight->m_scope !=
nullptr);
2709 const bool castShadows = renderLight->m_castShadow && !renderLight->m_fullyBaked;
2710 shadowMapCount +=
int(castShadows);
2711 const auto &direction = renderLight->getScalingCorrectDirection(renderLightTransform);
2712 renderableLights.push_back(QSSGShaderLight{ renderLight, castShadows, direction });
2716 const bool showLightCountWarning = !tooManyLightsWarningShown && (positionalLightsCount > maxLightCount);
2717 if (showLightCountWarning) {
2718 qWarning(
"Too many lights in scene, maximum is %d", maxLightCount);
2719 tooManyLightsWarningShown =
true;
2722 const bool showDirectionalLightCountWarning = !tooManyDirectionalLightsWarningShown && (directionalLightsCount > maxDirectionalLights);
2723 if (showDirectionalLightCountWarning) {
2724 qWarning(
"Too many directional lights in scene, maximum is %d", maxDirectionalLights);
2725 tooManyDirectionalLightsWarningShown =
true;
2728 if (shadowMapCount > 0) {
2729 requestShadowMapManager();
2730 layerPrepResult.flags.setRequiresShadowMapPass(
true);
2735 features.set(QSSGShaderFeatures::Feature::Ssm,
true);
2736 shadowMapManager->addShadowMaps(renderableLights);
2737 }
else if (shadowMapManager) {
2739 shadowMapManager->releaseCachedResources();
2745 QSSG_ASSERT(globalLights.isEmpty(), globalLights.clear());
2746 if (hasScopedLights) {
2747 for (
const auto &shaderLight : std::as_const(renderableLights)) {
2748 if (!shaderLight.light->m_scope)
2749 globalLights.push_back(shaderLight);
2752 const auto prepareLightsWithScopedLights = [&renderableLights,
this](QVector<QSSGRenderableNodeEntry> &renderableNodes) {
2753 for (qint32 idx = 0, end = renderableNodes.size(); idx < end; ++idx) {
2754 QSSGRenderableNodeEntry &theNodeEntry(renderableNodes[idx]);
2755 QSSGShaderLightList filteredLights;
2756 for (
const auto &light : std::as_const(renderableLights)) {
2757 if (light.light->m_scope && !scopeLight(theNodeEntry.node, light.light->m_scope))
2759 filteredLights.push_back(light);
2762 if (filteredLights.isEmpty()) {
2763 theNodeEntry.lights = QSSGDataView(globalLights);
2768 auto customLightList = RENDER_FRAME_NEW_BUFFER<QSSGShaderLight>(*renderer->contextInterface(), filteredLights.size());
2769 std::copy(filteredLights.cbegin(), filteredLights.cend(), customLightList.begin());
2770 theNodeEntry.lights = customLightList;
2775 prepareLightsWithScopedLights(renderableModels);
2776 prepareLightsWithScopedLights(renderableParticles);
2778 globalLights = renderableLights;
2780 const auto prepareLights = [
this](QVector<QSSGRenderableNodeEntry> &renderableNodes) {
2781 for (qint32 idx = 0, end = renderableNodes.size(); idx < end; ++idx) {
2782 QSSGRenderableNodeEntry &theNodeEntry(renderableNodes[idx]);
2783 theNodeEntry.lights = QSSGDataView(globalLights);
2787 prepareLights(renderableModels);
2788 prepareLights(renderableParticles);
2794 Q_STATIC_ASSERT(USERPASSES == size_t(QSSGRenderLayer::RenderExtensionStage::Count));
2795 for (size_t i = 0; i != size_t(QSSGRenderLayer::RenderExtensionStage::Count); ++i) {
2796 const auto &renderExtensions = layer.renderExtensions[i];
2797 auto &userPass = userPasses[i];
2798 for (
auto rit = renderExtensions.crbegin(), rend = renderExtensions.crend(); rit != rend; ++rit) {
2799 if ((*rit)->prepareData(frameData)) {
2801 userPass.extensions.push_back(*rit);
2809 const auto &userRenderPassManager = requestUserRenderPassManager();
2810 userRenderPassManager->updateUserPassOrder(layerTreeWasDirty);
2811 userRenderPasses.userPasses = userRenderPassManager->scheduledUserPasses();
2814 auto &opaqueObjects = opaqueObjectStore[0];
2815 auto &transparentObjects = transparentObjectStore[0];
2816 auto &screenTextureObjects = screenTextureObjectStore[0];
2818 if (!renderedCameras.isEmpty()) {
2819 wasDirty |= prepareModelsForRender(*renderer->contextInterface(), renderableModels, layerPrepResult.flags, renderedCameras, getCachedCameraDatas(), modelContexts, opaqueObjects, transparentObjects, screenTextureObjects, meshLodThreshold);
2820 if (particlesEnabled) {
2821 const auto &cameraDatas = getCachedCameraDatas();
2822 wasDirty |= prepareParticlesForRender(renderableParticles, cameraDatas[0], layerPrepResult.flags);
2825 wasDirty |= (item2DsView.size() != 0);
2827 if (orderIndependentTransparencyEnabled) {
2829 if (transparentObjects.size() > 0 && !layerPrepResult.flags.hasCustomBlendMode()) {
2830 if (layer.oitMethod == QSSGRenderLayer::OITMethod::WeightedBlended) {
2831 if (rhiCtx->mainPassSampleCount() > 1)
2832 layerPrepResult.flags.setRequiresDepthTextureMS(
true);
2834 layerPrepResult.flags.setRequiresDepthTexture(
true);
2837 orderIndependentTransparencyEnabled =
false;
2838 if (!oitWarningInvalidBlendModeShown) {
2839 qCWarning(lcQuick3DRender) <<
"Order Independent Transparency requested, but disabled due to invalid blend modes.";
2840 qCWarning(lcQuick3DRender) <<
"Use SourceOver blend mode for Order Independent Transparency.";
2841 oitWarningInvalidBlendModeShown =
true;
2845 layer.oitMethodDirty =
false;
2847 prepareReflectionProbesForRender();
2849 wasDirty = wasDirty || wasDataDirty;
2850 layerPrepResult.flags.setWasDirty(wasDirty);
2851 layerPrepResult.flags.setLayerDataDirty(wasDataDirty);
2854 const bool animating = wasDirty;
2856 layer.progAAPassIndex = 0;
2858 const bool progressiveAA = layer.isProgressiveAAEnabled() && !animating;
2859 layer.progressiveAAIsActive = progressiveAA;
2860 const bool temporalAA = layer.isTemporalAAEnabled() && !progressiveAA;
2862 layer.temporalAAIsActive = temporalAA;
2864 QVector2D vertexOffsetsAA;
2866 if (progressiveAA && layer.progAAPassIndex > 0 && layer.progAAPassIndex < quint32(layer.antialiasingQuality)) {
2867 int idx = layer.progAAPassIndex - 1;
2868 vertexOffsetsAA = s_ProgressiveAAVertexOffsets[idx] / QVector2D{
float(theViewport.width()/2.0),
float(theViewport.height()/2.0) };
2872 if (layer.temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector && layer.tempAAPassIndex > 0) {
2873 if (layer.tempAAPassIndex >= quint32(MAX_AA_LEVELS) + 1)
2874 layer.tempAAPassIndex = 1;
2875 int idx = layer.tempAAPassIndex - 1;
2876 vertexOffsetsAA = s_ProgressiveAAVertexOffsets[idx] / QVector2D{
float(theViewport.width()/2.0),
float(theViewport.height()/2.0) };
2877 layer.currentAndLastJitter = QVector4D(vertexOffsetsAA, layer.currentAndLastJitter.x(), layer.currentAndLastJitter.y());
2878 layerPrepResult.flags.setRequiresMotionVectorPass(
true);
2879 layerPrepResult.flags.setRequiresDepthTexture(
true);
2881 const int t = 1 - 2 * (layer.tempAAPassIndex % 2);
2882 const float f = t * layer.temporalAAStrength;
2883 vertexOffsetsAA = { f /
float(theViewport.width()/2.0), f /
float(theViewport.height()/2.0) };
2887 if (!renderedCameras.isEmpty()) {
2888 if (temporalAA || progressiveAA ) {
2889 QMatrix4x4 offsetProjection = renderedCameras[0]->projection;
2890 QMatrix4x4 invProjection = renderedCameras[0]->projection.inverted();
2891 if (renderedCameras[0]->type == QSSGRenderCamera::Type::OrthographicCamera) {
2892 offsetProjection(0, 3) -= vertexOffsetsAA.x();
2893 offsetProjection(1, 3) -= vertexOffsetsAA.y();
2894 }
else if (renderedCameras[0]->type == QSSGRenderCamera::Type::PerspectiveCamera) {
2895 offsetProjection(0, 2) += vertexOffsetsAA.x();
2896 offsetProjection(1, 2) += vertexOffsetsAA.y();
2898 for (
auto &modelContext : std::as_const(modelContexts)) {
2899 for (
int mvpIdx = 0; mvpIdx < renderedCameras.count(); ++mvpIdx)
2900 modelContext->modelViewProjections[mvpIdx] = offsetProjection * invProjection * modelContext->modelViewProjections[mvpIdx];
2905 const bool hasItem2Ds = (item2DsView.size() > 0);
2906 const bool layerEnableDepthTest = layer.layerFlags.testFlag(QSSGRenderLayer::LayerFlag::EnableDepthTest);
2907 const bool layerEnabledDepthPrePass = layer.layerFlags.testFlag(QSSGRenderLayer::LayerFlag::EnableDepthPrePass);
2908 const bool depthTestEnableDefault = layerEnableDepthTest && (!opaqueObjects.isEmpty() || depthPrepassObjectsState || hasDepthWriteObjects);
2909 const bool zPrePassForced = (depthPrepassObjectsState != 0);
2910 zPrePassActive = zPrePassForced || (layerEnabledDepthPrePass && layerEnableDepthTest && (hasDepthWriteObjects || hasItem2Ds));
2911 const bool depthWriteEnableDefault = depthTestEnableDefault && (!layerEnabledDepthPrePass || !zPrePassActive);
2913 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, depthTestEnableDefault);
2914 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled, depthWriteEnableDefault);
2918 layerPrepResult.setState(QSSGLayerRenderPreparationResult::State::Done);
2921 QSSG_ASSERT(activePasses.isEmpty(), activePasses.clear());
2925 if (layerPrepResult.flags.requiresDepthTexture())
2926 activePasses.push_back(&depthMapPass);
2927 if (layerPrepResult.flags.requiresDepthTextureMS())
2928 activePasses.push_back(&depthMapPassMS);
2930 if (layerPrepResult.flags.requiresNormalTexture())
2931 activePasses.push_back(&normalPass);
2934 if (layerPrepResult.flags.requiresSsaoPass())
2935 activePasses.push_back(&ssaoMapPass);
2938 if (layerPrepResult.flags.requiresShadowMapPass())
2939 activePasses.push_back(&shadowMapPass);
2941 if (zPrePassActive && !disableMainPasses)
2942 activePasses.push_back(&zPrePassPass);
2945 if (layerPrepResult.flags.requiresScreenTexture())
2946 activePasses.push_back(&screenMapPass);
2949 if (layerPrepResult.flags.requiresSkyMaterialPass())
2950 activePasses.push_back(&skyMaterialPass);
2953 if (reflectionProbesView.size() != 0)
2954 activePasses.push_back(&reflectionMapPass);
2956 auto &textureExtensionPass = userPasses[size_t(QSSGRenderLayer::RenderExtensionStage::TextureProviders)];
2957 if (textureExtensionPass.hasData())
2958 activePasses.push_back(&textureExtensionPass);
2960 auto &underlayPass = userPasses[size_t(QSSGRenderLayer::RenderExtensionStage::Underlay)];
2961 if (underlayPass.hasData())
2962 activePasses.push_back(&underlayPass);
2966 if (layerPrepResult.flags.requiresSkyMaterialPass())
2967 activePasses.push_back(&skyMaterialPass);
2970 if (userRenderPasses.hasData())
2971 activePasses.push_back(&userRenderPasses);
2973 const bool hasOpaqueObjects = (opaqueObjects.size() > 0);
2975 if (hasOpaqueObjects && !disableMainPasses)
2976 activePasses.push_back(&opaquePass);
2979 if (layerPrepResult.flags.requiresMotionVectorPass())
2980 activePasses.push_back(&motionVectorMapPass);
2984 if (renderer->contextInterface()->rhiContext()->rhi()->isFeatureSupported(QRhi::TexelFetch)) {
2985 if (layer.background == QSSGRenderLayer::Background::SkyBoxCubeMap && layer.skyBoxCubeMap && !disableMainPasses)
2986 activePasses.push_back(&skyboxCubeMapPass);
2987 else if (layer.background == QSSGRenderLayer::Background::SkyBox && layer.lightProbe && !disableMainPasses)
2988 activePasses.push_back(&skyboxPass);
2989 else if (layer.background == QSSGRenderLayer::Background::SkyMaterial && layer.skyMaterial && !disableMainPasses) {
2990 if (layer.skyMaterial->skyboxMode != QSSGRenderSkyMaterial::SkyboxMode::Cubemap)
2991 activePasses.push_back(&skyMaterialBackgroundPass);
2993 activePasses.push_back(&skyboxPass);
2997 if (hasItem2Ds && !disableMainPasses)
2998 activePasses.push_back(&item2DPass);
3000 if (layerPrepResult.flags.requiresScreenTexture())
3001 activePasses.push_back(&reflectionPass);
3004 if ((transparentObjects.size() > 0 || (!layerEnableDepthTest && hasOpaqueObjects)) && !disableMainPasses) {
3005 if (orderIndependentTransparencyEnabled) {
3006 activePasses.push_back(&oitRenderPass);
3007 activePasses.push_back(&oitCompositePass);
3008 oitRenderPass.setMethod(layer.oitMethod);
3009 oitCompositePass.setMethod(layer.oitMethod);
3011 activePasses.push_back(&transparentPass);
3015 auto &overlayPass = userPasses[size_t(QSSGRenderLayer::RenderExtensionStage::Overlay)];
3016 if (overlayPass.hasData())
3017 activePasses.push_back(&overlayPass);
3019 if (layer.gridEnabled)
3020 activePasses.push_back(&infiniteGridPass);
3022 if (
const auto &dbgDrawSystem = renderer->contextInterface()->debugDrawSystem(); dbgDrawSystem && dbgDrawSystem->isEnabled() && !disableMainPasses)
3023 activePasses.push_back(&debugDrawPass);