sculpto
gl_shader.cpp
Go to the documentation of this file.
1/*!****************************************************************//*!*
2 * \file gl_shader.cpp
3 * \brief OpenGL shader program class implementatino module.
4 *
5 * \author Sabitov Kirill
6 * \date 27 June 2022
7 *********************************************************************/
8
9#include "sclpch.h"
10#include "gl_shader.h"
11
12int scl::gl_shader_program::CurrentlyBoundShaderId {};
13
14constexpr GLenum scl::gl_shader_program::GetGLShaderType(shader_type Type)
15{
16 switch (Type)
17 {
18 case shader_type::VERTEX: return GL_VERTEX_SHADER;
19 case shader_type::GEOMETRY: return GL_GEOMETRY_SHADER;
20 case shader_type::PIXEL: return GL_FRAGMENT_SHADER;
21 case shader_type::COMPUTE: return GL_COMPUTE_SHADER;
22 }
23
24 SCL_CORE_ASSERT(0, "Unknown shader type.");
25 return GLenum();
26}
27
28bool scl::gl_shader_program::CompileShader(const shader_props &Shader, GLuint &ShaderId)
29{
30 if (ShaderId != 0) glDeleteShader(ShaderId);
31 SCL_CORE_ASSERT((ShaderId = glCreateShader(GetGLShaderType(Shader.Type))) != 0,
32 "Error in creation OpenGL shader primitive.");
33
34 int res {};
35 // Temporary object creation to prevent dangling pointer
36 std::string source_str = Shader.Source;
37 const char *source = source_str.c_str();
38 char ErrorLog[1000] {};
39 glShaderSource(ShaderId, 1, &source, nullptr);
40 glCompileShader(ShaderId);
41 glGetShaderiv(ShaderId, GL_COMPILE_STATUS, &res);
42 if (!res)
43 {
44 glGetShaderInfoLog(ShaderId, sizeof(ErrorLog), &res, ErrorLog);
45 SCL_CORE_ERROR("Error in compiling shader during shader program \"{}\" creation.\nError log:\n{}", DebugName, std::string(ErrorLog));
46 return false;
47 }
48
49 return true;
50}
51
52bool scl::gl_shader_program::CompileProgram(const std::vector<GLuint> &Shaders)
53{
54 SCL_CORE_ASSERT((Id = glCreateProgram()) != 0, "Error in creation OpenGL shader program premitive.");
55
56 int res {};
57 char ErrorLog[1000] {};
58 for (GLuint shader_id : Shaders) glAttachShader(Id, shader_id);
59 glLinkProgram(Id);
60 glGetProgramiv(Id, GL_LINK_STATUS, &res);
61 if (!res)
62 {
63 glGetProgramInfoLog(Id, sizeof(ErrorLog), &res, ErrorLog);
64 SCL_CORE_ERROR("Error in linking shader program \"{}\".\nError log:\n{}", DebugName, std::string(ErrorLog));
65 return false;
66 }
67 return true;
68}
69
70bool scl::gl_shader_program::Create(const std::vector<shader_props> &Shaders)
71{
72 u32 shaders_count = (u32)Shaders.size();
73
74 // Compile all passed shaders
75 std::vector<GLuint> shaders_ids(shaders_count);
76 for (u32 i = 0; i < shaders_count; i++)
77 if (!CompileShader(Shaders[i], shaders_ids[i])) {
78 // Delete all created shaders
79 for (auto shader_id : shaders_ids)
80 if (shader_id != 0) glDeleteShader(shader_id);
81 return false;
82 }
83
84 // Compile shader program
85 if (!CompileProgram(shaders_ids))
86 {
87 // Deatach and delete all created shaders
88 for (auto shader_id : shaders_ids) {
89 if (shader_id != 0) {
90 if (Id != 0) glDetachShader(Id, shader_id);
91 glDeleteShader(shader_id);
92 }
93 }
94 if (Id != 0) glDeleteProgram(Id), Id = 0;
95 return false;
96 }
97
98 SCL_CORE_SUCCES("OpenGL Shader with id {} created.", Id);
99 return true;
100}
101
102int scl::gl_shader_program::GetOrCacheLocation(const std::string &Name) const
103{
104 auto it = VariablesLocations.find(Name);
105 if (it != VariablesLocations.end()) return it->second;
106
107 int location = glGetUniformLocation(Id, Name.c_str());
108 VariablesLocations.emplace(Name, location);
109 if (location == -1)
110 SCL_CORE_WARN("Currently bound shader \"{}\" don't have active variable with name \"{}\".",
111 DebugName, Name);
112 return location;
113}
114
115bool scl::gl_shader_program::CheckIfShaderBinded() const
116{
117 if (Id != gl_shader_program::CurrentlyBoundShaderId)
118 {
119 if (!ShaderNotBindedErrorAlreadyShown)
120 {
121 SCL_CORE_ERROR("Trying set shader variable to shader \"{}\", which is not binded shader.", DebugName);
122 ShaderNotBindedErrorAlreadyShown = true;
123 }
124 return false;
125 }
126 return true;
127}
128
129scl::gl_shader_program::gl_shader_program(const std::vector<shader_props> &Shaders, const std::string &DebugName) :
130 shader_program(DebugName)
131{
132 Create(Shaders);
133}
134
136{
137 Free();
138}
139
141{
142 if (glIsProgram(Id))
143 {
144 glUseProgram(Id);
145 gl_shader_program::CurrentlyBoundShaderId = Id;
146 }
147}
148
150{
151 glUseProgram(0);
152 CurrentlyBoundShaderId = 0;
153}
154
155void scl::gl_shader_program::Update(const std::vector<shader_props> &Shaders)
156{
157 Free();
158 Create(Shaders);
159 SCL_CORE_INFO("OpenGL Shader with id {} updated.", Id);
160}
161
163{
164 VariablesLocations.clear();
165 ShaderNotBindedErrorAlreadyShown = false;
166
167 if (Id == 0) return;
168
169 int shaders_count {};
170 GLuint shaders_ids[5] {};
171 glGetAttachedShaders(Id, 5, &shaders_count, shaders_ids);
172
173 for (int i = 0; i < shaders_count; i++)
174 {
175 glDetachShader(Id, shaders_ids[i]);
176 glDeleteShader(shaders_ids[i]);
177 }
178 glDeleteProgram(Id);
179 SCL_CORE_INFO("OpenGL Shader with id {} freed.", Id);
180 Id = 0;
181}
182
183bool scl::gl_shader_program::SetBool(const std::string &Name, bool Value) const
184{
185 if (!CheckIfShaderBinded()) return false;
186 int location = GetOrCacheLocation(Name);
187 if (location == -1) return false;
188
189 glUniform1i(location, Value);
190 return true;
191}
192
193bool scl::gl_shader_program::SetFloat(const std::string &Name, float Value) const
194{
195 if (!CheckIfShaderBinded()) return false;
196 int location = GetOrCacheLocation(Name);
197 if (location == -1) return false;
198
199 glUniform1f(location, Value);
200 return true;
201}
202
203bool scl::gl_shader_program::SetFloat2(const std::string &Name, const vec2 &Value) const
204{
205 if (!CheckIfShaderBinded()) return false;
206 int location = GetOrCacheLocation(Name);
207 if (location == -1) return false;
208
209 glUniform2fv(location, 1, (float *)&Value);
210 return true;
211}
212
213bool scl::gl_shader_program::SetFloat3(const std::string &Name, const vec3 &Value) const
214{
215 if (!CheckIfShaderBinded()) return false;
216 int location = GetOrCacheLocation(Name);
217 if (location == -1) return false;
218
219 glUniform3fv(location, 1, (float *)&Value);
220 return true;
221}
222
223bool scl::gl_shader_program::SetFloat4(const std::string &Name, const vec4 &Value) const
224{
225 if (!CheckIfShaderBinded()) return false;
226 int location = GetOrCacheLocation(Name);
227 if (location == -1) return false;
228
229 glUniform4fv(location, 1, (float *)&Value);
230 return true;
231}
232
233bool scl::gl_shader_program::SetInt(const std::string &Name, int Value) const
234{
235 if (!CheckIfShaderBinded()) return false;
236 int location = GetOrCacheLocation(Name);
237 if (location == -1) return false;
238
239 glUniform1i(location, Value);
240 return true;
241}
242
243bool scl::gl_shader_program::SetInt2(const std::string &Name, const ivec2 &Value) const
244{
245 if (!CheckIfShaderBinded()) return false;
246 int location = GetOrCacheLocation(Name);
247 if (location == -1) return false;
248
249 glUniform2iv(location, 1, (int *)&Value);
250 return true;
251}
252
253bool scl::gl_shader_program::SetInt3(const std::string &Name, const ivec3 &Value) const
254{
255 if (!CheckIfShaderBinded()) return false;
256 int location = GetOrCacheLocation(Name);
257 if (location == -1) return false;
258
259 glUniform3iv(location, 1, (int *)&Value);
260 return true;
261}
262
263bool scl::gl_shader_program::SetInt4(const std::string &Name, const ivec4 &Value) const
264{
265 if (!CheckIfShaderBinded()) return false;
266 int location = GetOrCacheLocation(Name);
267 if (location == -1) return false;
268
269 glUniform4iv(location, 1, (int *)&Value);
270 return true;
271}
272
273bool scl::gl_shader_program::SetUInt(const std::string &Name, u32 Value) const
274{
275 if (!CheckIfShaderBinded()) return false;
276 int location = GetOrCacheLocation(Name);
277 if (location == -1) return false;
278
279 glUniform1ui(location, Value);
280 return true;
281}
282
283bool scl::gl_shader_program::SetUInt2(const std::string &Name, const uvec2 &Value) const
284{
285 if (!CheckIfShaderBinded()) return false;
286 int location = GetOrCacheLocation(Name);
287 if (location == -1) return false;
288
289 glUniform2uiv(location, 1, (u32 *)&Value);
290 return true;
291}
292
293bool scl::gl_shader_program::SetUInt3(const std::string &Name, const uvec3 &Value) const
294{
295 if (!CheckIfShaderBinded()) return false;
296 int location = GetOrCacheLocation(Name);
297 if (location == -1) return false;
298
299 glUniform3uiv(location, 1, (u32 *)&Value);
300 return true;
301}
302
303bool scl::gl_shader_program::SetUInt4(const std::string &Name, const uvec4 &Value) const
304{
305 if (!CheckIfShaderBinded()) return false;
306 int location = GetOrCacheLocation(Name);
307 if (location == -1) return false;
308
309 glUniform4uiv(location, 1, (u32 *)&Value);
310 return true;
311}
312
313bool scl::gl_shader_program::SetMatr3(const std::string &Name, const matr3 &Value) const
314{
315 if (!CheckIfShaderBinded()) return false;
316 int location = GetOrCacheLocation(Name);
317 if (location == -1) return false;
318
319 glUniformMatrix3fv(location, 1, FALSE, (float *)&Value);
320 return true;
321}
322
323bool scl::gl_shader_program::SetMatr4(const std::string &Name, const matr4 &Value) const
324{
325 if (!CheckIfShaderBinded()) return false;
326 int location = GetOrCacheLocation(Name);
327 if (location == -1) return false;
328
329 glUniformMatrix4fv(location, 1, FALSE, (float *)&Value);
330 return true;
331}
332
333bool scl::gl_shader_program::SetBool(int Location, bool Value) const
334{
335 if (!CheckIfShaderBinded()) return false;
336 glUniform1i(Location, Value);
337 return true;
338}
339
340bool scl::gl_shader_program::SetFloat(int Location, float Value) const
341{
342 if (!CheckIfShaderBinded()) return false;
343 glUniform1f(Location, Value);
344 return true;
345}
346
347bool scl::gl_shader_program::SetFloat2(int Location, const vec2 &Value) const
348{
349 if (!CheckIfShaderBinded()) return false;
350 glUniform2fv(Location, 1, (float *)&Value);
351 return true;
352}
353
354bool scl::gl_shader_program::SetFloat3(int Location, const vec3 &Value) const
355{
356 if (!CheckIfShaderBinded()) return false;
357 glUniform3fv(Location, 1, (float *)&Value);
358 return true;
359}
360
361bool scl::gl_shader_program::SetFloat4(int Location, const vec4 &Value) const
362{
363 if (!CheckIfShaderBinded()) return false;
364 glUniform4fv(Location, 1, (float *)&Value);
365 return true;
366}
367
368bool scl::gl_shader_program::SetInt(int Location, int Value) const
369{
370 if (!CheckIfShaderBinded()) return false;
371 glUniform1i(Location, Value);
372 return true;
373}
374
375bool scl::gl_shader_program::SetInt2(int Location, const ivec2 &Value) const
376{
377 if (!CheckIfShaderBinded()) return false;
378 glUniform2iv(Location, 1, (int *)&Value);
379 return true;
380}
381
382bool scl::gl_shader_program::SetInt3(int Location, const ivec3 &Value) const
383{
384 if (!CheckIfShaderBinded()) return false;
385 glUniform3iv(Location, 1, (int *)&Value);
386 return true;
387}
388
389bool scl::gl_shader_program::SetInt4(int Location, const ivec4 &Value) const
390{
391 if (!CheckIfShaderBinded()) return false;
392 glUniform4iv(Location, 1, (int *)&Value);
393 return true;
394}
395
396bool scl::gl_shader_program::SetUInt(int Location, u32 Value) const
397{
398 if (!CheckIfShaderBinded()) return false;
399 glUniform1ui(Location, Value);
400 return true;
401}
402
403bool scl::gl_shader_program::SetUInt2(int Location, const uvec2 &Value) const
404{
405 if (!CheckIfShaderBinded()) return false;
406 glUniform2uiv(Location, 1, (u32 *)&Value);
407 return true;
408}
409
410bool scl::gl_shader_program::SetUInt3(int Location, const uvec3 &Value) const
411{
412 if (!CheckIfShaderBinded()) return false;
413 glUniform3uiv(Location, 1, (u32 *)&Value);
414 return true;
415}
416
417bool scl::gl_shader_program::SetUInt4(int Location, const uvec4 &Value) const
418{
419 if (!CheckIfShaderBinded()) return false;
420 glUniform4uiv(Location, 1, (u32 *)&Value);
421 return true;
422}
423
424bool scl::gl_shader_program::SetMatr3(int Location, const matr3 &Value) const
425{
426 if (!CheckIfShaderBinded()) return false;
427 glUniformMatrix3fv(Location, 1, FALSE, (float *)&Value);
428 return true;
429}
430
431bool scl::gl_shader_program::SetMatr4(int Location, const matr4 &Value) const
432{
433 if (!CheckIfShaderBinded()) return false;
434 glUniformMatrix4fv(Location, 1, FALSE, (float *)&Value);
435 return true;
436}
#define SCL_CORE_ASSERT(expr,...)
Definition: assert.h:69
bool SetInt(const std::string &Name, int Value) const override
Definition: gl_shader.cpp:233
void Bind() const override
Definition: gl_shader.cpp:140
bool SetInt3(const std::string &Name, const ivec3 &Value) const override
Definition: gl_shader.cpp:253
bool SetInt4(const std::string &Name, const ivec4 &Value) const override
Definition: gl_shader.cpp:263
gl_shader_program(const std::vector< shader_props > &Shaders, const std::string &DebugName)
Definition: gl_shader.cpp:129
bool SetBool(const std::string &Name, bool Value) const override
Definition: gl_shader.cpp:183
bool SetUInt2(const std::string &Name, const uvec2 &Value) const override
Definition: gl_shader.cpp:283
void Unbind() const override
Definition: gl_shader.cpp:149
bool SetFloat4(const std::string &Name, const vec4 &Value) const override
Definition: gl_shader.cpp:223
bool SetUInt3(const std::string &Name, const uvec3 &Value) const override
Definition: gl_shader.cpp:293
bool SetMatr4(const std::string &Name, const matr4 &Value) const override
Definition: gl_shader.cpp:323
void Update(const std::vector< shader_props > &Shaders) override
Definition: gl_shader.cpp:155
bool SetMatr3(const std::string &Name, const matr3 &Value) const override
Definition: gl_shader.cpp:313
void Free() override
Definition: gl_shader.cpp:162
bool SetFloat(const std::string &Name, float Value) const override
Definition: gl_shader.cpp:193
bool SetFloat3(const std::string &Name, const vec3 &Value) const override
Definition: gl_shader.cpp:213
bool SetFloat2(const std::string &Name, const vec2 &Value) const override
Definition: gl_shader.cpp:203
bool SetUInt4(const std::string &Name, const uvec4 &Value) const override
Definition: gl_shader.cpp:303
bool SetInt2(const std::string &Name, const ivec2 &Value) const override
Definition: gl_shader.cpp:243
bool SetUInt(const std::string &Name, u32 Value) const override
Definition: gl_shader.cpp:273
OpenGL shader program class definition module.
#define SCL_CORE_SUCCES(...)
Definition: log.h:42
#define SCL_CORE_WARN(...)
Definition: log.h:43
#define SCL_CORE_INFO(...)
Definition: log.h:41
#define SCL_CORE_ERROR(...)
Definition: log.h:44
uint32_t u32
Definition: math_common.h:21
shader_type
Definition: shader.h:17
Sculpto library prehompiled header. Defines common definitions, includes commonly used modules.