Brenta Engine 1.2
Loading...
Searching...
No Matches
shader.hpp
1// SPDX-License-Identifier: MIT
2// Author: Giovanni Santini
3// Mail: giovanni.santini@proton.me
4// Github: @San7o
5
6#pragma once
7
8#include <algorithm>
9#include <brenta/logger.hpp>
10#include <fstream>
11#include <glad/glad.h>
12#include <glm/glm.hpp>
13#include <glm/gtc/matrix_transform.hpp>
14#include <glm/gtc/type_ptr.hpp>
15#include <iostream>
16#include <sstream>
17#include <string>
18#include <unordered_map>
19#include <vector>
20
21namespace brenta
22{
23
24namespace types
25{
26
27typedef std::string shader_name_t;
28
29} // namespace types
30
42class shader
43{
44public:
52 static std::unordered_map<types::shader_name_t, unsigned int> shaders;
53
70 template <typename... Args>
71 static bool create(std::string shader_name, GLenum type, std::string path,
72 Args... args)
73 {
74 std::vector<unsigned int> compiled_shaders = {};
75 if (!compile_shaders(compiled_shaders, type, path, args...))
76 {
77 ERROR("shader: error compiling shader {}", path);
78 return false;
79 }
80
81 /* shader Program */
82 unsigned int ID = glCreateProgram();
83 std::for_each(compiled_shaders.begin(), compiled_shaders.end(),
84 [&ID](auto shader) { glAttachShader(ID, shader); });
85
86 glLinkProgram(ID);
87 if (!shader::check_compile_errors(ID, "PROGRAM"))
88 {
89 return false;
90 }
91
92 shader::shaders.insert({shader_name, ID});
93 std::for_each(compiled_shaders.begin(), compiled_shaders.end(),
94 [](auto shader) { glDeleteShader(shader); });
95 return true;
96 }
97
114 template <typename... Args>
115 static bool create(const GLchar **feedback_varyings, int num_varyings,
116 std::string shader_name, GLenum type, std::string path,
117 Args... args)
118 {
119 std::vector<unsigned int> compiled_shaders = {};
120 if (!compile_shaders(compiled_shaders, type, path, args...))
121 {
122 ERROR("shader: error compiling shader {}", path)
123 return false;
124 }
125
126 /* shader Program */
127 unsigned int ID = glCreateProgram();
128 std::for_each(compiled_shaders.begin(), compiled_shaders.end(),
129 [&ID](auto shader) { glAttachShader(ID, shader); });
130
131 if (feedback_varyings != nullptr)
132 {
133 glTransformFeedbackVaryings(ID, num_varyings, feedback_varyings,
134 GL_INTERLEAVED_ATTRIBS);
135 }
136
137 glLinkProgram(ID);
138 if (!shader::check_compile_errors(ID, "PROGRAM"))
139 {
140 return false;
141 }
142
143 shader::shaders.insert({shader_name, ID});
144 std::for_each(compiled_shaders.begin(), compiled_shaders.end(),
145 [](auto shader) { glDeleteShader(shader); });
146
147 return true;
148 }
149
150 static bool
151 compile_shaders([[maybe_unused]] std::vector<unsigned int> &compiled)
152 {
153 return true;
154 }
155
156 template <typename... Args>
157 static bool compile_shaders(std::vector<unsigned int> &compiled, GLenum type,
158 std::string path, Args... args)
159 {
160 std::string code;
161 std::ifstream file;
162 file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
163
164 try
165 {
166 file.open(path);
167 if (!file.is_open()) throw "Cannot open file";
168 std::stringstream stream;
169 stream << file.rdbuf();
170 file.close();
171 code = stream.str();
172 }
173 catch (std::ifstream::failure &e)
174 {
175 ERROR("shader: error reading shader file: {}", path);
176 return false;
177 }
178
179 if (code.empty())
180 {
181 ERROR("shader: file is empty: {}", path);
182 return false;
183 }
184
185 const char *shader_code = code.c_str();
186 unsigned int shader = glCreateShader(type);
187 glShaderSource(shader, 1, &shader_code, NULL);
188 glCompileShader(shader);
189 if (!shader::check_compile_errors(shader, "SHADER"))
190 {
191 return false;
192 }
193
194 compiled.push_back(shader);
195 return compile_shaders(compiled, args...);
196 }
197
204 static unsigned int get_id(types::shader_name_t shader_name);
205
216 static bool use(types::shader_name_t shader_name);
217
218 // Utility uniform functions
219
228 static bool set_bool(types::shader_name_t shader_name,
229 const GLchar *name, bool value);
238 static bool set_int(types::shader_name_t shader_name, const GLchar *name,
239 int value);
248 static bool set_float(types::shader_name_t shader_name,
249 const GLchar *name, float value);
258 static bool set_mat4(types::shader_name_t shader_name, const GLchar *name,
259 glm::mat4 value);
270 static bool set_vec3(types::shader_name_t shader_name, const GLchar *name,
271 float x, float y, float z);
280 static bool set_vec3(types::shader_name_t shader_name, const GLchar *name,
281 glm::vec3 value);
282
283private:
284
285 static bool check_compile_errors(unsigned int shader, std::string type);
286
287};
288
289} // namespace brenta
Shader class.
Definition shader.hpp:43
static bool set_mat4(types::shader_name_t shader_name, const GLchar *name, glm::mat4 value)
Set a 4x4 matrix in the shader.
Definition shader.cpp:114
static std::unordered_map< types::shader_name_t, unsigned int > shaders
Map of shaders.
Definition shader.hpp:52
static bool set_bool(types::shader_name_t shader_name, const GLchar *name, bool value)
Set a boolean in the shader.
Definition shader.cpp:37
static bool create(const GLchar **feedback_varyings, int num_varyings, std::string shader_name, GLenum type, std::string path, Args... args)
Create a new shader with feedback varyings.
Definition shader.hpp:115
static bool set_vec3(types::shader_name_t shader_name, const GLchar *name, float x, float y, float z)
Set a 3D vector in the shader.
Definition shader.cpp:140
static bool create(std::string shader_name, GLenum type, std::string path, Args... args)
Create a new shader.
Definition shader.hpp:71
static unsigned int get_id(types::shader_name_t shader_name)
Get the ID of a shader.
Definition shader.cpp:14
static bool set_int(types::shader_name_t shader_name, const GLchar *name, int value)
Set an integer in the shader.
Definition shader.cpp:63
static bool use(types::shader_name_t shader_name)
Use the shader.
Definition shader.cpp:24
static bool set_float(types::shader_name_t shader_name, const GLchar *name, float value)
Set a float in the shader.
Definition shader.cpp:89