26struct QSSGMaterialVertexPipeline
28 enum class GenerationFlag
31 EnvMapReflection = 1 << 1,
34 ObjectNormal = 1 << 4,
35 WorldPosition = 1 << 5,
36 TangentBinormal = 1 << 6,
39 PerspDivDepth = 1 << 9,
40 PerspDivWorldPos = 1 << 10
43 typedef QHash<QByteArray, QByteArray> TStrTableStrMap;
44 typedef TStrTableStrMap::const_iterator TParamIter;
45 typedef QFlags<GenerationFlag> GenerationFlags;
47 QSSGProgramGenerator *m_programGenerator =
nullptr;
50 GenerationFlags m_generationFlags;
54 QList<QByteArray> m_addedFunctions;
57 const QSSGShaderDefaultMaterialKeyProperties &defaultMaterialShaderKeyProperties;
58 QSSGShaderMaterialAdapter *materialAdapter;
59 bool useFloatJointIndices;
60 bool hasCustomShadedMain;
62 bool skipCustomFragmentSnippet;
64 QSSGMaterialVertexPipeline(QSSGProgramGenerator &inProgram,
65 const QSSGShaderDefaultMaterialKeyProperties &materialProperties,
66 QSSGShaderMaterialAdapter *materialAdapter);
68 ~QSSGMaterialVertexPipeline() =
default;
71 bool setCode(GenerationFlag inCode)
73 if (m_generationFlags & inCode)
75 m_generationFlags |= inCode;
78 bool hasCode(GenerationFlag inCode) {
return (m_generationFlags & inCode); }
79 QSSGProgramGenerator *programGenerator()
const {
return m_programGenerator; }
81 QSSGStageGeneratorBase &vertex()
83 return *programGenerator()->getStage(QSSGShaderGeneratorStage::Vertex);
85 QSSGStageGeneratorBase &fragment()
87 return *programGenerator()->getStage(QSSGShaderGeneratorStage::Fragment);
91
92
93
94
95
96
97 void generateUVCoords(quint32 inUVSet,
const QSSGShaderDefaultMaterialKey &inKey)
99 if (inUVSet == 0 && setCode(GenerationFlag::UVCoords))
101 if (inUVSet == 1 && setCode(GenerationFlag::UVCoords1))
104 const bool meshHasUV0 = hasAttributeInKey(QSSGShaderKeyVertexAttribute::TexCoord0, inKey);
105 const bool meshHasUV1 = hasAttributeInKey(QSSGShaderKeyVertexAttribute::TexCoord1, inKey);
107 Q_ASSERT(inUVSet == 0 || inUVSet == 1);
110 if (hasCustomShadedMain || meshHasUV0) {
111 addInterpolationParameter(
"qt_varTexCoord0",
"vec2");
113 vertex().append(
" qt_vertUV0 = qt_getTargetTex0(qt_vertUV0);");
114 vertex() <<
" qt_varTexCoord0 = qt_vertUV0;\n";
115 fragment() <<
" vec2 qt_texCoord0 = qt_varTexCoord0;\n";
117 vertex() <<
" vec2 qt_varTexCoord0 = vec2(0.0);\n";
118 fragment() <<
" vec2 qt_texCoord0 = vec2(0.0);\n";
120 }
else if (inUVSet == 1) {
121 if (hasCustomShadedMain || meshHasUV1) {
122 addInterpolationParameter(
"qt_varTexCoord1",
"vec2");
124 vertex().append(
" qt_vertUV1 = qt_getTargetTex0(qt_vertUV1);");
125 vertex() <<
" qt_varTexCoord1 = qt_vertUV1;\n";
126 fragment() <<
" vec2 qt_texCoord1 = qt_varTexCoord1;\n";
128 vertex() <<
" vec2 qt_varTexCoord1 = vec2(0.0);\n";
129 fragment() <<
" vec2 qt_texCoord1 = vec2(0.0);\n";
134 void generateLightmapUVCoords(
const QSSGShaderDefaultMaterialKey &inKey)
136 if (hasAttributeInKey(QSSGShaderKeyVertexAttribute::TexCoordLightmap, inKey)) {
137 addInterpolationParameter(
"qt_varTexCoordLightmap",
"vec2");
138 vertex() <<
" qt_varTexCoordLightmap = qt_vertLightmapUV;\n";
139 fragment() <<
" vec2 qt_texCoordLightmap = qt_varTexCoordLightmap;\n";
141 vertex() <<
" vec2 qt_varTexCoordLightmap = vec2(0.0);\n";
142 fragment() <<
" vec2 qt_texCoordLightmap = vec2(0.0);\n";
146 void generateEnvMapReflection(
const QSSGShaderDefaultMaterialKey &inKey)
148 if (setCode(GenerationFlag::EnvMapReflection))
151 generateWorldPosition(inKey);
152 generateWorldNormal(inKey);
153 QSSGStageGeneratorBase &activeGenerator(activeStage());
154 addInterpolationParameter(
"qt_var_object_to_camera",
"vec3");
156 if (m_viewCount < 2) {
157 activeGenerator.addUniform(
"qt_cameraPosition",
"vec3");
158 activeGenerator.append(
" qt_var_object_to_camera = normalize( qt_local_model_world_position - qt_cameraPosition );");
160 activeGenerator.addUniformArray(
"qt_cameraPosition",
"vec3", m_viewCount);
161 activeGenerator.append(
" qt_var_object_to_camera = normalize( qt_local_model_world_position - qt_cameraPosition[qt_viewIndex] );");
165 fragment().append(
" vec3 environment_map_reflection = reflect( "
166 "normalize(qt_var_object_to_camera), qt_world_normal.xyz );");
167 fragment().append(
" environment_map_reflection *= vec3( 0.5, 0.5, 0 );");
168 fragment().append(
" environment_map_reflection += vec3( 0.5, 0.5, 1.0 );");
171 void generateViewVector(
const QSSGShaderDefaultMaterialKey &inKey)
173 if (setCode(GenerationFlag::ViewVector))
176 generateWorldPosition(inKey);
178 if (m_viewCount < 2) {
179 activeStage().addUniform(
"qt_cameraPosition",
"vec3");
180 fragment() <<
" vec3 qt_view_vector = normalize(qt_cameraPosition - qt_varWorldPos);\n";
182 activeStage().addUniformArray(
"qt_cameraPosition",
"vec3", m_viewCount);
183 fragment() <<
" vec3 qt_view_vector = normalize(qt_cameraPosition[qt_viewIndex] - qt_varWorldPos);\n";
191 void generateWorldNormal(
const QSSGShaderDefaultMaterialKey &inKey)
193 if (setCode(GenerationFlag::WorldNormal))
196 const bool meshHasNormal = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Normal, inKey);
198 if (hasCustomShadedMain || meshHasNormal) {
199 addInterpolationParameter(
"qt_varNormal",
"vec3");
200 doGenerateWorldNormal(inKey);
202 generateWorldPosition(inKey);
204 fragment().append(
" vec3 qt_varNormal = cross(dFdx(qt_varWorldPos), qt_rhi_properties.x * dFdy(qt_varWorldPos));");
206 fragment().append(
" vec3 qt_world_normal = normalize(qt_varNormal);");
209 void generateObjectNormal()
211 if (setCode(GenerationFlag::ObjectNormal))
214 addInterpolationParameter(
"qt_varObjectNormal",
"vec3");
215 vertex().append(
" qt_varObjectNormal = qt_vertNormal;");
216 fragment().append(
" vec3 object_normal = normalize(qt_varObjectNormal);");
219 void generateWorldPosition(
const QSSGShaderDefaultMaterialKey &inKey)
221 if (setCode(GenerationFlag::WorldPosition))
224 activeStage().addUniform(
"qt_modelMatrix",
"mat4");
225 addInterpolationParameter(
"qt_varWorldPos",
"vec3");
226 const bool usesInstancing = defaultMaterialShaderKeyProperties.m_usesInstancing.getValue(inKey);
227 if (!usesInstancing) {
229 vertex().append(
" vec3 qt_local_model_world_position = qt_vertPosition.xyz;");
231 vertex().append(
" vec3 qt_local_model_world_position = (qt_modelMatrix * qt_vertPosition).xyz;");
233 vertex().append(
" vec3 qt_local_model_world_position = (qt_instancedModelMatrix * qt_vertPosition).xyz;");
236 assignOutput(
"qt_varWorldPos",
"qt_local_model_world_position");
241 if (setCode(GenerationFlag::PerspDivDepth))
244 addInterpolationParameter(
"qt_varDepth",
"float");
245 vertex().append(
" qt_varDepth = gl_Position.z / gl_Position.w;");
248 void generateShadowWorldPosition(
const QSSGShaderDefaultMaterialKey &inKey)
250 if (setCode(GenerationFlag::PerspDivWorldPos))
253 activeStage().addUniform(
"qt_modelMatrix",
"mat4");
254 addInterpolationParameter(
"qt_varShadowWorldPos",
"vec3");
256 const bool usesInstancing = defaultMaterialShaderKeyProperties.m_usesInstancing.getValue(inKey);
257 if (!usesInstancing) {
259 vertex().append(
" vec4 qt_shadow_world_tmp = qt_vertPosition;");
261 vertex().append(
" vec4 qt_shadow_world_tmp = qt_modelMatrix * qt_vertPosition;");
263 vertex().append(
" vec4 qt_shadow_world_tmp = qt_instancedModelMatrix * qt_vertPosition;");
265 vertex().append(
" qt_varShadowWorldPos = qt_shadow_world_tmp.xyz / qt_shadow_world_tmp.w;");
268 void generateVarTangentAndBinormal(
const QSSGShaderDefaultMaterialKey &inKey,
bool &genTangent,
bool &genBinormal)
270 if (setCode(GenerationFlag::TangentBinormal))
273 const bool meshHasTangent = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Tangent, inKey);
274 const bool meshHasBinormal = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Binormal, inKey);
278 if (hasCustomShadedMain || meshHasTangent) {
279 addInterpolationParameter(
"qt_varTangent",
"vec3");
280 doGenerateVarTangent(inKey);
281 fragment() <<
" vec3 qt_tangent = normalize(qt_varTangent);\n";
283 if (hasCustomShadedMain || meshHasBinormal) {
284 addInterpolationParameter(
"qt_varBinormal",
"vec3");
285 doGenerateVarBinormal(inKey);
286 fragment() <<
" vec3 qt_binormal = normalize(qt_varBinormal);\n";
289 fragment() <<
" vec3 qt_binormal = vec3(0.0);\n";
293 fragment() <<
" vec3 qt_tangent = vec3(0.0);\n"
294 <<
" vec3 qt_binormal = vec3(0.0);\n";
297 void generateVertexColor(
const QSSGShaderDefaultMaterialKey &inKey)
299 if (setCode(GenerationFlag::VertexColor))
302 const bool meshHasColor = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Color, inKey);
304 const bool vColorEnabled = defaultMaterialShaderKeyProperties.m_vertexColorsEnabled.getValue(inKey);
305 const bool vColorMaskEnabled = defaultMaterialShaderKeyProperties.m_vertexColorsMaskEnabled.getValue(inKey);
306 const bool usesVarColor = defaultMaterialShaderKeyProperties.m_usesVarColor.getValue(inKey);
307 const bool usesInstancing = defaultMaterialShaderKeyProperties.m_usesInstancing.getValue(inKey);
308 const bool usesBlendParticles = defaultMaterialShaderKeyProperties.m_blendParticles.getValue(inKey);
310 const bool vertexColorsEnabled = (vColorEnabled && meshHasColor) || usesInstancing || usesBlendParticles || usesVarColor;
311 const bool vertexColorsMaskEnabled = (vColorMaskEnabled && meshHasColor);
313 if (vertexColorsEnabled || vertexColorsMaskEnabled) {
314 addInterpolationParameter(
"qt_varColor",
"vec4");
316 vertex().append(
" qt_vertColor = qt_getTargetColor(qt_vertColor);");
317 vertex().append(
" qt_varColor = qt_vertColor;");
319 fragment().append(
" vec4 qt_vertColorMask = qt_varColor;\n");
320 if (vertexColorsEnabled)
321 fragment().append(
" vec4 qt_vertColor = qt_varColor;\n");
323 fragment().append(
" vec4 qt_vertColor = vec4(1.0);\n");
325 fragment().append(
" vec4 qt_vertColorMask = vec4(1.0);\n");
326 fragment().append(
" vec4 qt_vertColor = vec4(1.0);\n");
330 void addIncoming(
const QByteArray &name,
const QByteArray &type) { activeStage().addIncoming(name, type); }
332 void addOutgoing(
const QByteArray &name,
const QByteArray &type) { addInterpolationParameter(name, type); }
334 void addUniform(
const QByteArray &name,
const QByteArray &type) { activeStage().addUniform(name, type); }
336 void addUniformArray(
const QByteArray &name,
const QByteArray &type, quint32 size) { activeStage().addUniformArray(name, type, size); }
338 void addInclude(
const QByteArray &name) { activeStage().addInclude(name); }
340 void addFunction(
const QByteArray &functionName)
342 if (!m_addedFunctions.contains(functionName)) {
343 m_addedFunctions.push_back(functionName);
344 QByteArray includeName =
"func" + functionName +
".glsllib";
345 addInclude(includeName);
349 void addConstantBuffer(
const QByteArray &name,
const QByteArray &layout)
351 activeStage().addConstantBuffer(name, layout);
354 void addConstantBufferParam(
const QByteArray &cbName,
const QByteArray ¶mName,
const QByteArray &type)
356 activeStage().addConstantBufferParam(cbName, paramName, type);
359 void addDefinition(
const QByteArray &name,
const QByteArray &value = QByteArray())
361 activeStage().addDefinition(name, value);
364 QSSGStageGeneratorBase &operator<<(
const QByteArray &data)
366 activeStage() << data;
367 return activeStage();
370 void append(
const QByteArray &data) { activeStage().append(data); }
372 QSSGShaderGeneratorStage stage()
const
374 return const_cast<QSSGMaterialVertexPipeline *>(
this)->activeStage().stage();
378 void beginVertexGeneration(
const QSSGShaderDefaultMaterialKey &inKey,
379 const QSSGShaderFeatures &inFeatureSet,
380 QSSGShaderLibraryManager &shaderLibraryManager);
383 void beginFragmentGeneration(QSSGShaderLibraryManager &shaderLibraryManager, QSSGRenderLayer::OITMethod oitMethod);
387 void assignOutput(
const QByteArray &inVarName,
const QByteArray &inVarValueExpr);
390 void endVertexGeneration();
391 void endFragmentGeneration();
393 QSSGStageGeneratorBase &activeStage();
394 void addInterpolationParameter(
const QByteArray &inParamName,
const QByteArray &inParamType);
395 void addFlatParameter(
const QByteArray &inParamName,
const QByteArray &inParamType);
397 void doGenerateWorldNormal(
const QSSGShaderDefaultMaterialKey &inKey);
398 void doGenerateVarTangent(
const QSSGShaderDefaultMaterialKey &inKey);
399 void doGenerateVarBinormal(
const QSSGShaderDefaultMaterialKey &inKey);
400 bool hasAttributeInKey(QSSGShaderKeyVertexAttribute::VertexAttributeBits inAttr,
const QSSGShaderDefaultMaterialKey &inKey);