diff --git a/ECS/Components/Mesh.h b/ECS/Components/Mesh.h index e9aa202..1f7b949 100644 --- a/ECS/Components/Mesh.h +++ b/ECS/Components/Mesh.h @@ -47,7 +47,7 @@ struct Mesh { glBindVertexArray(0); } - void render() { + void render() const { glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glDrawElements(GL_TRIANGLES, vertex_count, GL_UNSIGNED_INT, 0); diff --git a/ECS/Components/Texture.h b/ECS/Components/Texture.h index f6c19c3..9071947 100644 --- a/ECS/Components/Texture.h +++ b/ECS/Components/Texture.h @@ -8,30 +8,53 @@ #include "../../Util/stb_image.h" struct Texture { - explicit Texture(const std::string& path) { + struct Settings { + Settings(bool mipmaps, bool transparent) : mipmaps(mipmaps), transparent(transparent) {} + + bool mipmaps = true; + bool transparent = false; + }; + + explicit Texture(const std::string& path, Settings settings) { glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); 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); // Mipmapping + if (settings.mipmaps) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); int width, height, nrChannels; unsigned char *data = stbi_load(path.c_str(), &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); // Mipmapping + // Alpha channel? + unsigned int glChannels = GL_RGB; + if (nrChannels == 4) { + glChannels = GL_RGBA; + } + + glTexImage2D(GL_TEXTURE_2D, 0, glChannels, width, height, 0, glChannels, GL_UNSIGNED_BYTE, data); + + if (settings.mipmaps) { + glGenerateMipmap(GL_TEXTURE_2D); + } } else { std::cout << "Failed to load texture" << std::endl; } stbi_image_free(data); + + render_transparent = settings.transparent; } unsigned int id; + bool render_transparent = false; }; #endif //ECSGAME_TEXTURE_H diff --git a/ECS/Systems/RenderSystem.h b/ECS/Systems/RenderSystem.h index 1b9c4f9..82fb20f 100644 --- a/ECS/Systems/RenderSystem.h +++ b/ECS/Systems/RenderSystem.h @@ -28,29 +28,48 @@ public: shader.setMat4("projection", camera->projection); shader.setMat4("view", glm::inverse(cameraTransform->matrix)); + std::vector renderObjects; + pWorld->each([&](Entity *ent, ComponentHandle mesh, ComponentHandle transform) { - shader.setMat4("model", transform->matrix); - - mesh->render(); + renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get())); }); - // TODO: Duplicate of loop above, but for ObjMesh instead of Mesh. Is it possible to do this implicitly via polymorphism? + // TODO: Is it possible to do get ObjMeshes in the Mesh loop above implicitly via polymorphism? pWorld->each([&](Entity *ent, ComponentHandle mesh, ComponentHandle transform) { - shader.setMat4("model", transform->matrix); - - mesh->render(); + renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get())); }); - // Render ObjMeshes with textures + // ObjMesh with textures pWorld->each([&](Entity *ent, ComponentHandle mesh, ComponentHandle transform, ComponentHandle texture) { - shader.setMat4("model", transform->matrix); - glBindTexture(GL_TEXTURE_2D, texture->id); - - mesh->render(); + renderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh.get())); }); + + // TODO: Separate lists for transparent and non-transparent RenderObjects. The non-transparent list is + // rendered first, then the transparent list is sorted and rendered. + + for (const RenderObject &obj : renderObjects) { + shader.setMat4("model", obj.matrix); + + // 0 can't be a valid texture name, so we use it for meshes without textures here + if (obj.texture_id != 0) { + glBindTexture(GL_TEXTURE_2D, obj.texture_id); + } + + obj.mesh.render(); + } }); } + struct RenderObject { + RenderObject(const glm::mat4 &matrix, unsigned int textureId, const Mesh &mesh) : matrix(matrix), + texture_id(textureId), + mesh(mesh) {} + + glm::mat4 matrix; + unsigned int texture_id; + Mesh mesh; + }; + private: float gravityAmount; }; diff --git a/Resources/tex.jpg b/Resources/tex.jpg deleted file mode 100644 index 8ef744d..0000000 Binary files a/Resources/tex.jpg and /dev/null differ diff --git a/Resources/tex.png b/Resources/tex.png new file mode 100644 index 0000000..dbf64c7 Binary files /dev/null and b/Resources/tex.png differ diff --git a/Shaders/default-fragment.fs b/Shaders/default-fragment.fs index 3a25fd2..042aba1 100644 --- a/Shaders/default-fragment.fs +++ b/Shaders/default-fragment.fs @@ -2,10 +2,17 @@ out mediump vec4 FragColor; in mediump vec2 TexCoord; +in mediump vec3 Normal; -uniform sampler2D ourTexture; +uniform sampler2D tex; void main() { - FragColor = texture(ourTexture, TexCoord); + mediump vec4 texColor = texture(tex, TexCoord); + + // Alpha Scissors + if(texColor.a < 0.1) + discard; + + FragColor = texColor; } \ No newline at end of file diff --git a/Shaders/default-vertex.vs b/Shaders/default-vertex.vs index cb1a547..c34dac2 100644 --- a/Shaders/default-vertex.vs +++ b/Shaders/default-vertex.vs @@ -4,6 +4,7 @@ layout (location = 1) in vec3 NORMAL; layout (location = 2) in vec2 UV; out vec2 TexCoord; +out vec3 Normal; uniform mat4 model; uniform mat4 view; @@ -13,4 +14,5 @@ void main() { gl_Position = projection * view * model * vec4(aPos, 1.0); TexCoord = UV; + Normal = NORMAL; } \ No newline at end of file diff --git a/main.cpp b/main.cpp index 405a045..7d9f06e 100644 --- a/main.cpp +++ b/main.cpp @@ -33,6 +33,7 @@ static void mouse_callback(GLFWwindow* window, double xpos, double ypos) { } int main() { + // TODO: Move this to RenderSystem? GLFWwindow *window; /* Initialize the library */ @@ -65,6 +66,10 @@ int main() { glEnable(GL_DEPTH_TEST); + // Transparency + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // TODO: Could be automated by getting all classes within 'ECS/Systems' // world->registerSystem(new GravitySystem(-9.8f)); // world->registerSystem(new PositionDebugOutputSystem()); @@ -83,7 +88,7 @@ int main() { Entity *box2 = world->create(); box2->assign(); box2->assign("Resources/Monkey.obj"); - box2->assign("Resources/tex.jpg"); + box2->assign("Resources/tex.png", Texture::Settings(true, true)); box2->get()->translate(glm::vec3(0.0f, 0.0f, -5.0f)); Shader defaultShader("Shaders/default-vertex.vs", "Shaders/default-fragment.fs");