summary refs log tree commit diff stats
path: root/src/renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer.cpp')
-rw-r--r--src/renderer.cpp582
1 files changed, 582 insertions, 0 deletions
diff --git a/src/renderer.cpp b/src/renderer.cpp new file mode 100644 index 0000000..e74c6a4 --- /dev/null +++ b/src/renderer.cpp
@@ -0,0 +1,582 @@
1#include "renderer.h"
2#include <string>
3#include <fstream>
4#include <vector>
5#include <cstdio>
6#include "map.h"
7
8static bool rendererInitialized = false;
9
10static GLFWwindow* window;
11
12static GLuint FramebufferName; // The framebuffer
13static GLuint ntscShader; // The NTSC shader
14static GLuint finalShader; // The passthrough shader
15static GLuint blitShader; // The blitting shader
16static GLuint fillShader; // The fill shader
17
18// The buffers for the NTSC rendering process
19static GLuint renderedTex1;
20static GLuint renderedTex2;
21static GLuint renderedTexBufs[2];
22static int curBuf;
23static GLuint artifactsTex;
24static GLuint scanlinesTex;
25
26GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path)
27{
28 // Create the shaders
29 GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
30 GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
31
32 // Read the Vertex Shader code from the file
33 std::string VertexShaderCode;
34 std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
35 if(VertexShaderStream.is_open())
36 {
37 std::string Line = "";
38 while(getline(VertexShaderStream, Line))
39 VertexShaderCode += "\n" + Line;
40 VertexShaderStream.close();
41 }
42
43 // Read the Fragment Shader code from the file
44 std::string FragmentShaderCode;
45 std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
46 if(FragmentShaderStream.is_open()){
47 std::string Line = "";
48 while(getline(FragmentShaderStream, Line))
49 FragmentShaderCode += "\n" + Line;
50 FragmentShaderStream.close();
51 }
52
53 GLint Result = GL_FALSE;
54 int InfoLogLength;
55
56 // Compile Vertex Shader
57 printf("Compiling shader : %s\n", vertex_file_path);
58 char const * VertexSourcePointer = VertexShaderCode.c_str();
59 glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
60 glCompileShader(VertexShaderID);
61
62 // Check Vertex Shader
63 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
64 glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
65 std::vector<char> VertexShaderErrorMessage(InfoLogLength);
66 glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
67 fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
68
69 // Compile Fragment Shader
70 printf("Compiling shader : %s\n", fragment_file_path);
71 char const * FragmentSourcePointer = FragmentShaderCode.c_str();
72 glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
73 glCompileShader(FragmentShaderID);
74
75 // Check Fragment Shader
76 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
77 glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
78 std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
79 glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
80 fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
81
82 // Link the program
83 fprintf(stdout, "Linking program\n");
84 GLuint ProgramID = glCreateProgram();
85 glAttachShader(ProgramID, VertexShaderID);
86 glAttachShader(ProgramID, FragmentShaderID);
87 glLinkProgram(ProgramID);
88
89 // Check the program
90 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
91 glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
92 std::vector<char> ProgramErrorMessage( glm::max(InfoLogLength, int(1)) );
93 glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
94 fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
95
96 glDeleteShader(VertexShaderID);
97 glDeleteShader(FragmentShaderID);
98
99 return ProgramID;
100}
101
102GLuint loadBMP_custom(const char * imagepath){
103
104 printf("Reading image %s\n", imagepath);
105
106 // Data read from the header of the BMP file
107 unsigned char header[54];
108 unsigned int dataPos;
109 unsigned int imageSize;
110 unsigned int width, height;
111 // Actual RGB data
112 unsigned char * data;
113
114 // Open the file
115 FILE * file = fopen(imagepath,"rb");
116 if (!file) {printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); getchar(); return 0;}
117
118 // Read the header, i.e. the 54 first bytes
119
120 // If less than 54 bytes are read, problem
121 if ( fread(header, 1, 54, file)!=54 ){
122 printf("Not a correct BMP file\n");
123 return 0;
124 }
125 // A BMP files always begins with "BM"
126 if ( header[0]!='B' || header[1]!='M' ){
127 printf("Not a correct BMP file\n");
128 return 0;
129 }
130 // Make sure this is a 24bpp file
131 if ( *(int*)&(header[0x1E])!=0 ) {printf("Not a correct BMP file\n"); return 0;}
132 if ( *(int*)&(header[0x1C])!=24 ) {printf("Not a correct BMP file\n"); return 0;}
133
134 // Read the information about the image
135 dataPos = *(int*)&(header[0x0A]);
136 imageSize = *(int*)&(header[0x22]);
137 width = *(int*)&(header[0x12]);
138 height = *(int*)&(header[0x16]);
139
140 // Some BMP files are misformatted, guess missing information
141 if (imageSize==0) imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component
142 if (dataPos==0) dataPos=54; // The BMP header is done that way
143
144 // Create a buffer
145 data = new unsigned char [imageSize];
146
147 // Read the actual data from the file into the buffer
148 fread(data,1,imageSize,file);
149
150 // Everything is in memory now, the file wan be closed
151 fclose (file);
152
153 // Create one OpenGL texture
154 GLuint textureID;
155 glGenTextures(1, &textureID);
156
157 // "Bind" the newly created texture : all future texture functions will modify this texture
158 glBindTexture(GL_TEXTURE_2D, textureID);
159
160 // Give the image to OpenGL
161 glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
162
163 // OpenGL has now copied the data. Free our own version
164 delete [] data;
165
166 // Poor filtering, or ...
167 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
168 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
169
170 // ... nice trilinear filtering.
171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
172 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
175 glGenerateMipmap(GL_TEXTURE_2D);
176
177 // Return the ID of the texture we just created
178 return textureID;
179}
180
181GLFWwindow* initRenderer()
182{
183 if (rendererInitialized)
184 {
185 fprintf(stderr, "Renderer already initialized\n");
186 exit(-1);
187 }
188
189 // Initialize GLFW
190 if (!glfwInit())
191 {
192 fprintf(stderr, "Failed to initialize GLFW\n");
193 exit(-1);
194 }
195
196 glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
197 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want version 3.3
198 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
199 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Mac requires this
200 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
201
202 // Create a window
203 window = glfwCreateWindow(1024, 768, "Aromatherapy", NULL, NULL);
204 if (window == NULL)
205 {
206 fprintf(stderr, "Failed to open GLFW window\n");
207 glfwTerminate();
208 exit(-1);
209 }
210
211 glfwMakeContextCurrent(window);
212 glewExperimental = true; // Needed in core profile
213 if (glewInit() != GLEW_OK)
214 {
215 fprintf(stderr, "Failed to initialize GLEW\n");
216 exit(-1);
217 }
218
219 // Set up vertex array object
220 GLuint VertexArrayID;
221 glGenVertexArrays(1, &VertexArrayID);
222 glBindVertexArray(VertexArrayID);
223
224 // Set up the framebuffer
225 glGenFramebuffers(1, &FramebufferName);
226 glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
227 GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
228 glDrawBuffers(1, DrawBuffers);
229
230 // Set up the NTSC rendering buffers
231 glGenTextures(1, &renderedTex1);
232 glBindTexture(GL_TEXTURE_2D, renderedTex1);
233 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAME_WIDTH, GAME_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
238 renderedTexBufs[0] = renderedTex1;
239
240 glGenTextures(1, &renderedTex2);
241 glBindTexture(GL_TEXTURE_2D, renderedTex2);
242 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAME_WIDTH, GAME_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
246 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
247 renderedTexBufs[1] = renderedTex2;
248
249 curBuf = 0;
250
251 artifactsTex = loadBMP_custom("../res/artifacts.bmp");
252 scanlinesTex = loadBMP_custom("../res/scanlines.bmp");
253
254 // Load the shaders
255 ntscShader = LoadShaders("../shaders/ntsc.vertex", "../shaders/ntsc.fragment");
256 finalShader = LoadShaders("../shaders/final.vertex", "../shaders/final.fragment");
257 blitShader = LoadShaders("../shaders/blit.vertex", "../shaders/blit.fragment");
258 fillShader = LoadShaders("../shaders/fill.vertex", "../shaders/fill.fragment");
259
260 rendererInitialized = true;
261
262 return window;
263}
264
265void destroyRenderer()
266{
267 if (!rendererInitialized)
268 {
269 fprintf(stderr, "Renderer not initialized\n");
270 exit(-1);
271 }
272
273 // Delete the shaders
274 glDeleteProgram(ntscShader);
275 glDeleteProgram(finalShader);
276 glDeleteProgram(blitShader);
277 glDeleteProgram(fillShader);
278
279 // Delete the NTSC rendering buffers
280 glDeleteTextures(1, &renderedTex1);
281 glDeleteTextures(1, &renderedTex2);
282 glDeleteTextures(1, &artifactsTex);
283 glDeleteTextures(1, &scanlinesTex);
284
285 // Delete the framebuffer
286 glDeleteFramebuffers(1, &FramebufferName);
287
288 // Kill the window
289 glfwTerminate();
290
291 rendererInitialized = false;
292}
293
294Texture* createTexture(int width, int height)
295{
296 if (!rendererInitialized)
297 {
298 fprintf(stderr, "Renderer not initialized\n");
299 exit(-1);
300 }
301
302 Texture* tex = new Texture();
303 tex->width = width;
304 tex->height = height;
305
306 glGenTextures(1, &(tex->texID));
307 glBindTexture(GL_TEXTURE_2D, tex->texID);
308 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
309 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
310 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
313
314 return tex;
315}
316
317void destroyTexture(Texture* tex)
318{
319 if (!rendererInitialized)
320 {
321 fprintf(stderr, "Renderer not initialized\n");
322 exit(-1);
323 }
324
325 glDeleteTextures(1, &(tex->texID));
326
327 delete tex;
328}
329
330Texture* loadTextureFromBMP(char* filename)
331{
332 if (!rendererInitialized)
333 {
334 fprintf(stderr, "Renderer not initialized\n");
335 exit(-1);
336 }
337
338 Texture* tex = new Texture();
339 tex->texID = loadBMP_custom(filename);
340
341 glBindTexture(GL_TEXTURE_2D, tex->texID);
342 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &(tex->width));
343 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &(tex->height));
344
345 return tex;
346}
347
348void fillTexture(Texture* tex, Rectangle* dstrect, int r, int g, int b)
349{
350 if (!rendererInitialized)
351 {
352 fprintf(stderr, "Renderer not initialized\n");
353 exit(-1);
354 }
355
356 // Target the framebuffer
357 glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
358 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex->texID, 0);
359
360 // Set up the vertex attributes
361 GLfloat minx = (dstrect == NULL) ? 0.0f : dstrect->x;
362 GLfloat miny = (dstrect == NULL) ? 0.0f : dstrect->y;
363 GLfloat maxx = (dstrect == NULL) ? tex->width : dstrect->x + dstrect->w;
364 GLfloat maxy = (dstrect == NULL) ? tex->height : dstrect->y + dstrect->h;
365
366 minx = minx / tex->width * 2.0 - 1.0;
367 miny = -(miny / tex->height * 2.0 - 1.0);
368 maxx = maxx / tex->width * 2.0 - 1.0;
369 maxy = -(maxy / tex->height * 2.0 - 1.0);
370
371 GLfloat vertexbuffer_data[] = {
372 minx, miny,
373 maxx, miny,
374 maxx, maxy,
375 minx, miny,
376 minx, maxy,
377 maxx, maxy
378 };
379 GLuint vertexbuffer;
380 glGenBuffers(1, &vertexbuffer);
381 glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
382 glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW);
383 glEnableVertexAttribArray(0);
384 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
385
386 glViewport(0, 0, tex->width, tex->height);
387 glUseProgram(fillShader);
388 glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0);
389
390 glDrawArrays(GL_TRIANGLES, 0, 6);
391
392 glDisableVertexAttribArray(0);
393 glDeleteBuffers(1, &vertexbuffer);
394}
395
396void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle* dstrect)
397{
398 if (!rendererInitialized)
399 {
400 fprintf(stderr, "Renderer not initialized\n");
401 exit(-1);
402 }
403
404 // Target the framebuffer
405 glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
406 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dsttex->texID, 0);
407
408 // Set up the vertex attributes
409 GLfloat minx = (dstrect == NULL) ? 0.0f : dstrect->x;
410 GLfloat miny = (dstrect == NULL) ? 0.0f : dstrect->y;
411 GLfloat maxx = (dstrect == NULL) ? dsttex->width : dstrect->x + dstrect->w;
412 GLfloat maxy = (dstrect == NULL) ? dsttex->height : dstrect->y + dstrect->h;
413
414 minx = minx / dsttex->width * 2.0 - 1.0;
415 miny = -(miny / dsttex->height * 2.0 - 1.0);
416 maxx = maxx / dsttex->width * 2.0 - 1.0;
417 maxy = -(maxy / dsttex->height * 2.0 - 1.0);
418
419 GLfloat vertexbuffer_data[] = {
420 minx, miny,
421 maxx, miny,
422 minx, maxy,
423 maxx, maxy
424 };
425 GLuint vertexbuffer;
426 glGenBuffers(1, &vertexbuffer);
427 glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
428 glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW);
429 glEnableVertexAttribArray(0);
430 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
431
432 GLfloat minu = (srcrect == NULL) ? 0.0f : srcrect->x;
433 GLfloat minv = (srcrect == NULL) ? 0.0f : srcrect->y;
434 GLfloat maxu = (srcrect == NULL) ? srctex->width : srcrect->x + srcrect->w;
435 GLfloat maxv = (srcrect == NULL) ? srctex->height : srcrect->y + srcrect->h;
436
437 minu = minu / srctex->width;
438 minv = 1 - (minv / srctex->height);
439 maxu = maxu / srctex->width;
440 maxv = 1 - (maxv / srctex->height);
441
442 GLfloat texcoordbuffer_data[] = {
443 minu, minv,
444 maxu, minv,
445 minu, maxv,
446 maxu, maxv
447 };
448 GLuint texcoordbuffer;
449 glGenBuffers(1, &texcoordbuffer);
450 glBindBuffer(GL_ARRAY_BUFFER, texcoordbuffer);
451 glBufferData(GL_ARRAY_BUFFER, sizeof(texcoordbuffer_data), texcoordbuffer_data, GL_STATIC_DRAW);
452 glEnableVertexAttribArray(1);
453 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
454
455 // Set up the shader
456 glUseProgram(blitShader);
457 glViewport(0, 0, dsttex->width, dsttex->height);
458
459 glActiveTexture(GL_TEXTURE0);
460 glBindTexture(GL_TEXTURE_2D, srctex->texID);
461 glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0);
462
463 // Blit!
464 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
465
466 // Unload everything
467 glDisableVertexAttribArray(1);
468 glDisableVertexAttribArray(0);
469 glDeleteBuffers(1, &texcoordbuffer);
470 glDeleteBuffers(1, &vertexbuffer);
471}
472
473void renderScreen(Texture* tex)
474{
475 if (!rendererInitialized)
476 {
477 fprintf(stderr, "Renderer not initialized\n");
478 exit(-1);
479 }
480
481 // Set up framebuffer
482 glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
483 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexBufs[curBuf], 0);
484
485 // Set up renderer
486 glViewport(0,0,GAME_WIDTH,GAME_HEIGHT);
487 glClear(GL_COLOR_BUFFER_BIT);
488 glUseProgram(ntscShader);
489
490 glActiveTexture(GL_TEXTURE0);
491 glBindTexture(GL_TEXTURE_2D, tex->texID);
492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
494 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
495 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
496 glUniform1i(glGetUniformLocation(ntscShader, "curFrameSampler"), 0);
497
498 glActiveTexture(GL_TEXTURE1);
499 glBindTexture(GL_TEXTURE_2D, renderedTexBufs[(curBuf + 1) % 2]);
500 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
501 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
502 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
503 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
504 glUniform1i(glGetUniformLocation(ntscShader, "prevFrameSampler"), 1);
505
506 glActiveTexture(GL_TEXTURE2);
507 glBindTexture(GL_TEXTURE_2D, artifactsTex);
508 glUniform1i(glGetUniformLocation(ntscShader, "NTSCArtifactSampler"), 2);
509
510 glUniform1f(glGetUniformLocation(ntscShader, "NTSCLerp"), curBuf * 1.0);
511
512 GLfloat g_quad_vertex_buffer_data[] = {
513 -1.0f, -1.0f, 0.0f,
514 1.0f, -1.0f, 0.0f,
515 -1.0f, 1.0f, 0.0f,
516 -1.0f, 1.0f, 0.0f,
517 1.0f, -1.0f, 0.0f,
518 1.0f, 1.0f, 0.0f,
519 };
520
521 GLuint quad_vertexbuffer;
522 glGenBuffers(1, &quad_vertexbuffer);
523 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
524 glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);
525
526 glEnableVertexAttribArray(0);
527 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
528 glDrawArrays(GL_TRIANGLES, 0, 6);
529 glDisableVertexAttribArray(0);
530
531 GLfloat g_norms_data[] = {
532 0.0f, 0.0f, 1.0f,
533 0.0f, 0.0f, 1.0f,
534 0.0f, 0.0f, 1.0f,
535 0.0f, 0.0f, 1.0f,
536 0.0f, 0.0f, 1.0f,
537 0.0f, 0.0f, 1.0f
538 };
539
540 GLuint g_norms;
541 glGenBuffers(1, &g_norms);
542 glBindBuffer(GL_ARRAY_BUFFER, g_norms);
543 glBufferData(GL_ARRAY_BUFFER, sizeof(g_norms_data), g_norms_data, GL_STATIC_DRAW);
544
545 glBindFramebuffer(GL_FRAMEBUFFER, 0);
546 glViewport(0,0,1024,768);
547 glClear(GL_COLOR_BUFFER_BIT);
548 glUseProgram(finalShader);
549 glActiveTexture(GL_TEXTURE0);
550 glBindTexture(GL_TEXTURE_2D, renderedTexBufs[curBuf]);
551 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
552 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
553 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
554 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
555 float border_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
556 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
557 glGenerateMipmap(GL_TEXTURE_2D);
558 glUniform1i(glGetUniformLocation(finalShader, "rendertex"), 0);
559
560 glActiveTexture(GL_TEXTURE1);
561 glBindTexture(GL_TEXTURE_2D, scanlinesTex);
562 glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1);
563
564 glEnableVertexAttribArray(0);
565 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
566 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
567
568 glEnableVertexAttribArray(1);
569 glBindBuffer(GL_ARRAY_BUFFER, g_norms);
570 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
571
572 glDrawArrays(GL_TRIANGLES, 0, 6);
573 glDisableVertexAttribArray(1);
574 glDisableVertexAttribArray(0);
575
576 glfwSwapBuffers(window);
577
578 glDeleteBuffers(1, &g_norms);
579 glDeleteBuffers(1, &quad_vertexbuffer);
580
581 curBuf = (curBuf + 1) % 2;
582}