diff options
Diffstat (limited to 'src/runtimerender/Qt3DSRenderShaderCodeGenerator.cpp')
-rw-r--r-- | src/runtimerender/Qt3DSRenderShaderCodeGenerator.cpp | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/src/runtimerender/Qt3DSRenderShaderCodeGenerator.cpp b/src/runtimerender/Qt3DSRenderShaderCodeGenerator.cpp new file mode 100644 index 0000000..d84c37d --- /dev/null +++ b/src/runtimerender/Qt3DSRenderShaderCodeGenerator.cpp @@ -0,0 +1,526 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#include "Qt3DSRenderShaderCodeGenerator.h" + +using namespace qt3ds::render; + +using eastl::make_pair; + +SShaderCodeGeneratorBase::SShaderCodeGeneratorBase(IStringTable &inStringTable, + NVAllocatorCallback &alloc, + qt3ds::render::NVRenderContextType ctxType) + : m_StringTable(inStringTable) + , m_Codes(alloc, "SShaderCodeGenerator::m_Codes") + , m_Includes(alloc, "SShaderCodeGenerator::m_Includes") + , m_Uniforms(alloc, "SShaderCodeGenerator::m_Uniforms") + , m_ConstantBuffers(alloc, "SShaderCodeGenerator::m_ConstantBuffers") + , m_ConstantBufferParams(alloc, "SShaderCodeGenerator::m_ConstantBufferParams") + , m_Attributes(alloc, "SShaderCodeGenerator::m_Uniforms") + , m_RenderContextType(ctxType) +{ +} +void SShaderCodeGeneratorBase::Begin() +{ + m_Uniforms.clear(); + GetVaryings().clear(); + m_Attributes.clear(); + m_Includes.clear(); + m_Codes.clear(); + m_FinalShaderBuilder.clear(); + m_CodeBuilder.clear(); + m_ConstantBuffers.clear(); + m_ConstantBufferParams.clear(); +} +void SShaderCodeGeneratorBase::Append(const char *data) +{ + m_CodeBuilder.append(data); + m_CodeBuilder.append("\n"); +} +// don't add the newline +void SShaderCodeGeneratorBase::AppendPartial(const char *data) +{ + m_CodeBuilder.append(data); +} +void SShaderCodeGeneratorBase::AddUniform(const char *name, const char *type) +{ + m_Uniforms.insert(make_pair(m_StringTable.RegisterStr(name), m_StringTable.RegisterStr(type))); +} +void SShaderCodeGeneratorBase::AddUniform(TStrType &name, const char *type) +{ + AddUniform(name.c_str(), type); +} + +void SShaderCodeGeneratorBase::AddConstantBuffer(const char *name, const char *layout) +{ + m_ConstantBuffers.insert( + make_pair(m_StringTable.RegisterStr(name), m_StringTable.RegisterStr(layout))); +} +void SShaderCodeGeneratorBase::AddConstantBufferParam(const char *cbName, const char *paramName, + const char *type) +{ + TParamPair theParamPair(m_StringTable.RegisterStr(paramName), m_StringTable.RegisterStr(type)); + TConstantBufferParamPair theBufferParamPair(m_StringTable.RegisterStr(cbName), theParamPair); + m_ConstantBufferParams.push_back(theBufferParamPair); +} +void SShaderCodeGeneratorBase::AddAttribute(const char *name, const char *type) +{ + m_Attributes.insert( + make_pair(m_StringTable.RegisterStr(name), m_StringTable.RegisterStr(type))); +} +void SShaderCodeGeneratorBase::AddAttribute(TStrType &name, const char *type) +{ + AddAttribute(name.c_str(), type); +} +void SShaderCodeGeneratorBase::AddVarying(const char *name, const char *type) +{ + GetVaryings().insert( + make_pair(m_StringTable.RegisterStr(name), m_StringTable.RegisterStr(type))); +} +void SShaderCodeGeneratorBase::AddVarying(TStrType &name, const char *type) +{ + AddVarying(name.c_str(), type); +} +void SShaderCodeGeneratorBase::AddLocalVariable(const char *name, const char *type, int tabCount) +{ + for (; tabCount >= 0; --tabCount) + m_CodeBuilder.append("\t"); + m_CodeBuilder.append(type); + m_CodeBuilder.append(" "); + m_CodeBuilder.append(name); + m_CodeBuilder.append(";\n"); +} + +void SShaderCodeGeneratorBase::AddInclude(const char *name) +{ + m_Includes.insert(m_StringTable.RegisterStr(name)); +} +void SShaderCodeGeneratorBase::AddInclude(TStrType &name) +{ + AddInclude(name.c_str()); +} +void SShaderCodeGeneratorBase::AddLocalVariable(TStrType &name, const char *type, int tabCount) +{ + AddLocalVariable(name.c_str(), type, tabCount); +} +bool SShaderCodeGeneratorBase::HasCode(Enum value) +{ + return m_Codes.contains(value); +} +void SShaderCodeGeneratorBase::SetCode(Enum value) +{ + m_Codes.insert((QT3DSU32)value); +} + +void SShaderCodeGeneratorBase::SetupWorldPosition() +{ + if (!HasCode(WorldPosition)) { + SetCode(WorldPosition); + AddUniform("model_matrix", "mat4"); + Append("\tvec3 varWorldPos = (model_matrix * vec4(attr_pos, 1.0)).xyz;"); + } +} + +void SShaderCodeGeneratorBase::GenerateViewVector() +{ + if (!HasCode(ViewVector)) { + SetCode(ViewVector); + SetupWorldPosition(); + AddInclude("viewProperties.glsllib"); + Append("\tvec3 view_vector = normalize(camera_position - varWorldPos);"); + } +} + +void SShaderCodeGeneratorBase::GenerateWorldNormal() +{ + if (!HasCode(WorldNormal)) { + SetCode(WorldNormal); + AddAttribute("attr_norm", "vec3"); + AddUniform("normal_matrix", "mat3"); + Append("\tvec3 world_normal = normalize(normal_matrix * objectNormal).xyz;"); + } +} + +void SShaderCodeGeneratorBase::GenerateEnvMapReflection(SShaderCodeGeneratorBase &inFragmentShader) +{ + if (!HasCode(EnvMapReflection)) { + SetCode(EnvMapReflection); + SetupWorldPosition(); + GenerateWorldNormal(); + AddInclude("viewProperties.glsllib"); + AddVarying("var_object_to_camera", "vec3"); + Append("\tvar_object_to_camera = normalize( varWorldPos - camera_position );"); + // World normal cannot be relied upon in the vertex shader because of bump maps. + inFragmentShader.Append("\tvec3 environment_map_reflection = reflect( " + "vec3(var_object_to_camera.x, var_object_to_camera.y, " + "var_object_to_camera.z), world_normal.xyz );"); + inFragmentShader.Append("\tenvironment_map_reflection *= vec3( 0.5, 0.5, 0 );"); + inFragmentShader.Append("\tenvironment_map_reflection += vec3( 0.5, 0.5, 1.0 );"); + } +} + +void SShaderCodeGeneratorBase::GenerateUVCoords() +{ + if (!HasCode(UVCoords)) { + SetCode(UVCoords); + AddAttribute("attr_uv0", "vec2"); + Append("\tvec2 uv_coords = attr_uv0;"); + } +} + +void SShaderCodeGeneratorBase::GenerateTextureSwizzle(NVRenderTextureSwizzleMode::Enum swizzleMode, + eastl::basic_string<char8_t> &texSwizzle, + eastl::basic_string<char8_t> &lookupSwizzle) +{ + qt3ds::render::NVRenderContextType deprecatedContextFlags(NVRenderContextValues::GL2 + | NVRenderContextValues::GLES2); + + if (!(m_RenderContextType & deprecatedContextFlags)) { + switch (swizzleMode) { + case NVRenderTextureSwizzleMode::L8toR8: + case NVRenderTextureSwizzleMode::L16toR16: + texSwizzle.append(".rgb"); + lookupSwizzle.append(".rrr"); + break; + case NVRenderTextureSwizzleMode::L8A8toRG8: + texSwizzle.append(".rgba"); + lookupSwizzle.append(".rrrg"); + break; + case NVRenderTextureSwizzleMode::A8toR8: + texSwizzle.append(".a"); + lookupSwizzle.append(".r"); + break; + default: + break; + } + } +} + +void SShaderCodeGeneratorBase::GenerateShadedWireframeBase() +{ + // how this all work see + // http://developer.download.nvidia.com/SDK/10.5/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf + 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 SShaderCodeGeneratorBase::AddShaderItemMap(const char *itemType, + const TStrTableStrMap &itemMap) +{ + m_FinalShaderBuilder.append("\n"); + + for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); iter != end; + ++iter) { + m_FinalShaderBuilder.append(itemType); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->second); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->first); + m_FinalShaderBuilder.append(";\n"); + } +} + +void SShaderCodeGeneratorBase::AddShaderConstantBufferItemMap( + const char *itemType, const TStrTableStrMap &cbMap, TConstantBufferParamArray cbParamsArray) +{ + m_FinalShaderBuilder.append("\n"); + + // iterate over all constant buffers + for (TStrTableStrMap::const_iterator iter = cbMap.begin(), end = cbMap.end(); iter != end; + ++iter) { + m_FinalShaderBuilder.append(iter->second); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(itemType); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->first); + m_FinalShaderBuilder.append(" {\n"); + // iterate over all param entries and add match + for (TConstantBufferParamArray::const_iterator iter1 = cbParamsArray.begin(), + end = cbParamsArray.end(); + iter1 != end; ++iter1) { + if (iter1->first == iter->first) { + m_FinalShaderBuilder.append(iter1->second.second); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter1->second.first); + m_FinalShaderBuilder.append(";\n"); + } + } + + m_FinalShaderBuilder.append("};\n"); + } +} + +const char *SShaderCodeGeneratorBase::BuildShaderSource() +{ + for (nvhash_set<CRegisteredString>::const_iterator iter = m_Includes.begin(), + end = m_Includes.end(); + iter != end; ++iter) { + m_FinalShaderBuilder.append("#include \""); + m_FinalShaderBuilder.append(iter->c_str()); + m_FinalShaderBuilder.append("\"\n"); + } + AddShaderItemMap("attribute", m_Attributes); + AddShaderItemMap("uniform", m_Uniforms); + AddShaderConstantBufferItemMap("uniform", m_ConstantBuffers, m_ConstantBufferParams); + AddShaderItemMap("varying", GetVaryings()); + m_FinalShaderBuilder.append("\n"); + m_FinalShaderBuilder.append(m_CodeBuilder.c_str()); + return m_FinalShaderBuilder.c_str(); +} +SShaderCodeGeneratorBase &SShaderCodeGeneratorBase::operator<<(const char *data) +{ + m_CodeBuilder.append(data); + return *this; +} +SShaderCodeGeneratorBase &SShaderCodeGeneratorBase::operator<<(const TStrType &data) +{ + m_CodeBuilder.append(data); + return *this; +} + +SShaderCodeGeneratorBase &SShaderCodeGeneratorBase::operator<<(const SEndlType & /*data*/) +{ + m_CodeBuilder.append("\n"); + return *this; +} + +SShaderVertexCodeGenerator::SShaderVertexCodeGenerator(IStringTable &inStringTable, + NVAllocatorCallback &alloc, + qt3ds::render::NVRenderContextType ctxType) + : SShaderCodeGeneratorBase(inStringTable, alloc, ctxType) + , m_Varyings(alloc, "SShaderVertexCodeGenerator::m_Varyings") +{ +} +TStrTableStrMap &SShaderVertexCodeGenerator::GetVaryings() +{ + return m_Varyings; +} + +SShaderTessControlCodeGenerator::SShaderTessControlCodeGenerator( + SShaderVertexCodeGenerator &vert, NVAllocatorCallback &alloc, + qt3ds::render::NVRenderContextType ctxType) + : SShaderCodeGeneratorBase(vert.m_StringTable, alloc, ctxType) + , m_VertGenerator(vert) + , m_Varyings(alloc, "SShaderTessControlCodeGenerator::m_Varyings") +{ +} + +// overwritten from base +void SShaderTessControlCodeGenerator::AddShaderItemMap(const char *itemType, + const TStrTableStrMap &itemMap) +{ + eastl::string extVtx(""); + eastl::string extTC(""); + eastl::string type(itemType); + if (!type.compare("varying")) { + extVtx = "[]"; + extTC = "TC[]"; + itemType = "attribute"; + } + + m_FinalShaderBuilder.append("\n"); + + for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); iter != end; + ++iter) { + m_FinalShaderBuilder.append(itemType); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->second); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->first); + m_FinalShaderBuilder.append(extVtx.c_str()); + m_FinalShaderBuilder.append(";\n"); + } + + // if this is varyings write output of tess control shader + if (!extVtx.empty()) { + m_FinalShaderBuilder.append("\n"); + itemType = "varying"; + + for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); + iter != end; ++iter) { + m_FinalShaderBuilder.append(itemType); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->second); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->first); + m_FinalShaderBuilder.append(extTC.c_str()); + m_FinalShaderBuilder.append(";\n"); + } + } +} +TStrTableStrMap &SShaderTessControlCodeGenerator::GetVaryings() +{ + return m_VertGenerator.m_Varyings; +} + +SShaderTessEvalCodeGenerator::SShaderTessEvalCodeGenerator(SShaderTessControlCodeGenerator &tc, + NVAllocatorCallback &alloc, + qt3ds::render::NVRenderContextType ctxType) + : SShaderCodeGeneratorBase(tc.m_StringTable, alloc, ctxType) + , m_TessControlGenerator(tc) + , m_hasGeometryStage(false) +{ +} +// overwritten from base +void SShaderTessEvalCodeGenerator::AddShaderItemMap(const char *itemType, + const TStrTableStrMap &itemMap) +{ + eastl::string extTC(""); + eastl::string extTE(""); + eastl::string type(itemType); + if (!type.compare("varying")) { + extTC = "TC[]"; + itemType = "attribute"; + } + if (m_hasGeometryStage) { + extTE = "TE"; + } + + m_FinalShaderBuilder.append("\n"); + + for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); iter != end; + ++iter) { + m_FinalShaderBuilder.append(itemType); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->second); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->first); + m_FinalShaderBuilder.append(extTC.c_str()); + m_FinalShaderBuilder.append(";\n"); + } + + // if this are varyings write output of tess eval shader + if (!extTC.empty()) { + m_FinalShaderBuilder.append("\n"); + itemType = "varying"; + + for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); + iter != end; ++iter) { + m_FinalShaderBuilder.append(itemType); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->second); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->first); + m_FinalShaderBuilder.append(extTE.c_str()); + m_FinalShaderBuilder.append(";\n"); + } + } +} +TStrTableStrMap &SShaderTessEvalCodeGenerator::GetVaryings() +{ + return m_TessControlGenerator.m_VertGenerator.GetVaryings(); +} +void SShaderTessEvalCodeGenerator::SetGeometryStage(bool hasGeometryStage) +{ + m_hasGeometryStage = hasGeometryStage; +} + +SShaderGeometryCodeGenerator::SShaderGeometryCodeGenerator(SShaderVertexCodeGenerator &vert, + NVAllocatorCallback &alloc, + qt3ds::render::NVRenderContextType ctxType) + : SShaderCodeGeneratorBase(vert.m_StringTable, alloc, ctxType) + , m_VertGenerator(vert) + , m_hasTessellationStage(true) +{ +} + +// overwritten from base +void SShaderGeometryCodeGenerator::AddShaderItemMap(const char *itemType, + const TStrTableStrMap &itemMap) +{ + eastl::string inExt(""); + eastl::string type(itemType); + if (!type.compare("varying")) { + itemType = "attribute"; + if (m_hasTessellationStage) + inExt = "TE[]"; + else + inExt = "[]"; + } + + m_FinalShaderBuilder.append("\n"); + + for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); iter != end; + ++iter) { + m_FinalShaderBuilder.append(itemType); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->second); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->first); + m_FinalShaderBuilder.append(inExt.c_str()); + m_FinalShaderBuilder.append(";\n"); + } + + // if this are varyings write output of geometry shader + if (!type.compare("varying")) { + m_FinalShaderBuilder.append("\n"); + itemType = "varying"; + + for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); + iter != end; ++iter) { + m_FinalShaderBuilder.append(itemType); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->second); + m_FinalShaderBuilder.append(" "); + m_FinalShaderBuilder.append(iter->first); + m_FinalShaderBuilder.append(";\n"); + } + } +} +TStrTableStrMap &SShaderGeometryCodeGenerator::GetVaryings() +{ + return m_VertGenerator.m_Varyings; +} +void SShaderGeometryCodeGenerator::SetTessellationStage(bool hasTessellationStage) +{ + m_hasTessellationStage = hasTessellationStage; +} + +SShaderFragmentCodeGenerator::SShaderFragmentCodeGenerator(SShaderVertexCodeGenerator &vert, + NVAllocatorCallback &alloc, + qt3ds::render::NVRenderContextType ctxType) + : SShaderCodeGeneratorBase(vert.m_StringTable, alloc, ctxType) + , m_VertGenerator(vert) +{ +} +TStrTableStrMap &SShaderFragmentCodeGenerator::GetVaryings() +{ + return m_VertGenerator.m_Varyings; +} |