278 const QSSGRenderCamera &inCamera,
279 const QSSGRenderLight *inLight,
280 const int shadowMapResolution,
281 const float pcfRadius,
282 const float clipNear,
284 const QSSGBounds3 &castingObjectsBox,
285 const QSSGBounds3 &receivingObjectsBox,
286 bool lockShadowmapTexels,
287 QSSGDebugDrawSystem *debugDrawSystem,
289 bool drawSceneCascadeIntersection)
291 Q_ASSERT(inLight->type == QSSGRenderLight::Type::DirectionalLight);
292 QVarLengthArray<std::unique_ptr<QSSGRenderCamera>, 4> result;
294 if (clipNear >= clipFar || qFuzzyCompare(clipNear, clipFar))
297 const QMatrix4x4 lightGlobalTransform = data.getGlobalTransform(*inLight);
298 const QVector3D lightDir = inLight->getDirection(lightGlobalTransform);
299 const QVector3D lightPivot = inLight->pivot;
301 const QVector3D forward = lightDir.normalized();
302 const QVector3D right = qFuzzyCompare(qAbs(forward.y()), 1.0f)
303 ? QVector3D::crossProduct(forward, QVector3D(1, 0, 0)).normalized()
304 : QVector3D::crossProduct(forward, QVector3D(0, 1, 0)).normalized();
305 const QVector3D up = QVector3D::crossProduct(right, forward).normalized();
307 QMatrix4x4 lightMatrix;
308 lightMatrix.setRow(0, QVector4D(right, 0.0f));
309 lightMatrix.setRow(1, QVector4D(up, 0.0f));
310 lightMatrix.setRow(2, QVector4D(forward, 0.0f));
311 lightMatrix.setRow(3, QVector4D(0.0f, 0.0f, 0.0f, 1.0f));
312 QMatrix4x4 lightMatrixInverted = lightMatrix.inverted();
314 const float farScale = (clipFar - clipNear) / (inCamera.clipPlanes.clipFar() - inCamera.clipPlanes.clipNear());
316 const QMatrix4x4 cameraGlobalTransform = data.getGlobalTransform(inCamera);
317 QMatrix4x4 viewProjection(Qt::Uninitialized);
318 inCamera.calculateViewProjectionMatrix(cameraGlobalTransform, viewProjection);
319 const QSSGBoxPoints frustum = computeFrustumBounds(viewProjection);
320 const QSSGBoxPoints frustumUntransformed = lockShadowmapTexels ? computeFrustumBounds(inCamera.projection) : QSSGBoxPoints();
324 const auto calcFrustumRadius = [&](
float t0,
float t1) ->
float {
325 const QSSGBoxPoints pts = sliceFrustum(frustumUntransformed, t0 * farScale, t1 * farScale);
327 QVector3D center = QVector3D(0.f, 0.f, 0.f);
328 for (QVector3D point : pts) {
331 center = center * 0.125f;
333 float radiusSquared = 0;
334 for (QVector3D point : pts) {
335 radiusSquared = qMax(radiusSquared, (point - center).lengthSquared());
338 return std::sqrt(radiusSquared);
341 const auto computeSplitRanges = [inLight](
const QVarLengthArray<
float, 3> &splits) -> QVarLengthArray<QPair<
float,
float>, 4> {
342 QVarLengthArray<QPair<
float,
float>, 4> ranges;
343 const float csmBlendRatio = inLight->m_csmBlendRatio;
345 for (qsizetype i = 0; i < splits.length(); i++) {
346 const float tI = qBound(qMin(t0 + 0.01f, 1.0f), splits[i], 1.0f);
347 ranges.emplace_back(t0, qMin(1.0f, tI + csmBlendRatio));
350 ranges.emplace_back(t0, 1.0f);
354 const auto computeFrustums = [&](
const QVarLengthArray<
float, 3> &splits) {
355 for (
const auto &range : computeSplitRanges(splits)) {
356 const float frustumRadius = lockShadowmapTexels ? calcFrustumRadius(range.first, range.second) : 0.0f;
357 auto camera = computeShadowCameraFromFrustum(lightMatrix,
365 range.first * farScale,
366 range.second * farScale,
373 drawSceneCascadeIntersection);
374 result.emplace_back(std::move(camera));
378 switch (inLight->m_csmNumSplits) {
384 computeFrustums({ inLight->m_csmSplit1 });
388 computeFrustums({ inLight->m_csmSplit1, inLight->m_csmSplit2 });
392 computeFrustums({ inLight->m_csmSplit1, inLight->m_csmSplit2, inLight->m_csmSplit3 });
434 QSSGRhiShaderPipeline *shaderPipeline,
435 QSSGRenderableImage *renderableImage,
436 QSSGRhiShaderResourceBindingList &bindings,
437 bool isCustomMaterialMeshSubset =
false)
439 static const auto imageAffectsAlpha = [](QSSGRenderableImage::Type mapType) {
440 return mapType == QSSGRenderableImage::Type::BaseColor ||
441 mapType == QSSGRenderableImage::Type::Diffuse ||
442 mapType == QSSGRenderableImage::Type::Translucency ||
443 mapType == QSSGRenderableImage::Type::Opacity;
446 while (renderableImage) {
447 const auto mapType = renderableImage->m_mapType;
448 if (imageAffectsAlpha(mapType)) {
449 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(mapType);
450 const int samplerHint =
int(mapType);
451 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
452 if (samplerBinding >= 0) {
453 QRhiTexture *texture = renderableImage->m_texture.m_texture;
454 if (samplerBinding >= 0 && texture) {
455 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
456 QRhiSampler *sampler = rhiCtx->sampler({ QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
457 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
458 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
459 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
460 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
461 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
463 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
467 renderableImage = renderableImage->m_nextImage;
470 if (isCustomMaterialMeshSubset) {
471 QVector<QShaderDescription::InOutVariable> samplerVars =
472 shaderPipeline->fragmentStage()->shader().description().combinedImageSamplers();
473 for (
const QShaderDescription::InOutVariable &var : shaderPipeline->vertexStage()->shader().description().combinedImageSamplers()) {
474 auto it = std::find_if(samplerVars.cbegin(), samplerVars.cend(),
475 [&var](
const QShaderDescription::InOutVariable &v) {
return var.binding == v.binding; });
476 if (it == samplerVars.cend())
477 samplerVars.append(var);
480 int maxSamplerBinding = -1;
481 for (
const QShaderDescription::InOutVariable &var : std::as_const(samplerVars))
482 maxSamplerBinding = qMax(maxSamplerBinding, var.binding);
491 QBitArray samplerBindingsSpecified(maxSamplerBinding + 1);
493 if (maxSamplerBinding >= 0) {
495 int customTexCount = shaderPipeline->extraTextureCount();
496 for (
int i = 0; i < customTexCount; ++i) {
497 const QSSGRhiTexture &t(shaderPipeline->extraTextureAt(i));
498 const int samplerBinding = shaderPipeline->bindingForTexture(t.name);
499 if (samplerBinding >= 0) {
500 samplerBindingsSpecified.setBit(samplerBinding);
501 QRhiSampler *sampler = rhiCtx->sampler(t.samplerDesc);
502 bindings.addTexture(samplerBinding,
503 RENDERER_VISIBILITY_ALL,
511 QRhiSampler *dummySampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
512 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
513 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
514 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
515 QRhiTexture *dummyCubeTexture = rhiCtx->dummyTexture(QRhiTexture::CubeMap, resourceUpdates);
516 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
518 for (
const QShaderDescription::InOutVariable &var : std::as_const(samplerVars)) {
519 if (!samplerBindingsSpecified.testBit(var.binding)) {
520 QRhiTexture *t = var.type == QShaderDescription::SamplerCube ? dummyCubeTexture : dummyTexture;
521 bindings.addTexture(var.binding, RENDERER_VISIBILITY_ALL, t, dummySampler);
733 QSSGRhiGraphicsPipelineState *ps,
734 const QVector2D *depthAdjust,
735 const QSSGRenderableObjectList &sortedOpaqueObjects,
736 QSSGRenderCamera &inCamera,
738 QSSGRenderTextureCubeFace cubeFace,
739 quint32 cascadeIndex)
741 QSSGShaderFeatures featureSet;
743 featureSet.set(QSSGShaderFeatures::Feature::OrthoShadowPass,
true);
745 featureSet.set(QSSGShaderFeatures::Feature::PerspectiveShadowPass,
true);
751 featureSet.set(QSSGShaderFeatures::Feature::DisableMultiView,
true);
753 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(cubeFace);
754 const auto &defaultMaterialShaderKeyProperties = inData.getDefaultMaterialPropertyTable();
755 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
757 for (
const auto &handle : sortedOpaqueObjects) {
758 QSSGRenderableObject *theObject = handle.obj;
759 QSSG_ASSERT(theObject->renderableFlags.castsShadows(),
continue);
761 QSSGShaderFeatures objectFeatureSet = featureSet;
762 const bool isOpaqueDepthPrePass = theObject->depthWriteMode == QSSGDepthDrawMode::OpaquePrePass;
763 if (isOpaqueDepthPrePass)
764 objectFeatureSet.set(QSSGShaderFeatures::Feature::OpaqueDepthPrePass,
true);
766 QSSGRhiDrawCallData *dcd =
nullptr;
767 QMatrix4x4 modelViewProjection;
768 QSSGSubsetRenderable &renderable(
static_cast<QSSGSubsetRenderable &>(*theObject));
769 if (theObject->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || theObject->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
770 const bool hasSkinning = defaultMaterialShaderKeyProperties.m_boneCount.getValue(renderable.shaderDescription) > 0;
771 modelViewProjection = hasSkinning ? pEntry->m_lightViewProjection[cascadeIndex]
772 : pEntry->m_lightViewProjection[cascadeIndex] * renderable.modelContext.globalTransform;
776 const quintptr entryIdx = cascadeIndex + cubeFaceIdx + (quintptr(renderable.subset.offset) << 3);
777 dcd = &rhiCtxD->drawCallData({ passKey, &renderable.modelContext.model, pEntry, entryIdx });
780 QSSGRhiShaderResourceBindingList bindings;
781 QSSGRhiShaderPipelinePtr shaderPipeline;
782 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*theObject));
783 if (theObject->type == QSSGSubsetRenderable::Type::DefaultMaterialMeshSubset) {
784 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
785 ps->cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
786 const bool blendParticles = defaultMaterialShaderKeyProperties.m_blendParticles.getValue(subsetRenderable.shaderDescription);
788 shaderPipeline = shadersForDefaultMaterial(ps, subsetRenderable, objectFeatureSet);
791 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
792 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
794 QSSGRenderCameraList cameras({ &inCamera });
795 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, subsetRenderable, cameras, depthAdjust, &modelViewProjection);
797 QSSGParticleRenderer::updateUniformsForParticleModel(*shaderPipeline, ubufData, &subsetRenderable.modelContext.model, subsetRenderable.subset.offset);
798 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
800 QSSGParticleRenderer::prepareParticlesForModel(*shaderPipeline, rhiCtx, bindings, &subsetRenderable.modelContext.model);
801 }
else if (theObject->type == QSSGSubsetRenderable::Type::CustomMaterialMeshSubset) {
802 const auto &material =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
803 ps->cullMode = QSSGRhiHelpers::toCullMode(material.m_cullMode);
805 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
806 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(ps, material, subsetRenderable, inData.getDefaultMaterialPropertyTable(), objectFeatureSet);
809 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
810 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
812 QSSGRenderCameraList cameras({ &inCamera });
813 customMaterialSystem.updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, material, subsetRenderable,
814 cameras, depthAdjust, &modelViewProjection);
815 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
818 if (theObject->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || theObject->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
820 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(*ps, shaderPipeline.get());
821 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
822 ia = subsetRenderable.subset.rhi.ia;
823 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
824 int instanceBufferBinding = setupInstancing(&subsetRenderable, ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
825 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
828 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
831 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
833 addNormalTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
835 if (isOpaqueDepthPrePass) {
836 addOpaqueDepthPrePassBindings(rhiCtx,
837 shaderPipeline.get(),
838 subsetRenderable.firstImage,
840 (theObject->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset));
847 const int screenTextureBinding = shaderPipeline->bindingForTexture(
"qt_screenTexture",
int(QSSGRhiSamplerBindingHints::ScreenTexture));
848 const int screenTextureArrayBinding = shaderPipeline->bindingForTexture(
"qt_screenTextureArray",
int(QSSGRhiSamplerBindingHints::ScreenTextureArray));
849 if (screenTextureBinding >= 0 || screenTextureArrayBinding >= 0) {
850 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
851 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
852 if (screenTextureBinding >= 0) {
853 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
854 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
855 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
856 bindings.addTexture(screenTextureBinding,
857 QRhiShaderResourceBinding::FragmentStage,
858 dummyTexture, sampler);
860 if (screenTextureArrayBinding >= 0) {
861 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
862 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates, QSize(64, 64), Qt::black, inData.layer.viewCount);
863 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
864 bindings.addTexture(screenTextureArrayBinding,
865 QRhiShaderResourceBinding::FragmentStage,
866 dummyTexture, sampler);
871 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
872 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
874 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
875 QRhiSampler::Nearest,
877 QRhiSampler::ClampToEdge,
878 QRhiSampler::ClampToEdge,
881 bindings.addTexture(binding,
882 QRhiShaderResourceBinding::VertexStage,
889 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
890 if (targetsTexture) {
891 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
893 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
894 QRhiSampler::Nearest,
896 QRhiSampler::ClampToEdge,
897 QRhiSampler::ClampToEdge,
898 QRhiSampler::ClampToEdge
900 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
904 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
905 subsetRenderable.rhiRenderData.shadowPass.pipeline = rhiCtxD->pipeline(*ps, pEntry->m_rhiRenderPassDesc[cascadeIndex], srb);
906 subsetRenderable.rhiRenderData.shadowPass.srb[cubeFaceIdx] = srb;
941 QRhiRenderPassDescriptor *renderPassDescriptor,
942 QSSGRhiGraphicsPipelineState *ps,
943 QSSGShaderFeatures featureSet,
946 QSSGRenderCamera *alteredCamera,
947 QMatrix4x4 *alteredModelViewProjection,
948 QSSGRenderTextureCubeFace cubeFace,
952 const auto &defaultMaterialShaderKeyProperties = inData.getDefaultMaterialPropertyTable();
954 switch (inObject.type) {
955 case QSSGRenderableObject::Type::DefaultMaterialMeshSubset:
957 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(inObject));
959 if ((cubeFace == QSSGRenderTextureCubeFaceNone) && subsetRenderable.reflectionProbeIndex >= 0 && subsetRenderable.renderableFlags.testFlag(QSSGRenderableObjectFlag::ReceivesReflections))
960 featureSet.set(QSSGShaderFeatures::Feature::ReflectionProbe,
true);
962 if ((cubeFace != QSSGRenderTextureCubeFaceNone)) {
964 featureSet.disableTonemapping();
967 if (subsetRenderable.renderableFlags.rendersWithLightmap())
968 featureSet.set(QSSGShaderFeatures::Feature::Lightmap,
true);
970 const auto &shaderPipeline = shadersForDefaultMaterial(ps, subsetRenderable, featureSet);
971 if (shaderPipeline) {
979 QSSGRhiShaderResourceBindingList bindings;
980 const auto &modelNode = subsetRenderable.modelContext.model;
981 const bool blendParticles = defaultMaterialShaderKeyProperties.m_blendParticles.getValue(subsetRenderable.shaderDescription);
988 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(cubeFace);
989 const quintptr entryIdx = quintptr(cubeFace != QSSGRenderTextureCubeFaceNone) * (cubeFaceIdx + (quintptr(subsetRenderable.subset.offset) << 3));
991 const auto entryPartA =
reinterpret_cast<quintptr>(&subsetRenderable.material);
992 const auto entryPartB =
reinterpret_cast<quintptr>(entry);
993 const void *entryId =
reinterpret_cast<
const void *>(entryPartA ^ entryPartB);
995 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
996 QSSGRhiDrawCallData &dcd = rhiCtxD->drawCallData({ passKey, &modelNode, entryId, entryIdx });
998 shaderPipeline->ensureCombinedUniformBuffer(&dcd.ubuf);
999 char *ubufData = dcd.ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
1000 if (alteredCamera) {
1001 Q_ASSERT(alteredModelViewProjection);
1002 QSSGRenderCameraList cameras({ alteredCamera });
1003 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, subsetRenderable, cameras,
nullptr, alteredModelViewProjection);
1005 Q_ASSERT(!alteredModelViewProjection);
1006 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
1010 QSSGParticleRenderer::updateUniformsForParticleModel(*shaderPipeline, ubufData, &subsetRenderable.modelContext.model, subsetRenderable.subset.offset);
1011 dcd.ubuf->endFullDynamicBufferUpdateForCurrentFrame();
1014 QSSGParticleRenderer::prepareParticlesForModel(*shaderPipeline, rhiCtx, bindings, &subsetRenderable.modelContext.model);
1017 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
1018 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
1020 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
1021 QRhiSampler::Nearest,
1023 QRhiSampler::ClampToEdge,
1024 QRhiSampler::ClampToEdge,
1027 bindings.addTexture(binding,
1028 QRhiShaderResourceBinding::VertexStage,
1034 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
1035 if (targetsTexture) {
1036 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
1038 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
1039 QRhiSampler::Nearest,
1041 QRhiSampler::ClampToEdge,
1042 QRhiSampler::ClampToEdge,
1043 QRhiSampler::ClampToEdge
1045 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
1049 ps->samples = samples;
1050 ps->viewCount = viewCount;
1052 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
1053 ps->cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
1054 if (!oit || (oit && inData.layer.oitMethod == QSSGRenderLayer::OITMethod::None))
1055 fillTargetBlend(&ps->targetBlend[0], material.blendMode);
1057 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
1059 ia = subsetRenderable.subset.rhi.ia;
1060 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
1061 QVector3D cameraDirection = cameraDatas[0].direction;
1062 QVector3D cameraPosition = cameraDatas[0].position;
1063 if (alteredCamera) {
1064 const QMatrix4x4 camGlobalTranform = inData.getGlobalTransform(*alteredCamera);
1065 cameraDirection = QSSGRenderNode::getScalingCorrectDirection(camGlobalTranform);
1066 cameraPosition = QSSGRenderNode::getGlobalPos(camGlobalTranform);
1068 int instanceBufferBinding = setupInstancing(&subsetRenderable, ps, rhiCtx, cameraDirection, cameraPosition);
1069 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
1071 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd.ubuf, 0, shaderPipeline->ub0Size());
1073 if (shaderPipeline->isLightingEnabled()) {
1074 bindings.addUniformBuffer(1, RENDERER_VISIBILITY_ALL, dcd.ubuf,
1075 shaderPipeline->ub0LightDataOffset(),
1076 sizeof(QSSGShaderLightsUniformData));
1077 bindings.addUniformBuffer(2, RENDERER_VISIBILITY_ALL, dcd.ubuf,
1078 shaderPipeline->ub0DirectionalLightDataOffset(),
1079 sizeof(QSSGShaderDirectionalLightsUniformData));
1084 QSSGRenderableImage *renderableImage = subsetRenderable.firstImage;
1085 while (renderableImage) {
1086 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(renderableImage->m_mapType);
1087 const int samplerHint =
int(renderableImage->m_mapType);
1088 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
1089 if (samplerBinding >= 0) {
1090 QRhiTexture *texture = renderableImage->m_texture.m_texture;
1091 if (samplerBinding >= 0 && texture) {
1092 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
1093 QSSGRhiSamplerDescription samplerDesc = {
1094 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
1095 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
1096 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
1097 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
1098 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
1099 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
1101 rhiCtx->checkAndAdjustForNPoT(texture, &samplerDesc);
1102 QRhiSampler *sampler = rhiCtx->sampler(samplerDesc);
1103 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
1106 renderableImage = renderableImage->m_nextImage;
1109 if (shaderPipeline->isLightingEnabled()) {
1111 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_texture"); binding >= 0) {
1112 QRhiTexture *texture = shaderPipeline->shadowMapAtlasTexture();
1115 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
1116 texture = rhiCtx->dummyTexture({ }, resourceUpdates, QSize(1, 1), Qt::black, 2);
1117 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
1120 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
1121 QRhiSampler::Linear,
1123 QRhiSampler::ClampToEdge,
1124 QRhiSampler::ClampToEdge,
1125 QRhiSampler::Repeat });
1127 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
1131 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture"); binding >= 0) {
1132 if (
auto shadowMapBlueNoise = shaderPipeline->shadowMapBlueNoiseTexture()) {
1133 int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture");
1135 QRhiTexture *texture = shadowMapBlueNoise;
1136 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
1137 QRhiSampler::Linear,
1139 QRhiSampler::Repeat,
1140 QRhiSampler::Repeat,
1141 QRhiSampler::Repeat });
1142 Q_ASSERT(texture && sampler);
1143 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
1146 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
1147 QRhiTexture *texture = rhiCtx->dummyTexture({}, resourceUpdates);
1148 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
1149 QRhiSampler::Linear,
1151 QRhiSampler::Repeat,
1152 QRhiSampler::Repeat,
1153 QRhiSampler::Repeat });
1154 Q_ASSERT(texture && sampler);
1155 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
1156 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
1163 if (featureSet.isSet(QSSGShaderFeatures::Feature::ReflectionProbe)) {
1164 int reflectionSampler = shaderPipeline->bindingForTexture(
"qt_reflectionMap");
1165 QRhiTexture* reflectionTexture = inData.getReflectionMapManager()->reflectionMapEntry(subsetRenderable.reflectionProbeIndex)->m_rhiPrefilteredCube;
1166 const auto mipMapFilter = reflectionTexture && reflectionTexture->flags().testFlag(QRhiTexture::Flag::MipMapped)
1167 ? QRhiSampler::Linear
1168 : QRhiSampler::None;
1169 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
1170 QRhiSampler::Linear,
1172 QRhiSampler::ClampToEdge,
1173 QRhiSampler::ClampToEdge,
1174 QRhiSampler::Repeat });
1175 if (reflectionSampler >= 0 && reflectionTexture)
1176 bindings.addTexture(reflectionSampler, QRhiShaderResourceBinding::FragmentStage, reflectionTexture, sampler);
1177 }
else if (shaderPipeline->lightProbeTexture()) {
1178 int binding = shaderPipeline->bindingForTexture(
"qt_lightProbe",
int(QSSGRhiSamplerBindingHints::LightProbe));
1180 auto tiling = shaderPipeline->lightProbeTiling();
1181 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
1182 QSSGRhiHelpers::toRhi(tiling.first), QSSGRhiHelpers::toRhi(tiling.second), QRhiSampler::Repeat });
1183 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage,
1184 shaderPipeline->lightProbeTexture(), sampler);
1189 if (shaderPipeline->screenTexture()) {
1190 const int screenTextureBinding = shaderPipeline->bindingForTexture(
"qt_screenTexture",
int(QSSGRhiSamplerBindingHints::ScreenTexture));
1191 const int screenTextureArrayBinding = shaderPipeline->bindingForTexture(
"qt_screenTextureArray",
int(QSSGRhiSamplerBindingHints::ScreenTextureArray));
1192 if (screenTextureBinding >= 0 || screenTextureArrayBinding >= 0) {
1197 QRhiSampler::Filter mipFilter = shaderPipeline->screenTexture()->flags().testFlag(QRhiTexture::MipMapped)
1198 ? QRhiSampler::Linear : QRhiSampler::None;
1199 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, mipFilter,
1200 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
1201 if (screenTextureBinding >= 0) {
1202 bindings.addTexture(screenTextureBinding,
1203 QRhiShaderResourceBinding::FragmentStage,
1204 shaderPipeline->screenTexture(), sampler);
1206 if (screenTextureArrayBinding >= 0) {
1207 bindings.addTexture(screenTextureArrayBinding,
1208 QRhiShaderResourceBinding::FragmentStage,
1209 shaderPipeline->screenTexture(), sampler);
1214 if (shaderPipeline->lightmapTexture()) {
1215 int binding = shaderPipeline->bindingForTexture(
"qt_lightmap",
int(QSSGRhiSamplerBindingHints::LightmapTexture));
1217 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
1218 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
1219 bindings.addTexture(binding,
1220 QRhiShaderResourceBinding::FragmentStage,
1221 shaderPipeline->lightmapTexture(), sampler);
1227 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
1230 addNormalTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
1232 if (oit && inData.layer.oitMethod == QSSGRenderLayer::OITMethod::LinkedList)
1242 QRhiShaderResourceBindings *&srb = dcd.srb;
1243 bool srbChanged =
false;
1244 if (!srb || bindings != dcd.bindings) {
1245 srb = rhiCtxD->srb(bindings);
1246 rhiCtxD->releaseCachedSrb(dcd.bindings);
1247 dcd.bindings = bindings;
1251 if (cubeFace != QSSGRenderTextureCubeFaceNone)
1252 subsetRenderable.rhiRenderData.reflectionPass.srb[cubeFaceIdx] = srb;
1254 subsetRenderable.rhiRenderData.mainPass.srb = srb;
1256 const auto pipelineKey = QSSGGraphicsPipelineStateKey::create(*ps, renderPassDescriptor, srb);
1259 && dcd.renderTargetDescriptionHash == pipelineKey.extra.renderTargetDescriptionHash
1260 && dcd.renderTargetDescription == pipelineKey.renderTargetDescription
1263 if (cubeFace != QSSGRenderTextureCubeFaceNone)
1264 subsetRenderable.rhiRenderData.reflectionPass.pipeline = dcd.pipeline;
1266 subsetRenderable.rhiRenderData.mainPass.pipeline = dcd.pipeline;
1268 if (cubeFace != QSSGRenderTextureCubeFaceNone) {
1269 subsetRenderable.rhiRenderData.reflectionPass.pipeline = rhiCtxD->pipeline(pipelineKey,
1270 renderPassDescriptor,
1272 dcd.pipeline = subsetRenderable.rhiRenderData.reflectionPass.pipeline;
1274 subsetRenderable.rhiRenderData.mainPass.pipeline = rhiCtxD->pipeline(pipelineKey,
1275 renderPassDescriptor,
1277 dcd.pipeline = subsetRenderable.rhiRenderData.mainPass.pipeline;
1279 dcd.renderTargetDescriptionHash = pipelineKey.extra.renderTargetDescriptionHash;
1280 dcd.renderTargetDescription = pipelineKey.renderTargetDescription;
1286 case QSSGRenderableObject::Type::CustomMaterialMeshSubset:
1288 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(inObject));
1289 const QSSGRenderCustomMaterial &material =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
1290 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
1292 featureSet.set(QSSGShaderFeatures::Feature::LightProbe, inData.layer.lightProbe || material.m_iblProbe);
1294 if ((cubeFace == QSSGRenderTextureCubeFaceNone) && subsetRenderable.reflectionProbeIndex >= 0 && subsetRenderable.renderableFlags.testFlag(QSSGRenderableObjectFlag::ReceivesReflections))
1295 featureSet.set(QSSGShaderFeatures::Feature::ReflectionProbe,
true);
1297 if (cubeFace != QSSGRenderTextureCubeFaceNone) {
1299 featureSet.disableTonemapping();
1302 if (subsetRenderable.renderableFlags.rendersWithLightmap())
1303 featureSet.set(QSSGShaderFeatures::Feature::Lightmap,
true);
1305 customMaterialSystem.rhiPrepareRenderable(ps, passKey, subsetRenderable, featureSet,
1306 material, inData, renderPassDescriptor, samples, viewCount,
1307 alteredCamera, cubeFace, alteredModelViewProjection, entry, oit);
1310 case QSSGRenderableObject::Type::Particles:
1313 const auto &shaderPipeline = shadersForParticleMaterial(ps, particleRenderable, featureSet);
1314 if (shaderPipeline) {
1315 QSSGParticleRenderer::rhiPrepareRenderable(*shaderPipeline, passKey, rhiCtx, ps, particleRenderable, inData, renderPassDescriptor, samples, viewCount,
1316 alteredCamera, cubeFace, entry, oit);
1324 const QSSGRhiGraphicsPipelineState &state,
1326 bool *needsSetViewport,
1327 QSSGRenderTextureCubeFace cubeFace,
1328 qsizetype userPassIndex)
1330 switch (object.type) {
1331 case QSSGRenderableObject::Type::DefaultMaterialMeshSubset:
1333 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(object));
1335 QSSG_ASSERT(QSSGUserRenderPassManager::maxUserPassSlots() == std::size(subsetRenderable.rhiRenderData.userPassData),
return);
1337 QRhiGraphicsPipeline *ps = (userPassIndex >= 0 && size_t(userPassIndex) < QSSGUserRenderPassManager::maxUserPassSlots())
1338 ? subsetRenderable.rhiRenderData.userPassData[userPassIndex].pipeline : subsetRenderable.rhiRenderData.mainPass.pipeline;
1339 QRhiShaderResourceBindings *srb = (userPassIndex >= 0 && size_t(userPassIndex) < QSSGUserRenderPassManager::maxUserPassSlots())
1340 ? subsetRenderable.rhiRenderData.userPassData[userPassIndex].srb : subsetRenderable.rhiRenderData.mainPass.srb;
1342 if (cubeFace != QSSGRenderTextureCubeFaceNone) {
1343 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(cubeFace);
1344 ps = subsetRenderable.rhiRenderData.reflectionPass.pipeline;
1345 srb = subsetRenderable.rhiRenderData.reflectionPass.srb[cubeFaceIdx];
1351 QRhiBuffer *vertexBuffer = subsetRenderable.subset.rhi.vertexBuffer->buffer();
1352 QRhiBuffer *indexBuffer = subsetRenderable.subset.rhi.indexBuffer ? subsetRenderable.subset.rhi.indexBuffer->buffer() :
nullptr;
1354 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1356 cb->setGraphicsPipeline(ps);
1357 cb->setShaderResources(srb);
1359 if (*needsSetViewport) {
1360 cb->setViewport(state.viewport);
1361 if (state.flags.testFlag(QSSGRhiGraphicsPipelineState::Flag::UsesScissor))
1362 cb->setScissor(state.scissor);
1363 *needsSetViewport =
false;
1366 QRhiCommandBuffer::VertexInput vertexBuffers[2];
1367 int vertexBufferCount = 1;
1368 vertexBuffers[0] = QRhiCommandBuffer::VertexInput(vertexBuffer, 0);
1369 quint32 instances = 1;
1370 if ( subsetRenderable.modelContext.model.instancing()) {
1371 instances = subsetRenderable.modelContext.model.instanceCount();
1378 vertexBuffers[1] = QRhiCommandBuffer::VertexInput(subsetRenderable.instanceBuffer, 0);
1379 vertexBufferCount = 2;
1381 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderCall);
1382 if (state.flags.testFlag(QSSGRhiGraphicsPipelineState::Flag::UsesStencilRef))
1383 cb->setStencilRef(state.stencilRef);
1385 cb->setVertexInput(0, vertexBufferCount, vertexBuffers, indexBuffer, 0, subsetRenderable.subset.rhi.indexBuffer->indexFormat());
1386 cb->drawIndexed(subsetRenderable.subset.lodCount(subsetRenderable.subsetLevelOfDetail), instances, subsetRenderable.subset.lodOffset(subsetRenderable.subsetLevelOfDetail));
1387 QSSGRHICTX_STAT(rhiCtx, drawIndexed(subsetRenderable.subset.lodCount(subsetRenderable.subsetLevelOfDetail), instances));
1389 cb->setVertexInput(0, vertexBufferCount, vertexBuffers);
1390 cb->draw(subsetRenderable.subset.count, instances, subsetRenderable.subset.offset);
1391 QSSGRHICTX_STAT(rhiCtx, draw(subsetRenderable.subset.count, instances));
1393 Q_QUICK3D_PROFILE_END_WITH_IDS(QQuick3DProfiler::Quick3DRenderCall, (subsetRenderable.subset.count | quint64(instances) << 32),
1394 QVector<
int>({subsetRenderable.modelContext.model.profilingId,
1395 subsetRenderable.material.profilingId}));
1398 case QSSGRenderableObject::Type::CustomMaterialMeshSubset:
1400 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(object));
1401 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
1402 customMaterialSystem.rhiRenderRenderable(rhiCtx, subsetRenderable, needsSetViewport, cubeFace, state, userPassIndex);
1405 case QSSGRenderableObject::Type::Particles:
1408 QSSGParticleRenderer::rhiRenderRenderable(rhiCtx, renderable, needsSetViewport, cubeFace, state);
1433 QSSGPassKey passKey,
1434 QSSGRhiGraphicsPipelineState &ps,
1435 QSSGRenderShadowMap &shadowMapManager,
1436 const QSSGRenderCamera &camera,
1437 QSSGRenderCamera *debugCamera,
1439 const QSSGRenderableObjectList &sortedOpaqueObjects,
1441 const QSSGBounds3 &castingObjectsBox,
1442 const QSSGBounds3 &receivingObjectsBox)
1445 QSSGDebugDrawSystem *debugDrawSystem = renderer.contextInterface()->debugDrawSystem().get();
1446 const bool drawDirectionalLightShadowBoxes = layerData.layer.drawDirectionalLightShadowBoxes;
1447 const bool drawPointLightShadowBoxes = layerData.layer.drawPointLightShadowBoxes;
1448 const bool drawShadowCastingBounds = layerData.layer.drawShadowCastingBounds;
1449 const bool drawShadowReceivingBounds = layerData.layer.drawShadowReceivingBounds;
1450 const bool drawCascades = layerData.layer.drawCascades;
1451 const bool drawSceneCascadeIntersection = layerData.layer.drawSceneCascadeIntersection;
1452 const bool disableShadowCameraUpdate = layerData.layer.disableShadowCameraUpdate;
1453 const bool drawCulledObjects = layerData.layer.drawCulledObjects;
1454 QVector<
bool> debugIsObjectCulled = drawCulledObjects ? QVector<
bool>(sortedOpaqueObjects.size(),
true) : QVector<
bool>();
1456 static const auto rhiRenderOneShadowMap = [](QSSGRhiContext *rhiCtx,
1457 QSSGRhiGraphicsPipelineState *ps,
1458 const QSSGRenderableObjectList &sortedOpaqueObjects,
1460 const QSSGBounds3 cameraBounds,
1461 QVector<
bool> &debugIsObjectCulled,
1462 bool drawCulledObjects) {
1463 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1464 bool needsSetViewport =
true;
1466 for (
int i = 0, n = sortedOpaqueObjects.size(); i < n; ++i) {
1471 if (theObject->globalBoundsInstancing.isFinite() && theObject->globalBounds.isFinite()) {
1472 const QSSGBounds3 &globalBounds = !theObject->globalBoundsInstancing.isEmpty() ? theObject->globalBoundsInstancing
1473 : theObject->globalBounds;
1474 if (!globalBounds.isEmpty() && !cameraBounds.intersects(globalBounds)) {
1479 if (Q_UNLIKELY(drawCulledObjects))
1480 debugIsObjectCulled[i] =
false;
1483 if (theObject->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || theObject->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
1484 QSSGSubsetRenderable *renderable(
static_cast<QSSGSubsetRenderable *>(theObject));
1486 QRhiBuffer *vertexBuffer = renderable->subset.rhi.vertexBuffer->buffer();
1487 QRhiBuffer *indexBuffer = renderable->subset.rhi.indexBuffer
1488 ? renderable->subset.rhi.indexBuffer->buffer()
1492 if (!renderable->rhiRenderData.shadowPass.pipeline)
1495 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderCall);
1497 cb->setGraphicsPipeline(renderable->rhiRenderData.shadowPass.pipeline);
1499 QRhiShaderResourceBindings *srb = renderable->rhiRenderData.shadowPass.srb[cubeFace];
1500 cb->setShaderResources(srb);
1502 if (needsSetViewport) {
1503 cb->setViewport(ps->viewport);
1504 needsSetViewport =
false;
1507 QRhiCommandBuffer::VertexInput vertexBuffers[2];
1508 int vertexBufferCount = 1;
1509 vertexBuffers[0] = QRhiCommandBuffer::VertexInput(vertexBuffer, 0);
1510 quint32 instances = 1;
1511 if (renderable->modelContext.model.instancing()) {
1512 instances = renderable->modelContext.model.instanceCount();
1513 vertexBuffers[1] = QRhiCommandBuffer::VertexInput(renderable->instanceBuffer, 0);
1514 vertexBufferCount = 2;
1517 cb->setVertexInput(0, vertexBufferCount, vertexBuffers, indexBuffer, 0, renderable->subset.rhi.indexBuffer->indexFormat());
1518 cb->drawIndexed(renderable->subset.lodCount(renderable->subsetLevelOfDetail), instances, renderable->subset.lodOffset(renderable->subsetLevelOfDetail));
1519 QSSGRHICTX_STAT(rhiCtx, drawIndexed(renderable->subset.lodCount(renderable->subsetLevelOfDetail), instances));
1521 cb->setVertexInput(0, vertexBufferCount, vertexBuffers);
1522 cb->draw(renderable->subset.count, instances, renderable->subset.offset);
1523 QSSGRHICTX_STAT(rhiCtx, draw(renderable->subset.count, instances));
1525 Q_QUICK3D_PROFILE_END_WITH_IDS(QQuick3DProfiler::Quick3DRenderCall, (renderable->subset.count | quint64(instances) << 32),
1526 QVector<
int>({renderable->modelContext.model.profilingId,
1527 renderable->material.profilingId}));
1532 static const auto rhiClearShadowMap = [](
QSSGRenderer &renderer, QSSGRenderShadowMap &shadowMapManager, QSSGRhiContext *rhiCtx, QSSGRhiGraphicsPipelineState *ps, QRhiRenderPassDescriptor *renderPassDesc) {
1533 auto clearShadowMapShaderPipeline = renderer.contextInterface()->shaderCache()->getBuiltInRhiShaders().getRhiClearShadowMapShader();
1534 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(*ps, clearShadowMapShaderPipeline.get());
1537 ps->flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled,
false);
1538 ps->flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled,
false);
1539 renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx, ps, shadowMapManager.shadowClearSrb(), renderPassDesc, {});
1541 ps->flags |= { QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled };
1544 QRhi *rhi = rhiCtx->rhi();
1545 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1549 QVector2D depthAdjust;
1550 if (rhi->isClipDepthZeroToOne()) {
1552 depthAdjust[0] = 0.0f;
1553 depthAdjust[1] = 1.0f;
1556 depthAdjust[0] = 1.0f;
1557 depthAdjust[1] = 0.5f;
1560 if (drawShadowCastingBounds)
1562 if (drawShadowReceivingBounds)
1566 const QSize atlasTextureSize = shadowMapManager.shadowMapAtlasTexture()->pixelSize();
1568 renderer.rhiQuadRenderer()->prepareQuad(rhiCtx,
nullptr);
1569 for (
int i = 0, ie = globalLights.size(); i != ie; ++i) {
1570 if (!globalLights[i].shadows || globalLights[i].light->m_fullyBaked)
1577 const auto &light = globalLights[i].light;
1579 if (!shadowMapManager.shadowMapAtlasTexture())
1582 if (light->type == QSSGRenderLight::Type::DirectionalLight || light->type == QSSGRenderLight::Type::SpotLight) {
1583 const QSize size = atlasTextureSize * pEntry->m_atlasInfo[0].uvScale;
1587 if (!disableShadowCameraUpdate && debugCamera) {
1588 debugCamera->clipPlanes = camera.clipPlanes;
1589 debugCamera->projection = camera.projection;
1593 debugCamera->localTransform = layerData.getGlobalTransform(camera);
1596 QVarLengthArray<std::unique_ptr<QSSGRenderCamera>, 4> cascades;
1597 if (light->type == QSSGRenderLight::Type::DirectionalLight) {
1598 const float pcfRadius = light->m_softShadowQuality == QSSGRenderLight::SoftShadowQuality::Hard ? 0.f : light->m_pcfFactor;
1599 const float clipNear = camera.clipPlanes.clipNear();
1600 const float clipFar = qMin(light->m_shadowMapFar, camera.clipPlanes.clipFar());
1601 const float clipRange = clipFar - clipNear;
1602 cascades = setupCascadingCamerasForShadowMap(layerData,
1603 disableShadowCameraUpdate ? *debugCamera : camera,
1610 receivingObjectsBox,
1611 light->m_lockShadowmapTexels,
1614 drawSceneCascadeIntersection);
1617 pEntry->m_csmSplits[0] = clipNear + clipRange * (light->m_csmNumSplits > 0 ? light->m_csmSplit1 : 1.0f);
1618 pEntry->m_csmSplits[1] = clipNear + clipRange * (light->m_csmNumSplits > 1 ? light->m_csmSplit2 : 1.0f);
1619 pEntry->m_csmSplits[2] = clipNear + clipRange * (light->m_csmNumSplits > 2 ? light->m_csmSplit3 : 1.0f);
1620 pEntry->m_csmSplits[3] = clipNear + clipRange * 1.0f;
1621 pEntry->m_shadowMapFar = clipFar;
1622 }
else if (light->type == QSSGRenderLight::Type::SpotLight) {
1623 auto spotlightCamera =
std::make_unique<QSSGRenderCamera>(QSSGRenderCamera::Type::PerspectiveCamera);
1624 spotlightCamera->fov = QSSGRenderCamera::FieldOfView::fromDegrees(light->m_coneAngle * 2.0f);
1625 spotlightCamera->clipPlanes = { 1.0f, light->m_shadowMapFar };
1626 const QMatrix4x4 lightGlobalTransform = layerData.getGlobalTransform(*light);
1627 const QVector3D lightDir = QSSGRenderNode::getDirection(lightGlobalTransform);
1628 const QVector3D lightPos = QSSGRenderNode::getGlobalPos(lightGlobalTransform) - lightDir * spotlightCamera->clipPlanes.clipNear();
1629 const QVector3D lightPivot = light->pivot;
1630 const QVector3D forward = lightDir.normalized();
1631 const QVector3D right = qFuzzyCompare(qAbs(forward.y()), 1.0f)
1632 ? QVector3D::crossProduct(forward, QVector3D(1, 0, 0)).normalized()
1633 : QVector3D::crossProduct(forward, QVector3D(0, 1, 0)).normalized();
1634 const QVector3D up = QVector3D::crossProduct(right, forward).normalized();
1635 spotlightCamera->localTransform = QSSGRenderNode::calculateTransformMatrix(lightPos,
1636 QSSGRenderNode::initScale,
1638 QQuaternion::fromDirection(forward, up));
1639 QRectF theViewport(0.0f, 0.0f, (
float)light->m_shadowMapRes, (
float)light->m_shadowMapRes);
1640 QSSGRenderCamera::calculateProjectionInternal(*spotlightCamera, theViewport);
1641 cascades.push_back(
std::move(spotlightCamera));
1642 pEntry->m_shadowMapFar = light->m_shadowMapFar;
1647 memset(pEntry->m_csmActive, 0,
sizeof(pEntry->m_csmActive));
1649 QMatrix4x4 cascadeCameraGlobalTransforms(Qt::Uninitialized);
1650 const QMatrix4x4 bias = { 0.5, 0.0, 0.0, 0.5,
1653 0.0, 0.0, 0.0, 1.0 };
1655 for (
int cascadeIndex = 0; cascadeIndex < cascades.length(); cascadeIndex++) {
1656 const auto &cascadeCamera = cascades[cascadeIndex];
1660 cascadeCameraGlobalTransforms = layerData.getGlobalTransform(*cascadeCamera);
1661 pEntry->m_csmActive[cascadeIndex] = 1.f;
1662 QMatrix4x4 &viewProjection = pEntry->m_lightViewProjection[cascadeIndex];
1663 cascadeCamera->calculateViewProjectionMatrix(cascadeCameraGlobalTransforms, viewProjection);
1664 pEntry->m_lightViewProjection[cascadeIndex] = viewProjection;
1665 pEntry->m_fixedScaleBiasMatrix[cascadeIndex] = bias * viewProjection;
1666 const QMatrix4x4 inverted = viewProjection.inverted();
1667 const float x = 0.5f / (inverted * QVector4D(1, 0, 0, 0)).length();
1668 const float y = 0.5f / (inverted * QVector4D(0, 1, 0, 0)).length();
1669 const float z = 0.5f / (inverted * QVector4D(0, 0, 1, 0)).length();
1670 const QSSGBoxPoints frustumPoints = computeFrustumBounds(viewProjection);
1671 const QSSGBounds3 bounds = QSSGBounds3(frustumPoints);
1672 pEntry->m_dimensionsInverted[cascadeIndex] = QVector4D(x, y, z, 0.0f);
1673 pEntry->m_lightView = cascadeCameraGlobalTransforms.inverted();
1674 const bool isOrtho = cascadeCamera->type == QSSGRenderGraphObject::Type::OrthographicCamera;
1675 ps.viewport = calculateAtlasViewport(atlasTextureSize, pEntry->m_atlasInfo[cascadeIndex], rhi->isYUpInFramebuffer());
1676 rhiPrepareResourcesForShadowMap(rhiCtx, layerData, passKey, pEntry, &ps, &depthAdjust, sortedOpaqueObjects, *cascadeCamera, isOrtho, QSSGRenderTextureCubeFaceNone, cascadeIndex);
1679 QRhiTextureRenderTarget *rt = pEntry->m_rhiRenderTargets[cascadeIndex];
1680 cb->beginPass(rt, Qt::white, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
1681 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1682 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rt));
1683 rhiClearShadowMap(renderer, shadowMapManager, rhiCtx, &ps, rt->renderPassDescriptor());
1684 rhiRenderOneShadowMap(rhiCtx, &ps, sortedOpaqueObjects, 0, bounds, debugIsObjectCulled, drawCulledObjects);
1686 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1688 if (drawDirectionalLightShadowBoxes) {
1692 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"shadow_map"));
1694 const QSize size = atlasTextureSize * pEntry->m_atlasInfo[0].uvScale;
1695 ps.viewport = QRhiViewport(0, 0,
float(size.width()),
float(size.height()));
1697 QSSGRenderCamera theCameras[6] { QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1698 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1699 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1700 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1701 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1702 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera} };
1703 const float shadowMapFar = qMax<
float>(2.0f, light->m_shadowMapFar);
1704 setupCubeShadowCameras(layerData, light, shadowMapFar, theCameras);
1705 pEntry->m_lightView = QMatrix4x4();
1706 pEntry->m_shadowMapFar = shadowMapFar;
1708 const bool swapYFaces = !rhi->isYUpInFramebuffer();
1709 QMatrix4x4 cameraGlobalTransform(Qt::Uninitialized);
1710 for (
const auto face : QSSGRenderTextureCubeFaces) {
1711 cameraGlobalTransform = layerData.getGlobalTransform(theCameras[quint8(face)]);
1712 theCameras[quint8(face)].calculateViewProjectionMatrix(cameraGlobalTransform, pEntry->m_lightViewProjection[0]);
1713 pEntry->m_lightCubeView[quint8(face)] = cameraGlobalTransform.inverted();
1715 rhiPrepareResourcesForShadowMap(rhiCtx,
1721 sortedOpaqueObjects,
1722 theCameras[quint8(face)],
1729 const QVector3D center = QSSGRenderNode::getGlobalPos(layerData.getGlobalTransform(*light));
1730 const QSSGBounds3 bounds = QSSGBounds3(center - QVector3D(shadowMapFar, shadowMapFar, shadowMapFar),
1731 center + QVector3D(shadowMapFar, shadowMapFar, shadowMapFar));
1733 for (
const auto face : QSSGRenderTextureCubeFaces) {
1737 QSSGRenderTextureCubeFace outFace = face;
1755 if (outFace == QSSGRenderTextureCubeFace::PosY)
1756 outFace = QSSGRenderTextureCubeFace::NegY;
1757 else if (outFace == QSSGRenderTextureCubeFace::NegY)
1758 outFace = QSSGRenderTextureCubeFace::PosY;
1760 QRhiTextureRenderTarget *rt = pEntry->m_rhiRenderTargetCube[quint8(outFace)];
1761 cb->beginPass(rt, Qt::white, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
1762 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rt));
1763 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1764 rhiRenderOneShadowMap(rhiCtx, &ps, sortedOpaqueObjects, quint8(face), bounds, debugIsObjectCulled, drawCulledObjects);
1766 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1767 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QSSG_RENDERPASS_NAME(
"shadow_cube", 0, outFace));
1774 QRhiTextureRenderTarget *rtFront = pEntry->m_rhiRenderTargets[0];
1775 QRhiRenderPassDescriptor *frontDesc = pEntry->m_rhiRenderPassDesc[0];
1776 auto atlasShaderPipeline = renderer.contextInterface()->shaderCache()->getBuiltInRhiShaders().getRhiCubeMapToAtlasShader();
1777 ps.viewport = calculateAtlasViewport(atlasTextureSize, pEntry->m_atlasInfo[0], rhi->isYUpInFramebuffer());
1778 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, atlasShaderPipeline.get());
1779 QRhiShaderResourceBindings *srb = pEntry->m_cubeToAtlasFrontSrb;
1780 cb->beginPass(rtFront, Qt::white, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
1781 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rtFront));
1782 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1784 renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx, &ps, srb, frontDesc, QSSGRhiQuadRenderer::UvCoords);
1787 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1788 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QSSG_RENDERPASS_NAME(
"shadow_atlas", 6, 0));
1791 QRhiTextureRenderTarget *rtBack = pEntry->m_rhiRenderTargets[1];
1792 QRhiRenderPassDescriptor *backDesc = pEntry->m_rhiRenderPassDesc[1];
1793 srb = pEntry->m_cubeToAtlasBackSrb;
1794 ps.viewport = calculateAtlasViewport(atlasTextureSize, pEntry->m_atlasInfo[1], rhi->isYUpInFramebuffer());
1795 cb->beginPass(rtBack, Qt::white, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
1796 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rtBack));
1797 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1799 renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx, &ps, srb, backDesc, QSSGRhiQuadRenderer::UvCoords);
1802 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1803 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QSSG_RENDERPASS_NAME(
"shadow_atlas", 7, 0));
1807 ps = layerData.getPipelineState();
1808 ps.flags |= { QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled };
1810 ps.slopeScaledDepthBias = 1.5f;
1812 if (drawPointLightShadowBoxes) {
1818 if (Q_UNLIKELY(drawCulledObjects)) {
1819 for (
int i = 0, n = sortedOpaqueObjects.size(); i < n; ++i) {
1821 const QSSGBounds3 &globalBounds = !theObject->globalBoundsInstancing.isEmpty() ? theObject->globalBoundsInstancing
1822 : theObject->globalBounds;
1823 const QColor color = debugIsObjectCulled[i] ? QColorConstants::Red : QColorConstants::Green;
1830 QSSGPassKey passKey,
1832 QSSGRhiGraphicsPipelineState *ps,
1833 QSSGRenderReflectionMap &reflectionMapManager,
1834 const QVector<QSSGRenderReflectionProbe *> &reflectionProbes,
1835 const QSSGRenderableObjectList &reflectionPassObjects,
1838 QRhi *rhi = rhiCtx->rhi();
1839 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1841 const bool renderSkybox = (inData.layer.background == QSSGRenderLayer::Background::SkyBox ||
1842 inData.layer.background == QSSGRenderLayer::Background::SkyBoxCubeMap)
1843 && rhiCtx->rhi()->isFeatureSupported(QRhi::TexelFetch);
1845 for (
int i = 0, ie = reflectionProbes.size(); i != ie; ++i) {
1850 if (!pEntry->m_needsRender)
1853 if (reflectionProbes[i]->refreshMode == QSSGRenderReflectionProbe::ReflectionRefreshMode::FirstFrame && pEntry->m_rendered)
1856 if (reflectionProbes[i]->texture)
1859 Q_ASSERT(pEntry->m_rhiDepthStencil);
1860 Q_ASSERT(pEntry->m_rhiCube);
1862 const QSize size = pEntry->m_rhiCube->pixelSize();
1863 ps->viewport = QRhiViewport(0, 0,
float(size.width()),
float(size.height()));
1865 QSSGRenderCamera theCameras[6] { QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1866 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1867 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1868 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1869 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1870 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera} };
1871 setupCubeReflectionCameras(inData, reflectionProbes[i], theCameras);
1872 const bool swapYFaces = !rhi->isYUpInFramebuffer();
1873 QMatrix4x4 cameraGlobalTransform(Qt::Uninitialized);
1874 for (
const auto face : QSSGRenderTextureCubeFaces) {
1875 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(face);
1876 cameraGlobalTransform = inData.getGlobalTransform(theCameras[cubeFaceIdx]);
1877 theCameras[cubeFaceIdx].calculateViewProjectionMatrix(cameraGlobalTransform, pEntry->m_viewProjection);
1879 rhiPrepareResourcesForReflectionMap(rhiCtx, passKey, inData, pEntry, ps,
1880 reflectionPassObjects, theCameras[cubeFaceIdx], renderer, face);
1882 QRhiRenderPassDescriptor *renderPassDesc =
nullptr;
1883 for (
auto face : QSSGRenderTextureCubeFaces) {
1884 if (pEntry->m_timeSlicing == QSSGRenderReflectionProbe::ReflectionTimeSlicing::IndividualFaces)
1885 face = pEntry->m_timeSliceFace;
1887 QSSGRenderTextureCubeFace outFace = face;
1891 if (outFace == QSSGRenderTextureCubeFace::PosY)
1892 outFace = QSSGRenderTextureCubeFace::NegY;
1893 else if (outFace == QSSGRenderTextureCubeFace::NegY)
1894 outFace = QSSGRenderTextureCubeFace::PosY;
1896 QRhiTextureRenderTarget *rt = pEntry->m_rhiRenderTargets[quint8(outFace)];
1897 cb->beginPass(rt, reflectionProbes[i]->clearColor, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
1898 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rt));
1899 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1901 if (renderSkybox && pEntry->m_skyBoxSrbs[quint8(face)]) {
1902 const auto &shaderCache = renderer.contextInterface()->shaderCache();
1903 const bool isSkyBox = inData.layer.background == QSSGRenderLayer::Background::SkyBox;
1904 const auto &shaderPipeline = isSkyBox ? shaderCache->getBuiltInRhiShaders().getRhiSkyBoxShader(QSSGRenderLayer::TonemapMode::None, inData.layer.skyBoxIsRgbe8, 1)
1905 : shaderCache->getBuiltInRhiShaders().getRhiSkyBoxCubeShader(QSSGRenderLayer::TonemapMode::None, !inData.layer.skyBoxIsSrgb, 1);
1906 Q_ASSERT(shaderPipeline);
1907 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(*ps, shaderPipeline.get());
1908 QRhiShaderResourceBindings *srb = pEntry->m_skyBoxSrbs[quint8(face)];
1909 if (!renderPassDesc)
1910 renderPassDesc = rt->newCompatibleRenderPassDescriptor();
1911 rt->setRenderPassDescriptor(renderPassDesc);
1912 isSkyBox ? renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx, ps, srb, renderPassDesc, {})
1913 : renderer.rhiCubeRenderer()->recordRenderCube(rhiCtx, ps, srb, renderPassDesc, {});
1916 bool needsSetViewport =
true;
1917 for (
const auto &handle : reflectionPassObjects)
1918 rhiRenderRenderable(rhiCtx, *ps, *handle.obj, &needsSetViewport, face);
1921 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1922 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QSSG_RENDERPASS_NAME(
"reflection_cube", 0, outFace));
1924 if (pEntry->m_timeSlicing == QSSGRenderReflectionProbe::ReflectionTimeSlicing::IndividualFaces)
1928 renderPassDesc->deleteLater();
1930 pEntry->renderMips(rhiCtx);
1932 if (pEntry->m_timeSlicing == QSSGRenderReflectionProbe::ReflectionTimeSlicing::IndividualFaces)
1933 pEntry->m_timeSliceFace = QSSGBaseTypeHelpers::next(pEntry->m_timeSliceFace);
1935 if (reflectionProbes[i]->refreshMode == QSSGRenderReflectionProbe::ReflectionRefreshMode::FirstFrame)
1936 pEntry->m_rendered =
true;
1938 reflectionProbes[i]->hasScheduledUpdate =
false;
1939 pEntry->m_needsRender =
false;
1990 QSSGPassKey passKey,
1992 QSSGRhiShaderPipeline &shaderPipeline,
1993 QSSGRhiGraphicsPipelineState &ps,
1994 const QSSGAmbientOcclusionSettings &ao,
1995 const QSSGRhiRenderableTexture &rhiAoTexture,
1996 const QSSGRhiRenderableTexture &rhiDepthTexture,
1997 const QSSGRenderCamera &camera)
1999 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
2002 if (!rhiCtx->rhi()->isFeatureSupported(QRhi::TexelFetch)) {
2003 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
2005 cb->beginPass(rhiAoTexture.rt, Qt::white, { 1.0f, 0 });
2006 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rhiAoTexture.rt));
2008 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
2012 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, &shaderPipeline);
2014 const float R2 = ao.aoDistance * ao.aoDistance * 0.16f;
2015 const QSize textureSize = rhiAoTexture.texture->pixelSize();
2016 const float rw =
float(textureSize.width());
2017 const float rh =
float(textureSize.height());
2018 const float fov = camera.fov.asVerticalFov(rw / rh).radians();
2019 const float tanHalfFovY = tanf(0.5f * fov * (rh / rw));
2020 const float invFocalLenX = tanHalfFovY * (rw / rh);
2022 const QVector4D aoProps(ao.aoStrength * 0.01f, ao.aoDistance * 0.4f, ao.aoSoftness * 0.02f, ao.aoBias);
2023 const QVector4D aoProps2(
float(ao.aoSamplerate), (ao.aoDither) ? 1.0f : 0.0f, 0.0f, 0.0f);
2024 const QVector4D aoScreenConst(1.0f / R2, rh / (2.0f * tanHalfFovY), 1.0f / rw, 1.0f / rh);
2025 const QVector4D uvToEyeConst(2.0f * invFocalLenX, -2.0f * tanHalfFovY, -invFocalLenX, tanHalfFovY);
2026 const QVector2D cameraProps = camera.clipPlanes;
2035 const int UBUF_SIZE = 72;
2036 QSSGRhiDrawCallData &dcd(rhiCtxD->drawCallData({ passKey,
nullptr,
nullptr, 0 }));
2038 dcd.ubuf = rhiCtx->rhi()->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, UBUF_SIZE);
2042 char *ubufData = dcd.ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2043 memcpy(ubufData, &aoProps, 16);
2044 memcpy(ubufData + 16, &aoProps2, 16);
2045 memcpy(ubufData + 32, &aoScreenConst, 16);
2046 memcpy(ubufData + 48, &uvToEyeConst, 16);
2047 memcpy(ubufData + 64, &cameraProps, 8);
2048 dcd.ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2050 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
2051 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
2052 QSSGRhiShaderResourceBindingList bindings;
2053 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd.ubuf);
2056 bindings.addTexture(1, QRhiShaderResourceBinding::FragmentStage, rhiDepthTexture.texture, sampler);
2057 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
2059 renderer.rhiQuadRenderer()->prepareQuad(rhiCtx,
nullptr);
2060 renderer.rhiQuadRenderer()->recordRenderQuadPass(rhiCtx, &ps, srb, rhiAoTexture.rt, {});
2208 QSSGPassKey passKey,
2209 QSSGRenderLayer &layer,
2210 QSSGRenderCameraList &cameras,
2214 uint tonemapMode = 0)
2216 QSSG_ASSERT(layer.renderData,
return);
2218 const auto *renderData = layer.renderData;
2220 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
2221 const bool cubeMapMode = layer.background == QSSGRenderLayer::Background::SkyBoxCubeMap;
2222 const QSSGRenderImageTexture lightProbeTexture =
2223 cubeMapMode ? renderer.contextInterface()->bufferManager()->loadRenderImage(layer.skyBoxCubeMap, QSSGBufferManager::MipModeDisable)
2224 : renderer.contextInterface()->bufferManager()->loadRenderImage(layer.lightProbe, QSSGBufferManager::MipModeBsdf);
2225 const bool hasValidTexture = lightProbeTexture.m_texture !=
nullptr;
2226 if (hasValidTexture) {
2227 if (cubeFace == QSSGRenderTextureCubeFaceNone)
2228 layer.skyBoxIsRgbe8 = lightProbeTexture.m_flags.isRgbe8();
2230 layer.skyBoxIsSrgb = !lightProbeTexture.m_flags.isLinear();
2232 QSSGRhiShaderResourceBindingList bindings;
2234 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
2235 QRhiSampler::Linear,
2236 cubeMapMode ? QRhiSampler::None : QRhiSampler::Linear,
2237 QRhiSampler::Repeat,
2238 QRhiSampler::ClampToEdge,
2239 QRhiSampler::Repeat });
2240 int samplerBinding = 1;
2241 const quint32 ubufSize = cameras.count() >= 2 ? 416 : 240;
2242 bindings.addTexture(samplerBinding,
2243 QRhiShaderResourceBinding::FragmentStage,
2244 lightProbeTexture.m_texture, sampler);
2246 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(cubeFace);
2247 const quintptr entryIdx = quintptr(cubeFace != QSSGRenderTextureCubeFaceNone) * cubeFaceIdx;
2248 QSSGRhiDrawCallData &dcd = rhiCtxD->drawCallData({ passKey,
nullptr, entry, entryIdx });
2250 QRhi *rhi = rhiCtx->rhi();
2252 dcd.ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, ubufSize);
2256 float adjustY = rhi->isYUpInNDC() ? 1.0f : -1.0f;
2257 const float exposure = layer.lightProbeSettings.probeExposure;
2259 const QMatrix3x3 &rotationMatrix(layer.lightProbeSettings.probeOrientation);
2262 const float blurAmountOrSrgb = cubeMapMode ? layer.skyBoxIsSrgb : layer.skyboxBlurAmount;
2263 const float maxMipLevelOrTonemapMode = cubeMapMode ?
float(tonemapMode) :
float(lightProbeTexture.m_mipmapCount - 2);
2265 const QVector4D skyboxProperties = {
2269 maxMipLevelOrTonemapMode
2272 char *ubufData = dcd.ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2273 quint32 ubufOffset = 0;
2275 memcpy(ubufData + ubufOffset, &skyboxProperties, 16);
2278 memcpy(ubufData + ubufOffset, rotationMatrix.constData(), 12);
2280 memcpy(ubufData + ubufOffset, (
char *)rotationMatrix.constData() + 12, 12);
2282 memcpy(ubufData + ubufOffset, (
char *)rotationMatrix.constData() + 24, 12);
2285 for (qsizetype viewIdx = 0; viewIdx < cameras.count(); ++viewIdx) {
2286 const QMatrix4x4 &inverseProjection = cameras[viewIdx]->projection.inverted();
2287 const QMatrix4x4 &viewMatrix = renderData->getGlobalTransform(*cameras[viewIdx]);
2288 QMatrix4x4 viewProjection(Qt::Uninitialized);
2289 cameras[viewIdx]->calculateViewProjectionWithoutTranslation(viewMatrix, 0.1f, 5.0f, viewProjection);
2291 quint32 viewDataOffset = ubufOffset;
2292 memcpy(ubufData + viewDataOffset + viewIdx * 64, viewProjection.constData(), 64);
2293 viewDataOffset += cameras.count() * 64;
2294 memcpy(ubufData + viewDataOffset + viewIdx * 64, inverseProjection.constData(), 64);
2295 viewDataOffset += cameras.count() * 64;
2296 memcpy(ubufData + viewDataOffset + viewIdx * 48, viewMatrix.constData(), 48);
2298 dcd.ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2300 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd.ubuf);
2302 if (cubeFace != QSSGRenderTextureCubeFaceNone) {
2303 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(cubeFace);
2304 entry->m_skyBoxSrbs[cubeFaceIdx] = rhiCtxD->srb(bindings);
2306 layer.skyBoxSrb = rhiCtxD->srb(bindings);
2310 renderer.rhiCubeRenderer()->prepareCube(rhiCtx,
nullptr);
2312 renderer.rhiQuadRenderer()->prepareQuad(rhiCtx,
nullptr);
2349 QSSGPassKey passKey,
2350 const QSSGRhiGraphicsPipelineState &basePipelineState,
2351 QRhiRenderPassDescriptor *rpDesc,
2353 const QSSGRenderableObjectList &sortedOpaqueObjects,
2354 const QSSGRenderableObjectList &sortedTransparentObjects,
2358 static const auto rhiPrepareDepthPassForObject = [](QSSGRhiContext *rhiCtx,
2359 QSSGPassKey passKey,
2362 QRhiRenderPassDescriptor *rpDesc,
2363 QSSGRhiGraphicsPipelineState *ps) {
2364 QSSGRhiShaderPipelinePtr shaderPipeline;
2365 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
2367 const bool isOpaqueDepthPrePass = obj->depthWriteMode == QSSGDepthDrawMode::OpaquePrePass;
2368 QSSGShaderFeatures featureSet;
2369 featureSet.set(QSSGShaderFeatures::Feature::DepthPass,
true);
2370 if (isOpaqueDepthPrePass)
2371 featureSet.set(QSSGShaderFeatures::Feature::OpaqueDepthPrePass,
true);
2373 QSSGRhiDrawCallData *dcd =
nullptr;
2374 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2375 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
2376 const void *modelNode = &subsetRenderable.modelContext.model;
2377 dcd = &rhiCtxD->drawCallData({ passKey, modelNode, &subsetRenderable.material, 0 });
2380 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset) {
2381 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
2382 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
2383 ps->cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
2385 shaderPipeline = shadersForDefaultMaterial(ps, subsetRenderable, featureSet);
2386 if (shaderPipeline) {
2387 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2388 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2389 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
2390 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2394 }
else if (obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2395 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
2397 const auto &customMaterial =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
2399 ps->cullMode = QSSGRhiHelpers::toCullMode(customMaterial.m_cullMode);
2401 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
2402 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(ps, customMaterial, subsetRenderable, inData.getDefaultMaterialPropertyTable(), featureSet);
2404 if (shaderPipeline) {
2405 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2406 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2407 customMaterialSystem.updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, customMaterial, subsetRenderable,
2408 inData.renderedCameras,
nullptr,
nullptr);
2409 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2416 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2417 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
2418 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
2419 ia = subsetRenderable.subset.rhi.ia;
2421 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
2422 int instanceBufferBinding = setupInstancing(&subsetRenderable, ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
2423 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
2425 QSSGRhiShaderResourceBindingList bindings;
2426 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
2429 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
2431 if (isOpaqueDepthPrePass) {
2432 addOpaqueDepthPrePassBindings(rhiCtx,
2433 shaderPipeline.get(),
2434 subsetRenderable.firstImage,
2436 (obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset));
2442 const int normalTextureBinding = shaderPipeline->bindingForTexture(
"qt_normalTexture",
int(QSSGRhiSamplerBindingHints::NormalTexture));
2443 if (normalTextureBinding >= 0) {
2444 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
2445 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
2446 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
2447 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
2448 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
2449 bindings.addTexture(normalTextureBinding, RENDERER_VISIBILITY_ALL, dummyTexture, sampler);
2453 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
2454 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
2456 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
2457 QRhiSampler::Nearest,
2459 QRhiSampler::ClampToEdge,
2460 QRhiSampler::ClampToEdge,
2463 bindings.addTexture(binding,
2464 QRhiShaderResourceBinding::VertexStage,
2471 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
2472 if (targetsTexture) {
2473 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
2475 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
2476 QRhiSampler::Nearest,
2478 QRhiSampler::ClampToEdge,
2479 QRhiSampler::ClampToEdge,
2480 QRhiSampler::ClampToEdge
2482 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
2486 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
2488 subsetRenderable.rhiRenderData.depthPrePass.pipeline = rhiCtxD->pipeline(*ps,
2491 subsetRenderable.rhiRenderData.depthPrePass.srb = srb;
2502 QSSGRhiGraphicsPipelineState ps = basePipelineState;
2507 ps.samples = samples;
2508 ps.viewCount = viewCount;
2509 ps.flags |= { QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled };
2510 ps.targetBlend[0].colorWrite = {};
2512 for (
const QSSGRenderableObjectHandle &handle : sortedOpaqueObjects) {
2513 if (!rhiPrepareDepthPassForObject(rhiCtx, passKey, inData, handle.obj, rpDesc, &ps))
2517 for (
const QSSGRenderableObjectHandle &handle : sortedTransparentObjects) {
2518 if (!rhiPrepareDepthPassForObject(rhiCtx, passKey, inData, handle.obj, rpDesc, &ps))
2645 QSSGPassKey passKey,
2646 const QSSGRhiGraphicsPipelineState &basePipelineState,
2647 QRhiRenderPassDescriptor *rpDesc,
2649 const QSSGRenderableObjectList &sortedOpaqueObjects)
2651 QSSGRhiGraphicsPipelineState ps = basePipelineState;
2652 ps.depthFunc = QRhiGraphicsPipeline::LessOrEqual;
2653 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
false);
2655 for (
const QSSGRenderableObjectHandle &handle : sortedOpaqueObjects) {
2656 QSSGRenderableObject *obj = handle.obj;
2657 QSSGRhiShaderPipelinePtr shaderPipeline;
2658 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
2660 QSSGShaderFeatures featureSet;
2661 featureSet.set(QSSGShaderFeatures::Feature::NormalPass,
true);
2663 QSSGRhiDrawCallData *dcd =
nullptr;
2664 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2665 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
2666 const void *modelNode = &subsetRenderable.modelContext.model;
2667 dcd = &rhiCtxD->drawCallData({ passKey, modelNode, &subsetRenderable.material, 0 });
2670 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset) {
2671 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
2672 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
2673 ps.cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
2675 shaderPipeline = shadersForDefaultMaterial(&ps, subsetRenderable, featureSet);
2676 if (shaderPipeline) {
2677 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2678 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2679 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
2680 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2682 }
else if (obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2683 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
2685 const auto &customMaterial =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
2687 ps.cullMode = QSSGRhiHelpers::toCullMode(customMaterial.m_cullMode);
2689 const auto &customMaterialSystem = subsetRenderable.renderer->contextInterface()->customMaterialSystem();
2690 shaderPipeline = customMaterialSystem->shadersForCustomMaterial(&ps, customMaterial, subsetRenderable, inData.getDefaultMaterialPropertyTable(), featureSet);
2692 if (shaderPipeline) {
2693 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2694 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2695 customMaterialSystem->updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, customMaterial, subsetRenderable,
2696 inData.renderedCameras,
nullptr,
nullptr);
2697 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2702 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2703 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
2704 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(ps);
2705 ia = subsetRenderable.subset.rhi.ia;
2707 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
2708 int instanceBufferBinding = setupInstancing(&subsetRenderable, &ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
2709 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
2711 QSSGRhiShaderResourceBindingList bindings;
2712 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
2715 QSSGRenderableImage *renderableImage = subsetRenderable.firstImage;
2716 while (renderableImage) {
2717 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(renderableImage->m_mapType);
2718 const int samplerHint =
int(renderableImage->m_mapType);
2719 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
2720 if (samplerBinding >= 0) {
2721 QRhiTexture *texture = renderableImage->m_texture.m_texture;
2722 if (samplerBinding >= 0 && texture) {
2723 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
2724 QSSGRhiSamplerDescription samplerDesc = {
2725 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
2726 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
2727 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
2728 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
2729 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
2730 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
2732 rhiCtx->checkAndAdjustForNPoT(texture, &samplerDesc);
2733 QRhiSampler *sampler = rhiCtx->sampler(samplerDesc);
2734 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
2737 renderableImage = renderableImage->m_nextImage;
2740 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
2743 const int normalTextureBinding = shaderPipeline->bindingForTexture(
"qt_normalTexture",
int(QSSGRhiSamplerBindingHints::NormalTexture));
2744 if (normalTextureBinding >= 0) {
2745 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
2746 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
2747 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
2748 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
2749 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
2750 bindings.addTexture(normalTextureBinding, RENDERER_VISIBILITY_ALL, dummyTexture, sampler);
2756 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
2757 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
2759 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
2760 QRhiSampler::Nearest,
2762 QRhiSampler::ClampToEdge,
2763 QRhiSampler::ClampToEdge,
2766 bindings.addTexture(binding,
2767 QRhiShaderResourceBinding::VertexStage,
2774 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
2775 if (targetsTexture) {
2776 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
2778 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
2779 QRhiSampler::Nearest,
2781 QRhiSampler::ClampToEdge,
2782 QRhiSampler::ClampToEdge,
2783 QRhiSampler::ClampToEdge
2785 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
2789 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
2791 subsetRenderable.rhiRenderData.normalPass.pipeline = rhiCtxD->pipeline(ps,
2794 subsetRenderable.rhiRenderData.normalPass.srb = srb;
2863 QSSGPassKey passKey,
2864 const QSSGRhiGraphicsPipelineState &basePipelineState,
2865 QRhiRenderPassDescriptor *rpDesc,
2866 QSSGRenderGraphObject *overrideMaterial,
2868 QSSGRenderableObjectList &inObjects,
2869 QSSGShaderFeatures featureSet)
2872 const qsizetype index = overrideMaterial ? inData.getUserRenderPassManager()->acquireUserPassSlot() : -1;
2877 QSSGRhiGraphicsPipelineState ps = basePipelineState;
2878 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
2880 const bool isCustomMaterial = (overrideMaterial->type == QSSGRenderGraphObject::Type::CustomMaterial);
2881 const bool isDefaultMaterial = (overrideMaterial->type == QSSGRenderGraphObject::Type::DefaultMaterial ||
2882 overrideMaterial->type == QSSGRenderGraphObject::Type::PrincipledMaterial ||
2883 overrideMaterial->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial);
2885 if (!isCustomMaterial && !isDefaultMaterial) {
2886 qDebug() <<
"Override material must be a default or custom material.";
2890 for (
const QSSGRenderableObjectHandle &handle : inObjects) {
2891 QSSGRenderableObject *obj = handle.obj;
2893 if (obj->type != QSSGRenderableObject::Type::DefaultMaterialMeshSubset &&
2894 obj->type != QSSGRenderableObject::Type::CustomMaterialMeshSubset)
2897 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
2898 const void *modelNode = &subsetRenderable.modelContext.model;
2899 QSSGRhiDrawCallData *dcd = &rhiCtxD->drawCallData({ passKey, modelNode, overrideMaterial, 0 });
2905 QSSGRenderableObjectFlags renderableFlags = subsetRenderable.renderableFlags;
2906 float opacity = subsetRenderable.opacity;
2909 const bool hasAnyLights = !subsetRenderable.lights.isEmpty();
2910 const bool anyLightHasShadows = std::any_of(subsetRenderable.lights.begin(),
2911 subsetRenderable.lights.end(),
2912 [](
const QSSGShaderLight &light) {
return light.shadows; });
2916 auto layerPrepFlags = inData.layerPrepResult.getFlags();
2918 if (isCustomMaterial) {
2919 auto &material =
static_cast<QSSGRenderCustomMaterial &>(*overrideMaterial);
2920 auto prepResult = inData.prepareCustomMaterialForRender(material, renderableFlags, opacity,
2921 false, hasAnyLights, anyLightHasShadows,
2923 subsetRenderable.shaderDescription = prepResult.materialKey;
2925 auto &material =
static_cast<QSSGRenderDefaultMaterial &>(*overrideMaterial);
2926 auto prepResult = inData.prepareDefaultMaterialForRender(material, renderableFlags, opacity,
2927 hasAnyLights, anyLightHasShadows,
2929 subsetRenderable.shaderDescription = prepResult.materialKey;
2933 QSSGRhiShaderPipelinePtr shaderPipeline;
2935 if (isCustomMaterial) {
2936 const auto &material =
static_cast<
const QSSGRenderCustomMaterial &>(*overrideMaterial);
2937 ps.cullMode = QSSGRhiHelpers::toCullMode(material.m_cullMode);
2939 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
2940 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(&ps, material, subsetRenderable,
2941 inData.getDefaultMaterialPropertyTable(), featureSet);
2942 if (shaderPipeline) {
2943 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2944 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2945 customMaterialSystem.updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, material,
2946 subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
2947 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2950 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(*overrideMaterial);
2951 ps.cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
2953 shaderPipeline = shadersForDefaultMaterial(&ps, subsetRenderable, featureSet);
2954 if (shaderPipeline) {
2955 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2956 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2957 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, subsetRenderable,
2958 inData.renderedCameras,
nullptr,
nullptr, overrideMaterial);
2959 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2963 if (!shaderPipeline)
2966 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(ps);
2967 ia = subsetRenderable.subset.rhi.ia;
2969 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
2970 int instanceBufferBinding = setupInstancing(&subsetRenderable, &ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
2971 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
2973 QSSGRhiShaderResourceBindingList bindings;
2974 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
2977 QSSGRenderableImage *renderableImage = subsetRenderable.firstImage;
2978 while (renderableImage) {
2979 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(renderableImage->m_mapType);
2980 const int samplerHint =
int(renderableImage->m_mapType);
2981 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
2982 if (samplerBinding >= 0) {
2983 QRhiTexture *texture = renderableImage->m_texture.m_texture;
2985 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
2986 QSSGRhiSamplerDescription samplerDesc = {
2987 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
2988 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
2989 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
2990 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
2991 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
2992 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
2994 rhiCtx->checkAndAdjustForNPoT(texture, &samplerDesc);
2995 QRhiSampler *sampler = rhiCtx->sampler(samplerDesc);
2996 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
2999 renderableImage = renderableImage->m_nextImage;
3002 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
3005 const int normalTextureBinding = shaderPipeline->bindingForTexture(
"qt_normalTexture",
int(QSSGRhiSamplerBindingHints::NormalTexture));
3006 if (normalTextureBinding >= 0) {
3007 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
3008 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
3009 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3010 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
3011 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3012 bindings.addTexture(normalTextureBinding, RENDERER_VISIBILITY_ALL, dummyTexture, sampler);
3016 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
3017 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
3019 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3020 QRhiSampler::Nearest,
3022 QRhiSampler::ClampToEdge,
3023 QRhiSampler::ClampToEdge,
3026 bindings.addTexture(binding,
3027 QRhiShaderResourceBinding::VertexStage,
3034 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
3035 if (targetsTexture) {
3036 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
3038 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3039 QRhiSampler::Nearest,
3041 QRhiSampler::ClampToEdge,
3042 QRhiSampler::ClampToEdge,
3043 QRhiSampler::ClampToEdge
3045 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
3050 if (shaderPipeline->isLightingEnabled()) {
3051 bindings.addUniformBuffer(1, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3052 shaderPipeline->ub0LightDataOffset(),
3053 sizeof(QSSGShaderLightsUniformData));
3054 bindings.addUniformBuffer(2, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3055 shaderPipeline->ub0DirectionalLightDataOffset(),
3056 sizeof(QSSGShaderDirectionalLightsUniformData));
3059 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_texture"); binding >= 0) {
3060 QRhiTexture *texture = shaderPipeline->shadowMapAtlasTexture();
3063 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3064 texture = rhiCtx->dummyTexture({ }, resourceUpdates, QSize(1, 1), Qt::black, 2);
3065 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3068 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3069 QRhiSampler::Linear,
3071 QRhiSampler::ClampToEdge,
3072 QRhiSampler::ClampToEdge,
3073 QRhiSampler::Repeat });
3075 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3079 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture"); binding >= 0) {
3080 QRhiTexture *texture = shaderPipeline->shadowMapBlueNoiseTexture();
3083 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3084 texture = rhiCtx->dummyTexture({ }, resourceUpdates);
3085 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3088 QRhiSampler *sampler = rhiCtx->sampler(
3089 { QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None, QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
3091 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3095 if (shaderPipeline->lightProbeTexture()) {
3096 int binding = shaderPipeline->bindingForTexture(
"qt_lightProbe",
int(QSSGRhiSamplerBindingHints::LightProbe));
3098 auto tiling = shaderPipeline->lightProbeTiling();
3099 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
3100 QSSGRhiHelpers::toRhi(tiling.first), QSSGRhiHelpers::toRhi(tiling.second), QRhiSampler::Repeat });
3101 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage,
3102 shaderPipeline->lightProbeTexture(), sampler);
3107 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
3109 QSSG_ASSERT(srb,
continue);
3110 auto &rhiPassData = subsetRenderable.rhiRenderData.userPassData[index];
3111 rhiPassData.pipeline = rhiCtxD->pipeline(ps, rpDesc, srb);
3112 rhiPassData.srb = srb;
3119 QSSGPassKey passKey,
3120 const QSSGRhiGraphicsPipelineState &basePipelineState,
3121 QRhiRenderPassDescriptor *rpDesc,
3123 QSSGRenderableObjectList &inObjects,
3124 QSSGShaderFeatures featureSet)
3126 const qsizetype index = inData.getUserRenderPassManager()->acquireUserPassSlot();
3131 QSSGRhiGraphicsPipelineState ps = basePipelineState;
3132 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
3134 for (
const QSSGRenderableObjectHandle &handle : inObjects) {
3135 QSSGRenderableObject *obj = handle.obj;
3136 QSSGRhiShaderPipelinePtr shaderPipeline;
3138 QSSGRhiDrawCallData *dcd =
nullptr;
3139 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset ||
3140 obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3141 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3142 const void *modelNode = &subsetRenderable.modelContext.model;
3143 dcd = &rhiCtxD->drawCallData({ passKey, modelNode, &subsetRenderable.material, 0 });
3146 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset) {
3147 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3148 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
3149 ps.cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
3151 shaderPipeline = shadersForDefaultMaterial(&ps, subsetRenderable, featureSet);
3152 if (shaderPipeline) {
3153 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
3154 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
3155 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, subsetRenderable,
3156 inData.renderedCameras,
nullptr,
nullptr);
3157 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
3159 }
else if (obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3160 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3161 const auto &material =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
3162 ps.cullMode = QSSGRhiHelpers::toCullMode(material.m_cullMode);
3164 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
3165 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(&ps, material, subsetRenderable,
3166 inData.getDefaultMaterialPropertyTable(), featureSet);
3167 if (shaderPipeline) {
3168 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
3169 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
3170 customMaterialSystem.updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, material,
3171 subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
3172 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
3176 if (!shaderPipeline)
3180 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset ||
3181 obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3182 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
3183 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(ps);
3184 ia = subsetRenderable.subset.rhi.ia;
3186 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
3187 int instanceBufferBinding = setupInstancing(&subsetRenderable, &ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
3188 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
3190 QSSGRhiShaderResourceBindingList bindings;
3191 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
3194 QSSGRenderableImage *renderableImage = subsetRenderable.firstImage;
3195 while (renderableImage) {
3196 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(renderableImage->m_mapType);
3197 const int samplerHint =
int(renderableImage->m_mapType);
3198 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
3199 if (samplerBinding >= 0) {
3200 QRhiTexture *texture = renderableImage->m_texture.m_texture;
3201 if (samplerBinding >= 0 && texture) {
3202 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
3203 QSSGRhiSamplerDescription samplerDesc = {
3204 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
3205 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
3206 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
3207 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
3208 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
3209 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
3211 rhiCtx->checkAndAdjustForNPoT(texture, &samplerDesc);
3212 QRhiSampler *sampler = rhiCtx->sampler(samplerDesc);
3213 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
3216 renderableImage = renderableImage->m_nextImage;
3219 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
3222 const int normalTextureBinding = shaderPipeline->bindingForTexture(
"qt_normalTexture",
int(QSSGRhiSamplerBindingHints::NormalTexture));
3223 if (normalTextureBinding >= 0) {
3224 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
3225 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
3226 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3227 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
3228 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3229 bindings.addTexture(normalTextureBinding, RENDERER_VISIBILITY_ALL, dummyTexture, sampler);
3233 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
3234 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
3236 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3237 QRhiSampler::Nearest,
3239 QRhiSampler::ClampToEdge,
3240 QRhiSampler::ClampToEdge,
3243 bindings.addTexture(binding,
3244 QRhiShaderResourceBinding::VertexStage,
3251 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
3252 if (targetsTexture) {
3253 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
3255 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3256 QRhiSampler::Nearest,
3258 QRhiSampler::ClampToEdge,
3259 QRhiSampler::ClampToEdge,
3260 QRhiSampler::ClampToEdge
3262 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
3267 if (shaderPipeline->isLightingEnabled()) {
3268 bindings.addUniformBuffer(1, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3269 shaderPipeline->ub0LightDataOffset(),
3270 sizeof(QSSGShaderLightsUniformData));
3271 bindings.addUniformBuffer(2, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3272 shaderPipeline->ub0DirectionalLightDataOffset(),
3273 sizeof(QSSGShaderDirectionalLightsUniformData));
3276 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_texture"); binding >= 0) {
3277 QRhiTexture *texture = shaderPipeline->shadowMapAtlasTexture();
3280 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3281 texture = rhiCtx->dummyTexture({ }, resourceUpdates);
3282 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3285 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3286 QRhiSampler::Linear,
3288 QRhiSampler::ClampToEdge,
3289 QRhiSampler::ClampToEdge,
3290 QRhiSampler::Repeat });
3292 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3296 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture"); binding >= 0) {
3297 if (
auto shadowMapBlueNoise = shaderPipeline->shadowMapBlueNoiseTexture()) {
3298 int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture");
3300 QRhiTexture *texture = shadowMapBlueNoise;
3301 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3302 QRhiSampler::Linear,
3304 QRhiSampler::Repeat,
3305 QRhiSampler::Repeat,
3306 QRhiSampler::Repeat });
3307 Q_ASSERT(texture && sampler);
3308 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3311 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3312 QRhiTexture *texture = rhiCtx->dummyTexture({}, resourceUpdates);
3313 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3314 QRhiSampler::Linear,
3316 QRhiSampler::Repeat,
3317 QRhiSampler::Repeat,
3318 QRhiSampler::Repeat });
3319 Q_ASSERT(texture && sampler);
3320 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3321 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3326 if (featureSet.isSet(QSSGShaderFeatures::Feature::ReflectionProbe)) {
3327 int reflectionSampler = shaderPipeline->bindingForTexture(
"qt_reflectionMap");
3328 QRhiTexture* reflectionTexture = inData.getReflectionMapManager()->reflectionMapEntry(subsetRenderable.reflectionProbeIndex)->m_rhiPrefilteredCube;
3329 const auto mipMapFilter = reflectionTexture && reflectionTexture->flags().testFlag(QRhiTexture::Flag::MipMapped)
3330 ? QRhiSampler::Linear
3331 : QRhiSampler::None;
3332 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3333 QRhiSampler::Linear,
3335 QRhiSampler::ClampToEdge,
3336 QRhiSampler::ClampToEdge,
3337 QRhiSampler::Repeat });
3338 if (reflectionSampler >= 0 && reflectionTexture)
3339 bindings.addTexture(reflectionSampler, QRhiShaderResourceBinding::FragmentStage, reflectionTexture, sampler);
3340 }
else if (shaderPipeline->lightProbeTexture()) {
3341 int binding = shaderPipeline->bindingForTexture(
"qt_lightProbe",
int(QSSGRhiSamplerBindingHints::LightProbe));
3343 auto tiling = shaderPipeline->lightProbeTiling();
3344 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
3345 QSSGRhiHelpers::toRhi(tiling.first), QSSGRhiHelpers::toRhi(tiling.second), QRhiSampler::Repeat });
3346 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage,
3347 shaderPipeline->lightProbeTexture(), sampler);
3352 if (shaderPipeline->screenTexture()) {
3353 const int screenTextureBinding = shaderPipeline->bindingForTexture(
"qt_screenTexture",
int(QSSGRhiSamplerBindingHints::ScreenTexture));
3354 const int screenTextureArrayBinding = shaderPipeline->bindingForTexture(
"qt_screenTextureArray",
int(QSSGRhiSamplerBindingHints::ScreenTextureArray));
3355 if (screenTextureBinding >= 0 || screenTextureArrayBinding >= 0) {
3356 QRhiSampler::Filter mipFilter = shaderPipeline->screenTexture()->flags().testFlag(QRhiTexture::MipMapped)
3357 ? QRhiSampler::Linear : QRhiSampler::None;
3358 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, mipFilter,
3359 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
3360 if (screenTextureBinding >= 0) {
3361 bindings.addTexture(screenTextureBinding,
3362 QRhiShaderResourceBinding::FragmentStage,
3363 shaderPipeline->screenTexture(), sampler);
3365 if (screenTextureArrayBinding >= 0) {
3366 bindings.addTexture(screenTextureArrayBinding,
3367 QRhiShaderResourceBinding::FragmentStage,
3368 shaderPipeline->screenTexture(), sampler);
3373 if (shaderPipeline->lightmapTexture()) {
3374 int binding = shaderPipeline->bindingForTexture(
"qt_lightmap",
int(QSSGRhiSamplerBindingHints::LightmapTexture));
3376 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
3377 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
3378 bindings.addTexture(binding,
3379 QRhiShaderResourceBinding::FragmentStage,
3380 shaderPipeline->lightmapTexture(), sampler);
3387 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3388 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3390 int maxSamplerBinding = -1;
3391 QVector<QShaderDescription::InOutVariable> samplerVars =
3392 shaderPipeline->fragmentStage()->shader().description().combinedImageSamplers();
3393 for (
const QShaderDescription::InOutVariable &var : shaderPipeline->vertexStage()->shader().description().combinedImageSamplers()) {
3394 auto it = std::find_if(samplerVars.cbegin(), samplerVars.cend(),
3395 [&var](
const QShaderDescription::InOutVariable &v) {
return var.binding == v.binding; });
3396 if (it == samplerVars.cend())
3397 samplerVars.append(var);
3400 for (
const QShaderDescription::InOutVariable &var : std::as_const(samplerVars))
3401 maxSamplerBinding = qMax(maxSamplerBinding, var.binding);
3403 if (maxSamplerBinding >= 0) {
3404 int extraTexCount = shaderPipeline->extraTextureCount();
3405 for (
int i = 0; i < extraTexCount; ++i) {
3406 QSSGRhiTexture &t(shaderPipeline->extraTextureAt(i));
3407 const int samplerBinding = shaderPipeline->bindingForTexture(t.name);
3408 if (samplerBinding >= 0) {
3409 rhiCtx->checkAndAdjustForNPoT(t.texture, &t.samplerDesc);
3410 QRhiSampler *sampler = rhiCtx->sampler(t.samplerDesc);
3411 bindings.addTexture(samplerBinding,
3412 QRhiShaderResourceBinding::FragmentStage,
3420 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
3422 QSSG_ASSERT(srb,
continue);
3424 auto &rhiPassData = subsetRenderable.rhiRenderData.userPassData[index];
3425 rhiPassData.pipeline = rhiCtxD->pipeline(ps, rpDesc, srb);
3426 rhiPassData.srb = srb;
3435 QSSGPassKey passKey,
3436 const QSSGRhiGraphicsPipelineState &basePipelineState,
3437 QRhiRenderPassDescriptor *rpDesc,
3440 QSSGRenderableObjectList &inObjects,
3441 QSSGShaderFeatures featureSet)
3443 const qsizetype index = inData.getUserRenderPassManager()->acquireUserPassSlot();
3449 QSSGRhiGraphicsPipelineState ps = basePipelineState;
3450 for (
const QSSGRenderableObjectHandle &handle : inObjects) {
3451 QSSGRenderableObject *obj = handle.obj;
3452 QSSGRhiShaderPipelinePtr shaderPipeline;
3453 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
3454 const auto &bufferManager = inData.contextInterface()->bufferManager();
3456 featureSet.set(QSSGShaderFeatures::Feature::UserRenderPass,
true);
3458 QSSGRhiDrawCallData *dcd =
nullptr;
3459 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3460 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3461 const void *modelNode = &subsetRenderable.modelContext.model;
3462 dcd = &rhiCtxD->drawCallData({ passKey, modelNode, &subsetRenderable.material, 0 });
3465 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset) {
3466 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3467 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
3468 ps.cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
3470 shaderPipeline = shadersForDefaultMaterial(&ps, subsetRenderable, featureSet, shaderAugmentation);
3471 if (shaderPipeline) {
3472 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
3473 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
3475 for (
const auto &u : shaderAugmentation.propertyUniforms)
3476 shaderPipeline->setShaderResources(ubufData, *bufferManager, u.name, u.value, u.shaderDataType);
3477 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
3478 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
3480 }
else if (obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3481 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3482 const auto &material =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
3483 ps.cullMode = QSSGRhiHelpers::toCullMode(material.m_cullMode);
3485 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
3487 if (material.m_shadingMode == QSSGRenderCustomMaterial::ShadingMode::Unshaded)
3488 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(&ps, material, subsetRenderable, inData.getDefaultMaterialPropertyTable(), featureSet);
3490 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(&ps, material, subsetRenderable, inData.getDefaultMaterialPropertyTable(), featureSet, shaderAugmentation);
3492 if (shaderPipeline) {
3493 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
3494 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
3496 for (
const auto &u : shaderAugmentation.propertyUniforms)
3497 shaderPipeline->setShaderResources(ubufData, *bufferManager, u.name, u.value, u.shaderDataType);
3498 customMaterialSystem.updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, material,
3499 subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
3500 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
3504 if (!shaderPipeline) {
3506 qDebug() <<
"Failed to prepare user augmented pass for object.";
3511 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3512 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
3513 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(ps);
3514 ia = subsetRenderable.subset.rhi.ia;
3516 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
3517 int instanceBufferBinding = setupInstancing(&subsetRenderable, &ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
3518 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
3520 QSSGRhiShaderResourceBindingList bindings;
3521 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
3524 QSSGRenderableImage *renderableImage = subsetRenderable.firstImage;
3525 while (renderableImage) {
3526 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(renderableImage->m_mapType);
3527 const int samplerHint =
int(renderableImage->m_mapType);
3528 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
3529 if (samplerBinding >= 0) {
3530 QRhiTexture *texture = renderableImage->m_texture.m_texture;
3531 if (samplerBinding >= 0 && texture) {
3532 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
3533 QSSGRhiSamplerDescription samplerDesc = {
3534 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
3535 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
3536 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
3537 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
3538 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
3539 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
3541 rhiCtx->checkAndAdjustForNPoT(texture, &samplerDesc);
3542 QRhiSampler *sampler = rhiCtx->sampler(samplerDesc);
3543 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
3546 renderableImage = renderableImage->m_nextImage;
3549 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
3552 const int normalTextureBinding = shaderPipeline->bindingForTexture(
"qt_normalTexture",
int(QSSGRhiSamplerBindingHints::NormalTexture));
3553 if (normalTextureBinding >= 0) {
3554 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
3555 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
3556 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3557 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
3558 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3559 bindings.addTexture(normalTextureBinding, RENDERER_VISIBILITY_ALL, dummyTexture, sampler);
3565 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
3566 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
3568 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3569 QRhiSampler::Nearest,
3571 QRhiSampler::ClampToEdge,
3572 QRhiSampler::ClampToEdge,
3575 bindings.addTexture(binding,
3576 QRhiShaderResourceBinding::VertexStage,
3583 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
3584 if (targetsTexture) {
3585 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
3587 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3588 QRhiSampler::Nearest,
3590 QRhiSampler::ClampToEdge,
3591 QRhiSampler::ClampToEdge,
3592 QRhiSampler::ClampToEdge
3594 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
3599 if (shaderPipeline->isLightingEnabled()) {
3600 bindings.addUniformBuffer(1, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3601 shaderPipeline->ub0LightDataOffset(),
3602 sizeof(QSSGShaderLightsUniformData));
3603 bindings.addUniformBuffer(2, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3604 shaderPipeline->ub0DirectionalLightDataOffset(),
3605 sizeof(QSSGShaderDirectionalLightsUniformData));
3608 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_texture"); binding >= 0) {
3609 QRhiTexture *texture = shaderPipeline->shadowMapAtlasTexture();
3612 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3613 texture = rhiCtx->dummyTexture({ }, resourceUpdates, QSize(1, 1), Qt::black, 2);
3614 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3617 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3618 QRhiSampler::Linear,
3620 QRhiSampler::ClampToEdge,
3621 QRhiSampler::ClampToEdge,
3622 QRhiSampler::Repeat });
3624 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3628 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture"); binding >= 0) {
3629 if (
auto shadowMapBlueNoise = shaderPipeline->shadowMapBlueNoiseTexture()) {
3630 int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture");
3632 QRhiTexture *texture = shadowMapBlueNoise;
3633 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3634 QRhiSampler::Linear,
3636 QRhiSampler::Repeat,
3637 QRhiSampler::Repeat,
3638 QRhiSampler::Repeat });
3639 Q_ASSERT(texture && sampler);
3640 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3643 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3644 QRhiTexture *texture = rhiCtx->dummyTexture({}, resourceUpdates);
3645 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3646 QRhiSampler::Linear,
3648 QRhiSampler::Repeat,
3649 QRhiSampler::Repeat,
3650 QRhiSampler::Repeat });
3651 Q_ASSERT(texture && sampler);
3652 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3653 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3660 if (featureSet.isSet(QSSGShaderFeatures::Feature::ReflectionProbe)) {
3661 int reflectionSampler = shaderPipeline->bindingForTexture(
"qt_reflectionMap");
3662 QRhiTexture* reflectionTexture = inData.getReflectionMapManager()->reflectionMapEntry(subsetRenderable.reflectionProbeIndex)->m_rhiPrefilteredCube;
3663 const auto mipMapFilter = reflectionTexture && reflectionTexture->flags().testFlag(QRhiTexture::Flag::MipMapped)
3664 ? QRhiSampler::Linear
3665 : QRhiSampler::None;
3666 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3667 QRhiSampler::Linear,
3669 QRhiSampler::ClampToEdge,
3670 QRhiSampler::ClampToEdge,
3671 QRhiSampler::Repeat });
3672 if (reflectionSampler >= 0 && reflectionTexture)
3673 bindings.addTexture(reflectionSampler, QRhiShaderResourceBinding::FragmentStage, reflectionTexture, sampler);
3674 }
else if (shaderPipeline->lightProbeTexture()) {
3675 int binding = shaderPipeline->bindingForTexture(
"qt_lightProbe",
int(QSSGRhiSamplerBindingHints::LightProbe));
3677 auto tiling = shaderPipeline->lightProbeTiling();
3678 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
3679 QSSGRhiHelpers::toRhi(tiling.first), QSSGRhiHelpers::toRhi(tiling.second), QRhiSampler::Repeat });
3680 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage,
3681 shaderPipeline->lightProbeTexture(), sampler);
3686 if (shaderPipeline->screenTexture()) {
3687 const int screenTextureBinding = shaderPipeline->bindingForTexture(
"qt_screenTexture",
int(QSSGRhiSamplerBindingHints::ScreenTexture));
3688 const int screenTextureArrayBinding = shaderPipeline->bindingForTexture(
"qt_screenTextureArray",
int(QSSGRhiSamplerBindingHints::ScreenTextureArray));
3689 if (screenTextureBinding >= 0 || screenTextureArrayBinding >= 0) {
3694 QRhiSampler::Filter mipFilter = shaderPipeline->screenTexture()->flags().testFlag(QRhiTexture::MipMapped)
3695 ? QRhiSampler::Linear : QRhiSampler::None;
3696 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, mipFilter,
3697 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
3698 if (screenTextureBinding >= 0) {
3699 bindings.addTexture(screenTextureBinding,
3700 QRhiShaderResourceBinding::FragmentStage,
3701 shaderPipeline->screenTexture(), sampler);
3703 if (screenTextureArrayBinding >= 0) {
3704 bindings.addTexture(screenTextureArrayBinding,
3705 QRhiShaderResourceBinding::FragmentStage,
3706 shaderPipeline->screenTexture(), sampler);
3711 if (shaderPipeline->lightmapTexture()) {
3712 int binding = shaderPipeline->bindingForTexture(
"qt_lightmap",
int(QSSGRhiSamplerBindingHints::LightmapTexture));
3714 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
3715 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
3716 bindings.addTexture(binding,
3717 QRhiShaderResourceBinding::FragmentStage,
3718 shaderPipeline->lightmapTexture(), sampler);
3725 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3726 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3728 QVector<QShaderDescription::InOutVariable> samplerVars =
3729 shaderPipeline->fragmentStage()->shader().description().combinedImageSamplers();
3730 for (
const QShaderDescription::InOutVariable &var : shaderPipeline->vertexStage()->shader().description().combinedImageSamplers()) {
3731 auto it = std::find_if(samplerVars.cbegin(), samplerVars.cend(),
3732 [&var](
const QShaderDescription::InOutVariable &v) {
return var.binding == v.binding; });
3733 if (it == samplerVars.cend())
3734 samplerVars.append(var);
3737 int maxSamplerBinding = -1;
3738 for (
const QShaderDescription::InOutVariable &var : std::as_const(samplerVars))
3739 maxSamplerBinding = qMax(maxSamplerBinding, var.binding);
3748 QBitArray samplerBindingsSpecified(maxSamplerBinding + 1);
3750 if (maxSamplerBinding >= 0) {
3752 int extraTexCount = shaderPipeline->extraTextureCount();
3753 for (
int i = 0; i < extraTexCount; ++i) {
3754 QSSGRhiTexture &t(shaderPipeline->extraTextureAt(i));
3755 const int samplerBinding = shaderPipeline->bindingForTexture(t.name);
3756 if (samplerBinding >= 0) {
3757 samplerBindingsSpecified.setBit(samplerBinding);
3758 rhiCtx->checkAndAdjustForNPoT(t.texture, &t.samplerDesc);
3759 QRhiSampler *sampler = rhiCtx->sampler(t.samplerDesc);
3760 bindings.addTexture(samplerBinding,
3761 QRhiShaderResourceBinding::FragmentStage,
3769 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
3770 QSSG_ASSERT(srb,
return -1);
3771 auto &rhiPassData = subsetRenderable.rhiRenderData.userPassData[index];
3772 rhiPassData.pipeline = rhiCtxD->pipeline(ps, rpDesc, srb);
3773 rhiPassData.srb = srb;
3837 QSSGPassKey passKey,
3839 const QMatrix4x4 &viewProjection,
3841 QRhiRenderPassDescriptor *renderPassDescriptor,
3842 QSSGRhiGraphicsPipelineState *ps,
3843 QSSGRenderMotionVectorMap &motionVectorMapManager)
3845 if (inObject.type != QSSGRenderableObject::Type::DefaultMaterialMeshSubset &&
3846 inObject.type != QSSGRenderableObject::Type::CustomMaterialMeshSubset)
3849 QSSGSubsetRenderable &subsetRenderable =
static_cast<QSSGSubsetRenderable &>(inObject);
3850 auto &modelNode = subsetRenderable.modelContext.model;
3852 bool skin = modelNode.usesBoneTexture();
3853 bool instance = modelNode.instanceCount() > 0;
3854 bool morph = modelNode.morphTargets.size() > 0;
3856 QSSGRhiShaderPipelinePtr shaderPipeline = inData.contextInterface()->shaderCache()->
3857 getBuiltInRhiShaders().getRhiMotionVectorShader(skin, instance, morph);
3859 if (!shaderPipeline)
3862 QSSGRhiShaderResourceBindingList bindings;
3864 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
3865 QSSGRhiDrawCallData &dcd = rhiCtxD->drawCallData({ passKey, &modelNode,
nullptr, 0 });
3868 QSSGRenderTextureData *boneTextureData =
nullptr;
3870 boneTextureData = modelNode.skin;
3871 else if (modelNode.skeleton)
3872 boneTextureData = &modelNode.skeleton->boneTexData;
3874 QMatrix4x4 modelViewProjection = subsetRenderable.modelContext.modelViewProjections[0];
3875 QMatrix4x4 instanceLocal;
3876 QMatrix4x4 instanceGlobal;
3879 instanceLocal = inData.getInstanceTransforms(modelNode).local;
3880 instanceGlobal = inData.getInstanceTransforms(modelNode).global;
3882 modelViewProjection = viewProjection;
3884 auto motionData = motionVectorMapManager.trackMotionData(&modelNode,
3885 modelViewProjection,
3889 modelNode.instanceTable,
3890 modelNode.morphWeights);
3891 float velocityAmount = subsetRenderable.modelContext.model.motionVectorScale;
3892 int morphTargetCount = modelNode.morphWeights.count();
3904 const int ubufSize = 416;
3907 dcd.ubuf = rhiCtx->rhi()->newBuffer(QRhiBuffer::Dynamic,
3908 QRhiBuffer::UniformBuffer,
3913 char *ubufData = dcd.ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
3915 memcpy(ubufData, modelViewProjection.constData(), 64);
3917 memcpy(ubufData + ubufOffset, motionData.prevModelViewProjection.constData(), 64);
3919 memcpy(ubufData + ubufOffset, instanceLocal.constData(), 64);
3921 memcpy(ubufData + ubufOffset, instanceGlobal.constData(), 64);
3923 memcpy(ubufData + ubufOffset, motionData.prevInstanceLocal.constData(), 64);
3925 memcpy(ubufData + ubufOffset, motionData.prevInstanceGlobal.constData(), 64);
3927 memcpy(ubufData + ubufOffset, &inData.layer.currentAndLastJitter, 16);
3929 memcpy(ubufData + ubufOffset, &velocityAmount, 4);
3931 memcpy(ubufData + ubufOffset, &morphTargetCount, 4);
3932 dcd.ubuf->endFullDynamicBufferUpdateForCurrentFrame();
3934 bindings.addUniformBuffer(0, QRhiShaderResourceBinding::VertexStage |
3935 QRhiShaderResourceBinding::FragmentStage, dcd.ubuf);
3937 QRhiSampler *nearestSampler =
nullptr;
3939 if (skin || instance) {
3940 nearestSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3941 QRhiSampler::Nearest,
3943 QRhiSampler::ClampToEdge,
3944 QRhiSampler::ClampToEdge,
3950 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
3953 bindings.addTexture(binding,
3954 QRhiShaderResourceBinding::VertexStage,
3955 inData.getBonemapTexture(subsetRenderable.modelContext),
3957 binding = shaderPipeline->bindingForTexture(
"lastBoneTexture");
3959 bindings.addTexture(binding,
3960 QRhiShaderResourceBinding::VertexStage,
3961 motionData.prevBoneTexture.m_texture,
3968 int binding = shaderPipeline->bindingForTexture(
"lastInstanceTexture");
3970 bindings.addTexture(binding,
3971 QRhiShaderResourceBinding::VertexStage,
3972 motionData.prevInstanceTexture.m_texture,
3977 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
3978 if (targetsTexture) {
3979 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
3981 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3982 QRhiSampler::Nearest,
3984 QRhiSampler::ClampToEdge,
3985 QRhiSampler::ClampToEdge,
3986 QRhiSampler::ClampToEdge
3988 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
3990 if ((binding = shaderPipeline->bindingForTexture(
"morphWeightTexture")) >= 0)
3991 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, motionData.currentMorphWeightTexture.m_texture, targetsSampler);
3993 if ((binding = shaderPipeline->bindingForTexture(
"lastMorphWeightTexture")) >= 0)
3994 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, motionData.prevMorphWeightTexture.m_texture, targetsSampler);
3998 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
3999 ia = subsetRenderable.subset.rhi.ia;
4000 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
4001 QVector3D cameraDirection = cameraDatas[0].direction;
4002 QVector3D cameraPosition = cameraDatas[0].position;
4003 int instanceBufferBinding = setupInstancing(&subsetRenderable, ps, rhiCtx, cameraDirection, cameraPosition);
4004 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
4005 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(*ps, shaderPipeline.get());
4007 QRhiShaderResourceBindings *&srb = dcd.srb;
4008 bool srbChanged =
false;
4009 if (!srb || bindings != dcd.bindings) {
4010 srb = rhiCtxD->srb(bindings);
4011 rhiCtxD->releaseCachedSrb(dcd.bindings);
4012 dcd.bindings = bindings;
4016 subsetRenderable.rhiRenderData.motionVectorPass.srb = srb;
4018 const auto pipelineKey = QSSGGraphicsPipelineStateKey::create(*ps, renderPassDescriptor, srb);
4021 && dcd.renderTargetDescriptionHash == pipelineKey.extra.renderTargetDescriptionHash
4022 && dcd.renderTargetDescription == pipelineKey.renderTargetDescription
4025 subsetRenderable.rhiRenderData.motionVectorPass.pipeline = dcd.pipeline;
4028 subsetRenderable.rhiRenderData.motionVectorPass.pipeline = rhiCtxD->pipeline(pipelineKey,
4029 renderPassDescriptor,
4031 dcd.pipeline = subsetRenderable.rhiRenderData.motionVectorPass.pipeline;
4032 dcd.renderTargetDescriptionHash = pipelineKey.extra.renderTargetDescriptionHash;
4033 dcd.renderTargetDescription = pipelineKey.renderTargetDescription;