diff --git a/04-map/.imgs/showcase.png b/04-map/.imgs/showcase.png
index bbb63ef..4a68f3f 100644
Binary files a/04-map/.imgs/showcase.png and b/04-map/.imgs/showcase.png differ
diff --git a/04-map/README.md b/04-map/README.md
index fae3826..82c95d3 100644
--- a/04-map/README.md
+++ b/04-map/README.md
@@ -1,6 +1,6 @@
-
-
-
+
+
+
# Map
diff --git a/05-opengl/Makefile b/05-opengl/Makefile
new file mode 100644
index 0000000..a7faf5c
--- /dev/null
+++ b/05-opengl/Makefile
@@ -0,0 +1,29 @@
+CC=g++
+CFLAGS=`pkg-config --cflags glfw3 glew`
+LDFLAGS=`pkg-config --libs glfw3 glew`
+INCLUDE=/usr/include/stb/
+TARGET=opengl
+SDIR=src
+ADIR=assets
+ODIR=build
+
+SRC=$(shell find $(SDIR) -type f -name *.cpp)
+OBJ=$(SRC:.cpp=.o)
+
+all: $(TARGET)
+
+.PHONY: default
+$(TARGET): $(OBJ)
+ mkdir -p build
+ cp -rf $(ADIR) $(ODIR)/$(ADIR)
+ $(CC) -o $(ODIR)/$@ $^ $(LDFLAGS)
+
+%.o: %.cpp
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+run:
+ $(ODIR)/$(TARGET)
+
+.PHONY: clean
+clean:
+ rm -f $(ODIR)/$(TARGET) $(OBJ)
diff --git a/05-opengl/README.md b/05-opengl/README.md
new file mode 100644
index 0000000..7e71fd8
--- /dev/null
+++ b/05-opengl/README.md
@@ -0,0 +1,3 @@
+# Opengl
+
+Playing with Opengl because I realized SDL2 is not enough :/
diff --git a/05-opengl/assets/linux.png b/05-opengl/assets/linux.png
new file mode 100644
index 0000000..29ab51d
Binary files /dev/null and b/05-opengl/assets/linux.png differ
diff --git a/05-opengl/assets/shaders/shader.frag b/05-opengl/assets/shaders/shader.frag
new file mode 100644
index 0000000..51a6aac
--- /dev/null
+++ b/05-opengl/assets/shaders/shader.frag
@@ -0,0 +1,12 @@
+#version 330 core
+out vec4 color;
+in vec2 tex_coord;
+
+uniform sampler2D texture1;
+
+void main() {
+ color = texture(texture1, tex_coord);
+
+ if (color.a < 0.1)
+ discard;
+}
diff --git a/05-opengl/assets/shaders/shader.vert b/05-opengl/assets/shaders/shader.vert
new file mode 100644
index 0000000..07744c4
--- /dev/null
+++ b/05-opengl/assets/shaders/shader.vert
@@ -0,0 +1,11 @@
+#version 330 core
+
+layout (location = 0) in vec3 pos;
+layout (location = 1) in vec2 texture_coord;
+
+out vec2 tex_coord;
+
+void main() {
+ gl_Position = vec4(pos.xyz, 1.0);
+ tex_coord = texture_coord;
+}
diff --git a/05-opengl/assets/wall.jpg b/05-opengl/assets/wall.jpg
new file mode 100644
index 0000000..4963198
Binary files /dev/null and b/05-opengl/assets/wall.jpg differ
diff --git a/05-opengl/src/game.cpp b/05-opengl/src/game.cpp
new file mode 100644
index 0000000..78495a6
--- /dev/null
+++ b/05-opengl/src/game.cpp
@@ -0,0 +1,164 @@
+#include
+#include
+#include
+#include
+#include "game.hpp"
+#include "texture.hpp"
+#include "object.hpp"
+#include "other/stb_image.h"
+
+Game::Game(GLFWwindow *window) {
+ this->window = window;
+ this->program = glCreateProgram();
+}
+
+void Game::setup() {
+}
+
+void Game::run(int initial_width, int initial_height) {
+ glfwSetKeyCallback(this->window, Game::input_callback);
+ glfwSetFramebufferSizeCallback(this->window, Game::resize_callback);
+
+ Game::resize_callback(this->window, initial_width, initial_height);
+
+ this->vshader = Game::load_shader("assets/shaders/shader.vert", GL_VERTEX_SHADER);
+ if (!this->vshader)
+ return;
+
+ this->fshader = Game::load_shader("assets/shaders/shader.frag", GL_FRAGMENT_SHADER);
+ if (!this->fshader)
+ return;
+
+ if (Game::link_program())
+ return;
+
+ stbi_set_flip_vertically_on_load(true);
+
+ int width;
+ int height;
+ int channels;
+ unsigned char *image_bytes = stbi_load("assets/wall.jpg", &width, &height, &channels, 0);
+ if (image_bytes == NULL) {
+ std::cout << "Error: failed loading image data" << std::endl;
+ return;
+ }
+
+ Texture new_texture;
+ new_texture.bind_texture();
+ new_texture.load_data(image_bytes, width, height);
+
+ stbi_image_free(image_bytes);
+
+ Object new_object(this, new_texture);
+
+ new_object.vertices = {
+ 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+ -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f
+ };
+
+ new_object.indices = {
+ 0, 1, 3,
+ 1, 2, 3
+ };
+
+ new_object.bake();
+ this->objects.push_back(&new_object);
+
+ Game::logic();
+}
+
+void Game::input_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+ if (action != GLFW_PRESS)
+ return;
+
+ switch (key) {
+ case GLFW_KEY_ESCAPE:
+ glfwSetWindowShouldClose(window, true);
+ break;
+ default:
+ break;
+ }
+}
+
+void Game::resize_callback(GLFWwindow *window, int new_width, int new_height) {
+ glViewport(0, 0, new_width, new_height);
+}
+
+void Game::logic() {
+ while (!glfwWindowShouldClose(this->window)) {
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ for (int i = 0; i < this->objects.size(); i++)
+ (*this->objects[i]).draw();
+
+ glfwPollEvents();
+ glfwSwapBuffers(this->window);
+ }
+
+ glBindVertexArray(0);
+}
+
+unsigned int Game::load_shader(const char *path, unsigned int type) {
+ std::string source = Game::read_file(path);
+ const char *bytes = source.c_str();
+
+ unsigned int new_shader = glCreateShader(type);
+ if (!new_shader)
+ return 0;
+
+ glShaderSource(new_shader, 1, &bytes, NULL);
+ glCompileShader(new_shader);
+
+ int success;
+ char info_log[512];
+ glGetShaderiv(new_shader, GL_COMPILE_STATUS, &success);
+
+ if (!success) {
+ glGetShaderInfoLog(new_shader, 512, NULL, info_log);
+ std::cout << "Error: failed compiling new shader " << info_log << std::endl;
+ return 0;
+ }
+
+ return new_shader;
+}
+
+int Game::link_program() {
+ glAttachShader(this->program, this->vshader);
+ glAttachShader(this->program, this->fshader);
+ glLinkProgram(this->program);
+
+ int success;
+ char info_log[512];
+ glGetProgramiv(this->program, GL_LINK_STATUS, &success);
+
+ if (!success) {
+ glGetProgramInfoLog(this->program, 512, NULL, info_log);
+ std::cout << "Error: failed linking program " << info_log << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+std::string Game::read_file(const char *path) {
+ std::string content;
+ std::ifstream fs(path, std::ios::in);
+
+ if(!fs.is_open()) {
+ std::cerr << "Error: Could not read file " << path << ". File does not exist." << std::endl;
+ return NULL;
+ }
+
+ std::string line = "";
+ while(!fs.eof()) {
+ std::getline(fs, line);
+ content.append(line + "\n");
+ }
+
+ fs.close();
+ return content;
+}
+
diff --git a/05-opengl/src/game.hpp b/05-opengl/src/game.hpp
new file mode 100644
index 0000000..689bb15
--- /dev/null
+++ b/05-opengl/src/game.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include
+#include
+#include
+#include "object.hpp"
+
+class Game {
+public:
+ Game(GLFWwindow *window);
+ static std::string read_file(const char *path);
+ unsigned int load_shader(const char *path, unsigned int type);
+ int link_program();
+ void setup();
+ void run(int initial_width, int initial_height);
+ void logic();
+
+ // callbacks
+ static void input_callback(GLFWwindow *window, int key, int scancode, int action, int mods);
+ static void resize_callback(GLFWwindow *window, int new_width, int new_height);
+
+ GLFWwindow *window;
+
+ std::vector