bool create_shader (const char* file_name, GLuint* shader, GLenum type) { gl_log ("creating shader from %s...\n", file_name); char shader_string[MAX_SHADER_LENGTH]; parse_file_into_str (file_name, shader_string, MAX_SHADER_LENGTH); *shader = glCreateShader (type); const GLchar* p = (const GLchar*)shader_string; glShaderSource (*shader, 1, &p, NULL); glCompileShader (*shader); // check for compile errors int params = -1; glGetShaderiv (*shader, GL_COMPILE_STATUS, ¶ms); if (GL_TRUE != params) { gl_log_err ("ERROR: GL shader index %i did not compile\n", *shader); print_shader_info_log (*shader); return false; // or exit or something } gl_log ("shader compiled. index %i\n", *shader); return true; }
void glfw_error_callback (int error, const char* description) { fputs (description, stderr); gl_log_err ("%s\n", description); }
int main () { restart_gl_log (); // use GLFW and GLEW to start GL context. see gl_utils.cpp for details start_gl (); /* create buffer of particle initial attributes and a VAO */ GLuint vao = gen_particles (); GLuint shader_programme = create_programme_from_files ( "test_vs.glsl", "test_fs.glsl"); #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 }; 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; /* make up a world position for the emitter */ vec3 emitter_world_pos (0.0f, 0.0f, 0.0f); // locations of view and projection matrices int V_loc = glGetUniformLocation (shader_programme, "V"); assert (V_loc > -1); int P_loc = glGetUniformLocation (shader_programme, "P"); assert (P_loc > -1); int emitter_pos_wor_loc = glGetUniformLocation (shader_programme, "emitter_pos_wor"); assert (emitter_pos_wor_loc > -1); int elapsed_system_time_loc = glGetUniformLocation (shader_programme, "elapsed_system_time"); assert (elapsed_system_time_loc > -1); glUseProgram (shader_programme); glUniformMatrix4fv (V_loc, 1, GL_FALSE, view_mat.m); glUniformMatrix4fv (P_loc, 1, GL_FALSE, proj_mat); glUniform3f (emitter_pos_wor_loc, emitter_world_pos.v[0], emitter_world_pos.v[1], emitter_world_pos.v[2]); // load texture GLuint tex; if (!load_texture ("Droplet.png", &tex)) { gl_log_err ("ERROR: loading Droplet.png texture\n"); return 1; } glEnable (GL_CULL_FACE); // cull face glCullFace (GL_BACK); // cull back face glFrontFace (GL_CCW); // GL_CCW for counter clock-wise glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer" glEnable (GL_DEPTH_TEST); // enable depth-testing glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor (0.2, 0.2, 0.2, 1.0); /* MUST use this is in compatibility profile. doesn't exist in core glEnable(GL_POINT_SPRITE); */ 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); /* Render Particles. Enabling point re-sizing in vertex shader */ glEnable (GL_PROGRAM_POINT_SIZE); glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT); glEnable (GL_BLEND); glDepthMask (GL_FALSE); glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_2D, tex); glUseProgram (shader_programme); /* update time in shaders */ glUniform1f (elapsed_system_time_loc, (GLfloat)current_seconds); glBindVertexArray (vao); // draw points 0-3 from the currently bound VAO with current in-use shader glDrawArrays (GL_POINTS, 0, PARTICLE_COUNT); glDisable (GL_BLEND); glDepthMask (GL_TRUE); glDisable (GL_PROGRAM_POINT_SIZE); // update other events like input handling glfwPollEvents (); // 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 (V_loc, 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; }
/* we will tell GLFW to run this function whenever it finds an error */ void glfw_error_callback (int error, const char* description) { gl_log_err ("GLFW ERROR: code %i msg: %s\n", error, description); }