1 #include "Shaders.h"
2 bool initialized = false;
3
int2str(const int n)4 std::string int2str(const int n)
5 {
6 std::ostringstream stm;
7 stm << n;
8 return stm.str();
9 }
10
ComputeShader()11 ComputeShader::ComputeShader()
12 {
13
14 }
15
ComputeShader(const std::string file_path)16 ComputeShader::ComputeShader(const std::string file_path)
17 {
18 LoadShader(file_path);
19 }
20
LoadFileText(fs::path path)21 std::string ComputeShader::LoadFileText(fs::path path)
22 {
23 std::string text;
24 std::ifstream TextStream(path, std::ios::in);
25 if (TextStream.is_open())
26 {
27 std::string Line = "";
28 while (getline(TextStream, Line))
29 text += Line + "\n";
30 TextStream.close();
31 }
32 else
33 {
34 ERROR_MSG("Impossible to open text file");
35 }
36 return text;
37 }
38
Delete()39 void ComputeShader::Delete()
40 {
41 glDeleteProgram(ProgramID);
42 }
43
44
LoadShader(const std::string file_path)45 void ComputeShader::LoadShader(const std::string file_path)
46 {
47 // Create the shaders
48 GLuint ComputeShaderID = glCreateShader(GL_COMPUTE_SHADER);
49
50 // Read the Compute Shader code from the file
51 std::string ComputeShaderCode = PreprocessIncludes(fs::path(file_path));
52
53 GLint Result = GL_FALSE;
54 int InfoLogLength;
55
56 // Compile Compute Shader
57 char const * ComputeSourcePointer = ComputeShaderCode.c_str();
58 glShaderSource(ComputeShaderID, 1, &ComputeSourcePointer, NULL);
59 glCompileShader(ComputeShaderID);
60
61 // Check Compute Shader
62 glGetShaderiv(ComputeShaderID, GL_COMPILE_STATUS, &Result);
63 glGetShaderiv(ComputeShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
64 if (Result == GL_FALSE)
65 {
66 std::vector<char> ComputeShaderErrorMessage(InfoLogLength + 1);
67 glGetShaderInfoLog(ComputeShaderID, InfoLogLength, NULL, &ComputeShaderErrorMessage[0]);
68 ERROR_MSG(("Compute shader compilation error. \n" + std::string(&ComputeShaderErrorMessage[0])).c_str());
69 SaveErrors(file_path, ComputeShaderCode, std::string(&ComputeShaderErrorMessage[0]));
70 }
71
72 // Link the program
73 ProgramID = glCreateProgram();
74 glAttachShader(ProgramID, ComputeShaderID);
75 glLinkProgram(ProgramID);
76
77 // Check the program
78 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
79 glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
80 if (Result == GL_FALSE)
81 {
82 std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
83 glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
84 ERROR_MSG(("Compute program error. \n" + std::string(&ProgramErrorMessage[0])).c_str());
85 }
86
87 glDetachShader(ProgramID, ComputeShaderID);
88
89 glDeleteShader(ComputeShaderID);
90 }
91
Run(vec2 global)92 void ComputeShader::Run(vec2 global)
93 {
94 glUseProgram(ProgramID);
95 glDispatchCompute(ceil(global.x), ceil(global.y), 1);
96 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
97 }
98
setUniform(std::string name,float X,float Y)99 void ComputeShader::setUniform(std::string name, float X, float Y)
100 {
101 glUseProgram(ProgramID);
102 GLuint A = glGetUniformLocation(ProgramID, name.c_str());
103 glUniform2f(A, X, Y);
104 }
105
setUniform(std::string name,float X,float Y,float Z)106 void ComputeShader::setUniform(std::string name, float X, float Y, float Z)
107 {
108 glUseProgram(ProgramID);
109 GLuint A = glGetUniformLocation(ProgramID, name.c_str());
110 glUniform3f(A, X, Y, Z);
111 }
112
setUniform(std::string name,float X)113 void ComputeShader::setUniform(std::string name, float X)
114 {
115 glUseProgram(ProgramID);
116 GLuint A = glGetUniformLocation(ProgramID, name.c_str());
117 glUniform1f(A, X);
118 }
119
setUniform(std::string name,int X)120 void ComputeShader::setUniform(std::string name, int X)
121 {
122 glUseProgram(ProgramID);
123 GLuint A = glGetUniformLocation(ProgramID, name.c_str());
124 glUniform1i(A, X);
125 }
126
setUniform(std::string name,glm::mat3 X,bool transpose)127 void ComputeShader::setUniform(std::string name, glm::mat3 X, bool transpose)
128 {
129 glUseProgram(ProgramID);
130 GLuint A = glGetUniformLocation(ProgramID, name.c_str());
131 glUniformMatrix3fv(A, 1, transpose, glm::value_ptr(X));
132 }
133
setUniform(std::string name,glm::vec3 X)134 void ComputeShader::setUniform(std::string name, glm::vec3 X)
135 {
136 glUseProgram(ProgramID);
137 GLuint A = glGetUniformLocation(ProgramID, name.c_str());
138 glUniform3fv(A, 1, glm::value_ptr(X));
139 }
140
setUniform(std::string name,glm::vec2 X)141 void ComputeShader::setUniform(std::string name, glm::vec2 X)
142 {
143 glUseProgram(ProgramID);
144 GLuint A = glGetUniformLocation(ProgramID, name.c_str());
145 glUniform2fv(A, 1, glm::value_ptr(X));
146 }
147
setUniform(int i,GLuint tid)148 void ComputeShader::setUniform(int i, GLuint tid)
149 {
150 glUseProgram(ProgramID);
151 GLuint A = glGetUniformLocation(ProgramID, ("iTexture" + int2str(i)).c_str());
152 glActiveTexture(GL_TEXTURE0 + i);
153 glBindTexture(GL_TEXTURE_2D, tid);
154 glUniform1i(A, i);
155 }
156
setCameraObj(std::string name,gl_camera cam)157 void ComputeShader::setCameraObj(std::string name, gl_camera cam)
158 {
159 setUniform(name + ".position", cam.position);
160 setUniform(name + ".bokeh", cam.bokeh);
161 setUniform(name + ".dirx", cam.dirx);
162 setUniform(name + ".diry", cam.diry);
163 setUniform(name + ".dirz", cam.dirz);
164 setUniform(name + ".aspect_ratio", cam.aspect_ratio);
165 setUniform(name + ".exposure", cam.exposure);
166 setUniform(name + ".focus", cam.focus);
167 setUniform(name + ".FOV", cam.FOV);
168 setUniform(name + ".mblur", cam.mblur);
169 setUniform(name + ".position", cam.position);
170 setUniform(name + ".resolution", cam.resolution);
171 setUniform(name + ".size", cam.size);
172 setUniform(name + ".bloomradius", cam.bloomradius);
173 setUniform(name + ".bloomintensity", cam.bloomintensity);
174 setUniform(name + ".speckle", cam.speckle);
175 setUniform(name + ".cross_eye", cam.cross_eye);
176 setUniform(name + ".eye_separation", cam.eye_separation);
177 setUniform("iFrame", cam.iFrame);
178 }
179
setCamera(gl_camera cam)180 void ComputeShader::setCamera(gl_camera cam)
181 {
182 setCameraObj("Camera", cam);
183 setCameraObj("PrevCamera", prev_camera);
184 prev_camera = cam;
185 }
186
getNativeHandle()187 GLuint ComputeShader::getNativeHandle()
188 {
189 return ProgramID;
190 }
191
INIT()192 bool INIT()
193 {
194 if (initialized)
195 {
196 return true;
197 }
198 if ( glewInit() != GLEW_OK)
199 {
200 ERROR_MSG("Failed to initialize GLEW\n");
201 return false;
202 }
203 initialized = true;
204 return true;
205 }
206
207
PreprocessIncludes(const fs::path & filename,int level)208 std::string ComputeShader::PreprocessIncludes(const fs::path& filename, int level /*= 0 */)
209 {
210 if (level > 32)
211 ERROR_MSG("Header inclusion depth limit reached, might be caused by cyclic header inclusion");
212 using namespace std;
213
214 //match regular expression
215 static const regex re("^[ ]*#include\\s*[\"<](.*)[\">].*");
216 stringstream input;
217 stringstream output;
218 input << LoadFileText(filename);
219
220 smatch matches;
221 string line;
222 while (std::getline(input, line))
223 {
224 if (regex_search(line, matches, re))
225 {
226 //add the code from the included file
227 std::string include_file = compute_folder + "/" + matches[1].str();
228 output << PreprocessIncludes(include_file, level + 1) << endl;
229 }
230 else
231 {
232 output << line << "\n";
233 }
234 }
235 return output.str();
236 }
237
SaveErrors(const fs::path & filename,std::string code,std::string errors)238 void ComputeShader::SaveErrors(const fs::path& filename, std::string code, std::string errors)
239 {
240 fs::path outf = (filename.parent_path() / filename.filename()).concat("_error.txt");
241 std::ofstream error_out(outf);
242
243 error_out << code << std::endl << errors;
244 error_out.close();
245 }
246