diff --git a/CMakeLists.txt b/CMakeLists.txt index f49c297..538bda4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ find_package(OpenGL REQUIRED) find_package(glfw3 REQUIRED) find_package(glm REQUIRED) -add_executable(ecsgame Util/glad.c Util/OBJ_Loader.h Rendering/Shader.cpp Rendering/Shader.h main.cpp ECS/Components/Transform.h ECS/Components/Movement.h ECS/Events/InputEvent.h ECS/Events/MouseMoveEvent.h ECS/Systems/GravitySystem.h ECS/Systems/PositionDebugSystem.h ECS/Systems/KeyboardMovementSystem.h ECS/Components/Camera.h ECS/Systems/RenderSystem.h ECS/Components/Mesh.h ECS/Systems/MouseLookSystem.h ECS/Components/MouseLook.h ECS/Components/ObjMesh.h Util/stb_setup.cpp ECS/Components/Texture.h ECS/Components/LODObjMesh.h) +add_executable(ecsgame Util/glad.c Util/OBJ_Loader.h Rendering/Shader.cpp Rendering/Shader.h main.cpp ECS/Components/Transform.h ECS/Components/Movement.h ECS/Events/InputEvent.h ECS/Events/MouseMoveEvent.h ECS/Systems/GravitySystem.h ECS/Systems/PositionDebugSystem.h ECS/Systems/KeyboardMovementSystem.h ECS/Components/Camera.h ECS/Systems/RenderSystem.h ECS/Components/Mesh.h ECS/Systems/MouseLookSystem.h ECS/Components/MouseLook.h ECS/Components/ObjMesh.h Util/stb_setup.cpp ECS/Components/Texture.h ECS/Components/LODObjMesh.h ECS/Components/SineAnimation.h ECS/Systems/SineAnimationSystem.h) include_directories(${OPENGL_INCLUDE_DIRS}) diff --git a/ECS/Components/ObjMesh.h b/ECS/Components/ObjMesh.h index 3b1f035..de868c5 100644 --- a/ECS/Components/ObjMesh.h +++ b/ECS/Components/ObjMesh.h @@ -13,6 +13,8 @@ struct ObjMesh : public Mesh { Settings(float minDistanceForRender, float maxDistanceForRender) : minDistanceForRender( minDistanceForRender), maxDistanceForRender(maxDistanceForRender) {} + Settings() = default; + float minDistanceForRender = 0.0; float maxDistanceForRender = 1000.0; }; diff --git a/ECS/Systems/RenderSystem.h b/ECS/Systems/RenderSystem.h index 8f453ad..a2a11a0 100644 --- a/ECS/Systems/RenderSystem.h +++ b/ECS/Systems/RenderSystem.h @@ -21,7 +21,7 @@ public: void render(World *pWorld, Shader shader) { pWorld->each([&](Entity *ent, ComponentHandle camera, ComponentHandle cameraTransform) { - glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClearColor(0.6f, 0.9f, 0.9f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader.use(); @@ -30,22 +30,24 @@ public: shader.setMat4("view", glm::inverse(cameraTransform->matrix)); std::vector renderObjects; + std::vector transparentRenderObjects; pWorld->each([&](Entity *ent, ComponentHandle mesh, ComponentHandle transform) { - renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get())); + renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get(), 0)); }); glm::vec3 cameraPos = cameraTransform->getPosition(); - // TODO: Is it possible to do get ObjMeshes in the Mesh loop above implicitly via polymorphism? + /*// TODO: Is it possible to do get ObjMeshes in the Mesh loop above implicitly via polymorphism? + * // TODO: Commented out because of double rendering - we only want to get objects that explicitly DON'T have a texture here! pWorld->each([&](Entity *ent, ComponentHandle mesh, ComponentHandle transform) { // Add the object to the renderObjects to draw if the distance is within the min and max distance of the mesh float distance = glm::distance(cameraPos, transform->getPosition()); if (distance > mesh->minDistance && distance < mesh->maxDistance) { - renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get())); + renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get(), distance)); } - }); + });*/ // ObjMesh with textures pWorld->each([&](Entity *ent, ComponentHandle mesh, ComponentHandle transform, ComponentHandle texture) { @@ -53,7 +55,12 @@ public: float distance = glm::distance(cameraPos, transform->getPosition()); if (distance > mesh->minDistance && distance < mesh->maxDistance) { - renderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh.get())); + // Put it into the list of transparent render objects if the texture wants to be rendered transparently + if (texture->render_transparent) { + transparentRenderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh.get(), distance)); + } else { + renderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh.get(), distance)); + } } }); @@ -63,35 +70,52 @@ public: for (const auto &mesh : lodMesh->meshes) { if (distance > mesh.minDistance && distance < mesh.maxDistance) { - renderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh)); + // Put it into the list of transparent render objects if the texture wants to be rendered transparently + if (texture->render_transparent) { + transparentRenderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh, distance)); + } else { + renderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh, distance)); + } } } }); - // 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); + obj.render(shader); + } - // 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(); + // Sort transparent objects and render them + std::sort(transparentRenderObjects.begin(), transparentRenderObjects.end(), [](const RenderObject &first, const RenderObject &second) -> bool { + return first.distance > second.distance; + }); + for (const RenderObject &obj : transparentRenderObjects) { + obj.render(shader); } }); } struct RenderObject { - RenderObject(const glm::mat4 &matrix, unsigned int textureId, const Mesh &mesh) : matrix(matrix), + RenderObject(const glm::mat4 &matrix, unsigned int textureId, const Mesh &mesh, float distance) + : matrix(matrix), texture_id(textureId), - mesh(mesh) {} + mesh(mesh), + distance(distance) {} + + void render(Shader shader) const { + shader.setMat4("model", matrix); + + // 0 can't be a valid texture name, so we use it for meshes without textures here + if (texture_id != 0) { + glBindTexture(GL_TEXTURE_2D, texture_id); + } + + mesh.render(); + } glm::mat4 matrix; unsigned int texture_id; Mesh mesh; + float distance; }; }; diff --git a/Resources/Facade01_col.jpg b/Resources/Facade01_col.jpg new file mode 100644 index 0000000..059df19 Binary files /dev/null and b/Resources/Facade01_col.jpg differ diff --git a/Resources/Glass.png b/Resources/Glass.png new file mode 100644 index 0000000..d79a8a2 Binary files /dev/null and b/Resources/Glass.png differ diff --git a/Resources/Grass.jpg b/Resources/Grass.jpg new file mode 100644 index 0000000..2db3197 Binary files /dev/null and b/Resources/Grass.jpg differ diff --git a/Resources/Ground.mtl b/Resources/Ground.mtl new file mode 100644 index 0000000..f231bdf --- /dev/null +++ b/Resources/Ground.mtl @@ -0,0 +1,10 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl None +Ns 500 +Ka 0.8 0.8 0.8 +Kd 0.8 0.8 0.8 +Ks 0.8 0.8 0.8 +d 1 +illum 2 diff --git a/Resources/Ground.obj b/Resources/Ground.obj new file mode 100644 index 0000000..639f630 --- /dev/null +++ b/Resources/Ground.obj @@ -0,0 +1,16 @@ +# Blender v2.80 (sub 75) OBJ File: '' +# www.blender.org +mtllib Ground.mtl +o Plane_Plane.001 +v -100.000000 0.000000 100.000000 +v 100.000000 0.000000 100.000000 +v -100.000000 0.000000 -100.000000 +v 100.000000 0.000000 -100.000000 +vt -49.500000 -49.500000 +vt 50.500000 -49.500000 +vt 50.500000 50.500000 +vt -49.500000 50.500000 +vn 0.0000 1.0000 0.0000 +usemtl None +s off +f 1/1/1 2/2/1 4/3/1 3/4/1 diff --git a/Resources/Marble.jpg b/Resources/Marble.jpg new file mode 100644 index 0000000..a5b1607 Binary files /dev/null and b/Resources/Marble.jpg differ diff --git a/Resources/Wall.mtl b/Resources/Wall.mtl new file mode 100644 index 0000000..f231bdf --- /dev/null +++ b/Resources/Wall.mtl @@ -0,0 +1,10 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl None +Ns 500 +Ka 0.8 0.8 0.8 +Kd 0.8 0.8 0.8 +Ks 0.8 0.8 0.8 +d 1 +illum 2 diff --git a/Resources/Wall.obj b/Resources/Wall.obj new file mode 100644 index 0000000..b2d121f --- /dev/null +++ b/Resources/Wall.obj @@ -0,0 +1,16 @@ +# Blender v2.80 (sub 75) OBJ File: '' +# www.blender.org +mtllib Wall.mtl +o Plane +v -4.000000 0.000000 -0.000000 +v 4.000000 0.000000 -0.000000 +v -4.000000 8.000000 0.000000 +v 4.000000 8.000000 0.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vn 0.0000 -0.0000 1.0000 +usemtl None +s off +f 1/1/1 2/2/1 4/3/1 3/4/1 diff --git a/main.cpp b/main.cpp index 9c3c6cb..f932818 100644 --- a/main.cpp +++ b/main.cpp @@ -84,12 +84,31 @@ int main() { player->assign(glm::vec3(2.f, 2.f, 2.f)); player->assign(70.0f, 640, 480, 0.1f, 100.0f); player->assign(0.1); + player->get()->translate(glm::vec3(0.0f, 1.0f, 2.0f)); - Entity *box2 = world->create(); - box2->assign(); - box2->assign(std::vector{ObjMesh("Resources/Monkey.obj", ObjMesh::Settings(0.0, 8.0)), ObjMesh("Resources/MonkeySimple.obj", ObjMesh::Settings(8.0, 100.0))}); - box2->assign("Resources/tex.png", Texture::Settings(true, true)); - box2->get()->translate(glm::vec3(0.0f, 0.0f, -5.0f)); + Entity *monkey = world->create(); + monkey->assign(); + monkey->assign(std::vector{ObjMesh("Resources/Monkey.obj", ObjMesh::Settings(0.0, 8.0)), ObjMesh("Resources/MonkeySimple.obj", ObjMesh::Settings(8.0, 100.0))}); + monkey->assign("Resources/Marble.jpg", Texture::Settings(true, false)); + monkey->get()->translate(glm::vec3(0.0f, 2.0f, -6.0f)); + + Entity *wall1 = world->create(); + wall1->assign(); + wall1->assign(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); + wall1->assign("Resources/Glass.png", Texture::Settings(true, true)); + wall1->get()->translate(glm::vec3(0.0f, 0.0f, -2.0f)); + + Entity *wall2 = world->create(); + wall2->assign(); + wall2->assign(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); + wall2->assign("Resources/Glass.png", Texture::Settings(true, true)); + wall2->get()->translate(glm::vec3(0.0f, 0.0f, -10.0f)); + + Entity *ground = world->create(); + ground->assign(); + ground->assign(ObjMesh("Resources/Ground.obj", ObjMesh::Settings())); + ground->assign("Resources/Grass.jpg", Texture::Settings(true, false)); + ground->get()->translate(glm::vec3(0.0f, 0.0f, 0.0f)); Shader defaultShader("Shaders/default-vertex.vs", "Shaders/default-fragment.fs");