Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qssgshadermaterialadapter.cpp
Go to the documentation of this file.
1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2019 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5/* clang-format off */
6
7#include <QtQuick3DRuntimeRender/private/qssgshadermaterialadapter_p.h>
9#include <QtQuick3DRuntimeRender/private/qssgrhicustommaterialsystem_p.h>
10
12
14
16{
17 switch (materialNode.type) {
18 case QSSGRenderGraphObject::Type::DefaultMaterial:
19 case QSSGRenderGraphObject::Type::PrincipledMaterial:
20 case QSSGRenderGraphObject::Type::SpecularGlossyMaterial:
21 return new QSSGShaderDefaultMaterialAdapter(static_cast<const QSSGRenderDefaultMaterial &>(materialNode));
22
23 case QSSGRenderGraphObject::Type::CustomMaterial:
24 return new QSSGShaderCustomMaterialAdapter(static_cast<const QSSGRenderCustomMaterial &>(materialNode));
25
26 default:
27 break;
28 }
29
30 return nullptr;
31}
32
34{
35 return false;
36}
37
42
49
56
62
64{
65 return false;
66}
67
68
69
74
76{
77 return m_material.type == QSSGRenderGraphObject::Type::PrincipledMaterial;
78}
79
81{
82 return m_material.type == QSSGRenderGraphObject::Type::SpecularGlossyMaterial;
83}
84
89
94
99
104
109
114
119
124
129
134
136{
137 return m_material.hasLighting();
138}
139
144
149
154
159
160QSSGRenderDefaultMaterial::VertexColorMaskFlags QSSGShaderDefaultMaterialAdapter::vertexColorRedMask()
161{
162 return m_material.vertexColorRedMask;
163}
164
165QSSGRenderDefaultMaterial::VertexColorMaskFlags QSSGShaderDefaultMaterialAdapter::vertexColorGreenMask()
166{
167 return m_material.vertexColorGreenMask;
168}
169
170QSSGRenderDefaultMaterial::VertexColorMaskFlags QSSGShaderDefaultMaterialAdapter::vertexColorBlueMask()
171{
172 return m_material.vertexColorBlueMask;
173}
174
175QSSGRenderDefaultMaterial::VertexColorMaskFlags QSSGShaderDefaultMaterialAdapter::vertexColorAlphaMask()
176{
177 return m_material.vertexColorAlphaMask;
178}
179
184
189
191{
192 return m_material.color;
193}
194
199
201{
202 return m_material.ior;
203}
204
209
211{
212 return m_material.fresnelScale;
213}
214
216{
217 return m_material.fresnelBias;
218}
219
221{
222 return m_material.fresnelPower;
223}
224
229
234
239
244
249
254
259
261{
262 return m_material.bumpAmount;
263}
264
269
274
279
281{
282 return m_material.alphaCutoff;
283}
284
286{
287 return m_material.pointSize;
288}
289
291{
292 return m_material.lineWidth;
293}
294
296{
297 return m_material.heightAmount;
298}
299
304
309
314
319
324
329
334
339
344
349
350// Act like Principled. Lighting is always on, specular, metalness, etc. support should all be enabled.
351// Unlike Principled, the *enabled values do not depend on the metalness or specularAmount values
352// (we cannot tell what those are if they are written in the shader).
353
355{
356 return true;
357}
358
360{
361 return false;
362}
363
368
373
378
383
388
393
398
403
405{
406 // TODO: Expose Clearcoat properties to custom material
407 return false;
408}
409
411{
412 // TODO: Expose Transmission to custom material
413 return false;
414}
415
417{
418 return true;
419}
420
425
430
435
440
441QSSGRenderDefaultMaterial::VertexColorMaskFlags QSSGShaderCustomMaterialAdapter::vertexColorRedMask()
442{
444}
445
446QSSGRenderDefaultMaterial::VertexColorMaskFlags QSSGShaderCustomMaterialAdapter::vertexColorGreenMask()
447{
449}
450
451QSSGRenderDefaultMaterial::VertexColorMaskFlags QSSGShaderCustomMaterialAdapter::vertexColorBlueMask()
452{
454}
455
456QSSGRenderDefaultMaterial::VertexColorMaskFlags QSSGShaderCustomMaterialAdapter::vertexColorAlphaMask()
457{
459}
460
465
466// The following are the values that get set into uniforms such as
467// qt_material_properties etc. When a custom shader is present, these values
468// are not used at all. However, a CustomMaterial is also valid without a
469// vertex/fragment shader, or with no custom shaders at all. Therefore the
470// values here must match the defaults of PrincipledMaterial, in order to make
471// PrincipledMaterial { } and CustomMaterial { } identical.
472
477
482
487
489{
490 return 1.45f;
491}
492
497
499{
500 return 1.0f;
501}
502
504{
505 return 0.0f;
506}
507
509{
510 return 0.0f;
511}
512
517
522
527
532
534{
535 return 0.0f;
536}
537
539{
540 return 0.5f;
541}
542
544{
545 return 0.0f;
546}
547
549{
550 return 0.0f;
551}
552
557
559{
560 return 0.0f;
561}
562
564{
565 return 1.0f;
566}
567
569{
570 return 0.5f;
571}
572
574{
575 return 1.0f;
576}
577
579{
580 return m_material.m_lineWidth;
581}
582
584{
585 return 0.0f;
586}
587
589{
590 return 0.0f;
591}
592
594{
595 return 0.0f;
596}
597
599{
600 return 0.0f;
601}
602
607
612
617
619{
620 return 0.0f;
621}
622
624{
625 return std::numeric_limits<float>::infinity();
626}
627
629{
630 return { 1.0f, 1.0f, 1.0f };
631}
632
637
645
647 QSSGShaderLibraryManager &shaderLibraryManager,
648 bool multiViewCompatible)
649{
651 const QByteArray shaderPathKey = m_material.m_shaderPathKey[multiViewCompatible ? QSSGRenderCustomMaterial::MultiViewShaderPathKeyIndex
653 return shaderLibraryManager.getShaderSource(shaderPathKey, type);
654 }
655
656 return QByteArray();
657}
658
660 const QByteArray &funcName,
661 QSSGShaderLibraryManager &shaderLibraryManager)
662{
663 if (hasCustomShaderSnippet(shaderType))
665 shaderType).customFunctions.contains(funcName);
666
667 return false;
668}
669
671 QSSGRhiShaderPipeline &shaderPipeline,
673{
674 context.customMaterialSystem()->applyRhiShaderPropertyValues(ubufData, m_material, shaderPipeline);
675}
676
681
682namespace {
683
684// Custom material shader substitution table.
685// Must be in sync with the shader generator.
686static const QSSGCustomMaterialVariableSubstitution qssg_var_subst_tab[] = {
687 // uniform (block members)
688 { "MODELVIEWPROJECTION_MATRIX", "qt_modelViewProjection", true },
689 { "VIEWPROJECTION_MATRIX", "qt_viewProjectionMatrix", true },
690 { "MODEL_MATRIX", "qt_modelMatrix", false },
691 { "VIEW_MATRIX", "qt_viewMatrix", true },
692 { "NORMAL_MATRIX", "qt_normalMatrix", false },
693 { "BONE_TRANSFORMS", "qt_getTexMatrix", false },
694 { "BONE_NORMAL_TRANSFORMS", "qt_getTexMatrix", false },
695 { "PROJECTION_MATRIX", "qt_projectionMatrix", true },
696 { "INVERSE_PROJECTION_MATRIX", "qt_inverseProjectionMatrix", true },
697 { "CAMERA_POSITION", "qt_cameraPosition", true },
698 { "CAMERA_DIRECTION", "qt_cameraDirection", true },
699 { "CAMERA_PROPERTIES", "qt_cameraProperties", false },
700 { "FRAMEBUFFER_Y_UP", "qt_rhi_properties.x", false },
701 { "NDC_Y_UP", "qt_rhi_properties.y", false },
702 { "NEAR_CLIP_VALUE", "qt_rhi_properties.z", false },
703 { "IBL_MAXMIPMAP", "qt_lightProbeProperties.y", false },
704 { "IBL_HORIZON", "qt_lightProbeProperties.z", false },
705 { "IBL_EXPOSE", "qt_lightProbeProperties.w", false },
706
707 // outputs
708 { "POSITION", "gl_Position", false },
709 { "FRAGCOLOR", "fragOutput", false },
710 { "POINT_SIZE", "gl_PointSize", false },
711
712 // fragment inputs
713 { "FRAGCOORD", "gl_FragCoord", false },
714
715 // functions
716 { "DIRECTIONAL_LIGHT", "qt_directionalLightProcessor", false },
717 { "POINT_LIGHT", "qt_pointLightProcessor", false },
718 { "SPOT_LIGHT", "qt_spotLightProcessor", false },
719 { "AMBIENT_LIGHT", "qt_ambientLightProcessor", false },
720 { "SPECULAR_LIGHT", "qt_specularLightProcessor", false },
721 { "MAIN", "qt_customMain", false },
722 { "POST_PROCESS", "qt_customPostProcessor", false },
723 { "IBL_PROBE", "qt_iblProbeProcessor", false },
724
725 // textures
726 { "SCREEN_TEXTURE", "qt_screenTexture", true },
727 { "SCREEN_MIP_TEXTURE", "qt_screenTexture", true }, // same resource as SCREEN_TEXTURE under the hood
728 { "DEPTH_TEXTURE", "qt_depthTexture", true },
729 { "AO_TEXTURE", "qt_aoTexture", true },
730 { "IBL_TEXTURE", "qt_lightProbe", false },
731 { "LIGHTMAP", "qt_lightmap", false },
732
733 // For shaded only: vertex outputs, for convenience and perf. (only those
734 // that are always present when lighting is enabled) The custom vertex main
735 // can also calculate on its own and pass them on with VARYING but that's a
736 // bit wasteful since we calculate these anyways.
737 { "VAR_WORLD_NORMAL", "qt_varNormal", false },
738 { "VAR_WORLD_TANGENT", "qt_varTangent", false },
739 { "VAR_WORLD_BINORMAL", "qt_varBinormal", false },
740 { "VAR_WORLD_POSITION", "qt_varWorldPos", false },
741 // vertex color is always enabled for custom materials (shaded)
742 { "VAR_COLOR", "qt_varColor", false },
743
744 // effects
745 { "INPUT", "qt_inputTexture", true },
746 { "INPUT_UV", "qt_inputUV", false },
747 { "TEXTURE_UV", "qt_textureUV", false },
748 { "INPUT_SIZE", "qt_inputSize", false },
749 { "OUTPUT_SIZE", "qt_outputSize", false },
750 { "FRAME", "qt_frame_num", false },
751
752 // instancing
753 { "INSTANCE_COLOR", "qt_instanceColor", false },
754 { "INSTANCE_DATA", "qt_instanceData", false },
755 { "INSTANCE_INDEX", "gl_InstanceIndex", false },
756
757 // morphing
758 { "MORPH_POSITION", "qt_getTargetPositionFromTargetId", false },
759 { "MORPH_NORMAL", "qt_getTargetNormalFromTargetId", false },
760 { "MORPH_TANGENT", "qt_getTargetTangentFromTargetId", false },
761 { "MORPH_BINORMAL", "qt_getTargetBinormalFromTargetId", false },
762 { "MORPH_WEIGHTS", "qt_morphWeights", false },
763
764 // custom variables
765 { "SHARED_VARS", "struct QT_SHARED_VARS", false },
766
767 // multiview
768 { "VIEW_INDEX", "qt_viewIndex", false }
769};
770
771// Functions that, if present, get an argument list injected.
772static const QByteArrayView qssg_func_injectarg_tab[] = {
773 "DIRECTIONAL_LIGHT",
774 "POINT_LIGHT",
775 "SPOT_LIGHT",
776 "AMBIENT_LIGHT",
777 "SPECULAR_LIGHT",
778 "MAIN",
779 "POST_PROCESS",
780 "IBL_PROBE"
781};
782
783// This is based on the Qt Quick shader rewriter (with fixes)
784struct Tokenizer {
785 enum Token {
786 Token_Comment,
787 Token_OpenBrace,
788 Token_CloseBrace,
789 Token_OpenParen,
790 Token_CloseParen,
791 Token_SemiColon,
792 Token_Identifier,
793 Token_OpenBraket,
794 Token_CloseBraket,
795 Token_Unspecified,
796
797 Token_EOF
798 };
799
800 void initialize(const QByteArray &input);
801 Token next();
802
803 const char *stream;
804 const char *pos;
805 const char *identifier;
806};
807
808void Tokenizer::initialize(const QByteArray &input)
809{
810 stream = input.constData();
811 pos = input;
812 identifier = input;
813}
814
815Tokenizer::Token Tokenizer::next()
816{
817 while (*pos) {
818 char c = *pos++;
819 switch (c) {
820 case '/':
821 if (*pos == '/') {
822 // '//' comment
823 ++pos;
824 while (*pos && *pos != '\n') ++pos;
825 return Token_Comment;
826 } else if (*pos == '*') {
827 // /* */ comment
828 ++pos;
829 while (*pos && (*pos != '*' || pos[1] != '/')) ++pos;
830 if (*pos) pos += 2;
831 return Token_Comment;
832 }
833 return Token_Unspecified;
834
835 case ';': return Token_SemiColon;
836 case '\0': return Token_EOF;
837 case '{': return Token_OpenBrace;
838 case '}': return Token_CloseBrace;
839 case '(': return Token_OpenParen;
840 case ')': return Token_CloseParen;
841 case '[': return Token_OpenBraket;
842 case ']': return Token_CloseBraket;
843
844 case ' ':
845 case '\n':
846 case '\r': break;
847 default:
848 // Identifier...
849 if ((c >= 'a' && c <= 'z' ) || (c >= 'A' && c <= 'Z' ) || c == '_') {
850 identifier = pos - 1;
851 while (*pos && ((*pos >= 'a' && *pos <= 'z')
852 || (*pos >= 'A' && *pos <= 'Z')
853 || *pos == '_'
854 || (*pos >= '0' && *pos <= '9'))) {
855 ++pos;
856 }
857 return Token_Identifier;
858 } else {
859 return Token_Unspecified;
860 }
861 }
862 }
863
864 return Token_EOF;
865}
866} // namespace
867
870 const QByteArray &shaderCode,
872 const StringPairList &baseUniforms,
873 const StringPairList &baseInputs,
874 const StringPairList &baseOutputs,
875 bool multiViewCompatible)
876{
877 QByteArrayList inputs;
878 QByteArrayList outputs;
879
880 Tokenizer tok;
881 tok.initialize(shaderCode);
882
885 result.reserve(1024);
886 // If shader debugging is not enabled we reset the line count to make error message
887 // when a shader fails more useful. When shader debugging is enabled the whole shader
888 // will be printed and not just the user written part, so in that case we do not want
889 // to adjust the line numbers.
890 //
891 // NOTE: This is not perfect, we do expend the custom material and effect shaders, so
892 // there cane still be cases where the reported line numbers are slightly off.
894 result.prepend("#line 1\n");
895 const char *lastPos = shaderCode.constData();
896
897 int funcFinderState = 0;
898 int useJointTexState = -1;
899 int useJointNormalTexState = -1;
900 QByteArray currentShadedFunc;
901 Tokenizer::Token t = tok.next();
902 while (t != Tokenizer::Token_EOF) {
903 switch (t) {
904 case Tokenizer::Token_Comment:
905 break;
906 case Tokenizer::Token_Identifier:
907 {
908 QByteArray id = QByteArray::fromRawData(lastPos, tok.pos - lastPos);
909 if (id.trimmed() == QByteArrayLiteral("VARYING")) {
910 QByteArray vtype;
911 QByteArray vname;
912 bool vflat = false;
913 lastPos = tok.pos;
914 t = tok.next();
915 while (t != Tokenizer::Token_EOF) {
916 QByteArray data = QByteArray::fromRawData(lastPos, tok.pos - lastPos);
917 if (t == Tokenizer::Token_Identifier) {
918 if (vtype.isEmpty()) {
919 vtype = data.trimmed();
920 if (vtype == QByteArrayLiteral("flat")) {
921 vflat = true;
922 vtype.clear();
923 }
924 } else if (vname.isEmpty()) {
925 vname = data.trimmed();
926 }
927 }
928 if (t == Tokenizer::Token_SemiColon)
929 break;
930 lastPos = tok.pos;
931 t = tok.next();
932 }
934 outputs.append((vflat ? "flat " : "") + vtype + " " + vname);
935 else
936 inputs.append((vflat ? "flat " : "") + vtype + " " + vname);
937 } else {
938 const QByteArray trimmedId = id.trimmed();
939 if (funcFinderState == 0 && trimmedId == QByteArrayLiteral("void")) {
940 funcFinderState += 1;
941 } else if (funcFinderState == 1) {
942 auto begin = qssg_func_injectarg_tab;
943 const auto end = qssg_func_injectarg_tab + (sizeof(qssg_func_injectarg_tab) / sizeof(qssg_func_injectarg_tab[0]));
944 const auto foundIt = std::find_if(begin, end, [trimmedId](const QByteArrayView &entry) { return entry == trimmedId; });
945 if (foundIt != end) {
946 currentShadedFunc = trimmedId;
947 funcFinderState += 1;
948 }
949 } else {
950 funcFinderState = 0;
951 }
952
953 if (trimmedId == QByteArrayLiteral("SCREEN_TEXTURE"))
955 else if (trimmedId == QByteArrayLiteral("SCREEN_MIP_TEXTURE"))
957 else if (trimmedId == QByteArrayLiteral("DEPTH_TEXTURE"))
959 else if (trimmedId == QByteArrayLiteral("AO_TEXTURE"))
961 else if (trimmedId == QByteArrayLiteral("POSITION"))
963 else if (trimmedId == QByteArrayLiteral("PROJECTION_MATRIX"))
965 else if (trimmedId == QByteArrayLiteral("INVERSE_PROJECTION_MATRIX"))
967 else if (trimmedId == QByteArrayLiteral("VAR_COLOR"))
969 else if (trimmedId == QByteArrayLiteral("SHARED_VARS"))
971 else if (trimmedId == QByteArrayLiteral("IBL_ORIENTATION"))
973 else if (trimmedId == QByteArrayLiteral("LIGHTMAP"))
975 else if (trimmedId == QByteArrayLiteral("VIEW_INDEX"))
977 else if (trimmedId == QByteArrayLiteral("INPUT"))
979
980 for (const QSSGCustomMaterialVariableSubstitution &subst : qssg_var_subst_tab) {
981 if (trimmedId == subst.builtin) {
982 QByteArray newExpr;
983 newExpr.assign(subst.actualName);
984 if (subst.multiViewDependent && multiViewCompatible) {
985 if (subst.builtin.endsWith(QByteArrayLiteral("_TEXTURE"))
986 || subst.builtin == QByteArrayLiteral("INPUT"))
987 {
988 newExpr += QByteArrayLiteral("Array"); // e.g. qt_depthTexture -> qt_depthTextureArray
989 } else {
990 newExpr += QByteArrayLiteral("[qt_viewIndex]"); // e.g. qt_viewProjectionMatrix -> qt_viewProjectionMatrix[qt_viewIndex]
991 }
992 }
993 id.replace(subst.builtin, newExpr); // replace, not assignment, to keep whitespace etc.
994 if (trimmedId == QByteArrayLiteral("BONE_TRANSFORMS")) {
995 useJointTexState = 0;
997 } else if (trimmedId == QByteArrayLiteral("BONE_NORMAL_TRANSFORMS")) {
998 useJointNormalTexState = 0;
1000 }
1001 if (trimmedId == QByteArrayLiteral("MORPH_POSITION") ||
1002 trimmedId == QByteArrayLiteral("MORPH_NORMAL") ||
1003 trimmedId == QByteArrayLiteral("MORPH_TANGENT") ||
1004 trimmedId == QByteArrayLiteral("MORPH_BINORMAL"))
1006 break;
1007 }
1008 }
1009 result += id;
1010 }
1011 }
1012 break;
1013 case Tokenizer::Token_OpenParen:
1014 result += QByteArray::fromRawData(lastPos, tok.pos - lastPos);
1015 if (funcFinderState == 2) {
1016 result += QByteArrayLiteral("/*%QT_ARGS_");
1017 result += currentShadedFunc;
1018 result += QByteArrayLiteral("%*/");
1019 for (const QSSGCustomMaterialVariableSubstitution &subst : qssg_var_subst_tab) {
1020 if (currentShadedFunc == subst.builtin) {
1021 currentShadedFunc = subst.actualName.toByteArray();
1022 break;
1023 }
1024 }
1025 md.customFunctions.insert(currentShadedFunc);
1026 currentShadedFunc.clear();
1027 }
1028 funcFinderState = 0;
1029 break;
1030 case Tokenizer::Token_OpenBraket:
1031 // copy everything as-is up to the [
1032 result += QByteArray::fromRawData(lastPos, tok.pos - lastPos - 1);
1033 if (useJointTexState == 0) {
1034 result += QByteArrayLiteral("(2 * (");
1035 ++useJointTexState;
1036 break;
1037 } else if (useJointNormalTexState == 0) {
1038 result += QByteArrayLiteral("(1 + 2 * (");
1039 ++useJointNormalTexState;
1040 break;
1041 }
1042
1043 if (useJointTexState >= 0)
1044 ++useJointTexState;
1045 else if (useJointNormalTexState >= 0)
1046 ++useJointNormalTexState;
1047 result += QByteArrayLiteral("[");
1048 break;
1049 case Tokenizer::Token_CloseBraket:
1050 // copy everything as-is up to the ]
1051 result += QByteArray::fromRawData(lastPos, tok.pos - lastPos - 1);
1052 // This implementation will not allow mixed usages of BONE_TRANSFORMS and
1053 // BONE_NORMAL_TRANSFORMS.
1054 // For example, BONE_TRANSFORM[int(BONE_NORMAL_TRANFORMS[i][0].x)]
1055 // cannot be compiled successfully.
1056 if (useJointTexState <= 0 && useJointNormalTexState <= 0) {
1057 result += QByteArrayLiteral("]");
1058 break;
1059 }
1060 if (useJointTexState > 1) {
1061 result += QByteArrayLiteral("]");
1062 --useJointTexState;
1063 break;
1064 } else if (useJointNormalTexState > 1) {
1065 result += QByteArrayLiteral("]");
1066 --useJointNormalTexState;
1067 break;
1068 }
1069 result += QByteArrayLiteral("))");
1070 useJointTexState = -1;
1071 useJointNormalTexState = -1;
1072 break;
1073 default:
1074 result += QByteArray::fromRawData(lastPos, tok.pos - lastPos);
1075 break;
1076 }
1077 lastPos = tok.pos;
1078 t = tok.next();
1079 }
1080
1081 result += '\n';
1082
1083 StringPairList allUniforms = baseUniforms;
1084
1085 // We either have qt_depthTexture or qt_depthTextureArray (or none of them),
1086 // but never both. We do not generally support binding a 2D texture to a
1087 // sampler2DArray binding point and vice versa. Therefore it is up to the
1088 // shader snippet to ifdef with QSHADER_VIEW_COUNT if it wants to support
1089 // both multiview and non-multiview rendering.
1090 if (md.flags.testFlag(QSSGCustomShaderMetaData::UsesDepthTexture)) {
1091 if (multiViewCompatible)
1092 allUniforms.append({ "sampler2DArray", "qt_depthTextureArray" });
1093 else
1094 allUniforms.append({ "sampler2D", "qt_depthTexture" });
1095 }
1096
1097 // And the same pattern for qt_screenTexture(Array).
1099 if (multiViewCompatible)
1100 allUniforms.append({ "sampler2DArray", "qt_screenTextureArray" });
1101 else
1102 allUniforms.append({ "sampler2D", "qt_screenTexture" });
1103 }
1104
1105 // And for SSAO.
1106 if (md.flags.testFlag(QSSGCustomShaderMetaData::UsesAoTexture)) {
1107 if (multiViewCompatible)
1108 allUniforms.append({ "sampler2DArray", "qt_aoTextureArray" });
1109 else
1110 allUniforms.append({ "sampler2D", "qt_aoTexture" });
1111 }
1112
1113 // Input texture for post-processing effects.
1114 if (md.flags.testFlag(QSSGCustomShaderMetaData::UsesInputTexture)) {
1115 if (multiViewCompatible)
1116 allUniforms.append({ "sampler2DArray", "qt_inputTextureArray" });
1117 else
1118 allUniforms.append({ "sampler2D", "qt_inputTexture" });
1119 }
1120
1121 if (md.flags.testFlag(QSSGCustomShaderMetaData::UsesLightmap))
1122 allUniforms.append({ "sampler2D", "qt_lightmap" });
1123
1124 static const char *metaStart = "#ifdef QQ3D_SHADER_META\n/*{\n \"uniforms\": [\n";
1125 static const char *metaEnd = " ]\n}*/\n#endif\n";
1126 dst.append(metaStart);
1127 for (int i = 0, count = allUniforms.size(); i < count; ++i) {
1128 const auto &typeAndName(allUniforms[i]);
1129 dst.append(" { \"type\": \"" + typeAndName.first + "\", \"name\": \"" + typeAndName.second + "\" }");
1130 if (i < count - 1)
1131 dst.append(",");
1132 dst.append("\n");
1133 }
1134 dst.append(metaEnd);
1135
1136 const char *stageStr = type == QSSGShaderCache::ShaderType::Vertex ? "vertex" : "fragment";
1137 StringPairList allInputs = baseInputs;
1138 QVarLengthArray<bool, 16> inputIsFlat(allInputs.count(), false);
1139 for (const QByteArray &inputTypeAndName : inputs) {
1140 const QByteArrayList typeAndName = inputTypeAndName.split(' ');
1141 if (typeAndName.size() == 2) {
1142 allInputs.append({ typeAndName[0].trimmed(), typeAndName[1].trimmed() });
1143 inputIsFlat.append(false);
1144 } else if (typeAndName.size() == 3 && typeAndName[0].startsWith("flat")) {
1145 allInputs.append({ typeAndName[1].trimmed(), typeAndName[2].trimmed() });
1146 inputIsFlat.append(true);
1147 }
1148 }
1149 if (!allInputs.isEmpty()) {
1150 static const char *metaStart = "#ifdef QQ3D_SHADER_META\n/*{\n \"inputs\": [\n";
1151 static const char *metaEnd = " ]\n}*/\n#endif\n";
1152 dst.append(metaStart);
1153 for (int i = 0, count = allInputs.size(); i < count; ++i) {
1154 dst.append(" { \"type\": \"" + allInputs[i].first
1155 + "\", \"name\": \"" + allInputs[i].second
1156 + "\", \"stage\": \"" + stageStr
1157 + (inputIsFlat[i] ? "\", \"flat\": true" : "\"")
1158 + " }");
1159 if (i < count - 1)
1160 dst.append(",");
1161 dst.append("\n");
1162 }
1163 dst.append(metaEnd);
1164 }
1165
1166 StringPairList allOutputs = baseOutputs;
1167 QVarLengthArray<bool, 16> outputIsFlat(allOutputs.count(), false);
1168 for (const QByteArray &outputTypeAndName : outputs) {
1169 const QByteArrayList typeAndName = outputTypeAndName.split(' ');
1170 if (typeAndName.size() == 2) {
1171 allOutputs.append({ typeAndName[0].trimmed(), typeAndName[1].trimmed() });
1172 outputIsFlat.append(false);
1173 } else if (typeAndName.size() == 3 && typeAndName[0].startsWith("flat")) {
1174 allOutputs.append({ typeAndName[1].trimmed(), typeAndName[2].trimmed() });
1175 outputIsFlat.append(true);
1176 }
1177 }
1178 if (!allOutputs.isEmpty()) {
1179 static const char *metaStart = "#ifdef QQ3D_SHADER_META\n/*{\n \"outputs\": [\n";
1180 static const char *metaEnd = " ]\n}*/\n#endif\n";
1181 dst.append(metaStart);
1182 for (int i = 0, count = allOutputs.size(); i < count; ++i) {
1183 dst.append(" { \"type\": \"" + allOutputs[i].first
1184 + "\", \"name\": \"" + allOutputs[i].second
1185 + "\", \"stage\": \"" + stageStr
1186 + (outputIsFlat[i] ? "\", \"flat\": true" : "\"")
1187 + " }");
1188 if (i < count - 1)
1189 dst.append(",");
1190 dst.append("\n");
1191 }
1192 dst.append(metaEnd);
1193 }
1194
1195 return { result, md };
1196}
1197
1199{
1200 QList<QByteArrayView> k;
1201 k.reserve(std::size(qssg_var_subst_tab));
1202 for (const auto &v : qssg_var_subst_tab)
1203 k.push_back(v.builtin);
1204 return k;
1205}
1206
1208
\inmodule QtCore
\inmodule QtCore
Definition qbytearray.h:57
QByteArray trimmed() const &
Definition qbytearray.h:262
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
Definition qbytearray.h:634
QByteArray & assign(QByteArrayView v)
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:409
static bool shaderDebuggingEnabled()
QSSGCustomShaderMetaData getShaderMetaData(const QByteArray &inShaderPathKey, QSSGShaderCache::ShaderType type)
QByteArray getShaderSource(const QByteArray &inShaderPathKey, QSSGShaderCache::ShaderType type)
bool contains(const T &value) const
Definition qset.h:71
void append(const T &t)
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
The QVector4D class represents a vector or vertex in 4D space.
Definition qvectornd.h:330
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
Q_QUICK3DRUNTIMERENDER_EXPORT QList< QByteArrayView > preprocessorVars()
static void * context
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
static bool initialize()
Definition qctf.cpp:94
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLStreamKHR stream
GLsizei const GLfloat * v
[13]
GLuint GLuint end
GLenum GLuint id
[7]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLenum GLenum dst
GLint first
const GLubyte * c
GLuint entry
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLenum GLenum GLenum input
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
CustomShaderPresence m_customShaderPresence
QSSGRenderDefaultMaterial::MaterialSpecularModel specularModel
QSSGRenderDefaultMaterial::MaterialAlphaMode alphaMode
static ShaderCodeAndMetaData prepareCustomShader(QByteArray &dst, const QByteArray &shaderCode, QSSGShaderCache::ShaderType type, const StringPairList &baseUniforms, const StringPairList &baseInputs=StringPairList(), const StringPairList &baseOutputs=StringPairList(), bool multiViewCompatible=false)
bool hasCustomShaderSnippet(QSSGShaderCache::ShaderType type) override
bool hasCustomShaderFunction(QSSGShaderCache::ShaderType shaderType, const QByteArray &funcName, QSSGShaderLibraryManager &shaderLibraryManager) override
void setCustomPropertyUniforms(char *ubufData, QSSGRhiShaderPipeline &shaderPipeline, const QSSGRenderContextInterface &context) override
QSSGRenderDefaultMaterial::VertexColorMaskFlags vertexColorBlueMask() override
QByteArray customShaderSnippet(QSSGShaderCache::ShaderType type, QSSGShaderLibraryManager &shaderLibraryManager, bool multiViewCompatible) override
QSSGRenderDefaultMaterial::VertexColorMaskFlags vertexColorGreenMask() override
QSSGShaderCustomMaterialAdapter(const QSSGRenderCustomMaterial &material)
QPair< QByteArray, QSSGCustomShaderMetaData > ShaderCodeAndMetaData
QSSGRenderDefaultMaterial::VertexColorMaskFlags vertexColorAlphaMask() override
QSSGRenderDefaultMaterial::VertexColorMaskFlags vertexColorRedMask() override
QSSGRenderDefaultMaterial::MaterialSpecularModel specularModel() override
QSSGRenderDefaultMaterial::MaterialAlphaMode alphaMode() override
QSSGRenderDefaultMaterial::VertexColorMaskFlags vertexColorGreenMask() override
QSSGShaderDefaultMaterialAdapter(const QSSGRenderDefaultMaterial &material)
QSSGRenderDefaultMaterial::MaterialSpecularModel specularModel() override
QSSGRenderDefaultMaterial::MaterialAlphaMode alphaMode() override
QSSGRenderDefaultMaterial::VertexColorMaskFlags vertexColorRedMask() override
QSSGRenderDefaultMaterial::VertexColorMaskFlags vertexColorBlueMask() override
QSSGRenderDefaultMaterial::VertexColorMaskFlags vertexColorAlphaMask() override
virtual ~QSSGShaderMaterialAdapter()
virtual bool hasCustomShaderFunction(QSSGShaderCache::ShaderType shaderType, const QByteArray &funcName, QSSGShaderLibraryManager &shaderLibraryManager)
virtual QByteArray customShaderSnippet(QSSGShaderCache::ShaderType type, QSSGShaderLibraryManager &shaderLibraryManager, bool multiViewCompatible)
virtual bool hasCustomShaderSnippet(QSSGShaderCache::ShaderType type)
static QSSGShaderMaterialAdapter * create(const QSSGRenderGraphObject &materialNode)
virtual void setCustomPropertyUniforms(char *ubufData, QSSGRhiShaderPipeline &shaderPipeline, const QSSGRenderContextInterface &context)