diff --git a/src/main.cc b/src/main.cc index a55dbff..faaf0b8 100644 --- a/src/main.cc +++ b/src/main.cc @@ -55,11 +55,9 @@ struct Camera { // View matrix to be sent as uniform to the vertex shader glm::mat4 view_mat; - GLint u_view_idx; // Projection matrix to be sent as uniform to the vertex shader glm::mat4 projection_mat; - GLint u_projection_idx; }; struct Transform { @@ -72,20 +70,21 @@ struct Mesh { // VAO is an object that stores the state needed to supply the GPU with the vertex data. // Think of it as a specification or a C struct that defines the types of data stored for the // vertex array including the attributes for each vertex as well the indices buffer if it exists. - GLuint vao; + GLuint vao; // The buffer that contains all the vertex data // e.g. assume 3 vertices with position, colour and uv, the buffer would look like this // ----------------------------------------------------------------------------------- // | position1 | colour1 | uv1 | position2 | colour2 | uv2 | position3 | colour3 | uv3 | // ----------------------------------------------------------------------------------- - GLuint vbo; + GLuint vbo; // Holds the indices of the vertices that draw each triangle. Each triangle constitutes what // OpenGL refers to as element, hence the name Element Buffer Object - GLuint ebo; + GLuint ebo; - GLuint shader_program; + GLuint shader_program; + GLuint vertices_count; }; struct Model { @@ -94,14 +93,18 @@ struct Model { // Model matrix to be sent as uniform to the vertex shader glm::mat4 model_mat; + GLint u_model_idx; + GLint u_view_idx; + GLint u_projection_idx; }; struct App { SDL_Window *window; SDL_GLContext context; SDL_Event event; - Model model; + Model plane; + Model floor; Camera camera; float speed; glm::vec2 prev_mouse; @@ -109,10 +112,11 @@ struct App { }; int init (App &app); -void create_vertex_spec (Model &model); -void create_graphics_pipeline (Model &model, Camera &camera); +void create_vertex_spec (Model &model, const std::vector &vertices, const std::vector &indices); +void create_graphics_pipeline (Model &model, Camera &camera, const char *vs_file, const char *fs_file); void run_main_loop (App &app); void cleanup (App &app); +void render_model (const Model &model, const Camera &camera); GLuint create_shader_program (const std::string &vertex_shader_source, const std::string &fragment_shader_source); GLuint compile_shader (GLuint type, const std::string &source); std::string load_shader (const std::string &filepath); @@ -127,11 +131,57 @@ int main() { return result; } + const std::vector plane_vertices = { + // vert0 + -0.5f, -0.5f, 0.0f, // position + 1.0f, 0.0f, 0.0f, // colour + // vert1 + 0.5f, -0.5f, 0.0f, // position + 0.0f, 1.0f, 0.0f, // colour + // vert2 + -0.5f, 0.5f, 0.0f, // position + 0.0f, 0.0f, 1.0f, // colour + // vert3 + 0.5f, 0.5f, 0.0f, // position + 1.0f, 1.0f, 0.0f, // colour + }; + + const std::vector plane_indices = { + // first triangle + 0, 1, 2, + // second triangle + 2, 1, 3, + }; + + const std::vector floor_vertices = { + // vert0 + -10.0f, 0.0f, 10.0f, // position + 0.23529f, 0.43137f, 0.44313f, // colour + // vert1 + 10.0f, 0.0f, 10.0f, // position + 0.23529f, 0.43137f, 0.44313f, // colour + // vert2 + -10.0f, 0.0f, -10.0f, // position + 0.23529f, 0.43137f, 0.44313f, // colour + // vert3 + 10.0f, 0.0f, -10.0f, // position + 0.23529f, 0.43137f, 0.44313f, // colour + }; + + const std::vector floor_indices = { + // first triangle + 0, 1, 2, + // second triangle + 2, 1, 3, + }; + // Setup the geometry - create_vertex_spec(app.model); + create_vertex_spec(app.plane, plane_vertices, plane_indices); + create_vertex_spec(app.floor, floor_vertices, floor_indices); // Setup graphics pipeline. At the very minimum creating vertex and fragment shaders - create_graphics_pipeline(app.model, app.camera); + create_graphics_pipeline(app.plane, app.camera, "shaders/vert.glsl", "shaders/frag.glsl"); + create_graphics_pipeline(app.floor, app.camera, "shaders/vert.glsl", "shaders/frag.glsl"); run_main_loop(app); @@ -183,15 +233,20 @@ int init(App &app) { ); app.speed = 0.04f; - app.model.transform.translation = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 1.5f)); - app.model.transform.rotation = glm::mat4(1.0f); - app.model.transform.scale = glm::mat4(1.0f); - app.camera.rotation = glm::vec2(0.0f, -90.0f); - app.camera.position = glm::vec3(0.0f, 0.0f, 3.0f); + app.plane.transform.translation = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.5f, -1.0f)); + app.plane.transform.rotation = glm::mat4(1.0f); + app.plane.transform.scale = glm::mat4(1.0f); + app.plane.model_mat = app.plane.transform.translation * + app.plane.transform.rotation * app.plane.transform.scale; + app.floor.transform.translation = glm::mat4(1.0f); + app.floor.transform.rotation = glm::mat4(1.0f); + app.floor.transform.scale = glm::mat4(1.0f); + app.floor.model_mat = app.floor.transform.translation * + app.floor.transform.rotation * app.floor.transform.scale; + app.camera.rotation = glm::vec2(-5.0f, -90.0f); + app.camera.position = glm::vec3(0.0f, 0.5f, 3.0f); app.camera.view_direction = rotation_to_view_direction(app.camera); app.camera.up = glm::vec3(0.0f, 1.0f, 0.0f); - app.model.model_mat = app.model.transform.translation * - app.model.transform.rotation * app.model.transform.scale; app.camera.view_mat = glm::lookAt(app.camera.position, app.camera.position + app.camera.view_direction, app.camera.up); app.camera.projection_mat = glm::perspective(glm::radians(60.0f), (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, @@ -202,29 +257,7 @@ int init(App &app) { return EXIT_CODE_SUCCESS; } -void create_vertex_spec(Model &model) { - const std::vector vertices = { - // vert0 - -0.5f, -0.5f, 0.0f, // position - 1.0f, 0.0f, 0.0f, // colour - // vert1 - 0.5f, -0.5f, 0.0f, // position - 0.0f, 1.0f, 0.0f, // colour - // vert2 - -0.5f, 0.5f, 0.0f, // position - 0.0f, 0.0f, 1.0f, // colour - // vert3 - 0.5f, 0.5f, 0.0f, // position - 1.0f, 1.0f, 0.0f, // colour - }; - - const std::vector indices = { - // first triangle - 0, 1, 2, - // second triangle - 2, 1, 3, - }; - +void create_vertex_spec(Model &model, const std::vector &vertices, const std::vector &indices) { // Create and activate the VAO glGenVertexArrays(1, &model.mesh.vao); glBindVertexArray(model.mesh.vao); @@ -270,11 +303,13 @@ void create_vertex_spec(Model &model) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); + + model.mesh.vertices_count = indices.size(); } -void create_graphics_pipeline(Model &model, Camera &camera) { - const std::string vs_source = load_shader("shaders/vert.glsl"); - const std::string fs_source = load_shader("shaders/frag.glsl"); +void create_graphics_pipeline(Model &model, Camera &camera, const char *vs_file, const char *fs_file) { + const std::string vs_source = load_shader(vs_file); + const std::string fs_source = load_shader(fs_file); model.mesh.shader_program = create_shader_program(vs_source, fs_source); @@ -284,16 +319,15 @@ void create_graphics_pipeline(Model &model, Camera &camera) { printf("Failed to find uniform %s\n", u_model); } - // TODO (Abdelrahman): Finding the camera matrices uniforms shouldn't be handled here const char *u_view = "u_view"; - camera.u_view_idx = glGetUniformLocation(model.mesh.shader_program, u_view); - if (camera.u_view_idx < 0) { + model.u_view_idx = glGetUniformLocation(model.mesh.shader_program, u_view); + if (model.u_view_idx < 0) { printf("Failed to find uniform %s\n", u_view); } const char *u_projection = "u_projection"; - camera.u_projection_idx = glGetUniformLocation(model.mesh.shader_program, u_projection); - if (camera.u_projection_idx < 0) { + model.u_projection_idx = glGetUniformLocation(model.mesh.shader_program, u_projection); + if (model.u_projection_idx < 0) { printf("Failed to find uniform %s\n", u_projection); } } @@ -329,22 +363,9 @@ void run_main_loop(App &app) { glClearColor(0.36f, 0.34f, 0.42f, 1.0f); glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - glUseProgram(app.model.mesh.shader_program); - if (app.model.u_model_idx >= 0) { - glUniformMatrix4fv(app.model.u_model_idx, 1, GL_FALSE, glm::value_ptr(app.model.model_mat)); - } - if (app.camera.u_view_idx >= 0) { - glUniformMatrix4fv(app.camera.u_view_idx, 1, GL_FALSE, glm::value_ptr(app.camera.view_mat)); - } - if (app.camera.u_projection_idx >= 0) { - glUniformMatrix4fv(app.camera.u_projection_idx, 1, GL_FALSE, glm::value_ptr(app.camera.projection_mat)); - } - // End pre draw setup - - // Draw call - glBindVertexArray(app.model.mesh.vao); - glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *)0); - // End draw call + // Render models + render_model(app.floor, app.camera); + render_model(app.plane, app.camera); // Not necessary if we only have one shader program glUseProgram(0); @@ -359,6 +380,22 @@ void cleanup(App &app) { SDL_Quit(); } +void render_model(const Model &model, const Camera &camera) { + glUseProgram(model.mesh.shader_program); + if (model.u_model_idx >= 0) { + glUniformMatrix4fv(model.u_model_idx, 1, GL_FALSE, glm::value_ptr(model.model_mat)); + } + if (model.u_view_idx >= 0) { + glUniformMatrix4fv(model.u_view_idx, 1, GL_FALSE, glm::value_ptr(camera.view_mat)); + } + if (model.u_projection_idx >= 0) { + glUniformMatrix4fv(model.u_projection_idx, 1, GL_FALSE, glm::value_ptr(camera.projection_mat)); + } + + glBindVertexArray(model.mesh.vao); + glDrawElements (GL_TRIANGLES, model.mesh.vertices_count, GL_UNSIGNED_INT, (void *)0); +} + GLuint create_shader_program(const std::string &vertex_shader_source, const std::string &fragment_shader_source) { GLuint shader_program = glCreateProgram(); GLuint vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_source); @@ -430,40 +467,41 @@ std::string load_shader(const std::string &filepath) { void handle_object_movement(App &app) { switch (app.event.key.keysym.sym) { case SDLK_w: - app.model.transform.translation = glm::translate(app.model.transform.translation, + app.plane.transform.translation = glm::translate(app.plane.transform.translation, glm::vec3(0.0f, 0.0f, app.speed)); break; case SDLK_s: - app.model.transform.translation = glm::translate(app.model.transform.translation, + app.plane.transform.translation = glm::translate(app.plane.transform.translation, glm::vec3(0.0f, 0.0f, -app.speed)); break; case SDLK_d: - app.model.transform.translation = glm::translate(app.model.transform.translation, + app.plane.transform.translation = glm::translate(app.plane.transform.translation, glm::vec3(app.speed, 0.0f, 0.0f)); break; case SDLK_a: - app.model.transform.translation = glm::translate(app.model.transform.translation, + app.plane.transform.translation = glm::translate(app.plane.transform.translation, glm::vec3(-app.speed, 0.0f, 0.0f)); break; case SDLK_RIGHT: - app.model.transform.rotation = glm::rotate(app.model.transform.rotation, + app.plane.transform.rotation = glm::rotate(app.plane.transform.rotation, glm::radians(10.0f), glm::vec3(0.0f, 1.0f, 0.0f)); break; case SDLK_LEFT: - app.model.transform.rotation = glm::rotate(app.model.transform.rotation, + app.plane.transform.rotation = glm::rotate(app.plane.transform.rotation, glm::radians(-10.0f), glm::vec3(0.0f, 1.0f, 0.0f)); break; case SDLK_r: - app.model.transform.scale = glm::scale(app.model.transform.scale, glm::vec3(1.2f)); + app.plane.transform.scale = glm::scale(app.plane.transform.scale, glm::vec3(1.2f)); break; case SDLK_e: - app.model.transform.scale = glm::scale(app.model.transform.scale, glm::vec3(0.8f)); + app.plane.transform.scale = glm::scale(app.plane.transform.scale, glm::vec3(0.8f)); break; default: return; } - app.model.model_mat = app.model.transform.translation * app.model.transform.rotation * app.model.transform.scale; + app.plane.model_mat = app.plane.transform.translation * app.plane.transform.rotation * app.plane.transform.scale; + app.floor.model_mat = app.floor.transform.translation * app.floor.transform.rotation * app.floor.transform.scale; } void handle_camera_movement(App &app) {