277 const QSSGRenderCamera &inCamera,
278 const QSSGRenderLight *inLight,
279 const int shadowMapResolution,
280 const float pcfRadius,
281 const float clipNear,
283 const QSSGBounds3 &castingObjectsBox,
284 const QSSGBounds3 &receivingObjectsBox,
285 bool lockShadowmapTexels,
286 QSSGDebugDrawSystem *debugDrawSystem,
288 bool drawSceneCascadeIntersection)
290 Q_ASSERT(inLight->type == QSSGRenderLight::Type::DirectionalLight);
291 QVarLengthArray<std::unique_ptr<QSSGRenderCamera>, 4> result;
293 if (clipNear >= clipFar || qFuzzyCompare(clipNear, clipFar))
296 const QMatrix4x4 lightGlobalTransform = data.getGlobalTransform(*inLight);
297 const QVector3D lightDir = inLight->getDirection(lightGlobalTransform);
298 const QVector3D lightPivot = inLight->pivot;
300 const QVector3D forward = lightDir.normalized();
301 const QVector3D right = qFuzzyCompare(qAbs(forward.y()), 1.0f)
302 ? QVector3D::crossProduct(forward, QVector3D(1, 0, 0)).normalized()
303 : QVector3D::crossProduct(forward, QVector3D(0, 1, 0)).normalized();
304 const QVector3D up = QVector3D::crossProduct(right, forward).normalized();
306 QMatrix4x4 lightMatrix;
307 lightMatrix.setRow(0, QVector4D(right, 0.0f));
308 lightMatrix.setRow(1, QVector4D(up, 0.0f));
309 lightMatrix.setRow(2, QVector4D(forward, 0.0f));
310 lightMatrix.setRow(3, QVector4D(0.0f, 0.0f, 0.0f, 1.0f));
311 QMatrix4x4 lightMatrixInverted = lightMatrix.inverted();
313 const float farScale = (clipFar - clipNear) / (inCamera.clipPlanes.clipFar() - inCamera.clipPlanes.clipNear());
315 const QMatrix4x4 cameraGlobalTransform = data.getGlobalTransform(inCamera);
316 QMatrix4x4 viewProjection(Qt::Uninitialized);
317 inCamera.calculateViewProjectionMatrix(cameraGlobalTransform, viewProjection);
318 const QSSGBoxPoints frustum = computeFrustumBounds(viewProjection);
319 const QSSGBoxPoints frustumUntransformed = lockShadowmapTexels ? computeFrustumBounds(inCamera.projection) : QSSGBoxPoints();
323 const auto calcFrustumRadius = [&](
float t0,
float t1) ->
float {
324 const QSSGBoxPoints pts = sliceFrustum(frustumUntransformed, t0 * farScale, t1 * farScale);
326 QVector3D center = QVector3D(0.f, 0.f, 0.f);
327 for (QVector3D point : pts) {
330 center = center * 0.125f;
332 float radiusSquared = 0;
333 for (QVector3D point : pts) {
334 radiusSquared = qMax(radiusSquared, (point - center).lengthSquared());
337 return std::sqrt(radiusSquared);
340 const auto computeSplitRanges = [inLight](
const QVarLengthArray<
float, 3> &splits) -> QVarLengthArray<QPair<
float,
float>, 4> {
341 QVarLengthArray<QPair<
float,
float>, 4> ranges;
342 const float csmBlendRatio = inLight->m_csmBlendRatio;
344 for (qsizetype i = 0; i < splits.length(); i++) {
345 const float tI = qBound(qMin(t0 + 0.01f, 1.0f), splits[i], 1.0f);
346 ranges.emplace_back(t0, qMin(1.0f, tI + csmBlendRatio));
349 ranges.emplace_back(t0, 1.0f);
353 const auto computeFrustums = [&](
const QVarLengthArray<
float, 3> &splits) {
354 for (
const auto &range : computeSplitRanges(splits)) {
355 const float frustumRadius = lockShadowmapTexels ? calcFrustumRadius(range.first, range.second) : 0.0f;
356 auto camera = computeShadowCameraFromFrustum(lightMatrix,
364 range.first * farScale,
365 range.second * farScale,
372 drawSceneCascadeIntersection);
373 result.emplace_back(std::move(camera));
377 switch (inLight->m_csmNumSplits) {
383 computeFrustums({ inLight->m_csmSplit1 });
387 computeFrustums({ inLight->m_csmSplit1, inLight->m_csmSplit2 });
391 computeFrustums({ inLight->m_csmSplit1, inLight->m_csmSplit2, inLight->m_csmSplit3 });
433 QSSGRhiShaderPipeline *shaderPipeline,
434 QSSGRenderableImage *renderableImage,
435 QSSGRhiShaderResourceBindingList &bindings,
436 bool isCustomMaterialMeshSubset =
false)
438 static const auto imageAffectsAlpha = [](QSSGRenderableImage::Type mapType) {
439 return mapType == QSSGRenderableImage::Type::BaseColor ||
440 mapType == QSSGRenderableImage::Type::Diffuse ||
441 mapType == QSSGRenderableImage::Type::Translucency ||
442 mapType == QSSGRenderableImage::Type::Opacity;
445 while (renderableImage) {
446 const auto mapType = renderableImage->m_mapType;
447 if (imageAffectsAlpha(mapType)) {
448 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(mapType);
449 const int samplerHint =
int(mapType);
450 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
451 if (samplerBinding >= 0) {
452 QRhiTexture *texture = renderableImage->m_texture.m_texture;
453 if (samplerBinding >= 0 && texture) {
454 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
455 QRhiSampler *sampler = rhiCtx->sampler({ QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
456 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
457 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
458 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
459 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
460 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
462 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
466 renderableImage = renderableImage->m_nextImage;
469 if (isCustomMaterialMeshSubset) {
470 QVector<QShaderDescription::InOutVariable> samplerVars =
471 shaderPipeline->fragmentStage()->shader().description().combinedImageSamplers();
472 for (
const QShaderDescription::InOutVariable &var : shaderPipeline->vertexStage()->shader().description().combinedImageSamplers()) {
473 auto it = std::find_if(samplerVars.cbegin(), samplerVars.cend(),
474 [&var](
const QShaderDescription::InOutVariable &v) {
return var.binding == v.binding; });
475 if (it == samplerVars.cend())
476 samplerVars.append(var);
479 int maxSamplerBinding = -1;
480 for (
const QShaderDescription::InOutVariable &var : std::as_const(samplerVars))
481 maxSamplerBinding = qMax(maxSamplerBinding, var.binding);
490 QBitArray samplerBindingsSpecified(maxSamplerBinding + 1);
492 if (maxSamplerBinding >= 0) {
494 int customTexCount = shaderPipeline->extraTextureCount();
495 for (
int i = 0; i < customTexCount; ++i) {
496 const QSSGRhiTexture &t(shaderPipeline->extraTextureAt(i));
497 const int samplerBinding = shaderPipeline->bindingForTexture(t.name);
498 if (samplerBinding >= 0) {
499 samplerBindingsSpecified.setBit(samplerBinding);
500 QRhiSampler *sampler = rhiCtx->sampler(t.samplerDesc);
501 bindings.addTexture(samplerBinding,
502 RENDERER_VISIBILITY_ALL,
510 QRhiSampler *dummySampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
511 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
512 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
513 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
514 QRhiTexture *dummyCubeTexture = rhiCtx->dummyTexture(QRhiTexture::CubeMap, resourceUpdates);
515 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
517 for (
const QShaderDescription::InOutVariable &var : std::as_const(samplerVars)) {
518 if (!samplerBindingsSpecified.testBit(var.binding)) {
519 QRhiTexture *t = var.type == QShaderDescription::SamplerCube ? dummyCubeTexture : dummyTexture;
520 bindings.addTexture(var.binding, RENDERER_VISIBILITY_ALL, t, dummySampler);
732 QSSGRhiGraphicsPipelineState *ps,
733 const QVector2D *depthAdjust,
734 const QSSGRenderableObjectList &sortedOpaqueObjects,
735 QSSGRenderCamera &inCamera,
737 QSSGRenderTextureCubeFace cubeFace,
738 quint32 cascadeIndex)
740 QSSGShaderFeatures featureSet;
742 featureSet.set(QSSGShaderFeatures::Feature::OrthoShadowPass,
true);
744 featureSet.set(QSSGShaderFeatures::Feature::PerspectiveShadowPass,
true);
750 featureSet.set(QSSGShaderFeatures::Feature::DisableMultiView,
true);
752 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(cubeFace);
753 const auto &defaultMaterialShaderKeyProperties = inData.getDefaultMaterialPropertyTable();
754 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
756 for (
const auto &handle : sortedOpaqueObjects) {
757 QSSGRenderableObject *theObject = handle.obj;
758 QSSG_ASSERT(theObject->renderableFlags.castsShadows(),
continue);
760 QSSGShaderFeatures objectFeatureSet = featureSet;
761 const bool isOpaqueDepthPrePass = theObject->depthWriteMode == QSSGDepthDrawMode::OpaquePrePass;
762 if (isOpaqueDepthPrePass)
763 objectFeatureSet.set(QSSGShaderFeatures::Feature::OpaqueDepthPrePass,
true);
765 QSSGRhiDrawCallData *dcd =
nullptr;
766 QMatrix4x4 modelViewProjection;
767 QSSGSubsetRenderable &renderable(
static_cast<QSSGSubsetRenderable &>(*theObject));
768 if (theObject->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || theObject->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
769 const bool hasSkinning = defaultMaterialShaderKeyProperties.m_boneCount.getValue(renderable.shaderDescription) > 0;
770 modelViewProjection = hasSkinning ? pEntry->m_lightViewProjection[cascadeIndex]
771 : pEntry->m_lightViewProjection[cascadeIndex] * renderable.modelContext.globalTransform;
775 const quintptr entryIdx = cascadeIndex + cubeFaceIdx + (quintptr(renderable.subset.offset) << 3);
776 dcd = &rhiCtxD->drawCallData({ passKey, &renderable.modelContext.model, pEntry, entryIdx });
779 QSSGRhiShaderResourceBindingList bindings;
780 QSSGRhiShaderPipelinePtr shaderPipeline;
781 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*theObject));
782 if (theObject->type == QSSGSubsetRenderable::Type::DefaultMaterialMeshSubset) {
783 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
784 ps->cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
785 const bool blendParticles = defaultMaterialShaderKeyProperties.m_blendParticles.getValue(subsetRenderable.shaderDescription);
787 shaderPipeline = shadersForDefaultMaterial(ps, subsetRenderable, objectFeatureSet);
790 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
791 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
793 QSSGRenderCameraList cameras({ &inCamera });
794 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, subsetRenderable, cameras, depthAdjust, &modelViewProjection);
796 QSSGParticleRenderer::updateUniformsForParticleModel(*shaderPipeline, ubufData, &subsetRenderable.modelContext.model, subsetRenderable.subset.offset);
797 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
799 QSSGParticleRenderer::prepareParticlesForModel(*shaderPipeline, rhiCtx, bindings, &subsetRenderable.modelContext.model);
800 }
else if (theObject->type == QSSGSubsetRenderable::Type::CustomMaterialMeshSubset) {
801 const auto &material =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
802 ps->cullMode = QSSGRhiHelpers::toCullMode(material.m_cullMode);
804 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
805 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(ps, material, subsetRenderable, inData.getDefaultMaterialPropertyTable(), objectFeatureSet);
808 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
809 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
811 QSSGRenderCameraList cameras({ &inCamera });
812 customMaterialSystem.updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, material, subsetRenderable,
813 cameras, depthAdjust, &modelViewProjection);
814 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
817 if (theObject->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || theObject->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
819 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(*ps, shaderPipeline.get());
820 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
821 ia = subsetRenderable.subset.rhi.ia;
822 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
823 int instanceBufferBinding = setupInstancing(&subsetRenderable, ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
824 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
827 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
830 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
832 addNormalTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
834 if (isOpaqueDepthPrePass) {
835 addOpaqueDepthPrePassBindings(rhiCtx,
836 shaderPipeline.get(),
837 subsetRenderable.firstImage,
839 (theObject->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset));
846 const int screenTextureBinding = shaderPipeline->bindingForTexture(
"qt_screenTexture",
int(QSSGRhiSamplerBindingHints::ScreenTexture));
847 const int screenTextureArrayBinding = shaderPipeline->bindingForTexture(
"qt_screenTextureArray",
int(QSSGRhiSamplerBindingHints::ScreenTextureArray));
848 if (screenTextureBinding >= 0 || screenTextureArrayBinding >= 0) {
849 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
850 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
851 if (screenTextureBinding >= 0) {
852 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
853 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
854 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
855 bindings.addTexture(screenTextureBinding,
856 QRhiShaderResourceBinding::FragmentStage,
857 dummyTexture, sampler);
859 if (screenTextureArrayBinding >= 0) {
860 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
861 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates, QSize(64, 64), Qt::black, inData.layer.viewCount);
862 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
863 bindings.addTexture(screenTextureArrayBinding,
864 QRhiShaderResourceBinding::FragmentStage,
865 dummyTexture, sampler);
870 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
871 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
873 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
874 QRhiSampler::Nearest,
876 QRhiSampler::ClampToEdge,
877 QRhiSampler::ClampToEdge,
880 bindings.addTexture(binding,
881 QRhiShaderResourceBinding::VertexStage,
888 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
889 if (targetsTexture) {
890 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
892 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
893 QRhiSampler::Nearest,
895 QRhiSampler::ClampToEdge,
896 QRhiSampler::ClampToEdge,
897 QRhiSampler::ClampToEdge
899 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
903 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
904 subsetRenderable.rhiRenderData.shadowPass.pipeline = rhiCtxD->pipeline(*ps, pEntry->m_rhiRenderPassDesc[cascadeIndex], srb);
905 subsetRenderable.rhiRenderData.shadowPass.srb[cubeFaceIdx] = srb;
940 QRhiRenderPassDescriptor *renderPassDescriptor,
941 QSSGRhiGraphicsPipelineState *ps,
942 QSSGShaderFeatures featureSet,
945 QSSGRenderCamera *alteredCamera,
946 QMatrix4x4 *alteredModelViewProjection,
947 QSSGRenderTextureCubeFace cubeFace,
951 const auto &defaultMaterialShaderKeyProperties = inData.getDefaultMaterialPropertyTable();
953 switch (inObject.type) {
954 case QSSGRenderableObject::Type::DefaultMaterialMeshSubset:
956 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(inObject));
958 if ((cubeFace == QSSGRenderTextureCubeFaceNone) && subsetRenderable.reflectionProbeIndex >= 0 && subsetRenderable.renderableFlags.testFlag(QSSGRenderableObjectFlag::ReceivesReflections))
959 featureSet.set(QSSGShaderFeatures::Feature::ReflectionProbe,
true);
961 if ((cubeFace != QSSGRenderTextureCubeFaceNone)) {
963 featureSet.disableTonemapping();
966 if (subsetRenderable.renderableFlags.rendersWithLightmap())
967 featureSet.set(QSSGShaderFeatures::Feature::Lightmap,
true);
969 const auto &shaderPipeline = shadersForDefaultMaterial(ps, subsetRenderable, featureSet);
970 if (shaderPipeline) {
978 QSSGRhiShaderResourceBindingList bindings;
979 const auto &modelNode = subsetRenderable.modelContext.model;
980 const bool blendParticles = defaultMaterialShaderKeyProperties.m_blendParticles.getValue(subsetRenderable.shaderDescription);
987 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(cubeFace);
988 const quintptr entryIdx = quintptr(cubeFace != QSSGRenderTextureCubeFaceNone) * (cubeFaceIdx + (quintptr(subsetRenderable.subset.offset) << 3));
990 const auto entryPartA =
reinterpret_cast<quintptr>(&subsetRenderable.material);
991 const auto entryPartB =
reinterpret_cast<quintptr>(entry);
992 const void *entryId =
reinterpret_cast<
const void *>(entryPartA ^ entryPartB);
994 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
995 QSSGRhiDrawCallData &dcd = rhiCtxD->drawCallData({ passKey, &modelNode, entryId, entryIdx });
997 shaderPipeline->ensureCombinedUniformBuffer(&dcd.ubuf);
998 char *ubufData = dcd.ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
1000 Q_ASSERT(alteredModelViewProjection);
1001 QSSGRenderCameraList cameras({ alteredCamera });
1002 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, subsetRenderable, cameras,
nullptr, alteredModelViewProjection);
1004 Q_ASSERT(!alteredModelViewProjection);
1005 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
1009 QSSGParticleRenderer::updateUniformsForParticleModel(*shaderPipeline, ubufData, &subsetRenderable.modelContext.model, subsetRenderable.subset.offset);
1010 dcd.ubuf->endFullDynamicBufferUpdateForCurrentFrame();
1013 QSSGParticleRenderer::prepareParticlesForModel(*shaderPipeline, rhiCtx, bindings, &subsetRenderable.modelContext.model);
1016 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
1017 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
1019 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
1020 QRhiSampler::Nearest,
1022 QRhiSampler::ClampToEdge,
1023 QRhiSampler::ClampToEdge,
1026 bindings.addTexture(binding,
1027 QRhiShaderResourceBinding::VertexStage,
1033 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
1034 if (targetsTexture) {
1035 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
1037 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
1038 QRhiSampler::Nearest,
1040 QRhiSampler::ClampToEdge,
1041 QRhiSampler::ClampToEdge,
1042 QRhiSampler::ClampToEdge
1044 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
1048 ps->samples = samples;
1049 ps->viewCount = viewCount;
1051 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
1052 ps->cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
1053 if (!oit || (oit && inData.layer.oitMethod == QSSGRenderLayer::OITMethod::None))
1054 fillTargetBlend(&ps->targetBlend[0], material.blendMode);
1056 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
1058 ia = subsetRenderable.subset.rhi.ia;
1059 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
1060 QVector3D cameraDirection = cameraDatas[0].direction;
1061 QVector3D cameraPosition = cameraDatas[0].position;
1062 if (alteredCamera) {
1063 const QMatrix4x4 camGlobalTranform = inData.getGlobalTransform(*alteredCamera);
1064 cameraDirection = QSSGRenderNode::getScalingCorrectDirection(camGlobalTranform);
1065 cameraPosition = QSSGRenderNode::getGlobalPos(camGlobalTranform);
1067 int instanceBufferBinding = setupInstancing(&subsetRenderable, ps, rhiCtx, cameraDirection, cameraPosition);
1068 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
1070 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd.ubuf, 0, shaderPipeline->ub0Size());
1072 if (shaderPipeline->isLightingEnabled()) {
1073 bindings.addUniformBuffer(1, RENDERER_VISIBILITY_ALL, dcd.ubuf,
1074 shaderPipeline->ub0LightDataOffset(),
1075 sizeof(QSSGShaderLightsUniformData));
1076 bindings.addUniformBuffer(2, RENDERER_VISIBILITY_ALL, dcd.ubuf,
1077 shaderPipeline->ub0DirectionalLightDataOffset(),
1078 sizeof(QSSGShaderDirectionalLightsUniformData));
1083 QSSGRenderableImage *renderableImage = subsetRenderable.firstImage;
1084 while (renderableImage) {
1085 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(renderableImage->m_mapType);
1086 const int samplerHint =
int(renderableImage->m_mapType);
1087 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
1088 if (samplerBinding >= 0) {
1089 QRhiTexture *texture = renderableImage->m_texture.m_texture;
1090 if (samplerBinding >= 0 && texture) {
1091 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
1092 QSSGRhiSamplerDescription samplerDesc = {
1093 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
1094 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
1095 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
1096 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
1097 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
1098 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
1100 rhiCtx->checkAndAdjustForNPoT(texture, &samplerDesc);
1101 QRhiSampler *sampler = rhiCtx->sampler(samplerDesc);
1102 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
1105 renderableImage = renderableImage->m_nextImage;
1108 if (shaderPipeline->isLightingEnabled()) {
1110 auto shadowMapAtlas = shaderPipeline->shadowMapAtlasTexture();
1111 if (shadowMapAtlas) {
1112 int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_texture");
1114 QRhiTexture *texture = shadowMapAtlas;
1115 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
1116 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
1117 Q_ASSERT(texture && sampler);
1118 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
1123 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture"); binding >= 0) {
1124 if (
auto shadowMapBlueNoise = shaderPipeline->shadowMapBlueNoiseTexture()) {
1125 int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture");
1127 QRhiTexture *texture = shadowMapBlueNoise;
1128 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
1129 QRhiSampler::Linear,
1131 QRhiSampler::Repeat,
1132 QRhiSampler::Repeat,
1133 QRhiSampler::Repeat });
1134 Q_ASSERT(texture && sampler);
1135 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
1138 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
1139 QRhiTexture *texture = rhiCtx->dummyTexture({}, resourceUpdates);
1140 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
1141 QRhiSampler::Linear,
1143 QRhiSampler::Repeat,
1144 QRhiSampler::Repeat,
1145 QRhiSampler::Repeat });
1146 Q_ASSERT(texture && sampler);
1147 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
1148 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
1155 if (featureSet.isSet(QSSGShaderFeatures::Feature::ReflectionProbe)) {
1156 int reflectionSampler = shaderPipeline->bindingForTexture(
"qt_reflectionMap");
1157 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
1158 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
1159 QRhiTexture* reflectionTexture = inData.getReflectionMapManager()->reflectionMapEntry(subsetRenderable.reflectionProbeIndex)->m_rhiPrefilteredCube;
1160 if (reflectionSampler >= 0 && reflectionTexture)
1161 bindings.addTexture(reflectionSampler, QRhiShaderResourceBinding::FragmentStage, reflectionTexture, sampler);
1162 }
else if (shaderPipeline->lightProbeTexture()) {
1163 int binding = shaderPipeline->bindingForTexture(
"qt_lightProbe",
int(QSSGRhiSamplerBindingHints::LightProbe));
1165 auto tiling = shaderPipeline->lightProbeTiling();
1166 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
1167 QSSGRhiHelpers::toRhi(tiling.first), QSSGRhiHelpers::toRhi(tiling.second), QRhiSampler::Repeat });
1168 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage,
1169 shaderPipeline->lightProbeTexture(), sampler);
1174 if (shaderPipeline->screenTexture()) {
1175 const int screenTextureBinding = shaderPipeline->bindingForTexture(
"qt_screenTexture",
int(QSSGRhiSamplerBindingHints::ScreenTexture));
1176 const int screenTextureArrayBinding = shaderPipeline->bindingForTexture(
"qt_screenTextureArray",
int(QSSGRhiSamplerBindingHints::ScreenTextureArray));
1177 if (screenTextureBinding >= 0 || screenTextureArrayBinding >= 0) {
1182 QRhiSampler::Filter mipFilter = shaderPipeline->screenTexture()->flags().testFlag(QRhiTexture::MipMapped)
1183 ? QRhiSampler::Linear : QRhiSampler::None;
1184 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, mipFilter,
1185 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
1186 if (screenTextureBinding >= 0) {
1187 bindings.addTexture(screenTextureBinding,
1188 QRhiShaderResourceBinding::FragmentStage,
1189 shaderPipeline->screenTexture(), sampler);
1191 if (screenTextureArrayBinding >= 0) {
1192 bindings.addTexture(screenTextureArrayBinding,
1193 QRhiShaderResourceBinding::FragmentStage,
1194 shaderPipeline->screenTexture(), sampler);
1199 if (shaderPipeline->lightmapTexture()) {
1200 int binding = shaderPipeline->bindingForTexture(
"qt_lightmap",
int(QSSGRhiSamplerBindingHints::LightmapTexture));
1202 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
1203 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
1204 bindings.addTexture(binding,
1205 QRhiShaderResourceBinding::FragmentStage,
1206 shaderPipeline->lightmapTexture(), sampler);
1212 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
1215 addNormalTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
1217 if (oit && inData.layer.oitMethod == QSSGRenderLayer::OITMethod::LinkedList)
1227 QRhiShaderResourceBindings *&srb = dcd.srb;
1228 bool srbChanged =
false;
1229 if (!srb || bindings != dcd.bindings) {
1230 srb = rhiCtxD->srb(bindings);
1231 rhiCtxD->releaseCachedSrb(dcd.bindings);
1232 dcd.bindings = bindings;
1236 if (cubeFace != QSSGRenderTextureCubeFaceNone)
1237 subsetRenderable.rhiRenderData.reflectionPass.srb[cubeFaceIdx] = srb;
1239 subsetRenderable.rhiRenderData.mainPass.srb = srb;
1241 const auto pipelineKey = QSSGGraphicsPipelineStateKey::create(*ps, renderPassDescriptor, srb);
1244 && dcd.renderTargetDescriptionHash == pipelineKey.extra.renderTargetDescriptionHash
1245 && dcd.renderTargetDescription == pipelineKey.renderTargetDescription
1248 if (cubeFace != QSSGRenderTextureCubeFaceNone)
1249 subsetRenderable.rhiRenderData.reflectionPass.pipeline = dcd.pipeline;
1251 subsetRenderable.rhiRenderData.mainPass.pipeline = dcd.pipeline;
1253 if (cubeFace != QSSGRenderTextureCubeFaceNone) {
1254 subsetRenderable.rhiRenderData.reflectionPass.pipeline = rhiCtxD->pipeline(pipelineKey,
1255 renderPassDescriptor,
1257 dcd.pipeline = subsetRenderable.rhiRenderData.reflectionPass.pipeline;
1259 subsetRenderable.rhiRenderData.mainPass.pipeline = rhiCtxD->pipeline(pipelineKey,
1260 renderPassDescriptor,
1262 dcd.pipeline = subsetRenderable.rhiRenderData.mainPass.pipeline;
1264 dcd.renderTargetDescriptionHash = pipelineKey.extra.renderTargetDescriptionHash;
1265 dcd.renderTargetDescription = pipelineKey.renderTargetDescription;
1271 case QSSGRenderableObject::Type::CustomMaterialMeshSubset:
1273 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(inObject));
1274 const QSSGRenderCustomMaterial &material =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
1275 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
1277 featureSet.set(QSSGShaderFeatures::Feature::LightProbe, inData.layer.lightProbe || material.m_iblProbe);
1279 if ((cubeFace == QSSGRenderTextureCubeFaceNone) && subsetRenderable.reflectionProbeIndex >= 0 && subsetRenderable.renderableFlags.testFlag(QSSGRenderableObjectFlag::ReceivesReflections))
1280 featureSet.set(QSSGShaderFeatures::Feature::ReflectionProbe,
true);
1282 if (cubeFace != QSSGRenderTextureCubeFaceNone) {
1284 featureSet.disableTonemapping();
1287 if (subsetRenderable.renderableFlags.rendersWithLightmap())
1288 featureSet.set(QSSGShaderFeatures::Feature::Lightmap,
true);
1290 customMaterialSystem.rhiPrepareRenderable(ps, passKey, subsetRenderable, featureSet,
1291 material, inData, renderPassDescriptor, samples, viewCount,
1292 alteredCamera, cubeFace, alteredModelViewProjection, entry, oit);
1295 case QSSGRenderableObject::Type::Particles:
1298 const auto &shaderPipeline = shadersForParticleMaterial(ps, particleRenderable, featureSet);
1299 if (shaderPipeline) {
1300 QSSGParticleRenderer::rhiPrepareRenderable(*shaderPipeline, passKey, rhiCtx, ps, particleRenderable, inData, renderPassDescriptor, samples, viewCount,
1301 alteredCamera, cubeFace, entry, oit);
1309 const QSSGRhiGraphicsPipelineState &state,
1311 bool *needsSetViewport,
1312 QSSGRenderTextureCubeFace cubeFace,
1313 qsizetype userPassIndex)
1315 switch (object.type) {
1316 case QSSGRenderableObject::Type::DefaultMaterialMeshSubset:
1318 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(object));
1320 QRhiGraphicsPipeline *ps = (userPassIndex >= 0) ? subsetRenderable.rhiRenderData.userPassData[userPassIndex].pipeline : subsetRenderable.rhiRenderData.mainPass.pipeline;
1321 QRhiShaderResourceBindings *srb = (userPassIndex >= 0) ? subsetRenderable.rhiRenderData.userPassData[userPassIndex].srb : subsetRenderable.rhiRenderData.mainPass.srb;
1323 if (cubeFace != QSSGRenderTextureCubeFaceNone) {
1324 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(cubeFace);
1325 ps = subsetRenderable.rhiRenderData.reflectionPass.pipeline;
1326 srb = subsetRenderable.rhiRenderData.reflectionPass.srb[cubeFaceIdx];
1332 QRhiBuffer *vertexBuffer = subsetRenderable.subset.rhi.vertexBuffer->buffer();
1333 QRhiBuffer *indexBuffer = subsetRenderable.subset.rhi.indexBuffer ? subsetRenderable.subset.rhi.indexBuffer->buffer() :
nullptr;
1335 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1337 cb->setGraphicsPipeline(ps);
1338 cb->setShaderResources(srb);
1340 if (*needsSetViewport) {
1341 cb->setViewport(state.viewport);
1342 if (state.flags.testFlag(QSSGRhiGraphicsPipelineState::Flag::UsesScissor))
1343 cb->setScissor(state.scissor);
1344 *needsSetViewport =
false;
1347 QRhiCommandBuffer::VertexInput vertexBuffers[2];
1348 int vertexBufferCount = 1;
1349 vertexBuffers[0] = QRhiCommandBuffer::VertexInput(vertexBuffer, 0);
1350 quint32 instances = 1;
1351 if ( subsetRenderable.modelContext.model.instancing()) {
1352 instances = subsetRenderable.modelContext.model.instanceCount();
1359 vertexBuffers[1] = QRhiCommandBuffer::VertexInput(subsetRenderable.instanceBuffer, 0);
1360 vertexBufferCount = 2;
1362 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderCall);
1363 if (state.flags.testFlag(QSSGRhiGraphicsPipelineState::Flag::UsesStencilRef))
1364 cb->setStencilRef(state.stencilRef);
1366 cb->setVertexInput(0, vertexBufferCount, vertexBuffers, indexBuffer, 0, subsetRenderable.subset.rhi.indexBuffer->indexFormat());
1367 cb->drawIndexed(subsetRenderable.subset.lodCount(subsetRenderable.subsetLevelOfDetail), instances, subsetRenderable.subset.lodOffset(subsetRenderable.subsetLevelOfDetail));
1368 QSSGRHICTX_STAT(rhiCtx, drawIndexed(subsetRenderable.subset.lodCount(subsetRenderable.subsetLevelOfDetail), instances));
1370 cb->setVertexInput(0, vertexBufferCount, vertexBuffers);
1371 cb->draw(subsetRenderable.subset.count, instances, subsetRenderable.subset.offset);
1372 QSSGRHICTX_STAT(rhiCtx, draw(subsetRenderable.subset.count, instances));
1374 Q_QUICK3D_PROFILE_END_WITH_IDS(QQuick3DProfiler::Quick3DRenderCall, (subsetRenderable.subset.count | quint64(instances) << 32),
1375 QVector<
int>({subsetRenderable.modelContext.model.profilingId,
1376 subsetRenderable.material.profilingId}));
1379 case QSSGRenderableObject::Type::CustomMaterialMeshSubset:
1381 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(object));
1382 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
1383 customMaterialSystem.rhiRenderRenderable(rhiCtx, subsetRenderable, needsSetViewport, cubeFace, state, userPassIndex);
1386 case QSSGRenderableObject::Type::Particles:
1389 QSSGParticleRenderer::rhiRenderRenderable(rhiCtx, renderable, needsSetViewport, cubeFace, state);
1414 QSSGPassKey passKey,
1415 QSSGRhiGraphicsPipelineState &ps,
1416 QSSGRenderShadowMap &shadowMapManager,
1417 const QSSGRenderCamera &camera,
1418 QSSGRenderCamera *debugCamera,
1420 const QSSGRenderableObjectList &sortedOpaqueObjects,
1422 const QSSGBounds3 &castingObjectsBox,
1423 const QSSGBounds3 &receivingObjectsBox)
1426 QSSGDebugDrawSystem *debugDrawSystem = renderer.contextInterface()->debugDrawSystem().get();
1427 const bool drawDirectionalLightShadowBoxes = layerData.layer.drawDirectionalLightShadowBoxes;
1428 const bool drawPointLightShadowBoxes = layerData.layer.drawPointLightShadowBoxes;
1429 const bool drawShadowCastingBounds = layerData.layer.drawShadowCastingBounds;
1430 const bool drawShadowReceivingBounds = layerData.layer.drawShadowReceivingBounds;
1431 const bool drawCascades = layerData.layer.drawCascades;
1432 const bool drawSceneCascadeIntersection = layerData.layer.drawSceneCascadeIntersection;
1433 const bool disableShadowCameraUpdate = layerData.layer.disableShadowCameraUpdate;
1434 const bool drawCulledObjects = layerData.layer.drawCulledObjects;
1435 QVector<
bool> debugIsObjectCulled = drawCulledObjects ? QVector<
bool>(sortedOpaqueObjects.size(),
true) : QVector<
bool>();
1437 static const auto rhiRenderOneShadowMap = [](QSSGRhiContext *rhiCtx,
1438 QSSGRhiGraphicsPipelineState *ps,
1439 const QSSGRenderableObjectList &sortedOpaqueObjects,
1441 const QSSGBounds3 cameraBounds,
1442 QVector<
bool> &debugIsObjectCulled,
1443 bool drawCulledObjects) {
1444 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1445 bool needsSetViewport =
true;
1447 for (
int i = 0, n = sortedOpaqueObjects.size(); i < n; ++i) {
1452 if (theObject->globalBoundsInstancing.isFinite() && theObject->globalBounds.isFinite()) {
1453 const QSSGBounds3 &globalBounds = !theObject->globalBoundsInstancing.isEmpty() ? theObject->globalBoundsInstancing
1454 : theObject->globalBounds;
1455 if (!globalBounds.isEmpty() && !cameraBounds.intersects(globalBounds)) {
1460 if (Q_UNLIKELY(drawCulledObjects))
1461 debugIsObjectCulled[i] =
false;
1464 if (theObject->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || theObject->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
1465 QSSGSubsetRenderable *renderable(
static_cast<QSSGSubsetRenderable *>(theObject));
1467 QRhiBuffer *vertexBuffer = renderable->subset.rhi.vertexBuffer->buffer();
1468 QRhiBuffer *indexBuffer = renderable->subset.rhi.indexBuffer
1469 ? renderable->subset.rhi.indexBuffer->buffer()
1473 if (!renderable->rhiRenderData.shadowPass.pipeline)
1476 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderCall);
1478 cb->setGraphicsPipeline(renderable->rhiRenderData.shadowPass.pipeline);
1480 QRhiShaderResourceBindings *srb = renderable->rhiRenderData.shadowPass.srb[cubeFace];
1481 cb->setShaderResources(srb);
1483 if (needsSetViewport) {
1484 cb->setViewport(ps->viewport);
1485 needsSetViewport =
false;
1488 QRhiCommandBuffer::VertexInput vertexBuffers[2];
1489 int vertexBufferCount = 1;
1490 vertexBuffers[0] = QRhiCommandBuffer::VertexInput(vertexBuffer, 0);
1491 quint32 instances = 1;
1492 if (renderable->modelContext.model.instancing()) {
1493 instances = renderable->modelContext.model.instanceCount();
1494 vertexBuffers[1] = QRhiCommandBuffer::VertexInput(renderable->instanceBuffer, 0);
1495 vertexBufferCount = 2;
1498 cb->setVertexInput(0, vertexBufferCount, vertexBuffers, indexBuffer, 0, renderable->subset.rhi.indexBuffer->indexFormat());
1499 cb->drawIndexed(renderable->subset.lodCount(renderable->subsetLevelOfDetail), instances, renderable->subset.lodOffset(renderable->subsetLevelOfDetail));
1500 QSSGRHICTX_STAT(rhiCtx, drawIndexed(renderable->subset.lodCount(renderable->subsetLevelOfDetail), instances));
1502 cb->setVertexInput(0, vertexBufferCount, vertexBuffers);
1503 cb->draw(renderable->subset.count, instances, renderable->subset.offset);
1504 QSSGRHICTX_STAT(rhiCtx, draw(renderable->subset.count, instances));
1506 Q_QUICK3D_PROFILE_END_WITH_IDS(QQuick3DProfiler::Quick3DRenderCall, (renderable->subset.count | quint64(instances) << 32),
1507 QVector<
int>({renderable->modelContext.model.profilingId,
1508 renderable->material.profilingId}));
1513 static const auto rhiClearShadowMap = [](
QSSGRenderer &renderer, QSSGRenderShadowMap &shadowMapManager, QSSGRhiContext *rhiCtx, QSSGRhiGraphicsPipelineState *ps, QRhiRenderPassDescriptor *renderPassDesc) {
1514 auto clearShadowMapShaderPipeline = renderer.contextInterface()->shaderCache()->getBuiltInRhiShaders().getRhiClearShadowMapShader();
1515 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(*ps, clearShadowMapShaderPipeline.get());
1518 ps->flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled,
false);
1519 ps->flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled,
false);
1520 renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx, ps, shadowMapManager.shadowClearSrb(), renderPassDesc, {});
1522 ps->flags |= { QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled };
1525 QRhi *rhi = rhiCtx->rhi();
1526 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1530 QVector2D depthAdjust;
1531 if (rhi->isClipDepthZeroToOne()) {
1533 depthAdjust[0] = 0.0f;
1534 depthAdjust[1] = 1.0f;
1537 depthAdjust[0] = 1.0f;
1538 depthAdjust[1] = 0.5f;
1541 if (drawShadowCastingBounds)
1543 if (drawShadowReceivingBounds)
1547 const QSize atlasTextureSize = shadowMapManager.shadowMapAtlasTexture()->pixelSize();
1549 renderer.rhiQuadRenderer()->prepareQuad(rhiCtx,
nullptr);
1550 for (
int i = 0, ie = globalLights.size(); i != ie; ++i) {
1551 if (!globalLights[i].shadows || globalLights[i].light->m_fullyBaked)
1558 const auto &light = globalLights[i].light;
1560 if (!shadowMapManager.shadowMapAtlasTexture())
1563 if (light->type == QSSGRenderLight::Type::DirectionalLight || light->type == QSSGRenderLight::Type::SpotLight) {
1564 const QSize size = atlasTextureSize * pEntry->m_atlasInfo[0].uvScale;
1568 if (!disableShadowCameraUpdate && debugCamera) {
1569 debugCamera->clipPlanes = camera.clipPlanes;
1570 debugCamera->projection = camera.projection;
1574 debugCamera->localTransform = layerData.getGlobalTransform(camera);
1577 QVarLengthArray<std::unique_ptr<QSSGRenderCamera>, 4> cascades;
1578 if (light->type == QSSGRenderLight::Type::DirectionalLight) {
1579 const float pcfRadius = light->m_softShadowQuality == QSSGRenderLight::SoftShadowQuality::Hard ? 0.f : light->m_pcfFactor;
1580 const float clipNear = camera.clipPlanes.clipNear();
1581 const float clipFar = qMin(light->m_shadowMapFar, camera.clipPlanes.clipFar());
1582 const float clipRange = clipFar - clipNear;
1583 cascades = setupCascadingCamerasForShadowMap(layerData,
1584 disableShadowCameraUpdate ? *debugCamera : camera,
1591 receivingObjectsBox,
1592 light->m_lockShadowmapTexels,
1595 drawSceneCascadeIntersection);
1598 pEntry->m_csmSplits[0] = clipNear + clipRange * (light->m_csmNumSplits > 0 ? light->m_csmSplit1 : 1.0f);
1599 pEntry->m_csmSplits[1] = clipNear + clipRange * (light->m_csmNumSplits > 1 ? light->m_csmSplit2 : 1.0f);
1600 pEntry->m_csmSplits[2] = clipNear + clipRange * (light->m_csmNumSplits > 2 ? light->m_csmSplit3 : 1.0f);
1601 pEntry->m_csmSplits[3] = clipNear + clipRange * 1.0f;
1602 pEntry->m_shadowMapFar = clipFar;
1603 }
else if (light->type == QSSGRenderLight::Type::SpotLight) {
1604 auto spotlightCamera =
std::make_unique<QSSGRenderCamera>(QSSGRenderCamera::Type::PerspectiveCamera);
1605 spotlightCamera->fov = QSSGRenderCamera::FieldOfView::fromDegrees(light->m_coneAngle * 2.0f);
1606 spotlightCamera->clipPlanes = { 1.0f, light->m_shadowMapFar };
1607 const QMatrix4x4 lightGlobalTransform = layerData.getGlobalTransform(*light);
1608 const QVector3D lightDir = QSSGRenderNode::getDirection(lightGlobalTransform);
1609 const QVector3D lightPos = QSSGRenderNode::getGlobalPos(lightGlobalTransform) - lightDir * spotlightCamera->clipPlanes.clipNear();
1610 const QVector3D lightPivot = light->pivot;
1611 const QVector3D forward = lightDir.normalized();
1612 const QVector3D right = qFuzzyCompare(qAbs(forward.y()), 1.0f)
1613 ? QVector3D::crossProduct(forward, QVector3D(1, 0, 0)).normalized()
1614 : QVector3D::crossProduct(forward, QVector3D(0, 1, 0)).normalized();
1615 const QVector3D up = QVector3D::crossProduct(right, forward).normalized();
1616 spotlightCamera->localTransform = QSSGRenderNode::calculateTransformMatrix(lightPos,
1617 QSSGRenderNode::initScale,
1619 QQuaternion::fromDirection(forward, up));
1620 QRectF theViewport(0.0f, 0.0f, (
float)light->m_shadowMapRes, (
float)light->m_shadowMapRes);
1621 QSSGRenderCamera::calculateProjectionInternal(*spotlightCamera, theViewport);
1622 cascades.push_back(
std::move(spotlightCamera));
1623 pEntry->m_shadowMapFar = light->m_shadowMapFar;
1628 memset(pEntry->m_csmActive, 0,
sizeof(pEntry->m_csmActive));
1630 QMatrix4x4 cascadeCameraGlobalTransforms(Qt::Uninitialized);
1631 const QMatrix4x4 bias = { 0.5, 0.0, 0.0, 0.5,
1634 0.0, 0.0, 0.0, 1.0 };
1636 for (
int cascadeIndex = 0; cascadeIndex < cascades.length(); cascadeIndex++) {
1637 const auto &cascadeCamera = cascades[cascadeIndex];
1641 cascadeCameraGlobalTransforms = layerData.getGlobalTransform(*cascadeCamera);
1642 pEntry->m_csmActive[cascadeIndex] = 1.f;
1643 QMatrix4x4 &viewProjection = pEntry->m_lightViewProjection[cascadeIndex];
1644 cascadeCamera->calculateViewProjectionMatrix(cascadeCameraGlobalTransforms, viewProjection);
1645 pEntry->m_lightViewProjection[cascadeIndex] = viewProjection;
1646 pEntry->m_fixedScaleBiasMatrix[cascadeIndex] = bias * viewProjection;
1647 const QMatrix4x4 inverted = viewProjection.inverted();
1648 const float x = 0.5f / (inverted * QVector4D(1, 0, 0, 0)).length();
1649 const float y = 0.5f / (inverted * QVector4D(0, 1, 0, 0)).length();
1650 const float z = 0.5f / (inverted * QVector4D(0, 0, 1, 0)).length();
1651 const QSSGBoxPoints frustumPoints = computeFrustumBounds(viewProjection);
1652 const QSSGBounds3 bounds = QSSGBounds3(frustumPoints);
1653 pEntry->m_dimensionsInverted[cascadeIndex] = QVector4D(x, y, z, 0.0f);
1654 pEntry->m_lightView = cascadeCameraGlobalTransforms.inverted();
1655 const bool isOrtho = cascadeCamera->type == QSSGRenderGraphObject::Type::OrthographicCamera;
1656 ps.viewport = calculateAtlasViewport(atlasTextureSize, pEntry->m_atlasInfo[cascadeIndex], rhi->isYUpInFramebuffer());
1657 rhiPrepareResourcesForShadowMap(rhiCtx, layerData, passKey, pEntry, &ps, &depthAdjust, sortedOpaqueObjects, *cascadeCamera, isOrtho, QSSGRenderTextureCubeFaceNone, cascadeIndex);
1660 QRhiTextureRenderTarget *rt = pEntry->m_rhiRenderTargets[cascadeIndex];
1661 cb->beginPass(rt, Qt::white, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
1662 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1663 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rt));
1664 rhiClearShadowMap(renderer, shadowMapManager, rhiCtx, &ps, rt->renderPassDescriptor());
1665 rhiRenderOneShadowMap(rhiCtx, &ps, sortedOpaqueObjects, 0, bounds, debugIsObjectCulled, drawCulledObjects);
1667 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1669 if (drawDirectionalLightShadowBoxes) {
1673 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"shadow_map"));
1675 const QSize size = atlasTextureSize * pEntry->m_atlasInfo[0].uvScale;
1676 ps.viewport = QRhiViewport(0, 0,
float(size.width()),
float(size.height()));
1678 QSSGRenderCamera theCameras[6] { QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1679 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1680 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1681 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1682 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1683 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera} };
1684 const float shadowMapFar = qMax<
float>(2.0f, light->m_shadowMapFar);
1685 setupCubeShadowCameras(layerData, light, shadowMapFar, theCameras);
1686 pEntry->m_lightView = QMatrix4x4();
1687 pEntry->m_shadowMapFar = shadowMapFar;
1689 const bool swapYFaces = !rhi->isYUpInFramebuffer();
1690 QMatrix4x4 cameraGlobalTransform(Qt::Uninitialized);
1691 for (
const auto face : QSSGRenderTextureCubeFaces) {
1692 cameraGlobalTransform = layerData.getGlobalTransform(theCameras[quint8(face)]);
1693 theCameras[quint8(face)].calculateViewProjectionMatrix(cameraGlobalTransform, pEntry->m_lightViewProjection[0]);
1694 pEntry->m_lightCubeView[quint8(face)] = cameraGlobalTransform.inverted();
1696 rhiPrepareResourcesForShadowMap(rhiCtx,
1702 sortedOpaqueObjects,
1703 theCameras[quint8(face)],
1710 const QVector3D center = QSSGRenderNode::getGlobalPos(layerData.getGlobalTransform(*light));
1711 const QSSGBounds3 bounds = QSSGBounds3(center - QVector3D(shadowMapFar, shadowMapFar, shadowMapFar),
1712 center + QVector3D(shadowMapFar, shadowMapFar, shadowMapFar));
1714 for (
const auto face : QSSGRenderTextureCubeFaces) {
1718 QSSGRenderTextureCubeFace outFace = face;
1736 if (outFace == QSSGRenderTextureCubeFace::PosY)
1737 outFace = QSSGRenderTextureCubeFace::NegY;
1738 else if (outFace == QSSGRenderTextureCubeFace::NegY)
1739 outFace = QSSGRenderTextureCubeFace::PosY;
1741 QRhiTextureRenderTarget *rt = pEntry->m_rhiRenderTargetCube[quint8(outFace)];
1742 cb->beginPass(rt, Qt::white, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
1743 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rt));
1744 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1745 rhiRenderOneShadowMap(rhiCtx, &ps, sortedOpaqueObjects, quint8(face), bounds, debugIsObjectCulled, drawCulledObjects);
1747 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1748 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QSSG_RENDERPASS_NAME(
"shadow_cube", 0, outFace));
1755 QRhiTextureRenderTarget *rtFront = pEntry->m_rhiRenderTargets[0];
1756 QRhiRenderPassDescriptor *frontDesc = pEntry->m_rhiRenderPassDesc[0];
1757 auto atlasShaderPipeline = renderer.contextInterface()->shaderCache()->getBuiltInRhiShaders().getRhiCubeMapToAtlasShader();
1758 ps.viewport = calculateAtlasViewport(atlasTextureSize, pEntry->m_atlasInfo[0], rhi->isYUpInFramebuffer());
1759 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, atlasShaderPipeline.get());
1760 QRhiShaderResourceBindings *srb = pEntry->m_cubeToAtlasFrontSrb;
1761 cb->beginPass(rtFront, Qt::white, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
1762 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rtFront));
1763 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1765 renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx, &ps, srb, frontDesc, QSSGRhiQuadRenderer::UvCoords);
1768 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1769 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QSSG_RENDERPASS_NAME(
"shadow_atlas", 6, 0));
1772 QRhiTextureRenderTarget *rtBack = pEntry->m_rhiRenderTargets[1];
1773 QRhiRenderPassDescriptor *backDesc = pEntry->m_rhiRenderPassDesc[1];
1774 srb = pEntry->m_cubeToAtlasBackSrb;
1775 ps.viewport = calculateAtlasViewport(atlasTextureSize, pEntry->m_atlasInfo[1], rhi->isYUpInFramebuffer());
1776 cb->beginPass(rtBack, Qt::white, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
1777 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rtBack));
1778 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1780 renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx, &ps, srb, backDesc, QSSGRhiQuadRenderer::UvCoords);
1783 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1784 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QSSG_RENDERPASS_NAME(
"shadow_atlas", 7, 0));
1788 ps = layerData.getPipelineState();
1789 ps.flags |= { QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled };
1791 ps.slopeScaledDepthBias = 1.5f;
1793 if (drawPointLightShadowBoxes) {
1799 if (Q_UNLIKELY(drawCulledObjects)) {
1800 for (
int i = 0, n = sortedOpaqueObjects.size(); i < n; ++i) {
1802 const QSSGBounds3 &globalBounds = !theObject->globalBoundsInstancing.isEmpty() ? theObject->globalBoundsInstancing
1803 : theObject->globalBounds;
1804 const QColor color = debugIsObjectCulled[i] ? QColorConstants::Red : QColorConstants::Green;
1811 QSSGPassKey passKey,
1813 QSSGRhiGraphicsPipelineState *ps,
1814 QSSGRenderReflectionMap &reflectionMapManager,
1815 const QVector<QSSGRenderReflectionProbe *> &reflectionProbes,
1816 const QSSGRenderableObjectList &reflectionPassObjects,
1819 QRhi *rhi = rhiCtx->rhi();
1820 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1822 const bool renderSkybox = (inData.layer.background == QSSGRenderLayer::Background::SkyBox ||
1823 inData.layer.background == QSSGRenderLayer::Background::SkyBoxCubeMap)
1824 && rhiCtx->rhi()->isFeatureSupported(QRhi::TexelFetch);
1826 for (
int i = 0, ie = reflectionProbes.size(); i != ie; ++i) {
1831 if (!pEntry->m_needsRender)
1834 if (reflectionProbes[i]->refreshMode == QSSGRenderReflectionProbe::ReflectionRefreshMode::FirstFrame && pEntry->m_rendered)
1837 if (reflectionProbes[i]->texture)
1840 Q_ASSERT(pEntry->m_rhiDepthStencil);
1841 Q_ASSERT(pEntry->m_rhiCube);
1843 const QSize size = pEntry->m_rhiCube->pixelSize();
1844 ps->viewport = QRhiViewport(0, 0,
float(size.width()),
float(size.height()));
1846 QSSGRenderCamera theCameras[6] { QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1847 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1848 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1849 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1850 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera},
1851 QSSGRenderCamera{QSSGRenderCamera::Type::PerspectiveCamera} };
1852 setupCubeReflectionCameras(inData, reflectionProbes[i], theCameras);
1853 const bool swapYFaces = !rhi->isYUpInFramebuffer();
1854 QMatrix4x4 cameraGlobalTransform(Qt::Uninitialized);
1855 for (
const auto face : QSSGRenderTextureCubeFaces) {
1856 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(face);
1857 cameraGlobalTransform = inData.getGlobalTransform(theCameras[cubeFaceIdx]);
1858 theCameras[cubeFaceIdx].calculateViewProjectionMatrix(cameraGlobalTransform, pEntry->m_viewProjection);
1860 rhiPrepareResourcesForReflectionMap(rhiCtx, passKey, inData, pEntry, ps,
1861 reflectionPassObjects, theCameras[cubeFaceIdx], renderer, face);
1863 QRhiRenderPassDescriptor *renderPassDesc =
nullptr;
1864 for (
auto face : QSSGRenderTextureCubeFaces) {
1865 if (pEntry->m_timeSlicing == QSSGRenderReflectionProbe::ReflectionTimeSlicing::IndividualFaces)
1866 face = pEntry->m_timeSliceFace;
1868 QSSGRenderTextureCubeFace outFace = face;
1872 if (outFace == QSSGRenderTextureCubeFace::PosY)
1873 outFace = QSSGRenderTextureCubeFace::NegY;
1874 else if (outFace == QSSGRenderTextureCubeFace::NegY)
1875 outFace = QSSGRenderTextureCubeFace::PosY;
1877 QRhiTextureRenderTarget *rt = pEntry->m_rhiRenderTargets[quint8(outFace)];
1878 cb->beginPass(rt, reflectionProbes[i]->clearColor, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
1879 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rt));
1880 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1882 if (renderSkybox && pEntry->m_skyBoxSrbs[quint8(face)]) {
1883 const auto &shaderCache = renderer.contextInterface()->shaderCache();
1884 const bool isSkyBox = inData.layer.background == QSSGRenderLayer::Background::SkyBox;
1885 const auto &shaderPipeline = isSkyBox ? shaderCache->getBuiltInRhiShaders().getRhiSkyBoxShader(QSSGRenderLayer::TonemapMode::None, inData.layer.skyBoxIsRgbe8, 1)
1886 : shaderCache->getBuiltInRhiShaders().getRhiSkyBoxCubeShader(QSSGRenderLayer::TonemapMode::None, !inData.layer.skyBoxIsSrgb, 1);
1887 Q_ASSERT(shaderPipeline);
1888 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(*ps, shaderPipeline.get());
1889 QRhiShaderResourceBindings *srb = pEntry->m_skyBoxSrbs[quint8(face)];
1890 if (!renderPassDesc)
1891 renderPassDesc = rt->newCompatibleRenderPassDescriptor();
1892 rt->setRenderPassDescriptor(renderPassDesc);
1893 isSkyBox ? renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx, ps, srb, renderPassDesc, {})
1894 : renderer.rhiCubeRenderer()->recordRenderCube(rhiCtx, ps, srb, renderPassDesc, {});
1897 bool needsSetViewport =
true;
1898 for (
const auto &handle : reflectionPassObjects)
1899 rhiRenderRenderable(rhiCtx, *ps, *handle.obj, &needsSetViewport, face);
1902 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1903 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QSSG_RENDERPASS_NAME(
"reflection_cube", 0, outFace));
1905 if (pEntry->m_timeSlicing == QSSGRenderReflectionProbe::ReflectionTimeSlicing::IndividualFaces)
1909 renderPassDesc->deleteLater();
1911 pEntry->renderMips(rhiCtx);
1913 if (pEntry->m_timeSlicing == QSSGRenderReflectionProbe::ReflectionTimeSlicing::IndividualFaces)
1914 pEntry->m_timeSliceFace = QSSGBaseTypeHelpers::next(pEntry->m_timeSliceFace);
1916 if (reflectionProbes[i]->refreshMode == QSSGRenderReflectionProbe::ReflectionRefreshMode::FirstFrame)
1917 pEntry->m_rendered =
true;
1919 reflectionProbes[i]->hasScheduledUpdate =
false;
1920 pEntry->m_needsRender =
false;
1971 QSSGPassKey passKey,
1973 QSSGRhiShaderPipeline &shaderPipeline,
1974 QSSGRhiGraphicsPipelineState &ps,
1975 const QSSGAmbientOcclusionSettings &ao,
1976 const QSSGRhiRenderableTexture &rhiAoTexture,
1977 const QSSGRhiRenderableTexture &rhiDepthTexture,
1978 const QSSGRenderCamera &camera)
1980 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
1983 if (!rhiCtx->rhi()->isFeatureSupported(QRhi::TexelFetch)) {
1984 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1986 cb->beginPass(rhiAoTexture.rt, Qt::white, { 1.0f, 0 });
1987 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rhiAoTexture.rt));
1989 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
1993 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, &shaderPipeline);
1995 const float R2 = ao.aoDistance * ao.aoDistance * 0.16f;
1996 const QSize textureSize = rhiAoTexture.texture->pixelSize();
1997 const float rw =
float(textureSize.width());
1998 const float rh =
float(textureSize.height());
1999 const float fov = camera.fov.asVerticalFov(rw / rh).radians();
2000 const float tanHalfFovY = tanf(0.5f * fov * (rh / rw));
2001 const float invFocalLenX = tanHalfFovY * (rw / rh);
2003 const QVector4D aoProps(ao.aoStrength * 0.01f, ao.aoDistance * 0.4f, ao.aoSoftness * 0.02f, ao.aoBias);
2004 const QVector4D aoProps2(
float(ao.aoSamplerate), (ao.aoDither) ? 1.0f : 0.0f, 0.0f, 0.0f);
2005 const QVector4D aoScreenConst(1.0f / R2, rh / (2.0f * tanHalfFovY), 1.0f / rw, 1.0f / rh);
2006 const QVector4D uvToEyeConst(2.0f * invFocalLenX, -2.0f * tanHalfFovY, -invFocalLenX, tanHalfFovY);
2007 const QVector2D cameraProps = camera.clipPlanes;
2016 const int UBUF_SIZE = 72;
2017 QSSGRhiDrawCallData &dcd(rhiCtxD->drawCallData({ passKey,
nullptr,
nullptr, 0 }));
2019 dcd.ubuf = rhiCtx->rhi()->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, UBUF_SIZE);
2023 char *ubufData = dcd.ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2024 memcpy(ubufData, &aoProps, 16);
2025 memcpy(ubufData + 16, &aoProps2, 16);
2026 memcpy(ubufData + 32, &aoScreenConst, 16);
2027 memcpy(ubufData + 48, &uvToEyeConst, 16);
2028 memcpy(ubufData + 64, &cameraProps, 8);
2029 dcd.ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2031 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
2032 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
2033 QSSGRhiShaderResourceBindingList bindings;
2034 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd.ubuf);
2037 bindings.addTexture(1, QRhiShaderResourceBinding::FragmentStage, rhiDepthTexture.texture, sampler);
2038 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
2040 renderer.rhiQuadRenderer()->prepareQuad(rhiCtx,
nullptr);
2041 renderer.rhiQuadRenderer()->recordRenderQuadPass(rhiCtx, &ps, srb, rhiAoTexture.rt, {});
2189 QSSGPassKey passKey,
2190 QSSGRenderLayer &layer,
2191 QSSGRenderCameraList &cameras,
2195 uint tonemapMode = 0)
2197 QSSG_ASSERT(layer.renderData,
return);
2199 const auto *renderData = layer.renderData;
2201 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
2202 const bool cubeMapMode = layer.background == QSSGRenderLayer::Background::SkyBoxCubeMap;
2203 const QSSGRenderImageTexture lightProbeTexture =
2204 cubeMapMode ? renderer.contextInterface()->bufferManager()->loadRenderImage(layer.skyBoxCubeMap, QSSGBufferManager::MipModeDisable)
2205 : renderer.contextInterface()->bufferManager()->loadRenderImage(layer.lightProbe, QSSGBufferManager::MipModeBsdf);
2206 const bool hasValidTexture = lightProbeTexture.m_texture !=
nullptr;
2207 if (hasValidTexture) {
2208 if (cubeFace == QSSGRenderTextureCubeFaceNone)
2209 layer.skyBoxIsRgbe8 = lightProbeTexture.m_flags.isRgbe8();
2211 layer.skyBoxIsSrgb = !lightProbeTexture.m_flags.isLinear();
2213 QSSGRhiShaderResourceBindingList bindings;
2215 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
2216 QRhiSampler::Linear,
2217 cubeMapMode ? QRhiSampler::None : QRhiSampler::Linear,
2218 QRhiSampler::Repeat,
2219 QRhiSampler::ClampToEdge,
2220 QRhiSampler::Repeat });
2221 int samplerBinding = 1;
2222 const quint32 ubufSize = cameras.count() >= 2 ? 416 : 240;
2223 bindings.addTexture(samplerBinding,
2224 QRhiShaderResourceBinding::FragmentStage,
2225 lightProbeTexture.m_texture, sampler);
2227 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(cubeFace);
2228 const quintptr entryIdx = quintptr(cubeFace != QSSGRenderTextureCubeFaceNone) * cubeFaceIdx;
2229 QSSGRhiDrawCallData &dcd = rhiCtxD->drawCallData({ passKey,
nullptr, entry, entryIdx });
2231 QRhi *rhi = rhiCtx->rhi();
2233 dcd.ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, ubufSize);
2237 float adjustY = rhi->isYUpInNDC() ? 1.0f : -1.0f;
2238 const float exposure = layer.lightProbeSettings.probeExposure;
2240 const QMatrix3x3 &rotationMatrix(layer.lightProbeSettings.probeOrientation);
2243 const float blurAmountOrSrgb = cubeMapMode ? layer.skyBoxIsSrgb : layer.skyboxBlurAmount;
2244 const float maxMipLevelOrTonemapMode = cubeMapMode ?
float(tonemapMode) :
float(lightProbeTexture.m_mipmapCount - 2);
2246 const QVector4D skyboxProperties = {
2250 maxMipLevelOrTonemapMode
2253 char *ubufData = dcd.ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2254 quint32 ubufOffset = 0;
2256 memcpy(ubufData + ubufOffset, &skyboxProperties, 16);
2259 memcpy(ubufData + ubufOffset, rotationMatrix.constData(), 12);
2261 memcpy(ubufData + ubufOffset, (
char *)rotationMatrix.constData() + 12, 12);
2263 memcpy(ubufData + ubufOffset, (
char *)rotationMatrix.constData() + 24, 12);
2266 for (qsizetype viewIdx = 0; viewIdx < cameras.count(); ++viewIdx) {
2267 const QMatrix4x4 &inverseProjection = cameras[viewIdx]->projection.inverted();
2268 const QMatrix4x4 &viewMatrix = renderData->getGlobalTransform(*cameras[viewIdx]);
2269 QMatrix4x4 viewProjection(Qt::Uninitialized);
2270 cameras[viewIdx]->calculateViewProjectionWithoutTranslation(viewMatrix, 0.1f, 5.0f, viewProjection);
2272 quint32 viewDataOffset = ubufOffset;
2273 memcpy(ubufData + viewDataOffset + viewIdx * 64, viewProjection.constData(), 64);
2274 viewDataOffset += cameras.count() * 64;
2275 memcpy(ubufData + viewDataOffset + viewIdx * 64, inverseProjection.constData(), 64);
2276 viewDataOffset += cameras.count() * 64;
2277 memcpy(ubufData + viewDataOffset + viewIdx * 48, viewMatrix.constData(), 48);
2279 dcd.ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2281 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd.ubuf);
2283 if (cubeFace != QSSGRenderTextureCubeFaceNone) {
2284 const auto cubeFaceIdx = QSSGBaseTypeHelpers::indexOfCubeFace(cubeFace);
2285 entry->m_skyBoxSrbs[cubeFaceIdx] = rhiCtxD->srb(bindings);
2287 layer.skyBoxSrb = rhiCtxD->srb(bindings);
2291 renderer.rhiCubeRenderer()->prepareCube(rhiCtx,
nullptr);
2293 renderer.rhiQuadRenderer()->prepareQuad(rhiCtx,
nullptr);
2330 QSSGPassKey passKey,
2331 const QSSGRhiGraphicsPipelineState &basePipelineState,
2332 QRhiRenderPassDescriptor *rpDesc,
2334 const QSSGRenderableObjectList &sortedOpaqueObjects,
2335 const QSSGRenderableObjectList &sortedTransparentObjects,
2339 static const auto rhiPrepareDepthPassForObject = [](QSSGRhiContext *rhiCtx,
2340 QSSGPassKey passKey,
2343 QRhiRenderPassDescriptor *rpDesc,
2344 QSSGRhiGraphicsPipelineState *ps) {
2345 QSSGRhiShaderPipelinePtr shaderPipeline;
2346 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
2348 const bool isOpaqueDepthPrePass = obj->depthWriteMode == QSSGDepthDrawMode::OpaquePrePass;
2349 QSSGShaderFeatures featureSet;
2350 featureSet.set(QSSGShaderFeatures::Feature::DepthPass,
true);
2351 if (isOpaqueDepthPrePass)
2352 featureSet.set(QSSGShaderFeatures::Feature::OpaqueDepthPrePass,
true);
2354 QSSGRhiDrawCallData *dcd =
nullptr;
2355 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2356 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
2357 const void *modelNode = &subsetRenderable.modelContext.model;
2358 dcd = &rhiCtxD->drawCallData({ passKey, modelNode, &subsetRenderable.material, 0 });
2361 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset) {
2362 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
2363 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
2364 ps->cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
2366 shaderPipeline = shadersForDefaultMaterial(ps, subsetRenderable, featureSet);
2367 if (shaderPipeline) {
2368 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2369 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2370 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
2371 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2375 }
else if (obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2376 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
2378 const auto &customMaterial =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
2380 ps->cullMode = QSSGRhiHelpers::toCullMode(customMaterial.m_cullMode);
2382 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
2383 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(ps, customMaterial, subsetRenderable, inData.getDefaultMaterialPropertyTable(), featureSet);
2385 if (shaderPipeline) {
2386 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2387 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2388 customMaterialSystem.updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, ps, customMaterial, subsetRenderable,
2389 inData.renderedCameras,
nullptr,
nullptr);
2390 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2397 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2398 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
2399 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
2400 ia = subsetRenderable.subset.rhi.ia;
2402 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
2403 int instanceBufferBinding = setupInstancing(&subsetRenderable, ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
2404 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
2406 QSSGRhiShaderResourceBindingList bindings;
2407 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
2410 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
2412 if (isOpaqueDepthPrePass) {
2413 addOpaqueDepthPrePassBindings(rhiCtx,
2414 shaderPipeline.get(),
2415 subsetRenderable.firstImage,
2417 (obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset));
2423 const int normalTextureBinding = shaderPipeline->bindingForTexture(
"qt_normalTexture",
int(QSSGRhiSamplerBindingHints::NormalTexture));
2424 if (normalTextureBinding >= 0) {
2425 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
2426 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
2427 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
2428 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
2429 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
2430 bindings.addTexture(normalTextureBinding, RENDERER_VISIBILITY_ALL, dummyTexture, sampler);
2434 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
2435 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
2437 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
2438 QRhiSampler::Nearest,
2440 QRhiSampler::ClampToEdge,
2441 QRhiSampler::ClampToEdge,
2444 bindings.addTexture(binding,
2445 QRhiShaderResourceBinding::VertexStage,
2452 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
2453 if (targetsTexture) {
2454 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
2456 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
2457 QRhiSampler::Nearest,
2459 QRhiSampler::ClampToEdge,
2460 QRhiSampler::ClampToEdge,
2461 QRhiSampler::ClampToEdge
2463 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
2467 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
2469 subsetRenderable.rhiRenderData.depthPrePass.pipeline = rhiCtxD->pipeline(*ps,
2472 subsetRenderable.rhiRenderData.depthPrePass.srb = srb;
2483 QSSGRhiGraphicsPipelineState ps = basePipelineState;
2488 ps.samples = samples;
2489 ps.viewCount = viewCount;
2490 ps.flags |= { QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled };
2491 ps.targetBlend[0].colorWrite = {};
2493 for (
const QSSGRenderableObjectHandle &handle : sortedOpaqueObjects) {
2494 if (!rhiPrepareDepthPassForObject(rhiCtx, passKey, inData, handle.obj, rpDesc, &ps))
2498 for (
const QSSGRenderableObjectHandle &handle : sortedTransparentObjects) {
2499 if (!rhiPrepareDepthPassForObject(rhiCtx, passKey, inData, handle.obj, rpDesc, &ps))
2626 QSSGPassKey passKey,
2627 const QSSGRhiGraphicsPipelineState &basePipelineState,
2628 QRhiRenderPassDescriptor *rpDesc,
2630 const QSSGRenderableObjectList &sortedOpaqueObjects)
2632 QSSGRhiGraphicsPipelineState ps = basePipelineState;
2633 ps.depthFunc = QRhiGraphicsPipeline::LessOrEqual;
2634 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
false);
2636 for (
const QSSGRenderableObjectHandle &handle : sortedOpaqueObjects) {
2637 QSSGRenderableObject *obj = handle.obj;
2638 QSSGRhiShaderPipelinePtr shaderPipeline;
2639 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
2641 QSSGShaderFeatures featureSet;
2642 featureSet.set(QSSGShaderFeatures::Feature::NormalPass,
true);
2644 QSSGRhiDrawCallData *dcd =
nullptr;
2645 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2646 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
2647 const void *modelNode = &subsetRenderable.modelContext.model;
2648 dcd = &rhiCtxD->drawCallData({ passKey, modelNode, &subsetRenderable.material, 0 });
2651 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset) {
2652 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
2653 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
2654 ps.cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
2656 shaderPipeline = shadersForDefaultMaterial(&ps, subsetRenderable, featureSet);
2657 if (shaderPipeline) {
2658 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2659 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2660 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
2661 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2663 }
else if (obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2664 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
2666 const auto &customMaterial =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
2668 ps.cullMode = QSSGRhiHelpers::toCullMode(customMaterial.m_cullMode);
2670 const auto &customMaterialSystem = subsetRenderable.renderer->contextInterface()->customMaterialSystem();
2671 shaderPipeline = customMaterialSystem->shadersForCustomMaterial(&ps, customMaterial, subsetRenderable, inData.getDefaultMaterialPropertyTable(), featureSet);
2673 if (shaderPipeline) {
2674 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2675 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2676 customMaterialSystem->updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, customMaterial, subsetRenderable,
2677 inData.renderedCameras,
nullptr,
nullptr);
2678 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2683 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
2684 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
2685 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(ps);
2686 ia = subsetRenderable.subset.rhi.ia;
2688 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
2689 int instanceBufferBinding = setupInstancing(&subsetRenderable, &ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
2690 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
2692 QSSGRhiShaderResourceBindingList bindings;
2693 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
2696 QSSGRenderableImage *renderableImage = subsetRenderable.firstImage;
2697 while (renderableImage) {
2698 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(renderableImage->m_mapType);
2699 const int samplerHint =
int(renderableImage->m_mapType);
2700 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
2701 if (samplerBinding >= 0) {
2702 QRhiTexture *texture = renderableImage->m_texture.m_texture;
2703 if (samplerBinding >= 0 && texture) {
2704 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
2705 QSSGRhiSamplerDescription samplerDesc = {
2706 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
2707 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
2708 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
2709 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
2710 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
2711 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
2713 rhiCtx->checkAndAdjustForNPoT(texture, &samplerDesc);
2714 QRhiSampler *sampler = rhiCtx->sampler(samplerDesc);
2715 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
2718 renderableImage = renderableImage->m_nextImage;
2721 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
2724 const int normalTextureBinding = shaderPipeline->bindingForTexture(
"qt_normalTexture",
int(QSSGRhiSamplerBindingHints::NormalTexture));
2725 if (normalTextureBinding >= 0) {
2726 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
2727 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
2728 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
2729 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
2730 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
2731 bindings.addTexture(normalTextureBinding, RENDERER_VISIBILITY_ALL, dummyTexture, sampler);
2737 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
2738 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
2740 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
2741 QRhiSampler::Nearest,
2743 QRhiSampler::ClampToEdge,
2744 QRhiSampler::ClampToEdge,
2747 bindings.addTexture(binding,
2748 QRhiShaderResourceBinding::VertexStage,
2755 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
2756 if (targetsTexture) {
2757 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
2759 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
2760 QRhiSampler::Nearest,
2762 QRhiSampler::ClampToEdge,
2763 QRhiSampler::ClampToEdge,
2764 QRhiSampler::ClampToEdge
2766 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
2770 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
2772 subsetRenderable.rhiRenderData.normalPass.pipeline = rhiCtxD->pipeline(ps,
2775 subsetRenderable.rhiRenderData.normalPass.srb = srb;
2844 QSSGPassKey passKey,
2845 const QSSGRhiGraphicsPipelineState &basePipelineState,
2846 QRhiRenderPassDescriptor *rpDesc,
2847 QSSGRenderGraphObject *overrideMaterial,
2849 QSSGRenderableObjectList &inObjects,
2850 QSSGShaderFeatures featureSet,
2853 if (!overrideMaterial)
2856 QSSGRhiGraphicsPipelineState ps = basePipelineState;
2857 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
2859 const bool isCustomMaterial = (overrideMaterial->type == QSSGRenderGraphObject::Type::CustomMaterial);
2860 const bool isDefaultMaterial = (overrideMaterial->type == QSSGRenderGraphObject::Type::DefaultMaterial ||
2861 overrideMaterial->type == QSSGRenderGraphObject::Type::PrincipledMaterial ||
2862 overrideMaterial->type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial);
2864 if (!isCustomMaterial && !isDefaultMaterial) {
2865 qDebug() <<
"Override material must be a default or custom material.";
2869 for (
const QSSGRenderableObjectHandle &handle : inObjects) {
2870 QSSGRenderableObject *obj = handle.obj;
2872 if (obj->type != QSSGRenderableObject::Type::DefaultMaterialMeshSubset &&
2873 obj->type != QSSGRenderableObject::Type::CustomMaterialMeshSubset)
2876 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
2877 const void *modelNode = &subsetRenderable.modelContext.model;
2878 QSSGRhiDrawCallData *dcd = &rhiCtxD->drawCallData({ passKey, modelNode, overrideMaterial, 0 });
2884 QSSGRenderableObjectFlags renderableFlags = subsetRenderable.renderableFlags;
2885 float opacity = subsetRenderable.opacity;
2888 const bool hasAnyLights = !subsetRenderable.lights.isEmpty();
2889 const bool anyLightHasShadows = std::any_of(subsetRenderable.lights.begin(),
2890 subsetRenderable.lights.end(),
2891 [](
const QSSGShaderLight &light) {
return light.shadows; });
2895 auto layerPrepFlags = inData.layerPrepResult.getFlags();
2897 if (isCustomMaterial) {
2898 auto &material =
static_cast<QSSGRenderCustomMaterial &>(*overrideMaterial);
2899 auto prepResult = inData.prepareCustomMaterialForRender(material, renderableFlags, opacity,
2900 false, hasAnyLights, anyLightHasShadows,
2902 subsetRenderable.shaderDescription = prepResult.materialKey;
2904 auto &material =
static_cast<QSSGRenderDefaultMaterial &>(*overrideMaterial);
2905 auto prepResult = inData.prepareDefaultMaterialForRender(material, renderableFlags, opacity,
2906 hasAnyLights, anyLightHasShadows,
2908 subsetRenderable.shaderDescription = prepResult.materialKey;
2912 QSSGRhiShaderPipelinePtr shaderPipeline;
2914 if (isCustomMaterial) {
2915 const auto &material =
static_cast<
const QSSGRenderCustomMaterial &>(*overrideMaterial);
2916 ps.cullMode = QSSGRhiHelpers::toCullMode(material.m_cullMode);
2918 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
2919 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(&ps, material, subsetRenderable,
2920 inData.getDefaultMaterialPropertyTable(), featureSet);
2921 if (shaderPipeline) {
2922 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2923 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2924 customMaterialSystem.updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, material,
2925 subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
2926 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2929 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(*overrideMaterial);
2930 ps.cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
2932 shaderPipeline = shadersForDefaultMaterial(&ps, subsetRenderable, featureSet);
2933 if (shaderPipeline) {
2934 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
2935 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
2936 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, subsetRenderable,
2937 inData.renderedCameras,
nullptr,
nullptr);
2938 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
2942 if (!shaderPipeline)
2945 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(ps);
2946 ia = subsetRenderable.subset.rhi.ia;
2948 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
2949 int instanceBufferBinding = setupInstancing(&subsetRenderable, &ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
2950 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
2952 QSSGRhiShaderResourceBindingList bindings;
2953 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
2956 QSSGRenderableImage *renderableImage = subsetRenderable.firstImage;
2957 while (renderableImage) {
2958 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(renderableImage->m_mapType);
2959 const int samplerHint =
int(renderableImage->m_mapType);
2960 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
2961 if (samplerBinding >= 0) {
2962 QRhiTexture *texture = renderableImage->m_texture.m_texture;
2964 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
2965 QSSGRhiSamplerDescription samplerDesc = {
2966 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
2967 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
2968 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
2969 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
2970 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
2971 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
2973 rhiCtx->checkAndAdjustForNPoT(texture, &samplerDesc);
2974 QRhiSampler *sampler = rhiCtx->sampler(samplerDesc);
2975 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
2978 renderableImage = renderableImage->m_nextImage;
2981 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
2984 const int normalTextureBinding = shaderPipeline->bindingForTexture(
"qt_normalTexture",
int(QSSGRhiSamplerBindingHints::NormalTexture));
2985 if (normalTextureBinding >= 0) {
2986 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
2987 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
2988 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
2989 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
2990 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
2991 bindings.addTexture(normalTextureBinding, RENDERER_VISIBILITY_ALL, dummyTexture, sampler);
2995 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
2996 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
2998 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
2999 QRhiSampler::Nearest,
3001 QRhiSampler::ClampToEdge,
3002 QRhiSampler::ClampToEdge,
3005 bindings.addTexture(binding,
3006 QRhiShaderResourceBinding::VertexStage,
3013 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
3014 if (targetsTexture) {
3015 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
3017 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3018 QRhiSampler::Nearest,
3020 QRhiSampler::ClampToEdge,
3021 QRhiSampler::ClampToEdge,
3022 QRhiSampler::ClampToEdge
3024 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
3029 if (shaderPipeline->isLightingEnabled()) {
3030 bindings.addUniformBuffer(1, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3031 shaderPipeline->ub0LightDataOffset(),
3032 sizeof(QSSGShaderLightsUniformData));
3033 bindings.addUniformBuffer(2, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3034 shaderPipeline->ub0DirectionalLightDataOffset(),
3035 sizeof(QSSGShaderDirectionalLightsUniformData));
3038 auto shadowMapAtlas = shaderPipeline->shadowMapAtlasTexture();
3039 if (shadowMapAtlas) {
3040 int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_texture");
3042 QRhiTexture *texture = shadowMapAtlas;
3043 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
3044 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
3045 Q_ASSERT(texture && sampler);
3046 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3051 if (shaderPipeline->lightProbeTexture()) {
3052 int binding = shaderPipeline->bindingForTexture(
"qt_lightProbe",
int(QSSGRhiSamplerBindingHints::LightProbe));
3054 auto tiling = shaderPipeline->lightProbeTiling();
3055 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
3056 QSSGRhiHelpers::toRhi(tiling.first), QSSGRhiHelpers::toRhi(tiling.second), QRhiSampler::Repeat });
3057 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage,
3058 shaderPipeline->lightProbeTexture(), sampler);
3063 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
3065 QSSG_ASSERT(srb,
continue);
3066 QSSG_ASSERT(std::size(subsetRenderable.rhiRenderData.userPassData) > index,
continue);
3068 auto &rhiPassData = subsetRenderable.rhiRenderData.userPassData[index];
3069 rhiPassData.pipeline = rhiCtxD->pipeline(ps, rpDesc, srb);
3070 rhiPassData.srb = srb;
3075 QSSGPassKey passKey,
3076 const QSSGRhiGraphicsPipelineState &basePipelineState,
3077 QRhiRenderPassDescriptor *rpDesc,
3079 QSSGRenderableObjectList &inObjects,
3080 QSSGShaderFeatures featureSet,
3083 QSSGRhiGraphicsPipelineState ps = basePipelineState;
3084 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
3086 for (
const QSSGRenderableObjectHandle &handle : inObjects) {
3087 QSSGRenderableObject *obj = handle.obj;
3088 QSSGRhiShaderPipelinePtr shaderPipeline;
3090 QSSGRhiDrawCallData *dcd =
nullptr;
3091 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset ||
3092 obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3093 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3094 const void *modelNode = &subsetRenderable.modelContext.model;
3095 dcd = &rhiCtxD->drawCallData({ passKey, modelNode, &subsetRenderable.material, 0 });
3098 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset) {
3099 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3100 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
3101 ps.cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
3103 shaderPipeline = shadersForDefaultMaterial(&ps, subsetRenderable, featureSet);
3104 if (shaderPipeline) {
3105 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
3106 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
3107 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, subsetRenderable,
3108 inData.renderedCameras,
nullptr,
nullptr);
3109 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
3111 }
else if (obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3112 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3113 const auto &material =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
3114 ps.cullMode = QSSGRhiHelpers::toCullMode(material.m_cullMode);
3116 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
3117 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(&ps, material, subsetRenderable,
3118 inData.getDefaultMaterialPropertyTable(), featureSet);
3119 if (shaderPipeline) {
3120 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
3121 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
3122 customMaterialSystem.updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, material,
3123 subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
3124 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
3128 if (!shaderPipeline)
3132 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset ||
3133 obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3134 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
3135 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(ps);
3136 ia = subsetRenderable.subset.rhi.ia;
3138 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
3139 int instanceBufferBinding = setupInstancing(&subsetRenderable, &ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
3140 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
3142 QSSGRhiShaderResourceBindingList bindings;
3143 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
3146 QSSGRenderableImage *renderableImage = subsetRenderable.firstImage;
3147 while (renderableImage) {
3148 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(renderableImage->m_mapType);
3149 const int samplerHint =
int(renderableImage->m_mapType);
3150 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
3151 if (samplerBinding >= 0) {
3152 QRhiTexture *texture = renderableImage->m_texture.m_texture;
3153 if (samplerBinding >= 0 && texture) {
3154 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
3155 QSSGRhiSamplerDescription samplerDesc = {
3156 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
3157 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
3158 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
3159 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
3160 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
3161 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
3163 rhiCtx->checkAndAdjustForNPoT(texture, &samplerDesc);
3164 QRhiSampler *sampler = rhiCtx->sampler(samplerDesc);
3165 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
3168 renderableImage = renderableImage->m_nextImage;
3171 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
3174 const int normalTextureBinding = shaderPipeline->bindingForTexture(
"qt_normalTexture",
int(QSSGRhiSamplerBindingHints::NormalTexture));
3175 if (normalTextureBinding >= 0) {
3176 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
3177 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
3178 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3179 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
3180 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3181 bindings.addTexture(normalTextureBinding, RENDERER_VISIBILITY_ALL, dummyTexture, sampler);
3185 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
3186 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
3188 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3189 QRhiSampler::Nearest,
3191 QRhiSampler::ClampToEdge,
3192 QRhiSampler::ClampToEdge,
3195 bindings.addTexture(binding,
3196 QRhiShaderResourceBinding::VertexStage,
3203 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
3204 if (targetsTexture) {
3205 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
3207 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3208 QRhiSampler::Nearest,
3210 QRhiSampler::ClampToEdge,
3211 QRhiSampler::ClampToEdge,
3212 QRhiSampler::ClampToEdge
3214 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
3219 if (shaderPipeline->isLightingEnabled()) {
3220 bindings.addUniformBuffer(1, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3221 shaderPipeline->ub0LightDataOffset(),
3222 sizeof(QSSGShaderLightsUniformData));
3223 bindings.addUniformBuffer(2, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3224 shaderPipeline->ub0DirectionalLightDataOffset(),
3225 sizeof(QSSGShaderDirectionalLightsUniformData));
3228 auto shadowMapAtlas = shaderPipeline->shadowMapAtlasTexture();
3229 if (shadowMapAtlas) {
3230 int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_texture");
3232 QRhiTexture *texture = shadowMapAtlas;
3233 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
3234 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
3235 Q_ASSERT(texture && sampler);
3236 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3241 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture"); binding >= 0) {
3242 if (
auto shadowMapBlueNoise = shaderPipeline->shadowMapBlueNoiseTexture()) {
3243 int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture");
3245 QRhiTexture *texture = shadowMapBlueNoise;
3246 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3247 QRhiSampler::Linear,
3249 QRhiSampler::Repeat,
3250 QRhiSampler::Repeat,
3251 QRhiSampler::Repeat });
3252 Q_ASSERT(texture && sampler);
3253 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3256 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3257 QRhiTexture *texture = rhiCtx->dummyTexture({}, resourceUpdates);
3258 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3259 QRhiSampler::Linear,
3261 QRhiSampler::Repeat,
3262 QRhiSampler::Repeat,
3263 QRhiSampler::Repeat });
3264 Q_ASSERT(texture && sampler);
3265 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3266 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3271 if (featureSet.isSet(QSSGShaderFeatures::Feature::ReflectionProbe)) {
3272 int reflectionSampler = shaderPipeline->bindingForTexture(
"qt_reflectionMap");
3273 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
3274 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
3275 QRhiTexture* reflectionTexture = inData.getReflectionMapManager()->reflectionMapEntry(subsetRenderable.reflectionProbeIndex)->m_rhiPrefilteredCube;
3276 if (reflectionSampler >= 0 && reflectionTexture)
3277 bindings.addTexture(reflectionSampler, QRhiShaderResourceBinding::FragmentStage, reflectionTexture, sampler);
3278 }
else if (shaderPipeline->lightProbeTexture()) {
3279 int binding = shaderPipeline->bindingForTexture(
"qt_lightProbe",
int(QSSGRhiSamplerBindingHints::LightProbe));
3281 auto tiling = shaderPipeline->lightProbeTiling();
3282 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
3283 QSSGRhiHelpers::toRhi(tiling.first), QSSGRhiHelpers::toRhi(tiling.second), QRhiSampler::Repeat });
3284 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage,
3285 shaderPipeline->lightProbeTexture(), sampler);
3290 if (shaderPipeline->screenTexture()) {
3291 const int screenTextureBinding = shaderPipeline->bindingForTexture(
"qt_screenTexture",
int(QSSGRhiSamplerBindingHints::ScreenTexture));
3292 const int screenTextureArrayBinding = shaderPipeline->bindingForTexture(
"qt_screenTextureArray",
int(QSSGRhiSamplerBindingHints::ScreenTextureArray));
3293 if (screenTextureBinding >= 0 || screenTextureArrayBinding >= 0) {
3294 QRhiSampler::Filter mipFilter = shaderPipeline->screenTexture()->flags().testFlag(QRhiTexture::MipMapped)
3295 ? QRhiSampler::Linear : QRhiSampler::None;
3296 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, mipFilter,
3297 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
3298 if (screenTextureBinding >= 0) {
3299 bindings.addTexture(screenTextureBinding,
3300 QRhiShaderResourceBinding::FragmentStage,
3301 shaderPipeline->screenTexture(), sampler);
3303 if (screenTextureArrayBinding >= 0) {
3304 bindings.addTexture(screenTextureArrayBinding,
3305 QRhiShaderResourceBinding::FragmentStage,
3306 shaderPipeline->screenTexture(), sampler);
3311 if (shaderPipeline->lightmapTexture()) {
3312 int binding = shaderPipeline->bindingForTexture(
"qt_lightmap",
int(QSSGRhiSamplerBindingHints::LightmapTexture));
3314 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
3315 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
3316 bindings.addTexture(binding,
3317 QRhiShaderResourceBinding::FragmentStage,
3318 shaderPipeline->lightmapTexture(), sampler);
3325 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3326 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3328 int maxSamplerBinding = -1;
3329 QVector<QShaderDescription::InOutVariable> samplerVars =
3330 shaderPipeline->fragmentStage()->shader().description().combinedImageSamplers();
3331 for (
const QShaderDescription::InOutVariable &var : shaderPipeline->vertexStage()->shader().description().combinedImageSamplers()) {
3332 auto it = std::find_if(samplerVars.cbegin(), samplerVars.cend(),
3333 [&var](
const QShaderDescription::InOutVariable &v) {
return var.binding == v.binding; });
3334 if (it == samplerVars.cend())
3335 samplerVars.append(var);
3338 for (
const QShaderDescription::InOutVariable &var : std::as_const(samplerVars))
3339 maxSamplerBinding = qMax(maxSamplerBinding, var.binding);
3341 if (maxSamplerBinding >= 0) {
3342 int extraTexCount = shaderPipeline->extraTextureCount();
3343 for (
int i = 0; i < extraTexCount; ++i) {
3344 QSSGRhiTexture &t(shaderPipeline->extraTextureAt(i));
3345 const int samplerBinding = shaderPipeline->bindingForTexture(t.name);
3346 if (samplerBinding >= 0) {
3347 rhiCtx->checkAndAdjustForNPoT(t.texture, &t.samplerDesc);
3348 QRhiSampler *sampler = rhiCtx->sampler(t.samplerDesc);
3349 bindings.addTexture(samplerBinding,
3350 QRhiShaderResourceBinding::FragmentStage,
3358 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
3360 QSSG_ASSERT(srb,
continue);
3361 QSSG_ASSERT(std::size(subsetRenderable.rhiRenderData.userPassData) > index,
continue);
3363 auto &rhiPassData = subsetRenderable.rhiRenderData.userPassData[index];
3364 rhiPassData.pipeline = rhiCtxD->pipeline(ps, rpDesc, srb);
3365 rhiPassData.srb = srb;
3372 QSSGPassKey passKey,
3373 const QSSGRhiGraphicsPipelineState &basePipelineState,
3374 QRhiRenderPassDescriptor *rpDesc,
3377 QSSGRenderableObjectList &inObjects,
3378 QSSGShaderFeatures featureSet,
3382 QSSGRhiGraphicsPipelineState ps = basePipelineState;
3383 for (
const QSSGRenderableObjectHandle &handle : inObjects) {
3384 QSSGRenderableObject *obj = handle.obj;
3385 QSSGRhiShaderPipelinePtr shaderPipeline;
3386 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
3387 const auto &bufferManager = inData.contextInterface()->bufferManager();
3389 featureSet.set(QSSGShaderFeatures::Feature::UserRenderPass,
true);
3391 QSSGRhiDrawCallData *dcd =
nullptr;
3392 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3393 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3394 const void *modelNode = &subsetRenderable.modelContext.model;
3395 dcd = &rhiCtxD->drawCallData({ passKey, modelNode, &subsetRenderable.material, 0 });
3398 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset) {
3399 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3400 const auto &material =
static_cast<
const QSSGRenderDefaultMaterial &>(subsetRenderable.getMaterial());
3401 ps.cullMode = QSSGRhiHelpers::toCullMode(material.cullMode);
3403 shaderPipeline = shadersForDefaultMaterial(&ps, subsetRenderable, featureSet, shaderAugmentation);
3404 if (shaderPipeline) {
3405 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
3406 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
3408 for (
const auto &u : shaderAugmentation.propertyUniforms)
3409 shaderPipeline->setShaderResources(ubufData, *bufferManager, u.name, u.value, u.shaderDataType);
3410 updateUniformsForDefaultMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
3411 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
3413 }
else if (obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3414 QSSGSubsetRenderable &subsetRenderable(*
static_cast<QSSGSubsetRenderable *>(obj));
3415 const auto &material =
static_cast<
const QSSGRenderCustomMaterial &>(subsetRenderable.getMaterial());
3416 ps.cullMode = QSSGRhiHelpers::toCullMode(material.m_cullMode);
3418 QSSGCustomMaterialSystem &customMaterialSystem(*subsetRenderable.renderer->contextInterface()->customMaterialSystem().get());
3420 if (material.m_shadingMode == QSSGRenderCustomMaterial::ShadingMode::Unshaded)
3421 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(&ps, material, subsetRenderable, inData.getDefaultMaterialPropertyTable(), featureSet);
3423 shaderPipeline = customMaterialSystem.shadersForCustomMaterial(&ps, material, subsetRenderable, inData.getDefaultMaterialPropertyTable(), featureSet, shaderAugmentation);
3425 if (shaderPipeline) {
3426 shaderPipeline->ensureCombinedUniformBuffer(&dcd->ubuf);
3427 char *ubufData = dcd->ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
3429 for (
const auto &u : shaderAugmentation.propertyUniforms)
3430 shaderPipeline->setShaderResources(ubufData, *bufferManager, u.name, u.value, u.shaderDataType);
3431 customMaterialSystem.updateUniformsForCustomMaterial(*shaderPipeline, rhiCtx, inData, ubufData, &ps, material,
3432 subsetRenderable, inData.renderedCameras,
nullptr,
nullptr);
3433 dcd->ubuf->endFullDynamicBufferUpdateForCurrentFrame();
3437 if (!shaderPipeline) {
3439 qDebug() <<
"Failed to prepare user augmented pass for object.";
3444 if (obj->type == QSSGRenderableObject::Type::DefaultMaterialMeshSubset || obj->type == QSSGRenderableObject::Type::CustomMaterialMeshSubset) {
3445 QSSGSubsetRenderable &subsetRenderable(
static_cast<QSSGSubsetRenderable &>(*obj));
3446 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(ps);
3447 ia = subsetRenderable.subset.rhi.ia;
3449 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
3450 int instanceBufferBinding = setupInstancing(&subsetRenderable, &ps, rhiCtx, cameraDatas[0].direction, cameraDatas[0].position);
3451 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
3453 QSSGRhiShaderResourceBindingList bindings;
3454 bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd->ubuf);
3457 QSSGRenderableImage *renderableImage = subsetRenderable.firstImage;
3458 while (renderableImage) {
3459 const char *samplerName = QSSGMaterialShaderGenerator::getSamplerName(renderableImage->m_mapType);
3460 const int samplerHint =
int(renderableImage->m_mapType);
3461 int samplerBinding = shaderPipeline->bindingForTexture(samplerName, samplerHint);
3462 if (samplerBinding >= 0) {
3463 QRhiTexture *texture = renderableImage->m_texture.m_texture;
3464 if (samplerBinding >= 0 && texture) {
3465 const bool mipmapped = texture->flags().testFlag(QRhiTexture::MipMapped);
3466 QSSGRhiSamplerDescription samplerDesc = {
3467 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_minFilterType),
3468 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_magFilterType),
3469 mipmapped ? QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_mipFilterType) : QRhiSampler::None,
3470 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_horizontalTilingMode),
3471 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_verticalTilingMode),
3472 QSSGRhiHelpers::toRhi(renderableImage->m_imageNode.m_depthTilingMode)
3474 rhiCtx->checkAndAdjustForNPoT(texture, &samplerDesc);
3475 QRhiSampler *sampler = rhiCtx->sampler(samplerDesc);
3476 bindings.addTexture(samplerBinding, RENDERER_VISIBILITY_ALL, texture, sampler);
3479 renderableImage = renderableImage->m_nextImage;
3482 addDepthTextureBindings(rhiCtx, shaderPipeline.get(), bindings);
3485 const int normalTextureBinding = shaderPipeline->bindingForTexture(
"qt_normalTexture",
int(QSSGRhiSamplerBindingHints::NormalTexture));
3486 if (normalTextureBinding >= 0) {
3487 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
3488 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
3489 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3490 QRhiTexture *dummyTexture = rhiCtx->dummyTexture({}, resourceUpdates);
3491 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3492 bindings.addTexture(normalTextureBinding, RENDERER_VISIBILITY_ALL, dummyTexture, sampler);
3498 if (QRhiTexture *boneTexture = inData.getBonemapTexture(subsetRenderable.modelContext)) {
3499 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
3501 QRhiSampler *boneSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3502 QRhiSampler::Nearest,
3504 QRhiSampler::ClampToEdge,
3505 QRhiSampler::ClampToEdge,
3508 bindings.addTexture(binding,
3509 QRhiShaderResourceBinding::VertexStage,
3516 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
3517 if (targetsTexture) {
3518 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
3520 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3521 QRhiSampler::Nearest,
3523 QRhiSampler::ClampToEdge,
3524 QRhiSampler::ClampToEdge,
3525 QRhiSampler::ClampToEdge
3527 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
3532 if (shaderPipeline->isLightingEnabled()) {
3533 bindings.addUniformBuffer(1, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3534 shaderPipeline->ub0LightDataOffset(),
3535 sizeof(QSSGShaderLightsUniformData));
3536 bindings.addUniformBuffer(2, RENDERER_VISIBILITY_ALL, dcd->ubuf,
3537 shaderPipeline->ub0DirectionalLightDataOffset(),
3538 sizeof(QSSGShaderDirectionalLightsUniformData));
3541 auto shadowMapAtlas = shaderPipeline->shadowMapAtlasTexture();
3542 if (shadowMapAtlas) {
3543 int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_texture");
3545 QRhiTexture *texture = shadowMapAtlas;
3546 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
3547 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
3548 Q_ASSERT(texture && sampler);
3549 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3554 if (
int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture"); binding >= 0) {
3555 if (
auto shadowMapBlueNoise = shaderPipeline->shadowMapBlueNoiseTexture()) {
3556 int binding = shaderPipeline->bindingForTexture(
"qt_shadowmap_blue_noise_texture");
3558 QRhiTexture *texture = shadowMapBlueNoise;
3559 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3560 QRhiSampler::Linear,
3562 QRhiSampler::Repeat,
3563 QRhiSampler::Repeat,
3564 QRhiSampler::Repeat });
3565 Q_ASSERT(texture && sampler);
3566 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3569 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3570 QRhiTexture *texture = rhiCtx->dummyTexture({}, resourceUpdates);
3571 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear,
3572 QRhiSampler::Linear,
3574 QRhiSampler::Repeat,
3575 QRhiSampler::Repeat,
3576 QRhiSampler::Repeat });
3577 Q_ASSERT(texture && sampler);
3578 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, texture, sampler);
3579 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3586 if (featureSet.isSet(QSSGShaderFeatures::Feature::ReflectionProbe)) {
3587 int reflectionSampler = shaderPipeline->bindingForTexture(
"qt_reflectionMap");
3588 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
3589 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
3590 QRhiTexture* reflectionTexture = inData.getReflectionMapManager()->reflectionMapEntry(subsetRenderable.reflectionProbeIndex)->m_rhiPrefilteredCube;
3591 if (reflectionSampler >= 0 && reflectionTexture)
3592 bindings.addTexture(reflectionSampler, QRhiShaderResourceBinding::FragmentStage, reflectionTexture, sampler);
3593 }
else if (shaderPipeline->lightProbeTexture()) {
3594 int binding = shaderPipeline->bindingForTexture(
"qt_lightProbe",
int(QSSGRhiSamplerBindingHints::LightProbe));
3596 auto tiling = shaderPipeline->lightProbeTiling();
3597 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
3598 QSSGRhiHelpers::toRhi(tiling.first), QSSGRhiHelpers::toRhi(tiling.second), QRhiSampler::Repeat });
3599 bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage,
3600 shaderPipeline->lightProbeTexture(), sampler);
3605 if (shaderPipeline->screenTexture()) {
3606 const int screenTextureBinding = shaderPipeline->bindingForTexture(
"qt_screenTexture",
int(QSSGRhiSamplerBindingHints::ScreenTexture));
3607 const int screenTextureArrayBinding = shaderPipeline->bindingForTexture(
"qt_screenTextureArray",
int(QSSGRhiSamplerBindingHints::ScreenTextureArray));
3608 if (screenTextureBinding >= 0 || screenTextureArrayBinding >= 0) {
3613 QRhiSampler::Filter mipFilter = shaderPipeline->screenTexture()->flags().testFlag(QRhiTexture::MipMapped)
3614 ? QRhiSampler::Linear : QRhiSampler::None;
3615 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, mipFilter,
3616 QRhiSampler::Repeat, QRhiSampler::Repeat, QRhiSampler::Repeat });
3617 if (screenTextureBinding >= 0) {
3618 bindings.addTexture(screenTextureBinding,
3619 QRhiShaderResourceBinding::FragmentStage,
3620 shaderPipeline->screenTexture(), sampler);
3622 if (screenTextureArrayBinding >= 0) {
3623 bindings.addTexture(screenTextureArrayBinding,
3624 QRhiShaderResourceBinding::FragmentStage,
3625 shaderPipeline->screenTexture(), sampler);
3630 if (shaderPipeline->lightmapTexture()) {
3631 int binding = shaderPipeline->bindingForTexture(
"qt_lightmap",
int(QSSGRhiSamplerBindingHints::LightmapTexture));
3633 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
3634 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
3635 bindings.addTexture(binding,
3636 QRhiShaderResourceBinding::FragmentStage,
3637 shaderPipeline->lightmapTexture(), sampler);
3644 QRhiResourceUpdateBatch *resourceUpdates = rhiCtx->rhi()->nextResourceUpdateBatch();
3645 rhiCtx->commandBuffer()->resourceUpdate(resourceUpdates);
3647 QVector<QShaderDescription::InOutVariable> samplerVars =
3648 shaderPipeline->fragmentStage()->shader().description().combinedImageSamplers();
3649 for (
const QShaderDescription::InOutVariable &var : shaderPipeline->vertexStage()->shader().description().combinedImageSamplers()) {
3650 auto it = std::find_if(samplerVars.cbegin(), samplerVars.cend(),
3651 [&var](
const QShaderDescription::InOutVariable &v) {
return var.binding == v.binding; });
3652 if (it == samplerVars.cend())
3653 samplerVars.append(var);
3656 int maxSamplerBinding = -1;
3657 for (
const QShaderDescription::InOutVariable &var : std::as_const(samplerVars))
3658 maxSamplerBinding = qMax(maxSamplerBinding, var.binding);
3667 QBitArray samplerBindingsSpecified(maxSamplerBinding + 1);
3669 if (maxSamplerBinding >= 0) {
3671 int extraTexCount = shaderPipeline->extraTextureCount();
3672 for (
int i = 0; i < extraTexCount; ++i) {
3673 QSSGRhiTexture &t(shaderPipeline->extraTextureAt(i));
3674 const int samplerBinding = shaderPipeline->bindingForTexture(t.name);
3675 if (samplerBinding >= 0) {
3676 samplerBindingsSpecified.setBit(samplerBinding);
3677 rhiCtx->checkAndAdjustForNPoT(t.texture, &t.samplerDesc);
3678 QRhiSampler *sampler = rhiCtx->sampler(t.samplerDesc);
3679 bindings.addTexture(samplerBinding,
3680 QRhiShaderResourceBinding::FragmentStage,
3688 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
3690 QSSG_ASSERT(srb,
return);
3692 QSSG_ASSERT(std::size(subsetRenderable.rhiRenderData.userPassData) > index,
return);
3694 auto &rhiPassData = subsetRenderable.rhiRenderData.userPassData[index];
3695 rhiPassData.pipeline = rhiCtxD->pipeline(ps,
3698 rhiPassData.srb = srb;
3761 QSSGPassKey passKey,
3763 const QMatrix4x4 &viewProjection,
3765 QRhiRenderPassDescriptor *renderPassDescriptor,
3766 QSSGRhiGraphicsPipelineState *ps,
3767 QSSGRenderMotionVectorMap &motionVectorMapManager)
3769 if (inObject.type != QSSGRenderableObject::Type::DefaultMaterialMeshSubset &&
3770 inObject.type != QSSGRenderableObject::Type::CustomMaterialMeshSubset)
3773 QSSGSubsetRenderable &subsetRenderable =
static_cast<QSSGSubsetRenderable &>(inObject);
3774 auto &modelNode = subsetRenderable.modelContext.model;
3776 bool skin = modelNode.usesBoneTexture();
3777 bool instance = modelNode.instanceCount() > 0;
3778 bool morph = modelNode.morphTargets.size() > 0;
3780 QSSGRhiShaderPipelinePtr shaderPipeline = inData.contextInterface()->shaderCache()->
3781 getBuiltInRhiShaders().getRhiMotionVectorShader(skin, instance, morph);
3783 if (!shaderPipeline)
3786 QSSGRhiShaderResourceBindingList bindings;
3788 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
3789 QSSGRhiDrawCallData &dcd = rhiCtxD->drawCallData({ passKey, &modelNode,
nullptr, 0 });
3792 QSSGRenderTextureData *boneTextureData =
nullptr;
3794 boneTextureData = modelNode.skin;
3795 else if (modelNode.skeleton)
3796 boneTextureData = &modelNode.skeleton->boneTexData;
3798 QMatrix4x4 modelViewProjection = subsetRenderable.modelContext.modelViewProjections[0];
3799 QMatrix4x4 instanceLocal;
3800 QMatrix4x4 instanceGlobal;
3803 instanceLocal = inData.getInstanceTransforms(modelNode).local;
3804 instanceGlobal = inData.getInstanceTransforms(modelNode).global;
3806 modelViewProjection = viewProjection;
3808 auto motionData = motionVectorMapManager.trackMotionData(&modelNode,
3809 modelViewProjection,
3813 modelNode.instanceTable,
3814 modelNode.morphWeights);
3815 float velocityAmount = subsetRenderable.modelContext.model.motionVectorScale;
3816 int morphTargetCount = modelNode.morphWeights.count();
3828 const int ubufSize = 416;
3831 dcd.ubuf = rhiCtx->rhi()->newBuffer(QRhiBuffer::Dynamic,
3832 QRhiBuffer::UniformBuffer,
3837 char *ubufData = dcd.ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
3839 memcpy(ubufData, modelViewProjection.constData(), 64);
3841 memcpy(ubufData + ubufOffset, motionData.prevModelViewProjection.constData(), 64);
3843 memcpy(ubufData + ubufOffset, instanceLocal.constData(), 64);
3845 memcpy(ubufData + ubufOffset, instanceGlobal.constData(), 64);
3847 memcpy(ubufData + ubufOffset, motionData.prevInstanceLocal.constData(), 64);
3849 memcpy(ubufData + ubufOffset, motionData.prevInstanceGlobal.constData(), 64);
3851 memcpy(ubufData + ubufOffset, &inData.layer.currentAndLastJitter, 16);
3853 memcpy(ubufData + ubufOffset, &velocityAmount, 4);
3855 memcpy(ubufData + ubufOffset, &morphTargetCount, 4);
3856 dcd.ubuf->endFullDynamicBufferUpdateForCurrentFrame();
3858 bindings.addUniformBuffer(0, QRhiShaderResourceBinding::VertexStage |
3859 QRhiShaderResourceBinding::FragmentStage, dcd.ubuf);
3861 QRhiSampler *nearestSampler =
nullptr;
3863 if (skin || instance) {
3864 nearestSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3865 QRhiSampler::Nearest,
3867 QRhiSampler::ClampToEdge,
3868 QRhiSampler::ClampToEdge,
3874 int binding = shaderPipeline->bindingForTexture(
"qt_boneTexture");
3877 bindings.addTexture(binding,
3878 QRhiShaderResourceBinding::VertexStage,
3879 inData.getBonemapTexture(subsetRenderable.modelContext),
3881 binding = shaderPipeline->bindingForTexture(
"lastBoneTexture");
3883 bindings.addTexture(binding,
3884 QRhiShaderResourceBinding::VertexStage,
3885 motionData.prevBoneTexture.m_texture,
3892 int binding = shaderPipeline->bindingForTexture(
"lastInstanceTexture");
3894 bindings.addTexture(binding,
3895 QRhiShaderResourceBinding::VertexStage,
3896 motionData.prevInstanceTexture.m_texture,
3901 auto *targetsTexture = subsetRenderable.subset.rhi.targetsTexture;
3902 if (targetsTexture) {
3903 int binding = shaderPipeline->bindingForTexture(
"qt_morphTargetTexture");
3905 QRhiSampler *targetsSampler = rhiCtx->sampler({ QRhiSampler::Nearest,
3906 QRhiSampler::Nearest,
3908 QRhiSampler::ClampToEdge,
3909 QRhiSampler::ClampToEdge,
3910 QRhiSampler::ClampToEdge
3912 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, subsetRenderable.subset.rhi.targetsTexture, targetsSampler);
3914 if ((binding = shaderPipeline->bindingForTexture(
"morphWeightTexture")) >= 0)
3915 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, motionData.currentMorphWeightTexture.m_texture, targetsSampler);
3917 if ((binding = shaderPipeline->bindingForTexture(
"lastMorphWeightTexture")) >= 0)
3918 bindings.addTexture(binding, QRhiShaderResourceBinding::VertexStage, motionData.prevMorphWeightTexture.m_texture, targetsSampler);
3922 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
3923 ia = subsetRenderable.subset.rhi.ia;
3924 const QSSGRenderCameraDataList &cameraDatas(*inData.renderedCameraData);
3925 QVector3D cameraDirection = cameraDatas[0].direction;
3926 QVector3D cameraPosition = cameraDatas[0].position;
3927 int instanceBufferBinding = setupInstancing(&subsetRenderable, ps, rhiCtx, cameraDirection, cameraPosition);
3928 QSSGRhiHelpers::bakeVertexInputLocations(&ia, *shaderPipeline, instanceBufferBinding);
3929 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(*ps, shaderPipeline.get());
3931 QRhiShaderResourceBindings *&srb = dcd.srb;
3932 bool srbChanged =
false;
3933 if (!srb || bindings != dcd.bindings) {
3934 srb = rhiCtxD->srb(bindings);
3935 rhiCtxD->releaseCachedSrb(dcd.bindings);
3936 dcd.bindings = bindings;
3940 subsetRenderable.rhiRenderData.motionVectorPass.srb = srb;
3942 const auto pipelineKey = QSSGGraphicsPipelineStateKey::create(*ps, renderPassDescriptor, srb);
3945 && dcd.renderTargetDescriptionHash == pipelineKey.extra.renderTargetDescriptionHash
3946 && dcd.renderTargetDescription == pipelineKey.renderTargetDescription
3949 subsetRenderable.rhiRenderData.motionVectorPass.pipeline = dcd.pipeline;
3952 subsetRenderable.rhiRenderData.motionVectorPass.pipeline = rhiCtxD->pipeline(pipelineKey,
3953 renderPassDescriptor,
3955 dcd.pipeline = subsetRenderable.rhiRenderData.motionVectorPass.pipeline;
3956 dcd.renderTargetDescriptionHash = pipelineKey.extra.renderTargetDescriptionHash;
3957 dcd.renderTargetDescription = pipelineKey.renderTargetDescription;