diff options
Diffstat (limited to 'src/renderer.cpp')
-rw-r--r-- | src/renderer.cpp | 197 |
1 files changed, 168 insertions, 29 deletions
diff --git a/src/renderer.cpp b/src/renderer.cpp index 2ee0642..00ae7ef 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <fstream> | 3 | #include <fstream> |
4 | #include <vector> | 4 | #include <vector> |
5 | #include <cstdio> | 5 | #include <cstdio> |
6 | #include <cstring> | ||
6 | #include "mapview.h" | 7 | #include "mapview.h" |
7 | 8 | ||
8 | static bool rendererInitialized = false; | 9 | static bool rendererInitialized = false; |
@@ -10,6 +11,8 @@ static bool rendererInitialized = false; | |||
10 | static GLFWwindow* window; | 11 | static GLFWwindow* window; |
11 | 12 | ||
12 | static GLuint FramebufferName; // The framebuffer | 13 | static GLuint FramebufferName; // The framebuffer |
14 | static GLuint depthrenderbuffer; | ||
15 | |||
13 | static GLuint ntscShader; // The NTSC shader | 16 | static GLuint ntscShader; // The NTSC shader |
14 | static GLuint finalShader; // The passthrough shader | 17 | static GLuint finalShader; // The passthrough shader |
15 | static GLuint blitShader; // The blitting shader | 18 | static GLuint blitShader; // The blitting shader |
@@ -33,6 +36,12 @@ static GLuint VertexArrayID; | |||
33 | // A plane that fills the renderbuffer | 36 | // A plane that fills the renderbuffer |
34 | static GLuint quad_vertexbuffer; | 37 | static GLuint quad_vertexbuffer; |
35 | 38 | ||
39 | // Buffers for the mesh | ||
40 | static GLuint mesh_vertexbuffer; | ||
41 | static GLuint mesh_uvbuffer; | ||
42 | static GLuint mesh_normalbuffer; | ||
43 | static int mesh_numvertices; | ||
44 | |||
36 | GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path) | 45 | GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path) |
37 | { | 46 | { |
38 | // Create the shaders | 47 | // Create the shaders |
@@ -188,6 +197,58 @@ GLuint loadBMP_custom(const char * imagepath){ | |||
188 | return textureID; | 197 | return textureID; |
189 | } | 198 | } |
190 | 199 | ||
200 | void loadMesh(const char* filename, std::vector<glm::vec3>& out_vertices, std::vector<glm::vec2>& out_uvs, std::vector<glm::vec3>& out_normals) | ||
201 | { | ||
202 | FILE* file = fopen(filename, "r"); | ||
203 | if (file == NULL) | ||
204 | { | ||
205 | fprintf(stderr, "Could not open mesh file %s\n", filename); | ||
206 | exit(1); | ||
207 | } | ||
208 | |||
209 | std::vector<glm::vec3> temp_vertices; | ||
210 | std::vector<glm::vec2> temp_uvs; | ||
211 | std::vector<glm::vec3> temp_normals; | ||
212 | |||
213 | for (;;) | ||
214 | { | ||
215 | char lineHeader[256]; | ||
216 | int res = fscanf(file, "%s", lineHeader); | ||
217 | if (res == EOF) | ||
218 | { | ||
219 | break; | ||
220 | } | ||
221 | |||
222 | if (!strncmp(lineHeader, "v", 2)) | ||
223 | { | ||
224 | vec3 vertex; | ||
225 | fscanf(file, "%f %f %f\n", &vertex.x,&vertex.y,&vertex.z); | ||
226 | temp_vertices.push_back(vertex); | ||
227 | } else if (!strncmp(lineHeader, "vt", 3)) | ||
228 | { | ||
229 | vec2 uv; | ||
230 | fscanf(file, "%f %f\n", &uv.x, &uv.y); | ||
231 | temp_uvs.push_back(uv); | ||
232 | } else if (!strncmp(lineHeader, "vn", 3)) | ||
233 | { | ||
234 | vec3 normal; | ||
235 | fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z); | ||
236 | temp_normals.push_back(normal); | ||
237 | } else if (!strncmp(lineHeader, "f", 2)) | ||
238 | { | ||
239 | int vertexIDs[3], uvIDs[3], normalIDs[3]; | ||
240 | 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]); | ||
241 | |||
242 | for (int i=0; i<3; i++) | ||
243 | { | ||
244 | out_vertices.push_back(temp_vertices[vertexIDs[i] - 1]); | ||
245 | out_uvs.push_back(temp_uvs[uvIDs[i] - 1]); | ||
246 | out_normals.push_back(temp_normals[normalIDs[i] - 1]); | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | |||
191 | GLFWwindow* initRenderer() | 252 | GLFWwindow* initRenderer() |
192 | { | 253 | { |
193 | if (rendererInitialized) | 254 | if (rendererInitialized) |
@@ -230,12 +291,20 @@ GLFWwindow* initRenderer() | |||
230 | glGenVertexArrays(1, &VertexArrayID); | 291 | glGenVertexArrays(1, &VertexArrayID); |
231 | glBindVertexArray(VertexArrayID); | 292 | glBindVertexArray(VertexArrayID); |
232 | 293 | ||
294 | glEnable(GL_DEPTH_TEST); | ||
295 | glDepthFunc(GL_LESS); | ||
296 | |||
233 | // Set up the framebuffer | 297 | // Set up the framebuffer |
234 | glGenFramebuffers(1, &FramebufferName); | 298 | glGenFramebuffers(1, &FramebufferName); |
235 | glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); | 299 | glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); |
236 | GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; | 300 | GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; |
237 | glDrawBuffers(1, DrawBuffers); | 301 | glDrawBuffers(1, DrawBuffers); |
238 | 302 | ||
303 | glGenRenderbuffers(1, &depthrenderbuffer); | ||
304 | glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer); | ||
305 | glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 1024, 768); | ||
306 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer); | ||
307 | |||
239 | // Set up the NTSC rendering buffers | 308 | // Set up the NTSC rendering buffers |
240 | glGenTextures(1, &renderedTex1); | 309 | glGenTextures(1, &renderedTex1); |
241 | glBindTexture(GL_TEXTURE_2D, renderedTex1); | 310 | glBindTexture(GL_TEXTURE_2D, renderedTex1); |
@@ -274,6 +343,26 @@ GLFWwindow* initRenderer() | |||
274 | 343 | ||
275 | curBuf = 0; | 344 | curBuf = 0; |
276 | 345 | ||
346 | // Load the mesh! | ||
347 | std::vector<glm::vec3> mesh_vertices; | ||
348 | std::vector<glm::vec2> mesh_uvs; | ||
349 | std::vector<glm::vec3> mesh_normals; | ||
350 | loadMesh("../res/monitor-fef.obj", mesh_vertices, mesh_uvs, mesh_normals); | ||
351 | |||
352 | mesh_numvertices = mesh_vertices.size(); | ||
353 | |||
354 | glGenBuffers(1, &mesh_vertexbuffer); | ||
355 | glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer); | ||
356 | glBufferData(GL_ARRAY_BUFFER, mesh_vertices.size() * sizeof(vec3), &mesh_vertices[0], GL_STATIC_DRAW); | ||
357 | |||
358 | glGenBuffers(1, &mesh_uvbuffer); | ||
359 | glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer); | ||
360 | glBufferData(GL_ARRAY_BUFFER, mesh_uvs.size() * sizeof(vec3), &mesh_uvs[0], GL_STATIC_DRAW); | ||
361 | |||
362 | glGenBuffers(1, &mesh_normalbuffer); | ||
363 | glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer); | ||
364 | glBufferData(GL_ARRAY_BUFFER, mesh_normals.size() * sizeof(vec3), &mesh_normals[0], GL_STATIC_DRAW); | ||
365 | |||
277 | // Load the vertices of a flat surface | 366 | // Load the vertices of a flat surface |
278 | GLfloat g_quad_vertex_buffer_data[] = { | 367 | GLfloat g_quad_vertex_buffer_data[] = { |
279 | -1.0f, -1.0f, 0.0f, | 368 | -1.0f, -1.0f, 0.0f, |
@@ -314,6 +403,9 @@ void destroyRenderer() | |||
314 | 403 | ||
315 | // Delete the plane buffer | 404 | // Delete the plane buffer |
316 | glDeleteBuffers(1, &quad_vertexbuffer); | 405 | glDeleteBuffers(1, &quad_vertexbuffer); |
406 | glDeleteBuffers(1, &mesh_vertexbuffer); | ||
407 | glDeleteBuffers(1, &mesh_uvbuffer); | ||
408 | glDeleteBuffers(1, &mesh_normalbuffer); | ||
317 | 409 | ||
318 | // Delete the shaders | 410 | // Delete the shaders |
319 | glDeleteProgram(ntscShader); | 411 | glDeleteProgram(ntscShader); |
@@ -332,6 +424,7 @@ void destroyRenderer() | |||
332 | glDeleteTextures(1, &bloomPassTex); | 424 | glDeleteTextures(1, &bloomPassTex); |
333 | 425 | ||
334 | // Delete the framebuffer | 426 | // Delete the framebuffer |
427 | glDeleteRenderbuffers(1, &depthrenderbuffer); | ||
335 | glDeleteFramebuffers(1, &FramebufferName); | 428 | glDeleteFramebuffers(1, &FramebufferName); |
336 | 429 | ||
337 | // Delete the VAO | 430 | // Delete the VAO |
@@ -466,6 +559,7 @@ void fillTexture(Texture* tex, Rectangle* dstrect, int r, int g, int b) | |||
466 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); | 559 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); |
467 | 560 | ||
468 | glViewport(0, 0, tex->width, tex->height); | 561 | glViewport(0, 0, tex->width, tex->height); |
562 | glClear(GL_DEPTH_BUFFER_BIT); | ||
469 | glUseProgram(fillShader); | 563 | glUseProgram(fillShader); |
470 | glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0); | 564 | glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0); |
471 | 565 | ||
@@ -536,6 +630,7 @@ void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle | |||
536 | 630 | ||
537 | // Set up the shader | 631 | // Set up the shader |
538 | glUseProgram(blitShader); | 632 | glUseProgram(blitShader); |
633 | glClear(GL_DEPTH_BUFFER_BIT); | ||
539 | glViewport(0, 0, dsttex->width, dsttex->height); | 634 | glViewport(0, 0, dsttex->width, dsttex->height); |
540 | 635 | ||
541 | glActiveTexture(GL_TEXTURE0); | 636 | glActiveTexture(GL_TEXTURE0); |
@@ -552,6 +647,62 @@ void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle | |||
552 | glDeleteBuffers(1, &vertexbuffer); | 647 | glDeleteBuffers(1, &vertexbuffer); |
553 | } | 648 | } |
554 | 649 | ||
650 | void renderWithoutEffects(Texture* tex) | ||
651 | { | ||
652 | if (!rendererInitialized) | ||
653 | { | ||
654 | fprintf(stderr, "Renderer not initialized\n"); | ||
655 | exit(-1); | ||
656 | } | ||
657 | |||
658 | glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||
659 | glViewport(0, 0, 1024, 768); | ||
660 | glClear(GL_COLOR_BUFFER_BIT); | ||
661 | glUseProgram(blitShader); | ||
662 | |||
663 | const GLfloat fullBlitVertices_data[] = { | ||
664 | -1.0, -1.0, | ||
665 | 1.0, -1.0, | ||
666 | -1.0, 1.0, | ||
667 | 1.0, 1.0 | ||
668 | }; | ||
669 | |||
670 | GLuint fullBlitVertices; | ||
671 | glGenBuffers(1, &fullBlitVertices); | ||
672 | glBindBuffer(GL_ARRAY_BUFFER, fullBlitVertices); | ||
673 | glBufferData(GL_ARRAY_BUFFER, sizeof(fullBlitVertices_data), fullBlitVertices_data, GL_STATIC_DRAW); | ||
674 | glEnableVertexAttribArray(0); | ||
675 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
676 | |||
677 | const GLfloat fullBlitTex_data[] = { | ||
678 | 0.0, 0.0, | ||
679 | 1.0, 0.0, | ||
680 | 0.0, 1.0, | ||
681 | 1.0, 1.0 | ||
682 | }; | ||
683 | |||
684 | GLuint fullBlitTex; | ||
685 | glGenBuffers(1, &fullBlitTex); | ||
686 | glBindBuffer(GL_ARRAY_BUFFER, fullBlitTex); | ||
687 | glBufferData(GL_ARRAY_BUFFER, sizeof(fullBlitTex_data), fullBlitTex_data, GL_STATIC_DRAW); | ||
688 | glEnableVertexAttribArray(1); | ||
689 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
690 | |||
691 | glActiveTexture(GL_TEXTURE0); | ||
692 | glBindTexture(GL_TEXTURE_2D, tex->texID); | ||
693 | glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0); | ||
694 | |||
695 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | ||
696 | |||
697 | glDisableVertexAttribArray(1); | ||
698 | glDisableVertexAttribArray(0); | ||
699 | |||
700 | glDeleteBuffers(1, &fullBlitTex); | ||
701 | glDeleteBuffers(1, &fullBlitVertices); | ||
702 | |||
703 | glfwSwapBuffers(window); | ||
704 | } | ||
705 | |||
555 | void renderScreen(Texture* tex) | 706 | void renderScreen(Texture* tex) |
556 | { | 707 | { |
557 | if (!rendererInitialized) | 708 | if (!rendererInitialized) |
@@ -565,9 +716,9 @@ void renderScreen(Texture* tex) | |||
565 | glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); | 716 | glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); |
566 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexBufs[curBuf], 0); | 717 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexBufs[curBuf], 0); |
567 | 718 | ||
568 | // Set up the shaer | 719 | // Set up the shader |
569 | glViewport(0,0,GAME_WIDTH,GAME_HEIGHT); | 720 | glViewport(0,0,GAME_WIDTH,GAME_HEIGHT); |
570 | glClear(GL_COLOR_BUFFER_BIT); | 721 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
571 | glUseProgram(ntscShader); | 722 | glUseProgram(ntscShader); |
572 | 723 | ||
573 | // Use the current frame texture, nearest neighbor and clamped to edge | 724 | // Use the current frame texture, nearest neighbor and clamped to edge |
@@ -601,26 +752,11 @@ void renderScreen(Texture* tex) | |||
601 | glDrawArrays(GL_TRIANGLES, 0, 6); | 752 | glDrawArrays(GL_TRIANGLES, 0, 6); |
602 | glDisableVertexAttribArray(0); | 753 | glDisableVertexAttribArray(0); |
603 | 754 | ||
604 | // Load the normal vertices of a flat surface | ||
605 | GLfloat g_norms_data[] = { | ||
606 | 0.0f, 0.0f, 1.0f, | ||
607 | 0.0f, 0.0f, 1.0f, | ||
608 | 0.0f, 0.0f, 1.0f, | ||
609 | 0.0f, 0.0f, 1.0f, | ||
610 | 0.0f, 0.0f, 1.0f, | ||
611 | 0.0f, 0.0f, 1.0f | ||
612 | }; | ||
613 | |||
614 | GLuint g_norms; | ||
615 | glGenBuffers(1, &g_norms); | ||
616 | glBindBuffer(GL_ARRAY_BUFFER, g_norms); | ||
617 | glBufferData(GL_ARRAY_BUFFER, sizeof(g_norms_data), g_norms_data, GL_STATIC_DRAW); | ||
618 | |||
619 | // We're going to render the screen now | 755 | // We're going to render the screen now |
620 | //glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||
621 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, preBloomTex, 0); | 756 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, preBloomTex, 0); |
757 | //glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||
622 | glViewport(0,0,1024,768); | 758 | glViewport(0,0,1024,768); |
623 | glClear(GL_COLOR_BUFFER_BIT); | 759 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
624 | glUseProgram(finalShader); | 760 | glUseProgram(finalShader); |
625 | 761 | ||
626 | // Use the composited frame texture, linearly filtered and filling in black for the border | 762 | // Use the composited frame texture, linearly filtered and filling in black for the border |
@@ -641,9 +777,9 @@ void renderScreen(Texture* tex) | |||
641 | glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1); | 777 | glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1); |
642 | 778 | ||
643 | // Initialize the MVP matrices | 779 | // Initialize the MVP matrices |
644 | mat4 p_matrix = perspective(90.0f, 4.0f / 4.0f, 0.1f, 100.0f); | 780 | mat4 p_matrix = perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f); |
645 | mat4 v_matrix = lookAt(vec3(0,0,1), vec3(0,0,0), vec3(0,1,0)); | 781 | mat4 v_matrix = lookAt(vec3(2,0,0), vec3(0,0,0), vec3(0,1,0)); |
646 | mat4 m_matrix = mat4(1.0f); | 782 | mat4 m_matrix = mat4(1.0); |
647 | mat4 mvp_matrix = p_matrix * v_matrix * m_matrix; | 783 | mat4 mvp_matrix = p_matrix * v_matrix * m_matrix; |
648 | //mat4 mv_matrix = v_matrix * m_matrix; | 784 | //mat4 mv_matrix = v_matrix * m_matrix; |
649 | 785 | ||
@@ -651,21 +787,26 @@ void renderScreen(Texture* tex) | |||
651 | glUniformMatrix4fv(glGetUniformLocation(finalShader, "worldMat"), 1, GL_FALSE, &m_matrix[0][0]); | 787 | glUniformMatrix4fv(glGetUniformLocation(finalShader, "worldMat"), 1, GL_FALSE, &m_matrix[0][0]); |
652 | 788 | ||
653 | glEnableVertexAttribArray(0); | 789 | glEnableVertexAttribArray(0); |
654 | glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); | 790 | glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer); |
655 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); | 791 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); |
656 | 792 | ||
657 | glEnableVertexAttribArray(1); | 793 | glEnableVertexAttribArray(1); |
658 | glBindBuffer(GL_ARRAY_BUFFER, g_norms); | 794 | glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer); |
659 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); | 795 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); |
660 | 796 | ||
661 | glDrawArrays(GL_TRIANGLES, 0, 6); | 797 | glEnableVertexAttribArray(2); |
798 | glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer); | ||
799 | glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); | ||
800 | |||
801 | glDrawArrays(GL_TRIANGLES, 0, mesh_numvertices); | ||
802 | glDisableVertexAttribArray(2); | ||
662 | glDisableVertexAttribArray(1); | 803 | glDisableVertexAttribArray(1); |
663 | glDisableVertexAttribArray(0); | 804 | glDisableVertexAttribArray(0); |
664 | 805 | ||
665 | // Do the first pass of bloom (downsampling and tapping) | 806 | // Do the first pass of bloom (downsampling and tapping) |
666 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, bloomPassTex, 0); | 807 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, bloomPassTex, 0); |
667 | glViewport(0, 0, 64, 48); | 808 | glViewport(0, 0, 64, 48); |
668 | glClear(GL_COLOR_BUFFER_BIT); | 809 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
669 | glUseProgram(bloom1Shader); | 810 | glUseProgram(bloom1Shader); |
670 | 811 | ||
671 | glActiveTexture(GL_TEXTURE0); | 812 | glActiveTexture(GL_TEXTURE0); |
@@ -683,7 +824,7 @@ void renderScreen(Texture* tex) | |||
683 | // Do the second pass of bloom and render to screen | 824 | // Do the second pass of bloom and render to screen |
684 | glBindFramebuffer(GL_FRAMEBUFFER, 0); | 825 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
685 | glViewport(0, 0, 1024, 768); | 826 | glViewport(0, 0, 1024, 768); |
686 | glClear(GL_COLOR_BUFFER_BIT); | 827 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
687 | glUseProgram(bloom2Shader); | 828 | glUseProgram(bloom2Shader); |
688 | 829 | ||
689 | glActiveTexture(GL_TEXTURE0); | 830 | glActiveTexture(GL_TEXTURE0); |
@@ -704,7 +845,5 @@ void renderScreen(Texture* tex) | |||
704 | 845 | ||
705 | glfwSwapBuffers(window); | 846 | glfwSwapBuffers(window); |
706 | 847 | ||
707 | glDeleteBuffers(1, &g_norms); | ||
708 | |||
709 | curBuf = (curBuf + 1) % 2; | 848 | curBuf = (curBuf + 1) % 2; |
710 | } | 849 | } |