diff --git a/shaders/alt.frag b/shaders/alt.frag new file mode 100644 index 0000000..1c54beb --- /dev/null +++ b/shaders/alt.frag @@ -0,0 +1,12 @@ +#version 460 core + +layout (location = 0) in vec4 tex_color; +layout (location = 1) in vec2 tex_coord; + +out vec4 frag_color; + +uniform sampler2D tex; + +void main() { + frag_color = texture(tex, tex_coord) * (vec4(1.0) - tex_color); +} diff --git a/shaders/alt.vert b/shaders/alt.vert new file mode 100644 index 0000000..b83bde3 --- /dev/null +++ b/shaders/alt.vert @@ -0,0 +1,21 @@ +#version 460 core + +layout (location = 0) in vec3 a_pos; +layout (location = 1) in vec3 a_color; +layout (location = 2) in vec2 a_tex_coord; + +layout (std140, binding = 0) uniform Matrices { + mat4 view; + mat4 projection; +}; + +layout (location = 0) out vec4 tex_color; +layout (location = 1) out vec2 tex_coord; + +void main() { + vec3 offset = vec3(0.0, 0.0, -1.0); + gl_Position = projection * view * vec4(a_pos + offset, 1.0); + tex_color = vec4(a_color, 1.0); + tex_coord = a_tex_coord; +} + diff --git a/shaders/basic.vert b/shaders/basic.vert index 92d1795..bdc6752 100644 --- a/shaders/basic.vert +++ b/shaders/basic.vert @@ -4,11 +4,16 @@ layout (location = 0) in vec3 a_pos; layout (location = 1) in vec3 a_color; layout (location = 2) in vec2 a_tex_coord; +layout (std140, binding = 0) uniform Matrices { + mat4 view; + mat4 projection; +}; + layout (location = 0) out vec4 tex_color; layout (location = 1) out vec2 tex_coord; void main() { - gl_Position = vec4(a_pos, 1.0); + gl_Position = projection * view * vec4(a_pos, 1.0); tex_color = vec4(a_color, 1.0); tex_coord = a_tex_coord; } diff --git a/src/renderer.cpp b/src/renderer.cpp index 1e861c7..325ddc4 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -3,6 +3,10 @@ bool init_renderer(Renderer *renderer, u32 width, u32 height) { + renderer->m_width = width; + renderer->m_height = height; + + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { log(1, "%s error: failed to initialize GLAD\n", __FUNCTION__); return false; @@ -40,12 +44,29 @@ bool init_renderer(Renderer *renderer, u32 width, u32 height) { } { - bool success = load_shaders(&renderer->shader, "shaders/basic.vert", "shaders/basic.frag"); + bool success = init_uniform_buffer(&renderer->uniform_buffer); if (!success) { - log(1, "%s: shader loading failed\n", __FUNCTION__); + log(1, "%s: uniform buffer successfully created\n", __FUNCTION__); return false; } - log(1, "%s: shaders succesfully loaded\n", __FUNCTION__); + } + + { + bool success = load_shaders(&renderer->shader, "shaders/basic.vert", "shaders/basic.frag"); + if (!success) { + log(1, "%s: basic shader loading failed\n", __FUNCTION__); + return false; + } + log(1, "%s: basic shaders succesfully loaded\n", __FUNCTION__); + } + + { + bool success = load_shaders(&renderer->alt_shader, "shaders/alt.vert", "shaders/alt.frag"); + if (!success) { + log(1, "%s: alt shader loading failed\n", __FUNCTION__); + return false; + } + log(1, "%s: alt shaders succesfully loaded\n", __FUNCTION__); } return true; @@ -66,13 +87,30 @@ void draw_renderer(Renderer *renderer) { glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); - use_shader(&renderer->shader); + Vector3 camera_position = Vector3(0.4f, 0.3f, 1.0f); + Vector3 camera_look_at_position = Vector3(0.0f, 0.0f, 0.0f); + Vector3 camera_up_vector = Vector3(0.0f, 1.0f, 0.0f); + + renderer->projection_matrix = glm::perspective(glm::radians(90.0f), static_cast(renderer->m_width) / static_cast(renderer->m_height), 0.1f, 100.0f); + + f32 dt = glfwGetTime(); + Matrix4 model = Matrix4(1.0); + + if (!renderer->use_alt_shader) { + use_shader(&renderer->shader); + model = glm::rotate(Matrix4(1.0f), dt, Vector3(0.0f, 0.0f, 1.0f)); + } else { + use_shader(&renderer->alt_shader); + model = glm::rotate(Matrix4(1.0f), -dt, Vector3(0.0f, 0.0f, 1.0f)); + } + + renderer->view_matrix = glm::lookAt(camera_position, camera_look_at_position, camera_up_vector) * model; + + upload_uniform_buffer_data(&renderer->uniform_buffer, renderer->view_matrix, renderer->projection_matrix); bind_texture(&renderer->texture); - bind_vertex_buffer(&renderer->vertex_buffer); - draw_vertex_buffer(GL_TRIANGLES, 0, renderer->triangle_count * 3); unbind_vertex_buffer(); @@ -89,6 +127,7 @@ void upload_renderer_data(Renderer *renderer, Mesh *vertex_data) { void cleanup_renderer(Renderer *renderer) { cleanup_shader(&renderer->shader); + cleanup_shader(&renderer->alt_shader); cleanup_texture(&renderer->texture); cleanup_vertex_buffer(&renderer->vertex_buffer); cleanup_frame_buffer(&renderer->frame_buffer); @@ -231,6 +270,30 @@ void draw_vertex_buffer(u32 mode, u32 start, u32 num) { glDrawArrays(mode, start, num); } +/* + * Uniform buffer + */ +bool init_uniform_buffer(Uniform_Buffer *uniform_buffer) { + glGenBuffers(1, &uniform_buffer->ubo_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, uniform_buffer->ubo_buffer); + glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(Matrix4), nullptr, GL_STATIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + return true; +} + +void upload_uniform_buffer_data(Uniform_Buffer *uniform_buffer, Matrix4 view_matrix, Matrix4 projection_matrix) { + glBindBuffer(GL_UNIFORM_BUFFER, uniform_buffer->ubo_buffer); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Matrix4), glm::value_ptr(view_matrix)); + glBufferSubData(GL_UNIFORM_BUFFER, sizeof(Matrix4), sizeof(Matrix4), glm::value_ptr(projection_matrix)); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, uniform_buffer->ubo_buffer, 0, 2 * sizeof(Matrix4)); + glBindBuffer(GL_UNIFORM_BUFFER, 0); +} + +void cleanup(Uniform_Buffer *uniform_buffer) { + glDeleteBuffers(1, &uniform_buffer->ubo_buffer); +} + /* * Texture @@ -304,6 +367,9 @@ bool load_shaders(Shader *shader, string vertex_shader_filepath, string fragment return false; } + s32 ubo_index = glGetUniformBlockIndex(shader->program, "Matrices"); + glUniformBlockBinding(shader->program, ubo_index, 0); + glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); diff --git a/src/renderer.h b/src/renderer.h index 4669a6c..ace460c 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -7,6 +7,7 @@ #include #include #include +#include struct Vertex { @@ -32,6 +33,10 @@ struct Vertex_Buffer { u32 vbo = 0; }; +struct Uniform_Buffer { + u32 ubo_buffer = 0; +}; + struct Texture { u32 texture = 0; s32 width = 0; @@ -44,14 +49,20 @@ struct Shader { u32 program = 0; }; - struct Renderer { Shader shader; + Shader alt_shader; Frame_Buffer frame_buffer; Vertex_Buffer vertex_buffer; + Uniform_Buffer uniform_buffer; Texture texture; Mesh mesh; s32 triangle_count = 0; + bool use_alt_shader = false; + Matrix4 view_matrix = Matrix4(1.0f); + Matrix4 projection_matrix = Matrix4(1.0f); + u32 m_width = 0; + u32 m_height = 0; }; @@ -76,6 +87,10 @@ void bind_vertex_buffer(Vertex_Buffer *vertex_buffer); void unbind_vertex_buffer(); void draw_vertex_buffer(u32 mode, u32 start, u32 num); +bool init_uniform_buffer(Uniform_Buffer *uniform_buffer); +void upload_uniform_buffer_data(Uniform_Buffer *uniform_buffer, Matrix4 view_matrix, Matrix4 projection_matrix); +void cleanup(Uniform_Buffer *uniform_buffer); + bool load_texture(Texture *texture, string filepath); void bind_texture(Texture *texture); void unbind_texture(); diff --git a/src/window.cpp b/src/window.cpp index a7b5455..7ca6d84 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -82,25 +82,9 @@ void handle_close(GLFWwindow *gl_window) { void handle_key_events(GLFWwindow *gl_window, s32 key, s32 scancode, s32 action, s32 mods) { Window *window = static_cast(glfwGetWindowUserPointer(gl_window)); - string action_name; - - switch(action) { - case GLFW_PRESS: - action_name = "pressed"; - break; - case GLFW_RELEASE: - action_name = "released"; - break; - case GLFW_REPEAT: - action_name = "repeated"; - break; - default: - action_name = "invalid"; - break; + if (glfwGetKey(window->glfw_window, GLFW_KEY_SPACE) == GLFW_PRESS) { + window->renderer->use_alt_shader = !window->renderer->use_alt_shader; } - - const char *key_name = glfwGetKeyName(key, 0); - log(1, "%s: key %s (key %i, scancode %i) %s\n", __FUNCTION__, key_name, key, scancode, action_name.c_str()); } void handle_mouse_position_events(GLFWwindow *gl_window, f64 x_pos, f64 y_pos) {