jGL
Loading...
Searching...
No Matches
shader.h
Go to the documentation of this file.
1#ifndef SHADER
2#define SHADER
3
4#include <jGL/uniform.h>
5
6#include <glm/glm.hpp>
7#include <glm/gtc/type_ptr.hpp>
8
9
10#include <regex>
11#include <unordered_map>
12#include <iostream>
13#include <fstream>
14#include <memory>
15#include <jLog/jLog.h>
16#include <typeinfo>
17
18namespace jGL
19{
20
21 template <class T>
22 const std::regex UNIFORM_DATA_REGEX;
23
24 template <> inline
25 const std::regex UNIFORM_DATA_REGEX<int> = std::regex("uniform int (\\S+);");
26 template <> inline
27 const std::regex UNIFORM_DATA_REGEX<float> = std::regex("uniform float (\\S+);");
28 template <> inline
29 const std::regex UNIFORM_DATA_REGEX<glm::vec2> = std::regex("uniform vec2 (\\S+);");
30 template <> inline
31 const std::regex UNIFORM_DATA_REGEX<glm::vec4> = std::regex("uniform vec4 (\\S+);");
32 template <> inline
33 const std::regex UNIFORM_DATA_REGEX<glm::mat4> = std::regex("uniform mat4 (\\S+);");
34 template <> inline
35 const std::regex UNIFORM_DATA_REGEX<Sampler2D> = std::regex("uniform(\\slowp\\s|\\shighp\\s|\\smediump\\s|\\s)sampler2D (\\S+);");
36
37
43 struct Shader
44 {
51 Shader(const char * v, const char * f)
52 : vertex(v), fragment(f)
53 {
55 }
56
61 : vertex(""),fragment("")
62 {}
63
70 Shader(std::string path, std::string name);
71
72 virtual ~Shader() = default;
73
74 bool operator==(const Shader & s)
75 {
76 return this->vertex == s.vertex && this->fragment == s.fragment;
77 }
78
85 bool lint();
86
94 template <class T>
95 void setUniform(std::string name, T value)
96 {
97 if (uniforms.find(name) == uniforms.end())
98 {
99 throw std::runtime_error("could not find uniform: " + name);
100 }
101
102 AbstractjGLUniform * uniform = uniforms[name].get();
103
104 if (dynamic_cast<jGLUniform<T>*>(uniform) == nullptr)
105 {
106 return;
107 }
108
109 jGLUniform<T> * u = dynamic_cast<jGLUniform<T>*>(uniform);
110 if (u != nullptr){ setValue(u, value); return; }
111
112 return;
113 }
114
115 const std::string & getVertex() const { return vertex; }
116 const std::string & getFragment() const { return fragment; }
117
125 template <class T>
126 jGLUniform<T> getUniform(std::string name)
127 {
128 if (uniforms.find(name) == uniforms.end())
129 {
130 return NULL_UNIFORM<T>;
131 }
132
133 AbstractjGLUniform * uniform = uniforms[name].get();
134
135 if (dynamic_cast<jGLUniform<T>*>(uniform) == nullptr)
136 {
137 return NULL_UNIFORM<T>;
138 }
139
140 jGLUniform<T> * u = dynamic_cast<jGLUniform<T>*>(uniform);
141 if (u != nullptr){ return *u; }
142
143 return NULL_UNIFORM<T>;
144 }
145
151 std::vector<std::string> getUniformNames()
152 {
153 std::vector<std::string> v;
154 for (auto it = uniforms.cbegin(); it != uniforms.cend(); it++)
155 {
156 v.push_back(it->first);
157 }
158 return v;
159 }
160
165 virtual void use() = 0;
166
172 std::string displayVertexSource() const { return formatWithLineNumbers(vertex); }
173
179 std::string displayFragmentSource() const { return formatWithLineNumbers(fragment); }
180
181 protected:
182
183 std::string vertex;
184 std::string fragment;
185
186 std::unordered_map<std::string, std::shared_ptr<AbstractjGLUniform>> uniforms;
187
188 std::string parseShaderSource(std::ifstream & file);
189
190 virtual void compile() = 0;
191
192 bool parseUniforms();
193
194 std::string formatWithLineNumbers(std::string shader) const
195 {
196 if (shader.length() == 0) { return shader; }
197 std::string source = "1: ";
198 uint32_t line = 1;
199 auto iter = shader.begin();
200 while (iter != shader.end())
201 {
202 if (*iter == '\n' && iter+1 != shader.end())
203 {
204 line += 1;
205 source += "\n" + std::to_string(line)+": ";
206 }
207 else
208 {
209 source += *iter;
210 }
211 iter++;
212 }
213 return source;
214 }
215
216 template <class T>
217 void detectUniformsAndCreate(std::string code)
218 {
219 const std::regex r = UNIFORM_DATA_REGEX<T>;
220
221 auto start = std::sregex_iterator(code.begin(), code.end(), r);
222 auto end = std::sregex_iterator();
223 for (std::sregex_iterator it = start; it != end; it++)
224 {
225 std::string match = (*it).str();
226 if (match.find("lowp") != std::string::npos)
227 {
228 // uniform lowp TYPE NAME;
229 match.erase(0, match.find("lowp")+4);
230 // " TYPE NAME;"
231 }
232 if (match.find("highp") != std::string::npos)
233 {
234 // uniform highp TYPE NAME;
235 match.erase(0, match.find("highp")+5);
236 // " TYPE NAME;"
237 }
238 // found "uniform TYPE NAME;" or " TYPE NAME;"
239 match.erase(0, match.find(" ")+1);
240 match.erase(0, match.find(" ")+1);
241 std::string name = match.substr(0, match.find(";"));
242 std::shared_ptr<jGLUniform<T>> u = std::make_shared<jGLUniform<T>>(jGLUniform<T>(name,T(0)));
243 uniforms[name] = u;
244 }
245
246 }
247
248 // cannot have spec in class scope https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282
249 // also cannot use partial spec workaround because non-class, non-variable partial
250 // specialization is not allowed
251 // https://stackoverflow.com/questions/8061456/c-function-template-partial-specialization
252 // so the template dispatches to these guys
253
254 virtual void setValue(jGLUniform<int> * u, int value)
255 {
256 u->value = value;
257
258 }
259
260 virtual void setValue(jGLUniform<Sampler2D> * u, Sampler2D value)
261 {
262 u->value = value;
263 }
264
265 virtual void setValue(jGLUniform<float> * u, float value)
266 {
267 u->value = value;
268 }
269
270 virtual void setValue(jGLUniform<glm::vec2> * u, glm::vec2 value)
271 {
272 u->value = value;
273 }
274
275 virtual void setValue(jGLUniform<glm::vec4> * u, glm::vec4 value)
276 {
277 u->value = value;
278 }
279
280 virtual void setValue(jGLUniform<glm::mat4> * u, glm::mat4 value)
281 {
282 u->value = value;
283 }
284 };
285}
286
287#endif /* SHADER */
A drawable graphic.
Definition id.h:10
const std::regex UNIFORM_DATA_REGEX< int >
Definition shader.h:25
const std::regex UNIFORM_DATA_REGEX
Definition shader.h:22
const std::regex UNIFORM_DATA_REGEX< float >
Definition shader.h:27
const std::regex UNIFORM_DATA_REGEX< Sampler2D >
Definition shader.h:35
Definition uniform.h:10
Definition uniform.h:33
Generic shader program with vertex and fragment shader.
Definition shader.h:44
virtual ~Shader()=default
std::vector< std::string > getUniformNames()
Get all the parsed uniforms in the Shader.
Definition shader.h:151
std::string displayFragmentSource() const
Display the fragment shader with line numbers.
Definition shader.h:179
Shader()
Construct an empty Shader.
Definition shader.h:60
virtual void setValue(jGLUniform< glm::mat4 > *u, glm::mat4 value)
Definition shader.h:280
std::unordered_map< std::string, std::shared_ptr< AbstractjGLUniform > > uniforms
Definition shader.h:186
std::string displayVertexSource() const
Display the vertex shader with line numbers.
Definition shader.h:172
virtual void setValue(jGLUniform< int > *u, int value)
Definition shader.h:254
std::string parseShaderSource(std::ifstream &file)
Definition shader.cpp:22
const std::string & getFragment() const
Definition shader.h:116
virtual void setValue(jGLUniform< float > *u, float value)
Definition shader.h:265
virtual void use()=0
Use the shader.
std::string fragment
Definition shader.h:184
bool lint()
Check for common shader errors.
Definition shader.cpp:77
virtual void setValue(jGLUniform< glm::vec4 > *u, glm::vec4 value)
Definition shader.h:275
void setUniform(std::string name, T value)
Set a Uniform to a value.
Definition shader.h:95
void detectUniformsAndCreate(std::string code)
Definition shader.h:217
std::string vertex
Definition shader.h:183
bool operator==(const Shader &s)
Definition shader.h:74
virtual void compile()=0
virtual void setValue(jGLUniform< Sampler2D > *u, Sampler2D value)
Definition shader.h:260
Shader(const char *v, const char *f)
Construct a Shader from a vertex and fragment source.
Definition shader.h:51
const std::string & getVertex() const
Definition shader.h:115
std::string formatWithLineNumbers(std::string shader) const
Definition shader.h:194
jGLUniform< T > getUniform(std::string name)
Get a Uniform by name.
Definition shader.h:126
virtual void setValue(jGLUniform< glm::vec2 > *u, glm::vec2 value)
Definition shader.h:270
bool parseUniforms()
Definition shader.cpp:33
Definition uniform.h:22
T value
Definition uniform.h:27