diff options
| -rw-r--r-- | Makefile | 9 | ||||
| -rw-r--r-- | src/batch.cpp | 195 | ||||
| -rw-r--r-- | src/batch.hpp | 45 | ||||
| -rw-r--r-- | src/main.cpp | 198 | ||||
| -rw-r--r-- | src/shaders/default.frag | 19 | ||||
| -rw-r--r-- | src/shaders/default.vert | 21 | ||||
| -rw-r--r-- | src/texture.cpp | 28 | ||||
| -rw-r--r-- | src/texture.hpp | 5 |
8 files changed, 355 insertions, 165 deletions
@@ -3,7 +3,7 @@ EXE := game BUILD_DIR := build INC_FLAGS := -Isrc -Iglfw/build/include -Iglad/include -Istb -Iglm LINK_FLAGS := -lGL -lX11 -lpthread -lXrandr -lXi -ldl -OBJ_NAMES := glad.o input.o shader.o texture.o +OBJ_NAMES := glad.o input.o shader.o batch.o texture.o OBJ_FILES := $(addprefix $(BUILD_DIR)/, $(OBJ_NAMES)) @@ -20,10 +20,17 @@ input.o: src/input.cpp src/input.hpp shader.o: src/shader.cpp src/shader.hpp @mkdir -p $(BUILD_DIR) g++ -o $(BUILD_DIR)/shader.o -c src/shader.cpp $(INC_FLAGS) $(LINK_FLAGS) +batch.o: src/batch.cpp src/batch.hpp + @mkdir -p $(BUILD_DIR) + g++ -o $(BUILD_DIR)/batch.o -c src/batch.cpp $(INC_FLAGS) $(LINK_FLAGS) texture.o: src/texture.cpp src/texture.hpp @mkdir -p $(BUILD_DIR) g++ -o $(BUILD_DIR)/texture.o -c src/texture.cpp $(INC_FLAGS) $(LINK_FLAGS) +.PHONY: clean +clean: + rm -r $(BUILD_DIR) + .PHONY: run run: default $(BUILD_DIR)/$(EXE) diff --git a/src/batch.cpp b/src/batch.cpp new file mode 100644 index 0000000..d380e53 --- /dev/null +++ b/src/batch.cpp @@ -0,0 +1,195 @@ +#include "batch.hpp" + +#include <vector> +#include <iostream> +#include "glad/glad.h" + +#include "texture.hpp" + + +Batch::Batch(unsigned int batch_limit) +{ + this->batch_limit = batch_limit; + + glGenBuffers(1, &VBO); // generate the buffer + glGenBuffers(1, &EBO); + glGenVertexArrays(1, &VAO); // generate array + + glBindVertexArray(VAO); // bind array to apply "settings" to it + glBindBuffer(GL_ARRAY_BUFFER, VBO); // bind(activate) the buffer to the ARRAY_BUFFER + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); + + // position attribute + GLsizei stride = 10 * sizeof(float); + glVertexAttribPointer( + 0, // index + 3, // size(number of elements) + GL_FLOAT, + GL_FALSE, + stride, // stride(distance to reach next one) + (void*)0); // pointer(offset from start) + glEnableVertexAttribArray(0); + + // color attribute + glVertexAttribPointer( + 1, + 4, + GL_FLOAT, + GL_FALSE, + stride, + (void*)(3 * sizeof(float))); // configure how the vertex array looks + glEnableVertexAttribArray(1); + + //texture coordinates + glVertexAttribPointer( + 2, + 2, + GL_FLOAT, + GL_FALSE, + stride, + (void*)(7 * sizeof(float))); // configure how the vertex array looks + glEnableVertexAttribArray(2); + + //texture id + glVertexAttribPointer( + 3, + 1, + GL_FLOAT, + GL_FALSE, + stride, + (void*)(9 * sizeof(float))); // configure how the vertex array looks + glEnableVertexAttribArray(3); +} + +int Batch::drawTexture( + Texture texture, + float x, + float y, + float width, + float height, + glm::vec4 color + ) +{ + float h_height = height / 2.0; + float h_width = width / 2.0; + return this->primativeDrawQuad( + texture.id, + glm::vec3(x+h_height,y+h_width,0.0f), // top right + glm::vec3(x+h_height, y-h_width, 0.0f), // bottom right + glm::vec3(x-h_height, y-h_width, 0.0f), // bottom left + glm::vec3(x-h_height, y+h_height, 0.0f), // top left + color + ); +} + + +int Batch::drawRectangle( + float x, + float y, + float width, + float height, + glm::vec4 color + ) +{ + float h_height = height / 2.0; + float h_width = width / 2.0; + return this->primativeDrawQuad( + 0, + glm::vec3(x+h_height,y+h_width,0.0f), // top right + glm::vec3(x+h_height, y-h_width, 0.0f), // bottom right + glm::vec3(x-h_height, y-h_width, 0.0f), // bottom left + glm::vec3(x-h_height, y+h_height, 0.0f), // top left + color + ); +} + +int Batch::primativeDrawQuad( + unsigned int texture_id, + glm::vec3 a, + glm::vec3 b, + glm::vec3 c, + glm::vec3 d, + glm::vec4 color + ) +{ + // if no assigned texture, attempt to assign it + if(texture_id == 0) + last_texture = texture_id; + // if surpassing batch limit + // or if texture is different + if((size >= batch_limit) || ((last_texture != texture_id) && (texture_id != 0))) + this->flush_batch(); last_texture = texture_id; + + + float verts[] = { + // top right + a.x, a.y, a.z, // position + color.r, color.g, color.b, color.a, // colors + 1.0f, 1.0f, // tex coords + (float)texture_id, // tex id(0 means none) + + // bottom right + b.x, b.y, b.z, + color.r, color.g, color.b, color.a, + 1.0f, 0.0f, + (float)texture_id, + + // bottom left + c.x, c.y, c.z, + color.r, color.g, color.b, color.a, + 0.0f, 0.0f, + (float)texture_id, + + // top left + d.x, d.y, d.z, + color.r, color.g, color.b, color.a, + 0.0f, 1.0f, + (float)texture_id + }; + unsigned int inds[] = { + (size * 4) + 0, (size * 4) + 1, (size * 4) + 3, // first triangle + (size * 4) + 1, (size * 4) + 2, (size * 4) + 3, // second triangle + }; + vertices.reserve(sizeof(verts)); + indices.reserve(sizeof(inds)); + vertices.insert(vertices.end(), std::cbegin(verts), std::cend(verts)); + indices.insert(indices.end(), std::cbegin(inds), std::cend(inds)); + size += 1; + + return 0; +} + +void Batch::flush_batch() +{ + glBindVertexArray(VAO); + + // we already binded this in the VAO during initialization + // so no need to do it again + //glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData( // uploading vertices + GL_ARRAY_BUFFER, + vertices.size() * sizeof(float), + vertices.data(), + GL_STATIC_DRAW + ); + + // we already binded this in the VAO during initialization + // so no need to do it again + //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); + glBufferData( // uploading indices + GL_ELEMENT_ARRAY_BUFFER, + indices.size() * sizeof(unsigned int), + indices.data(), + GL_STATIC_DRAW + ); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, last_texture); + glDrawElements(GL_TRIANGLES, 6 * size, GL_UNSIGNED_INT, 0); + + glBindVertexArray(0); // unbind the VAO + + last_texture = -1; + size = 0; + vertices.clear(); + indices.clear(); +} diff --git a/src/batch.hpp b/src/batch.hpp new file mode 100644 index 0000000..444a547 --- /dev/null +++ b/src/batch.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include <vector> + +#include "glad/glad.h" +#include <glm/glm.hpp> + +#include "texture.hpp" + +class Batch +{ + public: + unsigned int VAO, VBO, EBO; + std::vector<float> vertices = {}; + std::vector<unsigned int> indices = {}; + unsigned int size, batch_limit; + unsigned int last_texture = 0; + + Batch(unsigned int batch_limit = 8192); + int drawTexture( + Texture texture, + float x, + float y, + float width, + float height, + glm::vec4 color + ); + int drawRectangle( + float x, + float y, + float width, + float height, + glm::vec4 color + ); + void flush_batch(); + private: + int primativeDrawQuad( + unsigned int texture_id, + glm::vec3 a, + glm::vec3 b, + glm::vec3 c, + glm::vec3 d, + glm::vec4 color + ); +}; diff --git a/src/main.cpp b/src/main.cpp index 2655f8c..c634ab5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,24 +3,10 @@ #include "input.hpp" #include "shader.hpp" -#include "texture.hpp" +#include "batch.hpp" #include <iostream> #include <cmath> -//#include <unistd.h> // use to print working directory -//#include <stdio.h> - -float vertices[] = { - // positions // colors // texture coords - 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top right - 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // bottom right - -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, // bottom left - -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left -}; -unsigned int indices[] = { // note that we start from 0! - 0, 1, 3, // first triangle - 1, 2, 3 // second triangle -}; void framebuffer_size_callback(GLFWwindow* window, int width, int height) { @@ -28,7 +14,6 @@ void framebuffer_size_callback(GLFWwindow* window, int width, int height) } int main() { - //printf("Current working dir: %s\n", get_current_dir_name()); glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // 4.6 is highest glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); @@ -55,90 +40,18 @@ int main() { Shader shader = Shader("src/shaders/default.vert", "src/shaders/default.frag"); - unsigned int VBO, VAO, EBO; - glGenBuffers(1, &VBO); // generate the buffer - glGenBuffers(1, &EBO); - - glGenVertexArrays(1, &VAO); // generate array - glBindVertexArray(VAO); // bind array to apply "settings" to it - - glBindBuffer(GL_ARRAY_BUFFER, VBO); // bind(activate) the buffer to the ARRAY_BUFFER - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // upload the data - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); - - // position attribute - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); // configure how the vertex array looks - glEnableVertexAttribArray(0); - // color attribute - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); // configure how the vertex array looks - glEnableVertexAttribArray(1); - //texture attribute - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); // configure how the vertex array looks - glEnableVertexAttribArray(2); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // wireframe mode - //{ - // int nrAttributes; - // glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes); - // std::cout << "Maximum nr of vertex attributes supported: " << nrAttributes << std::endl; - //} - - // Image/Texture stuffs -// unsigned int texture1, texture2; -// glGenTextures(1, &texture1); -// glBindTexture(GL_TEXTURE_2D, texture1); -// // set the texture wrapping/filtering options (on the currently bound texture object) -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -// // load and generate the texture -// { -// int width, height, nrChannels; -// unsigned char *data = stbi_load("assets/container.jpg", &width, &height, &nrChannels, 0); -// if (data) -// { -// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); -// glGenerateMipmap(GL_TEXTURE_2D); -// } -// else -// { -// std::cout << "Failed to load texture" << std::endl; -// } -// stbi_image_free(data); -// } -// glGenTextures(2, &texture2); -// glBindTexture(GL_TEXTURE_2D, texture2); -// // set the texture wrapping/filtering options (on the currently bound texture object) -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -// // load and generate the texture -// { -// int width, height, nrChannels; -// unsigned char *data = stbi_load("assets/awesomeface.png", &width, &height, &nrChannels, 0); -// if (data) -// { -// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); -// glGenerateMipmap(GL_TEXTURE_2D); -// } -// else -// { -// std::cout << "Failed to load texture" << std::endl; -// } -// stbi_image_free(data); -// } - Texture texture3 = Texture("assets/awesomeface.png", VAO, VBO); + Batch batch = Batch(); + Texture texture = Texture("assets/awesomeface.png"); shader.use(); - shader.setInt("texture1", 0); - shader.setInt("texture2", 1); float pi = 2.0f * acos(0.0f); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // game loop while(!glfwWindowShouldClose(window)) { @@ -148,36 +61,79 @@ int main() { glClear(GL_COLOR_BUFFER_BIT); - //glUseProgram(shaderProgram); // this will activate the shader and use them for all subsequent shader and render calls shader.use(); - float timeValue = glfwGetTime(); - float greenValue = 1.0f;//(sin(timeValue) / 2.0f) + 0.5f; - shader.set4f("ourColor", 1.0f - greenValue, greenValue, (greenValue / 2.0f) + 0.25f, 1.0f); - - shader.set1f("offset_x", greenValue - 0.5); - - float sin_move0 = sin((timeValue) / 2.0f) / 2.0f; - float cos_move0 = cos((timeValue) / 2.0f) / 2.0f; - float sin_move1 = sin((timeValue + (1*pi)) / 2.0f) / 2.0f; - float cos_move1 = cos((timeValue + (1*pi)) / 2.0f) / 2.0f; - float sin_move2 = sin((timeValue + (2*pi)) / 2.0f) / 2.0f; - float cos_move2 = cos((timeValue + (2*pi)) / 2.0f) / 2.0f; - float sin_move3 = sin((timeValue + (3*pi)) / 2.0f) / 2.0f; - float cos_move3 = cos((timeValue + (3*pi)) / 2.0f) / 2.0f; - //glActiveTexture(GL_TEXTURE0); - //glBindTexture(GL_TEXTURE_2D, texture1); - //glActiveTexture(GL_TEXTURE1); - //glBindTexture(GL_TEXTURE_2D, texture2); - //glBindVertexArray(VAO); // activate the preconfigured settings - //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // :) - - texture3.draw(cos_move0, sin_move0, 0.5, 0.5); - texture3.draw(cos_move1, sin_move1, 0.5, 0.5); - texture3.draw(cos_move2, sin_move2, 0.5, 0.5); - texture3.draw(cos_move3, sin_move3, 0.5, 0.5); - //drawTexture(texture1, VAO, VBO, -0.5, -0.5, 0.5, 0.5); - glBindVertexArray(0); + batch.drawRectangle( + -0.5, + -0.5, + 1.0, + 1.0, + glm::vec4(0.3,0.3,1.0,1.0) + ); + batch.drawRectangle( + 0.5, + 0.5, + 1.0, + 1.0, + glm::vec4(1.0,0.3,0.3,1.0) + ); + batch.drawRectangle( + -0.5, + 0.5, + 1.0, + 1.0, + glm::vec4(1.0,0.3,1.0,1.0) + ); + batch.drawRectangle( + 0.5, + -0.5, + 1.0, + 1.0, + glm::vec4(1.0,1.0,0.3,1.0) + ); + batch.drawTexture( + texture, + -0.5, + -0.5, + 1.0, + 1.0, + glm::vec4(1.0,1.0,1.0,0.3) + ); + batch.drawTexture( + texture, + 0.5, + 0.5, + 1.0, + 1.0, + glm::vec4(1.0,1.0,1.0,0.3) + ); + batch.drawTexture( + texture, + -0.5, + 0.5, + 1.0, + 1.0, + glm::vec4(1.0,1.0,1.0,0.3) + ); + batch.drawTexture( + texture, + 0.5, + -0.5, + 1.0, + 1.0, + glm::vec4(1.0,1.0,1.0,0.3) + ); + batch.drawTexture( + texture, + 0.0, + 0.0, + 1.0, + 1.0, + glm::vec4(1.0,1.0,1.0,0.5) + ); + + batch.flush_batch(); // does the drawing + glfwSwapBuffers(window); glfwPollEvents(); diff --git a/src/shaders/default.frag b/src/shaders/default.frag index 241369e..2ad6732 100644 --- a/src/shaders/default.frag +++ b/src/shaders/default.frag @@ -1,16 +1,21 @@ #version 330 core out vec4 FragColor; -in vec3 ourColor; -in vec2 TexCoord; +in vec4 v_Color; +in vec2 v_TexCoord; +in float v_TexId; -uniform sampler2D texture1; -//uniform sampler2D texture2; +uniform sampler2D texture_1; void main() { - vec2 texInvert = vec2(TexCoord.x, -TexCoord.y); - FragColor = texture(texture1, texInvert);// * ourColor; - //FragColor = texture(ourTexture, TexCoord) * vec4(ourColor.xyz, 1.0); + if(v_TexId > 0) + { + FragColor = texture(texture_1, v_TexCoord) * v_Color; + } + else + { + FragColor = v_Color; + } } diff --git a/src/shaders/default.vert b/src/shaders/default.vert index 5adf795..38e5343 100644 --- a/src/shaders/default.vert +++ b/src/shaders/default.vert @@ -1,16 +1,19 @@ #version 330 core -layout (location = 0) in vec3 aPos; -layout (location = 1) in vec3 aColor; -layout (location = 2) in vec2 aTexCoord; +layout (location = 0) in vec3 a_Pos; +layout (location = 1) in vec4 a_Color; +layout (location = 2) in vec2 a_TexCoord; +layout (location = 3) in float a_TexId; -uniform float offset_x; +//uniform float offset_x; -out vec3 ourColor; -out vec2 TexCoord; +out vec4 v_Color; +out vec2 v_TexCoord; +out float v_TexId; void main() { - gl_Position = vec4(aPos.x + offset_x, aPos.yz, 1.0); - ourColor = aColor; - TexCoord = aTexCoord; + gl_Position = vec4(a_Pos, 1.0); + v_Color = a_Color; + v_TexCoord = a_TexCoord; + v_TexId = a_TexId; } diff --git a/src/texture.cpp b/src/texture.cpp index 4432f4c..e9a49ce 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -5,11 +5,8 @@ #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" - -Texture::Texture(const char* texturePath, unsigned int VAO, unsigned int VBO) +Texture::Texture(const char* texture_path) { - this->VAO = VAO; - this->VBO = VBO; glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); // set the texture wrapping/filtering options (on the currently bound texture object) @@ -17,12 +14,12 @@ Texture::Texture(const char* texturePath, unsigned int VAO, unsigned int VBO) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // load and generate the texture int width, height, nrChannels; - unsigned char *data = stbi_load(texturePath, &width, &height, &nrChannels, 0); + stbi_set_flip_vertically_on_load(true); + unsigned char *data = stbi_load(texture_path, &width, &height, &nrChannels, 0); if (data) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); } else @@ -31,20 +28,3 @@ Texture::Texture(const char* texturePath, unsigned int VAO, unsigned int VBO) } stbi_image_free(data); } - -void Texture::draw(float x, float y, float width, float height) -{ - float vertices[] = { - // positions // colors // texture coords - x-width, y+height, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right - x-width, y, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right - x, y, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left - x, y+height, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left - }; - glBindBuffer(GL_ARRAY_BUFFER, VBO); // bind(activate) the buffer to the ARRAY_BUFFER - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); // upload the data - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, id); - glBindVertexArray(VAO); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); -} diff --git a/src/texture.hpp b/src/texture.hpp index 0a9c9e6..f8ceaed 100644 --- a/src/texture.hpp +++ b/src/texture.hpp @@ -4,7 +4,6 @@ class Texture { public: - unsigned int id, VAO, VBO; - Texture(const char* texturePath, unsigned int VAO, unsigned int VBO); - void draw(float x, float y, float width, float height); + unsigned int id; + Texture(const char* texture_path); }; |
