1 //  SuperTuxKart - a fun racing game with go-kart
2 //  Copyright (C) 2018 SuperTuxKart-Team
3 //
4 //  This program is free software; you can redistribute it and/or
5 //  modify it under the terms of the GNU General Public License
6 //  as published by the Free Software Foundation; either version 3
7 //  of the License, or (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program; if not, write to the Free Software
16 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 
18 #ifndef HEADER_SP_SHADER_MANAGER_HPP
19 #define HEADER_SP_SHADER_MANAGER_HPP
20 
21 #include <array>
22 #include <functional>
23 #include <memory>
24 #include <string>
25 #include <typeinfo>
26 #include <typeindex>
27 #include <unordered_map>
28 #include <vector>
29 
30 #include "utils/no_copy.hpp"
31 
32 class XMLNode;
33 namespace SP
34 {
35 class SPShader;
36 class SPUniformAssigner;
37 
38 enum SamplerType: unsigned int;
39 enum RenderPass: unsigned int;
40 
41 class SPShaderManager : public NoCopy
42 {
43 public:
44     struct PassInfo
45     {
46         std::function<void()> m_use_function;
47 
48         std::function<void()> m_unuse_function;
49 
50         std::string m_vertex_shader;
51 
52         std::string m_fragment_shader;
53 
54         std::string m_skinned_mesh_shader;
55 
56         std::vector<std::tuple<std::string, std::string, bool, SamplerType> >
57             m_prefilled_textures;
58     };
59 
60 private:
61     typedef std::vector<std::pair< std::string, std::function<void
62         (SPUniformAssigner*)> > > UniformAssigners;
63     struct ShaderInfo
64     {
65         std::string m_shader_name, m_fallback_name;
66 
67         int m_drawing_priority = 0;
68 
69         bool m_transparent_shader = false;
70 
71         bool m_use_alpha_channel = false;
72 
73         bool m_use_tangents = false;
74 
75         std::array<bool, 6> m_srgb =
76             {{
77                 true, true, false, false, false, false
78             }};
79     };
80 
81     static SPShaderManager* m_spsm;
82 
83     std::unordered_map<std::string, std::shared_ptr<SPShader> > m_shaders;
84 
85     std::vector<std::shared_ptr<SPShader> > m_official_shaders;
86 
87     std::unordered_map<std::string, SamplerType> m_official_sampler_types;
88 
89     std::unordered_map<std::string, std::function<void(SPUniformAssigner*)> >
90         m_official_uniform_assigner_functions;
91 
92     std::unordered_map<std::string, std::function<void()> >
93         m_official_use_functions;
94 
95     std::unordered_map<std::string, std::function<void()> >
96         m_official_unuse_functions;
97 
98     std::string m_shader_directory;
99 
100     // ------------------------------------------------------------------------
101     std::string getShaderFullPath(const std::string& name);
102     // ------------------------------------------------------------------------
103     void loadPassInfo(const XMLNode* pass, PassInfo& pi);
104     // ------------------------------------------------------------------------
105     void loadEachShader(const std::string& file_name);
106     // ------------------------------------------------------------------------
107     std::shared_ptr<SPShader> buildSPShader(const ShaderInfo& si,
108                                             const std::array<PassInfo, 2>& pi,
109                                             const UniformAssigners& ua,
110                                             bool skinned);
111 
112 public:
113     // ------------------------------------------------------------------------
get()114     static SPShaderManager* get()
115     {
116         if (m_spsm == NULL)
117         {
118             m_spsm = new SPShaderManager();
119         }
120         return m_spsm;
121     }
122     // ------------------------------------------------------------------------
destroy()123     static void destroy()
124     {
125         delete m_spsm;
126         m_spsm = NULL;
127     }
128     // ------------------------------------------------------------------------
129     static void addPrefilledTexturesToShader(SPShader* s,
130         const std::vector<std::tuple<std::string, std::string, bool,
131         SamplerType> >& t, RenderPass rp);
132     // ------------------------------------------------------------------------
133     SPShaderManager();
134     // ------------------------------------------------------------------------
135     ~SPShaderManager();
136     // ------------------------------------------------------------------------
getSPShader(const std::string & name)137     std::shared_ptr<SPShader> getSPShader(const std::string& name)
138     {
139         auto ret = m_shaders.find(name);
140         if (ret != m_shaders.end())
141         {
142             return ret->second;
143         }
144         return NULL;
145     }
146     // ------------------------------------------------------------------------
147     void loadSPShaders(const std::string& directory_name);
148     // ------------------------------------------------------------------------
addSPShader(const std::string & name,std::shared_ptr<SPShader> shader)149     void addSPShader(const std::string& name,
150                      std::shared_ptr<SPShader> shader)
151     {
152         m_shaders[name] = shader;
153     }
154     // ------------------------------------------------------------------------
155     void unloadAll();
156     // ------------------------------------------------------------------------
157     void initAll();
158     // ------------------------------------------------------------------------
159     void removeUnusedShaders();
160     // ------------------------------------------------------------------------
setOfficialShaders()161     void setOfficialShaders()
162     {
163         for (auto& p : m_shaders)
164         {
165             m_official_shaders.push_back(p.second);
166         }
167     }
168 
169 };
170 
171 }
172 
173 #endif
174