SuperTuxKart
Loading...
Searching...
No Matches
sp_shader.hpp
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_HPP
19#define HEADER_SP_SHADER_HPP
20
21#include "graphics/gl_headers.hpp"
22#include "graphics/sp/sp_per_object_uniform.hpp"
23#include "utils/log.hpp"
24#include "utils/no_copy.hpp"
25
26#include <array>
27#include <cstring>
28#include <functional>
29#include <ostream>
30#include <map>
31#include <memory>
32#include <string>
33#include <typeinfo>
34#include <typeindex>
35#include <unordered_map>
36#include <vector>
37
38namespace SP
39{
40
41enum SamplerType: unsigned int
42{
43 ST_NEAREST,
44 ST_NEAREST_CLAMPED,
45 ST_TRILINEAR,
46 ST_TRILINEAR_CLAMPED,
47 ST_BILINEAR,
48 ST_BILINEAR_CLAMPED,
49 ST_SEMI_TRILINEAR,
50 ST_SHADOW,
51 ST_TEXTURE_BUFFER,
52 ST_COUNT
53};
54
55enum RenderPass: unsigned int
56{
57 RP_1ST = 0,
58 RP_SHADOW,
59 RP_RESERVED,
60 RP_COUNT
61};
62
63inline std::ostream& operator<<(std::ostream& os, const RenderPass& rp)
64{
65 switch (rp)
66 {
67 case RP_1ST:
68 return os << "first pass";
69 case RP_SHADOW:
70 return os << "shadow pass";
71 case RP_RESERVED:
72 return os << "reserved pass";
73 default:
74 return os;
75 }
76}
77
78class SPUniformAssigner;
79
80class SPShader : public NoCopy, public SPPerObjectUniform
81{
82private:
83 std::string m_name;
84
85 std::vector<std::shared_ptr<GLuint> > m_shader_files;
86
87 GLuint m_program[RP_COUNT];
88
89 std::map<unsigned, unsigned> m_samplers[RP_COUNT];
90
91 std::vector<std::tuple<unsigned, std::string, SamplerType,
92 GLuint> >m_prefilled_samplers[RP_COUNT];
93
94 std::unordered_map<std::string, SPUniformAssigner*> m_uniforms[RP_COUNT];
95
96 std::unordered_map<std::string, std::function<GLuint()> >
97 m_custom_prefilled_getter[RP_COUNT];
98
99 std::function<void()> m_use_function[RP_COUNT], m_unuse_function[RP_COUNT];
100
101 const std::function<void(SPShader*)> m_init_function;
102
103 const int m_drawing_priority;
104
105 const bool m_transparent_shader;
106
107 const bool m_use_alpha_channel;
108
109 const bool m_use_tangents;
110
111 const std::array<bool, 6> m_srgb;
112
113public:
114 // ------------------------------------------------------------------------
115 static bool m_sp_shader_debug;
116 static std::map<std::string, std::pair<unsigned, SamplerType> >
117 m_prefilled_names;
118 // ------------------------------------------------------------------------
119 SPShader(const std::string& name,
120 const std::function<void(SPShader*)>& init_func,
121 bool transparent_shader = false, int drawing_priority = 0,
122 bool use_alpha_channel = false, bool use_tangents = false,
123 const std::array<bool, 6>& srgb =
124 {{ true, true, false, false, false, false }});
125 // ------------------------------------------------------------------------
126 ~SPShader()
127 {
128 unload();
129 }
130 // ------------------------------------------------------------------------
131 bool hasShader(RenderPass rp) { return m_program[rp] != 0; }
132 // ------------------------------------------------------------------------
133 GLuint getShaderProgram(RenderPass rp) { return m_program[rp]; }
134 // ------------------------------------------------------------------------
135 void use(RenderPass rp = RP_1ST)
136 {
137 if (m_use_function[rp] != NULL)
138 {
139 m_use_function[rp]();
140 }
141#ifndef SERVER_ONLY
142 glUseProgram(m_program[rp]);
143#endif
144 }
145 // ------------------------------------------------------------------------
146 void unuse(RenderPass rp = RP_1ST)
147 {
148 if (m_unuse_function[rp] != NULL)
149 {
150 m_unuse_function[rp]();
151 }
152 }
153 // ------------------------------------------------------------------------
154 void addShaderFile(const std::string& name,
155 GLint shader_type, RenderPass rp = RP_1ST);
156 // ------------------------------------------------------------------------
157 void linkShaderFiles(RenderPass rp = RP_1ST);
158 // ------------------------------------------------------------------------
159 void addAllTextures(RenderPass rp = RP_1ST);
160 // ------------------------------------------------------------------------
161 void addAllUniforms(RenderPass rp = RP_1ST);
162 // ------------------------------------------------------------------------
163 void addCustomPrefilledTextures(SamplerType st, GLuint texture_type,
164 const std::string& name,
165 std::function<GLuint()> func,
166 RenderPass rp = RP_1ST);
167 // ------------------------------------------------------------------------
168 void bindPrefilledTextures(RenderPass rp = RP_1ST) const;
169 // ------------------------------------------------------------------------
170 void bindTextures(const std::array<GLuint, 6>& tex,
171 RenderPass rp = RP_1ST) const;
172 // ------------------------------------------------------------------------
173 void addBasicUniforms(RenderPass rp = RP_1ST)
174 {
175#ifndef SERVER_ONLY
176 // Assign ubo indices
177 GLuint block_index = glGetUniformBlockIndex(m_program[rp],
178 "Matrices");
179 if (block_index != GL_INVALID_INDEX)
180 glUniformBlockBinding(m_program[rp], block_index, 0);
181 block_index = glGetUniformBlockIndex(m_program[rp], "SPFogData");
182 if (block_index != GL_INVALID_INDEX)
183 glUniformBlockBinding(m_program[rp], block_index, 2);
184#endif
185 }
186 // ------------------------------------------------------------------------
187 const std::string& getName() const { return m_name; }
188 // ------------------------------------------------------------------------
189 SPUniformAssigner* getUniformAssigner(const std::string& name,
190 RenderPass rp = RP_1ST) const;
191 // ------------------------------------------------------------------------
192 void setUniformsPerObject(SPPerObjectUniform* sppou,
193 std::vector<SPUniformAssigner*>* ua_used,
194 RenderPass rp = RP_1ST);
195 // ------------------------------------------------------------------------
196 void setUseFunction(std::function<void()> func, RenderPass rp = RP_1ST)
197 {
198 m_use_function[rp] = func;
199 }
200 // ------------------------------------------------------------------------
201 void setUnuseFunction(std::function<void()> func, RenderPass rp = RP_1ST)
202 {
203 m_unuse_function[rp] = func;
204 }
205 // ------------------------------------------------------------------------
206 bool isTransparent() const { return m_transparent_shader; }
207 // ------------------------------------------------------------------------
208 bool useAlphaChannel() const { return m_use_alpha_channel; }
209 // ------------------------------------------------------------------------
210 int getDrawingPriority() const { return m_drawing_priority; }
211 // ------------------------------------------------------------------------
212 bool samplerLess(RenderPass rp = RP_1ST) const
213 { return m_samplers[rp].empty(); }
214 // ------------------------------------------------------------------------
215 void unload();
216 // ------------------------------------------------------------------------
217 void init()
218 {
219 if (!m_shader_files.empty())
220 {
221 return;
222 }
223 m_init_function(this);
224 }
225 // ------------------------------------------------------------------------
226 bool isSrgbForTextureLayer(unsigned layer) const;
227 // ------------------------------------------------------------------------
228 bool useTangents() const { return m_use_tangents; }
229 // ------------------------------------------------------------------------
230 bool hasTextureLayer(unsigned layer)
231 {
232 for (unsigned rp = RP_1ST; rp < RP_COUNT; rp++)
233 {
234 if (m_samplers[rp].find(layer) != m_samplers[rp].end())
235 {
236 return true;
237 }
238 }
239 return false;
240 }
241};
242
243}
244
245#endif
Utility class, you can inherit from this class to disallow the assignment operator and copy construct...
Definition: no_copy.hpp:26
Definition: sp_per_object_uniform.hpp:31
Definition: sp_shader.hpp:81
Definition: sp_uniform_assigner.hpp:43