diff options
Diffstat (limited to 'src/renderer.cpp')
-rw-r--r-- | src/renderer.cpp | 862 |
1 files changed, 0 insertions, 862 deletions
diff --git a/src/renderer.cpp b/src/renderer.cpp deleted file mode 100644 index f840180..0000000 --- a/src/renderer.cpp +++ /dev/null | |||
@@ -1,862 +0,0 @@ | |||
1 | #include "renderer.h" | ||
2 | #include <string> | ||
3 | #include <fstream> | ||
4 | #include <vector> | ||
5 | #include <cstdio> | ||
6 | #include <cstring> | ||
7 | #include <cstdlib> | ||
8 | #include <glm/glm.hpp> | ||
9 | #include <glm/gtc/matrix_transform.hpp> | ||
10 | #include "consts.h" | ||
11 | |||
12 | // include stb_image | ||
13 | #define STB_IMAGE_IMPLEMENTATION | ||
14 | #define STBI_ONLY_PNG | ||
15 | #define STBI_ONLY_BMP | ||
16 | #include "stb_image.h" | ||
17 | |||
18 | static bool rendererInitialized = false; | ||
19 | |||
20 | static GLFWwindow* window; | ||
21 | |||
22 | static GLuint generic_framebuffer; // The framebuffer | ||
23 | static GLuint bloom_framebuffer; | ||
24 | static GLuint bloom_depthbuffer; | ||
25 | static int buffer_width = 1024; | ||
26 | static int buffer_height = 768; | ||
27 | |||
28 | static GLuint ntscShader; // The NTSC shader | ||
29 | static GLuint finalShader; // The passthrough shader | ||
30 | static GLuint blitShader; // The blitting shader | ||
31 | static GLuint fillShader; // The fill shader | ||
32 | static GLuint bloom1Shader; | ||
33 | static GLuint bloom2Shader; | ||
34 | |||
35 | // The buffers for the NTSC rendering process | ||
36 | static GLuint renderedTexBufs[2]; | ||
37 | static int curBuf; | ||
38 | static GLuint artifactsTex; | ||
39 | static GLuint scanlinesTex; | ||
40 | static GLuint preBloomTex; | ||
41 | static GLuint bloomPassTex1; | ||
42 | static GLuint bloomPassTex2; | ||
43 | |||
44 | // The VAO | ||
45 | static GLuint VertexArrayID; | ||
46 | |||
47 | // A plane that fills the renderbuffer | ||
48 | static GLuint quad_vertexbuffer; | ||
49 | |||
50 | // Buffers for the mesh | ||
51 | static GLuint mesh_vertexbuffer; | ||
52 | static GLuint mesh_uvbuffer; | ||
53 | static GLuint mesh_normalbuffer; | ||
54 | static int mesh_numvertices; | ||
55 | |||
56 | GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path) | ||
57 | { | ||
58 | // Create the shaders | ||
59 | GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); | ||
60 | GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); | ||
61 | |||
62 | // Read the Vertex Shader code from the file | ||
63 | std::string VertexShaderCode; | ||
64 | std::ifstream VertexShaderStream(vertex_file_path, std::ios::in); | ||
65 | if(VertexShaderStream.is_open()) | ||
66 | { | ||
67 | std::string Line = ""; | ||
68 | while(getline(VertexShaderStream, Line)) | ||
69 | VertexShaderCode += "\n" + Line; | ||
70 | VertexShaderStream.close(); | ||
71 | } | ||
72 | |||
73 | // Read the Fragment Shader code from the file | ||
74 | std::string FragmentShaderCode; | ||
75 | std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in); | ||
76 | if(FragmentShaderStream.is_open()){ | ||
77 | std::string Line = ""; | ||
78 | while(getline(FragmentShaderStream, Line)) | ||
79 | FragmentShaderCode += "\n" + Line; | ||
80 | FragmentShaderStream.close(); | ||
81 | } | ||
82 | |||
83 | GLint Result = GL_FALSE; | ||
84 | int InfoLogLength; | ||
85 | |||
86 | // Compile Vertex Shader | ||
87 | printf("Compiling shader : %s\n", vertex_file_path); | ||
88 | char const * VertexSourcePointer = VertexShaderCode.c_str(); | ||
89 | glShaderSource(VertexShaderID, 1, &VertexSourcePointer , nullptr); | ||
90 | glCompileShader(VertexShaderID); | ||
91 | |||
92 | // Check Vertex Shader | ||
93 | glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); | ||
94 | glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); | ||
95 | std::vector<char> VertexShaderErrorMessage(InfoLogLength); | ||
96 | glGetShaderInfoLog(VertexShaderID, InfoLogLength, nullptr, &VertexShaderErrorMessage[0]); | ||
97 | fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]); | ||
98 | |||
99 | // Compile Fragment Shader | ||
100 | printf("Compiling shader : %s\n", fragment_file_path); | ||
101 | char const * FragmentSourcePointer = FragmentShaderCode.c_str(); | ||
102 | glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , nullptr); | ||
103 | glCompileShader(FragmentShaderID); | ||
104 | |||
105 | // Check Fragment Shader | ||
106 | glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); | ||
107 | glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); | ||
108 | std::vector<char> FragmentShaderErrorMessage(InfoLogLength); | ||
109 | glGetShaderInfoLog(FragmentShaderID, InfoLogLength, nullptr, &FragmentShaderErrorMessage[0]); | ||
110 | fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]); | ||
111 | |||
112 | // Link the program | ||
113 | fprintf(stdout, "Linking program\n"); | ||
114 | GLuint ProgramID = glCreateProgram(); | ||
115 | glAttachShader(ProgramID, VertexShaderID); | ||
116 | glAttachShader(ProgramID, FragmentShaderID); | ||
117 | glLinkProgram(ProgramID); | ||
118 | |||
119 | // Check the program | ||
120 | glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); | ||
121 | glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); | ||
122 | std::vector<char> ProgramErrorMessage( glm::max(InfoLogLength, int(1)) ); | ||
123 | glGetProgramInfoLog(ProgramID, InfoLogLength, nullptr, &ProgramErrorMessage[0]); | ||
124 | fprintf(stdout, "%s\n", &ProgramErrorMessage[0]); | ||
125 | |||
126 | glDeleteShader(VertexShaderID); | ||
127 | glDeleteShader(FragmentShaderID); | ||
128 | |||
129 | return ProgramID; | ||
130 | } | ||
131 | |||
132 | void flipImageData(unsigned char* data, int width, int height, int comps) | ||
133 | { | ||
134 | unsigned char* data_copy = (unsigned char*) malloc(width*height*comps*sizeof(unsigned char)); | ||
135 | memcpy(data_copy, data, width*height*comps); | ||
136 | |||
137 | int row_size = width * comps; | ||
138 | |||
139 | for (int i=0;i<height;i++) | ||
140 | { | ||
141 | memcpy(data + (row_size*i), data_copy + (row_size*(height-i-1)), row_size); | ||
142 | } | ||
143 | |||
144 | free(data_copy); | ||
145 | } | ||
146 | |||
147 | void loadMesh(const char* filename, std::vector<glm::vec3>& out_vertices, std::vector<glm::vec2>& out_uvs, std::vector<glm::vec3>& out_normals) | ||
148 | { | ||
149 | out_vertices.clear(); | ||
150 | out_uvs.clear(); | ||
151 | out_normals.clear(); | ||
152 | |||
153 | FILE* file = fopen(filename, "r"); | ||
154 | if (file == nullptr) | ||
155 | { | ||
156 | fprintf(stderr, "Could not open mesh file %s\n", filename); | ||
157 | exit(1); | ||
158 | } | ||
159 | |||
160 | std::vector<glm::vec3> temp_vertices; | ||
161 | std::vector<glm::vec2> temp_uvs; | ||
162 | std::vector<glm::vec3> temp_normals; | ||
163 | |||
164 | for (;;) | ||
165 | { | ||
166 | char lineHeader[256]; | ||
167 | int res = fscanf(file, "%s", lineHeader); | ||
168 | if (res == EOF) | ||
169 | { | ||
170 | break; | ||
171 | } | ||
172 | |||
173 | if (!strncmp(lineHeader, "v", 2)) | ||
174 | { | ||
175 | glm::vec3 vertex; | ||
176 | fscanf(file, "%f %f %f\n", &vertex.x,&vertex.y,&vertex.z); | ||
177 | temp_vertices.push_back(vertex); | ||
178 | } else if (!strncmp(lineHeader, "vt", 3)) | ||
179 | { | ||
180 | glm::vec2 uv; | ||
181 | fscanf(file, "%f %f\n", &uv.x, &uv.y); | ||
182 | temp_uvs.push_back(uv); | ||
183 | } else if (!strncmp(lineHeader, "vn", 3)) | ||
184 | { | ||
185 | glm::vec3 normal; | ||
186 | fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z); | ||
187 | temp_normals.push_back(normal); | ||
188 | } else if (!strncmp(lineHeader, "f", 2)) | ||
189 | { | ||
190 | int vertexIDs[3], uvIDs[3], normalIDs[3]; | ||
191 | fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIDs[0], &uvIDs[0], &normalIDs[0], &vertexIDs[1], &uvIDs[1], &normalIDs[1], &vertexIDs[2], &uvIDs[2], &normalIDs[2]); | ||
192 | |||
193 | for (int i=0; i<3; i++) | ||
194 | { | ||
195 | out_vertices.push_back(temp_vertices[vertexIDs[i] - 1]); | ||
196 | out_uvs.push_back(temp_uvs[uvIDs[i] - 1]); | ||
197 | out_normals.push_back(temp_normals[normalIDs[i] - 1]); | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | |||
203 | void setFramebufferSize(GLFWwindow* w, int width, int height) | ||
204 | { | ||
205 | buffer_width = width; | ||
206 | buffer_height = height; | ||
207 | |||
208 | glDeleteFramebuffers(1, &bloom_framebuffer); | ||
209 | glDeleteRenderbuffers(1, &bloom_depthbuffer); | ||
210 | |||
211 | glGenFramebuffers(1, &bloom_framebuffer); | ||
212 | glBindFramebuffer(GL_FRAMEBUFFER, bloom_framebuffer); | ||
213 | GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT1}; | ||
214 | glDrawBuffers(1, DrawBuffers); | ||
215 | |||
216 | glGenRenderbuffers(1, &bloom_depthbuffer); | ||
217 | glBindRenderbuffer(GL_RENDERBUFFER, bloom_depthbuffer); | ||
218 | glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); | ||
219 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, bloom_depthbuffer); | ||
220 | |||
221 | glDeleteTextures(1, &preBloomTex); | ||
222 | glDeleteTextures(1, &bloomPassTex1); | ||
223 | glDeleteTextures(1, &bloomPassTex2); | ||
224 | |||
225 | glGenTextures(1, &preBloomTex); | ||
226 | glBindTexture(GL_TEXTURE_2D, preBloomTex); | ||
227 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); | ||
228 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
229 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
230 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
231 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
232 | |||
233 | glGenTextures(1, &bloomPassTex1); | ||
234 | glBindTexture(GL_TEXTURE_2D, bloomPassTex1); | ||
235 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width/4, height/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); | ||
236 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
237 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
238 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
239 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
240 | |||
241 | glGenTextures(1, &bloomPassTex2); | ||
242 | glBindTexture(GL_TEXTURE_2D, bloomPassTex2); | ||
243 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width/4, height/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); | ||
244 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
245 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
246 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
247 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
248 | } | ||
249 | |||
250 | GLFWwindow* initRenderer() | ||
251 | { | ||
252 | if (rendererInitialized) | ||
253 | { | ||
254 | fprintf(stderr, "Renderer already initialized\n"); | ||
255 | exit(-1); | ||
256 | } | ||
257 | |||
258 | // Initialize GLFW | ||
259 | if (!glfwInit()) | ||
260 | { | ||
261 | fprintf(stderr, "Failed to initialize GLFW\n"); | ||
262 | exit(-1); | ||
263 | } | ||
264 | |||
265 | glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing | ||
266 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want version 3.3 | ||
267 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); | ||
268 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Mac requires this | ||
269 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | ||
270 | |||
271 | // Create a window | ||
272 | window = glfwCreateWindow(1024, 768, "Aromatherapy", nullptr, nullptr); | ||
273 | if (window == nullptr) | ||
274 | { | ||
275 | fprintf(stderr, "Failed to open GLFW window\n"); | ||
276 | glfwTerminate(); | ||
277 | exit(-1); | ||
278 | } | ||
279 | |||
280 | glfwMakeContextCurrent(window); | ||
281 | glewExperimental = true; // Needed in core profile | ||
282 | if (glewInit() != GLEW_OK) | ||
283 | { | ||
284 | fprintf(stderr, "Failed to initialize GLEW\n"); | ||
285 | exit(-1); | ||
286 | } | ||
287 | |||
288 | glfwSetFramebufferSizeCallback(window, &setFramebufferSize); | ||
289 | |||
290 | // Set up vertex array object | ||
291 | glGenVertexArrays(1, &VertexArrayID); | ||
292 | glBindVertexArray(VertexArrayID); | ||
293 | |||
294 | // Enable depth testing | ||
295 | glEnable(GL_DEPTH_TEST); | ||
296 | glDepthFunc(GL_LESS); | ||
297 | |||
298 | // Enable blending | ||
299 | glEnable(GL_BLEND); | ||
300 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||
301 | |||
302 | // Set up the framebuffer | ||
303 | glGenFramebuffers(1, &generic_framebuffer); | ||
304 | glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); | ||
305 | GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; | ||
306 | glDrawBuffers(1, DrawBuffers); | ||
307 | |||
308 | glGenFramebuffers(1, &bloom_framebuffer); | ||
309 | glBindFramebuffer(GL_FRAMEBUFFER, bloom_framebuffer); | ||
310 | GLenum DrawBuffers2[1] = {GL_COLOR_ATTACHMENT1}; | ||
311 | glDrawBuffers(1, DrawBuffers2); | ||
312 | |||
313 | glfwGetFramebufferSize(window, &buffer_width, &buffer_height); | ||
314 | |||
315 | glGenRenderbuffers(1, &bloom_depthbuffer); | ||
316 | glBindRenderbuffer(GL_RENDERBUFFER, bloom_depthbuffer); | ||
317 | glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, buffer_width, buffer_height); | ||
318 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, bloom_depthbuffer); | ||
319 | |||
320 | // Set up the NTSC rendering buffers | ||
321 | glGenTextures(2, renderedTexBufs); | ||
322 | glBindTexture(GL_TEXTURE_2D, renderedTexBufs[0]); | ||
323 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAME_WIDTH, GAME_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); | ||
324 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
325 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
326 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
327 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
328 | |||
329 | glBindTexture(GL_TEXTURE_2D, renderedTexBufs[1]); | ||
330 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAME_WIDTH, GAME_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); | ||
331 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
332 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
333 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
334 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
335 | |||
336 | // Set up bloom rendering buffers | ||
337 | glGenTextures(1, &preBloomTex); | ||
338 | glBindTexture(GL_TEXTURE_2D, preBloomTex); | ||
339 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, buffer_width, buffer_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); | ||
340 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
341 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
342 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
343 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
344 | |||
345 | glGenTextures(1, &bloomPassTex1); | ||
346 | glBindTexture(GL_TEXTURE_2D, bloomPassTex1); | ||
347 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, buffer_width/4, buffer_height/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); | ||
348 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
349 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
350 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
351 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
352 | |||
353 | glGenTextures(1, &bloomPassTex2); | ||
354 | glBindTexture(GL_TEXTURE_2D, bloomPassTex2); | ||
355 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, buffer_width/4, buffer_height/4, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); | ||
356 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
357 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
358 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
359 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
360 | |||
361 | curBuf = 0; | ||
362 | |||
363 | // Load the mesh! | ||
364 | std::vector<glm::vec3> mesh_vertices; | ||
365 | std::vector<glm::vec2> mesh_uvs; | ||
366 | std::vector<glm::vec3> mesh_normals; | ||
367 | |||
368 | loadMesh("res/monitor-old.obj", mesh_vertices, mesh_uvs, mesh_normals); | ||
369 | |||
370 | mesh_numvertices = mesh_vertices.size(); | ||
371 | |||
372 | glGenBuffers(1, &mesh_vertexbuffer); | ||
373 | glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer); | ||
374 | glBufferData(GL_ARRAY_BUFFER, mesh_vertices.size() * sizeof(glm::vec3), mesh_vertices.data(), GL_STATIC_DRAW); | ||
375 | |||
376 | glGenBuffers(1, &mesh_uvbuffer); | ||
377 | glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer); | ||
378 | glBufferData(GL_ARRAY_BUFFER, mesh_uvs.size() * sizeof(glm::vec2), mesh_uvs.data(), GL_STATIC_DRAW); | ||
379 | |||
380 | glGenBuffers(1, &mesh_normalbuffer); | ||
381 | glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer); | ||
382 | glBufferData(GL_ARRAY_BUFFER, mesh_normals.size() * sizeof(glm::vec3), mesh_normals.data(), GL_STATIC_DRAW); | ||
383 | |||
384 | // Load the vertices of a flat surface | ||
385 | GLfloat g_quad_vertex_buffer_data[] = { | ||
386 | -1.0f, -1.0f, 0.0f, | ||
387 | 1.0f, -1.0f, 0.0f, | ||
388 | -1.0f, 1.0f, 0.0f, | ||
389 | -1.0f, 1.0f, 0.0f, | ||
390 | 1.0f, -1.0f, 0.0f, | ||
391 | 1.0f, 1.0f, 0.0f, | ||
392 | }; | ||
393 | |||
394 | glGenBuffers(1, &quad_vertexbuffer); | ||
395 | glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); | ||
396 | glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW); | ||
397 | |||
398 | glGenTextures(1, &artifactsTex); | ||
399 | glBindTexture(GL_TEXTURE_2D, artifactsTex); | ||
400 | int atdw, atdh; | ||
401 | unsigned char* artifactsTex_data = stbi_load("res/artifacts.bmp", &atdw, &atdh, 0, 3); | ||
402 | flipImageData(artifactsTex_data, atdw, atdh, 3); | ||
403 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, atdw, atdh, 0, GL_RGB, GL_UNSIGNED_BYTE, artifactsTex_data); | ||
404 | stbi_image_free(artifactsTex_data); | ||
405 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
406 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); | ||
407 | glGenerateMipmap(GL_TEXTURE_2D); | ||
408 | |||
409 | glGenTextures(1, &scanlinesTex); | ||
410 | glBindTexture(GL_TEXTURE_2D, scanlinesTex); | ||
411 | int stdw, stdh; | ||
412 | unsigned char* scanlinesTex_data = stbi_load("res/scanlines_333.bmp", &stdw, &stdh, 0, 3); | ||
413 | flipImageData(scanlinesTex_data, stdw, stdh, 3); | ||
414 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, atdw, atdh, 0, GL_RGB, GL_UNSIGNED_BYTE, scanlinesTex_data); | ||
415 | stbi_image_free(scanlinesTex_data); | ||
416 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
417 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); | ||
418 | glGenerateMipmap(GL_TEXTURE_2D); | ||
419 | |||
420 | // Load the shaders | ||
421 | ntscShader = LoadShaders("shaders/ntsc.vertex", "shaders/ntsc.fragment"); | ||
422 | finalShader = LoadShaders("shaders/final.vertex", "shaders/final.fragment"); | ||
423 | blitShader = LoadShaders("shaders/blit.vertex", "shaders/blit.fragment"); | ||
424 | fillShader = LoadShaders("shaders/fill.vertex", "shaders/fill.fragment"); | ||
425 | bloom1Shader = LoadShaders("shaders/bloom1.vertex", "shaders/bloom1.fragment"); | ||
426 | bloom2Shader = LoadShaders("shaders/bloom2.vertex", "shaders/bloom2.fragment"); | ||
427 | |||
428 | rendererInitialized = true; | ||
429 | |||
430 | return window; | ||
431 | } | ||
432 | |||
433 | void destroyRenderer() | ||
434 | { | ||
435 | if (!rendererInitialized) | ||
436 | { | ||
437 | fprintf(stderr, "Renderer not initialized\n"); | ||
438 | exit(-1); | ||
439 | } | ||
440 | |||
441 | // Delete the plane buffer | ||
442 | glDeleteBuffers(1, &quad_vertexbuffer); | ||
443 | glDeleteBuffers(1, &mesh_vertexbuffer); | ||
444 | glDeleteBuffers(1, &mesh_uvbuffer); | ||
445 | glDeleteBuffers(1, &mesh_normalbuffer); | ||
446 | |||
447 | // Delete the shaders | ||
448 | glDeleteProgram(ntscShader); | ||
449 | glDeleteProgram(finalShader); | ||
450 | glDeleteProgram(blitShader); | ||
451 | glDeleteProgram(fillShader); | ||
452 | glDeleteProgram(bloom1Shader); | ||
453 | glDeleteProgram(bloom2Shader); | ||
454 | |||
455 | // Delete the NTSC rendering buffers | ||
456 | glDeleteTextures(2, renderedTexBufs); | ||
457 | glDeleteTextures(1, &artifactsTex); | ||
458 | glDeleteTextures(1, &scanlinesTex); | ||
459 | glDeleteTextures(1, &preBloomTex); | ||
460 | glDeleteTextures(1, &bloomPassTex1); | ||
461 | glDeleteTextures(1, &bloomPassTex2); | ||
462 | |||
463 | // Delete the framebuffer | ||
464 | glDeleteRenderbuffers(1, &bloom_depthbuffer); | ||
465 | glDeleteFramebuffers(1, &bloom_framebuffer); | ||
466 | glDeleteFramebuffers(1, &generic_framebuffer); | ||
467 | |||
468 | // Delete the VAO | ||
469 | glDeleteVertexArrays(1, &VertexArrayID); | ||
470 | |||
471 | // Kill the window | ||
472 | glfwTerminate(); | ||
473 | |||
474 | rendererInitialized = false; | ||
475 | } | ||
476 | |||
477 | Texture::Texture(int width, int height) | ||
478 | { | ||
479 | if (!rendererInitialized) | ||
480 | { | ||
481 | fprintf(stderr, "Renderer not initialized\n"); | ||
482 | exit(-1); | ||
483 | } | ||
484 | |||
485 | this->width = width; | ||
486 | this->height = height; | ||
487 | |||
488 | glGenTextures(1, &texID); | ||
489 | glBindTexture(GL_TEXTURE_2D, texID); | ||
490 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); | ||
491 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
492 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
493 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
494 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
495 | } | ||
496 | |||
497 | Texture::Texture(const char* filename) | ||
498 | { | ||
499 | if (!rendererInitialized) | ||
500 | { | ||
501 | fprintf(stderr, "Renderer not initialized\n"); | ||
502 | exit(-1); | ||
503 | } | ||
504 | |||
505 | glGenTextures(1, &texID); | ||
506 | glBindTexture(GL_TEXTURE_2D, texID); | ||
507 | unsigned char* data = stbi_load(filename, &width, &height, 0, 4); | ||
508 | flipImageData(data, width, height, 4); | ||
509 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); | ||
510 | stbi_image_free(data); | ||
511 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
512 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
513 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
514 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
515 | } | ||
516 | |||
517 | Texture::Texture(const Texture& tex) | ||
518 | { | ||
519 | if (!rendererInitialized) | ||
520 | { | ||
521 | fprintf(stderr, "Renderer not initialized\n"); | ||
522 | exit(-1); | ||
523 | } | ||
524 | |||
525 | width = tex.width; | ||
526 | height = tex.height; | ||
527 | |||
528 | unsigned char* data = (unsigned char*) malloc(4 * width * height); | ||
529 | glBindTexture(GL_TEXTURE_2D, tex.texID); | ||
530 | glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); | ||
531 | |||
532 | glGenTextures(1, &texID); | ||
533 | glBindTexture(GL_TEXTURE_2D, texID); | ||
534 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); | ||
535 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
536 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
537 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
538 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
539 | |||
540 | free(data); | ||
541 | } | ||
542 | |||
543 | Texture::Texture(Texture&& tex) : Texture(0, 0) | ||
544 | { | ||
545 | swap(*this, tex); | ||
546 | } | ||
547 | |||
548 | Texture::~Texture() | ||
549 | { | ||
550 | if (!rendererInitialized) | ||
551 | { | ||
552 | fprintf(stderr, "Renderer not initialized\n"); | ||
553 | exit(-1); | ||
554 | } | ||
555 | |||
556 | glDeleteTextures(1, &texID); | ||
557 | } | ||
558 | |||
559 | Texture& Texture::operator= (Texture tex) | ||
560 | { | ||
561 | swap(*this, tex); | ||
562 | |||
563 | return *this; | ||
564 | } | ||
565 | |||
566 | void swap(Texture& tex1, Texture& tex2) | ||
567 | { | ||
568 | std::swap(tex1.width, tex2.width); | ||
569 | std::swap(tex1.height, tex2.height); | ||
570 | std::swap(tex1.texID, tex2.texID); | ||
571 | } | ||
572 | |||
573 | void Texture::fill(Rectangle dstrect, int r, int g, int b) | ||
574 | { | ||
575 | if (!rendererInitialized) | ||
576 | { | ||
577 | fprintf(stderr, "Renderer not initialized\n"); | ||
578 | exit(-1); | ||
579 | } | ||
580 | |||
581 | // Target the framebuffer | ||
582 | glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); | ||
583 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texID, 0); | ||
584 | |||
585 | // Set up the vertex attributes | ||
586 | GLfloat minx = (GLfloat) dstrect.x / width * 2.0 - 1.0; | ||
587 | GLfloat miny = -((GLfloat) dstrect.y / height * 2.0 - 1.0); | ||
588 | GLfloat maxx = (GLfloat) (dstrect.x + dstrect.w) / width * 2.0 - 1.0; | ||
589 | GLfloat maxy = -((GLfloat) (dstrect.y + dstrect.h) / height * 2.0 - 1.0); | ||
590 | |||
591 | GLfloat vertexbuffer_data[] = { | ||
592 | minx, miny, | ||
593 | maxx, miny, | ||
594 | maxx, maxy, | ||
595 | minx, miny, | ||
596 | minx, maxy, | ||
597 | maxx, maxy | ||
598 | }; | ||
599 | GLuint vertexbuffer; | ||
600 | glGenBuffers(1, &vertexbuffer); | ||
601 | glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); | ||
602 | glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW); | ||
603 | glEnableVertexAttribArray(0); | ||
604 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
605 | |||
606 | glViewport(0, 0, width, height); | ||
607 | glClear(GL_DEPTH_BUFFER_BIT); | ||
608 | glUseProgram(fillShader); | ||
609 | glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0); | ||
610 | |||
611 | glDrawArrays(GL_TRIANGLES, 0, 6); | ||
612 | |||
613 | glDisableVertexAttribArray(0); | ||
614 | glDeleteBuffers(1, &vertexbuffer); | ||
615 | } | ||
616 | |||
617 | void Texture::blit(const Texture& srctex, Rectangle srcrect, Rectangle dstrect, double alpha) | ||
618 | { | ||
619 | if (!rendererInitialized) | ||
620 | { | ||
621 | fprintf(stderr, "Renderer not initialized\n"); | ||
622 | exit(-1); | ||
623 | } | ||
624 | |||
625 | alpha = glm::clamp(alpha, 0.0, 1.0); | ||
626 | |||
627 | // Target the framebuffer | ||
628 | glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); | ||
629 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texID, 0); | ||
630 | |||
631 | // Set up the vertex attributes | ||
632 | GLfloat minx = (GLfloat) dstrect.x / width * 2.0 - 1.0; | ||
633 | GLfloat miny = -((GLfloat) dstrect.y / height * 2.0 - 1.0); | ||
634 | GLfloat maxx = (GLfloat) (dstrect.x + dstrect.w) / width * 2.0 - 1.0; | ||
635 | GLfloat maxy = -((GLfloat) (dstrect.y + dstrect.h) / height * 2.0 - 1.0); | ||
636 | |||
637 | GLfloat vertexbuffer_data[] = { | ||
638 | minx, miny, | ||
639 | maxx, miny, | ||
640 | minx, maxy, | ||
641 | maxx, maxy | ||
642 | }; | ||
643 | GLuint vertexbuffer; | ||
644 | glGenBuffers(1, &vertexbuffer); | ||
645 | glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); | ||
646 | glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW); | ||
647 | glEnableVertexAttribArray(0); | ||
648 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
649 | |||
650 | GLfloat minu = (GLfloat) srcrect.x / srctex.width; | ||
651 | GLfloat minv = 1 - ((GLfloat) srcrect.y / srctex.height); | ||
652 | GLfloat maxu = (GLfloat) (srcrect.x + srcrect.w) / srctex.width; | ||
653 | GLfloat maxv = 1 - ((GLfloat) (srcrect.y + srcrect.h) / srctex.height); | ||
654 | |||
655 | GLfloat texcoordbuffer_data[] = { | ||
656 | minu, minv, | ||
657 | maxu, minv, | ||
658 | minu, maxv, | ||
659 | maxu, maxv | ||
660 | }; | ||
661 | GLuint texcoordbuffer; | ||
662 | glGenBuffers(1, &texcoordbuffer); | ||
663 | glBindBuffer(GL_ARRAY_BUFFER, texcoordbuffer); | ||
664 | glBufferData(GL_ARRAY_BUFFER, sizeof(texcoordbuffer_data), texcoordbuffer_data, GL_STATIC_DRAW); | ||
665 | glEnableVertexAttribArray(1); | ||
666 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
667 | |||
668 | // Set up the shader | ||
669 | glUseProgram(blitShader); | ||
670 | glClear(GL_DEPTH_BUFFER_BIT); | ||
671 | glViewport(0, 0, width, height); | ||
672 | |||
673 | glActiveTexture(GL_TEXTURE0); | ||
674 | glBindTexture(GL_TEXTURE_2D, srctex.texID); | ||
675 | glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0); | ||
676 | glUniform1f(glGetUniformLocation(blitShader, "alpha"), alpha); | ||
677 | |||
678 | // Blit! | ||
679 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | ||
680 | |||
681 | // Unload everything | ||
682 | glDisableVertexAttribArray(1); | ||
683 | glDisableVertexAttribArray(0); | ||
684 | glDeleteBuffers(1, &texcoordbuffer); | ||
685 | glDeleteBuffers(1, &vertexbuffer); | ||
686 | } | ||
687 | |||
688 | void bloomPass1(GLuint srcTex, GLuint dstTex, bool horizontal, glm::vec2 srcRes, glm::vec2 dstRes) | ||
689 | { | ||
690 | glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); | ||
691 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstTex, 0); | ||
692 | glViewport(0,0,dstRes.x,dstRes.y); | ||
693 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||
694 | glUseProgram(bloom1Shader); | ||
695 | |||
696 | glActiveTexture(GL_TEXTURE0); | ||
697 | glBindTexture(GL_TEXTURE_2D, srcTex); | ||
698 | glUniform1i(glGetUniformLocation(bloom1Shader, "inTex"), 0); | ||
699 | |||
700 | glm::vec2 offset = glm::vec2(0.0); | ||
701 | if (horizontal) | ||
702 | { | ||
703 | offset.x = 1.2/srcRes.x; | ||
704 | } else { | ||
705 | offset.y = 1.2/srcRes.y; | ||
706 | } | ||
707 | |||
708 | glUniform2f(glGetUniformLocation(bloom1Shader, "offset"), offset.x, offset.y); | ||
709 | |||
710 | glEnableVertexAttribArray(0); | ||
711 | glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); | ||
712 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
713 | glDrawArrays(GL_TRIANGLES, 0, 6); | ||
714 | glDisableVertexAttribArray(0); | ||
715 | } | ||
716 | |||
717 | void Texture::renderScreen() const | ||
718 | { | ||
719 | if (!rendererInitialized) | ||
720 | { | ||
721 | fprintf(stderr, "Renderer not initialized\n"); | ||
722 | exit(-1); | ||
723 | } | ||
724 | |||
725 | // First we're going to composite our frame with the previous frame | ||
726 | // We start by setting up the framebuffer | ||
727 | glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); | ||
728 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexBufs[curBuf], 0); | ||
729 | |||
730 | // Set up the shader | ||
731 | glViewport(0,0,GAME_WIDTH,GAME_HEIGHT); | ||
732 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||
733 | glUseProgram(ntscShader); | ||
734 | |||
735 | // Use the current frame texture, nearest neighbor and clamped to edge | ||
736 | glActiveTexture(GL_TEXTURE0); | ||
737 | glBindTexture(GL_TEXTURE_2D, texID); | ||
738 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
739 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
740 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
741 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
742 | glUniform1i(glGetUniformLocation(ntscShader, "curFrameSampler"), 0); | ||
743 | |||
744 | // Use the previous frame composite texture, nearest neighbor and clamped to edge | ||
745 | glActiveTexture(GL_TEXTURE1); | ||
746 | glBindTexture(GL_TEXTURE_2D, renderedTexBufs[(curBuf + 1) % 2]); | ||
747 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
748 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
749 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
750 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
751 | glUniform1i(glGetUniformLocation(ntscShader, "prevFrameSampler"), 1); | ||
752 | |||
753 | // Load the NTSC artifact texture | ||
754 | glActiveTexture(GL_TEXTURE2); | ||
755 | glBindTexture(GL_TEXTURE_2D, artifactsTex); | ||
756 | glUniform1i(glGetUniformLocation(ntscShader, "NTSCArtifactSampler"), 2); | ||
757 | glUniform1f(glGetUniformLocation(ntscShader, "NTSCLerp"), curBuf * 1.0); | ||
758 | |||
759 | if ((rand() % 60) == 0) | ||
760 | { | ||
761 | // Change the 0.0 to a 1.0 or a 10.0 for a glitchy effect! | ||
762 | glUniform1f(glGetUniformLocation(ntscShader, "Tuning_NTSC"), 0.0); | ||
763 | } else { | ||
764 | glUniform1f(glGetUniformLocation(ntscShader, "Tuning_NTSC"), 0.0); | ||
765 | } | ||
766 | |||
767 | // Render our composition | ||
768 | glEnableVertexAttribArray(0); | ||
769 | glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); | ||
770 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
771 | glDrawArrays(GL_TRIANGLES, 0, 6); | ||
772 | glDisableVertexAttribArray(0); | ||
773 | |||
774 | // We're going to render the screen now | ||
775 | glBindFramebuffer(GL_FRAMEBUFFER, bloom_framebuffer); | ||
776 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, preBloomTex, 0); | ||
777 | glViewport(0,0,buffer_width,buffer_height); | ||
778 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||
779 | glUseProgram(finalShader); | ||
780 | |||
781 | // Use the composited frame texture, linearly filtered and filling in black for the border | ||
782 | glActiveTexture(GL_TEXTURE0); | ||
783 | glBindTexture(GL_TEXTURE_2D, renderedTexBufs[curBuf]); | ||
784 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
785 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); | ||
786 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); | ||
787 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); | ||
788 | float border_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; | ||
789 | glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); | ||
790 | glGenerateMipmap(GL_TEXTURE_2D); | ||
791 | glUniform1i(glGetUniformLocation(finalShader, "rendertex"), 0); | ||
792 | |||
793 | // Use the scanlines texture | ||
794 | glActiveTexture(GL_TEXTURE1); | ||
795 | glBindTexture(GL_TEXTURE_2D, scanlinesTex); | ||
796 | glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1); | ||
797 | |||
798 | // Initialize the MVP matrices | ||
799 | glm::mat4 p_matrix = glm::perspective(glm::radians(25.0f), (float) buffer_width / (float) buffer_height, 0.1f, 100.0f); | ||
800 | glm::mat4 v_matrix = glm::lookAt(glm::vec3(3.75,0,0), glm::vec3(0,0,0), glm::vec3(0,1,0)); | ||
801 | glm::mat4 m_matrix = glm::mat4(1.0); | ||
802 | glm::mat4 mvp_matrix = p_matrix * v_matrix * m_matrix; | ||
803 | |||
804 | glUniformMatrix4fv(glGetUniformLocation(finalShader, "MVP"), 1, GL_FALSE, &mvp_matrix[0][0]); | ||
805 | glUniformMatrix4fv(glGetUniformLocation(finalShader, "worldMat"), 1, GL_FALSE, &m_matrix[0][0]); | ||
806 | glUniform2f(glGetUniformLocation(finalShader, "resolution"), buffer_width, buffer_height); | ||
807 | glUniform1f(glGetUniformLocation(finalShader, "iGlobalTime"), glfwGetTime()); | ||
808 | glUniform3f(glGetUniformLocation(finalShader, "frameColor"), 0.76f, 0.78f, 0.81f); | ||
809 | |||
810 | glEnableVertexAttribArray(0); | ||
811 | glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer); | ||
812 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
813 | |||
814 | glEnableVertexAttribArray(1); | ||
815 | glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer); | ||
816 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
817 | |||
818 | glEnableVertexAttribArray(2); | ||
819 | glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer); | ||
820 | glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
821 | |||
822 | glDrawArrays(GL_TRIANGLES, 0, mesh_numvertices); | ||
823 | glDisableVertexAttribArray(2); | ||
824 | glDisableVertexAttribArray(1); | ||
825 | glDisableVertexAttribArray(0); | ||
826 | |||
827 | // First pass of bloom! | ||
828 | glm::vec2 buffer_size = glm::vec2(buffer_width, buffer_height); | ||
829 | bloomPass1(preBloomTex, bloomPassTex1, true, buffer_size, buffer_size / 4.0f); | ||
830 | bloomPass1(bloomPassTex1, bloomPassTex2, false, buffer_size / 4.0f, buffer_size / 4.0f); | ||
831 | |||
832 | // Do the second pass of bloom and render to screen | ||
833 | glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||
834 | glViewport(0, 0, buffer_width, buffer_height); | ||
835 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||
836 | glUseProgram(bloom2Shader); | ||
837 | |||
838 | glActiveTexture(GL_TEXTURE0); | ||
839 | glBindTexture(GL_TEXTURE_2D, preBloomTex); | ||
840 | glUniform1i(glGetUniformLocation(bloom2Shader, "clearTex"), 0); | ||
841 | |||
842 | glActiveTexture(GL_TEXTURE1); | ||
843 | glBindTexture(GL_TEXTURE_2D, bloomPassTex2); | ||
844 | glUniform1i(glGetUniformLocation(bloom2Shader, "blurTex"), 1); | ||
845 | |||
846 | glUniform1f(glGetUniformLocation(bloom2Shader, "iGlobalTime"), glfwGetTime()); | ||
847 | |||
848 | glEnableVertexAttribArray(0); | ||
849 | glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); | ||
850 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
851 | glDrawArrays(GL_TRIANGLES, 0, 6); | ||
852 | glDisableVertexAttribArray(0); | ||
853 | |||
854 | glfwSwapBuffers(window); | ||
855 | |||
856 | curBuf = (curBuf + 1) % 2; | ||
857 | } | ||
858 | |||
859 | Rectangle Texture::entirety() const | ||
860 | { | ||
861 | return {0, 0, width, height}; | ||
862 | } | ||