Merge "Removed unused macro invocation from shader" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / shader-option.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-scene3d/public-api/loader/shader-option.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23 #include <ostream>
24 #include <sstream>
25 #include <string>
26
27 namespace Dali::Scene3D::Loader
28 {
29 namespace
30 {
31 static constexpr std::string_view OPTION_KEYWORD[] =
32   {
33     "GLTF_CHANNELS",
34     "THREE_TEX",
35     "BASECOLOR_TEX",
36     "METALLIC_ROUGHNESS_TEX",
37     "NORMAL_TEX",
38     "OCCLUSION",
39     "EMISSIVE_TEXTURE",
40     "ALPHA_TEST",
41     "SSS",
42     "MATERIAL_SPECULAR_TEXTURE",
43     "MATERIAL_SPECULAR_COLOR_TEXTURE",
44     "SKINNING",
45     "FLIP_V",
46     "COLOR_ATTRIBUTE",
47     "VEC4_TANGENT",
48     "MORPH_POSITION",
49     "MORPH_NORMAL",
50     "MORPH_TANGENT",
51     "MORPH_VERSION_2_0",
52 };
53 static constexpr uint32_t NUMBER_OF_OPTIONS = sizeof(OPTION_KEYWORD) / sizeof(OPTION_KEYWORD[0]);
54 static const char*        ADD_EXTRA_SKINNING_ATTRIBUTES{"ADD_EXTRA_SKINNING_ATTRIBUTES"};
55 static const char*        ADD_EXTRA_WEIGHTS{"ADD_EXTRA_WEIGHTS"};
56
57 inline void HashString(uint64_t& hash, const char* string)
58 {
59   char c;
60   while((c = *string++))
61   {
62     hash = hash * 33 + c;
63   }
64 }
65 } // namespace
66
67 ShaderOption::ShaderOption(const ShaderOption& rhs)
68 {
69   mOptionHash = rhs.mOptionHash;
70   for(auto& macroDef : rhs.mMacros)
71   {
72     mMacros.emplace_back(macroDef);
73   }
74 }
75
76 ShaderOption& ShaderOption::operator=(const ShaderOption& rhs)
77 {
78   if(this != &rhs)
79   {
80     mOptionHash = rhs.mOptionHash;
81     for(auto& macroDef : rhs.mMacros)
82     {
83       mMacros.emplace_back(macroDef);
84     }
85   }
86   return *this;
87 }
88
89 void ShaderOption::SetTransparency()
90 {
91   mOptionHash |= (1 << NUMBER_OF_OPTIONS);
92 }
93
94 void ShaderOption::AddOption(Type shaderOptionType)
95 {
96   mOptionHash |= (1 << static_cast<uint32_t>(shaderOptionType));
97 }
98
99 void ShaderOption::AddJointMacros(size_t numberOfJointSets)
100 {
101   // Add options for ADD_EXTRA_SKINNING_ATTRIBUTES and ADD_EXTRA_WEIGHTS:
102   if(numberOfJointSets > 1)
103   {
104     std::ostringstream attributes;
105     std::ostringstream weights;
106     for(size_t i = 1; i < numberOfJointSets; ++i)
107     {
108       attributes << "in vec4 aJoints" << i << ";\n";
109       attributes << "in vec4 aWeights" << i << ";\n";
110
111       weights << "bone +=\n"
112               << "uBone[int(aJoints" << i << ".x)] * aWeights" << i << ".x +\n"
113               << "uBone[int(aJoints" << i << ".y)] * aWeights" << i << ".y +\n"
114               << "uBone[int(aJoints" << i << ".z)] * aWeights" << i << ".z +\n"
115               << "uBone[int(aJoints" << i << ".w)] * aWeights" << i << ".w;\n";
116     }
117     AddMacroDefinition(ADD_EXTRA_SKINNING_ATTRIBUTES, attributes.str());
118     AddMacroDefinition(ADD_EXTRA_WEIGHTS, weights.str());
119   }
120   else
121   {
122     AddMacroDefinition(ADD_EXTRA_SKINNING_ATTRIBUTES, std::string{});
123     AddMacroDefinition(ADD_EXTRA_WEIGHTS, std::string{});
124   }
125 }
126
127 void ShaderOption::AddMacroDefinition(std::string macro, std::string definition)
128 {
129   auto iter = std::find_if(mMacros.begin(), mMacros.end(), [macro](ShaderOption::MacroDefinition& md) { return md.macro == macro; });
130   if(iter != mMacros.end())
131   {
132     iter->definition = definition;
133   }
134   else
135   {
136     mMacros.emplace_back(MacroDefinition{macro, definition});
137   }
138 }
139
140 const std::vector<ShaderOption::MacroDefinition>& ShaderOption::GetMacroDefinitions() const
141 {
142   return mMacros;
143 }
144
145 uint64_t ShaderOption::GetOptionHash() const
146 {
147   uint64_t optionHash = mOptionHash;
148   if(!mMacros.empty())
149   {
150     uint64_t hash = 5381;
151     for(auto& macroDef : mMacros)
152     {
153       HashString(hash, macroDef.macro.c_str());
154       HashString(hash, macroDef.definition.c_str());
155     }
156     optionHash |= (hash << 32 & 0xFFFFFFFF00000000);
157   }
158   return optionHash;
159 }
160
161 void ShaderOption::GetDefines(std::vector<std::string>& defines) const
162 {
163   defines.clear();
164   for(uint32_t i = 0; i < NUMBER_OF_OPTIONS; ++i)
165   {
166     if(mOptionHash & 1 << i)
167     {
168       defines.push_back(OPTION_KEYWORD[i].data());
169     }
170   }
171 }
172
173 std::string_view ShaderOption::GetDefineKeyword(Type shaderOptionType)
174 {
175   return OPTION_KEYWORD[static_cast<uint32_t>(shaderOptionType)];
176 }
177
178 } // namespace Dali::Scene3D::Loader