summaryrefslogtreecommitdiffstats
path: root/src/Runtime/Source/runtimerender/Qt3DSRenderShaderKeys.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/Source/runtimerender/Qt3DSRenderShaderKeys.h')
-rw-r--r--src/Runtime/Source/runtimerender/Qt3DSRenderShaderKeys.h802
1 files changed, 802 insertions, 0 deletions
diff --git a/src/Runtime/Source/runtimerender/Qt3DSRenderShaderKeys.h b/src/Runtime/Source/runtimerender/Qt3DSRenderShaderKeys.h
new file mode 100644
index 00000000..5d02e414
--- /dev/null
+++ b/src/Runtime/Source/runtimerender/Qt3DSRenderShaderKeys.h
@@ -0,0 +1,802 @@
+/****************************************************************************
+**
+** 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_RENDER_SHADER_KEY_H
+#define QT3DS_RENDER_SHADER_KEY_H
+#include "Qt3DSRender.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "EASTL/string.h"
+#include "foundation/StringConversionImpl.h"
+#include "Qt3DSRenderDefaultMaterial.h"
+#include "Qt3DSRenderTessModeValues.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+namespace qt3ds {
+namespace render {
+ // We have an ever expanding set of properties we like to hash into one or more 32 bit
+ // quantities.
+ // Furthermore we would like this set of properties to be convertable to string
+ // So the shader cache file itself is somewhat human readable/diagnosable.
+ // To do this we create a set of objects that act as properties to the master shader key.
+ // These objects are tallied in order to figure out their actual offset into the shader key's
+ // data store. They are also run through in order to create the string shader cache key.
+
+ struct SShaderKeyPropertyBase
+ {
+ const char *m_Name;
+ QT3DSU32 m_Offset;
+ SShaderKeyPropertyBase(const char *name = "")
+ : m_Name(name)
+ , m_Offset(0)
+ {
+ }
+ QT3DSU32 GetOffset() const { return m_Offset; }
+ void SetOffset(QT3DSU32 of) { m_Offset = of; }
+
+ template <QT3DSU32 TBitWidth>
+ QT3DSU32 GetMaskTemplate() const
+ {
+ QT3DSU32 bit = m_Offset % 32;
+ QT3DSU32 startValue = (1 << TBitWidth) - 1;
+ QT3DSU32 mask = startValue << bit;
+ return mask;
+ }
+
+ QT3DSU32 GetIdx() const { return m_Offset / 32; }
+ protected:
+ void InternalToString(eastl::string &ioStr, const char *inBuffer) const
+ {
+ ioStr.append(m_Name);
+ ioStr.append("=");
+ ioStr.append(inBuffer);
+ }
+
+ static void InternalToString(eastl::string &ioStr, const char *name, bool inValue)
+ {
+ if (inValue) {
+ ioStr.append(name);
+ ioStr.append("=");
+ ioStr.append(inValue ? "true" : "false");
+ }
+ }
+ };
+
+ struct SShaderKeyBoolean : public SShaderKeyPropertyBase
+ {
+ enum {
+ BitWidth = 1,
+ };
+
+ SShaderKeyBoolean(const char *name = "")
+ : SShaderKeyPropertyBase(name)
+ {
+ }
+
+ QT3DSU32 GetMask() const { return GetMaskTemplate<BitWidth>(); }
+ void SetValue(NVDataRef<QT3DSU32> inDataStore, bool inValue) const
+ {
+ QT3DSU32 idx = GetIdx();
+ QT3DS_ASSERT(inDataStore.size() > idx);
+ QT3DSU32 mask = GetMask();
+ QT3DSU32 &target = inDataStore[idx];
+ if (inValue == true) {
+ target = target | mask;
+ } else {
+ mask = ~mask;
+ target = target & mask;
+ }
+ }
+
+ bool GetValue(NVConstDataRef<QT3DSU32> inDataStore) const
+ {
+ QT3DSU32 idx = GetIdx();
+ QT3DSU32 mask = GetMask();
+ const QT3DSU32 &target = inDataStore[idx];
+ return (target & mask) ? true : false;
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ bool isHigh = GetValue(inKeySet);
+ InternalToString(ioStr, m_Name, isHigh);
+ }
+ };
+
+ template <QT3DSU32 TBitWidth>
+ struct SShaderKeyUnsigned : public SShaderKeyPropertyBase
+ {
+ enum {
+ BitWidth = TBitWidth,
+ };
+ SShaderKeyUnsigned(const char *name = "")
+ : SShaderKeyPropertyBase(name)
+ {
+ }
+ QT3DSU32 GetMask() const { return GetMaskTemplate<BitWidth>(); }
+ void SetValue(NVDataRef<QT3DSU32> inDataStore, QT3DSU32 inValue) const
+ {
+ QT3DSU32 startValue = (1 << TBitWidth) - 1;
+ // Ensure inValue is within range of bit width.
+ inValue = inValue & startValue;
+ QT3DSU32 bit = m_Offset % 32;
+ QT3DSU32 mask = GetMask();
+ QT3DSU32 idx = GetIdx();
+ inValue = inValue << bit;
+ QT3DSU32 &target = inDataStore[idx];
+ // Get rid of existing value
+ QT3DSU32 inverseMask = ~mask;
+ target = target & inverseMask;
+ target = target | inValue;
+ }
+
+ QT3DSU32 GetValue(NVConstDataRef<QT3DSU32> inDataStore) const
+ {
+ QT3DSU32 idx = GetIdx();
+ QT3DSU32 bit = m_Offset % 32;
+ QT3DSU32 mask = GetMask();
+ const QT3DSU32 &target = inDataStore[idx];
+
+ QT3DSU32 retval = target & mask;
+ retval = retval >> bit;
+ return retval;
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ QT3DSU32 value = GetValue(inKeySet);
+ char buf[64];
+ StringConversion<QT3DSU32>().ToStr(value, toDataRef(buf, 64));
+ InternalToString(ioStr, buf);
+ }
+ };
+
+ struct SShaderKeyTessellation : public SShaderKeyUnsigned<4>
+ {
+ enum TessellationBits {
+ noTessellation = 1 << 0,
+ linearTessellation = 1 << 1,
+ phongTessellation = 1 << 2,
+ npatchTessellation = 1 << 3
+ };
+
+ SShaderKeyTessellation(const char *name = "")
+ : SShaderKeyUnsigned<4>(name)
+ {
+ }
+
+ bool GetBitValue(TessellationBits swizzleBit, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return (GetValue(inKeySet) & swizzleBit) ? true : false;
+ }
+
+ void SetBitValue(TessellationBits swizzleBit, bool inValue, NVDataRef<QT3DSU32> inKeySet)
+ {
+ QT3DSU32 theValue = GetValue(inKeySet);
+ QT3DSU32 mask = swizzleBit;
+ if (inValue) {
+ theValue = theValue | mask;
+ } else {
+ mask = ~mask;
+ theValue = theValue & mask;
+ }
+ SetValue(inKeySet, theValue);
+ }
+
+ void SetTessellationMode(NVDataRef<QT3DSU32> inKeySet, TessModeValues::Enum tessellationMode,
+ bool val)
+ {
+ switch (tessellationMode) {
+ case TessModeValues::NoTess:
+ SetBitValue(noTessellation, val, inKeySet);
+ break;
+ case TessModeValues::TessLinear:
+ SetBitValue(linearTessellation, val, inKeySet);
+ break;
+ case TessModeValues::TessNPatch:
+ SetBitValue(npatchTessellation, val, inKeySet);
+ break;
+ case TessModeValues::TessPhong:
+ SetBitValue(phongTessellation, val, inKeySet);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ bool IsNoTessellation(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(noTessellation, inKeySet);
+ }
+ void SetNoTessellation(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(noTessellation, val, inKeySet);
+ }
+
+ bool IsLinearTessellation(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(linearTessellation, inKeySet);
+ }
+ void SetLinearTessellation(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(linearTessellation, val, inKeySet);
+ }
+
+ bool IsNPatchTessellation(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(npatchTessellation, inKeySet);
+ }
+ void SetNPatchTessellation(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(npatchTessellation, val, inKeySet);
+ }
+
+ bool IsPhongTessellation(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(phongTessellation, inKeySet);
+ }
+ void SetPhongTessellation(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(phongTessellation, val, inKeySet);
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ ioStr.append(m_Name);
+ ioStr.append("={");
+ InternalToString(ioStr, "noTessellation", IsNoTessellation(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "linearTessellation", IsLinearTessellation(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "npatchTessellation", IsNPatchTessellation(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "phongTessellation", IsPhongTessellation(inKeySet));
+ ioStr.append("}");
+ }
+ };
+
+ struct SShaderKeyTextureSwizzle : public SShaderKeyUnsigned<5>
+ {
+ enum TextureSwizzleBits {
+ noSwizzle = 1 << 0,
+ L8toR8 = 1 << 1,
+ A8toR8 = 1 << 2,
+ L8A8toRG8 = 1 << 3,
+ L16toR16 = 1 << 4
+ };
+
+ SShaderKeyTextureSwizzle(const char *name = "")
+ : SShaderKeyUnsigned<5>(name)
+ {
+ }
+
+ bool GetBitValue(TextureSwizzleBits swizzleBit, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return (GetValue(inKeySet) & swizzleBit) ? true : false;
+ }
+
+ void SetBitValue(TextureSwizzleBits swizzleBit, bool inValue, NVDataRef<QT3DSU32> inKeySet)
+ {
+ QT3DSU32 theValue = GetValue(inKeySet);
+ QT3DSU32 mask = swizzleBit;
+ if (inValue) {
+ theValue = theValue | mask;
+ } else {
+ mask = ~mask;
+ theValue = theValue & mask;
+ }
+ SetValue(inKeySet, theValue);
+ }
+
+ void SetSwizzleMode(NVDataRef<QT3DSU32> inKeySet, NVRenderTextureSwizzleMode::Enum swizzleMode,
+ bool val)
+ {
+ switch (swizzleMode) {
+ case NVRenderTextureSwizzleMode::NoSwizzle:
+ SetBitValue(noSwizzle, val, inKeySet);
+ break;
+ case NVRenderTextureSwizzleMode::L8toR8:
+ SetBitValue(L8toR8, val, inKeySet);
+ break;
+ case NVRenderTextureSwizzleMode::A8toR8:
+ SetBitValue(A8toR8, val, inKeySet);
+ break;
+ case NVRenderTextureSwizzleMode::L8A8toRG8:
+ SetBitValue(L8A8toRG8, val, inKeySet);
+ break;
+ case NVRenderTextureSwizzleMode::L16toR16:
+ SetBitValue(L16toR16, val, inKeySet);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ bool IsNoSwizzled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(noSwizzle, inKeySet);
+ }
+ void SetNoSwizzled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(noSwizzle, val, inKeySet);
+ }
+
+ bool IsL8Swizzled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(L8toR8, inKeySet);
+ }
+ void SetL8Swizzled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(L8toR8, val, inKeySet);
+ }
+
+ bool IsA8Swizzled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(A8toR8, inKeySet);
+ }
+ void SetA8Swizzled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(A8toR8, val, inKeySet);
+ }
+
+ bool IsL8A8Swizzled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(L8A8toRG8, inKeySet);
+ }
+ void SetL8A8Swizzled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(L8A8toRG8, val, inKeySet);
+ }
+
+ bool IsL16Swizzled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(L16toR16, inKeySet);
+ }
+ void SetL16Swizzled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(L16toR16, val, inKeySet);
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ ioStr.append(m_Name);
+ ioStr.append("={");
+ InternalToString(ioStr, "noswizzle", IsNoSwizzled(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "l8swizzle", IsL8Swizzled(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "a8swizzle", IsA8Swizzled(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "l8a8swizzle", IsL8A8Swizzled(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "l16swizzle", IsL16Swizzled(inKeySet));
+ ioStr.append("}");
+ }
+ };
+
+ struct SShaderKeyImageMap : public SShaderKeyUnsigned<5>
+ {
+ enum ImageMapBits {
+ Enabled = 1 << 0,
+ EnvMap = 1 << 1,
+ LightProbe = 1 << 2,
+ InvertUV = 1 << 3,
+ Premultiplied = 1 << 4,
+ };
+
+ SShaderKeyImageMap(const char *name = "")
+ : SShaderKeyUnsigned<5>(name)
+ {
+ }
+
+ bool GetBitValue(ImageMapBits imageBit, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return (GetValue(inKeySet) & imageBit) ? true : false;
+ }
+
+ void SetBitValue(ImageMapBits imageBit, bool inValue, NVDataRef<QT3DSU32> inKeySet)
+ {
+ QT3DSU32 theValue = GetValue(inKeySet);
+ QT3DSU32 mask = imageBit;
+ if (inValue) {
+ theValue = theValue | mask;
+ } else {
+ mask = ~mask;
+ theValue = theValue & mask;
+ }
+ SetValue(inKeySet, theValue);
+ }
+
+ bool IsEnabled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(Enabled, inKeySet);
+ }
+ void SetEnabled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(Enabled, val, inKeySet);
+ }
+
+ bool IsEnvMap(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(EnvMap, inKeySet);
+ }
+ void SetEnvMap(NVDataRef<QT3DSU32> inKeySet, bool val) { SetBitValue(EnvMap, val, inKeySet); }
+
+ bool IsLightProbe(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(LightProbe, inKeySet);
+ }
+ void SetLightProbe(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(LightProbe, val, inKeySet);
+ }
+
+ bool IsInvertUVMap(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(InvertUV, inKeySet);
+ }
+ void SetInvertUVMap(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(InvertUV, val, inKeySet);
+ }
+
+ bool IsPremultiplied(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(Premultiplied, inKeySet);
+ }
+ void SetPremultiplied(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(Premultiplied, val, inKeySet);
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ ioStr.append(m_Name);
+ ioStr.append("={");
+ InternalToString(ioStr, "enabled", IsEnabled(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "envMap", IsEnvMap(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "lightProbe", IsLightProbe(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "invertUV", IsInvertUVMap(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "premultiplied", IsPremultiplied(inKeySet));
+ ioStr.append("}");
+ }
+ };
+
+ struct SShaderKeySpecularModel : SShaderKeyUnsigned<2>
+ {
+ SShaderKeySpecularModel(const char *name = "")
+ : SShaderKeyUnsigned<2>(name)
+ {
+ }
+
+ void SetSpecularModel(NVDataRef<QT3DSU32> inKeySet,
+ qt3ds::render::DefaultMaterialSpecularModel::Enum inModel)
+ {
+ SetValue(inKeySet, (QT3DSU32)inModel);
+ }
+
+ qt3ds::render::DefaultMaterialSpecularModel::Enum
+ GetSpecularModel(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return static_cast<qt3ds::render::DefaultMaterialSpecularModel::Enum>(GetValue(inKeySet));
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ ioStr.append(m_Name);
+ ioStr.append("=");
+ switch (GetSpecularModel(inKeySet)) {
+ case DefaultMaterialSpecularModel::KGGX:
+ ioStr.append("KGGX");
+ break;
+ case DefaultMaterialSpecularModel::KWard:
+ ioStr.append("KWard");
+ break;
+ case DefaultMaterialSpecularModel::Default:
+ ioStr.append("Default");
+ break;
+ }
+ ioStr.append(";");
+ }
+ };
+
+ struct SShaderDefaultMaterialKeyProperties
+ {
+ enum {
+ LightCount = 7,
+ };
+ enum ImageMapNames {
+ DiffuseMap0 = 0,
+ DiffuseMap1,
+ DiffuseMap2,
+ EmissiveMap,
+ EmissiveMap2,
+ SpecularMap,
+ OpacityMap,
+ BumpMap,
+ SpecularAmountMap,
+ NormalMap,
+ DisplacementMap,
+ TranslucencyMap,
+ LightmapIndirect,
+ LightmapRadiosity,
+ LightmapShadow,
+ RoughnessMap,
+ ImageMapCount
+ };
+
+ SShaderKeyBoolean m_HasLighting;
+ SShaderKeyBoolean m_HasIbl;
+ SShaderKeyUnsigned<3> m_LightCount;
+ SShaderKeyBoolean m_LightFlags[LightCount];
+ SShaderKeyBoolean m_LightAreaFlags[LightCount];
+ SShaderKeyBoolean m_LightShadowFlags[LightCount];
+ SShaderKeyBoolean m_SpecularEnabled;
+ SShaderKeyBoolean m_FresnelEnabled;
+ SShaderKeyBoolean m_VertexColorsEnabled;
+ SShaderKeySpecularModel m_SpecularModel;
+ SShaderKeyImageMap m_ImageMaps[ImageMapCount];
+ SShaderKeyTextureSwizzle m_TextureSwizzle[ImageMapCount];
+ SShaderKeyTessellation m_TessellationMode;
+ SShaderKeyBoolean m_HasSkinning;
+ SShaderKeyBoolean m_WireframeMode;
+
+ SShaderDefaultMaterialKeyProperties()
+ : m_HasLighting("hasLighting")
+ , m_HasIbl("hasIbl")
+ , m_LightCount("lightCount")
+ , m_SpecularEnabled("specularEnabled")
+ , m_FresnelEnabled("fresnelEnabled")
+ , m_VertexColorsEnabled("vertexColorsEnabled")
+ , m_SpecularModel("specularModel")
+ , m_TessellationMode("tessellationMode")
+ , m_HasSkinning("hasSkinning")
+ , m_WireframeMode("wireframeMode")
+ {
+ m_LightFlags[0].m_Name = "light0HasPosition";
+ m_LightFlags[1].m_Name = "light1HasPosition";
+ m_LightFlags[2].m_Name = "light2HasPosition";
+ m_LightFlags[3].m_Name = "light3HasPosition";
+ m_LightFlags[4].m_Name = "light4HasPosition";
+ m_LightFlags[5].m_Name = "light5HasPosition";
+ m_LightFlags[6].m_Name = "light6HasPosition";
+ m_LightAreaFlags[0].m_Name = "light0HasArea";
+ m_LightAreaFlags[1].m_Name = "light1HasArea";
+ m_LightAreaFlags[2].m_Name = "light2HasArea";
+ m_LightAreaFlags[3].m_Name = "light3HasArea";
+ m_LightAreaFlags[4].m_Name = "light4HasArea";
+ m_LightAreaFlags[5].m_Name = "light5HasArea";
+ m_LightAreaFlags[6].m_Name = "light6HasArea";
+ m_LightShadowFlags[0].m_Name = "light0HasShadow";
+ m_LightShadowFlags[1].m_Name = "light1HasShadow";
+ m_LightShadowFlags[2].m_Name = "light2HasShadow";
+ m_LightShadowFlags[3].m_Name = "light3HasShadow";
+ m_LightShadowFlags[4].m_Name = "light4HasShadow";
+ m_LightShadowFlags[5].m_Name = "light5HasShadow";
+ m_LightShadowFlags[6].m_Name = "light6HasShadow";
+ m_ImageMaps[0].m_Name = "diffuseMap0";
+ m_ImageMaps[1].m_Name = "diffuseMap1";
+ m_ImageMaps[2].m_Name = "diffuseMap2";
+ m_ImageMaps[3].m_Name = "emissiveMap";
+ m_ImageMaps[4].m_Name = "emissiveMap2";
+ m_ImageMaps[5].m_Name = "specularMap";
+ m_ImageMaps[6].m_Name = "opacityMap";
+ m_ImageMaps[7].m_Name = "bumpMap";
+ m_ImageMaps[8].m_Name = "specularAmountMap";
+ m_ImageMaps[9].m_Name = "normalMap";
+ m_ImageMaps[10].m_Name = "displacementMap";
+ m_ImageMaps[11].m_Name = "translucencyMap";
+ m_ImageMaps[12].m_Name = "lightmapIndirect";
+ m_ImageMaps[13].m_Name = "lightmapRadiosity";
+ m_ImageMaps[14].m_Name = "lightmapShadow";
+ m_ImageMaps[15].m_Name = "roughnessMap";
+ m_TextureSwizzle[0].m_Name = "diffuseMap0_swizzle";
+ m_TextureSwizzle[1].m_Name = "diffuseMap1_swizzle";
+ m_TextureSwizzle[2].m_Name = "diffuseMap2_swizzle";
+ m_TextureSwizzle[3].m_Name = "emissiveMap_swizzle";
+ m_TextureSwizzle[4].m_Name = "emissiveMap2_swizzle";
+ m_TextureSwizzle[5].m_Name = "specularMap_swizzle";
+ m_TextureSwizzle[6].m_Name = "opacityMap_swizzle";
+ m_TextureSwizzle[7].m_Name = "bumpMap_swizzle";
+ m_TextureSwizzle[8].m_Name = "specularAmountMap_swizzle";
+ m_TextureSwizzle[9].m_Name = "normalMap_swizzle";
+ m_TextureSwizzle[10].m_Name = "displacementMap_swizzle";
+ m_TextureSwizzle[11].m_Name = "translucencyMap_swizzle";
+ m_TextureSwizzle[12].m_Name = "lightmapIndirect_swizzle";
+ m_TextureSwizzle[13].m_Name = "lightmapRadiosity_swizzle";
+ m_TextureSwizzle[14].m_Name = "lightmapShadow_swizzle";
+ m_TextureSwizzle[15].m_Name = "roughnessMap_swizzle";
+ SetPropertyOffsets();
+ }
+
+ template <typename TVisitor>
+ void VisitProperties(TVisitor &inVisitor)
+ {
+ inVisitor.Visit(m_HasLighting);
+ inVisitor.Visit(m_HasIbl);
+ inVisitor.Visit(m_LightCount);
+
+ for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx) {
+ inVisitor.Visit(m_LightFlags[idx]);
+ }
+
+ for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx) {
+ inVisitor.Visit(m_LightAreaFlags[idx]);
+ }
+
+ for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx) {
+ inVisitor.Visit(m_LightShadowFlags[idx]);
+ }
+
+ inVisitor.Visit(m_SpecularEnabled);
+ inVisitor.Visit(m_FresnelEnabled);
+ inVisitor.Visit(m_VertexColorsEnabled);
+ inVisitor.Visit(m_SpecularModel);
+
+ for (QT3DSU32 idx = 0, end = ImageMapCount; idx < end; ++idx) {
+ inVisitor.Visit(m_ImageMaps[idx]);
+ inVisitor.Visit(m_TextureSwizzle[idx]);
+ }
+
+ inVisitor.Visit(m_TessellationMode);
+ inVisitor.Visit(m_HasSkinning);
+ inVisitor.Visit(m_WireframeMode);
+ }
+
+ struct SOffsetVisitor
+ {
+ QT3DSU32 m_Offset;
+ SOffsetVisitor()
+ : m_Offset(0)
+ {
+ }
+ template <typename TPropType>
+ void Visit(TPropType &inProp)
+ {
+ // if we cross the 32 bit border we just move
+ // to the next dword.
+ // This cost a few extra bits but prevents tedious errors like
+ // loosing shader key bits because they got moved beyond the 32 border
+ QT3DSU32 bit = m_Offset % 32;
+ if (bit + TPropType::BitWidth > 31) {
+ m_Offset += 32 - bit;
+ }
+
+ inProp.SetOffset(m_Offset);
+ m_Offset += TPropType::BitWidth;
+ }
+ };
+
+ void SetPropertyOffsets()
+ {
+ SOffsetVisitor visitor;
+ VisitProperties(visitor);
+ // If this assert fires, then the default material key needs more bits.
+ QT3DS_ASSERT(visitor.m_Offset < 224);
+ }
+ };
+
+ struct SShaderDefaultMaterialKey
+ {
+ enum {
+ DataBufferSize = 7,
+ };
+ QT3DSU32 m_DataBuffer[DataBufferSize];
+ size_t m_FeatureSetHash;
+
+ SShaderDefaultMaterialKey(size_t inFeatureSetHash)
+ : m_FeatureSetHash(inFeatureSetHash)
+ {
+ for (size_t idx = 0; idx < DataBufferSize; ++idx)
+ m_DataBuffer[idx] = 0;
+ }
+
+ SShaderDefaultMaterialKey()
+ : m_FeatureSetHash(0)
+ {
+ for (size_t idx = 0; idx < DataBufferSize; ++idx)
+ m_DataBuffer[idx] = 0;
+ }
+
+ size_t hash() const
+ {
+ size_t retval = 0;
+ for (size_t idx = 0; idx < DataBufferSize; ++idx)
+ retval = retval ^ eastl::hash<QT3DSU32>()(m_DataBuffer[idx]);
+ return retval ^ m_FeatureSetHash;
+ }
+
+ bool operator==(const SShaderDefaultMaterialKey &other) const
+ {
+ bool retval = true;
+ for (size_t idx = 0; idx < DataBufferSize && retval; ++idx)
+ retval = m_DataBuffer[idx] == other.m_DataBuffer[idx];
+ return retval && m_FeatureSetHash == other.m_FeatureSetHash;
+ }
+
+ // Cast operators to make getting properties easier.
+ operator NVDataRef<QT3DSU32>() { return toDataRef(m_DataBuffer, DataBufferSize); }
+
+ operator NVConstDataRef<QT3DSU32>() const
+ {
+ return toConstDataRef(m_DataBuffer, DataBufferSize);
+ }
+
+ struct SStringVisitor
+ {
+ eastl::string &m_Str;
+ NVConstDataRef<QT3DSU32> m_KeyStore;
+ SStringVisitor(eastl::string &s, NVConstDataRef<QT3DSU32> ks)
+ : m_Str(s)
+ , m_KeyStore(ks)
+ {
+ }
+ template <typename TPropType>
+ void Visit(const TPropType &prop)
+ {
+ QT3DSU32 originalSize = m_Str.size();
+ if (m_Str.size())
+ m_Str.append(";");
+ prop.ToString(m_Str, m_KeyStore);
+ // if the only thing we added was the semicolon
+ // then nuke the semicolon
+ if (originalSize && m_Str.size() == originalSize + 1)
+ m_Str.resize(originalSize);
+ }
+ };
+
+ void ToString(eastl::string &ioString,
+ SShaderDefaultMaterialKeyProperties &inProperties) const
+ {
+ SStringVisitor theVisitor(ioString, *this);
+ inProperties.VisitProperties(theVisitor);
+ }
+ };
+}
+}
+
+namespace eastl {
+template <>
+struct hash<qt3ds::render::SShaderDefaultMaterialKey>
+{
+ size_t operator()(const qt3ds::render::SShaderDefaultMaterialKey &key) const
+ {
+ return key.hash();
+ }
+};
+}
+
+#endif