Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qssgvertexpipelineimpl.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
6
7#include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h>
8#include <QtQuick3DRuntimeRender/private/qssgrenderlight_p.h>
9#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
10#include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h>
11#include <QtQuick3DRuntimeRender/private/qssgrendershaderlibrarymanager_p.h>
12#include <QtQuick3DRuntimeRender/private/qssgrendershadercodegenerator_p.h>
13#include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterialshadergenerator_p.h>
14#include <QtQuick3DRuntimeRender/private/qssgshadermaterialadapter_p.h>
15
17
19 const QSSGShaderDefaultMaterialKeyProperties &materialProperties,
20 QSSGShaderMaterialAdapter *materialAdapter)
21 : m_programGenerator(&programGen)
22 , defaultMaterialShaderKeyProperties(materialProperties)
23 , materialAdapter(materialAdapter)
24 , hasCustomShadedMain(false)
25 , skipCustomFragmentSnippet(false)
26{
27}
28
29static inline void insertProcessorArgs(QByteArray &snippet, const char *argKey, const char* (*argListFunc)(), bool usesShared = false, bool isSharedInout = false)
30{
31 const int argKeyLen = int(strlen(argKey));
32 const int argKeyPos = snippet.indexOf(argKey);
33 if (argKeyPos >= 0) {
34 if (!usesShared) {
35 snippet = snippet.left(argKeyPos) + argListFunc() + snippet.mid(argKeyPos + argKeyLen);
36 } else {
37 const char *inoutString = isSharedInout ? ", inout " : ", in ";
38 snippet = snippet.left(argKeyPos) + argListFunc() + inoutString + QByteArrayLiteral("QT_SHARED_VARS SHARED") + snippet.mid(argKeyPos + argKeyLen);
39 }
40 }
41}
42
43static inline void insertDirectionalLightProcessorArgs(QByteArray &snippet, bool usesShared)
44{
45 insertProcessorArgs(snippet, "/*%QT_ARGS_DIRECTIONAL_LIGHT%*/", QSSGMaterialShaderGenerator::directionalLightProcessorArgumentList, usesShared, true);
46}
47
48static inline void insertPointLightProcessorArgs(QByteArray &snippet, bool usesShared)
49{
50 insertProcessorArgs(snippet, "/*%QT_ARGS_POINT_LIGHT%*/", QSSGMaterialShaderGenerator::pointLightProcessorArgumentList, usesShared, true);
51}
52
53static inline void insertSpotLightProcessorArgs(QByteArray &snippet, bool usesShared)
54{
55 insertProcessorArgs(snippet, "/*%QT_ARGS_SPOT_LIGHT%*/", QSSGMaterialShaderGenerator::spotLightProcessorArgumentList, usesShared, true);
56}
57
58static inline void insertAmbientLightProcessorArgs(QByteArray &snippet, bool usesShared)
59{
60 insertProcessorArgs(snippet, "/*%QT_ARGS_AMBIENT_LIGHT%*/", QSSGMaterialShaderGenerator::ambientLightProcessorArgumentList, usesShared, true);
61}
62
63static inline void insertIblProbeProcessorArgs(QByteArray &snippet, bool usesShared)
64{
65 insertProcessorArgs(snippet, "/*%QT_ARGS_IBL_PROBE%*/", QSSGMaterialShaderGenerator::iblProbeProcessorArgumentList, usesShared, true);
66}
67
68static inline void insertSpecularLightProcessorArgs(QByteArray &snippet, bool usesShared)
69{
70 insertProcessorArgs(snippet, "/*%QT_ARGS_SPECULAR_LIGHT%*/", QSSGMaterialShaderGenerator::specularLightProcessorArgumentList, usesShared, true);
71}
72
73static inline void insertFragmentMainArgs(QByteArray &snippet, bool usesShared = false)
74{
75 insertProcessorArgs(snippet, "/*%QT_ARGS_MAIN%*/", QSSGMaterialShaderGenerator::shadedFragmentMainArgumentList, usesShared, true);
76}
77
78static inline void insertPostProcessorArgs(QByteArray &snippet, bool usesShared)
79{
80 insertProcessorArgs(snippet, "/*%QT_ARGS_POST_PROCESS%*/", QSSGMaterialShaderGenerator::postProcessorArgumentList, usesShared, false);
81}
82
83static inline void insertVertexMainArgs(QByteArray &snippet)
84{
86}
87
88static inline void insertVertexInstancedMainArgs(QByteArray &snippet)
89{
91}
92
93static inline const char *customMainCallWithArguments(bool usesInstancing)
94{
95 if (usesInstancing)
96 return " qt_customMain(qt_vertPosition.xyz, qt_vertNormal, qt_vertUV0, qt_vertUV1, qt_vertTangent, qt_vertBinormal, qt_vertJoints, qt_vertWeights, qt_vertColor, qt_instancedModelMatrix, qt_instancedMVPMatrix);";
97 else
98 return " qt_customMain(qt_vertPosition.xyz, qt_vertNormal, qt_vertUV0, qt_vertUV1, qt_vertTangent, qt_vertBinormal, qt_vertJoints, qt_vertWeights, qt_vertColor);\n";
99}
100
102 const QSSGShaderFeatures &inFeatureSet,
103 QSSGShaderLibraryManager &shaderLibraryManager)
104{
105 QSSGShaderGeneratorStageFlags theStages(QSSGProgramGenerator::defaultFlags());
106 programGenerator()->beginProgram(theStages);
107
108 QSSGStageGeneratorBase &vertexShader(vertex());
109
116 const bool meshHasTexCoordLightmap = defaultMaterialShaderKeyProperties.m_vertexAttributes.getBitValue(
124 const bool meshHasJointsAndWeights = defaultMaterialShaderKeyProperties.m_vertexAttributes.getBitValue(
126 const bool overridesPosition = defaultMaterialShaderKeyProperties.m_overridesPosition.getValue(inKey);
127 const bool usesProjectionMatrix = defaultMaterialShaderKeyProperties.m_usesProjectionMatrix.getValue(inKey);
128 const bool usesInvProjectionMatrix = defaultMaterialShaderKeyProperties.m_usesInverseProjectionMatrix.getValue(inKey);
129 const bool usesPointsTopology = defaultMaterialShaderKeyProperties.m_usesPointsTopology.getValue(inKey);
130 const bool usesFloatJointIndices = defaultMaterialShaderKeyProperties.m_usesFloatJointIndices.getValue(inKey);
131 const bool blendParticles = defaultMaterialShaderKeyProperties.m_blendParticles.getValue(inKey);
134 const auto morphSize = defaultMaterialShaderKeyProperties.m_targetCount.getValue(inKey);
135 m_hasMorphing = morphSize > 0;
136
137 vertexShader.addIncoming("attr_pos", "vec3");
138 if (usesInstancing) {
139 vertexShader.addIncoming("qt_instanceTransform0", "vec4");
140 vertexShader.addIncoming("qt_instanceTransform1", "vec4");
141 vertexShader.addIncoming("qt_instanceTransform2", "vec4");
142 vertexShader.addIncoming("qt_instanceColor", "vec4");
143 vertexShader.addIncoming("qt_instanceData", "vec4");
144 }
145 if (blendParticles) {
146 vertexShader.addInclude("particles.glsllib");
147 vertexShader.addUniform("qt_particleTexture", "sampler2D");
148 vertexShader.addUniform("qt_countPerSlice", "uint");
149 vertexShader.addUniform("qt_oneOverParticleImageSize", "vec2");
150 vertexShader.addUniform("qt_particleMatrix", "mat4");
151 vertexShader.addUniform("qt_particleIndexOffset", "uint");
152 }
153
154 if (m_hasSkinning && meshHasJointsAndWeights) {
155 vertexShader.addInclude("skinanim.glsllib");
156 if (usesFloatJointIndices)
157 vertexShader.addIncoming("attr_joints", "vec4");
158 else
159 vertexShader.addIncoming("attr_joints", "ivec4");
160 vertexShader.addIncoming("attr_weights", "vec4");
161
162 vertexShader.addUniform("qt_boneTexture", "sampler2D");
163 }
164 if (m_hasMorphing) {
165 vertexShader.addInclude("morphanim.glsllib");
166 vertexShader.addUniformArray("qt_morphWeights", "float", morphSize);
167 vertexShader.addUniform("qt_morphTargetTexture", "sampler2DArray");
168 }
169
172 if (hasCustomVertexShader) {
174 shaderLibraryManager);
176 QByteArrayLiteral("qt_customMain"),
177 shaderLibraryManager))
178 {
179 if (usesInstancing)
181 else
182 insertVertexMainArgs(snippet);
183
185 vertexShader.addInclude("skinanim.glsllib");
186 vertexShader.addUniform("qt_boneTexture", "sampler2D");
187 m_hasSkinning = false;
188 }
189
191 vertexShader.addInclude("morphanim_custom.glsllib");
192 if (morphSize > 0)
193 vertexShader.addUniformArray("qt_morphWeights", "float", morphSize);
194 vertexShader.addUniform("qt_morphTargetTexture", "sampler2DArray");
195 m_hasMorphing = false;
196 }
197
198 if (!materialAdapter->isUnshaded()) {
199 hasCustomShadedMain = true;
200 }
201 }
202 vertexShader << snippet;
203 }
204
205 vertexShader << "void main()"
206 << "\n"
207 << "{"
208 << "\n";
209 // These local variables will be used for whole the pipeline
210 // instead of each attributes since it is more convenient
211 // for adding new routines.
212 vertexShader.append(" vec4 qt_vertPosition = vec4(attr_pos, 1.0);");
213 vertexShader.append(" vec3 qt_vertNormal = vec3(0.0);");
214 vertexShader.append(" vec3 qt_vertTangent = vec3(0.0);");
215 vertexShader.append(" vec3 qt_vertBinormal = vec3(0.0);");
216 if (meshHasTexCoord0 || hasCustomVertexShader)
217 vertexShader.append(" vec2 qt_vertUV0 = vec2(0.0);");
218 if (meshHasTexCoord1 || hasCustomVertexShader)
219 vertexShader.append(" vec2 qt_vertUV1 = vec2(0.0);");
220 if (m_hasSkinning || hasCustomVertexShader)
221 vertexShader.append(" ivec4 qt_vertJoints = ivec4(0);");
222 if (meshHasJointsAndWeights || m_hasSkinning || hasCustomVertexShader)
223 vertexShader.append(" vec4 qt_vertWeights = vec4(0.0);");
224 if (meshHasColors || usesInstancing || blendParticles || hasCustomVertexShader || hasCustomFragmentShader)
225 vertexShader.append(" vec4 qt_vertColor = vec4(1.0);"); // must be 1,1,1,1 to not alter when multiplying with it
226
227 if (!usesInstancing) {
228 vertexShader.addUniform("qt_modelViewProjection", "mat4");
229 } else {
230 // Must manualy calculate a MVP
231 vertexShader.addUniform("qt_modelMatrix", "mat4");
232 vertexShader.addUniform("qt_parentMatrix", "mat4");
233 vertexShader.addUniform("qt_viewProjectionMatrix", "mat4");
234 }
235
236 // The custom fragment main should be skipped if this is a
237 // depth pass, but not if it is also a OpaqueDepthPrePass
238 // because then we need to know the real alpha values
240 const bool isDepthPass = inFeatureSet.isSet(QSSGShaderFeatures::Feature::DepthPass);
241 const bool isOpaqueDepthPrePass = inFeatureSet.isSet(QSSGShaderFeatures::Feature::OpaqueDepthPrePass);
242 skipCustomFragmentSnippet = (isDepthPass && !isOpaqueDepthPrePass);
243
244 if (hasCustomVertexShader || hasCustomFragmentShader) {
245 // This is both for unshaded and shaded. Regardless of any other
246 // condition we have to ensure the keywords (VIEW_MATRIX etc.) promised
247 // by the documentation are available in *both* the custom vertex and
248 // fragment shader snippets, even if only one of them is present.
249 vertexShader.addUniform("qt_viewProjectionMatrix", "mat4");
250 vertexShader.addUniform("qt_modelMatrix", "mat4");
251 vertexShader.addUniform("qt_viewMatrix", "mat4");
252 vertexShader.addUniform("qt_normalMatrix", "mat3");
253 vertexShader.addUniform("qt_cameraPosition", "vec3");
254 vertexShader.addUniform("qt_cameraDirection", "vec3");
255 vertexShader.addUniform("qt_cameraProperties", "vec2");
256 if (usesProjectionMatrix)
257 vertexShader.addUniform("qt_projectionMatrix", "mat4");
258 if (usesInvProjectionMatrix)
259 vertexShader.addUniform("qt_inverseProjectionMatrix", "mat4");
260 }
261
262 if (meshHasNormals) {
263 vertexShader.append(" qt_vertNormal = attr_norm;");
264 vertexShader.addIncoming("attr_norm", "vec3");
265 }
266 if (meshHasTexCoord0) {
267 vertexShader.append(" qt_vertUV0 = attr_uv0;");
268 vertexShader.addIncoming("attr_uv0", "vec2");
269 }
270 if (meshHasTexCoord1) {
271 vertexShader.append(" qt_vertUV1 = attr_uv1;");
272 vertexShader.addIncoming("attr_uv1", "vec2");
273 }
274 if (meshHasTexCoordLightmap) {
275 vertexShader.append(" vec2 qt_vertLightmapUV = attr_lightmapuv;");
276 vertexShader.addIncoming("attr_lightmapuv", "vec2");
277 }
278 if (meshHasTangents) {
279 vertexShader.append(" qt_vertTangent = attr_textan;");
280 vertexShader.addIncoming("attr_textan", "vec3");
281 }
282 if (meshHasBinormals) {
283 vertexShader.append(" qt_vertBinormal = attr_binormal;");
284 vertexShader.addIncoming("attr_binormal", "vec3");
285 }
286 if (meshHasColors && materialAdapter->isVertexColorsEnabled()) {
287 vertexShader.append(" qt_vertColor = attr_color;");
288 vertexShader.addIncoming("attr_color", "vec4");
289 }
290
291 if (meshHasJointsAndWeights && (m_hasSkinning || hasCustomVertexShader)) {
292 if (usesFloatJointIndices) {
293 vertexShader.addIncoming("attr_joints", "vec4");
294 vertexShader.append(" qt_vertJoints = ivec4(attr_joints);");
295 } else {
296 vertexShader.addIncoming("attr_joints", "ivec4");
297 vertexShader.append(" qt_vertJoints = attr_joints;");
298 }
299 vertexShader.addIncoming("attr_weights", "vec4");
300 vertexShader.append(" qt_vertWeights = attr_weights;");
301 }
302
303 if (usesInstancing) {
304 vertexShader.append(" qt_vertColor *= qt_instanceColor;");
305 vertexShader.append(" mat4 qt_instanceMatrix = mat4(qt_instanceTransform0, qt_instanceTransform1, qt_instanceTransform2, vec4(0.0, 0.0, 0.0, 1.0));");
306 if (m_hasSkinning)
307 vertexShader.append(" mat4 qt_instancedModelMatrix = qt_parentMatrix * transpose(qt_instanceMatrix);");
308 else
309 vertexShader.append(" mat4 qt_instancedModelMatrix = qt_parentMatrix * transpose(qt_instanceMatrix) * qt_modelMatrix;");
310 vertexShader.append(" mat3 qt_instancedNormalMatrix = mat3(transpose(inverse(qt_instancedModelMatrix)));");
311 vertexShader.append(" mat4 qt_instancedMVPMatrix = qt_viewProjectionMatrix * qt_instancedModelMatrix;");
312 }
313
314 if (!materialAdapter->isUnshaded() || !hasCustomVertexShader) {
315 vertexShader << " vec3 qt_uTransform;\n";
316 vertexShader << " vec3 qt_vTransform;\n";
317
320
321 if (m_hasMorphing && !hasCustomVertexShader)
322 vertexShader.append(" qt_vertPosition.xyz = qt_getTargetPosition(qt_vertPosition.xyz);");
323
324 if (m_hasSkinning) {
325 vertexShader.append(" mat4 skinMat = mat4(1);");
326 vertexShader.append(" if (qt_vertWeights != vec4(0.0)) {");
327 vertexShader.append(" skinMat = qt_getSkinMatrix(qt_vertJoints, qt_vertWeights);");
328 vertexShader.append(" qt_vertPosition = skinMat * qt_vertPosition;");
329 vertexShader.append(" }");
330 }
331 if (blendParticles) {
332 vertexShader.append(" qt_vertPosition.xyz = qt_applyParticle(qt_vertPosition.xyz, qt_vertNormal, qt_vertColor, qt_vertNormal, qt_vertColor, qt_particleMatrix);");
333 }
334
335 if (!hasCustomShadedMain || !overridesPosition) {
336 if (!usesInstancing)
337 vertexShader.append(" gl_Position = qt_modelViewProjection * qt_vertPosition;");
338 else
339 vertexShader.append(" gl_Position = qt_instancedMVPMatrix * qt_vertPosition;");
340 }
341 }
342
343 if (usesPointsTopology && !hasCustomVertexShader) {
344 vertexShader.addUniform("qt_materialPointSize", "float");
345 vertexShader.append(" gl_PointSize = qt_materialPointSize;");
346 } // with a custom vertex shader it is up to it to set gl_PointSize (aka POINT_SIZE)
347}
348
350{
351 fragment().addUniform("qt_material_properties", "vec4");
352 fragment().addUniform("qt_rhi_properties", "vec4");
353
356 shaderLibraryManager);
357 if (!materialAdapter->isUnshaded()) {
358 const bool usesShared = materialAdapter->usesSharedVariables();
359 insertAmbientLightProcessorArgs(snippet, usesShared);
360 insertIblProbeProcessorArgs(snippet, usesShared);
361 insertSpecularLightProcessorArgs(snippet, usesShared);
362 insertSpotLightProcessorArgs(snippet, usesShared);
363 insertPointLightProcessorArgs(snippet, usesShared);
364 insertDirectionalLightProcessorArgs(snippet, usesShared);
365 insertFragmentMainArgs(snippet, usesShared);
366 insertPostProcessorArgs(snippet, usesShared);
367 }
368 fragment() << snippet;
369 }
370
371 fragment() << "void main()"
372 << "\n"
373 << "{"
374 << "\n";
375
377 fragment() << " float qt_objectOpacity = qt_material_properties.a;\n";
378}
379
380void QSSGMaterialVertexPipeline::assignOutput(const QByteArray &inVarName, const QByteArray &inVarValue)
381{
382 vertex() << " " << inVarName << " = " << inVarValue << ";\n";
383}
384
386{
387 QSSGStageGeneratorBase &vertexGenerator(vertex());
389 if (!usesInstancing)
390 vertexGenerator.addUniform("qt_normalMatrix", "mat3");
391 if (m_hasMorphing)
392 vertexGenerator.append(" qt_vertNormal = qt_getTargetNormal(qt_vertNormal);");
393 if (m_hasSkinning) {
394 vertexGenerator.append(" if (qt_vertWeights != vec4(0.0))");
395 vertexGenerator.append(" qt_vertNormal = qt_getSkinNormalMatrix(qt_vertJoints, qt_vertWeights) * qt_vertNormal;");
396 }
397 // If new model->skin is used,
398 // both qt_normalMatrix and qt_modelMatrix are identity.
399 if (!usesInstancing) {
400 if (m_hasSkinning)
401 vertexGenerator.append(" vec3 qt_world_normal = normalize(qt_vertNormal);");
402 else
403 vertexGenerator.append(" vec3 qt_world_normal = normalize(qt_normalMatrix * qt_vertNormal);");
404 } else {
405 vertexGenerator.append(" vec3 qt_world_normal = normalize(qt_instancedNormalMatrix * qt_vertNormal);");
406 }
407 vertexGenerator.append(" qt_varNormal = qt_world_normal;");
408}
409
411{
412 if (m_hasMorphing)
413 vertex() << " qt_vertTangent = qt_getTargetTangent(qt_vertTangent);\n";
414 if (m_hasSkinning) {
415 vertex() << " if (qt_vertWeights != vec4(0.0))\n"
416 << " qt_vertTangent = (skinMat * vec4(qt_vertTangent, 0.0)).xyz;\n";
417
418 }
420 if (!usesInstancing) {
421 if (!m_hasSkinning)
422 vertex() << " qt_varTangent = (qt_modelMatrix * vec4(qt_vertTangent, 0.0)).xyz;\n";
423 else
424 vertex() << " qt_varTangent = qt_vertTangent;\n";
425 } else {
426 vertex() << " qt_varTangent = (qt_instancedModelMatrix * vec4(qt_vertTangent, 0.0)).xyz;\n";
427 }
428}
429
431{
432 if (m_hasMorphing)
433 vertex() << " qt_vertBinormal = qt_getTargetBinormal(qt_vertBinormal);\n";
434 if (m_hasSkinning) {
435 vertex() << " if (qt_vertWeights != vec4(0.0))\n"
436 << " qt_vertBinormal = (skinMat * vec4(qt_vertBinormal, 0.0)).xyz;\n";
437 }
439 if (!usesInstancing) {
440 if (!m_hasSkinning)
441 vertex() << " qt_varBinormal = (qt_modelMatrix * vec4(qt_vertBinormal, 0.0)).xyz;\n";
442 else
443 vertex() << " qt_varBinormal = qt_vertBinormal;\n";
444 } else {
445 vertex() << " qt_varBinormal = (qt_instancedModelMatrix * vec4(qt_vertBinormal, 0.0)).xyz;\n";
446 }
447}
448
450 const QSSGShaderDefaultMaterialKey &inKey)
451{
453}
454
456{
459 vertex().append("}");
460}
461
463{
465 fragment() << " qt_customMain();\n";
466
467 fragment().append("}");
468}
469
471{
472 m_interpolationParameters.insert(inName, inType);
473 vertex().addOutgoing(inName, inType);
474 fragment().addIncoming(inName, inType);
475}
476
478{
479 return vertex();
480}
481
\inmodule QtCore
Definition qbytearray.h:57
qsizetype indexOf(char c, qsizetype from=0) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray left(qsizetype len) const
Returns a byte array that contains the first len bytes of this byte array.
QByteArray mid(qsizetype index, qsizetype len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
static constexpr QSSGShaderGeneratorStageFlags defaultFlags()
void beginProgram(QSSGShaderGeneratorStageFlags inEnabledStages=defaultFlags())
Combined button and popup list for selecting options.
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
static void insertVertexMainArgs(QByteArray &snippet)
static void insertPostProcessorArgs(QByteArray &snippet, bool usesShared)
static void insertPointLightProcessorArgs(QByteArray &snippet, bool usesShared)
static void insertAmbientLightProcessorArgs(QByteArray &snippet, bool usesShared)
static void insertProcessorArgs(QByteArray &snippet, const char *argKey, const char *(*argListFunc)(), bool usesShared=false, bool isSharedInout=false)
static const char * customMainCallWithArguments(bool usesInstancing)
static void insertFragmentMainArgs(QByteArray &snippet, bool usesShared=false)
static void insertIblProbeProcessorArgs(QByteArray &snippet, bool usesShared)
static void insertSpecularLightProcessorArgs(QByteArray &snippet, bool usesShared)
static void insertVertexInstancedMainArgs(QByteArray &snippet)
static void insertVertexMainArgs(QByteArray &snippet)
static void insertSpotLightProcessorArgs(QByteArray &snippet, bool usesShared)
static void insertDirectionalLightProcessorArgs(QByteArray &snippet, bool usesShared)
void beginVertexGeneration(const QSSGShaderDefaultMaterialKey &inKey, const QSSGShaderFeatures &inFeatureSet, QSSGShaderLibraryManager &shaderLibraryManager)
QSSGStageGeneratorBase & vertex()
QSSGShaderMaterialAdapter * materialAdapter
QSSGMaterialVertexPipeline(QSSGProgramGenerator &inProgram, const QSSGShaderDefaultMaterialKeyProperties &materialProperties, QSSGShaderMaterialAdapter *materialAdapter)
QSSGStageGeneratorBase & fragment()
void doGenerateVarTangent(const QSSGShaderDefaultMaterialKey &inKey)
void beginFragmentGeneration(QSSGShaderLibraryManager &shaderLibraryManager)
const QSSGShaderDefaultMaterialKeyProperties & defaultMaterialShaderKeyProperties
void doGenerateVarBinormal(const QSSGShaderDefaultMaterialKey &inKey)
void addInterpolationParameter(const QByteArray &inParamName, const QByteArray &inParamType)
void doGenerateWorldNormal(const QSSGShaderDefaultMaterialKey &inKey)
QSSGStageGeneratorBase & activeStage()
bool hasAttributeInKey(QSSGShaderKeyVertexAttribute::VertexAttributeBits inAttr, const QSSGShaderDefaultMaterialKey &inKey)
void assignOutput(const QByteArray &inVarName, const QByteArray &inVarValueExpr)
QSSGProgramGenerator * programGenerator() const
QSSGShaderKeyVertexAttribute m_vertexAttributes
constexpr bool isSet(Feature feature) const
bool getValue(QSSGDataView< quint32 > inDataStore) const
quint32 getValue(QSSGDataView< quint32 > inDataStore) const
bool getBitValue(VertexAttributeBits bit, QSSGDataView< quint32 > inKeySet) const
virtual bool isVertexColorsEnabled()=0
virtual bool usesCustomMorphing()=0
virtual bool usesCustomSkinning()=0
virtual QByteArray customShaderSnippet(QSSGShaderCache::ShaderType type, QSSGShaderLibraryManager &shaderLibraryManager)
virtual bool hasCustomShaderFunction(QSSGShaderCache::ShaderType shaderType, const QByteArray &funcName, QSSGShaderLibraryManager &shaderLibraryManager)
virtual bool hasCustomShaderSnippet(QSSGShaderCache::ShaderType type)
virtual void addUniformArray(const QByteArray &name, const QByteArray &type, quint32 size)
virtual void addUniform(const QByteArray &name, const QByteArray &type)
virtual void append(const QByteArray &data)
virtual void addOutgoing(const QByteArray &name, const QByteArray &type)
virtual void addIncoming(const QByteArray &name, const QByteArray &type)
virtual void addInclude(const QByteArray &name) final