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
qssgvertexpipelineimpl_p.h
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#ifndef QSSG_VERTEX_PIPELINE_IMPL_H
6#define QSSG_VERTEX_PIPELINE_IMPL_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterialshadergenerator_p.h>
20#include <QtQuick3DRuntimeRender/private/qssgrendershaderkeys_p.h>
21
22#include <QtCore/QSharedPointer>
23
25
27{
28 enum class GenerationFlag
29 {
30 UVCoords = 1,
31 EnvMapReflection = 1 << 1,
32 ViewVector = 1 << 2,
33 WorldNormal = 1 << 3,
34 ObjectNormal = 1 << 4,
35 WorldPosition = 1 << 5,
36 TangentBinormal = 1 << 6,
37 UVCoords1 = 1 << 7,
38 VertexColor = 1 << 8,
39 PerspDivDepth = 1 << 9,
40 PerspDivWorldPos = 1 << 10
41 };
42
43 typedef QHash<QByteArray, QByteArray> TStrTableStrMap;
45 typedef QFlags<GenerationFlag> GenerationFlags;
46
49
53 QList<QByteArray> m_addedFunctions;
54 int m_viewCount = 1;
55
62
64 const QSSGShaderDefaultMaterialKeyProperties &materialProperties,
66
68
69 // Trues true if the code was *not* set.
71 {
72 if (m_generationFlags & inCode)
73 return true;
74 m_generationFlags |= inCode;
75 return false;
76 }
77 bool hasCode(GenerationFlag inCode) { return (m_generationFlags & inCode); }
79
88
97 {
98 if (inUVSet == 0 && setCode(GenerationFlag::UVCoords))
99 return;
100 if (inUVSet == 1 && setCode(GenerationFlag::UVCoords1))
101 return;
102
103 const bool meshHasUV0 = hasAttributeInKey(QSSGShaderKeyVertexAttribute::TexCoord0, inKey);
104 const bool meshHasUV1 = hasAttributeInKey(QSSGShaderKeyVertexAttribute::TexCoord1, inKey);
105
106 Q_ASSERT(inUVSet == 0 || inUVSet == 1);
107
108 if (inUVSet == 0) {
109 if (hasCustomShadedMain || meshHasUV0) {
110 addInterpolationParameter("qt_varTexCoord0", "vec2");
111 if (m_hasMorphing)
112 vertex().append(" qt_vertUV0 = qt_getTargetTex0(qt_vertUV0);");
113 vertex() << " qt_varTexCoord0 = qt_vertUV0;\n";
114 fragment() <<" vec2 qt_texCoord0 = qt_varTexCoord0;\n";
115 } else {
116 vertex() << " vec2 qt_varTexCoord0 = vec2(0.0);\n";
117 fragment() << " vec2 qt_texCoord0 = vec2(0.0);\n";
118 }
119 } else if (inUVSet == 1) {
120 if (hasCustomShadedMain || meshHasUV1) {
121 addInterpolationParameter("qt_varTexCoord1", "vec2");
122 if (m_hasMorphing)
123 vertex().append(" qt_vertUV1 = qt_getTargetTex0(qt_vertUV1);");
124 vertex() << " qt_varTexCoord1 = qt_vertUV1;\n";
125 fragment() <<" vec2 qt_texCoord1 = qt_varTexCoord1;\n";
126 } else {
127 vertex() << " vec2 qt_varTexCoord1 = vec2(0.0);\n";
128 fragment() << " vec2 qt_texCoord1 = vec2(0.0);\n";
129 }
130 }
131 }
132
134 {
136 addInterpolationParameter("qt_varTexCoordLightmap", "vec2");
137 vertex() << " qt_varTexCoordLightmap = qt_vertLightmapUV;\n";
138 fragment() <<" vec2 qt_texCoordLightmap = qt_varTexCoordLightmap;\n";
139 } else {
140 vertex() << " vec2 qt_varTexCoordLightmap = vec2(0.0);\n";
141 fragment() << " vec2 qt_texCoordLightmap = vec2(0.0);\n";
142 }
143 }
144
146 {
148 return;
149
151 generateWorldNormal(inKey);
152 QSSGStageGeneratorBase &activeGenerator(activeStage());
153 addInterpolationParameter("qt_var_object_to_camera", "vec3");
154
155 if (m_viewCount < 2) {
156 activeGenerator.addUniform("qt_cameraPosition", "vec3");
157 activeGenerator.append(" qt_var_object_to_camera = normalize( qt_local_model_world_position - qt_cameraPosition );");
158 } else {
159 activeGenerator.addUniformArray("qt_cameraPosition", "vec3", m_viewCount);
160 activeGenerator.append(" qt_var_object_to_camera = normalize( qt_local_model_world_position - qt_cameraPosition[qt_viewIndex] );");
161 }
162
163 // World normal cannot be relied upon in the vertex shader because of bump maps.
164 fragment().append(" vec3 environment_map_reflection = reflect( "
165 "normalize(qt_var_object_to_camera), qt_world_normal.xyz );");
166 fragment().append(" environment_map_reflection *= vec3( 0.5, 0.5, 0 );");
167 fragment().append(" environment_map_reflection += vec3( 0.5, 0.5, 1.0 );");
168 }
169
171 {
173 return;
174
176
177 if (m_viewCount < 2) {
178 activeStage().addUniform("qt_cameraPosition", "vec3");
179 fragment() << " vec3 qt_view_vector = normalize(qt_cameraPosition - qt_varWorldPos);\n";
180 } else {
181 activeStage().addUniformArray("qt_cameraPosition", "vec3", m_viewCount);
182 fragment() << " vec3 qt_view_vector = normalize(qt_cameraPosition[qt_viewIndex] - qt_varWorldPos);\n";
183 }
184 }
185
186 // fragment shader expects varying vertex normal
187 // lighting in vertex pipeline expects qt_world_normal
188
189 // qt_world_normal in both vert and frag shader
191 {
193 return;
194
195 const bool meshHasNormal = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Normal, inKey);
196
197 if (hasCustomShadedMain || meshHasNormal) {
198 addInterpolationParameter("qt_varNormal", "vec3");
200 } else {
202 // qt_rhi_properties.x is used to correct for Y inversion for non OpenGL backends
203 fragment().append(" vec3 qt_varNormal = cross(dFdx(qt_varWorldPos), qt_rhi_properties.x * dFdy(qt_varWorldPos));");
204 }
205 fragment().append(" vec3 qt_world_normal = normalize(qt_varNormal);");
206 }
207
209 {
211 return;
212
213 addInterpolationParameter("qt_varObjectNormal", "vec3");
214 vertex().append(" qt_varObjectNormal = qt_vertNormal;");
215 fragment().append(" vec3 object_normal = normalize(qt_varObjectNormal);");
216 }
217
219 {
221 return;
222
223 activeStage().addUniform("qt_modelMatrix", "mat4");
224 addInterpolationParameter("qt_varWorldPos", "vec3");
226 if (!usesInstancing) {
227 if (m_hasSkinning)
228 vertex().append(" vec3 qt_local_model_world_position = qt_vertPosition.xyz;");
229 else
230 vertex().append(" vec3 qt_local_model_world_position = (qt_modelMatrix * qt_vertPosition).xyz;");
231 } else {
232 vertex().append(" vec3 qt_local_model_world_position = (qt_instancedModelMatrix * qt_vertPosition).xyz;");
233 }
234
235 assignOutput("qt_varWorldPos", "qt_local_model_world_position");
236 }
237
239 {
241 return;
242
243 addInterpolationParameter("qt_varDepth", "float");
244 vertex().append(" qt_varDepth = gl_Position.z / gl_Position.w;");
245 }
246
248 {
250 return;
251
252 activeStage().addUniform("qt_modelMatrix", "mat4");
253 addInterpolationParameter("qt_varShadowWorldPos", "vec3");
254
256 if (!usesInstancing) {
257 if (m_hasSkinning)
258 vertex().append(" vec4 qt_shadow_world_tmp = qt_vertPosition;");
259 else
260 vertex().append(" vec4 qt_shadow_world_tmp = qt_modelMatrix * qt_vertPosition;");
261 } else {
262 vertex().append(" vec4 qt_shadow_world_tmp = qt_instancedModelMatrix * qt_vertPosition;");
263 }
264 vertex().append(" qt_varShadowWorldPos = qt_shadow_world_tmp.xyz / qt_shadow_world_tmp.w;");
265 }
266
267 void generateVarTangentAndBinormal(const QSSGShaderDefaultMaterialKey &inKey, bool &genTangent, bool &genBinormal)
268 {
270 return;
271
272 const bool meshHasTangent = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Tangent, inKey);
273 const bool meshHasBinormal = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Binormal, inKey);
274
275 // I assume that there is no mesh having only binormal without tangent
276 // since it is an abnormal case
277 if (hasCustomShadedMain || meshHasTangent) {
278 addInterpolationParameter("qt_varTangent", "vec3");
280 fragment() << " vec3 qt_tangent = normalize(qt_varTangent);\n";
281
282 if (hasCustomShadedMain || meshHasBinormal) {
283 addInterpolationParameter("qt_varBinormal", "vec3");
285 fragment() << " vec3 qt_binormal = normalize(qt_varBinormal);\n";
286 genBinormal = true;
287 } else {
288 fragment() << " vec3 qt_binormal = vec3(0.0);\n";
289 }
290 genTangent = true;
291 } else {
292 fragment() << " vec3 qt_tangent = vec3(0.0);\n"
293 << " vec3 qt_binormal = vec3(0.0);\n";
294 }
295 }
297 {
299 return;
300
301 const bool meshHasColor = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Color, inKey);
302
303 const bool vColorEnabled = defaultMaterialShaderKeyProperties.m_vertexColorsEnabled.getValue(inKey);
304 const bool vColorMaskEnabled = defaultMaterialShaderKeyProperties.m_vertexColorsMaskEnabled.getValue(inKey);
305 const bool usesVarColor = defaultMaterialShaderKeyProperties.m_usesVarColor.getValue(inKey);
307 const bool usesBlendParticles = defaultMaterialShaderKeyProperties.m_blendParticles.getValue(inKey);
308
309 const bool vertexColorsEnabled = (vColorEnabled && meshHasColor) || usesInstancing || usesBlendParticles || usesVarColor;
310 const bool vertexColorsMaskEnabled = (vColorMaskEnabled && meshHasColor);
311
312 if (vertexColorsEnabled || vertexColorsMaskEnabled) {
313 addInterpolationParameter("qt_varColor", "vec4");
314 if (m_hasMorphing)
315 vertex().append(" qt_vertColor = qt_getTargetColor(qt_vertColor);");
316 vertex().append(" qt_varColor = qt_vertColor;");
317
318 fragment().append(" vec4 qt_vertColorMask = qt_varColor;\n");
319 if (vertexColorsEnabled)
320 fragment().append(" vec4 qt_vertColor = qt_varColor;\n");
321 else
322 fragment().append(" vec4 qt_vertColor = vec4(1.0);\n");
323 }else {
324 fragment().append(" vec4 qt_vertColorMask = vec4(1.0);\n");
325 fragment().append(" vec4 qt_vertColor = vec4(1.0);\n"); // must be 1,1,1,1 to not alter when multiplying with it
326 }
327 }
328
330
332
334
336
338
339 void addFunction(const QByteArray &functionName)
340 {
341 if (!m_addedFunctions.contains(functionName)) {
342 m_addedFunctions.push_back(functionName);
343 QByteArray includeName = "func" + functionName + ".glsllib";
344 addInclude(includeName);
345 }
346 }
347
352
353 void addConstantBufferParam(const QByteArray &cbName, const QByteArray &paramName, const QByteArray &type)
354 {
355 activeStage().addConstantBufferParam(cbName, paramName, type);
356 }
357
362
364 {
365 activeStage() << data;
366 return activeStage();
367 }
368
370
372 {
373 return const_cast<QSSGMaterialVertexPipeline *>(this)->activeStage().stage();
374 }
375
376 // Responsible for beginning all vertex and fragment generation (void main() { etc).
378 const QSSGShaderFeatures &inFeatureSet,
379 QSSGShaderLibraryManager &shaderLibraryManager);
380 // The fragment shader expects a floating point constant, qt_objectOpacity to be defined
381 // post this method.
382 void beginFragmentGeneration(QSSGShaderLibraryManager &shaderLibraryManager);
383 // Output variables may be mangled in some circumstances so the shader generation system
384 // needs an abstraction
385 // mechanism around this.
386 void assignOutput(const QByteArray &inVarName, const QByteArray &inVarValueExpr);
387
388 // responsible for closing all vertex and fragment generation
389 void endVertexGeneration();
391
393 void addInterpolationParameter(const QByteArray &inParamName, const QByteArray &inParamType);
394 void addFlatParameter(const QByteArray &inParamName, const QByteArray &inParamType);
395
400};
401
403
404#endif
\inmodule QtCore
Definition qbytearray.h:57
void push_back(parameter_type t)
Definition qlist.h:675
QSSGStageGeneratorBase * getStage(QSSGShaderGeneratorStage inStage)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
Combined button and popup list for selecting options.
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLuint name
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
unsigned int quint32
Definition qtypes.h:50
QVBoxLayout * layout
bool contains(const AT &t) const noexcept
Definition qlist.h:45
void append(const QByteArray &data)
void addFlatParameter(const QByteArray &inParamName, const QByteArray &inParamType)
QFlags< GenerationFlag > GenerationFlags
bool setCode(GenerationFlag inCode)
void generateShadowWorldPosition(const QSSGShaderDefaultMaterialKey &inKey)
void beginVertexGeneration(const QSSGShaderDefaultMaterialKey &inKey, const QSSGShaderFeatures &inFeatureSet, QSSGShaderLibraryManager &shaderLibraryManager)
void addIncoming(const QByteArray &name, const QByteArray &type)
void addDefinition(const QByteArray &name, const QByteArray &value=QByteArray())
void addUniform(const QByteArray &name, const QByteArray &type)
void addInclude(const QByteArray &name)
bool hasCode(GenerationFlag inCode)
QSSGStageGeneratorBase & vertex()
QSSGShaderMaterialAdapter * materialAdapter
QSSGMaterialVertexPipeline(QSSGProgramGenerator &inProgram, const QSSGShaderDefaultMaterialKeyProperties &materialProperties, QSSGShaderMaterialAdapter *materialAdapter)
void generateEnvMapReflection(const QSSGShaderDefaultMaterialKey &inKey)
void addUniformArray(const QByteArray &name, const QByteArray &type, quint32 size)
QSSGStageGeneratorBase & fragment()
void doGenerateVarTangent(const QSSGShaderDefaultMaterialKey &inKey)
void beginFragmentGeneration(QSSGShaderLibraryManager &shaderLibraryManager)
const QSSGShaderDefaultMaterialKeyProperties & defaultMaterialShaderKeyProperties
void generateVertexColor(const QSSGShaderDefaultMaterialKey &inKey)
void doGenerateVarBinormal(const QSSGShaderDefaultMaterialKey &inKey)
QSSGProgramGenerator * m_programGenerator
void addConstantBuffer(const QByteArray &name, const QByteArray &layout)
void addInterpolationParameter(const QByteArray &inParamName, const QByteArray &inParamType)
void doGenerateWorldNormal(const QSSGShaderDefaultMaterialKey &inKey)
~QSSGMaterialVertexPipeline()=default
void addConstantBufferParam(const QByteArray &cbName, const QByteArray &paramName, const QByteArray &type)
QSSGStageGeneratorBase & activeStage()
void generateVarTangentAndBinormal(const QSSGShaderDefaultMaterialKey &inKey, bool &genTangent, bool &genBinormal)
QSSGShaderGeneratorStage stage() const
bool hasAttributeInKey(QSSGShaderKeyVertexAttribute::VertexAttributeBits inAttr, const QSSGShaderDefaultMaterialKey &inKey)
void assignOutput(const QByteArray &inVarName, const QByteArray &inVarValueExpr)
QSSGProgramGenerator * programGenerator() const
void generateViewVector(const QSSGShaderDefaultMaterialKey &inKey)
void addOutgoing(const QByteArray &name, const QByteArray &type)
void addFunction(const QByteArray &functionName)
void generateWorldNormal(const QSSGShaderDefaultMaterialKey &inKey)
QHash< QByteArray, QByteArray > TStrTableStrMap
void generateWorldPosition(const QSSGShaderDefaultMaterialKey &inKey)
void generateUVCoords(quint32 inUVSet, const QSSGShaderDefaultMaterialKey &inKey)
Generates UV coordinates in shader code.
void generateLightmapUVCoords(const QSSGShaderDefaultMaterialKey &inKey)
TStrTableStrMap::const_iterator TParamIter
QSSGStageGeneratorBase & operator<<(const QByteArray &data)
bool getValue(QSSGDataView< quint32 > inDataStore) const
QSSGShaderGeneratorStage stage() const
virtual void addConstantBuffer(const QByteArray &name, const QByteArray &layout)
virtual void addConstantBufferParam(const QByteArray &cbName, const QByteArray &paramName, const QByteArray &type)
virtual void addUniformArray(const QByteArray &name, const QByteArray &type, quint32 size)
virtual void addUniform(const QByteArray &name, const QByteArray &type)
virtual void addDefinition(const QByteArray &name, const QByteArray &value) final
virtual void append(const QByteArray &data)
virtual void addIncoming(const QByteArray &name, const QByteArray &type)
virtual void addInclude(const QByteArray &name) final