Adding chipmunk implementation for physics adaptor
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / shader-definition.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-definition.h>
20
21 // INTERNAL INCLUDES
22 #include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
23 #include <dali-scene3d/public-api/loader/utils.h>
24
25 namespace Dali::Scene3D::Loader
26 {
27 namespace
28 {
29 const char* SHADER_HINT_OUTPUT_IS_TRANSPARENT("OUTPUT_IS_TRANSPARENT"); ///< Might generate transparent alpha from opaque inputs.
30 const char* SHADER_HINT_MODIFIES_GEOMETRY("MODIFIES_GEOMETRY");         ///< Might change position of vertices, this option disables any culling optimizations.
31 } // namespace
32
33 ShaderDefinition::ShaderDefinition(const ShaderDefinition& other)
34 : mRendererState(other.mRendererState),
35   mVertexShaderPath(other.mVertexShaderPath),
36   mFragmentShaderPath(other.mFragmentShaderPath),
37   mDefines(other.mDefines),
38   mHints(other.mHints),
39   mUniforms(other.mUniforms),
40   mUseBuiltInShader(other.mUseBuiltInShader)
41 {
42 }
43
44 void ShaderDefinition::ApplyDefine(std::string& shaderCode, const std::string& definevar)
45 {
46   const std::string IF_1 = "#if 1";
47
48   std::size_t found = shaderCode.find(definevar);
49   while(found != std::string::npos)
50   {
51     // Greater then "@" character means is a letter,
52     // therefore is not has the definevar we looking for.
53     if((found + definevar.length()) < shaderCode.length() && shaderCode.at(found + definevar.length()) > '@')
54     {
55       found = shaderCode.find(definevar, found + definevar.length());
56       continue;
57     }
58     if(found > 0u && shaderCode.at(found - 1) > '@')
59     {
60       found = shaderCode.find(definevar, found + definevar.length());
61       continue;
62     }
63
64     std::size_t defidx     = shaderCode.rfind("#ifdef", found);
65     std::size_t newlineidx = shaderCode.rfind("\n", found);
66     if(newlineidx < defidx && defidx != std::string::npos)
67     {
68       shaderCode.replace(defidx, found - defidx + definevar.length(), IF_1);
69       found = defidx + IF_1.length();
70     }
71     else
72     {
73       found += definevar.length();
74     }
75     found = shaderCode.find(definevar, found);
76   }
77 }
78
79 ShaderDefinition::RawData
80 ShaderDefinition::LoadRaw(const std::string& shadersPath) const
81 {
82   RawData raw;
83
84   bool fail = false;
85   if(!mUseBuiltInShader)
86   {
87     raw.mVertexShaderSource = LoadTextFile((shadersPath + mVertexShaderPath).c_str(), &fail);
88     if(!fail)
89     {
90       raw.mFragmentShaderSource = LoadTextFile((shadersPath + mFragmentShaderPath).c_str(), &fail);
91       if(fail)
92       {
93         ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mFragmentShaderPath << "'.";
94       }
95     }
96     else
97     {
98       ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mVertexShaderPath << "'.";
99     }
100   }
101   else
102   {
103     raw.mVertexShaderSource   = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_VERT.data();
104     raw.mFragmentShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
105   }
106
107   if(!fail)
108   {
109     for(const auto& definevar : mDefines)
110     {
111       ApplyDefine(raw.mVertexShaderSource, definevar);
112       ApplyDefine(raw.mFragmentShaderSource, definevar);
113     }
114   }
115
116   return raw;
117 }
118
119 Shader ShaderDefinition::Load(RawData&& raw) const
120 {
121   uint32_t hints = Shader::Hint::NONE;
122   for(const auto& hint : mHints)
123   {
124     if(hint == SHADER_HINT_OUTPUT_IS_TRANSPARENT)
125     {
126       hints |= Shader::Hint::OUTPUT_IS_TRANSPARENT;
127     }
128     else if(hint == SHADER_HINT_MODIFIES_GEOMETRY)
129     {
130       hints |= Shader::Hint::MODIFIES_GEOMETRY;
131     }
132   }
133
134   Shader shader = Shader::New(raw.mVertexShaderSource, raw.mFragmentShaderSource, static_cast<Shader::Hint::Value>(hints));
135   for(Property::Map::SizeType i0 = 0, i1 = mUniforms.Count(); i0 != i1; ++i0)
136   {
137     auto pair = mUniforms.GetKeyValue(i0);
138     DALI_ASSERT_ALWAYS(pair.first.type == Property::Key::STRING);
139     shader.RegisterProperty(pair.first.stringKey, pair.second);
140   }
141
142   return shader;
143 }
144
145 } // namespace Dali::Scene3D::Loader