898void QSSGLayerRenderData::prepareImageForRender(QSSGRenderImage &inImage,
899 QSSGRenderableImage::Type inMapType,
900 QSSGRenderableImage *&ioFirstImage,
901 QSSGRenderableImage *&ioNextImage,
902 QSSGRenderableObjectFlags &ioFlags,
903 QSSGShaderDefaultMaterialKey &inShaderKey,
904 quint32 inImageIndex,
905 QSSGRenderDefaultMaterial *inMaterial)
907 QSSGRenderContextInterface &contextInterface = *renderer->contextInterface();
908 const auto &bufferManager = contextInterface.bufferManager();
910 if (inImage.clearDirty())
911 ioFlags |= QSSGRenderableObjectFlag::Dirty;
922 const QSSGRenderImageTexture texture = bufferManager->loadRenderImage(&inImage);
924 if (texture.m_texture) {
925 if (texture.m_flags.hasTransparency()
926 && (inMapType == QSSGRenderableImage::Type::Diffuse
927 || inMapType == QSSGRenderableImage::Type::Opacity
928 || inMapType == QSSGRenderableImage::Type::Translucency))
930 ioFlags |= QSSGRenderableObjectFlag::HasTransparency;
933 QSSGRenderableImage *theImage = RENDER_FRAME_NEW<QSSGRenderableImage>(contextInterface, inMapType, inImage, texture);
934 QSSGShaderKeyImageMap &theKeyProp = defaultMaterialShaderKeyProperties.m_imageMaps[inImageIndex];
936 theKeyProp.setEnabled(inShaderKey,
true);
937 switch (inImage.m_mappingMode) {
938 case QSSGRenderImage::MappingModes::Normal:
940 case QSSGRenderImage::MappingModes::Environment:
941 theKeyProp.setEnvMap(inShaderKey,
true);
943 case QSSGRenderImage::MappingModes::LightProbe:
944 theKeyProp.setLightProbe(inShaderKey,
true);
954 switch (texture.m_texture->format()) {
955 case QRhiTexture::Format::RED_OR_ALPHA8:
956 hasA = !renderer->contextInterface()->rhiContext()->rhi()->isFeatureSupported(QRhi::RedOrAlpha8IsRed);
958 case QRhiTexture::Format::R8:
968 if (inImage.isImageTransformIdentity())
969 theKeyProp.setIdentityTransform(inShaderKey,
true);
971 if (inImage.m_indexUV == 1)
972 theKeyProp.setUsesUV1(inShaderKey,
true);
974 if (texture.m_flags.isLinear())
975 theKeyProp.setLinear(inShaderKey,
true);
977 if (texture.m_flags.isPreMultipliedAlpha())
978 theKeyProp.setPreMultipliedAlpha(inShaderKey,
true);
980 if (ioFirstImage ==
nullptr)
981 ioFirstImage = theImage;
983 ioNextImage->m_nextImage = theImage;
985 ioNextImage = theImage;
987 if (inMaterial && inImageIndex >= QSSGShaderDefaultMaterialKeyProperties::SingleChannelImagesFirst) {
988 QSSGRenderDefaultMaterial::TextureChannelMapping value = QSSGRenderDefaultMaterial::R;
990 const quint32 scIndex = inImageIndex - QSSGShaderDefaultMaterialKeyProperties::SingleChannelImagesFirst;
991 QSSGShaderKeyTextureChannel &channelKey = defaultMaterialShaderKeyProperties.m_textureChannels[scIndex];
992 switch (inImageIndex) {
993 case QSSGShaderDefaultMaterialKeyProperties::OpacityMap:
994 value = inMaterial->opacityChannel;
996 case QSSGShaderDefaultMaterialKeyProperties::RoughnessMap:
997 value = inMaterial->roughnessChannel;
999 case QSSGShaderDefaultMaterialKeyProperties::MetalnessMap:
1000 value = inMaterial->metalnessChannel;
1002 case QSSGShaderDefaultMaterialKeyProperties::OcclusionMap:
1003 value = inMaterial->occlusionChannel;
1005 case QSSGShaderDefaultMaterialKeyProperties::TranslucencyMap:
1006 value = inMaterial->translucencyChannel;
1008 case QSSGShaderDefaultMaterialKeyProperties::HeightMap:
1009 value = inMaterial->heightChannel;
1011 case QSSGShaderDefaultMaterialKeyProperties::ClearcoatMap:
1012 value = inMaterial->clearcoatChannel;
1014 case QSSGShaderDefaultMaterialKeyProperties::ClearcoatRoughnessMap:
1015 value = inMaterial->clearcoatRoughnessChannel;
1017 case QSSGShaderDefaultMaterialKeyProperties::TransmissionMap:
1018 value = inMaterial->transmissionChannel;
1020 case QSSGShaderDefaultMaterialKeyProperties::ThicknessMap:
1021 value = inMaterial->thicknessChannel;
1023 case QSSGShaderDefaultMaterialKeyProperties::BaseColorMap:
1024 value = inMaterial->baseColorChannel;
1026 case QSSGShaderDefaultMaterialKeyProperties::SpecularAmountMap:
1027 value = inMaterial->specularAmountChannel;
1029 case QSSGShaderDefaultMaterialKeyProperties::EmissiveMap:
1030 value = inMaterial->emissiveChannel;
1035 bool useDefault =
false;
1037 case QSSGRenderDefaultMaterial::TextureChannelMapping::G:
1040 case QSSGRenderDefaultMaterial::TextureChannelMapping::B:
1043 case QSSGRenderDefaultMaterial::TextureChannelMapping::A:
1050 value = QSSGRenderDefaultMaterial::R;
1051 channelKey.setTextureChannel(QSSGShaderKeyTextureChannel::TexturChannelBits(value), inShaderKey);
1081QSSGDefaultMaterialPreparationResult QSSGLayerRenderData::prepareDefaultMaterialForRender(
1082 QSSGRenderDefaultMaterial &inMaterial,
1083 QSSGRenderableObjectFlags &inExistingFlags,
1084 float inOpacity,
bool hasAnyLights,
1085 bool anyLightHasShadows,
1086 QSSGLayerRenderPreparationResultFlags &ioFlags)
1088 QSSGRenderDefaultMaterial *theMaterial = &inMaterial;
1089 QSSGDefaultMaterialPreparationResult retval(QSSGShaderDefaultMaterialKey(qHash(features)));
1090 retval.renderableFlags = inExistingFlags;
1091 QSSGRenderableObjectFlags &renderableFlags(retval.renderableFlags);
1092 QSSGShaderDefaultMaterialKey &theGeneratedKey(retval.materialKey);
1093 retval.opacity = inOpacity;
1094 float &subsetOpacity(retval.opacity);
1096 if (theMaterial->isDirty())
1097 renderableFlags |= QSSGRenderableObjectFlag::Dirty;
1099 subsetOpacity *= theMaterial->opacity;
1101 QSSGRenderableImage *firstImage =
nullptr;
1103 const bool lighting = theMaterial->lighting != QSSGRenderDefaultMaterial::MaterialLighting::NoLighting;
1104 defaultMaterialShaderKeyProperties.m_hasLighting.setValue(theGeneratedKey, lighting);
1106 defaultMaterialShaderKeyProperties.m_hasPunctualLights.setValue(theGeneratedKey, hasAnyLights);
1107 defaultMaterialShaderKeyProperties.m_hasShadows.setValue(theGeneratedKey, anyLightHasShadows);
1108 defaultMaterialShaderKeyProperties.m_hasIbl.setValue(theGeneratedKey, layer.lightProbe !=
nullptr);
1111 defaultMaterialShaderKeyProperties.m_specularAAEnabled.setValue(theGeneratedKey, layer.specularAAEnabled);
1114 defaultMaterialShaderKeyProperties.m_isDoubleSided.setValue(theGeneratedKey, theMaterial->cullMode == QSSGCullFaceMode::Disabled);
1117 defaultMaterialShaderKeyProperties.m_overridesPosition.setValue(theGeneratedKey,
false);
1120 defaultMaterialShaderKeyProperties.m_usesProjectionMatrix.setValue(theGeneratedKey,
false);
1121 defaultMaterialShaderKeyProperties.m_usesInverseProjectionMatrix.setValue(theGeneratedKey,
false);
1123 defaultMaterialShaderKeyProperties.m_usesVarColor.setValue(theGeneratedKey,
false);
1126 defaultMaterialShaderKeyProperties.m_alphaMode.setValue(theGeneratedKey, theMaterial->alphaMode);
1129 setVertexInputPresence(renderableFlags, theGeneratedKey);
1132 defaultMaterialShaderKeyProperties.m_usesPointsTopology.setValue(theGeneratedKey, renderableFlags.isPointsTopology());
1135 defaultMaterialShaderKeyProperties.m_lightmapEnabled.setValue(theGeneratedKey, renderableFlags.rendersWithLightmap());
1136 defaultMaterialShaderKeyProperties.m_metallicRoughnessEnabled.setValue(theGeneratedKey, theMaterial->type == QSSGRenderDefaultMaterial::Type::PrincipledMaterial);
1137 defaultMaterialShaderKeyProperties.m_specularGlossyEnabled.setValue(theGeneratedKey, theMaterial->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial);
1141 defaultMaterialShaderKeyProperties.m_debugMode.setValue(theGeneratedKey,
int(layer.debugMode));
1144 defaultMaterialShaderKeyProperties.m_fogEnabled.setValue(theGeneratedKey, layer.fog.enabled);
1147 defaultMaterialShaderKeyProperties.m_viewCount.setValue(theGeneratedKey, layer.viewCount);
1148 defaultMaterialShaderKeyProperties.m_usesViewIndex.setValue(theGeneratedKey, layer.viewCount >= 2);
1150 if (!defaultMaterialShaderKeyProperties.m_hasIbl.getValue(theGeneratedKey) && theMaterial->iblProbe) {
1151 features.set(QSSGShaderFeatures::Feature::LightProbe,
true);
1152 defaultMaterialShaderKeyProperties.m_hasIbl.setValue(theGeneratedKey,
true);
1157 if (subsetOpacity >= QSSGRendererPrivate::minimumRenderOpacity) {
1173 if (theMaterial->blendMode != QSSGRenderDefaultMaterial::MaterialBlendMode::SourceOver
1174 || theMaterial->opacityMap
1175 || theMaterial->alphaMode == QSSGRenderDefaultMaterial::Blend)
1177 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1180 const bool specularEnabled = theMaterial->isSpecularEnabled();
1181 const bool metalnessEnabled = theMaterial->isMetalnessEnabled();
1182 defaultMaterialShaderKeyProperties.m_specularEnabled.setValue(theGeneratedKey, specularEnabled || metalnessEnabled);
1183 defaultMaterialShaderKeyProperties.m_specularModel.setSpecularModel(theGeneratedKey, theMaterial->specularModel);
1184 defaultMaterialShaderKeyProperties.m_diffuseModel.setDiffuseModel(theGeneratedKey, theMaterial->diffuseModel);
1185 defaultMaterialShaderKeyProperties.m_fresnelScaleBiasEnabled.setValue(theGeneratedKey, theMaterial->isFresnelScaleBiasEnabled());
1186 defaultMaterialShaderKeyProperties.m_clearcoatFresnelScaleBiasEnabled.setValue(theGeneratedKey, theMaterial->isClearcoatFresnelScaleBiasEnabled());
1187 defaultMaterialShaderKeyProperties.m_fresnelEnabled.setValue(theGeneratedKey, theMaterial->isFresnelEnabled());
1188 defaultMaterialShaderKeyProperties.m_baseColorSingleChannelEnabled.setValue(theGeneratedKey, theMaterial->isBaseColorSingleChannelEnabled());
1189 defaultMaterialShaderKeyProperties.m_specularSingleChannelEnabled.setValue(theGeneratedKey, theMaterial->isSpecularAmountSingleChannelEnabled());
1190 defaultMaterialShaderKeyProperties.m_emissiveSingleChannelEnabled.setValue(theGeneratedKey, theMaterial->isEmissiveSingleChannelEnabled());
1191 defaultMaterialShaderKeyProperties.m_invertOpacityMapValue.setValue(theGeneratedKey, theMaterial->isInvertOpacityMapValue());
1192 defaultMaterialShaderKeyProperties.m_vertexColorsEnabled.setValue(theGeneratedKey, theMaterial->isVertexColorsEnabled());
1193 defaultMaterialShaderKeyProperties.m_vertexColorsMaskEnabled.setValue(theGeneratedKey, theMaterial->isVertexColorsMaskEnabled());
1194 defaultMaterialShaderKeyProperties.m_vertexColorRedMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorRedMask.toInt()));
1195 defaultMaterialShaderKeyProperties.m_vertexColorGreenMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorGreenMask.toInt()));
1196 defaultMaterialShaderKeyProperties.m_vertexColorBlueMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorBlueMask.toInt()));
1197 defaultMaterialShaderKeyProperties.m_vertexColorAlphaMask.setValue(theGeneratedKey, quint16(theMaterial->vertexColorAlphaMask.toInt()));
1198 defaultMaterialShaderKeyProperties.m_clearcoatEnabled.setValue(theGeneratedKey, theMaterial->isClearcoatEnabled());
1199 defaultMaterialShaderKeyProperties.m_transmissionEnabled.setValue(theGeneratedKey, theMaterial->isTransmissionEnabled());
1204 QSSGRenderableImage *nextImage =
nullptr;
1205#define CHECK_IMAGE_AND_PREPARE(img, imgtype, shadercomponent)
1207 prepareImageForRender(*(img), imgtype, firstImage, nextImage, renderableFlags,
1208 theGeneratedKey, shadercomponent, &inMaterial)
1210 if (theMaterial->type == QSSGRenderGraphObject::Type::PrincipledMaterial ||
1211 theMaterial->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial) {
1213 QSSGRenderableImage::Type::BaseColor,
1214 QSSGShaderDefaultMaterialKeyProperties::BaseColorMap);
1216 QSSGRenderableImage::Type::Occlusion,
1217 QSSGShaderDefaultMaterialKeyProperties::OcclusionMap);
1219 QSSGRenderableImage::Type::Height,
1220 QSSGShaderDefaultMaterialKeyProperties::HeightMap);
1222 QSSGRenderableImage::Type::Clearcoat,
1223 QSSGShaderDefaultMaterialKeyProperties::ClearcoatMap);
1225 QSSGRenderableImage::Type::ClearcoatRoughness,
1226 QSSGShaderDefaultMaterialKeyProperties::ClearcoatRoughnessMap);
1228 QSSGRenderableImage::Type::ClearcoatNormal,
1229 QSSGShaderDefaultMaterialKeyProperties::ClearcoatNormalMap);
1231 QSSGRenderableImage::Type::Transmission,
1232 QSSGShaderDefaultMaterialKeyProperties::TransmissionMap);
1234 QSSGRenderableImage::Type::Thickness,
1235 QSSGShaderDefaultMaterialKeyProperties::ThicknessMap);
1236 if (theMaterial->type == QSSGRenderGraphObject::Type::PrincipledMaterial) {
1238 QSSGRenderableImage::Type::Metalness,
1239 QSSGShaderDefaultMaterialKeyProperties::MetalnessMap);
1243 QSSGRenderableImage::Type::Diffuse,
1244 QSSGShaderDefaultMaterialKeyProperties::DiffuseMap);
1246 CHECK_IMAGE_AND_PREPARE(theMaterial->emissiveMap, QSSGRenderableImage::Type::Emissive, QSSGShaderDefaultMaterialKeyProperties::EmissiveMap);
1248 QSSGRenderableImage::Type::Specular,
1249 QSSGShaderDefaultMaterialKeyProperties::SpecularMap);
1251 QSSGRenderableImage::Type::Roughness,
1252 QSSGShaderDefaultMaterialKeyProperties::RoughnessMap);
1253 CHECK_IMAGE_AND_PREPARE(theMaterial->opacityMap, QSSGRenderableImage::Type::Opacity, QSSGShaderDefaultMaterialKeyProperties::OpacityMap);
1254 CHECK_IMAGE_AND_PREPARE(theMaterial->bumpMap, QSSGRenderableImage::Type::Bump, QSSGShaderDefaultMaterialKeyProperties::BumpMap);
1256 QSSGRenderableImage::Type::SpecularAmountMap,
1257 QSSGShaderDefaultMaterialKeyProperties::SpecularAmountMap);
1258 CHECK_IMAGE_AND_PREPARE(theMaterial->normalMap, QSSGRenderableImage::Type::Normal, QSSGShaderDefaultMaterialKeyProperties::NormalMap);
1260 QSSGRenderableImage::Type::Translucency,
1261 QSSGShaderDefaultMaterialKeyProperties::TranslucencyMap);
1263#undef CHECK_IMAGE_AND_PREPARE
1265 if (subsetOpacity < QSSGRendererPrivate::minimumRenderOpacity) {
1266 subsetOpacity = 0.0f;
1270 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1271 renderableFlags |= QSSGRenderableObjectFlag::CompletelyTransparent;
1274 if (subsetOpacity > 1.f - QSSGRendererPrivate::minimumRenderOpacity)
1275 subsetOpacity = 1.f;
1277 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1279 if (inMaterial.isTransmissionEnabled()) {
1280 ioFlags.setRequiresScreenTexture(
true);
1281 ioFlags.setRequiresMipmapsForScreenTexture(
true);
1282 renderableFlags |= QSSGRenderableObjectFlag::RequiresScreenTexture;
1285 if (renderableFlags.hasTransparency()) {
1286 if (orderIndependentTransparencyEnabled)
1287 defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(layer.oitMethod));
1288 if (layer.oitMethodDirty)
1289 renderableFlags |= QSSGRenderableObjectFlag::Dirty;
1292 retval.firstImage = firstImage;
1293 if (retval.renderableFlags.isDirty())
1294 retval.dirty =
true;
1296 renderer->addMaterialDirtyClear(&inMaterial);
1300QSSGDefaultMaterialPreparationResult QSSGLayerRenderData::prepareCustomMaterialForRender(
1301 QSSGRenderCustomMaterial &inMaterial, QSSGRenderableObjectFlags &inExistingFlags,
1302 float inOpacity,
bool alreadyDirty,
bool hasAnyLights,
bool anyLightHasShadows,
1303 QSSGLayerRenderPreparationResultFlags &ioFlags)
1305 QSSGDefaultMaterialPreparationResult retval(QSSGShaderDefaultMaterialKey(qHash(features)));
1306 retval.renderableFlags = inExistingFlags;
1307 QSSGRenderableObjectFlags &renderableFlags(retval.renderableFlags);
1308 QSSGShaderDefaultMaterialKey &theGeneratedKey(retval.materialKey);
1309 retval.opacity = inOpacity;
1310 float &subsetOpacity(retval.opacity);
1312 if (subsetOpacity < QSSGRendererPrivate::minimumRenderOpacity) {
1313 subsetOpacity = 0.0f;
1317 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1318 renderableFlags |= QSSGRenderableObjectFlag::CompletelyTransparent;
1321 if (subsetOpacity > 1.f - QSSGRendererPrivate::minimumRenderOpacity)
1322 subsetOpacity = 1.f;
1324 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1326 defaultMaterialShaderKeyProperties.m_hasLighting.setValue(theGeneratedKey,
true);
1327 defaultMaterialShaderKeyProperties.m_hasPunctualLights.setValue(theGeneratedKey, hasAnyLights);
1328 defaultMaterialShaderKeyProperties.m_hasShadows.setValue(theGeneratedKey, anyLightHasShadows);
1329 defaultMaterialShaderKeyProperties.m_hasIbl.setValue(theGeneratedKey, layer.lightProbe !=
nullptr);
1330 defaultMaterialShaderKeyProperties.m_specularEnabled.setValue(theGeneratedKey,
true);
1332 defaultMaterialShaderKeyProperties.m_specularAAEnabled.setValue(theGeneratedKey, layer.specularAAEnabled);
1335 defaultMaterialShaderKeyProperties.m_isDoubleSided.setValue(theGeneratedKey, inMaterial.m_cullMode == QSSGCullFaceMode::Disabled);
1338 defaultMaterialShaderKeyProperties.m_metallicRoughnessEnabled.setValue(theGeneratedKey,
true);
1341 const bool overridesPosition = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::OverridesPosition);
1342 defaultMaterialShaderKeyProperties.m_overridesPosition.setValue(theGeneratedKey, overridesPosition);
1345 const bool usesProjectionMatrix = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ProjectionMatrix);
1346 defaultMaterialShaderKeyProperties.m_usesProjectionMatrix.setValue(theGeneratedKey, usesProjectionMatrix);
1347 const bool usesInvProjectionMatrix = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::InverseProjectionMatrix);
1348 defaultMaterialShaderKeyProperties.m_usesInverseProjectionMatrix.setValue(theGeneratedKey, usesInvProjectionMatrix);
1351 setVertexInputPresence(renderableFlags, theGeneratedKey);
1354 defaultMaterialShaderKeyProperties.m_usesPointsTopology.setValue(theGeneratedKey, renderableFlags.isPointsTopology());
1357 defaultMaterialShaderKeyProperties.m_lightmapEnabled.setValue(theGeneratedKey, renderableFlags.rendersWithLightmap());
1360 defaultMaterialShaderKeyProperties.m_debugMode.setValue(theGeneratedKey,
int(layer.debugMode));
1363 defaultMaterialShaderKeyProperties.m_fogEnabled.setValue(theGeneratedKey, layer.fog.enabled);
1366 defaultMaterialShaderKeyProperties.m_viewCount.setValue(theGeneratedKey, layer.viewCount);
1367 defaultMaterialShaderKeyProperties.m_usesViewIndex.setValue(theGeneratedKey,
1368 inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ViewIndex));
1373 const bool usesVarColor = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::VarColor);
1374 defaultMaterialShaderKeyProperties.m_usesVarColor.setValue(theGeneratedKey, usesVarColor);
1376 const bool usesClearcoat = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Clearcoat);
1377 defaultMaterialShaderKeyProperties.m_clearcoatEnabled.setValue(theGeneratedKey, usesClearcoat);
1379 const bool usesClearcoatFresnelScaleBias = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ClearcoatFresnelScaleBias);
1380 defaultMaterialShaderKeyProperties.m_clearcoatFresnelScaleBiasEnabled.setValue(theGeneratedKey, usesClearcoatFresnelScaleBias);
1382 const bool usesFresnelScaleBias = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::FresnelScaleBias);
1383 defaultMaterialShaderKeyProperties.m_fresnelScaleBiasEnabled.setValue(theGeneratedKey, usesFresnelScaleBias);
1385 const bool usesTransmission = inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Transmission);
1386 defaultMaterialShaderKeyProperties.m_transmissionEnabled.setValue(theGeneratedKey, usesTransmission);
1388 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Blending))
1389 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1391 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ScreenTexture)) {
1392 ioFlags.setRequiresScreenTexture(
true);
1393 renderableFlags |= QSSGRenderableObjectFlag::RequiresScreenTexture;
1396 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ScreenMipTexture)) {
1397 ioFlags.setRequiresScreenTexture(
true);
1398 ioFlags.setRequiresMipmapsForScreenTexture(
true);
1399 renderableFlags |= QSSGRenderableObjectFlag::RequiresScreenTexture;
1402 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::DepthTexture))
1403 ioFlags.setRequiresDepthTexture(
true);
1405 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::NormalTexture)) {
1406 ioFlags.setRequiresNormalTexture(
true);
1407 renderableFlags |= QSSGRenderableObjectFlag::RequiresNormalTexture;
1410 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::AoTexture)) {
1411 ioFlags.setRequiresDepthTexture(
true);
1412 ioFlags.setRequiresSsaoPass(
true);
1414 if (orderIndependentTransparencyEnabled && renderableFlags.hasTransparency())
1415 defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(layer.oitMethod));
1417 retval.firstImage =
nullptr;
1419 if (inMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::MotionVectorTexture))
1420 ioFlags.setRequiresMotionVectorPass(
true);
1422 if (retval.dirty || alreadyDirty)
1423 renderer->addMaterialDirtyClear(&inMaterial);
1481bool QSSGLayerRenderData::prepareModelsForRender(QSSGRenderContextInterface &contextInterface,
1482 const RenderableNodeEntries &renderableModels,
1483 QSSGLayerRenderPreparationResultFlags &ioFlags,
1484 const QSSGRenderCameraList &allCameras,
1485 const QSSGRenderCameraDataList &allCameraData,
1486 TModelContextPtrList &modelContexts,
1487 QSSGRenderableObjectList &opaqueObjects,
1488 QSSGRenderableObjectList &transparentObjects,
1489 QSSGRenderableObjectList &screenTextureObjects,
1492 const auto &rhiCtx = contextInterface.rhiContext();
1493 const auto &bufferManager = contextInterface.bufferManager();
1495 const auto &debugDrawSystem = contextInterface.debugDrawSystem();
1496 const bool maybeDebugDraw = debugDrawSystem && debugDrawSystem->isEnabled();
1498 bool wasDirty =
false;
1500 for (
const QSSGRenderableNodeEntry &renderable : renderableModels) {
1501 if ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::Disabled) != 0)
1504 const QSSGRenderModel &model = *
static_cast<QSSGRenderModel *>(renderable.node);
1505 const auto &lights = renderable.lights;
1506 QSSGRenderMesh *theMesh = modelData->getMesh(model);
1510 const bool altGlobalTransform = ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::GlobalTransform) != 0);
1511 const auto &globalTransform = altGlobalTransform ? renderable.extOverrides.globalTransform : getGlobalTransform(model);
1512 QMatrix3x3 normalMatrix { Qt::Uninitialized };
1513 QSSGLayerRenderData::ModelViewProjections mvps;
1514 if (altGlobalTransform) {
1515 QSSGRenderNode::calculateNormalMatrix(globalTransform, normalMatrix);
1516 size_t mvpCount = 0;
1517 for (
const auto &cameraData : allCameraData) {
1518 QSSGRenderNode::calculateMVPAndNormalMatrix(globalTransform, cameraData.viewProjection, mvps[mvpCount++], normalMatrix);
1521 if (model.usesBoneTexture()) {
1525 size_t mvpCount = 0;
1526 for (
const QSSGRenderCameraData &cameraData : allCameraData) {
1527 mvps[mvpCount++] = cameraData.viewProjection;
1528 normalMatrix = QMatrix3x3();
1531 normalMatrix = getNormalMatrix(model);
1532 mvps = getModelMvps(model);
1535 const bool altModelOpacity = ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::GlobalOpacity) != 0);
1536 const float modelGlobalOpacity = altModelOpacity ? renderable.extOverrides.globalOpacity : getGlobalOpacity(model);
1537 QSSGModelContext &theModelContext = *RENDER_FRAME_NEW<QSSGModelContext>(contextInterface, model, globalTransform, normalMatrix, mvps);
1538 modelContexts.push_back(&theModelContext);
1541 const auto &meshSubsets = theMesh->subsets;
1542 const auto meshSubsetCount = meshSubsets.size();
1543 theModelContext.subsets = RENDER_FRAME_NEW_BUFFER<QSSGSubsetRenderable>(contextInterface, meshSubsetCount);
1547 auto boneTexture = bufferManager->loadSkinmap(model.skin);
1548 setBonemapTexture(theModelContext, boneTexture.m_texture);
1549 }
else if (model.skeleton) {
1550 auto boneTexture = bufferManager->loadSkinmap(&(model.skeleton->boneTexData));
1551 setBonemapTexture(theModelContext, boneTexture.m_texture);
1555 QSSGRenderableObjectFlags renderableFlagsForModel;
1557 if (meshSubsetCount > 0) {
1558 const QSSGRenderSubset &theSubset = meshSubsets.at(0);
1560 renderableFlagsForModel.setMotionVectorParticipant(model.motionVectorEnabled);
1562 renderableFlagsForModel.setCastsShadows(model.castsShadows);
1563 renderableFlagsForModel.setReceivesShadows(model.receivesShadows);
1564 renderableFlagsForModel.setReceivesReflections(model.receivesReflections);
1565 renderableFlagsForModel.setCastsReflections(model.castsReflections);
1567 renderableFlagsForModel.setUsedInBakedLighting(model.usedInBakedLighting);
1568 if (model.hasLightmap()) {
1569 QSSGRenderImageTexture lmImageTexture = bufferManager->loadLightmap(model);
1570 if (lmImageTexture.m_texture) {
1571 renderableFlagsForModel.setRendersWithLightmap(
true);
1572 setLightmapTexture(theModelContext, lmImageTexture.m_texture);
1581 bool hasJoint =
false;
1582 bool hasWeight =
false;
1583 bool hasMorphTarget = theSubset.rhi.targetsTexture !=
nullptr;
1584 for (
const QSSGRhiInputAssemblerState::InputSemantic &sem : std::as_const(theSubset.rhi.ia.inputs)) {
1585 if (sem == QSSGRhiInputAssemblerState::PositionSemantic) {
1586 renderableFlagsForModel.setHasAttributePosition(
true);
1587 }
else if (sem == QSSGRhiInputAssemblerState::NormalSemantic) {
1588 renderableFlagsForModel.setHasAttributeNormal(
true);
1589 }
else if (sem == QSSGRhiInputAssemblerState::TexCoord0Semantic) {
1590 renderableFlagsForModel.setHasAttributeTexCoord0(
true);
1591 }
else if (sem == QSSGRhiInputAssemblerState::TexCoord1Semantic) {
1592 renderableFlagsForModel.setHasAttributeTexCoord1(
true);
1593 }
else if (sem == QSSGRhiInputAssemblerState::TexCoordLightmapSemantic) {
1594 renderableFlagsForModel.setHasAttributeTexCoordLightmap(
true);
1595 }
else if (sem == QSSGRhiInputAssemblerState::TangentSemantic) {
1596 renderableFlagsForModel.setHasAttributeTangent(
true);
1597 }
else if (sem == QSSGRhiInputAssemblerState::BinormalSemantic) {
1598 renderableFlagsForModel.setHasAttributeBinormal(
true);
1599 }
else if (sem == QSSGRhiInputAssemblerState::ColorSemantic) {
1600 renderableFlagsForModel.setHasAttributeColor(
true);
1603 }
else if (sem == QSSGRhiInputAssemblerState::JointSemantic) {
1605 }
else if (sem == QSSGRhiInputAssemblerState::WeightSemantic) {
1609 renderableFlagsForModel.setHasAttributeJointAndWeight(hasJoint && hasWeight);
1610 renderableFlagsForModel.setHasAttributeMorphTarget(hasMorphTarget);
1613 QSSGRenderableObjectList bakedLightingObjects;
1614 bool usesBlendParticles = particlesEnabled && theModelContext.model.particleBuffer !=
nullptr
1615 && model.particleBuffer->particleCount();
1616 const bool anyLightHasShadows = std::find_if(lights.begin(),
1618 [](
const QSSGShaderLight &light) {
return light.shadows; })
1620 const bool hasAnyLights = !lights.isEmpty();
1621 QSSGRenderLight::SoftShadowQuality maxSoftShadowQuality = QSSGRenderLight::SoftShadowQuality::Hard;
1622 if (anyLightHasShadows) {
1624 for (
const QSSGShaderLight &light : lights) {
1625 if (light.shadows && light.light->m_softShadowQuality > maxSoftShadowQuality)
1626 maxSoftShadowQuality = light.light->m_softShadowQuality;
1632 auto &renderableSubsets = theModelContext.subsets;
1633 const bool hasMaterialOverrides = ((renderable.overridden & QSSGRenderableNodeEntry::Overridden::Materials) != 0);
1634 const auto &materials = hasMaterialOverrides ? renderable.extOverrides.materials : modelData->getMaterials(model);
1635 const auto materialCount = materials.size();
1636 QSSGRenderGraphObject *lastMaterial = !materials.isEmpty() ? materials.last() :
nullptr;
1637 int idx = 0, subsetIdx = 0;
1638 for (; idx < meshSubsetCount; ++idx) {
1640 QSSGRenderGraphObject *theMaterialObject = (idx >= materialCount) ? lastMaterial : materials[idx];
1641 if (!theMaterialObject)
1644 const QSSGRenderSubset &theSubset = meshSubsets.at(idx);
1645 QSSGRenderableObjectFlags renderableFlags = renderableFlagsForModel;
1646 float subsetOpacity = modelGlobalOpacity;
1648 renderableFlags.setPointsTopology(theSubset.rhi.ia.topology == QRhiGraphicsPipeline::Points);
1649 QSSGRenderableObject *theRenderableObject = &renderableSubsets[subsetIdx++];
1651 const bool usesInstancing = theModelContext.model.instancing()
1652 && rhiCtx->rhi()->isFeatureSupported(QRhi::Instancing);
1653 if (usesInstancing && theModelContext.model.instanceTable->hasTransparency())
1654 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1655 if (theModelContext.model.hasTransparency)
1656 renderableFlags |= QSSGRenderableObjectFlag::HasTransparency;
1659 quint32 subsetLevelOfDetail = 0;
1660 if (!theSubset.lods.isEmpty() && lodThreshold > 0.0f) {
1662 float lodDistanceMultiplier = camerasView[0]->getLevelOfDetailMultiplier();
1663 float distanceThreshold = 0.0f;
1664 const auto scale = QSSGUtils::mat44::getScale(globalTransform);
1665 float modelScale = qMax(scale.x(), qMax(scale.y(), scale.z()));
1666 QSSGBounds3 transformedBounds = theSubset.bounds;
1667 if (camerasView[0]->type != QSSGRenderGraphObject::Type::OrthographicCamera) {
1668 transformedBounds.transform(globalTransform);
1669 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1670 debugDrawSystem->drawBounds(transformedBounds, QColor(Qt::red));
1671 const QMatrix4x4 cameraGlobalTranform = getGlobalTransform(*camerasView[0]);
1672 const QVector3D cameraNormal = QSSGRenderNode::getScalingCorrectDirection(cameraGlobalTranform);
1673 const QVector3D cameraPosition = QSSGRenderNode::getGlobalPos(cameraGlobalTranform);
1674 const QSSGPlane cameraPlane = QSSGPlane(cameraPosition, cameraNormal);
1675 const QVector3D lodSupportMin = transformedBounds.getSupport(-cameraNormal);
1676 const QVector3D lodSupportMax = transformedBounds.getSupport(cameraNormal);
1677 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1678 debugDrawSystem->drawPoint(lodSupportMin, QColor(
"orange"));
1680 const float distanceMin = cameraPlane.distance(lodSupportMin);
1681 const float distanceMax = cameraPlane.distance(lodSupportMax);
1683 if (distanceMin * distanceMax < 0.0)
1684 distanceThreshold = 0.0;
1685 else if (distanceMin >= 0.0)
1686 distanceThreshold = distanceMin;
1687 else if (distanceMax <= 0.0)
1688 distanceThreshold = -distanceMax;
1692 distanceThreshold = 1.0;
1695 int currentLod = -1;
1696 if (model.levelOfDetailBias > 0.0f) {
1697 const float threshold = distanceThreshold * lodDistanceMultiplier;
1698 const float modelBias = 1 / model.levelOfDetailBias;
1699 for (qsizetype i = 0; i < theSubset.lods.count(); ++i) {
1700 float subsetDistance = theSubset.lods[i].distance * modelScale * modelBias;
1701 float screenSize = subsetDistance / threshold;
1702 if (screenSize > lodThreshold)
1707 if (currentLod == -1)
1708 subsetLevelOfDetail = 0;
1710 subsetLevelOfDetail = currentLod + 1;
1711 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLod))
1712 debugDrawSystem->drawBounds(transformedBounds, QSSGDebugDrawSystem::levelOfDetailColor(subsetLevelOfDetail));
1715 QVector3D theModelCenter(theSubset.bounds.center());
1716 theModelCenter = QSSGUtils::mat44::transform(globalTransform, theModelCenter);
1717 if (maybeDebugDraw && debugDrawSystem->isEnabled(QSSGDebugDrawSystem::Mode::MeshLodNormal)) {
1718 const QMatrix4x4 allCamera0GlobalTransform = getGlobalTransform(*allCameras[0]);
1719 debugDrawSystem->debugNormals(*bufferManager, theModelContext, theSubset, subsetLevelOfDetail, (theModelCenter - QSSGRenderNode::getGlobalPos(allCamera0GlobalTransform)).length() * 0.01);
1722 auto checkF32TypeIndex = [&rhiCtx](QRhiVertexInputAttribute::Format f) {
1723 if ((f == QRhiVertexInputAttribute::Format::Float4)
1724 || (f == QRhiVertexInputAttribute::Format::Float3)
1725 || (f == QRhiVertexInputAttribute::Format::Float2)
1726 || (f == QRhiVertexInputAttribute::Format::Float)) {
1729 if (!rhiCtx->rhi()->isFeatureSupported(QRhi::IntAttributes))
1730 qWarning() <<
"WARN: Model has non-integer type indices for skinning but current RHI backend doesn't support it!";
1734 if (theMaterialObject->type == QSSGRenderGraphObject::Type::DefaultMaterial ||
1735 theMaterialObject->type == QSSGRenderGraphObject::Type::PrincipledMaterial ||
1736 theMaterialObject->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial) {
1737 QSSGRenderDefaultMaterial &theMaterial(
static_cast<QSSGRenderDefaultMaterial &>(*theMaterialObject));
1738 QSSGDefaultMaterialPreparationResult theMaterialPrepResult(prepareDefaultMaterialForRender(theMaterial, renderableFlags, subsetOpacity, hasAnyLights, anyLightHasShadows, ioFlags));
1739 QSSGShaderDefaultMaterialKey &theGeneratedKey(theMaterialPrepResult.materialKey);
1740 subsetOpacity = theMaterialPrepResult.opacity;
1741 QSSGRenderableImage *firstImage(theMaterialPrepResult.firstImage);
1742 wasDirty |= theMaterialPrepResult.dirty;
1743 renderableFlags = theMaterialPrepResult.renderableFlags;
1744 if (renderableFlags.hasTransparency())
1745 ioFlags.setHasCustomBlendMode(theMaterial.blendMode != QSSGRenderDefaultMaterial::MaterialBlendMode::SourceOver);
1748 defaultMaterialShaderKeyProperties.m_blendParticles.setValue(theGeneratedKey, usesBlendParticles);
1750 if (defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.getValue(theGeneratedKey) ==
int(QSSGRenderLayer::OITMethod::LinkedList))
1751 defaultMaterialShaderKeyProperties.m_oitMSAA.setValue(theGeneratedKey, rhiCtx->mainPassSampleCount() > 1);
1754 const auto boneCount = model.skin ? model.skin->boneCount :
1755 model.skeleton ? model.skeleton->boneCount : 0;
1756 defaultMaterialShaderKeyProperties.m_boneCount.setValue(theGeneratedKey, boneCount);
1757 if (
auto idJoint = theSubset.rhi.ia.inputs.indexOf(QSSGRhiInputAssemblerState::JointSemantic); idJoint != -1) {
1758 const auto attr = theSubset.rhi.ia.inputLayout.attributeAt(idJoint);
1759 defaultMaterialShaderKeyProperties.m_usesFloatJointIndices.setValue(theGeneratedKey, checkF32TypeIndex(attr->format()));
1763 defaultMaterialShaderKeyProperties.m_shadowSoftness.setShadowSoftness(theGeneratedKey, maxSoftShadowQuality);
1766 defaultMaterialShaderKeyProperties.m_usesInstancing.setValue(theGeneratedKey, usesInstancing);
1768 defaultMaterialShaderKeyProperties.m_targetCount.setValue(theGeneratedKey,
1769 theSubset.rhi.ia.targetCount);
1770 defaultMaterialShaderKeyProperties.m_targetPositionOffset.setValue(theGeneratedKey,
1771 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::PositionSemantic]);
1772 defaultMaterialShaderKeyProperties.m_targetNormalOffset.setValue(theGeneratedKey,
1773 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::NormalSemantic]);
1774 defaultMaterialShaderKeyProperties.m_targetTangentOffset.setValue(theGeneratedKey,
1775 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TangentSemantic]);
1776 defaultMaterialShaderKeyProperties.m_targetBinormalOffset.setValue(theGeneratedKey,
1777 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::BinormalSemantic]);
1778 defaultMaterialShaderKeyProperties.m_targetTexCoord0Offset.setValue(theGeneratedKey,
1779 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord0Semantic]);
1780 defaultMaterialShaderKeyProperties.m_targetTexCoord1Offset.setValue(theGeneratedKey,
1781 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord1Semantic]);
1782 defaultMaterialShaderKeyProperties.m_targetColorOffset.setValue(theGeneratedKey,
1783 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::ColorSemantic]);
1785 new (theRenderableObject) QSSGSubsetRenderable(QSSGSubsetRenderable::Type::DefaultMaterialMeshSubset,
1792 subsetLevelOfDetail,
1797 anyLightHasShadows);
1798 wasDirty = wasDirty || renderableFlags.isDirty();
1799 }
else if (theMaterialObject->type == QSSGRenderGraphObject::Type::CustomMaterial) {
1800 QSSGRenderCustomMaterial &theMaterial(
static_cast<QSSGRenderCustomMaterial &>(*theMaterialObject));
1802 const auto &theMaterialSystem(contextInterface.customMaterialSystem());
1803 wasDirty |= theMaterialSystem->prepareForRender(theModelContext.model, theSubset, theMaterial);
1805 if (theMaterial.m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::Blending))
1806 ioFlags.setHasCustomBlendMode(!hasCustomBlendMode(theMaterial));
1808 QSSGDefaultMaterialPreparationResult theMaterialPrepResult(
1809 prepareCustomMaterialForRender(theMaterial, renderableFlags, subsetOpacity, wasDirty,
1810 hasAnyLights, anyLightHasShadows, ioFlags));
1811 QSSGShaderDefaultMaterialKey &theGeneratedKey(theMaterialPrepResult.materialKey);
1812 subsetOpacity = theMaterialPrepResult.opacity;
1813 QSSGRenderableImage *firstImage(theMaterialPrepResult.firstImage);
1814 renderableFlags = theMaterialPrepResult.renderableFlags;
1816 if (model.particleBuffer && model.particleBuffer->particleCount())
1817 defaultMaterialShaderKeyProperties.m_blendParticles.setValue(theGeneratedKey,
true);
1819 defaultMaterialShaderKeyProperties.m_blendParticles.setValue(theGeneratedKey,
false);
1821 if (defaultMaterialShaderKeyProperties.m_orderIndependentTransparency.getValue(theGeneratedKey) ==
int(QSSGRenderLayer::OITMethod::LinkedList))
1822 defaultMaterialShaderKeyProperties.m_oitMSAA.setValue(theGeneratedKey, rhiCtx->mainPassSampleCount() > 1);
1825 defaultMaterialShaderKeyProperties.m_shadowSoftness.setShadowSoftness(theGeneratedKey, maxSoftShadowQuality);
1828 const auto boneCount = model.skin ? model.skin->boneCount :
1829 model.skeleton ? model.skeleton->boneCount : 0;
1830 defaultMaterialShaderKeyProperties.m_boneCount.setValue(theGeneratedKey, boneCount);
1831 if (
auto idJoint = theSubset.rhi.ia.inputs.indexOf(QSSGRhiInputAssemblerState::JointSemantic); idJoint != -1) {
1832 const auto attr = theSubset.rhi.ia.inputLayout.attributeAt(idJoint);
1833 defaultMaterialShaderKeyProperties.m_usesFloatJointIndices.setValue(theGeneratedKey, checkF32TypeIndex(attr->format()));
1837 bool usesInstancing = theModelContext.model.instancing()
1838 && rhiCtx->rhi()->isFeatureSupported(QRhi::Instancing);
1839 defaultMaterialShaderKeyProperties.m_usesInstancing.setValue(theGeneratedKey, usesInstancing);
1841 defaultMaterialShaderKeyProperties.m_targetCount.setValue(theGeneratedKey,
1842 theSubset.rhi.ia.targetCount);
1843 defaultMaterialShaderKeyProperties.m_targetPositionOffset.setValue(theGeneratedKey,
1844 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::PositionSemantic]);
1845 defaultMaterialShaderKeyProperties.m_targetNormalOffset.setValue(theGeneratedKey,
1846 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::NormalSemantic]);
1847 defaultMaterialShaderKeyProperties.m_targetTangentOffset.setValue(theGeneratedKey,
1848 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TangentSemantic]);
1849 defaultMaterialShaderKeyProperties.m_targetBinormalOffset.setValue(theGeneratedKey,
1850 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::BinormalSemantic]);
1851 defaultMaterialShaderKeyProperties.m_targetTexCoord0Offset.setValue(theGeneratedKey,
1852 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord0Semantic]);
1853 defaultMaterialShaderKeyProperties.m_targetTexCoord1Offset.setValue(theGeneratedKey,
1854 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::TexCoord1Semantic]);
1855 defaultMaterialShaderKeyProperties.m_targetColorOffset.setValue(theGeneratedKey,
1856 theSubset.rhi.ia.targetOffsets[QSSGRhiInputAssemblerState::ColorSemantic]);
1858 if (theMaterial.m_iblProbe)
1859 theMaterial.m_iblProbe->clearDirty();
1861 new (theRenderableObject) QSSGSubsetRenderable(QSSGSubsetRenderable::Type::CustomMaterialMeshSubset,
1868 subsetLevelOfDetail,
1873 anyLightHasShadows);
1875 if (theRenderableObject)
1876 theRenderableObject->camdistSq = getCameraDistanceSq(*theRenderableObject, allCameraData[0]);
1880 if (Q_UNLIKELY(idx != subsetIdx))
1881 renderableSubsets.mSize = subsetIdx;
1883 for (
auto &ro : renderableSubsets) {
1884 const auto depthMode = ro.depthWriteMode;
1885 hasDepthWriteObjects |= (depthMode == QSSGDepthDrawMode::Always || depthMode == QSSGDepthDrawMode::OpaqueOnly);
1886 enum ObjectType : quint8 { ScreenTexture, Transparent, Opaque };
1887 static constexpr DepthPrepassObject ppState[][2] = { {DepthPrepassObject::None, DepthPrepassObject::ScreenTexture},
1888 {DepthPrepassObject::None, DepthPrepassObject::Transparent},
1889 {DepthPrepassObject::None, DepthPrepassObject::Opaque} };
1891 if (ro.renderableFlags.requiresScreenTexture()) {
1892 depthPrepassObjectsState |= DepthPrepassObjectStateT(ppState[ObjectType::ScreenTexture][size_t(depthMode == QSSGDepthDrawMode::OpaquePrePass)]);
1893 screenTextureObjects.push_back({&ro, ro.camdistSq, model.tag});
1894 }
else if (ro.renderableFlags.hasTransparency()) {
1895 depthPrepassObjectsState |= DepthPrepassObjectStateT(ppState[ObjectType::Transparent][size_t(depthMode == QSSGDepthDrawMode::OpaquePrePass)]);
1896 transparentObjects.push_back({&ro, ro.camdistSq, model.tag});
1898 depthPrepassObjectsState |= DepthPrepassObjectStateT(ppState[ObjectType::Opaque][size_t(depthMode == QSSGDepthDrawMode::OpaquePrePass)]);
1899 opaqueObjects.push_back({&ro, ro.camdistSq, model.tag});
1902 if (ro.renderableFlags.usedInBakedLighting())
1903 bakedLightingObjects.push_back({&ro, ro.camdistSq, model.tag});
1906 if (!bakedLightingObjects.isEmpty())
1907 bakedLightingModels.push_back(QSSGBakedLightingModel(&model, bakedLightingObjects));
1913bool QSSGLayerRenderData::prepareParticlesForRender(
const RenderableNodeEntries &renderableParticles,
const QSSGRenderCameraData &cameraData, QSSGLayerRenderPreparationResultFlags &ioFlags)
1915 QSSG_ASSERT(particlesEnabled,
return false);
1917 QSSGRenderContextInterface &contextInterface = *renderer->contextInterface();
1922 auto &opaqueObjects = opaqueObjectStore[0];
1923 auto &transparentObjects = transparentObjectStore[0];
1924 auto &screenTextureObjects = screenTextureObjectStore[0];
1926 for (
auto &renderable : renderableParticles) {
1927 QSSGShaderParticleMaterialKeyProperties &properties = particleMaterialShaderKeyProperties;
1929 QSSGRenderParticles &particles = *
static_cast<QSSGRenderParticles *>(renderable.node);
1930 QSSGShaderParticleMaterialKey &theGeneratedKey(particles.materialKey);
1931 const auto &lights = renderable.lights;
1933 QSSGRenderableObjectFlags renderableFlags;
1934 renderableFlags.setCastsShadows(
false);
1935 renderableFlags.setReceivesShadows(
false);
1936 renderableFlags.setHasAttributePosition(
true);
1937 renderableFlags.setHasAttributeNormal(
true);
1938 renderableFlags.setHasAttributeTexCoord0(
true);
1939 renderableFlags.setHasAttributeColor(
true);
1940 renderableFlags.setHasTransparency(particles.m_hasTransparency);
1941 renderableFlags.setCastsReflections(particles.m_castsReflections);
1942 if (particles.m_hasTransparency && particles.m_blendMode != QSSGRenderParticles::BlendMode::SourceOver)
1943 ioFlags.setHasCustomBlendMode(
true);
1945 properties.m_isLineParticle.setValue(theGeneratedKey, particles.m_featureLevel >= QSSGRenderParticles::FeatureLevel::Line);
1946 const bool animated = particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineAnimated
1947 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::Animated
1948 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::AnimatedVLight
1949 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineAnimatedVLight;
1950 const bool mapped = particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineMapped
1951 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::Mapped
1952 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::MappedVLight
1953 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineMappedVLight;
1954 const bool lit = particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineVLight
1955 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::AnimatedVLight
1956 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::MappedVLight
1957 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineMappedVLight
1958 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::LineAnimatedVLight
1959 || particles.m_featureLevel == QSSGRenderParticles::FeatureLevel::SimpleVLight;
1960 properties.m_isAnimated.setValue(theGeneratedKey, animated);
1961 properties.m_isMapped.setValue(theGeneratedKey, mapped);
1962 properties.m_hasLighting.setValue(theGeneratedKey, lit);
1963 properties.m_viewCount.setValue(theGeneratedKey, layer.viewCount);
1964 if (renderableFlags.hasTransparency() && orderIndependentTransparencyEnabled) {
1965 properties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(layer.oitMethod));
1966 if (layer.oitMethod == QSSGRenderLayer::OITMethod::LinkedList)
1967 properties.m_oitMSAA.setValue(theGeneratedKey, contextInterface.rhiContext()->mainPassSampleCount() > 1);
1969 properties.m_orderIndependentTransparency.setValue(theGeneratedKey,
int(0));
1972 float opacity = getGlobalOpacity(particles);
1973 QVector3D center(particles.m_particleBuffer.bounds().center());
1974 center = QSSGUtils::mat44::transform(getGlobalTransform(particles), center);
1976 QSSGRenderableImage *firstImage =
nullptr;
1977 if (particles.m_sprite) {
1978 const auto &bufferManager = contextInterface.bufferManager();
1980 if (particles.m_sprite->clearDirty())
1983 const QSSGRenderImageTexture texture = bufferManager->loadRenderImage(particles.m_sprite);
1984 QSSGRenderableImage *theImage = RENDER_FRAME_NEW<QSSGRenderableImage>(contextInterface, QSSGRenderableImage::Type::Diffuse, *particles.m_sprite, texture);
1985 firstImage = theImage;
1986 properties.m_isSpriteLinear.setValue(theGeneratedKey, texture.m_flags.isLinear());
1989 QSSGRenderableImage *colorTable =
nullptr;
1990 if (particles.m_colorTable) {
1991 const auto &bufferManager = contextInterface.bufferManager();
1993 if (particles.m_colorTable->clearDirty())
1996 const QSSGRenderImageTexture texture = bufferManager->loadRenderImage(particles.m_colorTable);
1998 QSSGRenderableImage *theImage = RENDER_FRAME_NEW<QSSGRenderableImage>(contextInterface, QSSGRenderableImage::Type::Diffuse, *particles.m_colorTable, texture);
1999 colorTable = theImage;
2000 properties.m_isColorTableLinear.setValue(theGeneratedKey, texture.m_flags.isLinear());
2003 if (opacity > 0.0f && particles.m_particleBuffer.particleCount()) {
2004 const auto globalTransform = getGlobalTransform(particles);
2005 auto *theRenderableObject = RENDER_FRAME_NEW<QSSGParticlesRenderable>(contextInterface,
2016 if (theRenderableObject) {
2017 if (theRenderableObject->renderableFlags.requiresScreenTexture())
2018 screenTextureObjects.push_back({theRenderableObject, getCameraDistanceSq(*theRenderableObject, cameraData), particles.tag});
2019 else if (theRenderableObject->renderableFlags.hasTransparency())
2020 transparentObjects.push_back({theRenderableObject, getCameraDistanceSq(*theRenderableObject, cameraData), particles.tag});
2022 opaqueObjects.push_back({theRenderableObject, getCameraDistanceSq(*theRenderableObject, cameraData), particles.tag});
2192void QSSGLayerRenderData::prepareForRender()
2194 QSSG_ASSERT_X(layerPrepResult.isNull(),
"Prep-result was not reset for render!", layerPrepResult = {});
2196 QRect theViewport(renderer->viewport());
2200 frameData.m_ctx = renderer->contextInterface();
2205 ps.viewport = {
float(theViewport.x()),
float(theViewport.y()),
float(theViewport.width()),
float(theViewport.height()), 0.0f, 1.0f };
2206 if (layer.scissorRect.isValid()) {
2207 ps.flags |= QSSGRhiGraphicsPipelineState::Flag::UsesScissor;
2208 ps.scissor = { layer.scissorRect.x(),
2209 theViewport.height() - (layer.scissorRect.y() + layer.scissorRect.height()),
2210 layer.scissorRect.width(),
2211 layer.scissorRect.height() };
2214 ps.depthFunc = QRhiGraphicsPipeline::LessOrEqual;
2215 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
false);
2218 ps.polygonMode = layer.wireframeMode ? QRhiGraphicsPipeline::Line : QRhiGraphicsPipeline::Fill;
2220 bool wasDirty =
false;
2221 bool wasDataDirty =
false;
2222 wasDirty = layer.isDirty();
2224 const bool shouldDisableInternalPasses = (layer.renderOverrides & size_t(QSSGRenderLayer::RenderOverrides::DisableInternalPasses)) != 0;
2225 wasDirty |= (shouldDisableInternalPasses != disableMainPasses);
2226 disableMainPasses = shouldDisableInternalPasses;
2229 layerPrepResult = { theViewport, layer };
2232 const bool SSAOEnabled = layer.ssaoEnabled();
2233 layerPrepResult.flags.setRequiresSsaoPass(SSAOEnabled);
2234 features.set(QSSGShaderFeatures::Feature::Ssao, SSAOEnabled);
2237 bool requiresDepthTexture = SSAOEnabled;
2238 bool requiresNormalTexture =
false;
2239 bool requiresMotionVectorTexture =
false;
2240 for (QSSGRenderEffect *theEffect = layer.firstEffect; theEffect; theEffect = theEffect->m_nextEffect) {
2241 if (theEffect->isDirty()) {
2243 theEffect->clearDirty();
2245 if (theEffect->testFlag(QSSGRenderEffect::Flags::UsesDepthTexture))
2246 requiresDepthTexture =
true;
2247 if (theEffect->testFlag(QSSGRenderEffect::Flags::UsesNormalTexture))
2248 requiresNormalTexture =
true;
2249 if (theEffect->testFlag(QSSGRenderEffect::Flags::UsesMotionVectorTexture))
2250 requiresMotionVectorTexture =
true;
2253 const auto &rhiCtx = renderer->contextInterface()->rhiContext();
2254 orderIndependentTransparencyEnabled = (layer.oitMethod != QSSGRenderLayer::OITMethod::None);
2255 if (layer.oitMethod == QSSGRenderLayer::OITMethod::WeightedBlended) {
2256 orderIndependentTransparencyEnabled = rhiCtx->rhi()->isFeatureSupported(QRhi::PerRenderTargetBlending);
2257 if (rhiCtx->mainPassSampleCount() > 1)
2258 orderIndependentTransparencyEnabled |= rhiCtx->rhi()->isFeatureSupported(QRhi::TexelFetch) && rhiCtx->rhi()->isFeatureSupported(QRhi::SampleVariables);
2259 if (!orderIndependentTransparencyEnabled && !oitWarningUnsupportedShown) {
2260 qCWarning(lcQuick3DRender) <<
"WeightedBlended OIT is requested, but it is not supported.";
2261 oitWarningUnsupportedShown =
true;
2263 }
else if (layer.oitMethod == QSSGRenderLayer::OITMethod::LinkedList) {
2264 if (rhiCtx->mainPassSampleCount() > 1)
2265 orderIndependentTransparencyEnabled |= rhiCtx->rhi()->isFeatureSupported(QRhi::SampleVariables);
2266 if (!orderIndependentTransparencyEnabled && !oitWarningUnsupportedShown) {
2267 qCWarning(lcQuick3DRender) <<
"LinkedList OIT is requested, but it is not supported.";
2268 oitWarningUnsupportedShown =
true;
2271 if (layer.oitMethodDirty) {
2272 oitRenderContext.reset();
2273 for (
auto &renderResult : renderResults)
2274 renderResult.reset();
2277 layerPrepResult.flags.setRequiresDepthTexture(requiresDepthTexture);
2279 layerPrepResult.flags.setRequiresNormalTexture(requiresNormalTexture);
2281 layerPrepResult.flags.setRequiresMotionVectorPass(requiresMotionVectorTexture);
2285 if (!layer.firstEffect)
2286 QSSGLayerRenderData::setTonemapFeatures(features, layer.tonemapMode);
2293 if (rhiCtx->rhi()->resourceLimit(QRhi::MaxUniformBufferRange) < REDUCED_MAX_LIGHT_COUNT_THRESHOLD_BYTES) {
2294 features.set(QSSGShaderFeatures::Feature::ReduceMaxNumLights,
true);
2295 static bool notified =
false;
2298 qCDebug(lcQuick3DRender,
"Qt Quick 3D maximum number of lights has been reduced from %d to %d due to the graphics driver's limitations",
2299 QSSG_MAX_NUM_LIGHTS, QSSG_REDUCED_MAX_NUM_LIGHTS);
2304 QSSGRenderImageTexture lightProbeTexture;
2305 if (layer.lightProbe) {
2306 const auto &lightProbeSettings = layer.lightProbeSettings;
2307 if (layer.lightProbe->m_format == QSSGRenderTextureFormat::Unknown) {
2310 if (renderer->contextInterface()->rhiContext()->rhi()->isTextureFormatSupported(QRhiTexture::RGBA16F))
2311 layer.lightProbe->m_format = QSSGRenderTextureFormat::RGBA16F;
2313 layer.lightProbe->m_format = QSSGRenderTextureFormat::RGBE8;
2316 if (layer.lightProbe->clearDirty())
2317 wasDataDirty =
true;
2320 lightProbeTexture = renderer->contextInterface()->bufferManager()->loadRenderImage(layer.lightProbe, QSSGBufferManager::MipModeBsdf);
2321 if (lightProbeTexture.m_texture) {
2323 features.set(QSSGShaderFeatures::Feature::LightProbe,
true);
2324 features.set(QSSGShaderFeatures::Feature::IblOrientation, !lightProbeSettings.probeOrientation.isIdentity());
2328 if (lightProbeTexture.m_flags.isRgbe8())
2329 features.set(QSSGShaderFeatures::Feature::RGBELightProbe,
true);
2331 layer.lightProbe =
nullptr;
2334 const bool forceIblExposureValues = (features.isSet(QSSGShaderFeatures::Feature::LightProbe) && layer.tonemapMode == QSSGRenderLayer::TonemapMode::Custom);
2335 features.set(QSSGShaderFeatures::Feature::ForceIblExposure, forceIblExposureValues);
2338 frameData.m_ctx->bufferManager()->setLightmapSource(layer.lightmapSource);
2342 version = nodeData->version();
2347 auto &globalTransforms = nodeData->globalTransforms;
2348 auto &globalOpacities = nodeData->globalOpacities;
2349 auto &instanceTransforms = nodeData->instanceTransforms;
2352 QSSGRenderDataHelpers::GlobalStateResultT globalStateResult = QSSGRenderDataHelpers::GlobalStateResult::None;
2354 const bool layerTreeWasDirty = layer.isDirty(QSSGRenderLayer::DirtyFlag::TreeDirty);
2355 layer.clearDirty(QSSGRenderLayer::DirtyFlag::TreeDirty);
2356 if (layerTreeWasDirty) {
2357 wasDataDirty =
true;
2358 layerNodes = nodeData->getLayerNodeView(layer);
2360 for (
auto &node : layerNodes)
2361 globalStateResult |= QSSGRenderDataHelpers::updateGlobalNodeState(node, version);
2363 bool transformAndOpacityDirty =
false;
2364 for (
auto &node : layerNodes)
2365 transformAndOpacityDirty |= QSSGRenderDataHelpers::calcGlobalNodeData<QSSGRenderDataHelpers::Strategy::Update>(node, version, globalTransforms, globalOpacities);
2368 if (transformAndOpacityDirty) {
2369 for (
const auto &node : layerNodes)
2370 wasDataDirty |= QSSGRenderDataHelpers::calcInstanceTransforms(node, version, globalTransforms, instanceTransforms);
2373 wasDataDirty |= transformAndOpacityDirty;
2379 const bool hasExplicitCamera = (layer.explicitCameras.size() != 0);
2380 bool cameraLayerMaskDirty =
false;
2381 quint32 layerMask = QSSGRenderCamera::LayerMaskAll;
2382 if (hasExplicitCamera) {
2383 QSSGRenderCamera *explicitCamera = layer.explicitCameras[0];
2384 layerMask = explicitCamera->tag.value();
2385 cameraLayerMaskDirty = explicitCamera->isDirty(QSSGRenderCamera::DirtyFlag::LayerMaskDirty);
2386 explicitCamera->clearDirty(QSSGRenderCamera::DirtyFlag::LayerMaskDirty);
2389 const bool restatNodes = (layerTreeWasDirty || (globalStateResult & QSSGRenderDataHelpers::GlobalStateResult::ActiveChanged) || cameraLayerMaskDirty);
2393 particlesView.clear();
2394 item2DsView.clear();
2395 camerasView.clear();
2397 reflectionProbesView.clear();
2398 nonCategorizedView.clear();
2400 enum NodeType : size_t { Model = 0, Particles, Item2D, Camera, ImportedCamera, Light, ReflectionProbe, Other, Inactive };
2401 const auto nodeType = [layerMask](QSSGRenderNode *node) -> NodeType {
2402 if (!(node->getGlobalState(QSSGRenderNode::GlobalState::Active) && (node->tag.isSet(layerMask))))
2403 return NodeType::Inactive;
2404 switch (node->type) {
2405 case QSSGRenderGraphObject::Type::Model:
return NodeType::Model;
2406 case QSSGRenderGraphObject::Type::Particles:
return NodeType::Particles;
2407 case QSSGRenderGraphObject::Type::Item2D:
return NodeType::Item2D;
2408 case QSSGRenderGraphObject::Type::ReflectionProbe:
return NodeType::ReflectionProbe;
2412 if (QSSGRenderGraphObject::isCamera(node->type)) {
2415 const bool isImported = node->getGlobalState(QSSGRenderNode::GlobalState::Imported);
2416 constexpr NodeType cameraTypes[2] { NodeType::Camera, NodeType::ImportedCamera };
2417 return cameraTypes[size_t(isImported)];
2419 if (QSSGRenderGraphObject::isLight(node->type))
2420 return NodeType::Light;
2422 return NodeType::Other;
2434 layerNodesCategorized = { layerNodes.begin(), layerNodes.end() };
2436 std::stable_sort(layerNodesCategorized.begin(), layerNodesCategorized.end(), [nodeType](QSSGRenderNode *a, QSSGRenderNode *b) {
2437 return nodeType(a) < nodeType(b);
2442 const LayerNodeStatResult stat = statLayerNodes(layerNodesCategorized, layerMask);
2447 if (stat.modelCount > 0) {
2448 modelsView = QSSGModelsView((QSSGRenderModel **)(layerNodesCategorized.data() + next), stat.modelCount);
2449 next = modelsView.size();
2451 if (stat.particlesCount > 0) {
2452 particlesView = QSSGParticlesView((QSSGRenderParticles **)(layerNodesCategorized.data() + next), stat.particlesCount);
2453 next += particlesView.size();
2455 if (stat.item2DCount > 0) {
2456 item2DsView = QSSGItem2DsView((QSSGRenderItem2D **)(layerNodesCategorized.data() + next), stat.item2DCount);
2457 next += item2DsView.size();
2459 if (stat.cameraCount > 0) {
2460 camerasView = QSSGCamerasView((QSSGRenderCamera **)(layerNodesCategorized.data() + next), stat.cameraCount);
2461 next += camerasView.size();
2463 if (stat.lightCount > 0) {
2464 lightsView = QSSGLightsView((QSSGRenderLight **)(layerNodesCategorized.data() + next), stat.lightCount);
2465 next += lightsView.size();
2467 if (stat.reflectionProbeCount > 0) {
2468 reflectionProbesView = QSSGReflectionProbesView((QSSGRenderReflectionProbe **)(layerNodesCategorized.data() + next), stat.reflectionProbeCount);
2469 next += reflectionProbesView.size();
2471 if (stat.otherCount > 0) {
2472 nonCategorizedView = QSSGNonCategorizedView((QSSGRenderNode **)(layerNodesCategorized.data() + next), stat.otherCount);
2473 next += nonCategorizedView.size();
2479 renderableModels.clear();
2480 renderableParticles.clear();
2481 renderableModels.reserve(modelsView.size());
2482 renderableParticles.reserve(particlesView.size());
2484 renderableModels = {modelsView.begin(), modelsView.end()};
2485 renderableParticles = {particlesView.begin(), particlesView.end()};
2492 QSSGRenderCamera::Configuration cameraConfig { renderer->dpr(), layer.isSsaaEnabled() ? layer.ssaaMultiplier : 1.0f };
2493 renderedCameras.clear();
2494 if (!layer.explicitCameras.isEmpty()) {
2495 for (QSSGRenderCamera *cam : std::as_const(layer.explicitCameras)) {
2497 if (cam->getGlobalState(QSSGRenderCamera::GlobalState::Active)) {
2498 const bool computeFrustumSucceeded = cam->calculateProjection(theViewport, cameraConfig);
2499 if (Q_LIKELY(computeFrustumSucceeded))
2500 renderedCameras.append(cam);
2502 qCCritical(INTERNAL_ERROR,
"Failed to calculate camera frustum");
2506 }
else if (QSSG_GUARD_X(layer.viewCount == 1,
"Multiview rendering requires explicit cameras to be set!.")) {
2511 for (
auto iter = camerasView.begin(); renderedCameras.isEmpty() && iter != camerasView.end(); iter++) {
2512 QSSGRenderCamera *theCamera = *iter;
2513 if (theCamera->getGlobalState(QSSGRenderCamera::GlobalState::Active)) {
2514 const bool computeFrustumSucceeded = theCamera->calculateProjection(theViewport, cameraConfig);
2515 if (Q_LIKELY(computeFrustumSucceeded))
2516 renderedCameras.append(theCamera);
2518 qCCritical(INTERNAL_ERROR,
"Failed to calculate camera frustum");
2523 float meshLodThreshold = 1.0f;
2524 if (!renderedCameras.isEmpty())
2525 meshLodThreshold = renderedCameras[0]->levelOfDetailPixelThreshold / theViewport.width();
2527 layer.renderedCamerasMutex.lock();
2528 layer.renderedCameras = renderedCameras;
2529 layer.renderedCamerasMutex.unlock();
2532 const QSSGRenderCameraDataList &renderCameraData = getCachedCameraDatas();
2533 modelData->updateModelData(modelsView, renderer, renderCameraData);
2536 item2DData->updateItem2DData(item2DsView, renderer, renderCameraData);
2539 prepareResourceLoaders();
2542 updateDirtySkeletons(*
this, modelsView);
2545 int directionalLightsCount = 0;
2546 int positionalLightsCount = 0;
2547 const int maxLightCount = effectiveMaxLightCount(features);
2548 const int maxDirectionalLights = effectiveMaxDirectionalLightCount(features);
2549 QSSGShaderLightList renderableLights;
2550 int shadowMapCount = 0;
2551 bool hasScopedLights =
false;
2557 auto it = std::make_reverse_iterator(lightsView.end());
2558 const auto end = it + qMin(maxLightCount, lightsView.size());
2559 for (; it != end; ++it) {
2560 QSSGRenderLight *renderLight = (*it);
2561 QMatrix4x4 renderLightTransform = getGlobalTransform(*renderLight);
2562 if (renderLight->type == QSSGRenderGraphObject::Type::DirectionalLight)
2563 directionalLightsCount++;
2565 positionalLightsCount++;
2567 if (positionalLightsCount > maxLightCount)
2569 if (directionalLightsCount > maxDirectionalLights)
2573 hasScopedLights |= (renderLight->m_scope !=
nullptr);
2574 const bool castShadows = renderLight->m_castShadow && !renderLight->m_fullyBaked;
2575 shadowMapCount +=
int(castShadows);
2576 const auto &direction = renderLight->getScalingCorrectDirection(renderLightTransform);
2577 renderableLights.push_back(QSSGShaderLight{ renderLight, castShadows, direction });
2581 const bool showLightCountWarning = !tooManyLightsWarningShown && (positionalLightsCount > maxLightCount);
2582 if (showLightCountWarning) {
2583 qWarning(
"Too many lights in scene, maximum is %d", maxLightCount);
2584 tooManyLightsWarningShown =
true;
2587 const bool showDirectionalLightCountWarning = !tooManyDirectionalLightsWarningShown && (directionalLightsCount > maxDirectionalLights);
2588 if (showDirectionalLightCountWarning) {
2589 qWarning(
"Too many directional lights in scene, maximum is %d", maxDirectionalLights);
2590 tooManyDirectionalLightsWarningShown =
true;
2593 if (shadowMapCount > 0) {
2594 requestShadowMapManager();
2595 layerPrepResult.flags.setRequiresShadowMapPass(
true);
2600 features.set(QSSGShaderFeatures::Feature::Ssm,
true);
2601 shadowMapManager->addShadowMaps(renderableLights);
2602 }
else if (shadowMapManager) {
2604 shadowMapManager->releaseCachedResources();
2610 QSSG_ASSERT(globalLights.isEmpty(), globalLights.clear());
2611 if (hasScopedLights) {
2612 for (
const auto &shaderLight : std::as_const(renderableLights)) {
2613 if (!shaderLight.light->m_scope)
2614 globalLights.push_back(shaderLight);
2617 const auto prepareLightsWithScopedLights = [&renderableLights,
this](QVector<QSSGRenderableNodeEntry> &renderableNodes) {
2618 for (qint32 idx = 0, end = renderableNodes.size(); idx < end; ++idx) {
2619 QSSGRenderableNodeEntry &theNodeEntry(renderableNodes[idx]);
2620 QSSGShaderLightList filteredLights;
2621 for (
const auto &light : std::as_const(renderableLights)) {
2622 if (light.light->m_scope && !scopeLight(theNodeEntry.node, light.light->m_scope))
2624 filteredLights.push_back(light);
2627 if (filteredLights.isEmpty()) {
2628 theNodeEntry.lights = QSSGDataView(globalLights);
2633 auto customLightList = RENDER_FRAME_NEW_BUFFER<QSSGShaderLight>(*renderer->contextInterface(), filteredLights.size());
2634 std::copy(filteredLights.cbegin(), filteredLights.cend(), customLightList.begin());
2635 theNodeEntry.lights = customLightList;
2640 prepareLightsWithScopedLights(renderableModels);
2641 prepareLightsWithScopedLights(renderableParticles);
2643 globalLights = renderableLights;
2645 const auto prepareLights = [
this](QVector<QSSGRenderableNodeEntry> &renderableNodes) {
2646 for (qint32 idx = 0, end = renderableNodes.size(); idx < end; ++idx) {
2647 QSSGRenderableNodeEntry &theNodeEntry(renderableNodes[idx]);
2648 theNodeEntry.lights = QSSGDataView(globalLights);
2652 prepareLights(renderableModels);
2653 prepareLights(renderableParticles);
2659 Q_STATIC_ASSERT(USERPASSES == size_t(QSSGRenderLayer::RenderExtensionStage::Count));
2660 for (size_t i = 0; i != size_t(QSSGRenderLayer::RenderExtensionStage::Count); ++i) {
2661 const auto &renderExtensions = layer.renderExtensions[i];
2662 auto &userPass = userPasses[i];
2663 for (
auto rit = renderExtensions.crbegin(), rend = renderExtensions.crend(); rit != rend; ++rit) {
2664 if ((*rit)->prepareData(frameData)) {
2666 userPass.extensions.push_back(*rit);
2674 const auto &userRenderPassManager = requestUserRenderPassManager();
2675 userRenderPassManager->updateUserPassOrder(layerTreeWasDirty);
2676 userRenderPasses.userPasses = userRenderPassManager->scheduledUserPasses();
2679 auto &opaqueObjects = opaqueObjectStore[0];
2680 auto &transparentObjects = transparentObjectStore[0];
2681 auto &screenTextureObjects = screenTextureObjectStore[0];
2683 if (!renderedCameras.isEmpty()) {
2684 wasDirty |= prepareModelsForRender(*renderer->contextInterface(), renderableModels, layerPrepResult.flags, renderedCameras, getCachedCameraDatas(), modelContexts, opaqueObjects, transparentObjects, screenTextureObjects, meshLodThreshold);
2685 if (particlesEnabled) {
2686 const auto &cameraDatas = getCachedCameraDatas();
2687 wasDirty |= prepareParticlesForRender(renderableParticles, cameraDatas[0], layerPrepResult.flags);
2690 wasDirty |= (item2DsView.size() != 0);
2692 if (orderIndependentTransparencyEnabled) {
2694 if (transparentObjects.size() > 0 && !layerPrepResult.flags.hasCustomBlendMode()) {
2695 if (layer.oitMethod == QSSGRenderLayer::OITMethod::WeightedBlended) {
2696 if (rhiCtx->mainPassSampleCount() > 1)
2697 layerPrepResult.flags.setRequiresDepthTextureMS(
true);
2699 layerPrepResult.flags.setRequiresDepthTexture(
true);
2702 orderIndependentTransparencyEnabled =
false;
2703 if (!oitWarningInvalidBlendModeShown) {
2704 qCWarning(lcQuick3DRender) <<
"Order Independent Transparency requested, but disabled due to invalid blend modes.";
2705 qCWarning(lcQuick3DRender) <<
"Use SourceOver blend mode for Order Independent Transparency.";
2706 oitWarningInvalidBlendModeShown =
true;
2710 layer.oitMethodDirty =
false;
2712 prepareReflectionProbesForRender();
2714 wasDirty = wasDirty || wasDataDirty;
2715 layerPrepResult.flags.setWasDirty(wasDirty);
2716 layerPrepResult.flags.setLayerDataDirty(wasDataDirty);
2719 const bool animating = wasDirty;
2721 layer.progAAPassIndex = 0;
2723 const bool progressiveAA = layer.isProgressiveAAEnabled() && !animating;
2724 layer.progressiveAAIsActive = progressiveAA;
2725 const bool temporalAA = layer.isTemporalAAEnabled() && !progressiveAA;
2727 layer.temporalAAIsActive = temporalAA;
2729 QVector2D vertexOffsetsAA;
2731 if (progressiveAA && layer.progAAPassIndex > 0 && layer.progAAPassIndex < quint32(layer.antialiasingQuality)) {
2732 int idx = layer.progAAPassIndex - 1;
2733 vertexOffsetsAA = s_ProgressiveAAVertexOffsets[idx] / QVector2D{
float(theViewport.width()/2.0),
float(theViewport.height()/2.0) };
2737 if (layer.temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector && layer.tempAAPassIndex > 0) {
2738 if (layer.tempAAPassIndex >= quint32(MAX_AA_LEVELS) + 1)
2739 layer.tempAAPassIndex = 1;
2740 int idx = layer.tempAAPassIndex - 1;
2741 vertexOffsetsAA = s_ProgressiveAAVertexOffsets[idx] / QVector2D{
float(theViewport.width()/2.0),
float(theViewport.height()/2.0) };
2742 layer.currentAndLastJitter = QVector4D(vertexOffsetsAA, layer.currentAndLastJitter.x(), layer.currentAndLastJitter.y());
2743 layerPrepResult.flags.setRequiresMotionVectorPass(
true);
2744 layerPrepResult.flags.setRequiresDepthTexture(
true);
2746 const int t = 1 - 2 * (layer.tempAAPassIndex % 2);
2747 const float f = t * layer.temporalAAStrength;
2748 vertexOffsetsAA = { f /
float(theViewport.width()/2.0), f /
float(theViewport.height()/2.0) };
2752 if (!renderedCameras.isEmpty()) {
2753 if (temporalAA || progressiveAA ) {
2754 QMatrix4x4 offsetProjection = renderedCameras[0]->projection;
2755 QMatrix4x4 invProjection = renderedCameras[0]->projection.inverted();
2756 if (renderedCameras[0]->type == QSSGRenderCamera::Type::OrthographicCamera) {
2757 offsetProjection(0, 3) -= vertexOffsetsAA.x();
2758 offsetProjection(1, 3) -= vertexOffsetsAA.y();
2759 }
else if (renderedCameras[0]->type == QSSGRenderCamera::Type::PerspectiveCamera) {
2760 offsetProjection(0, 2) += vertexOffsetsAA.x();
2761 offsetProjection(1, 2) += vertexOffsetsAA.y();
2763 for (
auto &modelContext : std::as_const(modelContexts)) {
2764 for (
int mvpIdx = 0; mvpIdx < renderedCameras.count(); ++mvpIdx)
2765 modelContext->modelViewProjections[mvpIdx] = offsetProjection * invProjection * modelContext->modelViewProjections[mvpIdx];
2770 const bool hasItem2Ds = (item2DsView.size() > 0);
2771 const bool layerEnableDepthTest = layer.layerFlags.testFlag(QSSGRenderLayer::LayerFlag::EnableDepthTest);
2772 const bool layerEnabledDepthPrePass = layer.layerFlags.testFlag(QSSGRenderLayer::LayerFlag::EnableDepthPrePass);
2773 const bool depthTestEnableDefault = layerEnableDepthTest && (!opaqueObjects.isEmpty() || depthPrepassObjectsState || hasDepthWriteObjects);
2774 const bool zPrePassForced = (depthPrepassObjectsState != 0);
2775 zPrePassActive = zPrePassForced || (layerEnabledDepthPrePass && layerEnableDepthTest && (hasDepthWriteObjects || hasItem2Ds));
2776 const bool depthWriteEnableDefault = depthTestEnableDefault && (!layerEnabledDepthPrePass || !zPrePassActive);
2778 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, depthTestEnableDefault);
2779 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled, depthWriteEnableDefault);
2783 layerPrepResult.setState(QSSGLayerRenderPreparationResult::State::Done);
2786 QSSG_ASSERT(activePasses.isEmpty(), activePasses.clear());
2790 if (layerPrepResult.flags.requiresDepthTexture())
2791 activePasses.push_back(&depthMapPass);
2792 if (layerPrepResult.flags.requiresDepthTextureMS())
2793 activePasses.push_back(&depthMapPassMS);
2795 if (layerPrepResult.flags.requiresNormalTexture())
2796 activePasses.push_back(&normalPass);
2799 if (layerPrepResult.flags.requiresSsaoPass())
2800 activePasses.push_back(&ssaoMapPass);
2803 if (layerPrepResult.flags.requiresShadowMapPass())
2804 activePasses.push_back(&shadowMapPass);
2806 if (zPrePassActive && !disableMainPasses)
2807 activePasses.push_back(&zPrePassPass);
2810 if (layerPrepResult.flags.requiresScreenTexture())
2811 activePasses.push_back(&screenMapPass);
2814 activePasses.push_back(&reflectionMapPass);
2816 auto &textureExtensionPass = userPasses[size_t(QSSGRenderLayer::RenderExtensionStage::TextureProviders)];
2817 if (textureExtensionPass.hasData())
2818 activePasses.push_back(&textureExtensionPass);
2820 auto &underlayPass = userPasses[size_t(QSSGRenderLayer::RenderExtensionStage::Underlay)];
2821 if (underlayPass.hasData())
2822 activePasses.push_back(&underlayPass);
2825 if (userRenderPasses.hasData())
2826 activePasses.push_back(&userRenderPasses);
2828 const bool hasOpaqueObjects = (opaqueObjects.size() > 0);
2830 if (hasOpaqueObjects && !disableMainPasses)
2831 activePasses.push_back(&opaquePass);
2834 if (layerPrepResult.flags.requiresMotionVectorPass())
2835 activePasses.push_back(&motionVectorMapPass);
2839 if (renderer->contextInterface()->rhiContext()->rhi()->isFeatureSupported(QRhi::TexelFetch)) {
2840 if (layer.background == QSSGRenderLayer::Background::SkyBoxCubeMap && layer.skyBoxCubeMap && !disableMainPasses)
2841 activePasses.push_back(&skyboxCubeMapPass);
2842 else if (layer.background == QSSGRenderLayer::Background::SkyBox && layer.lightProbe && !disableMainPasses)
2843 activePasses.push_back(&skyboxPass);
2846 if (hasItem2Ds && !disableMainPasses)
2847 activePasses.push_back(&item2DPass);
2849 if (layerPrepResult.flags.requiresScreenTexture())
2850 activePasses.push_back(&reflectionPass);
2853 if ((transparentObjects.size() > 0 || (!layerEnableDepthTest && hasOpaqueObjects)) && !disableMainPasses) {
2854 if (orderIndependentTransparencyEnabled) {
2855 activePasses.push_back(&oitRenderPass);
2856 activePasses.push_back(&oitCompositePass);
2857 oitRenderPass.setMethod(layer.oitMethod);
2858 oitCompositePass.setMethod(layer.oitMethod);
2860 activePasses.push_back(&transparentPass);
2864 auto &overlayPass = userPasses[size_t(QSSGRenderLayer::RenderExtensionStage::Overlay)];
2865 if (overlayPass.hasData())
2866 activePasses.push_back(&overlayPass);
2868 if (layer.gridEnabled)
2869 activePasses.push_back(&infiniteGridPass);
2871 if (
const auto &dbgDrawSystem = renderer->contextInterface()->debugDrawSystem(); dbgDrawSystem && dbgDrawSystem->isEnabled() && !disableMainPasses)
2872 activePasses.push_back(&debugDrawPass);