28struct QSSGMaterialVertexPipeline
30 enum class GenerationFlag
33 EnvMapReflection = 1 << 1,
36 ObjectNormal = 1 << 4,
37 WorldPosition = 1 << 5,
38 TangentBinormal = 1 << 6,
41 PerspDivDepth = 1 << 9,
42 PerspDivWorldPos = 1 << 10
45 typedef QHash<QByteArray, QByteArray> TStrTableStrMap;
46 typedef TStrTableStrMap::const_iterator TParamIter;
47 typedef QFlags<GenerationFlag> GenerationFlags;
49 QSSGProgramGenerator *m_programGenerator =
nullptr;
52 GenerationFlags m_generationFlags;
56 QList<QByteArray> m_addedFunctions;
59 const QSSGShaderDefaultMaterialKeyProperties &defaultMaterialShaderKeyProperties;
60 QSSGShaderMaterialAdapter *materialAdapter;
61 bool useFloatJointIndices;
62 bool hasCustomShadedMain;
64 bool skipCustomFragmentSnippet;
66 QSSGMaterialVertexPipeline(QSSGProgramGenerator &inProgram,
67 const QSSGShaderDefaultMaterialKeyProperties &materialProperties,
68 QSSGShaderMaterialAdapter *materialAdapter);
70 ~QSSGMaterialVertexPipeline() =
default;
73 bool setCode(GenerationFlag inCode)
75 if (m_generationFlags & inCode)
77 m_generationFlags |= inCode;
80 bool hasCode(GenerationFlag inCode) {
return (m_generationFlags & inCode); }
81 QSSGProgramGenerator *programGenerator()
const {
return m_programGenerator; }
83 QSSGStageGeneratorBase &vertex()
85 return *programGenerator()->getStage(QSSGShaderGeneratorStage::Vertex);
87 QSSGStageGeneratorBase &fragment()
89 return *programGenerator()->getStage(QSSGShaderGeneratorStage::Fragment);
93
94
95
96
97
98
99 void generateUVCoords(quint32 inUVSet,
const QSSGShaderDefaultMaterialKey &inKey)
101 if (inUVSet == 0 && setCode(GenerationFlag::UVCoords))
103 if (inUVSet == 1 && setCode(GenerationFlag::UVCoords1))
106 const bool meshHasUV0 = hasAttributeInKey(QSSGShaderKeyVertexAttribute::TexCoord0, inKey);
107 const bool meshHasUV1 = hasAttributeInKey(QSSGShaderKeyVertexAttribute::TexCoord1, inKey);
109 Q_ASSERT(inUVSet == 0 || inUVSet == 1);
112 if (hasCustomShadedMain || meshHasUV0) {
113 addInterpolationParameter(
"qt_varTexCoord0",
"vec2");
115 vertex().append(
" qt_vertUV0 = qt_getTargetTex0(qt_vertUV0);");
116 vertex() <<
" qt_varTexCoord0 = qt_vertUV0;\n";
117 fragment() <<
" vec2 qt_texCoord0 = qt_varTexCoord0;\n";
119 vertex() <<
" vec2 qt_varTexCoord0 = vec2(0.0);\n";
120 fragment() <<
" vec2 qt_texCoord0 = vec2(0.0);\n";
122 }
else if (inUVSet == 1) {
123 if (hasCustomShadedMain || meshHasUV1) {
124 addInterpolationParameter(
"qt_varTexCoord1",
"vec2");
126 vertex().append(
" qt_vertUV1 = qt_getTargetTex0(qt_vertUV1);");
127 vertex() <<
" qt_varTexCoord1 = qt_vertUV1;\n";
128 fragment() <<
" vec2 qt_texCoord1 = qt_varTexCoord1;\n";
130 vertex() <<
" vec2 qt_varTexCoord1 = vec2(0.0);\n";
131 fragment() <<
" vec2 qt_texCoord1 = vec2(0.0);\n";
136 void generateLightmapUVCoords(
const QSSGShaderDefaultMaterialKey &inKey)
138 if (hasAttributeInKey(QSSGShaderKeyVertexAttribute::TexCoordLightmap, inKey)) {
139 addInterpolationParameter(
"qt_varTexCoordLightmap",
"vec2");
140 vertex() <<
" qt_varTexCoordLightmap = qt_vertLightmapUV;\n";
141 fragment() <<
" vec2 qt_texCoordLightmap = qt_varTexCoordLightmap;\n";
143 vertex() <<
" vec2 qt_varTexCoordLightmap = vec2(0.0);\n";
144 fragment() <<
" vec2 qt_texCoordLightmap = vec2(0.0);\n";
148 void generateEnvMapReflection(
const QSSGShaderDefaultMaterialKey &inKey)
150 if (setCode(GenerationFlag::EnvMapReflection))
153 generateWorldPosition(inKey);
154 generateWorldNormal(inKey);
155 QSSGStageGeneratorBase &activeGenerator(activeStage());
156 addInterpolationParameter(
"qt_var_object_to_camera",
"vec3");
158 if (m_viewCount < 2) {
159 activeGenerator.addUniform(
"qt_cameraPosition",
"vec3");
160 activeGenerator.append(
" qt_var_object_to_camera = normalize( qt_local_model_world_position - qt_cameraPosition );");
162 activeGenerator.addUniformArray(
"qt_cameraPosition",
"vec3", m_viewCount);
163 activeGenerator.append(
" qt_var_object_to_camera = normalize( qt_local_model_world_position - qt_cameraPosition[qt_viewIndex] );");
167 fragment().append(
" vec3 environment_map_reflection = reflect( "
168 "normalize(qt_var_object_to_camera), qt_world_normal.xyz );");
169 fragment().append(
" environment_map_reflection *= vec3( 0.5, 0.5, 0 );");
170 fragment().append(
" environment_map_reflection += vec3( 0.5, 0.5, 1.0 );");
173 void generateViewVector(
const QSSGShaderDefaultMaterialKey &inKey)
175 if (setCode(GenerationFlag::ViewVector))
178 generateWorldPosition(inKey);
180 if (m_viewCount < 2) {
181 activeStage().addUniform(
"qt_cameraPosition",
"vec3");
182 fragment() <<
" vec3 qt_view_vector = normalize(qt_cameraPosition - qt_varWorldPos);\n";
184 activeStage().addUniformArray(
"qt_cameraPosition",
"vec3", m_viewCount);
185 fragment() <<
" vec3 qt_view_vector = normalize(qt_cameraPosition[qt_viewIndex] - qt_varWorldPos);\n";
193 void generateWorldNormal(
const QSSGShaderDefaultMaterialKey &inKey)
195 if (setCode(GenerationFlag::WorldNormal))
198 const bool meshHasNormal = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Normal, inKey);
200 if (hasCustomShadedMain || meshHasNormal) {
201 addInterpolationParameter(
"qt_varNormal",
"vec3");
202 doGenerateWorldNormal(inKey);
204 generateWorldPosition(inKey);
206 fragment().append(
" vec3 qt_varNormal = cross(dFdx(qt_varWorldPos), qt_rhi_properties.x * dFdy(qt_varWorldPos));");
208 fragment().append(
" vec3 qt_world_normal = normalize(qt_varNormal);");
211 void generateObjectNormal()
213 if (setCode(GenerationFlag::ObjectNormal))
216 addInterpolationParameter(
"qt_varObjectNormal",
"vec3");
217 vertex().append(
" qt_varObjectNormal = qt_vertNormal;");
218 fragment().append(
" vec3 object_normal = normalize(qt_varObjectNormal);");
221 void generateWorldPosition(
const QSSGShaderDefaultMaterialKey &inKey)
223 if (setCode(GenerationFlag::WorldPosition))
226 activeStage().addUniform(
"qt_modelMatrix",
"mat4");
227 addInterpolationParameter(
"qt_varWorldPos",
"vec3");
228 const bool usesInstancing = defaultMaterialShaderKeyProperties.m_usesInstancing.getValue(inKey);
229 if (!usesInstancing) {
231 vertex().append(
" vec3 qt_local_model_world_position = qt_vertPosition.xyz;");
233 vertex().append(
" vec3 qt_local_model_world_position = (qt_modelMatrix * qt_vertPosition).xyz;");
235 vertex().append(
" vec3 qt_local_model_world_position = (qt_instancedModelMatrix * qt_vertPosition).xyz;");
238 assignOutput(
"qt_varWorldPos",
"qt_local_model_world_position");
243 if (setCode(GenerationFlag::PerspDivDepth))
246 addInterpolationParameter(
"qt_varDepth",
"float");
247 vertex().append(
" qt_varDepth = gl_Position.z / gl_Position.w;");
250 void generateShadowWorldPosition(
const QSSGShaderDefaultMaterialKey &inKey)
252 if (setCode(GenerationFlag::PerspDivWorldPos))
255 activeStage().addUniform(
"qt_modelMatrix",
"mat4");
256 addInterpolationParameter(
"qt_varShadowWorldPos",
"vec3");
258 const bool usesInstancing = defaultMaterialShaderKeyProperties.m_usesInstancing.getValue(inKey);
259 if (!usesInstancing) {
261 vertex().append(
" vec4 qt_shadow_world_tmp = qt_vertPosition;");
263 vertex().append(
" vec4 qt_shadow_world_tmp = qt_modelMatrix * qt_vertPosition;");
265 vertex().append(
" vec4 qt_shadow_world_tmp = qt_instancedModelMatrix * qt_vertPosition;");
267 vertex().append(
" qt_varShadowWorldPos = qt_shadow_world_tmp.xyz / qt_shadow_world_tmp.w;");
270 void generateVarTangentAndBinormal(
const QSSGShaderDefaultMaterialKey &inKey,
bool &genTangent,
bool &genBinormal)
272 if (setCode(GenerationFlag::TangentBinormal))
275 const bool meshHasTangent = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Tangent, inKey);
276 const bool meshHasBinormal = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Binormal, inKey);
280 if (hasCustomShadedMain || meshHasTangent) {
281 addInterpolationParameter(
"qt_varTangent",
"vec3");
282 doGenerateVarTangent(inKey);
283 fragment() <<
" vec3 qt_tangent = normalize(qt_varTangent);\n";
285 if (hasCustomShadedMain || meshHasBinormal) {
286 addInterpolationParameter(
"qt_varBinormal",
"vec3");
287 doGenerateVarBinormal(inKey);
288 fragment() <<
" vec3 qt_binormal = normalize(qt_varBinormal);\n";
291 fragment() <<
" vec3 qt_binormal = vec3(0.0);\n";
295 fragment() <<
" vec3 qt_tangent = vec3(0.0);\n"
296 <<
" vec3 qt_binormal = vec3(0.0);\n";
299 void generateVertexColor(
const QSSGShaderDefaultMaterialKey &inKey)
301 if (setCode(GenerationFlag::VertexColor))
304 const bool meshHasColor = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Color, inKey);
306 const bool vColorEnabled = defaultMaterialShaderKeyProperties.m_vertexColorsEnabled.getValue(inKey);
307 const bool vColorMaskEnabled = defaultMaterialShaderKeyProperties.m_vertexColorsMaskEnabled.getValue(inKey);
308 const bool usesVarColor = defaultMaterialShaderKeyProperties.m_usesVarColor.getValue(inKey);
309 const bool usesInstancing = defaultMaterialShaderKeyProperties.m_usesInstancing.getValue(inKey);
310 const bool usesBlendParticles = defaultMaterialShaderKeyProperties.m_blendParticles.getValue(inKey);
312 const bool vertexColorsEnabled = (vColorEnabled && meshHasColor) || usesInstancing || usesBlendParticles || usesVarColor;
313 const bool vertexColorsMaskEnabled = (vColorMaskEnabled && meshHasColor);
315 if (vertexColorsEnabled || vertexColorsMaskEnabled) {
316 addInterpolationParameter(
"qt_varColor",
"vec4");
318 vertex().append(
" qt_vertColor = qt_getTargetColor(qt_vertColor);");
319 vertex().append(
" qt_varColor = qt_vertColor;");
321 fragment().append(
" vec4 qt_vertColorMask = qt_varColor;\n");
322 if (vertexColorsEnabled)
323 fragment().append(
" vec4 qt_vertColor = qt_varColor;\n");
325 fragment().append(
" vec4 qt_vertColor = vec4(1.0);\n");
327 fragment().append(
" vec4 qt_vertColorMask = vec4(1.0);\n");
328 fragment().append(
" vec4 qt_vertColor = vec4(1.0);\n");
332 void addIncoming(
const QByteArray &name,
const QByteArray &type) { activeStage().addIncoming(name, type); }
334 void addOutgoing(
const QByteArray &name,
const QByteArray &type) { addInterpolationParameter(name, type); }
336 void addUniform(
const QByteArray &name,
const QByteArray &type) { activeStage().addUniform(name, type); }
338 void addUniformArray(
const QByteArray &name,
const QByteArray &type, quint32 size) { activeStage().addUniformArray(name, type, size); }
340 void addInclude(
const QByteArray &name) { activeStage().addInclude(name); }
342 void addFunction(
const QByteArray &functionName)
344 if (!m_addedFunctions.contains(functionName)) {
345 m_addedFunctions.push_back(functionName);
346 QByteArray includeName =
"func" + functionName +
".glsllib";
347 addInclude(includeName);
351 void addConstantBuffer(
const QByteArray &name,
const QByteArray &layout)
353 activeStage().addConstantBuffer(name, layout);
356 void addConstantBufferParam(
const QByteArray &cbName,
const QByteArray ¶mName,
const QByteArray &type)
358 activeStage().addConstantBufferParam(cbName, paramName, type);
361 void addDefinition(
const QByteArray &name,
const QByteArray &value = QByteArray())
363 activeStage().addDefinition(name, value);
366 QSSGStageGeneratorBase &operator<<(
const QByteArray &data)
368 activeStage() << data;
369 return activeStage();
372 void append(
const QByteArray &data) { activeStage().append(data); }
374 QSSGShaderGeneratorStage stage()
const
376 return const_cast<QSSGMaterialVertexPipeline *>(
this)->activeStage().stage();
380 void beginVertexGeneration(
const QSSGShaderDefaultMaterialKey &inKey,
381 const QSSGShaderFeatures &inFeatureSet,
382 QSSGShaderLibraryManager &shaderLibraryManager);
385 void beginFragmentGeneration(QSSGShaderLibraryManager &shaderLibraryManager, QSSGRenderLayer::OITMethod oitMethod);
389 void assignOutput(
const QByteArray &inVarName,
const QByteArray &inVarValueExpr);
392 void endVertexGeneration();
393 void endFragmentGeneration();
395 QSSGStageGeneratorBase &activeStage();
396 void addInterpolationParameter(
const QByteArray &inParamName,
const QByteArray &inParamType);
397 void addFlatParameter(
const QByteArray &inParamName,
const QByteArray &inParamType);
399 void doGenerateWorldNormal(
const QSSGShaderDefaultMaterialKey &inKey);
400 void doGenerateVarTangent(
const QSSGShaderDefaultMaterialKey &inKey);
401 void doGenerateVarBinormal(
const QSSGShaderDefaultMaterialKey &inKey);
402 bool hasAttributeInKey(QSSGShaderKeyVertexAttribute::VertexAttributeBits inAttr,
const QSSGShaderDefaultMaterialKey &inKey);