From 2d910d35f50280d2af2e82edf91d791525e9ada3 Mon Sep 17 00:00:00 2001 From: Inho Lee <inho.lee@qt.io> Date: Wed, 24 Jun 2020 09:51:44 +0200 Subject: [PATCH] Quick3D: support gltf2's normal, tangent generation This patch will fix NormalTangentMirrorTest Task-number: QTBUG-78840 Change-Id: I4af026b47fccab8dbdb8a822f42cf0ec21709d95 Reviewed-by: Andy Nichols <andy.nichols@qt.io> --- .../assetimporters/assimp/options.json | 2 +- .../qssgrendercustommaterialsystem.cpp | 37 ++++----- .../qssgrendercustommaterialsystem_p.h | 7 +- .../rendererimpl/qssgrendererimplshaders.cpp | 75 +++++++------------ .../rendererimpl/qssgvertexpipelineimpl_p.h | 70 +++++++++++++---- 5 files changed, 104 insertions(+), 87 deletions(-) diff --git a/src/plugins/assetimporters/assimp/options.json b/src/plugins/assetimporters/assimp/options.json index 02f24f446..75b1d5783 100644 --- a/src/plugins/assetimporters/assimp/options.json +++ b/src/plugins/assetimporters/assimp/options.json @@ -3,7 +3,7 @@ "calculateTangentSpace": { "name": "Calculate Tangent Space", "description": "Calculates the tangents and bitangents for the imported meshes.", - "value": true, + "value": false, "type": "Boolean" }, "joinIdenticalVertices": { diff --git a/src/runtimerender/qssgrendercustommaterialsystem.cpp b/src/runtimerender/qssgrendercustommaterialsystem.cpp index 5fbcb98ae..b0c16a148 100644 --- a/src/runtimerender/qssgrendercustommaterialsystem.cpp +++ b/src/runtimerender/qssgrendercustommaterialsystem.cpp @@ -315,7 +315,7 @@ void QSSGCustomMaterialVertexPipeline::assignOutput(const QByteArray &inVarName, vertex() << "\t" << inVarName << " = " << inVarValue << ";\n"; } -void QSSGCustomMaterialVertexPipeline::generateUVCoords(const QSSGShaderDefaultMaterialKey &inKey, quint32 inUVSet) +void QSSGCustomMaterialVertexPipeline::generateUVCoords(const QSSGShaderDefaultMaterialKey &, quint32 inUVSet) { if (inUVSet == 0 && setCode(GenerationFlag::UVCoords)) return; @@ -329,15 +329,15 @@ void QSSGCustomMaterialVertexPipeline::generateUVCoords(const QSSGShaderDefaultM else if (inUVSet == 1) addInterpolationParameter("varTexCoord1", "vec3"); - doGenerateUVCoords(inKey, inUVSet); + doGenerateUVCoords(inUVSet); } -void QSSGCustomMaterialVertexPipeline::generateWorldNormal(const QSSGShaderDefaultMaterialKey &inKey) +void QSSGCustomMaterialVertexPipeline::generateWorldNormal(const QSSGShaderDefaultMaterialKey &) { if (setCode(GenerationFlag::WorldNormal)) return; addInterpolationParameter("varNormal", "vec3"); - doGenerateWorldNormal(inKey); + doGenerateWorldNormal(); } void QSSGCustomMaterialVertexPipeline::generateObjectNormal() @@ -347,7 +347,7 @@ void QSSGCustomMaterialVertexPipeline::generateObjectNormal() doGenerateObjectNormal(); } -void QSSGCustomMaterialVertexPipeline::generateVarTangentAndBinormal(const QSSGShaderDefaultMaterialKey &inKey) +void QSSGCustomMaterialVertexPipeline::generateVarTangentAndBinormal(const QSSGShaderDefaultMaterialKey &) { if (setCode(GenerationFlag::TangentBinormal)) return; @@ -355,7 +355,8 @@ void QSSGCustomMaterialVertexPipeline::generateVarTangentAndBinormal(const QSSGS addInterpolationParameter("varBinormal", "vec3"); addInterpolationParameter("varObjTangent", "vec3"); addInterpolationParameter("varObjBinormal", "vec3"); - doGenerateVarTangentAndBinormal(inKey); + doGenerateVarTangent(); + doGenerateVarBinormal(); } void QSSGCustomMaterialVertexPipeline::generateWorldPosition() @@ -423,7 +424,7 @@ void QSSGCustomMaterialVertexPipeline::addInterpolationParameter(const QByteArra } } -void QSSGCustomMaterialVertexPipeline::doGenerateUVCoords(const QSSGShaderDefaultMaterialKey &, quint32 inUVSet) +void QSSGCustomMaterialVertexPipeline::doGenerateUVCoords(quint32 inUVSet) { Q_ASSERT(inUVSet == 0 || inUVSet == 1); @@ -440,7 +441,7 @@ void QSSGCustomMaterialVertexPipeline::doGenerateUVCoords(const QSSGShaderDefaul } } -void QSSGCustomMaterialVertexPipeline::doGenerateWorldNormal(const QSSGShaderDefaultMaterialKey &) +void QSSGCustomMaterialVertexPipeline::doGenerateWorldNormal() { QSSGShaderStageGeneratorInterface &vertexGenerator(vertex()); vertexGenerator.addIncoming("attr_norm", "vec3"); @@ -464,20 +465,20 @@ void QSSGCustomMaterialVertexPipeline::doGenerateWorldPosition() assignOutput("varWorldPos", "worldPos.xyz"); } -void QSSGCustomMaterialVertexPipeline::doGenerateVarTangentAndBinormal(const QSSGShaderDefaultMaterialKey &) +void QSSGCustomMaterialVertexPipeline::doGenerateVarTangent() { vertex().addIncoming("attr_textan", "vec3"); - vertex().addIncoming("attr_binormal", "vec3"); - vertex() << "\tvarTangent = normalMatrix * attr_textan;" - << "\n" - << "\tvarBinormal = normalMatrix * attr_binormal;" - << "\n"; + vertex() << "\tvarTangent = normalMatrix * attr_textan;\n"; + vertex() << "\tvarObjTangent = attr_textan;\n"; +} + +void QSSGCustomMaterialVertexPipeline::doGenerateVarBinormal() +{ + vertex().addIncoming("attr_binormal", "vec3"); - vertex() << "\tvarObjTangent = attr_textan;" - << "\n" - << "\tvarObjBinormal = attr_binormal;" - << "\n"; + vertex() << "\tvarBinormal = normalMatrix * attr_binormal;\n"; + vertex() << "\tvarObjBinormal = attr_binormal;\n"; } void QSSGCustomMaterialVertexPipeline::doGenerateVertexColor(const QSSGShaderDefaultMaterialKey &) diff --git a/src/runtimerender/qssgrendercustommaterialsystem_p.h b/src/runtimerender/qssgrendercustommaterialsystem_p.h index 07544c38b..466ab7276 100644 --- a/src/runtimerender/qssgrendercustommaterialsystem_p.h +++ b/src/runtimerender/qssgrendercustommaterialsystem_p.h @@ -233,11 +233,12 @@ struct Q_QUICK3DRUNTIMERENDER_EXPORT QSSGCustomMaterialVertexPipeline : public Q virtual void endFragmentGeneration(bool customShader) override; virtual QSSGShaderStageGeneratorInterface &activeStage() override; virtual void addInterpolationParameter(const QByteArray &inName, const QByteArray &inType) override; - virtual void doGenerateUVCoords(const QSSGShaderDefaultMaterialKey &inKey, quint32 inUVSet) override; - virtual void doGenerateWorldNormal(const QSSGShaderDefaultMaterialKey &inKey) override; + virtual void doGenerateUVCoords(quint32 inUVSet) override; + virtual void doGenerateWorldNormal() override; virtual void doGenerateObjectNormal() override; virtual void doGenerateWorldPosition() override; - virtual void doGenerateVarTangentAndBinormal(const QSSGShaderDefaultMaterialKey &inKey) override; + virtual void doGenerateVarTangent() override; + virtual void doGenerateVarBinormal() override; virtual void doGenerateVertexColor(const QSSGShaderDefaultMaterialKey &inKey) override; }; QT_END_NAMESPACE diff --git a/src/runtimerender/rendererimpl/qssgrendererimplshaders.cpp b/src/runtimerender/rendererimpl/qssgrendererimplshaders.cpp index 28cd6f991..4b81f18ba 100644 --- a/src/runtimerender/rendererimpl/qssgrendererimplshaders.cpp +++ b/src/runtimerender/rendererimpl/qssgrendererimplshaders.cpp @@ -308,43 +308,25 @@ struct QSSGSubsetMaterialVertexPipeline : public QSSGVertexPipelineImpl { vertex() << " " << inVarName << " = " << inVarValue << ";\n"; } - void doGenerateUVCoords(const QSSGShaderDefaultMaterialKey &inKey, quint32 inUVSet = 0) override + void doGenerateUVCoords(quint32 inUVSet = 0) override { Q_ASSERT(inUVSet == 0 || inUVSet == 1); if (inUVSet == 0) { - const bool meshHasTexCoord0 = renderer.defaultMaterialShaderKeyProperties().m_vertexAttributes.getBitValue( - QSSGShaderKeyVertexAttribute::TexCoord0, inKey); - if (meshHasTexCoord0) - vertex().addIncoming("attr_uv0", "vec2"); - else - vertex().append(" vec2 attr_uv0 = vec2(0.0);"); - vertex() << " varTexCoord0 = attr_uv0;" - << "\n"; + vertex().addIncoming("attr_uv0", "vec2"); + vertex() << " varTexCoord0 = attr_uv0;\n"; } else if (inUVSet == 1) { - const bool meshHasTexCoord1 = renderer.defaultMaterialShaderKeyProperties().m_vertexAttributes.getBitValue( - QSSGShaderKeyVertexAttribute::TexCoord1, inKey); - if (meshHasTexCoord1) - vertex().addIncoming("attr_uv1", "vec2"); - else - vertex().append(" vec2 attr_uv1 = vec2(0.0);"); - vertex() << " varTexCoord1 = attr_uv1;" - << "\n"; + vertex().addIncoming("attr_uv1", "vec2"); + vertex() << " varTexCoord1 = attr_uv1;\n"; } } // fragment shader expects varying vertex normal // lighting in vertex pipeline expects world_normal - void doGenerateWorldNormal(const QSSGShaderDefaultMaterialKey &inKey) override + void doGenerateWorldNormal() override { - const bool meshHasNormals = renderer.defaultMaterialShaderKeyProperties().m_vertexAttributes.getBitValue( - QSSGShaderKeyVertexAttribute::Normal, inKey); - QSSGShaderStageGeneratorInterface &vertexGenerator(vertex()); - if (meshHasNormals) - vertexGenerator.addIncoming("attr_norm", "vec3"); - else - vertexGenerator.append(" vec3 attr_norm = vec3(0.0);"); + vertexGenerator.addIncoming("attr_norm", "vec3"); vertexGenerator.addUniform("normalMatrix", "mat3"); if (hasTessellation() == false) { vertexGenerator.append(" vec3 world_normal = normalize(normalMatrix * attr_norm).xyz;"); @@ -362,36 +344,26 @@ struct QSSGSubsetMaterialVertexPipeline : public QSSGVertexPipelineImpl assignOutput("varWorldPos", "local_model_world_position"); } - void doGenerateVarTangentAndBinormal(const QSSGShaderDefaultMaterialKey &inKey) override + void doGenerateVarTangent() override { - const bool meshHasTangents = renderer.defaultMaterialShaderKeyProperties().m_vertexAttributes.getBitValue( - QSSGShaderKeyVertexAttribute::Tangent, inKey); - const bool meshHasBinormals = renderer.defaultMaterialShaderKeyProperties().m_vertexAttributes.getBitValue( - QSSGShaderKeyVertexAttribute::Binormal, inKey); + vertex().addIncoming("attr_textan", "vec3"); - if (meshHasTangents) - vertex().addIncoming("attr_textan", "vec3"); + bool hasNPatchTessellation = tessMode == TessellationModeValues::NPatch; + if (!hasNPatchTessellation) + vertex() << " varTangent = normalMatrix * attr_textan;\n"; else - vertex() << " vec3 attr_textan = vec3(0.0);\n"; + vertex() << " varTangent = attr_textan;\n"; + } - if (meshHasBinormals) - vertex().addIncoming("attr_binormal", "vec3"); - else - vertex() << " vec3 attr_binormal = vec3(0.0);\n"; + void doGenerateVarBinormal() override + { + vertex().addIncoming("attr_binormal", "vec3"); bool hasNPatchTessellation = tessMode == TessellationModeValues::NPatch; - - if (!hasNPatchTessellation) { - vertex() << " varTangent = normalMatrix * attr_textan;" - << "\n" - << " varBinormal = normalMatrix * attr_binormal;" - << "\n"; - } else { - vertex() << " varTangent = attr_textan;" - << "\n" - << " varBinormal = attr_binormal;" - << "\n"; - } + if (!hasNPatchTessellation) + vertex() << " varBinormal = normalMatrix * attr_binormal;\n"; + else + vertex() << " varBinormal = attr_binormal;\n"; } void doGenerateVertexColor(const QSSGShaderDefaultMaterialKey &inKey) override @@ -405,6 +377,11 @@ struct QSSGSubsetMaterialVertexPipeline : public QSSGVertexPipelineImpl vertex().append(" varColor = attr_color;"); } + bool hasAttributeInKey(QSSGShaderKeyVertexAttribute::VertexAttributeBits inAttr, const QSSGShaderDefaultMaterialKey &inKey) override + { + return renderer.defaultMaterialShaderKeyProperties().m_vertexAttributes.getBitValue(inAttr, inKey); + } + void endVertexGeneration(bool customShader) override { diff --git a/src/runtimerender/rendererimpl/qssgvertexpipelineimpl_p.h b/src/runtimerender/rendererimpl/qssgvertexpipelineimpl_p.h index 9852bc1b4..db3c76507 100644 --- a/src/runtimerender/rendererimpl/qssgvertexpipelineimpl_p.h +++ b/src/runtimerender/rendererimpl/qssgvertexpipelineimpl_p.h @@ -44,6 +44,7 @@ #include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterialshadergenerator_p.h> #include <QtQuick3DRuntimeRender/private/qssgrendertessmodevalues_p.h> +#include <QtQuick3DRuntimeRender/private/qssgrendershaderkeys_p.h> #include <QtCore/QSharedPointer> @@ -236,12 +237,21 @@ struct QSSGVertexPipelineImpl : public QSSGDefaultMaterialVertexPipelineInterfac Q_ASSERT(inUVSet == 0 || inUVSet == 1); - if (inUVSet == 0) - addInterpolationParameter("varTexCoord0", "vec2"); - else if (inUVSet == 1) - addInterpolationParameter("varTexCoord1", "vec2"); - - doGenerateUVCoords(inKey, inUVSet); + if (inUVSet == 0) { + if (hasAttributeInKey(QSSGShaderKeyVertexAttribute::TexCoord0, inKey)) { + addInterpolationParameter("varTexCoord0", "vec2"); + doGenerateUVCoords(inUVSet); + } else { + fragment() << " vec2 varTexCoord0 = vec2(0.0);\n"; + } + } else if (inUVSet == 1) { + if (hasAttributeInKey(QSSGShaderKeyVertexAttribute::TexCoord1, inKey)) { + addInterpolationParameter("varTexCoord1", "vec2"); + doGenerateUVCoords(inUVSet); + } else { + fragment() << " vec2 varTexCoord1 = vec2(0.0);\n"; + } + } } void generateEnvMapReflection(const QSSGShaderDefaultMaterialKey &inKey) override { @@ -284,8 +294,14 @@ struct QSSGVertexPipelineImpl : public QSSGDefaultMaterialVertexPipelineInterfac { if (setCode(GenerationFlag::WorldNormal)) return; - addInterpolationParameter("varNormal", "vec3"); - doGenerateWorldNormal(inKey); + + if (hasAttributeInKey(QSSGShaderKeyVertexAttribute::Normal, inKey)) { + addInterpolationParameter("varNormal", "vec3"); + doGenerateWorldNormal(); + } else { + generateWorldPosition(); + fragment().append(" vec3 varNormal = cross(dFdx(varWorldPos), dFdy(varWorldPos));"); + } fragment().append(" vec3 world_normal = normalize( varNormal );"); } void generateObjectNormal() override @@ -310,11 +326,26 @@ struct QSSGVertexPipelineImpl : public QSSGDefaultMaterialVertexPipelineInterfac { if (setCode(GenerationFlag::TangentBinormal)) return; - addInterpolationParameter("varTangent", "vec3"); - addInterpolationParameter("varBinormal", "vec3"); - doGenerateVarTangentAndBinormal(inKey); - fragment() << " vec3 tangent = normalize(varTangent);\n" - << " vec3 binormal = normalize(varBinormal);\n"; + + // I assume that there is no mesh having only binormal without tangent + // since it is an abnormal case + if (hasAttributeInKey(QSSGShaderKeyVertexAttribute::Tangent, inKey)) { + const bool hasBinormal = hasAttributeInKey(QSSGShaderKeyVertexAttribute::Binormal, inKey); + addInterpolationParameter("varTangent", "vec3"); + doGenerateVarTangent(); + fragment() << " vec3 tangent = normalize(varTangent);\n"; + + if (hasBinormal) { + addInterpolationParameter("varBinormal", "vec3"); + doGenerateVarBinormal(); + fragment() << " vec3 binormal = normalize(varBinormal);\n"; + } else { + fragment() << " vec3 binormal = vec3(0.0);\n"; + } + } else { + fragment() << " vec3 tangent = vec3(0.0);\n" + << " vec3 binormal = vec3(0.0);\n"; + } } void generateVertexColor(const QSSGShaderDefaultMaterialKey &inKey) override { @@ -376,12 +407,19 @@ struct QSSGVertexPipelineImpl : public QSSGDefaultMaterialVertexPipelineInterfac virtual QSSGShaderStageGeneratorInterface &activeStage() = 0; virtual void addInterpolationParameter(const QByteArray &inParamName, const QByteArray &inParamType) = 0; - virtual void doGenerateUVCoords(const QSSGShaderDefaultMaterialKey &inKey, quint32 inUVSet) = 0; - virtual void doGenerateWorldNormal(const QSSGShaderDefaultMaterialKey &inKey) = 0; + virtual void doGenerateUVCoords(quint32 inUVSet) = 0; + virtual void doGenerateWorldNormal() = 0; virtual void doGenerateObjectNormal() = 0; virtual void doGenerateWorldPosition() = 0; - virtual void doGenerateVarTangentAndBinormal(const QSSGShaderDefaultMaterialKey &inKey) = 0; + virtual void doGenerateVarTangent() = 0; + virtual void doGenerateVarBinormal() = 0; virtual void doGenerateVertexColor(const QSSGShaderDefaultMaterialKey &inKey) = 0; + virtual bool hasAttributeInKey(QSSGShaderKeyVertexAttribute::VertexAttributeBits inAttr, const QSSGShaderDefaultMaterialKey &inKey) { + // it returns true by default + Q_UNUSED(inAttr) + Q_UNUSED(inKey) + return true; + } }; QT_END_NAMESPACE -- GitLab