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