diff --git a/shaders/vert.glsl b/shaders/vert.glsl index 8ce7bc9..75a8ae9 100644 --- a/shaders/vert.glsl +++ b/shaders/vert.glsl @@ -4,11 +4,12 @@ layout(location=0) in vec3 position; layout(location=1) in vec3 vert_colour; uniform mat4 u_model; +uniform mat4 u_view; uniform mat4 u_projection; out vec3 vert_colours; void main() { vert_colours = vert_colour; - gl_Position = u_projection * u_model * vec4(position, 1.0f); + gl_Position = u_projection * u_view * u_model * vec4(position, 1.0f); }; diff --git a/src/main.cc b/src/main.cc index 3dd030e..484ab16 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,15 +1,25 @@ +// GLAD #include "glad/glad.h" + +// GLM +#define GLM_ENABLE_EXPERIMENTAL #include "glm/ext/matrix_transform.hpp" +#include "glm/ext/vector_float3.hpp" #include "glm/gtc/type_ptr.hpp" #include "glm/trigonometric.hpp" +#include "glm/gtx/rotate_vector.hpp" +#include "glm/gtx/string_cast.hpp" + +// SDL #include +#include #include #include #include +#include #include -#include -#include -#include + +// STDLIB #include #include #include @@ -26,6 +36,12 @@ enum exit_codes : int { EXIT_CODE_GLAD_LOADER_FAILED, }; +struct Camera { + glm::vec3 position; + glm::vec3 view_direction; + glm::vec3 up_vector; +}; + struct App { SDL_Window *window; SDL_GLContext context; @@ -49,6 +65,8 @@ struct App { GLuint shader_program; + Camera camera; + float speed; glm::mat4 translation; glm::mat4 rotation; @@ -57,7 +75,10 @@ struct App { // Model matrix to be sent as uniform to the vertex shader glm::mat4 model_mat; GLint u_model_idx; - bool recalc_model_mat; + + // 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; @@ -74,6 +95,8 @@ void cleanup (App &app); 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); +void handle_object_movement (App &app); +void handle_camera_movement (App &app); int main() { App app = {}; @@ -109,6 +132,8 @@ int init(App &app) { return EXIT_CODE_WINDOW_CREATION_FAILED; } + SDL_SetRelativeMouseMode(SDL_TRUE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); @@ -134,16 +159,20 @@ int init(App &app) { glGetString(GL_SHADING_LANGUAGE_VERSION) ); - app.speed = 0.02f; - app.translation = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -1.5f)); - app.rotation = glm::mat4(1.0f); - app.scale = glm::mat4(1.0f); - app.model_mat = app.translation * app.rotation * app.scale; - app.projection_mat = glm::perspective(glm::radians(60.0f), - (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, - 0.1f, - 20.0f - ); + app.speed = 0.02f; + app.translation = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -1.5f)); + app.rotation = glm::mat4(1.0f); + app.scale = glm::mat4(1.0f); + app.camera.position = glm::vec3(0.0f); + app.camera.view_direction = glm::vec3(0.0f, 0.0f, -1.0f); + app.camera.up_vector = glm::vec3(0.0f, 1.0f, 0.0f); + app.model_mat = app.translation * app.rotation * app.scale; + app.view_mat = glm::lookAt(app.camera.position, app.camera.view_direction, app.camera.up_vector); + app.projection_mat = glm::perspective(glm::radians(60.0f), + (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, + 0.1f, + 20.0f + ); return EXIT_CODE_SUCCESS; } @@ -230,6 +259,12 @@ void create_graphics_pipeline(App &app) { printf("Failed to find uniform %s\n", u_model); } + const char *u_view = "u_view"; + app.u_view_idx = glGetUniformLocation(app.shader_program, u_view); + if (app.u_view_idx < 0) { + printf("Failed to find uniform %s\n", u_view); + } + const char *u_projection = "u_projection"; app.u_projection_idx = glGetUniformLocation(app.shader_program, u_projection); if (app.u_projection_idx < 0) { @@ -247,37 +282,11 @@ void run_main_loop(App &app) { app.running = false; break; case SDL_KEYDOWN: - if (app.event.key.keysym.sym == SDLK_w) { - app.translation = glm::translate(app.translation, glm::vec3(0.0f, 0.0f, app.speed)); - app.recalc_model_mat = true; - } else if (app.event.key.keysym.sym == SDLK_s) { - app.translation = glm::translate(app.translation, glm::vec3(0.0f, 0.0f, -app.speed)); - app.recalc_model_mat = true; - } else if (app.event.key.keysym.sym == SDLK_d) { - app.translation = glm::translate(app.translation, glm::vec3(app.speed, 0.0f, 0.0f)); - app.recalc_model_mat = true; - } else if (app.event.key.keysym.sym == SDLK_a) { - app.translation = glm::translate(app.translation, glm::vec3(-app.speed, 0.0f, 0.0f)); - app.recalc_model_mat = true; - } else if (app.event.key.keysym.sym == SDLK_RIGHT) { - app.rotation = glm::rotate(app.rotation, glm::radians(10.0f), glm::vec3(0.0f, 1.0f, 0.0f)); - app.recalc_model_mat = true; - } else if (app.event.key.keysym.sym == SDLK_LEFT) { - app.rotation = glm::rotate(app.rotation, glm::radians(-10.0f), glm::vec3(0.0f, 1.0f, 0.0f)); - app.recalc_model_mat = true; - } else if (app.event.key.keysym.sym == SDLK_r) { - app.scale = glm::scale(app.scale, glm::vec3(1.2f)); - app.recalc_model_mat = true; - } else if (app.event.key.keysym.sym == SDLK_e) { - app.scale = glm::scale(app.scale, glm::vec3(0.8f)); - app.recalc_model_mat = true; - } - - if (app.recalc_model_mat) { - app.recalc_model_mat = false; - app.model_mat = app.translation * app.rotation * app.scale; - } - + // handle_object_movement(app); + handle_camera_movement(app); + break; + case SDL_MOUSEMOTION: + handle_camera_movement(app); break; } } @@ -288,12 +297,15 @@ void run_main_loop(App &app) { glViewport (0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); glClearColor(0.36f, 0.34f, 0.42f, 1.0f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glUseProgram(app.shader_program); if (app.u_model_idx >= 0) { glUniformMatrix4fv(app.u_model_idx, 1, GL_FALSE, glm::value_ptr(app.model_mat)); } + if (app.u_view_idx >= 0) { + glUniformMatrix4fv(app.u_view_idx, 1, GL_FALSE, glm::value_ptr(app.view_mat)); + } if (app.u_projection_idx >= 0) { glUniformMatrix4fv(app.u_projection_idx, 1, GL_FALSE, glm::value_ptr(app.projection_mat)); } @@ -301,7 +313,7 @@ void run_main_loop(App &app) { // Draw call glBindVertexArray(app.vao); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *)0); + glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *)0); // End draw call // Not necessary if we only have one shader program @@ -383,3 +395,63 @@ std::string load_shader(const std::string &filepath) { return output; } + +void handle_object_movement(App &app) { + switch (app.event.key.keysym.sym) { + case SDLK_w: + app.translation = glm::translate(app.translation, glm::vec3(0.0f, 0.0f, app.speed)); + break; + case SDLK_s: + app.translation = glm::translate(app.translation, glm::vec3(0.0f, 0.0f, -app.speed)); + break; + case SDLK_d: + app.translation = glm::translate(app.translation, glm::vec3(app.speed, 0.0f, 0.0f)); + break; + case SDLK_a: + app.translation = glm::translate(app.translation, glm::vec3(-app.speed, 0.0f, 0.0f)); + break; + case SDLK_RIGHT: + app.rotation = glm::rotate(app.rotation, glm::radians(10.0f), glm::vec3(0.0f, 1.0f, 0.0f)); + break; + case SDLK_LEFT: + app.rotation = glm::rotate(app.rotation, glm::radians(-10.0f), glm::vec3(0.0f, 1.0f, 0.0f)); + break; + case SDLK_r: + app.scale = glm::scale(app.scale, glm::vec3(1.2f)); + break; + case SDLK_e: + app.scale = glm::scale(app.scale, glm::vec3(0.8f)); + break; + default: + return; + } + + app.model_mat = app.translation * app.rotation * app.scale; +} + +void handle_camera_movement(App &app) { + if (app.event.type == SDL_MOUSEMOTION) { + app.camera.view_direction = glm::rotate(app.camera.view_direction, + glm::radians((float)app.event.motion.xrel * -0.5f), + app.camera.up_vector); + } else { + switch (app.event.key.keysym.sym) { + case SDLK_w: + app.camera.position += app.camera.view_direction * app.speed; + break; + case SDLK_s: + app.camera.position -= app.camera.view_direction * app.speed; + break; + case SDLK_d: + app.camera.position.x += app.speed; + break; + case SDLK_a: + app.camera.position.x -= app.speed; + break; + default: + return; + } + } + + app.view_mat = glm::lookAt(app.camera.position, app.camera.view_direction, app.camera.up_vector); +}