// // opengl_renderer.cxx // graphics // // Created by Sam Jaffe on 5/20/19. // Copyright © 2019 Sam Jaffe. All rights reserved. // #include "opengl_renderer.h" #ifdef __APPLE__ #include #endif #include "game/graphics/manager.hpp" #include "game/graphics/material.hpp" #include "game/graphics/vertex.h" #include "game/util/env.hpp" #include "game/util/time.hpp" #include "matrix.hpp" #include "matrix/matrix.hpp" #include "matrix/matrix_helpers.hpp" using namespace graphics; opengl_renderer::opengl_renderer() : mgr(new opengl_manager), active_material(0) { glGenVertexArrays(1, &vertex_array_object); glBindVertexArray(vertex_array_object); glGenBuffers(1, &vertex_buffer_object); glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object); } opengl_renderer::~opengl_renderer() { glDeleteBuffers(1, &vertex_buffer_object); glDeleteVertexArrays(1, &vertex_array_object); } void opengl_renderer::clear() { world_to_clip = identity; math::vec2i resolution = env::screen_size(); world_to_clip = graphics::orthogonal_view(0.f, resolution[0], 0.f, resolution[1], -1.f, 1.f); glClearDepth(1.f); glClearColor(0.f, 0.f, 0.0f, 1.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); current_time = env::clock::current_time(); // TODO (sjaffe): I labeled this as needed before, but I don't know why // I think it has to do with the resolution being 2x the screen size // static auto const rescale = make_vector(0.5f, 0.5f, 1.f); // world_to_clip = world_to_clip * math::matrix::scalar(rescale); } void opengl_renderer::flush() { glFlush(); } void opengl_renderer::draw(::identity material_id, math::matr4 const & object_to_world, std::vector const & vertices) { material const & mat = manager()->get(material_id); activate(mat); // TODO: Attatch shader-id to material-id unsigned int const id = mat.program.id; int objectLocation = glGetUniformLocation(id, "u_objectToWorldMatrix"); // Argument 2: GL_TRUE -> row-major ; GL_FALSE -> column-major glUniformMatrix4fv(objectLocation, 1, GL_TRUE, &object_to_world(0, 0)); int clipLocation = glGetUniformLocation(id, "u_worldToClipMatrix"); glUniformMatrix4fv(clipLocation, 1, GL_TRUE, &world_to_clip(0, 0)); int timeLocation = glGetUniformLocation(id, "u_time"); glUniform1d(timeLocation, current_time); // TODO: Cache attribute locations int positionLocation = glGetAttribLocation(id, "a_position"); int colorLocation = glGetAttribLocation(id, "a_color"); int texCoordsLocation = glGetAttribLocation(id, "a_texCoords"); glEnableVertexAttribArray(positionLocation); glEnableVertexAttribArray(colorLocation); glEnableVertexAttribArray(texCoordsLocation); glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), &vertices[0].position); glVertexAttribPointer(colorLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(vertex), &vertices[0].color); glVertexAttribPointer(texCoordsLocation, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), &vertices[0].texture_coords); glDrawArrays(GL_TRIANGLES, 0, static_cast(vertices.size())); glDisableVertexAttribArray(positionLocation); glDisableVertexAttribArray(colorLocation); glDisableVertexAttribArray(texCoordsLocation); } void opengl_renderer::activate(material const & mat) { if (mat.id == active_material) return; glUseProgram(mat.program.id); for (unsigned int i = 0; i < mat.uniforms.size(); i++) { const uniform & uniform = mat.uniforms[i]; glActiveTexture(i + GL_TEXTURE0); // glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, uniform.texture.id); glUniform1i(uniform.uniform_id, i); } glActiveTexture(GL_TEXTURE0); } template <> renderer_impl * graphics::get_renderer_impl() { static opengl_renderer impl; return &impl; }