From a89e820bd8e8216e7b02219c9fa09f7f6e7161bb Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 31 Jul 2023 13:42:13 +0200 Subject: [PATCH] Refactored texture usage --- src/Engine/main.cpp | 71 +++++++++------------------------ src/Engine/textures/Texture2D.h | 44 ++++++++++++++++++-- 2 files changed, 59 insertions(+), 56 deletions(-) diff --git a/src/Engine/main.cpp b/src/Engine/main.cpp index 0380b20..3150759 100644 --- a/src/Engine/main.cpp +++ b/src/Engine/main.cpp @@ -8,13 +8,15 @@ #include #include "shaders/Shader.h" +#include "textures/Texture2D.h" #include "util/stb_image.h" // Continue: https://learnopengl.com/Getting-started/Coordinate-Systems // Chapter: More Cubes! // // TODO: look at project->properties->VC++ Directories-> change everything to the Environment var -// For the "real" Nebulix Engine setup everything so it can be compiled/used with VSCode/CLion and not just VS (so basically having an "external" folder which has open gl, GLAD, etc. in it or something like this) +// For the "real" Nebulix Engine setup everything so it can be compiled/used with VSCode/CLion and not just VS +// (so basically having an "external" folder which has open gl, GLAD, GLM, stb_image etc. in it or something like this) // // HOW TO redirect error output to file @@ -42,6 +44,12 @@ void ProcessInput(GLFWwindow* window) glfwSetWindowShouldClose(window, true); } +void Configure() +{ + stbi_set_flip_vertically_on_load(true); // because an image has 0 at top of y axis and opengl expects it to be on the botton, so if this is omitted, the image will be flipped + glEnable(GL_DEPTH_TEST); +} + int main() { glfwInit(); @@ -70,6 +78,8 @@ int main() OnWindowResize(window, WINDOW_WIDTH, WINDOW_HEIGHT); glfwSetFramebufferSizeCallback(window, OnWindowResize); + Configure(); + float vertices[] = { // object coordinates, uv-coordinates -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, @@ -116,23 +126,8 @@ int main() GLuint faces[]{ 0, 1, 3, - 1, 2, 3, - - 4, 5, 6, - 5, 6, 7, - - 8, 9, 10, - 9, 10, 11, - - 12, 13, 14, - 13, 14, 15, - - 16, 17, 18, - 17, 18, 19, - - 20, 21, 22, - 21, 22, 23 - }; // 23 + 1, 2, 3 + }; // VBO == all verticies; EBO == connection of vertices (faces) and is optional although it is a bit more efficient than using VBOs; // VAO == collection of VBOs/EBOs used for rendering @@ -152,7 +147,7 @@ int main() // position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); - // uv-coordinates (or more general the third vertex attribute) + // uv-coordinates (or more general the third vertex attribute which can be anything not just uv-coordinates) glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(2); // I could unbind the VAO, but this is usually not needed because when creating a new VAO we need to bind that to change it anyway, so there shouldn't be a problem @@ -173,35 +168,8 @@ int main() glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // TEXTURES - stbi_set_flip_vertically_on_load(true); // because an image has 0 at top of y axis and opengl expects it to be on the botton, so if this is omitted, the image will be flipped - int width, height, nrChannels; - unsigned char* image = stbi_load("images/container.jpg", &width, &height, &nrChannels, 0); - if (!image) - { - std::cerr << "ERROR::IO::LOAD_TEXTURE"; - stbi_image_free(image); - return -1; // it would be better to just use a default error image instead and make the error message a warning message instead - } - unsigned int textureID_container; - glGenTextures(1, &textureID_container); - glBindTexture(GL_TEXTURE_2D, textureID_container); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); - glGenerateMipmap(GL_TEXTURE_2D); - stbi_image_free(image); - - image = stbi_load("images/awesomeface.png", &width, &height, &nrChannels, 0); - if (!image) - { - std::cerr << "ERROR::IO::LOAD_TEXTURE"; - stbi_image_free(image); - return -1; // it would be better to just use a default error image instead and make the error message a warning message instead - } - unsigned int textureID_face; - glGenTextures(1, &textureID_face); - glBindTexture(GL_TEXTURE_2D, textureID_face); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); - glGenerateMipmap(GL_TEXTURE_2D); - stbi_image_free(image); + Texture2D containerImage("images/container.jpg"); + Texture2D faceImage("images/awesomeface.png", 0, GL_RGBA); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); @@ -214,7 +182,6 @@ int main() viewMatrix = glm::translate(viewMatrix, vec3(0, 0, -3.0f)); mat4 projectionMatrix = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f); - glEnable(GL_DEPTH_TEST); float timeLastFrame = glfwGetTime(); // main loop while(!glfwWindowShouldClose(window)) @@ -235,10 +202,8 @@ int main() shader->SetMatrix("viewMatrix", viewMatrix); shader->SetMatrix("projectionMatrix", projectionMatrix); - glActiveTexture(GL_TEXTURE0); // before binding texture, activate correct textre Unit (some drivers might show nothing if this is omitted) - glBindTexture(GL_TEXTURE_2D, textureID_container); - glActiveTexture(GL_TEXTURE0 + 1); // GL_TEXTURE0 + 1 == GL_TEXTURE1, this means looping over multiple units is easily possible - glBindTexture(GL_TEXTURE_2D, textureID_face); + containerImage.BindTexture(); + faceImage.BindTexture(GL_TEXTURE0 + 1); // GL_TEXTURE0 + 1 == GL_TEXTURE1, this means looping over multiple units is easily possible glBindVertexArray(vertexArrayObject); //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // for EBOs diff --git a/src/Engine/textures/Texture2D.h b/src/Engine/textures/Texture2D.h index 7d10415..20f7601 100644 --- a/src/Engine/textures/Texture2D.h +++ b/src/Engine/textures/Texture2D.h @@ -1,11 +1,49 @@ #pragma once +#include +#include + +#include "../util/stb_image.h" +#include "../exceptions/IOException.h" + // Maybe make a base "Texture" class and make a Texture2D and Texture3D child class. look into what would make more sense class Texture2D { public: - Texture2D(); - ~Texture2D(); + // maybe add a parameter for configuring mipmapping + Texture2D(std::string pathToTexture, int desiredColourChannels = 0, GLenum fileFormat = GL_RGB) + { + unsigned char* image = stbi_load(pathToTexture.c_str(), &width, &height, &nrChannels, desiredColourChannels); + if (!image) + { + stbi_image_free(image); + throw Nebulix::IOException("ERROR::FILE::IO::LOAD_TEXTURE"); // it would be better to just use a default error image instead and make the error message a warning message + } + glGenTextures(1, &textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, fileFormat, GL_UNSIGNED_BYTE, image); + glGenerateMipmap(GL_TEXTURE_2D); + stbi_image_free(image); + } + ~Texture2D() + { + glDeleteTextures(1, &textureId); + } + /// + /// Activate and bind this texture to use it + /// + /// The texture unit of this texture. For example GL_TEXTURE0 (default) + void BindTexture(GLenum textureUnit = GL_TEXTURE0) + { + // TODO: add the interpolation configuration. Make as properties which have default settings kinda like Unity + glActiveTexture(textureUnit); // before binding texture, activate correct textre Unit (some drivers might show nothing if this is omitted) + glBindTexture(GL_TEXTURE_2D, textureId); + } + + int GetWidth() { return width; } + int GetHeight() { return height; } + int GetNrChannels() { return nrChannels; } private: - + GLuint textureId; + int width, height, nrChannels; };