bool create_programme (GLuint vert, GLuint frag, GLuint* programme) { *programme = glCreateProgram (); gl_log ( "created programme %u. attaching shaders %u and %u...\n", *programme, vert, frag ); glAttachShader (*programme, vert); glAttachShader (*programme, frag); // link the shader programme. if binding input attributes do that before link glLinkProgram (*programme); GLint params = -1; glGetProgramiv (*programme, GL_LINK_STATUS, ¶ms); if (GL_TRUE != params) { gl_log_err ( "ERROR: could not link shader programme GL index %u\n", *programme ); print_programme_info_log (*programme); return false; } assert (is_programme_valid (*programme)); // delete shaders here to free memory glDeleteShader (vert); glDeleteShader (frag); return true; }
bool is_programme_valid (GLuint sp) { glValidateProgram (sp); GLint params = -1; glGetProgramiv (sp, GL_VALIDATE_STATUS, ¶ms); if (GL_TRUE != params) { gl_log_err ("program %i GL_VALIDATE_STATUS = GL_FALSE\n", sp); print_programme_info_log (sp); return false; } gl_log ("program %i GL_VALIDATE_STATUS = GL_TRUE\n", sp); return true; }
int main () { assert (restart_gl_log ()); // all the start-up code for GLFW and GLEW is called here assert (start_gl ()); // tell GL to only draw onto a pixel if the shape is closer to the viewer glEnable (GL_DEPTH_TEST); // enable depth-testing glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" /* OTHER STUFF GOES HERE NEXT */ GLfloat points[] = { 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f }; GLfloat colours[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; glm::mat4 mvp = glm::mat4(1.0f); GLuint points_vbo; glGenBuffers (1, &points_vbo); glBindBuffer (GL_ARRAY_BUFFER, points_vbo); // glBufferData (GL_ARRAY_BUFFER, 9 * sizeof (GLfloat), points, GL_STATIC_DRAW); glBufferData (GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data) * sizeof (GLfloat), g_vertex_buffer_data, GL_STATIC_DRAW); /* create a second VBO, containing the array of colours. note that we could also put them both into a single vertex buffer. in this case we would use the pointer and stride parameters of glVertexAttribPointer() to describe the different data layouts */ GLuint colours_vbo; glGenBuffers (1, &colours_vbo); glBindBuffer (GL_ARRAY_BUFFER, colours_vbo); // glBufferData (GL_ARRAY_BUFFER, 9 * sizeof (GLfloat), colours, GL_STATIC_DRAW); glBufferData (GL_ARRAY_BUFFER, sizeof(g_color_buffer_data) * sizeof (GLfloat), g_color_buffer_data, GL_STATIC_DRAW); /* create the VAO. we bind each VBO in turn, and call glVertexAttribPointer() to indicate where the memory should be fetched for vertex shader input variables 0, and 1, respectively. we also have to explicitly enable both 'attribute' variables. 'attribute' is the older name for vertex shader 'in' variables. */ GLuint vao; glGenVertexArrays (1, &vao); glBindVertexArray (vao); glBindBuffer (GL_ARRAY_BUFFER, points_vbo); glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL); glBindBuffer (GL_ARRAY_BUFFER, colours_vbo); glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray (0); glEnableVertexAttribArray (1); char vertex_shader[1024 * 256]; char fragment_shader[1024 * 256]; assert (parse_file_into_str ("test_vs.glsl", vertex_shader, 1024 * 256)); assert (parse_file_into_str ("test_fs.glsl", fragment_shader, 1024 * 256)); GLuint vs = glCreateShader (GL_VERTEX_SHADER); const GLchar* p = (const GLchar*)vertex_shader; glShaderSource (vs, 1, &p, NULL); glCompileShader (vs); // check for compile errors int params = -1; glGetShaderiv (vs, GL_COMPILE_STATUS, ¶ms); if (GL_TRUE != params) { fprintf (stderr, "ERROR: GL shader index %i did not compile\n", vs); print_shader_info_log (vs); return 1; // or exit or something } GLuint fs = glCreateShader (GL_FRAGMENT_SHADER); p = (const GLchar*)fragment_shader; glShaderSource (fs, 1, &p, NULL); glCompileShader (fs); // check for compile errors glGetShaderiv (fs, GL_COMPILE_STATUS, ¶ms); if (GL_TRUE != params) { fprintf (stderr, "ERROR: GL shader index %i did not compile\n", fs); print_shader_info_log (fs); return 1; // or exit or something } GLuint shader_programme = glCreateProgram (); glAttachShader (shader_programme, fs); glAttachShader (shader_programme, vs); glBindAttribLocation(shader_programme, 0, "vertex_position"); glBindAttribLocation(shader_programme, 1, "vertex_colour"); glLinkProgram (shader_programme); glGetProgramiv (shader_programme, GL_LINK_STATUS, ¶ms); if (GL_TRUE != params) { fprintf ( stderr, "ERROR: could not link shader programme GL index %i\n", shader_programme ); print_programme_info_log (shader_programme); return false; } //pass uniform GLint u = glGetUniformLocation(shader_programme, "mvp"); assert (u > -1); glUniformMatrix4fv(u, 1, GL_FALSE, &mvp[0][0]); glEnable (GL_CULL_FACE); // cull face glCullFace (GL_BACK); // cull back face glFrontFace (GL_CW); // GL_CCW for counter clock-wise while (!glfwWindowShouldClose (g_window)) { _update_fps_counter (g_window); // wipe the drawing surface clear glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport (0, 0, g_gl_width, g_gl_height); glUseProgram (shader_programme); glBindVertexArray (vao); // draw points 0-3 from the currently bound VAO with current in-use shader glDrawArrays (GL_TRIANGLES, 0, 12* 3); // update other events like input handling glfwPollEvents (); if (GLFW_PRESS == glfwGetKey (g_window, GLFW_KEY_ESCAPE)) { glfwSetWindowShouldClose (g_window, 1); } // put the stuff we've been drawing onto the display glfwSwapBuffers (g_window); } // close GL context and any other GLFW resources glfwTerminate(); return 0; }
int main () { restart_gl_log (); // all the GLFW and GLEW start-up code is moved to here in gl_utils.cpp start_gl (); // tell GL to only draw onto a pixel if the shape is closer to the viewer glEnable (GL_DEPTH_TEST); // enable depth-testing glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" /* OTHER STUFF GOES HERE NEXT */ GLfloat points[] = { 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f }; GLfloat colours[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; GLuint points_vbo; glGenBuffers (1, &points_vbo); glBindBuffer (GL_ARRAY_BUFFER, points_vbo); glBufferData (GL_ARRAY_BUFFER, 9 * sizeof (GLfloat), points, GL_STATIC_DRAW); GLuint colours_vbo; glGenBuffers (1, &colours_vbo); glBindBuffer (GL_ARRAY_BUFFER, colours_vbo); glBufferData (GL_ARRAY_BUFFER, 9 * sizeof (GLfloat), colours, GL_STATIC_DRAW); GLuint vao; glGenVertexArrays (1, &vao); glBindVertexArray (vao); glBindBuffer (GL_ARRAY_BUFFER, points_vbo); glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL); glBindBuffer (GL_ARRAY_BUFFER, colours_vbo); glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray (0); glEnableVertexAttribArray (1); char vertex_shader[1024 * 256]; char fragment_shader[1024 * 256]; parse_file_into_str ("test_vs.glsl", vertex_shader, 1024 * 256); parse_file_into_str ("test_fs.glsl", fragment_shader, 1024 * 256); GLuint vs = glCreateShader (GL_VERTEX_SHADER); const GLchar* p = (const GLchar*)vertex_shader; glShaderSource (vs, 1, &p, NULL); glCompileShader (vs); // check for compile errors int params = -1; glGetShaderiv (vs, GL_COMPILE_STATUS, ¶ms); if (GL_TRUE != params) { fprintf (stderr, "ERROR: GL shader index %i did not compile\n", vs); print_shader_info_log (vs); return 1; // or exit or something } GLuint fs = glCreateShader (GL_FRAGMENT_SHADER); p = (const GLchar*)fragment_shader; glShaderSource (fs, 1, &p, NULL); glCompileShader (fs); // check for compile errors glGetShaderiv (fs, GL_COMPILE_STATUS, ¶ms); if (GL_TRUE != params) { fprintf (stderr, "ERROR: GL shader index %i did not compile\n", fs); print_shader_info_log (fs); return 1; // or exit or something } GLuint shader_programme = glCreateProgram (); glAttachShader (shader_programme, fs); glAttachShader (shader_programme, vs); glLinkProgram (shader_programme); glGetProgramiv (shader_programme, GL_LINK_STATUS, ¶ms); if (GL_TRUE != params) { fprintf ( stderr, "ERROR: could not link shader programme GL index %i\n", shader_programme ); print_programme_info_log (shader_programme); return false; } GLfloat matrix[] = { 1.0f, 0.0f, 0.0f, 0.0f, // first column 0.0f, 1.0f, 0.0f, 0.0f, // second column 0.0f, 0.0f, 1.0f, 0.0f, // third column 0.5f, 0.0f, 0.0f, 1.0f // fourth column }; int matrix_location = glGetUniformLocation (shader_programme, "matrix"); glUseProgram (shader_programme); glUniformMatrix4fv (matrix_location, 1, GL_FALSE, matrix); glEnable (GL_CULL_FACE); // cull face glCullFace (GL_BACK); // cull back face glFrontFace (GL_CW); // GL_CCW for counter clock-wise float speed = 1.0f; // move at 1 unit per second float last_position = 0.0f; while (!glfwWindowShouldClose (g_window)) { // add a timer for doing animation static double previous_seconds = glfwGetTime (); double current_seconds = glfwGetTime (); double elapsed_seconds = current_seconds - previous_seconds; previous_seconds = current_seconds; _update_fps_counter (g_window); // wipe the drawing surface clear glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport (0, 0, g_gl_width, g_gl_height); // // Note: this call is not necessary, but I like to do it anyway before any // time that I call glDrawArrays() so I never use the wrong shader programme glUseProgram (shader_programme); // update the matrix // - you could simplify this by just using sin(current_seconds) matrix[12] = elapsed_seconds * speed + last_position; last_position = matrix[12]; if (fabs (last_position) > 1.0) { speed = -speed; } // // Note: this call is related to the most recently 'used' shader programme glUniformMatrix4fv (matrix_location, 1, GL_FALSE, matrix); // // Note: this call is not necessary, but I like to do it anyway before any // time that I call glDrawArrays() so I never use the wrong vertex data glBindVertexArray (vao); // draw points 0-3 from the currently bound VAO with current in-use shader glDrawArrays (GL_TRIANGLES, 0, 3); // update other events like input handling glfwPollEvents (); if (GLFW_PRESS == glfwGetKey (g_window, GLFW_KEY_ESCAPE)) { glfwSetWindowShouldClose (g_window, 1); } // put the stuff we've been drawing onto the display glfwSwapBuffers (g_window); } // close GL context and any other GLFW resources glfwTerminate(); return 0; }
int main () { assert (restart_gl_log ()); assert (start_gl ()); // tell GL to only draw onto a pixel if the shape is closer to the viewer glEnable (GL_DEPTH_TEST); // enable depth-testing glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" glClearColor (0.2, 0.2, 0.2, 1.0); GLfloat points[] = { 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f }; GLfloat colours[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; GLuint points_vbo; glGenBuffers (1, &points_vbo); glBindBuffer (GL_ARRAY_BUFFER, points_vbo); glBufferData (GL_ARRAY_BUFFER, 9 * sizeof (GLfloat), points, GL_STATIC_DRAW); GLuint colours_vbo; glGenBuffers (1, &colours_vbo); glBindBuffer (GL_ARRAY_BUFFER, colours_vbo); glBufferData (GL_ARRAY_BUFFER, 9 * sizeof (GLfloat), colours, GL_STATIC_DRAW); GLuint vao; glGenVertexArrays (1, &vao); glBindVertexArray (vao); glBindBuffer (GL_ARRAY_BUFFER, points_vbo); glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL); glBindBuffer (GL_ARRAY_BUFFER, colours_vbo); glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray (0); glEnableVertexAttribArray (1); char vertex_shader[1024 * 256]; char geometry_shader[1024 * 256]; char fragment_shader[1024 * 256]; assert (parse_file_into_str ("test_vs.glsl", vertex_shader, 1024 * 256)); assert (parse_file_into_str ("test_gs.glsl", geometry_shader, 1024 * 256)); assert (parse_file_into_str ("test_fs.glsl", fragment_shader, 1024 * 256)); GLuint vs = glCreateShader (GL_VERTEX_SHADER); const GLchar* p = (const GLchar*)vertex_shader; glShaderSource (vs, 1, &p, NULL); glCompileShader (vs); // check for compile errors int params = -1; glGetShaderiv (vs, GL_COMPILE_STATUS, ¶ms); if (GL_TRUE != params) { fprintf (stderr, "ERROR: GL shader index %i did not compile\n", vs); print_shader_info_log (vs); return 1; // or exit or something } // create geometry shader GLuint gs = glCreateShader (GL_GEOMETRY_SHADER); p = (const GLchar*)geometry_shader; glShaderSource (gs, 1, &p, NULL); glCompileShader (gs); // check for compile errors glGetShaderiv (gs, GL_COMPILE_STATUS, ¶ms); if (GL_TRUE != params) { fprintf (stderr, "ERROR: GL shader index %i did not compile\n", gs); print_shader_info_log (gs); return 1; // or exit or something } GLuint fs = glCreateShader (GL_FRAGMENT_SHADER); p = (const GLchar*)fragment_shader; glShaderSource (fs, 1, &p, NULL); glCompileShader (fs); // check for compile errors glGetShaderiv (fs, GL_COMPILE_STATUS, ¶ms); if (GL_TRUE != params) { fprintf (stderr, "ERROR: GL shader index %i did not compile\n", fs); print_shader_info_log (fs); return 1; // or exit or something } GLuint shader_programme = glCreateProgram (); glAttachShader (shader_programme, fs); // attach geometry shader too glAttachShader (shader_programme, gs); glAttachShader (shader_programme, vs); glLinkProgram (shader_programme); glGetProgramiv (shader_programme, GL_LINK_STATUS, ¶ms); if (GL_TRUE != params) { fprintf ( stderr, "ERROR: could not link shader programme GL index %i\n", shader_programme ); print_programme_info_log (shader_programme); return false; } assert (is_programme_valid (shader_programme)); glEnable (GL_CULL_FACE); // cull face glCullFace (GL_BACK); // cull back face glFrontFace (GL_CW); // GL_CCW for counter clock-wise while (!glfwWindowShouldClose (g_window)) { _update_fps_counter (g_window); // wipe the drawing surface clear glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport (0, 0, g_gl_width, g_gl_height); glUseProgram (shader_programme); glBindVertexArray (vao); // points drawing mode glDrawArrays (GL_POINTS, 0, 3); // update other events like input handling glfwPollEvents (); if (GLFW_PRESS == glfwGetKey (g_window, GLFW_KEY_ESCAPE)) { glfwSetWindowShouldClose (g_window, 1); } // put the stuff we've been drawing onto the display glfwSwapBuffers (g_window); } // close GL context and any other GLFW resources glfwTerminate(); return 0; }
int main () { assert (restart_gl_log ()); /*------------------------------start GL context------------------------------*/ assert (start_gl ()); /*------------------------------create geometry-------------------------------*/ GLfloat points[] = { 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f }; GLfloat colours[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; GLuint points_vbo; glGenBuffers (1, &points_vbo); glBindBuffer (GL_ARRAY_BUFFER, points_vbo); glBufferData (GL_ARRAY_BUFFER, 9 * sizeof (GLfloat), points, GL_STATIC_DRAW); GLuint colours_vbo; glGenBuffers (1, &colours_vbo); glBindBuffer (GL_ARRAY_BUFFER, colours_vbo); glBufferData (GL_ARRAY_BUFFER, 9 * sizeof (GLfloat), colours, GL_STATIC_DRAW); GLuint vao; glGenVertexArrays (1, &vao); glBindVertexArray (vao); glBindBuffer (GL_ARRAY_BUFFER, points_vbo); glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL); glBindBuffer (GL_ARRAY_BUFFER, colours_vbo); glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray (0); glEnableVertexAttribArray (1); /*------------------------------create shaders--------------------------------*/ char vertex_shader[1024 * 256]; char fragment_shader[1024 * 256]; assert (parse_file_into_str ("Shaders/test_vs.glsl", vertex_shader, 1024 * 256)); assert (parse_file_into_str ("Shaders/test_fs.glsl", fragment_shader, 1024 * 256)); GLuint vs = glCreateShader (GL_VERTEX_SHADER); const GLchar* p = (const GLchar*)vertex_shader; glShaderSource (vs, 1, &p, NULL); glCompileShader (vs); // check for compile errors int params = -1; glGetShaderiv (vs, GL_COMPILE_STATUS, ¶ms); if (GL_TRUE != params) { fprintf (stderr, "ERROR: GL shader index %i did not compile\n", vs); print_shader_info_log (vs); return 1; // or exit or something } GLuint fs = glCreateShader (GL_FRAGMENT_SHADER); p = (const GLchar*)fragment_shader; glShaderSource (fs, 1, &p, NULL); glCompileShader (fs); // check for compile errors glGetShaderiv (fs, GL_COMPILE_STATUS, ¶ms); if (GL_TRUE != params) { fprintf (stderr, "ERROR: GL shader index %i did not compile\n", fs); print_shader_info_log (fs); return 1; // or exit or something } GLuint shader_programme = glCreateProgram (); glAttachShader (shader_programme, fs); glAttachShader (shader_programme, vs); glLinkProgram (shader_programme); glGetProgramiv (shader_programme, GL_LINK_STATUS, ¶ms); if (GL_TRUE != params) { fprintf ( stderr, "ERROR: could not link shader programme GL index %i\n", shader_programme ); print_programme_info_log (shader_programme); return false; } /*--------------------------create camera matrices----------------------------*/ /* create PROJECTION MATRIX */ #define ONE_DEG_IN_RAD (2.0 * M_PI) / 360.0 // 0.017444444 // input variables float near = 0.1f; // clipping plane float far = 100.0f; // clipping plane float fov = 67.0f * ONE_DEG_IN_RAD; // convert 67 degrees to radians float aspect = (float)g_gl_width / (float)g_gl_height; // aspect ratio // matrix components float range = tan (fov * 0.5f) * near; float Sx = (2.0f * near) / (range * aspect + range * aspect); float Sy = near / range; float Sz = -(far + near) / (far - near); float Pz = -(2.0f * far * near) / (far - near); GLfloat proj_mat[] = { Sx, 0.0f, 0.0f, 0.0f, 0.0f, Sy, 0.0f, 0.0f, 0.0f, 0.0f, Sz, -1.0f, 0.0f, 0.0f, Pz, 0.0f }; /* create VIEW MATRIX */ float cam_speed = 1.0f; // 1 unit per second float cam_yaw_speed = 10.0f; // 10 degrees per second float cam_pos[] = {0.0f, 0.0f, 2.0f}; // don't start at zero, or we will be too close float cam_yaw = 0.0f; // y-rotation in degrees mat4 T = translate (identity_mat4 (), vec3 (-cam_pos[0], -cam_pos[1], -cam_pos[2])); mat4 R = rotate_y_deg (identity_mat4 (), -cam_yaw); mat4 view_mat = R * T; /* get location numbers of matrices in shader programme */ GLint view_mat_location = glGetUniformLocation (shader_programme, "view"); GLint proj_mat_location = glGetUniformLocation (shader_programme, "proj"); /* use program (make current in state machine) and set default matrix values*/ glUseProgram (shader_programme); glUniformMatrix4fv (view_mat_location, 1, GL_FALSE, view_mat.m); glUniformMatrix4fv (proj_mat_location, 1, GL_FALSE, proj_mat); /*------------------------------rendering loop--------------------------------*/ /* some rendering defaults */ glEnable (GL_CULL_FACE); // cull face glCullFace (GL_BACK); // cull back face glFrontFace (GL_CW); // GL_CCW for counter clock-wise while (!glfwWindowShouldClose (g_window)) { static double previous_seconds = glfwGetTime (); double current_seconds = glfwGetTime (); double elapsed_seconds = current_seconds - previous_seconds; previous_seconds = current_seconds; _update_fps_counter (g_window); // wipe the drawing surface clear glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport (0, 0, g_gl_width, g_gl_height); glUseProgram (shader_programme); glBindVertexArray (vao); // draw points 0-3 from the currently bound VAO with current in-use shader glDrawArrays (GL_TRIANGLES, 0, 3); // update other events like input handling glfwPollEvents (); /*-----------------------------move camera here-------------------------------*/ // control keys bool cam_moved = false; if (glfwGetKey (g_window, GLFW_KEY_A)) { cam_pos[0] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_D)) { cam_pos[0] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_PAGE_UP)) { cam_pos[1] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_PAGE_DOWN)) { cam_pos[1] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_W)) { cam_pos[2] -= cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_S)) { cam_pos[2] += cam_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_LEFT)) { cam_yaw += cam_yaw_speed * elapsed_seconds; cam_moved = true; } if (glfwGetKey (g_window, GLFW_KEY_RIGHT)) { cam_yaw -= cam_yaw_speed * elapsed_seconds; cam_moved = true; } /* update view matrix */ if (cam_moved) { mat4 T = translate (identity_mat4 (), vec3 (-cam_pos[0], -cam_pos[1], -cam_pos[2])); // cam translation mat4 R = rotate_y_deg (identity_mat4 (), -cam_yaw); // mat4 view_mat = R * T; glUniformMatrix4fv (view_mat_location, 1, GL_FALSE, view_mat.m); } if (GLFW_PRESS == glfwGetKey (g_window, GLFW_KEY_ESCAPE)) { glfwSetWindowShouldClose (g_window, 1); } // put the stuff we've been drawing onto the display glfwSwapBuffers (g_window); } // close GL context and any other GLFW resources glfwTerminate(); return 0; }