From 02784e1edfb4c6e474b58a50ee8c1eb3a8c01ae2 Mon Sep 17 00:00:00 2001 From: Joey de Vries Date: Wed, 12 Apr 2017 22:51:42 +0200 Subject: [PATCH] Code re-work: model loading --- includes/learnopengl/mesh.h | 4 +- includes/learnopengl/model.h | 60 +++--- .../light_casters_directional.cpp | 4 +- .../{shader.frag => 1.model_loading.fs} | 5 +- .../1.model_loading/1.model_loading.vs | 16 ++ .../1.model_loading/model_loading.cpp | 181 ++++++++++++++++++ .../1.model_loading/model_rendered.cpp | 172 ----------------- src/3.model_loading/1.model_loading/shader.vs | 16 -- 8 files changed, 241 insertions(+), 217 deletions(-) rename src/3.model_loading/1.model_loading/{shader.frag => 1.model_loading.fs} (55%) create mode 100644 src/3.model_loading/1.model_loading/1.model_loading.vs create mode 100644 src/3.model_loading/1.model_loading/model_loading.cpp delete mode 100644 src/3.model_loading/1.model_loading/model_rendered.cpp delete mode 100644 src/3.model_loading/1.model_loading/shader.vs diff --git a/includes/learnopengl/mesh.h b/includes/learnopengl/mesh.h index e99b0d5..dd9a322 100644 --- a/includes/learnopengl/mesh.h +++ b/includes/learnopengl/mesh.h @@ -7,7 +7,7 @@ #include using namespace std; // GL Includes -#include // Contains all the necessery OpenGL includes +#include // Contains all the necessery OpenGL includes #include #include @@ -76,7 +76,7 @@ public: ss << heightNr++; // Transfer GLuint to stream number = ss.str(); // Now set the sampler to the correct texture unit - glUniform1i(glGetUniformLocation(shader.Program, (name + number).c_str()), i); + glUniform1i(glGetUniformLocation(shader.ID, (name + number).c_str()), i); // And finally bind the texture glBindTexture(GL_TEXTURE_2D, this->textures[i].id); } diff --git a/includes/learnopengl/model.h b/includes/learnopengl/model.h index fbb9e41..91e5d9a 100644 --- a/includes/learnopengl/model.h +++ b/includes/learnopengl/model.h @@ -8,17 +8,17 @@ #include using namespace std; // GL Includes -#include // Contains all the necessery OpenGL includes +#include // Contains all the necessery OpenGL includes #include #include -#include +#include #include #include #include #include -GLint TextureFromFile(const char* path, string directory, bool gamma = false); +unsigned int TextureFromFile(const char* path, string directory, bool gamma = false); class Model { @@ -201,28 +201,42 @@ private: }; - - -GLint TextureFromFile(const char* path, string directory, bool gamma) +unsigned int TextureFromFile(const char* path, string directory, bool gamma) { - //Generate texture ID and load texture data string filename = string(path); filename = directory + '/' + filename; - GLuint textureID; - glGenTextures(1, &textureID); - int width,height; - unsigned char* image = SOIL_load_image(filename.c_str(), &width, &height, 0, SOIL_LOAD_RGB); - // Assign texture to ID - glBindTexture(GL_TEXTURE_2D, textureID); - glTexImage2D(GL_TEXTURE_2D, 0, gamma ? GL_SRGB : GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); - glGenerateMipmap(GL_TEXTURE_2D); - // Parameters - 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); - glBindTexture(GL_TEXTURE_2D, 0); - SOIL_free_image_data(image); + unsigned int textureID; + glGenTextures(1, &textureID); + + int width, height, nrComponents; + unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0); + if (data) + { + GLenum format; + if (nrComponents == 1) + format = GL_RED; + else if (nrComponents == 3) + format = GL_RGB; + else if (nrComponents == 4) + format = GL_RGBA; + + glBindTexture(GL_TEXTURE_2D, textureID); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); + glGenerateMipmap(GL_TEXTURE_2D); + + 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); + + stbi_image_free(data); + } + else + { + std::cout << "Texture failed to load at path: " << path << std::endl; + stbi_image_free(data); + } + return textureID; -} +} \ No newline at end of file diff --git a/src/2.lighting/5.1.light_casters_directional/light_casters_directional.cpp b/src/2.lighting/5.1.light_casters_directional/light_casters_directional.cpp index 8058fa2..2fc739b 100644 --- a/src/2.lighting/5.1.light_casters_directional/light_casters_directional.cpp +++ b/src/2.lighting/5.1.light_casters_directional/light_casters_directional.cpp @@ -65,8 +65,8 @@ int main() // ----------------------------- glEnable(GL_DEPTH_TEST); - // build and compile our shader zprogram - // ------------------------------------ + // build and compile shaders + // ------------------------- Shader lightingShader("5.1.light_casters.vs", "5.1.light_casters.fs"); Shader lampShader("1.lamp.vs", "1.lamp.fs"); diff --git a/src/3.model_loading/1.model_loading/shader.frag b/src/3.model_loading/1.model_loading/1.model_loading.fs similarity index 55% rename from src/3.model_loading/1.model_loading/shader.frag rename to src/3.model_loading/1.model_loading/1.model_loading.fs index 235fc04..9da78b1 100644 --- a/src/3.model_loading/1.model_loading/shader.frag +++ b/src/3.model_loading/1.model_loading/1.model_loading.fs @@ -1,10 +1,11 @@ #version 330 core +out vec4 FragColor; + in vec2 TexCoords; -out vec4 color; uniform sampler2D texture_diffuse1; void main() { - color = texture(texture_diffuse1, TexCoords); + FragColor = texture(texture_diffuse1, TexCoords); } \ No newline at end of file diff --git a/src/3.model_loading/1.model_loading/1.model_loading.vs b/src/3.model_loading/1.model_loading/1.model_loading.vs new file mode 100644 index 0000000..f9203e8 --- /dev/null +++ b/src/3.model_loading/1.model_loading/1.model_loading.vs @@ -0,0 +1,16 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = aTexCoords; + gl_Position = projection * view * model * vec4(aPos, 1.0f); +} \ No newline at end of file diff --git a/src/3.model_loading/1.model_loading/model_loading.cpp b/src/3.model_loading/1.model_loading/model_loading.cpp new file mode 100644 index 0000000..61f1ad4 --- /dev/null +++ b/src/3.model_loading/1.model_loading/model_loading.cpp @@ -0,0 +1,181 @@ +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +void framebuffer_size_callback(GLFWwindow* window, int width, int height); +void mouse_callback(GLFWwindow* window, double xpos, double ypos); +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); + +// camera +Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); +float lastX = 800.0f / 2.0; +float lastY = 600.0 / 2.0; +bool firstMouse = true; + +float deltaTime = 0.0f; // time between current frame and last frame +float lastFrame = 0.0f; + +int main() +{ + // glfw: initialize and configure + // ------------------------------ + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + // glfw window creation + // -------------------- + GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL); + glfwMakeContextCurrent(window); + if (window == NULL) + { + std::cout << "Failed to create GLFW window" << std::endl; + glfwTerminate(); + return -1; + } + glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + glfwSetCursorPosCallback(window, mouse_callback); + glfwSetScrollCallback(window, scroll_callback); + + // tell GLFW to capture our mouse + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + // glad: load all OpenGL function pointers + // --------------------------------------- + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { + std::cout << "Failed to initialize GLAD" << std::endl; + return -1; + } + + // configure global opengl state + // ----------------------------- + glEnable(GL_DEPTH_TEST); + + // build and compile shaders + // ------------------------- + Shader ourShader("1.model_loading.vs", "1.model_loading.fs"); + + // load models + // ----------- + Model ourModel(FileSystem::getPath("resources/objects/nanosuit/nanosuit.obj")); + + + // draw in wireframe + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + // render loop + // ----------- + while (!glfwWindowShouldClose(window)) + { + // per-frame time logic + // -------------------- + float currentFrame = glfwGetTime(); + deltaTime = currentFrame - lastFrame; + lastFrame = currentFrame; + + // input + // ----- + processInput(window); + + // render + // ------ + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // don't forget to enable shader before setting uniforms + ourShader.use(); + + // view/projection transformations + glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), 800.0f / 600.0f, 0.1f, 100.0f); + glm::mat4 view = camera.GetViewMatrix(); + ourShader.setMat4("projection", projection); + ourShader.setMat4("view", view); + + // render the loaded model + glm::mat4 model; + model = glm::translate(model, glm::vec3(0.0f, -1.75f, 0.0f)); // translate it down so it's at the center of the scene + model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // it's a bit too big for our scene, so scale it down + ourShader.setMat4("model", model); + ourModel.Draw(ourShader); + + + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- + glfwSwapBuffers(window); + glfwPollEvents(); + } + + // glfw: terminate, clearing all previously allocated GLFW resources. + // ------------------------------------------------------------------ + glfwTerminate(); + return 0; +} + +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) +{ + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); + + float cameraSpeed = 2.5 * deltaTime; + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) + camera.ProcessKeyboard(FORWARD, deltaTime); + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) + camera.ProcessKeyboard(BACKWARD, deltaTime); + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) + camera.ProcessKeyboard(LEFT, deltaTime); + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) + camera.ProcessKeyboard(RIGHT, deltaTime); +} + +// glfw: whenever the window size changed (by OS or user resize) this callback function executes +// --------------------------------------------------------------------------------------------- +void framebuffer_size_callback(GLFWwindow* window, int width, int height) +{ + // make sure the viewport matches the new window dimensions; note that width and + // height will be significantly larger than specified on retina displays. + glViewport(0, 0, width, height); +} + + +// glfw: whenever the mouse moves, this callback is called +// ------------------------------------------------------- +void mouse_callback(GLFWwindow* window, double xpos, double ypos) +{ + if (firstMouse) + { + lastX = xpos; + lastY = ypos; + firstMouse = false; + } + + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top + + lastX = xpos; + lastY = ypos; + + camera.ProcessMouseMovement(xoffset, yoffset); +} + +// glfw: whenever the mouse scroll wheel scrolls, this callback is called +// ---------------------------------------------------------------------- +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) +{ + camera.ProcessMouseScroll(yoffset); +} \ No newline at end of file diff --git a/src/3.model_loading/1.model_loading/model_rendered.cpp b/src/3.model_loading/1.model_loading/model_rendered.cpp deleted file mode 100644 index 10b4442..0000000 --- a/src/3.model_loading/1.model_loading/model_rendered.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// Std. Includes -#include - -// GLEW -#define GLEW_STATIC -#include - -// GLFW -#include - -// GL includes -#include -#include -#include - -// GLM Mathemtics -#include -#include -#include - -// Other Libs -#include -#include - -// Properties -GLuint screenWidth = 800, screenHeight = 600; - -// Function prototypes -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); -void mouse_callback(GLFWwindow* window, double xpos, double ypos); -void Do_Movement(); - -// Camera -Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); -bool keys[1024]; -GLfloat lastX = 400, lastY = 300; -bool firstMouse = true; - -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; - -// The MAIN function, from here we start our application and run our Game loop -int main() -{ - // Init GLFW - glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); - - GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed - glfwMakeContextCurrent(window); - - // Set the required callback functions - glfwSetKeyCallback(window, key_callback); - glfwSetCursorPosCallback(window, mouse_callback); - glfwSetScrollCallback(window, scroll_callback); - - // Options - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - - // Initialize GLEW to setup the OpenGL Function pointers - glewExperimental = GL_TRUE; - glewInit(); - - // Define the viewport dimensions - glViewport(0, 0, screenWidth, screenHeight); - - // Setup some OpenGL options - glEnable(GL_DEPTH_TEST); - - // Setup and compile our shaders - Shader shader("shader.vs", "shader.frag"); - - // Load models - Model ourModel(FileSystem::getPath("resources/objects/nanosuit/nanosuit.obj").c_str()); - - // Draw in wireframe - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - // Game loop - while(!glfwWindowShouldClose(window)) - { - // Set frame time - GLfloat currentFrame = glfwGetTime(); - deltaTime = currentFrame - lastFrame; - lastFrame = currentFrame; - - // Check and call events - glfwPollEvents(); - Do_Movement(); - - // Clear the colorbuffer - glClearColor(0.05f, 0.05f, 0.05f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - shader.Use(); // <-- Don't forget this one! - // Transformation matrices - glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f); - glm::mat4 view = camera.GetViewMatrix(); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - - // Draw the loaded model - glm::mat4 model; - model = glm::translate(model, glm::vec3(0.0f, -1.75f, 0.0f)); // Translate it down a bit so it's at the center of the scene - model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // It's a bit too big for our scene, so scale it down - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - ourModel.Draw(shader); - - // Swap the buffers - glfwSwapBuffers(window); - } - - glfwTerminate(); - return 0; -} - -#pragma region "User input" - -// Moves/alters the camera positions based on user input -void Do_Movement() -{ - // Camera controls - if(keys[GLFW_KEY_W]) - camera.ProcessKeyboard(FORWARD, deltaTime); - if(keys[GLFW_KEY_S]) - camera.ProcessKeyboard(BACKWARD, deltaTime); - if(keys[GLFW_KEY_A]) - camera.ProcessKeyboard(LEFT, deltaTime); - if(keys[GLFW_KEY_D]) - camera.ProcessKeyboard(RIGHT, deltaTime); -} - -// Is called whenever a key is pressed/released via GLFW -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) -{ - if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - if(action == GLFW_PRESS) - keys[key] = true; - else if(action == GLFW_RELEASE) - keys[key] = false; -} - -void mouse_callback(GLFWwindow* window, double xpos, double ypos) -{ - if(firstMouse) - { - lastX = xpos; - lastY = ypos; - firstMouse = false; - } - - GLfloat xoffset = xpos - lastX; - GLfloat yoffset = lastY - ypos; - - lastX = xpos; - lastY = ypos; - - camera.ProcessMouseMovement(xoffset, yoffset); -} - -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) -{ - camera.ProcessMouseScroll(yoffset); -} - -#pragma endregion \ No newline at end of file diff --git a/src/3.model_loading/1.model_loading/shader.vs b/src/3.model_loading/1.model_loading/shader.vs deleted file mode 100644 index 6c9831b..0000000 --- a/src/3.model_loading/1.model_loading/shader.vs +++ /dev/null @@ -1,16 +0,0 @@ -#version 330 core -layout (location = 0) in vec3 position; -// layout (location = 1) in vec3 normal; -layout (location = 2) in vec2 texCoords; - -out vec2 TexCoords; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; - -void main() -{ - gl_Position = projection * view * model * vec4(position, 1.0f); - TexCoords = texCoords; -} \ No newline at end of file