395 QSSGMaterialVertexPipeline &vertexShader,
396 const QSSGShaderDefaultMaterialKey &inKey,
397 const QSSGShaderDefaultMaterialKeyProperties &keyProps,
398 const QSSGShaderFeatures &featureSet,
399 const QSSGRenderGraphObject &inMaterial,
400 QSSGRenderableImage *firstImage,
401 QSSGShaderLibraryManager &shaderLibraryManager)
403 QSSGShaderMaterialAdapter *materialAdapter = getMaterialAdapter(inMaterial);
404 auto hasCustomFunction = [&shaderLibraryManager, materialAdapter](
const QByteArray &funcName) {
405 return materialAdapter->hasCustomShaderFunction(QSSGShaderCache::ShaderType::Fragment,
407 shaderLibraryManager);
410 generateFragmentDefines(fragmentShader, inKey, keyProps, materialAdapter, shaderLibraryManager);
414 bool vertexColorsEnabled = keyProps.m_vertexColorsEnabled.getValue(inKey)
415 || keyProps.m_usesVarColor.getValue(inKey)
416 || keyProps.m_vertexColorsMaskEnabled.getValue(inKey)
417 || keyProps.m_usesInstancing.getValue(inKey)
418 || keyProps.m_blendParticles.getValue(inKey);
420 bool hasLighting = keyProps.m_hasLighting.getValue(inKey);
421 bool hasPunctualLights = keyProps.m_hasPunctualLights.getValue(inKey);
422 bool isDoubleSided = keyProps.m_isDoubleSided.getValue(inKey);
423 bool hasImage = firstImage !=
nullptr;
425 QSSGRenderLayer::OITMethod oitMethod =
static_cast<QSSGRenderLayer::OITMethod>(keyProps.m_orderIndependentTransparency.getValue(inKey));
426 bool hasIblProbe = keyProps.m_hasIbl.getValue(inKey);
427 bool specularLightingEnabled = keyProps.m_specularEnabled.getValue(inKey) || hasIblProbe;
428 bool specularAAEnabled = keyProps.m_specularAAEnabled.getValue(inKey);
429 quint32 numMorphTargets = keyProps.m_targetCount.getValue(inKey);
431 QSSGRenderableImage *bumpImage =
nullptr;
432 quint32 imageIdx = 0;
433 QSSGRenderableImage *specularAmountImage =
nullptr;
434 QSSGRenderableImage *roughnessImage =
nullptr;
435 QSSGRenderableImage *metalnessImage =
nullptr;
436 QSSGRenderableImage *occlusionImage =
nullptr;
438 QSSGRenderableImage *normalImage =
nullptr;
440 QSSGRenderableImage *translucencyImage =
nullptr;
442 QSSGRenderableImage *opacityImage =
nullptr;
444 QSSGRenderableImage *heightImage =
nullptr;
446 QSSGRenderableImage *clearcoatImage =
nullptr;
447 QSSGRenderableImage *clearcoatRoughnessImage =
nullptr;
448 QSSGRenderableImage *clearcoatNormalImage =
nullptr;
450 QSSGRenderableImage *transmissionImage =
nullptr;
452 QSSGRenderableImage *thicknessImage =
nullptr;
454 QSSGRenderableImage *baseImage =
nullptr;
457 QVector<QSSGRenderableImage *> identityImages;
460 auto channelStr = [](
const QSSGShaderKeyTextureChannel &chProp,
const QSSGShaderDefaultMaterialKey &inKey) -> QByteArray {
462 switch (chProp.getTextureChannel(inKey)) {
463 case QSSGShaderKeyTextureChannel::R:
466 case QSSGShaderKeyTextureChannel::G:
469 case QSSGShaderKeyTextureChannel::B:
472 case QSSGShaderKeyTextureChannel::A:
479 auto maskVariableByVertexColorChannel = [&fragmentShader, keyProps, inKey](
const QByteArray &maskVariable,
const QSSGRenderDefaultMaterial::VertexColorMask &maskEnum ){
480 if (keyProps.m_vertexColorsMaskEnabled.getValue(inKey)) {
481 if ( keyProps.m_vertexColorRedMask.getValue(inKey) & maskEnum )
482 fragmentShader <<
" " << maskVariable <<
" *= qt_vertColorMask.r;\n";
483 else if ( keyProps.m_vertexColorGreenMask.getValue(inKey) & maskEnum )
484 fragmentShader <<
" " << maskVariable <<
" *= qt_vertColorMask.g;\n";
485 else if ( keyProps.m_vertexColorBlueMask.getValue(inKey) & maskEnum )
486 fragmentShader <<
" " << maskVariable <<
" *= qt_vertColorMask.b;\n";
487 else if ( keyProps.m_vertexColorAlphaMask.getValue(inKey) & maskEnum )
488 fragmentShader <<
" " << maskVariable <<
" *= qt_vertColorMask.a;\n";
492 for (QSSGRenderableImage *img = firstImage; img !=
nullptr; img = img->m_nextImage, ++imageIdx) {
493 if (img->m_imageNode.isImageTransformIdentity())
494 identityImages.push_back(img);
495 if (img->m_mapType == QSSGRenderableImage::Type::BaseColor || img->m_mapType == QSSGRenderableImage::Type::Diffuse) {
497 }
else if (img->m_mapType == QSSGRenderableImage::Type::Bump) {
499 }
else if (img->m_mapType == QSSGRenderableImage::Type::SpecularAmountMap) {
500 specularAmountImage = img;
501 }
else if (img->m_mapType == QSSGRenderableImage::Type::Roughness) {
502 roughnessImage = img;
503 }
else if (img->m_mapType == QSSGRenderableImage::Type::Metalness) {
504 metalnessImage = img;
505 }
else if (img->m_mapType == QSSGRenderableImage::Type::Occlusion) {
506 occlusionImage = img;
507 }
else if (img->m_mapType == QSSGRenderableImage::Type::Normal) {
509 }
else if (img->m_mapType == QSSGRenderableImage::Type::Translucency) {
510 translucencyImage = img;
511 }
else if (img->m_mapType == QSSGRenderableImage::Type::Opacity) {
513 }
else if (img->m_mapType == QSSGRenderableImage::Type::Height) {
515 }
else if (img->m_mapType == QSSGRenderableImage::Type::Clearcoat) {
516 clearcoatImage = img;
517 }
else if (img->m_mapType == QSSGRenderableImage::Type::ClearcoatRoughness) {
518 clearcoatRoughnessImage = img;
519 }
else if (img->m_mapType == QSSGRenderableImage::Type::ClearcoatNormal) {
520 clearcoatNormalImage = img;
521 }
else if (img->m_mapType == QSSGRenderableImage::Type::Transmission) {
522 transmissionImage = img;
523 }
else if (img->m_mapType == QSSGRenderableImage::Type::Thickness) {
524 thicknessImage = img;
528 const bool isDepthPass = featureSet.isSet(QSSGShaderFeatures::Feature::DepthPass);
529 const bool isOrthoShadowPass = featureSet.isSet(QSSGShaderFeatures::Feature::OrthoShadowPass);
530 const bool isPerspectiveShadowPass = featureSet.isSet(QSSGShaderFeatures::Feature::PerspectiveShadowPass);
531 const bool isOpaqueDepthPrePass = featureSet.isSet(QSSGShaderFeatures::Feature::OpaqueDepthPrePass);
532 const bool isNormalPass = featureSet.isSet(QSSGShaderFeatures::Feature::NormalPass);
533 const bool hasIblOrientation = featureSet.isSet(QSSGShaderFeatures::Feature::IblOrientation);
534 bool enableShadowMaps = featureSet.isSet(QSSGShaderFeatures::Feature::Ssm);
535 bool enableSSAO = featureSet.isSet(QSSGShaderFeatures::Feature::Ssao);
536 bool enableLightmap = featureSet.isSet(QSSGShaderFeatures::Feature::Lightmap);
537 bool hasReflectionProbe = featureSet.isSet(QSSGShaderFeatures::Feature::ReflectionProbe);
538 bool enableBumpNormal = normalImage || bumpImage;
539 bool genBumpNormalImageCoords =
false;
540 bool genClearcoatNormalImageCoords =
false;
541 bool enableParallaxMapping = heightImage !=
nullptr;
542 bool enableClearcoat = keyProps.m_clearcoatEnabled.getValue(inKey);
543 bool enableTransmission = keyProps.m_transmissionEnabled.getValue(inKey);
544 const bool enableFresnelScaleBias = keyProps.m_fresnelScaleBiasEnabled.getValue(inKey);
545 const bool enableClearcoatFresnelScaleBias = keyProps.m_clearcoatFresnelScaleBiasEnabled.getValue(inKey);
547 const bool isMetallicRoughnessWorkflow = keyProps.m_metallicRoughnessEnabled.getValue(inKey);
548 const bool isSpecularGlossinessWorkflow = keyProps.m_specularGlossyEnabled.getValue(inKey);
549 const bool isPbrMaterial = isMetallicRoughnessWorkflow || isSpecularGlossinessWorkflow;
551 specularLightingEnabled |= specularAmountImage !=
nullptr;
552 specularLightingEnabled |= hasReflectionProbe;
554 const bool hasCustomVert = materialAdapter->hasCustomShaderSnippet(QSSGShaderCache::ShaderType::Vertex);
555 auto debugMode = QSSGRenderLayer::MaterialDebugMode(keyProps.m_debugMode.getValue(inKey));
556 const bool enableFog = keyProps.m_fogEnabled.getValue(inKey);
558 const int viewCount = featureSet.isSet(QSSGShaderFeatures::Feature::DisableMultiView)
559 ? 1 : keyProps.m_viewCount.getValue(inKey);
562 if (numMorphTargets > 0 || hasCustomVert) {
563 vertexShader.addDefinition(QByteArrayLiteral(
"QT_MORPH_MAX_COUNT"),
564 QByteArray::number(numMorphTargets));
566 if ((offset = keyProps.m_targetPositionOffset.getValue(inKey)) < UINT8_MAX) {
567 vertexShader.addDefinition(QByteArrayLiteral(
"QT_TARGET_POSITION_OFFSET"),
568 QByteArray::number(offset));
570 if ((offset = keyProps.m_targetNormalOffset.getValue(inKey)) < UINT8_MAX) {
571 vertexShader.addDefinition(QByteArrayLiteral(
"QT_TARGET_NORMAL_OFFSET"),
572 QByteArray::number(offset));
574 if ((offset = keyProps.m_targetTangentOffset.getValue(inKey)) < UINT8_MAX) {
575 vertexShader.addDefinition(QByteArrayLiteral(
"QT_TARGET_TANGENT_OFFSET"),
576 QByteArray::number(offset));
578 if ((offset = keyProps.m_targetBinormalOffset.getValue(inKey)) < UINT8_MAX) {
579 vertexShader.addDefinition(QByteArrayLiteral(
"QT_TARGET_BINORMAL_OFFSET"),
580 QByteArray::number(offset));
582 if ((offset = keyProps.m_targetTexCoord0Offset.getValue(inKey)) < UINT8_MAX) {
583 vertexShader.addDefinition(QByteArrayLiteral(
"QT_TARGET_TEX0_OFFSET"),
584 QByteArray::number(offset));
586 if ((offset = keyProps.m_targetTexCoord1Offset.getValue(inKey)) < UINT8_MAX) {
587 vertexShader.addDefinition(QByteArrayLiteral(
"QT_TARGET_TEX1_OFFSET"),
588 QByteArray::number(offset));
590 if ((offset = keyProps.m_targetColorOffset.getValue(inKey)) < UINT8_MAX) {
591 vertexShader.addDefinition(QByteArrayLiteral(
"QT_TARGET_COLOR_OFFSET"),
592 QByteArray::number(offset));
596 bool includeCustomFragmentMain =
true;
597 if (isDepthPass || isOrthoShadowPass || isPerspectiveShadowPass || isNormalPass) {
600 enableShadowMaps =
false;
601 enableLightmap =
false;
603 specularLightingEnabled =
false;
604 enableClearcoat =
false;
605 enableTransmission =
false;
607 oitMethod = QSSGRenderLayer::OITMethod::None;
609 if (!isOpaqueDepthPrePass) {
610 vertexColorsEnabled =
false;
612 includeCustomFragmentMain =
false;
616 bool includeSSAOVars = enableSSAO || enableShadowMaps;
618 vertexShader.beginFragmentGeneration(shaderLibraryManager, oitMethod);
621 const bool hasCustomFrag = materialAdapter->hasCustomShaderSnippet(QSSGShaderCache::ShaderType::Fragment);
622 const bool usesSharedVar = materialAdapter->usesSharedVariables();
625 if (isOrthoShadowPass)
626 fragmentShader.addUniform(
"qt_shadowDepthAdjust",
"vec2");
628 if (hasCustomFrag && materialAdapter->isUnshaded()) {
641 fragmentShader.addUniform(
"qt_material_emissive_color",
"vec3");
642 fragmentShader.addUniform(
"qt_material_base_color",
"vec4");
643 fragmentShader.addUniform(
"qt_material_properties",
"vec4");
644 fragmentShader.addUniform(
"qt_material_properties2",
"vec4");
645 fragmentShader.addUniform(
"qt_material_properties3",
"vec4");
646 if (enableParallaxMapping || enableTransmission)
647 fragmentShader.addUniform(
"qt_material_properties4",
"vec4");
648 if (!hasCustomFrag) {
649 if (enableTransmission) {
650 fragmentShader.addUniform(
"qt_material_attenuation",
"vec4");
651 fragmentShader.addUniform(
"qt_material_thickness",
"float");
653 if (enableFresnelScaleBias || enableClearcoatFresnelScaleBias)
654 fragmentShader.addUniform(
"qt_material_properties5",
"vec4");
655 fragmentShader.addUniform(
"qt_material_clearcoat_normal_strength",
"float");
656 fragmentShader.addUniform(
"qt_material_clearcoat_fresnel_power",
"float");
659 if (vertexColorsEnabled) {
660 vertexShader.generateVertexColor(inKey);
662 fragmentShader.append(
" vec4 qt_vertColorMask = vec4(1.0);");
663 fragmentShader.append(
" vec4 qt_vertColor = vec4(1.0);");
666 if (hasImage && ((!isDepthPass && !isOrthoShadowPass && !isPerspectiveShadowPass) || isOpaqueDepthPrePass)) {
667 fragmentShader.append(
" vec3 qt_uTransform;");
668 fragmentShader.append(
" vec3 qt_vTransform;");
671 if (hasLighting || hasCustomFrag || isNormalPass) {
673 vertexShader.generateViewVector(inKey);
674 if (keyProps.m_usesProjectionMatrix.getValue(inKey)) {
676 fragmentShader.addUniformArray(
"qt_projectionMatrix",
"mat4", viewCount);
678 fragmentShader.addUniform(
"qt_projectionMatrix",
"mat4");
680 if (keyProps.m_usesInverseProjectionMatrix.getValue(inKey)) {
682 fragmentShader.addUniformArray(
"qt_inverseProjectionMatrix",
"mat4", viewCount);
684 fragmentShader.addUniform(
"qt_inverseProjectionMatrix",
"mat4");
686 vertexShader.generateWorldNormal(inKey);
687 vertexShader.generateWorldPosition(inKey);
690 const bool tangentOrBinormalDebugMode = (debugMode == QSSGRenderLayer::MaterialDebugMode::Tangent) || (debugMode == QSSGRenderLayer::MaterialDebugMode::Binormal);
691 const bool needsTangentAndBinormal = hasCustomFrag || enableParallaxMapping || clearcoatNormalImage || enableBumpNormal || tangentOrBinormalDebugMode;
694 if (needsTangentAndBinormal) {
695 bool genTangent =
false;
696 bool genBinormal =
false;
697 vertexShader.generateVarTangentAndBinormal(inKey, genTangent, genBinormal);
701 if (enableBumpNormal) {
705 auto *bumpNormalImage = bumpImage !=
nullptr ? bumpImage : normalImage;
706 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *bumpNormalImage,
true, bumpNormalImage->m_imageNode.m_indexUV);
707 genBumpNormalImageCoords =
true;
708 id = (bumpImage !=
nullptr) ?
int(QSSGRenderableImage::Type::Bump) :
int(QSSGRenderableImage::Type::Normal);
709 }
else if (clearcoatNormalImage) {
711 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *clearcoatNormalImage,
true, clearcoatNormalImage->m_imageNode.m_indexUV);
712 genClearcoatNormalImageCoords =
true;
713 id =
int(QSSGRenderableImage::Type::ClearcoatNormal);
719 fragmentShader <<
" qt_tangent = (dUVdy.y * dFdx(qt_varWorldPos) - dUVdx.y * dFdy(qt_varWorldPos)) / (dUVdx.x * dUVdy.y - dUVdx.y * dUVdy.x);\n"
720 <<
" qt_tangent = qt_tangent - dot(qt_world_normal, qt_tangent) * qt_world_normal;\n"
721 <<
" qt_tangent = normalize(qt_tangent);\n";
725 fragmentShader <<
" qt_binormal = cross(qt_world_normal, qt_tangent);\n";
729 fragmentShader.append(
"#if QSHADER_HLSL && QSHADER_VIEW_COUNT >= 2");
730 fragmentShader.append(
" const float qt_facing = 1.0;");
731 fragmentShader.append(
"#else");
732 fragmentShader.append(
" const float qt_facing = gl_FrontFacing ? 1.0 : -1.0;");
733 fragmentShader.append(
"#endif");
734 fragmentShader.append(
" qt_world_normal *= qt_facing;\n");
735 if (needsTangentAndBinormal) {
736 fragmentShader.append(
" qt_tangent *= qt_facing;");
737 fragmentShader.append(
" qt_binormal *= qt_facing;");
748 fragmentShader <<
" float qt_customOcclusionAmount = 1.0;\n";
749 fragmentShader <<
" float qt_customIOR = 1.5;\n";
750 fragmentShader <<
" float qt_customSpecularAmount = 0.5;\n";
751 fragmentShader <<
" float qt_customSpecularRoughness = 0.0;\n";
752 fragmentShader <<
" float qt_customMetalnessAmount = 0.0;\n";
753 fragmentShader <<
" float qt_customFresnelPower = 5.0;\n";
754 fragmentShader <<
" vec4 qt_customBaseColor = vec4(1.0);\n";
755 fragmentShader <<
" vec3 qt_customEmissiveColor = vec3(0.0);\n";
756 if (enableClearcoat) {
757 fragmentShader <<
" float qt_customClearcoatAmount = 0.0;\n";
758 fragmentShader <<
" float qt_customClearcoatFresnelPower = 5.0;\n";
759 fragmentShader <<
" float qt_customClearcoatRoughness = 0.0;\n";
760 fragmentShader <<
" vec3 qt_customClearcoatNormal = qt_world_normal;\n";
761 if (enableClearcoatFresnelScaleBias) {
762 fragmentShader <<
" float qt_customClearcoatFresnelScale = 1.0;\n";
763 fragmentShader <<
" float qt_customClearcoatFresnelBias = 0.0;\n";
766 if (enableFresnelScaleBias) {
767 fragmentShader <<
" float qt_customFresnelScale = 1.0;\n";
768 fragmentShader <<
" float qt_customFresnelBias = 0.0;\n";
771 if (enableTransmission) {
772 fragmentShader <<
" float qt_customTransmissionFactor = 0.0;\n";
773 fragmentShader <<
" float qt_customThicknessFactor = 0.0;\n";
774 fragmentShader <<
" vec3 qt_customAttenuationColor = vec3(1.0);\n";
775 fragmentShader <<
" float qt_customAttenuationDistance = 0.0;\n";
778 fragmentShader <<
" QT_SHARED_VARS qt_customShared;\n";
781 vertexShader.generateUVCoords(0, inKey);
782 vertexShader.generateUVCoords(1, inKey);
783 if (includeCustomFragmentMain && hasCustomFunction(QByteArrayLiteral(
"qt_customMain"))) {
784 fragmentShader <<
" qt_customMain(qt_customBaseColor, qt_customEmissiveColor, qt_customMetalnessAmount, qt_customSpecularRoughness,"
785 " qt_customSpecularAmount, qt_customFresnelPower, qt_world_normal, qt_tangent, qt_binormal,"
786 " qt_texCoord0, qt_texCoord1, qt_view_vector, qt_customIOR, qt_customOcclusionAmount";
787 if (enableClearcoat) {
788 fragmentShader <<
", qt_customClearcoatAmount, qt_customClearcoatFresnelPower, qt_customClearcoatRoughness, qt_customClearcoatNormal";
789 if (enableClearcoatFresnelScaleBias) {
790 fragmentShader <<
", qt_customClearcoatFresnelScale, qt_customClearcoatFresnelBias";
793 if (enableFresnelScaleBias) {
794 fragmentShader <<
", qt_customFresnelScale, qt_customFresnelBias";
796 if (enableTransmission) {
797 fragmentShader <<
", qt_customTransmissionFactor, qt_customThicknessFactor, qt_customAttenuationColor, qt_customAttenuationDistance";
800 fragmentShader <<
", qt_customShared);\n";
802 fragmentShader <<
");\n";
804 fragmentShader <<
" vec4 qt_diffuseColor = qt_customBaseColor * qt_vertColor;\n";
805 fragmentShader <<
" vec3 qt_global_emission = qt_customEmissiveColor;\n";
806 fragmentShader <<
" float qt_iOR = qt_customIOR;\n";
808 fragmentShader <<
" vec4 qt_diffuseColor = qt_material_base_color * qt_vertColor;\n";
809 fragmentShader <<
" vec3 qt_global_emission = qt_material_emissive_color;\n";
810 if (specularLightingEnabled || hasImage)
811 fragmentShader <<
" float qt_iOR = qt_material_specular.w;\n";
814 const bool hasCustomIblProbe = hasCustomFrag && hasCustomFunction(QByteArrayLiteral(
"qt_iblProbeProcessor"));
817 fragmentShader <<
" vec4 fragOutput = vec4(0.0);\n";
819 if (isOrthoShadowPass)
820 vertexShader.generateDepth();
822 if (isPerspectiveShadowPass)
823 vertexShader.generateShadowWorldPosition(inKey);
828 if (hasLighting || isNormalPass) {
830 fragmentShader.addInclude(
"ssao.glsllib");
832 if (enableLightmap) {
833 vertexShader.generateLightmapUVCoords(inKey);
834 fragmentShader.addFunction(
"lightmap");
837 if (enableParallaxMapping) {
840 const bool hasIdentityMap = identityImages.contains(heightImage);
842 generateImageUVSampler(vertexShader, fragmentShader, inKey, *heightImage, imageFragCoords, heightImage->m_imageNode.m_indexUV);
844 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *heightImage,
true, heightImage->m_imageNode.m_indexUV);
845 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Height)];
846 fragmentShader.addInclude(
"parallaxMapping.glsllib");
847 fragmentShader <<
" float qt_heightAmount = qt_material_properties4.x;\n";
848 maskVariableByVertexColorChannel(
"qt_heightAmount", QSSGRenderDefaultMaterial::HeightAmountMask );
850 fragmentShader <<
" qt_texCoord0 = qt_parallaxMapping(" << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
", " << names.imageSampler
851 <<
", qt_tangent, qt_binormal, qt_world_normal, qt_varWorldPos, qt_cameraPosition, qt_heightAmount, qt_material_properties4.y, qt_material_properties4.z);\n";
853 fragmentShader <<
" qt_texCoord0 = qt_parallaxMapping(" << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
", " << names.imageSampler
854 <<
", qt_tangent, qt_binormal, qt_world_normal, qt_varWorldPos, qt_cameraPosition[qt_viewIndex], qt_heightAmount, qt_material_properties4.y, qt_material_properties4.z);\n";
859 if (enableClearcoat) {
860 addLocalVariable(fragmentShader,
"qt_clearcoatNormal",
"vec3");
866 fragmentShader <<
" qt_clearcoatNormal = qt_customClearcoatNormal;\n";
868 if (clearcoatNormalImage) {
869 if (enableParallaxMapping || !genClearcoatNormalImageCoords)
870 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *clearcoatNormalImage, enableParallaxMapping, clearcoatNormalImage->m_imageNode.m_indexUV);
871 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::ClearcoatNormal)];
872 fragmentShader.addFunction(
"sampleNormalTexture");
873 fragmentShader <<
" float qt_clearcoat_normal_strength = qt_material_clearcoat_normal_strength;\n";
874 maskVariableByVertexColorChannel(
"qt_clearcoat_normal_strength", QSSGRenderDefaultMaterial::ClearcoatNormalStrengthMask );
875 fragmentShader <<
" qt_clearcoatNormal = qt_sampleNormalTexture(" << names.imageSampler <<
", qt_clearcoat_normal_strength, " << names.imageFragCoords <<
", qt_tangent, qt_binormal, qt_world_normal);\n";
879 fragmentShader <<
" qt_clearcoatNormal = qt_world_normal;\n";
884 if (bumpImage !=
nullptr) {
885 if (enableParallaxMapping || !genBumpNormalImageCoords) {
886 generateImageUVCoordinates(vertexShader, fragmentShader, inKey,
887 *bumpImage, enableParallaxMapping,
888 bumpImage->m_imageNode.m_indexUV,
889 genBumpNormalImageCoords);
891 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Bump)];
892 fragmentShader.addUniform(names.imageSamplerSize,
"vec2");
893 fragmentShader.append(
" float qt_bumpAmount = qt_material_properties2.y;\n");
894 maskVariableByVertexColorChannel(
"qt_bumpAmount", QSSGRenderDefaultMaterial::NormalStrengthMask );
895 fragmentShader.addInclude(
"defaultMaterialBumpNoLod.glsllib");
896 fragmentShader <<
" qt_world_normal = qt_defaultMaterialBumpNoLod(" << names.imageSampler <<
", qt_bumpAmount, " << names.imageFragCoords <<
", qt_tangent, qt_binormal, qt_world_normal, " << names.imageSamplerSize <<
");\n";
897 }
else if (normalImage !=
nullptr) {
898 if (enableParallaxMapping || !genBumpNormalImageCoords) {
899 generateImageUVCoordinates(vertexShader, fragmentShader, inKey,
900 *normalImage, enableParallaxMapping,
901 normalImage->m_imageNode.m_indexUV,
902 genBumpNormalImageCoords);
904 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Normal)];
905 fragmentShader.append(
" float qt_normalStrength = qt_material_properties2.y;\n");
906 maskVariableByVertexColorChannel(
"qt_normalStrength", QSSGRenderDefaultMaterial::NormalStrengthMask );
907 fragmentShader.addFunction(
"sampleNormalTexture");
908 fragmentShader <<
" qt_world_normal = qt_sampleNormalTexture(" << names.imageSampler <<
", qt_normalStrength, " << names.imageFragCoords <<
", qt_tangent, qt_binormal, qt_world_normal);\n";
911 fragmentShader.append(
" vec3 tmp_light_color;");
914 if (specularLightingEnabled || hasImage) {
915 fragmentShader.append(
" vec3 qt_specularBase;");
916 fragmentShader.addUniform(
"qt_material_specular",
"vec4");
918 fragmentShader.append(
" vec3 qt_specularTint = vec3(1.0);");
920 fragmentShader.append(
" vec3 qt_specularTint = qt_material_specular.rgb;");
924 const bool hasIdentityMap = identityImages.contains(baseImage);
926 generateImageUVSampler(vertexShader, fragmentShader, inKey, *baseImage, imageFragCoords, baseImage->m_imageNode.m_indexUV);
928 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *baseImage, enableParallaxMapping, baseImage->m_imageNode.m_indexUV);
933 fragmentShader.addInclude(
"tonemapping.glsllib");
934 if (keyProps.m_baseColorSingleChannelEnabled.getValue(inKey)) {
935 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::BaseColorChannel];
936 fragmentShader <<
" vec4 qt_base_texture_color = vec4(vec3(texture2D(" << names.imageSampler <<
", " << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
"), 1.0f);\n";
938 fragmentShader <<
" vec4 qt_base_texture_color = texture2D(" << names.imageSampler <<
", " << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
");\n";
940 if (!keyProps.m_imageMaps[QSSGShaderDefaultMaterialKeyProperties::BaseColorMap].isLinear(inKey))
941 fragmentShader <<
" qt_base_texture_color = qt_sRGBToLinear(qt_base_texture_color);\n";
942 fragmentShader <<
" qt_diffuseColor *= qt_base_texture_color;\n";
946 if (keyProps.m_alphaMode.getAlphaMode(inKey) == QSSGRenderDefaultMaterial::MaterialAlphaMode::Mask) {
950 fragmentShader <<
" if (qt_diffuseColor.a < qt_material_properties3.y) {\n"
951 <<
" qt_diffuseColor = vec4(0.0);\n"
954 <<
" qt_diffuseColor.a = 1.0;\n"
956 }
else if (keyProps.m_alphaMode.getAlphaMode(inKey) == QSSGRenderDefaultMaterial::MaterialAlphaMode::Opaque) {
957 fragmentShader <<
" qt_diffuseColor.a = 1.0;\n";
961 const bool hasIdentityMap = identityImages.contains(opacityImage);
963 generateImageUVSampler(vertexShader, fragmentShader, inKey, *opacityImage, imageFragCoords, opacityImage->m_imageNode.m_indexUV);
965 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *opacityImage, enableParallaxMapping, opacityImage->m_imageNode.m_indexUV);
967 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Opacity)];
968 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::OpacityChannel];
969 fragmentShader <<
" float qt_opacity_map_value = texture2D(" << names.imageSampler <<
", " << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
";\n";
970 if (keyProps.m_invertOpacityMapValue.getValue(inKey))
971 fragmentShader <<
" qt_opacity_map_value = 1.0 - qt_opacity_map_value;\n";
972 fragmentShader <<
" qt_objectOpacity *= qt_opacity_map_value;\n";
977 addLocalVariable(fragmentShader,
"qt_aoFactor",
"float");
978 fragmentShader <<
" float qt_roughnessAmount = qt_customSpecularRoughness;\n";
979 fragmentShader <<
" qt_aoFactor *= qt_customOcclusionAmount;\n";
982 fragmentShader <<
" float qt_roughnessAmount = qt_material_properties.y;\n";
985 maskVariableByVertexColorChannel(
"qt_roughnessAmount", QSSGRenderDefaultMaterial::RoughnessMask );
987 if (roughnessImage) {
988 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::RoughnessChannel];
989 const bool hasIdentityMap = identityImages.contains(roughnessImage);
991 generateImageUVSampler(vertexShader, fragmentShader, inKey, *roughnessImage, imageFragCoords, roughnessImage->m_imageNode.m_indexUV);
993 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *roughnessImage, enableParallaxMapping, roughnessImage->m_imageNode.m_indexUV);
995 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Roughness)];
996 fragmentShader <<
" qt_roughnessAmount *= texture2D(" << names.imageSampler <<
", "
997 << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
";\n";
1000 if (materialAdapter->isSpecularGlossy())
1001 fragmentShader <<
" qt_roughnessAmount = clamp(1.0 - qt_roughnessAmount, 0.0, 1.0);\n";
1005 if (specularLightingEnabled) {
1006 vertexShader.generateViewVector(inKey);
1007 fragmentShader.addUniform(
"qt_material_properties",
"vec4");
1010 fragmentShader <<
" qt_specularBase = vec3(1.0);\n";
1012 fragmentShader <<
" qt_specularBase = qt_diffuseColor.rgb;\n";
1014 fragmentShader <<
" float qt_specularFactor = qt_customSpecularAmount;\n";
1016 fragmentShader <<
" float qt_specularFactor = qt_material_properties.x;\n";
1018 maskVariableByVertexColorChannel(
"qt_specularFactor", QSSGRenderDefaultMaterial::SpecularAmountMask );
1023 fragmentShader <<
" float qt_metalnessAmount = qt_customMetalnessAmount;\n";
1024 else if (!isSpecularGlossinessWorkflow)
1025 fragmentShader <<
" float qt_metalnessAmount = qt_material_properties.z;\n";
1027 fragmentShader <<
" float qt_metalnessAmount = 0.0;\n";
1029 maskVariableByVertexColorChannel(
"qt_metalnessAmount", QSSGRenderDefaultMaterial::MetalnessMask );
1031 if (specularLightingEnabled && metalnessImage) {
1032 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::MetalnessChannel];
1033 const bool hasIdentityMap = identityImages.contains(metalnessImage);
1035 generateImageUVSampler(vertexShader, fragmentShader, inKey, *metalnessImage, imageFragCoords, metalnessImage->m_imageNode.m_indexUV);
1037 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *metalnessImage, enableParallaxMapping, metalnessImage->m_imageNode.m_indexUV);
1039 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Metalness)];
1040 fragmentShader <<
" float qt_sampledMetalness = texture2D(" << names.imageSampler <<
", "
1041 << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
";\n";
1042 fragmentShader <<
" qt_metalnessAmount = clamp(qt_metalnessAmount * qt_sampledMetalness, 0.0, 1.0);\n";
1045 fragmentShader.addUniform(
"qt_light_ambient_total",
"vec3");
1047 fragmentShader.append(
" vec4 global_diffuse_light = vec4(0.0);");
1049 if (enableLightmap) {
1050 fragmentShader <<
" global_diffuse_light.rgb = qt_lightmap_color(qt_texCoordLightmap) * (1.0 - qt_metalnessAmount) * qt_diffuseColor.rgb;\n";
1052 if (hasCustomFrag && hasCustomFunction(QByteArrayLiteral(
"qt_ambientLightProcessor"))) {
1054 fragmentShader.append(
" qt_ambientLightProcessor(global_diffuse_light.rgb, qt_light_ambient_total.rgb * (1.0 - qt_metalnessAmount) * qt_diffuseColor.rgb, qt_world_normal, qt_view_vector");
1056 fragmentShader <<
", qt_customShared);\n";
1058 fragmentShader <<
");\n";
1060 fragmentShader.append(
" global_diffuse_light = vec4(qt_light_ambient_total.rgb * (1.0 - qt_metalnessAmount) * qt_diffuseColor.rgb, 0.0);");
1064 fragmentShader.append(
" vec3 global_specular_light = vec3(0.0);");
1068 if (specularAmountImage) {
1069 const bool hasIdentityMap = identityImages.contains(specularAmountImage);
1071 generateImageUVSampler(vertexShader, fragmentShader, inKey, *specularAmountImage, imageFragCoords, specularAmountImage->m_imageNode.m_indexUV);
1073 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *specularAmountImage, enableParallaxMapping, specularAmountImage->m_imageNode.m_indexUV);
1075 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::SpecularAmountMap )];
1077 if (keyProps.m_specularSingleChannelEnabled.getValue(inKey)) {
1078 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::SpecularAmountChannel];
1079 fragmentShader <<
" vec4 qt_specular_amount_map = vec4(vec3(texture2D(" << names.imageSampler <<
", " << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
"), 1.0f);\n";
1081 fragmentShader <<
" vec4 qt_specular_amount_map = texture2D(" << names.imageSampler <<
", " << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
");\n";
1083 fragmentShader <<
" qt_specularBase *= qt_sRGBToLinear(qt_specular_amount_map).rgb;\n";
1086 if (specularLightingEnabled) {
1087 if (isSpecularGlossinessWorkflow) {
1088 fragmentShader <<
" qt_specularTint *= qt_specularBase;\n";
1089 fragmentShader <<
" vec3 qt_specularAmount = vec3(1.0);\n";
1091 fragmentShader <<
" vec3 qt_specularAmount = qt_specularBase * vec3(qt_metalnessAmount + qt_specularFactor * (1.0 - qt_metalnessAmount));\n";
1095 if (translucencyImage !=
nullptr) {
1096 const bool hasIdentityMap = identityImages.contains(translucencyImage);
1098 generateImageUVSampler(vertexShader, fragmentShader, inKey, *translucencyImage, imageFragCoords);
1100 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *translucencyImage, enableParallaxMapping);
1102 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Translucency)];
1103 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::TranslucencyChannel];
1104 fragmentShader <<
" float qt_translucent_depth_range = texture2D(" << names.imageSampler
1105 <<
", " << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
";\n";
1106 fragmentShader <<
" float qt_translucent_thickness = qt_translucent_depth_range * qt_translucent_depth_range;\n";
1107 fragmentShader <<
" float qt_translucent_thickness_exp = exp(qt_translucent_thickness * qt_material_properties2.z);\n";
1110 addLocalVariable(fragmentShader,
"qt_aoFactor",
"float");
1113 fragmentShader.append(
" qt_aoFactor = qt_screenSpaceAmbientOcclusionFactor();");
1115 fragmentShader.append(
" qt_aoFactor = 1.0;");
1117 if (hasCustomFrag) {
1118 fragmentShader <<
" float qt_roughnessAmount = qt_customSpecularRoughness;\n";
1119 fragmentShader <<
" qt_aoFactor *= qt_customOcclusionAmount;\n";
1122 fragmentShader <<
" float qt_roughnessAmount = qt_material_properties.y;\n";
1125 maskVariableByVertexColorChannel(
"qt_roughnessAmount", QSSGRenderDefaultMaterial::RoughnessMask );
1129 if (occlusionImage) {
1130 addLocalVariable(fragmentShader,
"qt_ao",
"float");
1131 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::OcclusionChannel];
1132 const bool hasIdentityMap = identityImages.contains(occlusionImage);
1134 generateImageUVSampler(vertexShader, fragmentShader, inKey, *occlusionImage, imageFragCoords, occlusionImage->m_imageNode.m_indexUV);
1136 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *occlusionImage, enableParallaxMapping, occlusionImage->m_imageNode.m_indexUV);
1137 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Occlusion)];
1138 fragmentShader <<
" qt_ao = texture2D(" << names.imageSampler <<
", "
1139 << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
";\n";
1140 fragmentShader <<
" qt_aoFactor *= qt_ao * qt_material_properties3.x;\n";
1142 maskVariableByVertexColorChannel(
"qt_aoFactor", QSSGRenderDefaultMaterial::OcclusionAmountMask );
1145 if (specularLightingEnabled && roughnessImage) {
1146 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::RoughnessChannel];
1147 const bool hasIdentityMap = identityImages.contains(roughnessImage);
1149 generateImageUVSampler(vertexShader, fragmentShader, inKey, *roughnessImage, imageFragCoords, roughnessImage->m_imageNode.m_indexUV);
1151 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *roughnessImage, enableParallaxMapping, roughnessImage->m_imageNode.m_indexUV);
1153 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Roughness)];
1154 fragmentShader <<
" qt_roughnessAmount *= texture2D(" << names.imageSampler <<
", "
1155 << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
";\n";
1159 if (isSpecularGlossinessWorkflow)
1160 fragmentShader <<
" qt_roughnessAmount = clamp(1.0 - qt_roughnessAmount, 0.0, 1.0);\n";
1162 if (enableClearcoat) {
1163 addLocalVariable(fragmentShader,
"qt_clearcoatAmount",
"float");
1164 addLocalVariable(fragmentShader,
"qt_clearcoatRoughness",
"float");
1165 addLocalVariable(fragmentShader,
"qt_clearcoatF0",
"vec3");
1166 addLocalVariable(fragmentShader,
"qt_clearcoatF90",
"vec3");
1167 addLocalVariable(fragmentShader,
"qt_global_clearcoat",
"vec3");
1170 fragmentShader <<
" qt_clearcoatAmount = qt_customClearcoatAmount;\n";
1172 fragmentShader <<
" qt_clearcoatAmount = qt_material_properties3.z;\n";
1173 maskVariableByVertexColorChannel(
"qt_clearcoatAmount", QSSGRenderDefaultMaterial::ClearcoatAmountMask );
1175 fragmentShader <<
" qt_clearcoatRoughness = qt_customClearcoatRoughness;\n";
1177 fragmentShader <<
" qt_clearcoatRoughness = qt_material_properties3.w;\n";
1178 maskVariableByVertexColorChannel(
"qt_clearcoatRoughness", QSSGRenderDefaultMaterial::ClearcoatRoughnessAmountMask );
1179 fragmentShader <<
" qt_clearcoatF0 = vec3(((1.0-qt_iOR) * (1.0-qt_iOR)) / ((1.0+qt_iOR) * (1.0+qt_iOR)));\n";
1180 fragmentShader <<
" qt_clearcoatF90 = vec3(1.0);\n";
1181 fragmentShader <<
" qt_global_clearcoat = vec3(0.0);\n";
1183 if (clearcoatImage) {
1184 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::ClearcoatChannel];
1185 const bool hasIdentityMap = identityImages.contains(clearcoatImage);
1187 generateImageUVSampler(vertexShader, fragmentShader, inKey, *clearcoatImage, imageFragCoords, clearcoatImage->m_imageNode.m_indexUV);
1189 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *clearcoatImage, enableParallaxMapping, clearcoatImage->m_imageNode.m_indexUV);
1190 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Clearcoat)];
1191 fragmentShader <<
" qt_clearcoatAmount *= texture2D(" << names.imageSampler <<
", "
1192 << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
";\n";
1195 if (clearcoatRoughnessImage) {
1196 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::ClearcoatRoughnessChannel];
1197 const bool hasIdentityMap = identityImages.contains(clearcoatRoughnessImage);
1199 generateImageUVSampler(vertexShader, fragmentShader, inKey, *clearcoatRoughnessImage, imageFragCoords, clearcoatRoughnessImage->m_imageNode.m_indexUV);
1201 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *clearcoatRoughnessImage, enableParallaxMapping, clearcoatRoughnessImage->m_imageNode.m_indexUV);
1202 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::ClearcoatRoughness)];
1203 fragmentShader <<
" qt_clearcoatRoughness *= texture2D(" << names.imageSampler <<
", "
1204 << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
";\n";
1205 fragmentShader <<
" qt_clearcoatRoughness = clamp(qt_clearcoatRoughness, 0.0, 1.0);\n";
1209 if (enableTransmission) {
1210 fragmentShader.addInclude(
"transmission.glsllib");
1211 addLocalVariable(fragmentShader,
"qt_transmissionFactor",
"float");
1212 addLocalVariable(fragmentShader,
"qt_global_transmission",
"vec3");
1214 addLocalVariable(fragmentShader,
"qt_thicknessFactor",
"float");
1215 addLocalVariable(fragmentShader,
"qt_attenuationColor",
"vec3");
1216 addLocalVariable(fragmentShader,
"qt_attenuationDistance",
"float");
1217 fragmentShader <<
" qt_global_transmission = vec3(0.0);\n";
1219 if (hasCustomFrag) {
1220 fragmentShader <<
" qt_transmissionFactor = qt_customTransmissionFactor;\n";
1221 fragmentShader <<
" qt_thicknessFactor = qt_customThicknessFactor;\n";
1222 fragmentShader <<
" qt_attenuationColor = qt_customAttenuationColor;\n";
1223 fragmentShader <<
" qt_attenuationDistance = qt_customAttenuationDistance;\n";
1225 fragmentShader <<
" qt_transmissionFactor = qt_material_properties4.w;\n";
1226 maskVariableByVertexColorChannel(
"qt_transmissionFactor", QSSGRenderDefaultMaterial::TransmissionFactorMask );
1228 if (transmissionImage) {
1229 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::TransmissionChannel];
1230 const bool hasIdentityMap = identityImages.contains(transmissionImage);
1232 generateImageUVSampler(vertexShader, fragmentShader, inKey, *transmissionImage, imageFragCoords, transmissionImage->m_imageNode.m_indexUV);
1234 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *transmissionImage, enableParallaxMapping, transmissionImage->m_imageNode.m_indexUV);
1235 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Transmission)];
1236 fragmentShader <<
" qt_transmissionFactor *= texture2D(" << names.imageSampler <<
", "
1237 << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
";\n";
1240 fragmentShader <<
" qt_thicknessFactor = qt_material_thickness;\n";
1241 maskVariableByVertexColorChannel(
"qt_thicknessFactor", QSSGRenderDefaultMaterial::ThicknessFactorMask );
1242 fragmentShader <<
" qt_attenuationColor = qt_material_attenuation.xyz;\n";
1243 fragmentShader <<
" qt_attenuationDistance = qt_material_attenuation.w;\n";
1245 if (thicknessImage) {
1246 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::ThicknessChannel];
1247 const bool hasIdentityMap = identityImages.contains(thicknessImage);
1249 generateImageUVSampler(vertexShader, fragmentShader, inKey, *thicknessImage, imageFragCoords, thicknessImage->m_imageNode.m_indexUV);
1251 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *thicknessImage, enableParallaxMapping, thicknessImage->m_imageNode.m_indexUV);
1252 const auto &names = imageStringTable[
int(QSSGRenderableImage::Type::Thickness)];
1253 fragmentShader <<
" qt_thicknessFactor *= texture2D(" << names.imageSampler <<
", "
1254 << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
")" << channelStr(channelProps, inKey) <<
";\n";
1258 if (hasPunctualLights || specularLightingEnabled) {
1259 fragmentShader <<
" vec3 qt_f0 = vec3(1.0);\n";
1260 fragmentShader <<
" vec3 qt_f90 = vec3(1.0);\n";
1263 if (specularLightingEnabled) {
1264 fragmentShader.addInclude(
"principledMaterialFresnel.glsllib");
1265 if (!isSpecularGlossinessWorkflow) {
1266 fragmentShader <<
" qt_f0 = qt_F0_ior(qt_iOR, qt_metalnessAmount, qt_diffuseColor.rgb);\n";
1268 fragmentShader <<
" const float qt_reflectance = max(max(qt_specularTint.r, qt_specularTint.g), qt_specularTint.b);\n";
1269 fragmentShader <<
" qt_f0 = qt_specularTint;\n";
1270 fragmentShader <<
" qt_specularTint = vec3(1.0);\n";
1271 fragmentShader <<
" qt_f90 = vec3(clamp(qt_reflectance * 50.0, 0.0, 1.0));\n";
1272 fragmentShader <<
" qt_diffuseColor.rgb *= (1 - qt_reflectance);\n";
1275 if (specularAAEnabled) {
1276 fragmentShader.append(
" vec3 vNormalWsDdx = dFdx(qt_world_normal.xyz);\n");
1277 fragmentShader.append(
" vec3 vNormalWsDdy = dFdy(qt_world_normal.xyz);\n");
1278 fragmentShader.append(
" float flGeometricRoughnessFactor = pow(clamp(max(dot(vNormalWsDdx, vNormalWsDdx), dot(vNormalWsDdy, vNormalWsDdy)), 0.0, 1.0), 0.333);\n");
1279 fragmentShader.append(
" qt_roughnessAmount = max(flGeometricRoughnessFactor, qt_roughnessAmount);\n");
1283 fragmentShader <<
" float qt_fresnelPower = qt_customFresnelPower;\n";
1285 fragmentShader <<
" float qt_fresnelPower = qt_material_properties2.x;\n";
1287 if (isPbrMaterial) {
1288 fragmentShader <<
" vec3 qt_principledMaterialFresnelValue = qt_principledMaterialFresnel(qt_world_normal, qt_view_vector, qt_f0, qt_roughnessAmount, qt_fresnelPower);\n";
1289 if (enableFresnelScaleBias) {
1290 if (hasCustomFrag) {
1291 fragmentShader <<
" float qt_fresnelScale = qt_customFresnelScale;\n";
1292 fragmentShader <<
" float qt_fresnelBias = qt_customFresnelBias;\n";
1294 fragmentShader <<
" float qt_fresnelScale = qt_material_properties5.x;\n";
1295 fragmentShader <<
" float qt_fresnelBias = qt_material_properties5.y;\n";
1297 fragmentShader <<
" qt_principledMaterialFresnelValue = clamp(vec3(qt_fresnelBias) + "
1298 <<
"qt_fresnelScale * qt_principledMaterialFresnelValue, 0.0, 1.0);\n";
1300 fragmentShader <<
" qt_specularAmount *= qt_principledMaterialFresnelValue;\n";
1301 if (isMetallicRoughnessWorkflow) {
1304 fragmentShader <<
" qt_specularTint = mix(vec3(1.0), qt_specularTint, 1.0 - qt_metalnessAmount);\n";
1307 fragmentShader <<
" qt_specularAmount *= qt_principledMaterialFresnel(qt_world_normal, qt_view_vector, qt_f0, qt_roughnessAmount, qt_fresnelPower);\n";
1311 if (hasLighting && hasPunctualLights) {
1312 fragmentShader.addUniform(
"qt_lightAndShadowCounts",
"vec4");
1313 fragmentShader.addFunction(
"processPunctualLighting");
1314 fragmentShader <<
" qt_processPunctualLighting(global_diffuse_light.rgb,\n"
1315 <<
" global_specular_light.rgb,\n"
1316 <<
" qt_diffuseColor.rgb,\n"
1317 <<
" qt_world_normal.xyz,\n"
1318 <<
" qt_view_vector,\n"
1319 <<
"#if QSSG_ENABLE_SPECULAR\n"
1320 <<
" qt_specularAmount,\n"
1321 <<
" qt_specularTint,\n"
1322 <<
"#endif // QSSG_ENABLE_SPECULAR\n"
1323 <<
" qt_roughnessAmount,\n"
1324 <<
" qt_metalnessAmount,\n"
1325 <<
"#if QSSG_CUSTOM_MATERIAL_DIRECTIONAL_LIGHT_PROCESSOR || QSSG_CUSTOM_MATERIAL_POINT_LIGHT_PROCESSOR || QSSG_CUSTOM_MATERIAL_SPOT_LIGHT_PROCESSOR || QSSG_CUSTOM_MATERIAL_SPECULAR_PROCESSOR\n"
1326 <<
" qt_customBaseColor,\n"
1327 <<
"#endif // QSSG_CUSTOM_MATERIAL_*\n"
1328 <<
"#if QSSG_CUSTOM_MATERIAL_SPECULAR_PROCESSOR\n"
1329 <<
" qt_customSpecularAmount,\n"
1330 <<
"#endif // QSSG_CUSTOM_MATERIAL_SPECULAR_PROCESSOR\n"
1331 <<
"#if QSSG_CUSTOM_MATERIAL_SHARED_VARIABLES\n"
1332 <<
" qt_customShared,\n"
1333 <<
"#endif // QSSG_CUSTOM_MATERIAL_SHARED_VARIABLES\n"
1334 <<
"#if QSSG_ENABLE_CLEARCOAT\n"
1335 <<
" qt_global_clearcoat,\n"
1336 <<
" qt_clearcoatNormal,\n"
1337 <<
" qt_clearcoatRoughness,\n"
1338 <<
" qt_clearcoatF0,\n"
1339 <<
" qt_clearcoatF90,\n"
1340 <<
"#endif // QSSG_ENABLE_CLEARCOAT\n"
1341 <<
"#if QSSG_ENABLE_TRANSMISSION\n"
1342 <<
" qt_global_transmission,\n"
1343 <<
" qt_thicknessFactor,\n"
1345 <<
" qt_transmissionFactor,\n"
1346 <<
" qt_attenuationColor,\n"
1347 <<
" qt_attenuationDistance,\n"
1348 <<
"#endif // QSSG_ENABLE_TRANSMISSION\n"
1356 fragmentShader <<
" global_diffuse_light = vec4(global_diffuse_light.rgb * qt_aoFactor, qt_objectOpacity * qt_diffuseColor.a);\n";
1358 if (hasReflectionProbe) {
1359 vertexShader.generateWorldNormal(inKey);
1360 fragmentShader.addInclude(
"sampleReflectionProbe.glsllib");
1362 fragmentShader <<
" vec3 qt_reflectionDiffuse = vec3(0.0);\n";
1363 if (isPbrMaterial) {
1364 fragmentShader <<
" qt_reflectionDiffuse = qt_diffuseColor.rgb * (1.0 - qt_specularAmount) * qt_sampleDiffuseReflection(qt_reflectionMap, qt_world_normal).rgb;\n";
1366 fragmentShader <<
" qt_reflectionDiffuse = qt_diffuseColor.rgb * qt_sampleDiffuseReflection(qt_reflectionMap, qt_world_normal).rgb;\n";
1369 if (specularLightingEnabled) {
1370 fragmentShader <<
" vec3 qt_reflectionSpecular = vec3(0.0);\n";
1371 if (isPbrMaterial) {
1372 fragmentShader <<
" qt_reflectionSpecular = "
1373 <<
"qt_specularTint * qt_sampleGlossyReflectionPrincipled(qt_reflectionMap, qt_world_normal, qt_view_vector, qt_specularAmount, qt_roughnessAmount).rgb;\n";
1375 fragmentShader <<
" qt_reflectionSpecular = qt_specularAmount * "
1376 <<
"qt_specularTint * qt_sampleGlossyReflection(qt_reflectionMap, qt_world_normal, qt_view_vector, qt_roughnessAmount).rgb;\n";
1379 if (enableClearcoat) {
1380 fragmentShader <<
" vec3 qt_iblClearcoat = qt_sampleGlossyReflectionPrincipled(qt_reflectionMap, qt_clearcoatNormal, qt_view_vector, qt_clearcoatF0, qt_clearcoatRoughness).rgb;\n";
1383 fragmentShader <<
" global_diffuse_light.rgb += qt_reflectionDiffuse;\n";
1384 if (specularLightingEnabled)
1385 fragmentShader <<
" global_specular_light += qt_reflectionSpecular;\n";
1386 if (enableClearcoat)
1387 fragmentShader <<
" qt_global_clearcoat += qt_iblClearcoat;\n";
1388 }
else if (hasIblProbe) {
1389 vertexShader.generateWorldNormal(inKey);
1390 fragmentShader.addInclude(
"sampleProbe.glsllib");
1391 if (hasCustomIblProbe) {
1393 fragmentShader <<
" vec3 qt_iblDiffuse = vec3(0.0);\n";
1394 fragmentShader <<
" vec3 qt_iblSpecular = vec3(0.0);\n";
1395 fragmentShader <<
" qt_iblProbeProcessor(qt_iblDiffuse, qt_iblSpecular, qt_customBaseColor, qt_aoFactor, qt_specularFactor, qt_roughnessAmount, qt_world_normal, qt_view_vector";
1396 if (hasIblOrientation)
1397 fragmentShader <<
", qt_lightProbeOrientation";
1399 fragmentShader <<
", mat3(1.0)";
1401 fragmentShader <<
", qt_customShared);\n";
1403 fragmentShader <<
");\n";
1405 if (isPbrMaterial) {
1406 fragmentShader <<
" vec3 qt_iblDiffuse = qt_diffuseColor.rgb * (1.0 - qt_specularAmount) * qt_sampleDiffuse(qt_world_normal).rgb;\n";
1408 fragmentShader <<
" vec3 qt_iblDiffuse = qt_diffuseColor.rgb * qt_sampleDiffuse(qt_world_normal).rgb;\n";
1410 if (specularLightingEnabled) {
1411 if (isPbrMaterial) {
1412 fragmentShader <<
" vec3 qt_iblSpecular = "
1413 <<
"qt_specularTint * qt_sampleGlossyPrincipled(qt_world_normal, qt_view_vector, qt_specularAmount, qt_roughnessAmount).rgb;\n";
1415 fragmentShader <<
" vec3 qt_iblSpecular = qt_specularAmount * "
1416 <<
"qt_specularTint * qt_sampleGlossy(qt_world_normal, qt_view_vector, qt_roughnessAmount).rgb;\n";
1419 if (enableClearcoat) {
1420 fragmentShader <<
" vec3 qt_iblClearcoat = qt_sampleGlossyPrincipled(qt_clearcoatNormal, qt_view_vector, qt_clearcoatF0, qt_clearcoatRoughness).rgb;\n";
1424 fragmentShader <<
" global_diffuse_light.rgb += qt_iblDiffuse * qt_aoFactor;\n";
1425 if (specularLightingEnabled)
1426 fragmentShader <<
" global_specular_light += qt_iblSpecular * qt_aoFactor;\n";
1427 if (enableClearcoat)
1428 fragmentShader <<
" qt_global_clearcoat += qt_iblClearcoat * qt_aoFactor;\n";
1429 }
else if (hasCustomIblProbe) {
1431 fragmentShader.addUniform(
"qt_lightProbe",
"samplerCube");
1432 fragmentShader.addUniform(
"qt_lightProbeProperties",
"vec4");
1436 if (enableTransmission) {
1437 fragmentShader <<
" qt_global_transmission += qt_transmissionFactor * qt_getIBLVolumeRefraction(qt_world_normal, qt_view_vector, qt_roughnessAmount, "
1438 "qt_diffuseColor.rgb, qt_specularAmount, qt_varWorldPos, qt_iOR, qt_thicknessFactor, qt_attenuationColor, qt_attenuationDistance);\n";
1442 bool texColorDeclared =
false;
1443 for (QSSGRenderableImage *image = firstImage; image; image = image->m_nextImage) {
1445 if (image->m_mapType != QSSGRenderableImage::Type::Specular
1446 && image->m_mapType != QSSGRenderableImage::Type::Emissive)
1451 if (!texColorDeclared) {
1452 fragmentShader.append(
" vec4 qt_texture_color;");
1453 texColorDeclared =
true;
1456 const bool hasIdentityMap = identityImages.contains(image);
1458 generateImageUVSampler(vertexShader, fragmentShader, inKey, *image, imageFragCoords, image->m_imageNode.m_indexUV);
1460 generateImageUVCoordinates(vertexShader, fragmentShader, inKey, *image, enableParallaxMapping, image->m_imageNode.m_indexUV);
1463 fragmentShader <<
" qt_texture_color = texture2D(" << names.imageSampler
1464 <<
", " << (hasIdentityMap ? imageFragCoords : names.imageFragCoords) <<
");\n";
1466 switch (image->m_mapType) {
1467 case QSSGRenderableImage::Type::Specular:
1468 fragmentShader.addInclude(
"tonemapping.glsllib");
1469 fragmentShader.append(
" global_specular_light += qt_sRGBToLinear(qt_texture_color.rgb) * qt_specularTint;");
1470 fragmentShader.append(
" global_diffuse_light.a *= qt_texture_color.a;");
1472 case QSSGRenderableImage::Type::Emissive:
1473 fragmentShader.addInclude(
"tonemapping.glsllib");
1474 if (keyProps.m_emissiveSingleChannelEnabled.getValue(inKey)) {
1475 const auto &channelProps = keyProps.m_textureChannels[QSSGShaderDefaultMaterialKeyProperties::EmissiveChannel];
1476 fragmentShader <<
" qt_global_emission *= qt_sRGBToLinear(vec3(qt_texture_color" <<
1477 channelStr(channelProps, inKey) <<
"));\n";
1479 fragmentShader.append(
" qt_global_emission *= qt_sRGBToLinear(qt_texture_color.rgb);");
1489 if (enableTransmission)
1490 fragmentShader <<
" global_diffuse_light.rgb = mix(global_diffuse_light.rgb, qt_global_transmission, qt_transmissionFactor);\n";
1492 if (isMetallicRoughnessWorkflow) {
1493 fragmentShader <<
" global_diffuse_light.rgb *= 1.0 - qt_metalnessAmount;\n";
1497 fragmentShader.addInclude(
"fog.glsllib");
1498 fragmentShader <<
" calculateFog(qt_global_emission, global_specular_light, global_diffuse_light.rgb);\n";
1501 fragmentShader <<
" vec4 qt_color_sum = vec4(global_diffuse_light.rgb + global_specular_light + qt_global_emission, global_diffuse_light.a);\n";
1503 if (enableClearcoat) {
1504 fragmentShader.addInclude(
"bsdf.glsllib");
1506 fragmentShader <<
" float qt_clearcoatFresnelPower = qt_customClearcoatFresnelPower;\n";
1508 fragmentShader <<
" float qt_clearcoatFresnelPower = qt_material_clearcoat_fresnel_power;\n";
1509 fragmentShader <<
" vec3 qt_clearcoatFresnel = qt_schlick3(qt_clearcoatF0, qt_clearcoatF90, clamp(dot(qt_clearcoatNormal, qt_view_vector), 0.0, 1.0), qt_clearcoatFresnelPower);\n";
1510 if (enableClearcoatFresnelScaleBias) {
1511 if (hasCustomFrag) {
1512 fragmentShader <<
" float qt_clearcoatFresnelScale = qt_customClearcoatFresnelScale;\n";
1513 fragmentShader <<
" float qt_clearcoatFresnelBias = qt_customClearcoatFresnelBias;\n";
1515 fragmentShader <<
" float qt_clearcoatFresnelScale = qt_material_properties5.z;\n";
1516 fragmentShader <<
" float qt_clearcoatFresnelBias = qt_material_properties5.w;\n";
1518 fragmentShader <<
" qt_clearcoatFresnel = clamp(vec3(qt_clearcoatFresnelBias) + qt_clearcoatFresnelScale * qt_clearcoatFresnel, 0.0, 1.0);\n";
1520 fragmentShader <<
" qt_global_clearcoat = qt_global_clearcoat * qt_clearcoatAmount;\n";
1521 fragmentShader <<
" qt_color_sum.rgb = qt_color_sum.rgb * (1.0 - qt_clearcoatAmount * qt_clearcoatFresnel) + qt_global_clearcoat;\n";
1524 if (hasCustomFrag && hasCustomFunction(QByteArrayLiteral(
"qt_customPostProcessor"))) {
1526 fragmentShader <<
" qt_customPostProcessor(qt_color_sum, global_diffuse_light, global_specular_light, qt_global_emission, qt_texCoord0, qt_texCoord1";
1528 fragmentShader <<
", qt_customShared);\n";
1530 fragmentShader <<
");\n";
1533 Q_ASSERT(!isDepthPass && !isOrthoShadowPass && !isPerspectiveShadowPass && !isNormalPass);
1535 if (oitMethod == QSSGRenderLayer::OITMethod::WeightedBlended) {
1536 fragmentShader.addInclude(
"orderindependenttransparency.glsllib");
1537 fragmentShader.addInclude(
"tonemapping.glsllib");
1538 fragmentShader.addUniform(
"qt_cameraPosition",
"vec3");
1539 fragmentShader.addUniform(
"qt_cameraProperties",
"vec2");
1540 fragmentShader.append(
" float z = abs(gl_FragCoord.z);");
1541 fragmentShader.append(
" qt_color_sum.rgb = qt_tonemap(qt_color_sum.rgb) * qt_color_sum.a;");
1542 fragmentShader.append(
" fragOutput = qt_color_sum * qt_transparencyWeight(z, qt_color_sum.a, qt_cameraProperties.y);");
1543 fragmentShader.append(
" revealageOutput = vec4(qt_color_sum.a);");
1545 fragmentShader.addInclude(
"tonemapping.glsllib");
1546 fragmentShader.append(
" fragOutput = vec4(qt_tonemap(qt_color_sum));");
1549 if (Q_UNLIKELY(debugMode != QSSGRenderLayer::MaterialDebugMode::None)) {
1550 fragmentShader.append(
" vec3 debugOutput = vec3(0.0);\n");
1551 switch (debugMode) {
1552 case QSSGRenderLayer::MaterialDebugMode::BaseColor:
1553 fragmentShader.append(
" debugOutput += qt_tonemap(qt_diffuseColor.rgb);\n");
1555 case QSSGRenderLayer::MaterialDebugMode::Roughness:
1556 fragmentShader.append(
" debugOutput += vec3(qt_roughnessAmount);\n");
1558 case QSSGRenderLayer::MaterialDebugMode::Metalness:
1559 fragmentShader.append(
" debugOutput += vec3(qt_metalnessAmount);\n");
1561 case QSSGRenderLayer::MaterialDebugMode::Diffuse:
1562 fragmentShader.append(
" debugOutput += qt_tonemap(global_diffuse_light.rgb);\n");
1564 case QSSGRenderLayer::MaterialDebugMode::Specular:
1565 fragmentShader.append(
" debugOutput += qt_tonemap(global_specular_light);\n");
1567 case QSSGRenderLayer::MaterialDebugMode::ShadowOcclusion:
1570 fragmentShader.addFunction(
"debugShadowOcclusion");
1571 fragmentShader.append(
" debugOutput += vec3(qt_debugShadowOcclusion());\n");
1573 case QSSGRenderLayer::MaterialDebugMode::Emission:
1574 fragmentShader.append(
" debugOutput += qt_tonemap(qt_global_emission);\n");
1576 case QSSGRenderLayer::MaterialDebugMode::AmbientOcclusion:
1577 fragmentShader.append(
" debugOutput += vec3(qt_aoFactor);\n");
1579 case QSSGRenderLayer::MaterialDebugMode::Normal:
1580 fragmentShader.append(
" debugOutput += qt_world_normal * 0.5 + 0.5;\n");
1582 case QSSGRenderLayer::MaterialDebugMode::Tangent:
1583 fragmentShader.append(
" debugOutput += qt_tangent * 0.5 + 0.5;\n");
1585 case QSSGRenderLayer::MaterialDebugMode::Binormal:
1586 fragmentShader.append(
" debugOutput += qt_binormal * 0.5 + 0.5;\n");
1588 case QSSGRenderLayer::MaterialDebugMode::F0:
1590 fragmentShader.append(
" debugOutput += qt_f0;");
1592 case QSSGRenderLayer::MaterialDebugMode::None:
1596 fragmentShader.append(
" fragOutput = vec4(debugOutput, 1.0);\n");
1599 if ((isOrthoShadowPass || isPerspectiveShadowPass || isDepthPass) && isOpaqueDepthPrePass) {
1600 fragmentShader <<
" if ((qt_diffuseColor.a * qt_objectOpacity) < (1.0 - 1e-6))\n";
1601 fragmentShader <<
" discard;\n";
1604 if (isOrthoShadowPass) {
1605 Q_ASSERT(viewCount == 1);
1606 fragmentShader <<
" // directional shadow pass\n"
1607 <<
" float qt_shadowDepth = (qt_varDepth + qt_shadowDepthAdjust.x) * qt_shadowDepthAdjust.y;\n"
1608 <<
" fragOutput = vec4(qt_shadowDepth);\n";
1609 }
else if (isPerspectiveShadowPass) {
1610 Q_ASSERT(viewCount == 1);
1611 fragmentShader.addUniform(
"qt_cameraPosition",
"vec3");
1612 fragmentShader.addUniform(
"qt_cameraProperties",
"vec2");
1613 fragmentShader <<
" // omnidirectional shadow pass\n"
1614 <<
" vec3 qt_shadowCamPos = vec3(qt_cameraPosition.x, qt_cameraPosition.y, qt_cameraPosition.z);\n"
1615 <<
" float qt_shadowDist = length(qt_varShadowWorldPos - qt_shadowCamPos);\n"
1616 <<
" qt_shadowDist = (qt_shadowDist - qt_cameraProperties.x) / (qt_cameraProperties.y - qt_cameraProperties.x);\n"
1617 <<
" fragOutput = vec4(qt_shadowDist, qt_shadowDist, qt_shadowDist, 1.0);\n";
1618 }
else if (isNormalPass) {
1620 fragmentShader.append(
" fragOutput = vec4(qt_world_normal, qt_roughnessAmount);\n");
1622 if (oitMethod == QSSGRenderLayer::OITMethod::WeightedBlended) {
1623 fragmentShader.addInclude(
"orderindependenttransparency.glsllib");
1624 fragmentShader.addUniform(
"qt_cameraPosition",
"vec3");
1625 fragmentShader.addUniform(
"qt_cameraProperties",
"vec2");
1626 fragmentShader.append(
" float z = abs(gl_FragCoord.z);");
1627 fragmentShader.append(
" vec4 color = vec4(qt_diffuseColor.rgb, qt_diffuseColor.a * qt_objectOpacity);");
1628 fragmentShader.append(
" fragOutput = qt_transparencyWeight(z, color.a, qt_cameraProperties.y) * color;");
1629 fragmentShader.append(
" revealageOutput = vec4(color.a);");
1631 fragmentShader.addInclude(
"tonemapping.glsllib");
1632 fragmentShader.append(
" fragOutput = vec4(qt_tonemap(qt_diffuseColor.rgb), qt_diffuseColor.a * qt_objectOpacity);");
1710void QSSGMaterialShaderGenerator::setRhiMaterialProperties(
const QSSGRenderContextInterface &renderContext,
1711 QSSGRhiShaderPipeline &shaders,
1713 QSSGRhiGraphicsPipelineState *inPipelineState,
1714 const QSSGRenderGraphObject &inMaterial,
1715 const QSSGShaderDefaultMaterialKey &inKey,
1716 const QSSGShaderDefaultMaterialKeyProperties &inProperties,
1717 const QSSGRenderCameraList &inCameras,
1718 const QSSGRenderMvpArray &inModelViewProjections,
1719 const QMatrix3x3 &inNormalMatrix,
1720 const QMatrix4x4 &inGlobalTransform,
1721 const QMatrix4x4 &clipSpaceCorrMatrix,
1722 const QMatrix4x4 &localInstanceTransform,
1723 const QMatrix4x4 &globalInstanceTransform,
1724 const QSSGDataView<
float> &inMorphWeights,
1725 QSSGRenderableImage *inFirstImage,
1727 const QSSGLayerRenderData &inRenderProperties,
1728 const QSSGShaderLightListView &inLights,
1729 const QSSGShaderReflectionProbe &reflectionProbe,
1730 bool receivesShadows,
1731 bool receivesReflections,
1732 const QVector2D *shadowDepthAdjust,
1733 QRhiTexture *lightmapTexture)
1735 QSSGShaderMaterialAdapter *materialAdapter = getMaterialAdapter(inMaterial);
1736 QSSGRhiShaderPipeline::CommonUniformIndices &cui = shaders.commonUniformIndices;
1738 materialAdapter->setCustomPropertyUniforms(ubufData, shaders, renderContext);
1740 const QVector2D camProperties(inCameras[0]->clipPlanes);
1741 shaders.setUniform(ubufData,
"qt_cameraProperties", &camProperties, 2 *
sizeof(
float), &cui.cameraPropertiesIdx);
1743 const int viewCount = inCameras.count();
1746 QMatrix4x4 camGlobalTransforms[2] { QMatrix4x4{Qt::Uninitialized}, QMatrix4x4{Qt::Uninitialized} };
1747 if (viewCount < 2) {
1748 camGlobalTransforms[0] = inRenderProperties.getGlobalTransform(*inCameras[0]);
1750 for (size_t viewIndex = 0; viewIndex != std::size(camGlobalTransforms); ++viewIndex)
1751 camGlobalTransforms[viewIndex] = inRenderProperties.getGlobalTransform(*inCameras[viewIndex]);
1754 if (viewCount < 2) {
1755 const QMatrix4x4 &camGlobalTransform = camGlobalTransforms[0];
1756 const QVector3D camGlobalPos = QSSGRenderNode::getGlobalPos(camGlobalTransform);
1757 shaders.setUniform(ubufData,
"qt_cameraPosition", &camGlobalPos, 3 *
sizeof(
float), &cui.cameraPositionIdx);
1758 const QVector3D camDirection = QSSG_GUARD(inRenderProperties.renderedCameraData.has_value())
1759 ? inRenderProperties.renderedCameraData.value()[0].direction
1760 : QVector3D{ 0.0f, 0.0f, -1.0f };
1761 shaders.setUniform(ubufData,
"qt_cameraDirection", &camDirection, 3 *
sizeof(
float), &cui.cameraDirectionIdx);
1763 QVarLengthArray<QVector3D, 2> camGlobalPos(viewCount);
1764 QVarLengthArray<QVector3D> camDirection(viewCount);
1765 for (size_t viewIndex = 0; viewIndex != std::size(camGlobalTransforms); ++viewIndex) {
1766 const QMatrix4x4 &camGlobalTransform = camGlobalTransforms[viewIndex];
1767 camGlobalPos[viewIndex] = QSSGRenderNode::getGlobalPos(camGlobalTransform);
1768 camDirection[viewIndex] = QSSG_GUARD(inRenderProperties.renderedCameraData.has_value())
1769 ? inRenderProperties.renderedCameraData.value()[viewIndex].direction
1770 : QVector3D{ 0.0f, 0.0f, -1.0f };
1772 shaders.setUniformArray(ubufData,
"qt_cameraPosition", camGlobalPos.constData(), viewCount, QSSGRenderShaderValue::Vec3, &cui.cameraPositionIdx);
1773 shaders.setUniformArray(ubufData,
"qt_cameraDirection", camDirection.constData(), viewCount, QSSGRenderShaderValue::Vec3, &cui.cameraDirectionIdx);
1776 const auto globalRenderData = QSSGLayerRenderData::globalRenderProperties(renderContext);
1779 bool usesProjectionMatrix =
false;
1780 bool usesInvProjectionMatrix =
false;
1781 bool usesViewProjectionMatrix =
false;
1782 bool usesModelViewProjectionMatrix =
false;
1783 bool usesNormalMatrix =
false;
1784 bool usesParentMatrix =
false;
1786 if (inMaterial.type == QSSGRenderGraphObject::Type::CustomMaterial) {
1787 const auto *customMaterial =
static_cast<
const QSSGRenderCustomMaterial *>(&inMaterial);
1788 usesProjectionMatrix = customMaterial->m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::ProjectionMatrix);
1789 usesInvProjectionMatrix = customMaterial->m_renderFlags.testFlag(QSSGRenderCustomMaterial::RenderFlag::InverseProjectionMatrix);
1791 usesViewProjectionMatrix =
true;
1794 const bool usesInstancing = inProperties.m_usesInstancing.getValue(inKey);
1795 if (usesInstancing) {
1797 usesViewProjectionMatrix =
true;
1798 usesParentMatrix =
true;
1800 usesModelViewProjectionMatrix =
true;
1801 usesNormalMatrix =
true;
1804 if (materialAdapter->isTransmissionEnabled())
1805 usesViewProjectionMatrix =
true;
1808 if (usesProjectionMatrix || usesInvProjectionMatrix) {
1809 if (viewCount < 2) {
1810 const QMatrix4x4 projection = clipSpaceCorrMatrix * inCameras[0]->projection;
1811 if (usesProjectionMatrix)
1812 shaders.setUniform(ubufData,
"qt_projectionMatrix", projection.constData(), 16 *
sizeof(
float), &cui.projectionMatrixIdx);
1813 if (usesInvProjectionMatrix)
1814 shaders.setUniform(ubufData,
"qt_inverseProjectionMatrix", projection.inverted().constData(), 16 *
sizeof (
float), &cui.inverseProjectionMatrixIdx);
1816 QVarLengthArray<QMatrix4x4, 2> projections(viewCount);
1817 QVarLengthArray<QMatrix4x4, 2> invertedProjections(viewCount);
1818 for (size_t viewIndex = 0; viewIndex != std::size(camGlobalTransforms); ++viewIndex) {
1819 projections[viewIndex] = clipSpaceCorrMatrix * inCameras[viewIndex]->projection;
1820 if (usesInvProjectionMatrix)
1821 invertedProjections[viewIndex] = projections[viewIndex].inverted();
1823 if (usesProjectionMatrix)
1824 shaders.setUniformArray(ubufData,
"qt_projectionMatrix", projections.constData(), viewCount, QSSGRenderShaderValue::Matrix4x4, &cui.projectionMatrixIdx);
1825 if (usesInvProjectionMatrix)
1826 shaders.setUniformArray(ubufData,
"qt_inverseProjectionMatrix", invertedProjections.constData(), viewCount, QSSGRenderShaderValue::Matrix4x4, &cui.inverseProjectionMatrixIdx);
1830 if (viewCount < 2) {
1831 const QMatrix4x4 viewMatrix = camGlobalTransforms[0].inverted();
1832 shaders.setUniform(ubufData,
"qt_viewMatrix", viewMatrix.constData(), 16 *
sizeof(
float), &cui.viewMatrixIdx);
1834 QVarLengthArray<QMatrix4x4, 2> viewMatrices(viewCount);
1835 for (size_t viewIndex = 0; viewIndex != std::size(camGlobalTransforms); ++viewIndex)
1836 viewMatrices[viewIndex] = camGlobalTransforms[viewIndex].inverted();
1837 shaders.setUniformArray(ubufData,
"qt_viewMatrix", viewMatrices.constData(), viewCount, QSSGRenderShaderValue::Matrix4x4, &cui.viewMatrixIdx);
1840 if (usesViewProjectionMatrix) {
1841 if (viewCount < 2) {
1842 const QMatrix4x4 &camGlobalTransform = camGlobalTransforms[0];
1843 QMatrix4x4 viewProj(Qt::Uninitialized);
1844 inCameras[0]->calculateViewProjectionMatrix(camGlobalTransform, viewProj);
1845 viewProj = clipSpaceCorrMatrix * viewProj;
1846 shaders.setUniform(ubufData,
"qt_viewProjectionMatrix", viewProj.constData(), 16 *
sizeof(
float), &cui.viewProjectionMatrixIdx);
1848 QVarLengthArray<QMatrix4x4, 2> viewProjections(viewCount);
1849 for (size_t viewIndex = 0; viewIndex != std::size(camGlobalTransforms); ++viewIndex) {
1850 const auto &camGlobalTransform = camGlobalTransforms[viewIndex];
1851 inCameras[viewIndex]->calculateViewProjectionMatrix(camGlobalTransform, viewProjections[viewIndex]);
1852 viewProjections[viewIndex] = clipSpaceCorrMatrix * viewProjections[viewIndex];
1854 shaders.setUniformArray(ubufData,
"qt_viewProjectionMatrix", viewProjections.constData(), viewCount, QSSGRenderShaderValue::Matrix4x4, &cui.viewProjectionMatrixIdx);
1860 shaders.setUniform(ubufData,
"qt_modelMatrix", localInstanceTransform.constData(), 16 *
sizeof(
float), &cui.modelMatrixIdx);
1862 shaders.setUniform(ubufData,
"qt_modelMatrix", inGlobalTransform.constData(), 16 *
sizeof(
float), &cui.modelMatrixIdx);
1864 if (usesModelViewProjectionMatrix) {
1865 if (viewCount < 2) {
1866 QMatrix4x4 mvp { clipSpaceCorrMatrix };
1867 mvp *= inModelViewProjections[0];
1868 shaders.setUniform(ubufData,
"qt_modelViewProjection", mvp.constData(), 16 *
sizeof(
float), &cui.modelViewProjectionIdx);
1870 QVarLengthArray<QMatrix4x4, 2> mvps(viewCount);
1871 for (
int viewIndex = 0; viewIndex < viewCount; ++viewIndex)
1872 mvps[viewIndex] = clipSpaceCorrMatrix * inModelViewProjections[viewIndex];
1873 shaders.setUniformArray(ubufData,
"qt_modelViewProjection", mvps.constData(), viewCount, QSSGRenderShaderValue::Matrix4x4, &cui.modelViewProjectionIdx);
1876 if (usesNormalMatrix)
1877 shaders.setUniform(ubufData,
"qt_normalMatrix", inNormalMatrix.constData(), 12 *
sizeof(
float), &cui.normalMatrixIdx,
1878 QSSGRhiShaderPipeline::UniformFlag::Mat3);
1879 if (usesParentMatrix)
1880 shaders.setUniform(ubufData,
"qt_parentMatrix", globalInstanceTransform.constData(), 16 *
sizeof(
float));
1883 const qsizetype morphSize = inProperties.m_targetCount.getValue(inKey);
1884 if (morphSize > 0) {
1885 if (inMorphWeights.mSize >= morphSize) {
1886 shaders.setUniformArray(ubufData,
"qt_morphWeights", inMorphWeights.mData, morphSize,
1887 QSSGRenderShaderValue::Float, &cui.morphWeightsIdx);
1889 const QList<
float> zeroWeights(morphSize - inMorphWeights.mSize, 0.0f);
1890 QList<
float> newWeights(inMorphWeights.mData, inMorphWeights.mData + inMorphWeights.mSize);
1891 newWeights.append(zeroWeights);
1892 shaders.setUniformArray(ubufData,
"qt_morphWeights", newWeights.constData(), morphSize,
1893 QSSGRenderShaderValue::Float, &cui.morphWeightsIdx);
1897 QVector3D theLightAmbientTotal;
1898 quint32 lightCount = 0;
1899 quint32 directionalLightCount = 0;
1900 quint32 shadowCount = 0;
1901 quint32 directionalShadowCount = 0;
1902 QSSGShaderLightsUniformData &lightsUniformData(shaders.lightsUniformData());
1903 QSSGShaderDirectionalLightsUniformData &directionalLightsUniformData(shaders.directionalLightsUniformData());
1905 for (quint32 lightIdx = 0, lightEnd = inLights.size();
1906 lightIdx < lightEnd && lightIdx < QSSG_MAX_NUM_LIGHTS; ++lightIdx)
1908 QSSGRenderLight *theLight(inLights[lightIdx].light);
1911 const bool lightShadows = inLights[lightIdx].shadows;
1912 const float brightness = theLight->m_brightness;
1913 quint32 lightmapState = 0;
1914 if (theLight->m_bakingEnabled) {
1915 if (theLight->m_fullyBaked) {
1924 const QVector3D diffuseColor(theLight->m_diffuseColor.x() * brightness,
1925 theLight->m_diffuseColor.y() * brightness,
1926 theLight->m_diffuseColor.z() * brightness);
1927 const QVector3D specularColor(theLight->m_specularColor.x() * brightness,
1928 theLight->m_specularColor.y() * brightness,
1929 theLight->m_specularColor.z() * brightness);
1930 const QVector3D direction(inLights[lightIdx].direction);
1933 if (theLight->type == QSSGRenderGraphObject::Type::DirectionalLight) {
1935 QSSGShaderDirectionalLightData &lightData(directionalLightsUniformData.directionalLightData[directionalLightCount]);
1936 lightData.direction[0] = direction.x();
1937 lightData.direction[1] = direction.y();
1938 lightData.direction[2] = direction.z();
1939 lightData.diffuseColor[0] = diffuseColor.x();
1940 lightData.diffuseColor[1] = diffuseColor.y();
1941 lightData.diffuseColor[2] = diffuseColor.z();
1942 lightData.specularColor[0] = specularColor.x();
1943 lightData.specularColor[1] = specularColor.y();
1944 lightData.specularColor[2] = specularColor.z();
1945 lightData.lightmapState = lightmapState;
1946 if (lightShadows && receivesShadows) {
1947 lightData.enableShadows = 1.0f;
1948 QSSGShadowMapEntry *pEntry = inRenderProperties.getShadowMapManager()->shadowMapEntry(lightIdx);
1951 const quint32 layerCount = pEntry->m_csmNumSplits + 1;
1953 for (quint32 i = 0; i < layerCount; ++i)
1954 memcpy(lightData.matrices[i], pEntry->m_fixedScaleBiasMatrix[i].constData(), 16 *
sizeof(
float));
1956 lightData.shadowBias = theLight->m_shadowBias;
1958 const bool noCascades = !(pEntry->m_csmActive[0] || pEntry->m_csmActive[1] || pEntry->m_csmActive[2] || pEntry->m_csmActive[3]);
1959 if (theLight->type == QSSGRenderLight::Type::DirectionalLight && noCascades)
1960 lightData.enableShadows = 0.0f;
1961 lightData.shadowFactor = theLight->m_shadowFactor;
1962 lightData.shadowMapFar = theLight->m_shadowMapFar;
1963 lightData.shadowPcfSamples = softShadowQualityToInt(theLight->m_softShadowQuality);
1964 lightData.shadowPcfFactor = theLight->m_pcfFactor;
1966 for (quint32 i = 0; i < layerCount; ++i) {
1967 const auto &atlasInfo = pEntry->m_atlasInfo[i];
1968 lightData.atlasLocations[i][0] = atlasInfo.uOffset;
1969 lightData.atlasLocations[i][1] = atlasInfo.vOffset;
1970 lightData.atlasLocations[i][2] = atlasInfo.uvScale;
1971 lightData.atlasLocations[i][3] = atlasInfo.layerIndex;
1974 lightData.csmNumSplits = pEntry->m_csmNumSplits;
1975 memcpy(lightData.csmSplits, pEntry->m_csmSplits, 4 *
sizeof(
float));
1976 memcpy(lightData.csmActive, pEntry->m_csmActive, 4 *
sizeof(
float));
1977 lightData.csmBlendRatio = theLight->m_csmBlendRatio;
1978 for (quint32 i = 0; i < layerCount; ++i)
1979 memcpy(lightData.dimensionsInverted[i], &pEntry->m_dimensionsInverted[i], 4 *
sizeof(
float));
1981 directionalShadowCount++;
1983 lightData.enableShadows = 0.0f;
1985 directionalLightCount++;
1988 QSSGShaderLightData &lightData(lightsUniformData.lightData[lightCount]);
1989 const auto gt = inRenderProperties.getGlobalTransform(*theLight);
1990 const QVector3D globalPos = QSSGRenderNode::getGlobalPos(gt);
1991 lightData.position[0] = globalPos.x();
1992 lightData.position[1] = globalPos.y();
1993 lightData.position[2] = globalPos.z();
1994 lightData.constantAttenuation = QSSGUtils::aux::translateConstantAttenuation(theLight->m_constantFade);
1995 lightData.linearAttenuation = QSSGUtils::aux::translateLinearAttenuation(theLight->m_linearFade);
1996 lightData.quadraticAttenuation = QSSGUtils::aux::translateQuadraticAttenuation(theLight->m_quadraticFade);
1997 lightData.coneAngle = 360.0f;
1998 lightData.direction[0] = direction.x();
1999 lightData.direction[1] = direction.y();
2000 lightData.direction[2] = direction.z();
2001 lightData.diffuseColor[0] = diffuseColor.x();
2002 lightData.diffuseColor[1] = diffuseColor.y();
2003 lightData.diffuseColor[2] = diffuseColor.z();
2004 lightData.specularColor[0] = specularColor.x();
2005 lightData.specularColor[1] = specularColor.y();
2006 lightData.specularColor[2] = specularColor.z();
2007 lightData.lightmapState = lightmapState;
2008 if (theLight->type == QSSGRenderLight::Type::SpotLight) {
2012 const float coneAngle = theLight->m_coneAngle;
2013 const float innerConeAngle = (theLight->m_innerConeAngle > coneAngle) ? coneAngle : theLight->m_innerConeAngle;
2014 lightData.coneAngle = qCos(qDegreesToRadians(coneAngle));
2015 lightData.innerConeAngle = qCos(qDegreesToRadians(innerConeAngle));
2018 if (lightShadows && receivesShadows) {
2019 QSSGShadowMapEntry *pEntry = inRenderProperties.getShadowMapManager()->shadowMapEntry(lightIdx);
2021 lightData.enableShadows = 1.0f;
2022 lightData.shadowPcfFactor = theLight->m_pcfFactor;
2023 lightData.shadowPcfSamples = softShadowQualityToInt(theLight->m_softShadowQuality);
2024 lightData.shadowFactor = theLight->m_shadowFactor;
2025 lightData.shadowBias = theLight->m_shadowBias;
2026 lightData.shadowClipNear = 1.0f;
2027 lightData.shadowMapFar = pEntry->m_shadowMapFar;
2028 lightData.shadowTextureSize = pEntry->m_atlasInfo[0].uvScale;
2030 if (theLight->type == QSSGRenderLight::Type::SpotLight) {
2032 static const QMatrix4x4 bias = {
2036 0.0, 0.0, 0.0, 1.0 };
2037 const QMatrix4x4 m = bias * pEntry->m_lightViewProjection[0];
2038 memcpy(lightData.shadowMatrix, m.constData(), 16 *
sizeof(
float));
2039 lightData.shadowAtlasUV0[0] = pEntry->m_atlasInfo[0].uOffset;
2040 lightData.shadowAtlasUV0[1] = pEntry->m_atlasInfo[0].vOffset;
2041 lightData.shadowAtlasLayer0 = pEntry->m_atlasInfo[0].layerIndex;
2044 Q_ASSERT(theLight->type == QSSGRenderLight::Type::PointLight);
2045 memcpy(lightData.shadowMatrix, pEntry->m_lightView.constData(), 16 *
sizeof(
float));
2046 lightData.shadowAtlasUV0[0] = pEntry->m_atlasInfo[0].uOffset;
2047 lightData.shadowAtlasUV0[1] = pEntry->m_atlasInfo[0].vOffset;
2048 lightData.shadowAtlasLayer0 = pEntry->m_atlasInfo[0].layerIndex;
2049 lightData.shadowAtlasUV1[0] = pEntry->m_atlasInfo[1].uOffset;
2050 lightData.shadowAtlasUV1[1] = pEntry->m_atlasInfo[1].vOffset;
2051 lightData.shadowAtlasLayer1 = pEntry->m_atlasInfo[1].layerIndex;
2056 lightData.enableShadows = 0.0f;
2062 theLightAmbientTotal += theLight->m_ambientColor;
2066 if (shadowCount > 0 || directionalShadowCount > 0)
2067 shaders.setShadowMapAtlasTexture(inRenderProperties.getShadowMapManager()->shadowMapAtlasTexture());
2069 shaders.setShadowMapAtlasTexture(
nullptr);
2071 const QSSGRhiRenderableTexture *depthTexture = inRenderProperties.getRenderResult(QSSGFrameData::RenderResult::DepthTexture);
2072 const QSSGRhiRenderableTexture *normalTexture = inRenderProperties.getRenderResult(QSSGFrameData::RenderResult::NormalTexture);
2073 const QSSGRhiRenderableTexture *ssaoTexture = inRenderProperties.getRenderResult(QSSGFrameData::RenderResult::AoTexture);
2074 const QSSGRhiRenderableTexture *screenTexture = inRenderProperties.getRenderResult(QSSGFrameData::RenderResult::ScreenTexture);
2076 shaders.setDepthTexture(depthTexture->texture);
2077 shaders.setNormalTexture(normalTexture->texture);
2078 shaders.setSsaoTexture(ssaoTexture->texture);
2079 shaders.setScreenTexture(screenTexture->texture);
2080 shaders.setLightmapTexture(lightmapTexture);
2082 const QSSGRenderLayer &layer = QSSGLayerRenderData::getCurrent(*renderContext.renderer())->layer;
2083 QSSGRenderImage *theLightProbe = layer.lightProbe;
2084 const auto &lightProbeData = layer.lightProbeSettings;
2087 QSSGRenderImage *materialIblProbe = materialAdapter->iblProbe();
2088 if (materialIblProbe)
2089 theLightProbe = materialIblProbe;
2090 QSSGRenderImageTexture lightProbeTexture;
2092 lightProbeTexture = renderContext.bufferManager()->loadRenderImage(theLightProbe, QSSGBufferManager::MipModeBsdf);
2093 if (theLightProbe && lightProbeTexture.m_texture) {
2094 QSSGRenderTextureCoordOp theHorzLightProbeTilingMode = theLightProbe->m_horizontalTilingMode;
2095 QSSGRenderTextureCoordOp theVertLightProbeTilingMode = theLightProbe->m_verticalTilingMode;
2096 const int maxMipLevel = lightProbeTexture.m_mipmapCount - 1;
2098 if (!materialIblProbe && !lightProbeData.probeOrientation.isIdentity()) {
2099 shaders.setUniform(ubufData,
"qt_lightProbeOrientation",
2100 lightProbeData.probeOrientation.constData(),
2101 12 *
sizeof(
float), &cui.lightProbeOrientationIdx,
2102 QSSGRhiShaderPipeline::UniformFlag::Mat3);
2105 const float props[4] = { 0.0f,
float(maxMipLevel), lightProbeData.probeHorizon, lightProbeData.probeExposure };
2106 shaders.setUniform(ubufData,
"qt_lightProbeProperties", props, 4 *
sizeof(
float), &cui.lightProbePropertiesIdx);
2108 shaders.setLightProbeTexture(lightProbeTexture.m_texture, theHorzLightProbeTilingMode, theVertLightProbeTilingMode);
2111 const float emptyProps[4] = { 0.0f, 0.0f, -1.0f, 0.0f };
2112 shaders.setUniform(ubufData,
"qt_lightProbeProperties", emptyProps, 4 *
sizeof(
float), &cui.lightProbePropertiesIdx);
2114 shaders.setLightProbeTexture(
nullptr);
2117 if (receivesReflections && reflectionProbe.enabled) {
2118 shaders.setUniform(ubufData,
"qt_reflectionProbeCubeMapCenter", &reflectionProbe.probeCubeMapCenter, 3 *
sizeof(
float), &cui.reflectionProbeCubeMapCenter);
2119 shaders.setUniform(ubufData,
"qt_reflectionProbeBoxMin", &reflectionProbe.probeBoxMin, 3 *
sizeof(
float), &cui.reflectionProbeBoxMin);
2120 shaders.setUniform(ubufData,
"qt_reflectionProbeBoxMax", &reflectionProbe.probeBoxMax, 3 *
sizeof(
float), &cui.reflectionProbeBoxMax);
2121 shaders.setUniform(ubufData,
"qt_reflectionProbeCorrection", &reflectionProbe.parallaxCorrection,
sizeof(
int), &cui.reflectionProbeCorrection);
2124 const QVector3D emissiveColor = materialAdapter->emissiveColor();
2125 shaders.setUniform(ubufData,
"qt_material_emissive_color", &emissiveColor, 3 *
sizeof(
float), &cui.material_emissiveColorIdx);
2127 const auto qMix = [](
float x,
float y,
float a) {
2128 return (x * (1.0f - a) + (y * a));
2131 const auto qMix3 = [&qMix](
const QVector3D &x,
const QVector3D &y,
float a) {
2132 return QVector3D{qMix(x.x(), y.x(), a), qMix(x.y(), y.y(), a), qMix(x.z(), y.z(), a)};
2135 const QVector4D color = materialAdapter->color();
2136 const QVector3D materialSpecularTint = materialAdapter->specularTint();
2137 const QVector3D specularTint = materialAdapter->isPrincipled() ? qMix3(QVector3D(1.0f, 1.0f, 1.0f), color.toVector3D(), materialSpecularTint.x())
2138 : materialSpecularTint;
2139 shaders.setUniform(ubufData,
"qt_material_base_color", &color, 4 *
sizeof(
float), &cui.material_baseColorIdx);
2141 const float ior = materialAdapter->ior();
2142 QVector4D specularColor(specularTint, ior);
2143 shaders.setUniform(ubufData,
"qt_material_specular", &specularColor, 4 *
sizeof(
float), &cui.material_specularIdx);
2145 const bool hasLighting = materialAdapter->hasLighting();
2146 shaders.setLightsEnabled(hasLighting);
2148 const float lightAndShadowCounts[4] = {
2150 float(directionalLightCount),
2152 float(directionalShadowCount)
2154 shaders.setUniform(ubufData,
"qt_lightAndShadowCounts", &lightAndShadowCounts, 4 *
sizeof(
float), &cui.lightAndShadowCountsIdx);
2156 const size_t lightDataSize = lightCount *
sizeof(QSSGShaderLightData);
2157 const size_t directionalLightDataSize = directionalLightCount *
sizeof(QSSGShaderDirectionalLightData);
2159 memcpy(ubufData + shaders.ub0LightDataOffset(), &lightsUniformData, lightDataSize);
2160 memcpy(ubufData + shaders.ub0DirectionalLightDataOffset(), &directionalLightsUniformData, directionalLightDataSize);
2163 shaders.setUniform(ubufData,
"qt_light_ambient_total", &theLightAmbientTotal, 3 *
sizeof(
float), &cui.light_ambient_totalIdx);
2165 const float materialProperties[4] = {
2166 materialAdapter->specularAmount(),
2167 materialAdapter->specularRoughness(),
2168 materialAdapter->metalnessAmount(),
2171 shaders.setUniform(ubufData,
"qt_material_properties", materialProperties, 4 *
sizeof(
float), &cui.material_propertiesIdx);
2173 const float materialProperties2[4] = {
2174 materialAdapter->fresnelPower(),
2175 materialAdapter->bumpAmount(),
2176 materialAdapter->translucentFallOff(),
2177 materialAdapter->diffuseLightWrap()
2179 shaders.setUniform(ubufData,
"qt_material_properties2", materialProperties2, 4 *
sizeof(
float), &cui.material_properties2Idx);
2181 const float materialProperties3[4] = {
2182 materialAdapter->occlusionAmount(),
2183 materialAdapter->alphaCutOff(),
2184 materialAdapter->clearcoatAmount(),
2185 materialAdapter->clearcoatRoughnessAmount()
2187 shaders.setUniform(ubufData,
"qt_material_properties3", materialProperties3, 4 *
sizeof(
float), &cui.material_properties3Idx);
2189 const float materialProperties4[4] = {
2190 materialAdapter->heightAmount(),
2191 materialAdapter->minHeightSamples(),
2192 materialAdapter->maxHeightSamples(),
2193 materialAdapter->transmissionFactor()
2195 shaders.setUniform(ubufData,
"qt_material_properties4", materialProperties4, 4 *
sizeof(
float), &cui.material_properties4Idx);
2197 const bool hasCustomFrag = materialAdapter->hasCustomShaderSnippet(QSSGShaderCache::ShaderType::Fragment);
2198 if (!hasCustomFrag) {
2199 if (inProperties.m_fresnelScaleBiasEnabled.getValue(inKey) || inProperties.m_clearcoatFresnelScaleBiasEnabled.getValue(inKey)) {
2200 const float materialProperties5[4] = {
2201 materialAdapter->fresnelScale(),
2202 materialAdapter->fresnelBias(),
2203 materialAdapter->clearcoatFresnelScale(),
2204 materialAdapter->clearcoatFresnelBias()
2206 shaders.setUniform(ubufData,
"qt_material_properties5", materialProperties5, 4 *
sizeof(
float), &cui.material_properties5Idx);
2209 const float material_clearcoat_normal_strength = materialAdapter->clearcoatNormalStrength();
2210 shaders.setUniform(ubufData,
"qt_material_clearcoat_normal_strength", &material_clearcoat_normal_strength,
sizeof(
float), &cui.clearcoatNormalStrengthIdx);
2212 const float material_clearcoat_fresnel_power = materialAdapter->clearcoatFresnelPower();
2213 shaders.setUniform(ubufData,
"qt_material_clearcoat_fresnel_power", &material_clearcoat_fresnel_power,
sizeof(
float), &cui.clearcoatFresnelPowerIdx);
2215 if (materialAdapter->isTransmissionEnabled()) {
2216 const QVector4D attenuationProperties(materialAdapter->attenuationColor(), materialAdapter->attenuationDistance());
2217 shaders.setUniform(ubufData,
"qt_material_attenuation", &attenuationProperties, 4 *
sizeof(
float), &cui.material_attenuationIdx);
2219 const float thickness = materialAdapter->thicknessFactor();
2220 shaders.setUniform(ubufData,
"qt_material_thickness", &thickness,
sizeof(
float), &cui.thicknessFactorIdx);
2224 const float rhiProperties[4] = {
2225 globalRenderData.isYUpInFramebuffer ? 1.0f : -1.0f,
2226 globalRenderData.isYUpInNDC ? 1.0f : -1.0f,
2227 globalRenderData.isClipDepthZeroToOne ? 0.0f : -1.0f,
2230 shaders.setUniform(ubufData,
"qt_rhi_properties", rhiProperties, 4 *
sizeof(
float), &cui.rhiPropertiesIdx);
2232 qsizetype imageIdx = 0;
2233 for (QSSGRenderableImage *theImage = inFirstImage; theImage; theImage = theImage->m_nextImage, ++imageIdx) {
2235 const auto &names = imageStringTable[
int(theImage->m_mapType)];
2236 if (imageIdx == cui.imageIndices.size())
2237 cui.imageIndices.append(QSSGRhiShaderPipeline::CommonUniformIndices::ImageIndices());
2238 auto &indices = cui.imageIndices[imageIdx];
2240 const QMatrix4x4 &textureTransform = theImage->m_imageNode.m_textureTransform;
2243 const float *dataPtr(textureTransform.constData());
2247 const float offsets[3] = { dataPtr[12], dataPtr[13], 0.0f };
2248 shaders.setUniform(ubufData, names.imageOffsets, offsets,
sizeof(offsets), &indices.imageOffsetsUniformIndex);
2250 const float rotations[4] = { dataPtr[0], dataPtr[4], dataPtr[1], dataPtr[5] };
2251 shaders.setUniform(ubufData, names.imageRotations, rotations,
sizeof(rotations), &indices.imageRotationsUniformIndex);
2254 if (shadowDepthAdjust)
2255 shaders.setUniform(ubufData,
"qt_shadowDepthAdjust", shadowDepthAdjust, 2 *
sizeof(
float), &cui.shadowDepthAdjustIdx);
2257 const bool usesPointsTopology = inProperties.m_usesPointsTopology.getValue(inKey);
2258 if (usesPointsTopology) {
2259 const float pointSize = materialAdapter->pointSize();
2260 shaders.setUniform(ubufData,
"qt_materialPointSize", &pointSize,
sizeof(
float), &cui.pointSizeIdx);
2267 if (inRenderProperties.layer.fog.enabled) {
2268 const float fogColor[4] = {
2269 inRenderProperties.layer.fog.color.x(),
2270 inRenderProperties.layer.fog.color.y(),
2271 inRenderProperties.layer.fog.color.z(),
2272 inRenderProperties.layer.fog.density
2274 shaders.setUniform(ubufData,
"qt_fogColor", fogColor, 4 *
sizeof(
float), &cui.fogColorIdx);
2275 const float fogDepthProperties[4] = {
2276 inRenderProperties.layer.fog.depthBegin,
2277 inRenderProperties.layer.fog.depthEnd,
2278 inRenderProperties.layer.fog.depthCurve,
2279 inRenderProperties.layer.fog.depthEnabled ? 1.0f : 0.0f
2281 shaders.setUniform(ubufData,
"qt_fogDepthProperties", fogDepthProperties, 4 *
sizeof(
float), &cui.fogDepthPropertiesIdx);
2282 const float fogHeightProperties[4] = {
2283 inRenderProperties.layer.fog.heightMin,
2284 inRenderProperties.layer.fog.heightMax,
2285 inRenderProperties.layer.fog.heightCurve,
2286 inRenderProperties.layer.fog.heightEnabled ? 1.0f : 0.0f
2288 shaders.setUniform(ubufData,
"qt_fogHeightProperties", fogHeightProperties, 4 *
sizeof(
float), &cui.fogHeightPropertiesIdx);
2289 const float fogTransmitProperties[4] = {
2290 inRenderProperties.layer.fog.transmitCurve,
2293 inRenderProperties.layer.fog.transmitEnabled ? 1.0f : 0.0f
2295 shaders.setUniform(ubufData,
"qt_fogTransmitProperties", fogTransmitProperties, 4 *
sizeof(
float), &cui.fogTransmitPropertiesIdx);
2298 inPipelineState->lineWidth = materialAdapter->lineWidth();