From 11f63887e9573415f2ed2fed84986ab4c4bd0b4f Mon Sep 17 00:00:00 2001 From: plane000 Date: Sun, 16 Sep 2018 22:28:22 +0100 Subject: [PATCH] (broken) texture loading --- OpenGL/OpenGL.vcxproj | 13 +++++--- OpenGL/OpenGL.vcxproj.filters | 19 ++++++++++-- OpenGL/display.cpp | 2 +- OpenGL/{headers => }/display.h | 0 OpenGL/main.cpp | 28 +++++++++++------ OpenGL/mesh.cpp | 26 +++++++++++----- OpenGL/{headers => }/mesh.h | 10 ++++-- OpenGL/shader.cpp | 37 +++++++++++++---------- OpenGL/{headers => }/shader.h | 3 +- OpenGL/texture.cpp | 37 +++++++++++++++++++++++ OpenGL/texture.h | 16 ++++++++++ resources/shaders/simple2d_fragment.glsl | 11 +++++++ resources/shaders/simple2d_vertex.glsl | 13 ++++++++ resources/textures/chance-cube.jpg | Bin 0 -> 56067 bytes 14 files changed, 171 insertions(+), 44 deletions(-) rename OpenGL/{headers => }/display.h (100%) rename OpenGL/{headers => }/mesh.h (51%) rename OpenGL/{headers => }/shader.h (89%) create mode 100644 OpenGL/texture.cpp create mode 100644 OpenGL/texture.h create mode 100644 resources/shaders/simple2d_fragment.glsl create mode 100644 resources/shaders/simple2d_vertex.glsl create mode 100644 resources/textures/chance-cube.jpg diff --git a/OpenGL/OpenGL.vcxproj b/OpenGL/OpenGL.vcxproj index 36502c7..804288a 100644 --- a/OpenGL/OpenGL.vcxproj +++ b/OpenGL/OpenGL.vcxproj @@ -1,4 +1,4 @@ - + @@ -77,6 +77,7 @@ true true .\include;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) .\lib;%(AdditionalLibraryDirectories) @@ -124,11 +125,15 @@ + + - - - + + + + + diff --git a/OpenGL/OpenGL.vcxproj.filters b/OpenGL/OpenGL.vcxproj.filters index e315d3d..6951a5e 100644 --- a/OpenGL/OpenGL.vcxproj.filters +++ b/OpenGL/OpenGL.vcxproj.filters @@ -5,21 +5,34 @@ + + helpers + + {3e9ef4e5-bcd4-4161-8243-90e67d85dc43} + + {3b3efd97-0e64-421a-b292-4d37dfc52e96} + - + headers - + headers - + headers + + headers + + + helpers + \ No newline at end of file diff --git a/OpenGL/display.cpp b/OpenGL/display.cpp index b2cfd05..61ba2a8 100644 --- a/OpenGL/display.cpp +++ b/OpenGL/display.cpp @@ -1,7 +1,7 @@ #include #include -#include "headers/display.h" +#include "display.h" Display::Display(int width, int height, const std::string& title) { SDL_Init(SDL_INIT_VIDEO); diff --git a/OpenGL/headers/display.h b/OpenGL/display.h similarity index 100% rename from OpenGL/headers/display.h rename to OpenGL/display.h diff --git a/OpenGL/main.cpp b/OpenGL/main.cpp index 22bb368..4d09851 100644 --- a/OpenGL/main.cpp +++ b/OpenGL/main.cpp @@ -1,29 +1,39 @@ #include #include -#include "headers/display.h" -#include "headers/mesh.h" -#include "headers/shader.h" +#include "display.h" +#include "mesh.h" +#include "shader.h" +#include "texture.h" #undef main int main(int argc, char** argv) { - Display display(800, 600, "Crumpet Engine"); + Display display(800, 800, "Crumpet Engine"); glClearColor(0.1f, 0.45f, 0.9f, 1.0f); GLfloat vertices[] = { - -0.5f, -0.5f, 0.0f, - 0.5f, -0.5f, 0.0f, - 0.0f, 0.5f, 0.0f + // positions // colors // texture coords + 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right + 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right + -0.5f,-0.5f, 0.0f, 0.0f, 0.0f, 1.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 }; - Mesh mesh(vertices, sizeof(vertices) / sizeof(vertices[0])); - Shader shader; + unsigned int indices[] = { + 0, 1, 3, // first triangle + 1, 2, 3 // second triangle + }; + + Mesh mesh(vertices, indices, sizeof(vertices) / sizeof(vertices[0])); + Shader shader("E:/Games/Practicing/OpenGL/resources/shaders/simple2d"); + Texture chanceCube("E:/Games/Practicing/OpenGL/resources/textures/chance-cube.jpg"); while(!display.isClosed()) { glClear(GL_COLOR_BUFFER_BIT); shader.Bind(); + chanceCube.Bind(0); mesh.Draw(); display.Update(); diff --git a/OpenGL/mesh.cpp b/OpenGL/mesh.cpp index 1decc73..1818fa5 100644 --- a/OpenGL/mesh.cpp +++ b/OpenGL/mesh.cpp @@ -1,20 +1,32 @@ -#include "headers/mesh.h" +#include "mesh.h" -Mesh::Mesh(GLfloat *vertices, unsigned int numVerticies) { +Mesh::Mesh(GLfloat *vertices, unsigned int *indices, unsigned int numVerticies) { m_drawCount = numVerticies; glGenVertexArrays(1, &m_VAO); + glGenBuffers(1, &m_VBO); + glGenBuffers(1, &m_EBO); + glBindVertexArray(m_VAO); - glGenBuffers(NUM_BUFFERS, m_VBO); - glBindBuffer(GL_ARRAY_BUFFER, m_VBO[POSITION_VB]); - glBufferData(GL_ARRAY_BUFFER, numVerticies * sizeof(vertices[0]), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, m_VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_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); glEnableVertexAttribArray(0); + // color attribute + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + glEnableVertexAttribArray(1); + // texture coord attribute + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); + std::cout << "Mesh loaded successfully" << std::endl; } diff --git a/OpenGL/headers/mesh.h b/OpenGL/mesh.h similarity index 51% rename from OpenGL/headers/mesh.h rename to OpenGL/mesh.h index e1a371e..f11f711 100644 --- a/OpenGL/headers/mesh.h +++ b/OpenGL/mesh.h @@ -1,21 +1,25 @@ #pragma once #include +#include +#include #include class Mesh { public: - Mesh(GLfloat *vertices, unsigned int numVerticies); + Mesh(GLfloat *vertices, unsigned int *indices, unsigned int numVerticies); void Draw(); virtual ~Mesh(); private: enum { POSITION_VB, - NUM_BUFFERS + NUM_BUFFERS, + TEXCOORD_VB }; unsigned int m_VAO; - unsigned int m_VBO[NUM_BUFFERS]; + unsigned int m_VBO; + unsigned int m_EBO; unsigned int m_drawCount; }; diff --git a/OpenGL/shader.cpp b/OpenGL/shader.cpp index e60566b..891cbb7 100644 --- a/OpenGL/shader.cpp +++ b/OpenGL/shader.cpp @@ -1,22 +1,12 @@ -#include "headers/shader.h" +#include "shader.h" -const char *vertexShaderSource = "#version 330 core\n" -"layout (location = 0) in vec3 aPos;\n" -"void main()\n" -"{\n" -" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" -"}\0"; -const char *fragmentShaderSource = "#version 330 core\n" -"out vec4 FragColor;\n" -"void main()\n" -"{\n" -" FragColor = vec4(0.25f, 1.0f, 0.49f, 1.0f);\n" -"}\n\0"; +Shader::Shader(std::string path) { + std::string vertexPath = path + "_vertex.glsl"; + std::string fragmentPath = path + "_fragment.glsl"; -Shader::Shader() { m_program = glCreateProgram(); - m_shaders[0] = CreateShader(vertexShaderSource, GL_VERTEX_SHADER); - m_shaders[1] = CreateShader(fragmentShaderSource, GL_FRAGMENT_SHADER); + m_shaders[0] = CreateShader(LoadFile(vertexPath), GL_VERTEX_SHADER); + m_shaders[1] = CreateShader(LoadFile(fragmentPath), GL_FRAGMENT_SHADER); for (unsigned int i = 0; i < NUM_SHADERS; i++) { glAttachShader(m_program, m_shaders[i]); @@ -70,9 +60,24 @@ void Shader::Bind() { } std::string Shader::LoadFile(std::string path) { + std::ifstream file; + file.open((path).c_str()); + std::string output; + std::string line; + + if (file.is_open()) { + while (file.good()) { + getline(file, line); + output.append(line + "\n"); + } + } + else { + std::cout << "Unable to load shader: " << path << std::endl; + } std::cout << "Successfully loaded " + path << std::endl; + return output; } Shader::~Shader() { diff --git a/OpenGL/headers/shader.h b/OpenGL/shader.h similarity index 89% rename from OpenGL/headers/shader.h rename to OpenGL/shader.h index 3246f46..a6db243 100644 --- a/OpenGL/headers/shader.h +++ b/OpenGL/shader.h @@ -2,11 +2,12 @@ #include #include +#include #include class Shader { public: - Shader(); + Shader(std::string path); void Bind(); virtual ~Shader(); private: diff --git a/OpenGL/texture.cpp b/OpenGL/texture.cpp new file mode 100644 index 0000000..ffa3aab --- /dev/null +++ b/OpenGL/texture.cpp @@ -0,0 +1,37 @@ +#include "texture.h" +#include "stb_image.h" +#include +#include + +Texture::Texture(std::string fileName) { + int width, height, numComponents; + unsigned char* imageData = stbi_load(fileName.c_str(), &width, &height, &numComponents, 4); + + if (imageData == NULL) + std::cout << "Loading failed for texture: " << fileName << std::endl; + + glGenTextures(1, &m_texture); + glBindTexture(GL_TEXTURE_2D, m_texture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); + + stbi_image_free(imageData); + std::cout << "Loaded texture: " << fileName << std::endl; +} + +void Texture::Bind(unsigned int unit) { + assert(unit >= 0 && unit <= 31); + + glActiveTexture(GL_TEXTURE0 + unit); + glBindTexture(GL_TEXTURE_2D, m_texture); +} + +Texture::~Texture() { + glDeleteTextures(1, &m_texture); +} diff --git a/OpenGL/texture.h b/OpenGL/texture.h new file mode 100644 index 0000000..5b11396 --- /dev/null +++ b/OpenGL/texture.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +class Texture { +public: + Texture(std::string fileName); + + void Bind(unsigned int unit); + + virtual ~Texture(); +private: + GLuint m_texture; +}; + diff --git a/resources/shaders/simple2d_fragment.glsl b/resources/shaders/simple2d_fragment.glsl new file mode 100644 index 0000000..c244f30 --- /dev/null +++ b/resources/shaders/simple2d_fragment.glsl @@ -0,0 +1,11 @@ +#version 330 core +out vec4 FragColor; + +in vec3 ourColor; +in vec2 TexCoord; + +uniform sampler2D ourTexture; + +void main() { + FragColor = texture(ourTexture, TexCoord); +} diff --git a/resources/shaders/simple2d_vertex.glsl b/resources/shaders/simple2d_vertex.glsl new file mode 100644 index 0000000..7bb7d54 --- /dev/null +++ b/resources/shaders/simple2d_vertex.glsl @@ -0,0 +1,13 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aColor; +layout (location = 2) in vec2 aTexCoord; + +out vec3 ourColor; +out vec2 TexCoord; + +void main() { + gl_Position = vec4(aPos, 1.0); + ourColor = aColor; + TexCoord = aTexCoord; +} diff --git a/resources/textures/chance-cube.jpg b/resources/textures/chance-cube.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ff09f421c8be54359ecc41a039e1559c26601d1e GIT binary patch literal 56067 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