[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / shader-option.cpp
1 /*
2  * Copyright (c) 2024 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     "SL_VERSION_LOW",
53 };
54 static constexpr uint32_t NUMBER_OF_OPTIONS = sizeof(OPTION_KEYWORD) / sizeof(OPTION_KEYWORD[0]);
55 static const char*        ADD_EXTRA_SKINNING_ATTRIBUTES{"ADD_EXTRA_SKINNING_ATTRIBUTES"};
56 static const char*        ADD_EXTRA_WEIGHTS{"ADD_EXTRA_WEIGHTS"};
57
58 inline void HashString(uint64_t& hash, const char* string)
59 {
60   char c;
61   while((c = *string++))
62   {
63     hash = hash * 33 + c;
64   }
65 }
66 } // namespace
67
68 ShaderOption::ShaderOption(const ShaderOption& rhs)
69 {
70   mOptionHash = rhs.mOptionHash;
71   for(auto& macroDef : rhs.mMacros)
72   {
73     mMacros.emplace_back(macroDef);
74   }
75 }
76
77 ShaderOption& ShaderOption::operator=(const ShaderOption& rhs)
78 {
79   if(this != &rhs)
80   {
81     mOptionHash = rhs.mOptionHash;
82     for(auto& macroDef : rhs.mMacros)
83     {
84       mMacros.emplace_back(macroDef);
85     }
86   }
87   return *this;
88 }
89
90 void ShaderOption::SetTransparency()
91 {
92   mOptionHash |= (1 << NUMBER_OF_OPTIONS);
93 }
94
95 void ShaderOption::AddOption(Type shaderOptionType)
96 {
97   mOptionHash |= (1 << static_cast<uint32_t>(shaderOptionType));
98 }
99
100 void ShaderOption::AddJointMacros(size_t numberOfJointSets)
101 {
102   // Add options for ADD_EXTRA_SKINNING_ATTRIBUTES and ADD_EXTRA_WEIGHTS:
103   if(numberOfJointSets > 1)
104   {
105     std::ostringstream attributes;
106     std::ostringstream weights;
107     for(size_t i = 1; i < numberOfJointSets; ++i)
108     {
109       attributes << "INPUT vec4 aJoints" << i << ";\n";
110       attributes << "INPUT vec4 aWeights" << i << ";\n";
111
112       weights << "bone +=\n"
113               << "uBone[int(aJoints" << i << ".x)] * aWeights" << i << ".x +\n"
114               << "uBone[int(aJoints" << i << ".y)] * aWeights" << i << ".y +\n"
115               << "uBone[int(aJoints" << i << ".z)] * aWeights" << i << ".z +\n"
116               << "uBone[int(aJoints" << i << ".w)] * aWeights" << i << ".w;\n";
117     }
118     AddMacroDefinition(ADD_EXTRA_SKINNING_ATTRIBUTES, attributes.str());
119     AddMacroDefinition(ADD_EXTRA_WEIGHTS, weights.str());
120   }
121   else
122   {
123     AddMacroDefinition(ADD_EXTRA_SKINNING_ATTRIBUTES, std::string{});
124     AddMacroDefinition(ADD_EXTRA_WEIGHTS, std::string{});
125   }
126 }
127
128 void ShaderOption::AddMacroDefinition(std::string macro, std::string definition)
129 {
130   auto iter = std::find_if(mMacros.begin(), mMacros.end(), [macro](ShaderOption::MacroDefinition& md) { return md.macro == macro; });
131   if(iter != mMacros.end())
132   {
133     iter->definition = definition;
134   }
135   else
136   {
137     mMacros.emplace_back(MacroDefinition{macro, definition});
138   }
139 }
140
141 const std::vector<ShaderOption::MacroDefinition>& ShaderOption::GetMacroDefinitions() const
142 {
143   return mMacros;
144 }
145
146 uint64_t ShaderOption::GetOptionHash() const
147 {
148   uint64_t optionHash = mOptionHash;
149   if(!mMacros.empty())
150   {
151     uint64_t hash = 5381;
152     for(auto& macroDef : mMacros)
153     {
154       HashString(hash, macroDef.macro.c_str());
155       HashString(hash, macroDef.definition.c_str());
156     }
157     optionHash |= ((hash << 32) & 0xFFFFFFFF00000000);
158   }
159   return optionHash;
160 }
161
162 void ShaderOption::GetDefines(std::vector<std::string>& defines) const
163 {
164   defines.clear();
165   for(uint32_t i = 0; i < NUMBER_OF_OPTIONS; ++i)
166   {
167     if(mOptionHash & (1 << i))
168     {
169       defines.push_back(OPTION_KEYWORD[i].data());
170     }
171   }
172 }
173
174 std::string_view ShaderOption::GetDefineKeyword(Type shaderOptionType)
175 {
176   return OPTION_KEYWORD[static_cast<uint32_t>(shaderOptionType)];
177 }
178
179 } // namespace Dali::Scene3D::Loader