diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2019-06-03 14:00:07 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2019-06-03 14:01:18 +0300 |
commit | 01cfc8025119609803b3fc00b1e8ca5bc56e84d0 (patch) | |
tree | c41480bbb06377f3a79d13c465a53435cccb9de4 /src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSVertexPipelineImpl.h | |
parent | c36739204786bd90df6e2ef5a8be78c980240bdd (diff) | |
parent | 089d283afb8cde5024e60c29eeeeefc5c3c80543 (diff) |
Merge branch '2.4'
Change-Id: Ib7de8e52a477c06599ced87bb973a5abd25549c4
Diffstat (limited to 'src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSVertexPipelineImpl.h')
-rw-r--r-- | src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSVertexPipelineImpl.h | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSVertexPipelineImpl.h b/src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSVertexPipelineImpl.h new file mode 100644 index 00000000..a9b5e7b2 --- /dev/null +++ b/src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSVertexPipelineImpl.h @@ -0,0 +1,463 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2012 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_VERTEX_PIPELINE_IMPL_H +#define QT3DS_VERTEX_PIPELINE_IMPL_H +#include "Qt3DSRenderDefaultMaterialShaderGenerator.h" + +namespace qt3ds { +namespace render { + // Baseclass for the vertex pipelines to be sure we have consistent implementations. + struct SVertexPipelineImpl : public IDefaultMaterialVertexPipeline + { + struct GenerationFlagValues + { + enum Enum { + UVCoords = 1, + EnvMapReflection = 1 << 1, + ViewVector = 1 << 2, + WorldNormal = 1 << 3, + ObjectNormal = 1 << 4, + WorldPosition = 1 << 5, + TangentBinormal = 1 << 6, + UVCoords1 = 1 << 7, + VertexColor = 1 << 8, + }; + }; + + typedef TStrTableStrMap::const_iterator TParamIter; + typedef NVFlags<GenerationFlagValues::Enum> TGenerationFlags; + + IMaterialShaderGenerator &m_MaterialGenerator; + IShaderProgramGenerator &m_ProgramGenerator; + IStringTable &m_StringTable; + Qt3DSString m_TempString; + + TGenerationFlags m_GenerationFlags; + bool m_Wireframe; + TStrTableStrMap m_InterpolationParameters; + QT3DSU32 m_DisplacementIdx; + SRenderableImage *m_DisplacementImage; + QStringList m_addedFunctions; + + SVertexPipelineImpl(NVAllocatorCallback &inAllocator, IMaterialShaderGenerator &inMaterial, + IShaderProgramGenerator &inProgram, IStringTable &inStringTable, + bool inWireframe // only works if tessellation is true + ) + + : m_MaterialGenerator(inMaterial) + , m_ProgramGenerator(inProgram) + , m_StringTable(inStringTable) + , m_Wireframe(inWireframe) + , m_InterpolationParameters(inAllocator, "m_InterpolationParameters") + , m_DisplacementIdx(0) + , m_DisplacementImage(NULL) + { + } + + // Trues true if the code was *not* set. + bool SetCode(GenerationFlagValues::Enum inCode) + { + if (((QT3DSU32)m_GenerationFlags & inCode) != 0) + return true; + m_GenerationFlags |= inCode; + return false; + } + bool HasCode(GenerationFlagValues::Enum inCode) + { + return ((QT3DSU32)(m_GenerationFlags & inCode)) != 0; + } + IShaderProgramGenerator &ProgramGenerator() { return m_ProgramGenerator; } + IShaderStageGenerator &Vertex() + { + return *ProgramGenerator().GetStage(ShaderGeneratorStages::Vertex); + } + IShaderStageGenerator &TessControl() + { + return *ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl); + } + IShaderStageGenerator &TessEval() + { + return *ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval); + } + IShaderStageGenerator &Geometry() + { + return *ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry); + } + IShaderStageGenerator &Fragment() + { + return *ProgramGenerator().GetStage(ShaderGeneratorStages::Fragment); + } + IMaterialShaderGenerator &MaterialGenerator() { return m_MaterialGenerator; } + + void SetupDisplacement(QT3DSU32 displacementImageIdx, SRenderableImage *displacementImage) + { + m_DisplacementIdx = displacementImageIdx; + m_DisplacementImage = displacementImage; + } + + CRegisteredString Str(const char8_t *inItem) { return m_StringTable.RegisterStr(inItem); } + + bool HasTessellation() const + { + return m_ProgramGenerator.GetEnabledStages() & ShaderGeneratorStages::TessEval; + } + bool HasGeometryStage() const + { + return m_ProgramGenerator.GetEnabledStages() & ShaderGeneratorStages::Geometry; + } + bool HasDisplacment() const { return m_DisplacementImage != NULL; } + + void InitializeWireframeGeometryShader() + { + if (m_Wireframe && ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry) + && ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)) { + IShaderStageGenerator &geometryShader( + *ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry)); + // currently geometry shader is only used for drawing wireframe + if (m_Wireframe) { + geometryShader.AddUniform("viewport_matrix", "mat4"); + geometryShader.AddOutgoing("varEdgeDistance", "vec3"); + geometryShader.Append("layout (triangles) in;"); + geometryShader.Append("layout (triangle_strip, max_vertices = 3) out;"); + geometryShader.Append("void main() {"); + + // how this all work see + // http://developer.download.nvidia.com/SDK/10.5/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf + + geometryShader.Append( + "// project points to screen space\n" + "\tvec3 p0 = vec3(viewport_matrix * (gl_in[0].gl_Position / " + "gl_in[0].gl_Position.w));\n" + "\tvec3 p1 = vec3(viewport_matrix * (gl_in[1].gl_Position / " + "gl_in[1].gl_Position.w));\n" + "\tvec3 p2 = vec3(viewport_matrix * (gl_in[2].gl_Position / " + "gl_in[2].gl_Position.w));\n" + "// compute triangle heights\n" + "\tfloat e1 = length(p1 - p2);\n" + "\tfloat e2 = length(p2 - p0);\n" + "\tfloat e3 = length(p1 - p0);\n" + "\tfloat alpha = acos( (e2*e2 + e3*e3 - e1*e1) / (2.0*e2*e3) );\n" + "\tfloat beta = acos( (e1*e1 + e3*e3 - e2*e2) / (2.0*e1*e3) );\n" + "\tfloat ha = abs( e3 * sin( beta ) );\n" + "\tfloat hb = abs( e3 * sin( alpha ) );\n" + "\tfloat hc = abs( e2 * sin( alpha ) );\n"); + } + } + } + + void FinalizeWireframeGeometryShader() + { + IShaderStageGenerator &geometryShader( + *ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry)); + + if (m_Wireframe == true && ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry) + && ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)) { + const char8_t *theExtension("TE["); + // we always assume triangles + for (int i = 0; i < 3; i++) { + char buf[10]; + sprintf(buf, "%d", i); + for (TStrTableStrMap::const_iterator iter = m_InterpolationParameters.begin(), + end = m_InterpolationParameters.end(); + iter != end; ++iter) { + geometryShader << "\t" << iter->first.c_str() << " = " + << iter->first.c_str() << theExtension << buf << "];\n"; + } + + geometryShader << "\tgl_Position = gl_in[" << buf << "].gl_Position;\n"; + // the triangle distance is interpolated through the shader stage + if (i == 0) + geometryShader << "\n\tvarEdgeDistance = vec3(ha*" + << "gl_in[" << buf << "].gl_Position.w, 0.0, 0.0);\n"; + else if (i == 1) + geometryShader << "\n\tvarEdgeDistance = vec3(0.0, hb*" + << "gl_in[" << buf << "].gl_Position.w, 0.0);\n"; + else if (i == 2) + geometryShader << "\n\tvarEdgeDistance = vec3(0.0, 0.0, hc*" + << "gl_in[" << buf << "].gl_Position.w);\n"; + + // submit vertex + geometryShader << "\tEmitVertex();\n"; + } + // end primitive + geometryShader << "\tEndPrimitive();\n"; + } + } + + virtual void SetupTessIncludes(ShaderGeneratorStages::Enum inStage, + TessModeValues::Enum inTessMode) + { + IShaderStageGenerator &tessShader(*ProgramGenerator().GetStage(inStage)); + + // depending on the selected tessellation mode chose program + switch (inTessMode) { + case TessModeValues::TessPhong: + tessShader.AddInclude("tessellationPhong.glsllib"); + break; + case TessModeValues::TessNPatch: + tessShader.AddInclude("tessellationNPatch.glsllib"); + break; + default: + QT3DS_ASSERT(false); // fallthrough intentional + case TessModeValues::TessLinear: + tessShader.AddInclude("tessellationLinear.glsllib"); + break; + } + } + + void GenerateUVCoords(QT3DSU32 inUVSet = 0) override + { + if (inUVSet == 0 && SetCode(GenerationFlagValues::UVCoords)) + return; + if (inUVSet == 1 && SetCode(GenerationFlagValues::UVCoords1)) + return; + + QT3DS_ASSERT(inUVSet == 0 || inUVSet == 1); + + if (inUVSet == 0) + AddInterpolationParameter("varTexCoord0", "vec2"); + else if (inUVSet == 1) + AddInterpolationParameter("varTexCoord1", "vec2"); + + DoGenerateUVCoords(inUVSet); + } + void GenerateEnvMapReflection() override + { + if (SetCode(GenerationFlagValues::EnvMapReflection)) + return; + + GenerateWorldPosition(); + GenerateWorldNormal(); + IShaderStageGenerator &activeGenerator(ActiveStage()); + activeGenerator.AddInclude("viewProperties.glsllib"); + AddInterpolationParameter("var_object_to_camera", "vec3"); + activeGenerator.Append("\tvar_object_to_camera = normalize( local_model_world_position " + "- camera_position );"); + // World normal cannot be relied upon in the vertex shader because of bump maps. + Fragment().Append("\tvec3 environment_map_reflection = reflect( " + "normalize(var_object_to_camera), world_normal.xyz );"); + Fragment().Append("\tenvironment_map_reflection *= vec3( 0.5, 0.5, 0 );"); + Fragment().Append("\tenvironment_map_reflection += vec3( 0.5, 0.5, 1.0 );"); + } + void GenerateViewVector() override + { + if (SetCode(GenerationFlagValues::ViewVector)) + return; + GenerateWorldPosition(); + IShaderStageGenerator &activeGenerator(ActiveStage()); + activeGenerator.AddInclude("viewProperties.glsllib"); + AddInterpolationParameter("varViewVector", "vec3"); + activeGenerator.Append("\tvec3 local_view_vector = normalize(camera_position - " + "local_model_world_position);"); + AssignOutput("varViewVector", "local_view_vector"); + Fragment() << "\tvec3 view_vector = normalize(varViewVector);" << Endl; + } + + // fragment shader expects varying vertex normal + // lighting in vertex pipeline expects world_normal + void GenerateWorldNormal() override + { + if (SetCode(GenerationFlagValues::WorldNormal)) + return; + AddInterpolationParameter("varNormal", "vec3"); + DoGenerateWorldNormal(); + Fragment().Append("\tvec3 world_normal = normalize( varNormal );"); + } + void GenerateObjectNormal() override + { + if (SetCode(GenerationFlagValues::ObjectNormal)) + return; + DoGenerateObjectNormal(); + Fragment().Append("\tvec3 object_normal = normalize(varObjectNormal);"); + } + void GenerateWorldPosition() override + { + if (SetCode(GenerationFlagValues::WorldPosition)) + return; + + ActiveStage().AddUniform("model_matrix", "mat4"); + AddInterpolationParameter("varWorldPos", "vec3"); + DoGenerateWorldPosition(); + + AssignOutput("varWorldPos", "local_model_world_position"); + } + void GenerateVarTangentAndBinormal() override + { + if (SetCode(GenerationFlagValues::TangentBinormal)) + return; + AddInterpolationParameter("varTangent", "vec3"); + AddInterpolationParameter("varBinormal", "vec3"); + DoGenerateVarTangentAndBinormal(); + Fragment() << "\tvec3 tangent = normalize(varTangent);" << Endl + << "\tvec3 binormal = normalize(varBinormal);" << Endl; + } + void GenerateVertexColor() override + { + if (SetCode(GenerationFlagValues::VertexColor)) + return; + AddInterpolationParameter("varColor", "vec3"); + DoGenerateVertexColor(); + Fragment().Append("\tvec3 vertColor = varColor;"); + } + + bool HasActiveWireframe() override { return m_Wireframe; } + + // IShaderStageGenerator interface + void AddIncoming(const char8_t *name, const char8_t *type) override + { + ActiveStage().AddIncoming(name, type); + } + void AddIncoming(const TStrType &name, const char8_t *type) override + { + AddIncoming(name.c_str(), type); + } + void AddIncoming(const QString &name, const char8_t *type) override + { + AddIncoming(name.toUtf8().constData(), type); + } + + void AddOutgoing(const char8_t *name, const char8_t *type) override + { + AddInterpolationParameter(name, type); + } + void AddOutgoing(const TStrType &name, const char8_t *type) override + { + AddOutgoing(name.c_str(), type); + } + void AddOutgoing(const QString &name, const char8_t *type) override + { + AddOutgoing(name.toUtf8().constData(), type); + } + void AddUniform(const QString &name, const char8_t *type) override + { + AddUniform(name.toUtf8().constData(), type); + } + + void AddUniform(const char8_t *name, const char8_t *type) override + { + ActiveStage().AddUniform(name, type); + } + void AddUniform(const TStrType &name, const char8_t *type) override + { + AddUniform(name.c_str(), type); + } + + void AddInclude(const char8_t *name) override { ActiveStage().AddInclude(name); } + void AddInclude(const TStrType &name) override { AddInclude(name.c_str()); } + void AddInclude(const QString &name) override + { + QByteArray arr = name.toLatin1(); + AddInclude(arr.data()); + } + + void AddFunction(const QString &functionName) override + { + if (!m_addedFunctions.contains(functionName)) { + m_addedFunctions.push_back(functionName); + QString includeName; + QTextStream stream(&includeName); + stream << "func" << functionName << ".glsllib"; + AddInclude(includeName); + } + } + + void AddConstantBuffer(const char *name, const char *layout) override + { + ActiveStage().AddConstantBuffer(name, layout); + } + void AddConstantBuffer(const QString &name, const char *layout) override + { + AddConstantBuffer(name.toUtf8().constData(), layout); + } + + void AddConstantBufferParam(const char *cbName, const char *paramName, + const char *type) override + { + ActiveStage().AddConstantBufferParam(cbName, paramName, type); + } + void AddConstantBufferParam(const QString &cbName, const QString ¶mName, + const char *type) override + { + AddConstantBufferParam(cbName.toUtf8().constData(), + paramName.toUtf8().constData(), type); + } + + IShaderStageGenerator &operator<<(const char *data) override + { + ActiveStage() << data; + return *this; + } + IShaderStageGenerator &operator<<(const TStrType &data) override + { + ActiveStage() << data; + return *this; + } + IShaderStageGenerator &operator<<(const QString &data) override + { + ActiveStage() << data; + return *this; + } + IShaderStageGenerator &operator<<(const SEndlType &data) override + { + ActiveStage() << data; + return *this; + } + void Append(const char *data) override { ActiveStage().Append(data); } + void AppendPartial(const char *data) override { ActiveStage().Append(data); } + + ShaderGeneratorStages::Enum Stage() const override + { + return const_cast<SVertexPipelineImpl *>(this)->ActiveStage().Stage(); + } + + void BeginVertexGeneration(QT3DSU32 displacementImageIdx, + SRenderableImage *displacementImage) override = 0; + void AssignOutput(const char8_t *inVarName, const char8_t *inVarValueExpr) override = 0; + void EndVertexGeneration(bool customShader) override = 0; + + void BeginFragmentGeneration() override = 0; + void EndFragmentGeneration(bool customShader) override = 0; + + virtual IShaderStageGenerator &ActiveStage() = 0; + virtual void AddInterpolationParameter(const char8_t *inParamName, + const char8_t *inParamType) = 0; + + virtual void DoGenerateUVCoords(QT3DSU32 inUVSet) = 0; + virtual void DoGenerateWorldNormal() = 0; + virtual void DoGenerateObjectNormal() = 0; + virtual void DoGenerateWorldPosition() = 0; + virtual void DoGenerateVarTangentAndBinormal() = 0; + virtual void DoGenerateVertexColor() = 0; + }; +} +} + +#endif |