diff --git a/ECS/Components/Texture.h b/ECS/Components/Texture.h index 9071947..21d3b46 100644 --- a/ECS/Components/Texture.h +++ b/ECS/Components/Texture.h @@ -8,16 +8,22 @@ #include "../../Util/stb_image.h" struct Texture { + uint id; + uint normal_id; + bool render_transparent = false; + struct Settings { - Settings(bool mipmaps, bool transparent) : mipmaps(mipmaps), transparent(transparent) {} + Settings(bool mipmaps) : mipmaps(mipmaps) {} bool mipmaps = true; - bool transparent = false; }; - explicit Texture(const std::string& path, Settings settings) { - glGenTextures(1, &id); - glBindTexture(GL_TEXTURE_2D, id); + // Bind a texture from the given path and return its ID + uint loadTexture(const std::string& path, Settings settings) { + uint gl_id; + + glGenTextures(1, &gl_id); + glBindTexture(GL_TEXTURE_2D, gl_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); @@ -50,11 +56,17 @@ struct Texture { stbi_image_free(data); - render_transparent = settings.transparent; + return gl_id; } - unsigned int id; - bool render_transparent = false; + explicit Texture(const std::string& path, Settings settings, bool transparent) : id(loadTexture(path, settings)), render_transparent(transparent) {} + + void addNormalmap(const std::string& path, Settings settings) { + normal_id = loadTexture(path, settings); + } + + + }; #endif //ECSGAME_TEXTURE_H diff --git a/ECS/Systems/RenderSystem.h b/ECS/Systems/RenderSystem.h index 3ddafe5..a87e74a 100644 --- a/ECS/Systems/RenderSystem.h +++ b/ECS/Systems/RenderSystem.h @@ -51,10 +51,11 @@ void renderQuad() class RenderSystem : public EntitySystem { public: struct RenderObject { - RenderObject(const glm::mat4 &matrix, const glm::vec3 &origin, unsigned int textureId, const Mesh &mesh, float distance, const Material &material) + RenderObject(const glm::mat4 &matrix, const glm::vec3 &origin, unsigned int textureId, unsigned int normalId, const Mesh &mesh, float distance, const Material &material) : matrix(matrix), origin(origin), texture_id(textureId), + normal_id(normalId), mesh(mesh), distance(distance), material(material) {} @@ -69,6 +70,10 @@ public: glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texture_id); } + if (normal_id != 0) { + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, normal_id); + } // TODO: Not always required (not when rendering shadows) - make functions separate? shader.setFloat("diffuseStrength", material.diffuse); @@ -80,6 +85,7 @@ public: glm::mat4 matrix; glm::vec3 origin; unsigned int texture_id; + unsigned int normal_id; Mesh mesh; float distance; Material material; @@ -116,12 +122,13 @@ public: Material material = materialComponent.isValid() ? materialComponent.get() : Material(); unsigned int textureID = textureComponent.isValid() ? textureComponent->id : 0; + unsigned int normalID = textureComponent.isValid() ? textureComponent->normal_id : 0; // Put it into the list of transparent render objects if the texture wants to be rendered transparently if (textureComponent.isValid() && textureComponent->render_transparent) { - renderObjects[1].emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, mesh.get(), distance, material)); + renderObjects[1].emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, normalID, mesh.get(), distance, material)); } else { - renderObjects[0].emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, mesh.get(), distance, material)); + renderObjects[0].emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, normalID, mesh.get(), distance, material)); } } }); @@ -138,12 +145,13 @@ public: Material material = materialComponent.isValid() ? materialComponent.get() : Material(); unsigned int textureID = textureComponent.isValid() ? textureComponent->id : 0; + unsigned int normalID = textureComponent.isValid() ? textureComponent->normal_id : 0; // Put it into the list of transparent render objects if the texture wants to be rendered transparently if (textureComponent.isValid() && textureComponent->render_transparent) { - renderObjects[1].emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, mesh, distance, material)); + renderObjects[1].emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, normalID, mesh, distance, material)); } else { - renderObjects[0].emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, mesh, distance, material)); + renderObjects[0].emplace_back(RenderObject(transform->matrix, transform->get_origin(), textureID, normalID, mesh, distance, material)); } } } diff --git a/Resources/Grass.jpg b/Resources/Grass.jpg index 2db3197..82957dd 100644 Binary files a/Resources/Grass.jpg and b/Resources/Grass.jpg differ diff --git a/Resources/Grass_Normal.jpg b/Resources/Grass_Normal.jpg new file mode 100644 index 0000000..b4b04da Binary files /dev/null and b/Resources/Grass_Normal.jpg differ diff --git a/Shaders/default-fragment.fs b/Shaders/default-fragment.fs index 60266d5..5b9082e 100644 --- a/Shaders/default-fragment.fs +++ b/Shaders/default-fragment.fs @@ -8,6 +8,7 @@ in mediump vec4 FragPosLightSpace; layout(binding=0) uniform sampler2D shadowMap; layout(binding=1) uniform sampler2D tex; +layout(binding=2) uniform sampler2D normalmap; uniform mediump vec3 lightDirection; uniform mediump vec3 cameraPosition; @@ -43,20 +44,25 @@ void main() { mediump vec4 texColor = texture(tex, TexCoord); + // Get normal from normal map in the range [-1,1] + mediump vec3 map_normal = normalize(texture(normalmap, TexCoord).rgb * 2.0 - 1.0); + + mediump vec3 final_normal = map_normal; + // Alpha Scissors if(texColor.a < 0.1) discard; // Lighting // Diffuse - mediump float diff = max(dot(Normal, lightDirection), 0.0); + mediump float diff = max(dot(final_normal, lightDirection), 0.0); // Ambient mediump float ambient = 0.2; // Specular mediump vec3 viewDir = normalize(cameraPosition - FragPos); - mediump vec3 reflectDir = reflect(-lightDirection, Normal); + mediump vec3 reflectDir = reflect(-lightDirection, final_normal); mediump float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0); diff --git a/main.cpp b/main.cpp index 57572d8..b5f3180 100644 --- a/main.cpp +++ b/main.cpp @@ -118,7 +118,7 @@ int main() { monkey->assign(); monkey->assign(std::vector{ObjMesh("Resources/Monkey.obj",ObjMesh::Settings(0.0, 8.0, 0.4, 0.6)), ObjMesh("Resources/MonkeySimple.obj", ObjMesh::Settings(8.0, 100.0, 0.4, 0.6))}); - monkey->assign("Resources/Marble.jpg", Texture::Settings(true, false)); + monkey->assign("Resources/Marble.jpg", Texture::Settings(true), false); monkey->assign(glm::vec3(0.0, 0.3, 0.0), 0.5); monkey->assign(0.6, 0.6); monkey->get()->set_origin(glm::vec3(0.0f, 2.0f, -6.0f)); @@ -127,7 +127,7 @@ int main() { monkey2->assign(); monkey2->assign(std::vector{ObjMesh("Resources/Monkey.obj",ObjMesh::Settings(0.0, 8.0, 0.4, 0.6)), ObjMesh("Resources/MonkeySimple.obj", ObjMesh::Settings(8.0, 100.0, 0.4, 0.6))}); - monkey2->assign("Resources/Marble.jpg", Texture::Settings(true, false)); + monkey2->assign("Resources/Marble.jpg", Texture::Settings(true), false); monkey2->assign(glm::vec3(0.0, 0.3, 0.0), 0.5); monkey2->assign(0.6, 0.6); monkey2->get()->set_origin(glm::vec3(-5.0f, 2.0f, -20.0f)); @@ -135,21 +135,21 @@ int main() { Entity *wall1 = world->create(); wall1->assign(); wall1->assign(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); - wall1->assign("Resources/Glass.png", Texture::Settings(true, true)); + wall1->assign("Resources/Glass.png", Texture::Settings(true), true); wall1->assign(0.2, 0.8); wall1->get()->set_origin(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->assign("Resources/Glass.png", Texture::Settings(true), true); wall2->assign(0.2, 0.8); wall2->get()->set_origin(glm::vec3(0.0f, 0.0f, -10.0f)); Entity *wall3 = world->create(); wall3->assign(); wall3->assign(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); - wall3->assign("Resources/Glass.png", Texture::Settings(true, true)); + wall3->assign("Resources/Glass.png", Texture::Settings(true), true); wall3->assign(0.2, 0.8); wall3->get()->set_origin(glm::vec3(4.0f, 0.0f, -6.0f)); wall3->get()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0)); @@ -157,7 +157,7 @@ int main() { Entity *wall4 = world->create(); wall4->assign(); wall4->assign(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); - wall4->assign("Resources/Glass.png", Texture::Settings(true, true)); + wall4->assign("Resources/Glass.png", Texture::Settings(true), true); wall4->assign(0.2, 0.8); wall4->get()->set_origin(glm::vec3(-4.0f, 0.0f, -6.0f)); wall4->get()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0)); @@ -165,14 +165,15 @@ int main() { Entity *ground = world->create(); ground->assign(); ground->assign(ObjMesh("Resources/Ground.obj", ObjMesh::Settings())); - ground->assign("Resources/Grass.jpg", Texture::Settings(true, false)); + ground->assign("Resources/Grass.jpg", Texture::Settings(true), false); + ground->get()->addNormalmap("Resources/Grass_Normal.jpg", Texture::Settings(true)); ground->assign(1.0, 0.0); ground->get()->set_origin(glm::vec3(0.0f, 0.0f, 0.0f)); Entity *bench = world->create(); bench->assign(); bench->assign(ObjMesh("Resources/bench.obj", ObjMesh::Settings())); - bench->assign("Resources/Wood.jpg", Texture::Settings(true, false)); + bench->assign("Resources/Wood.jpg", Texture::Settings(true), false); bench->assign(0.8, 0.2); bench->get()->set_origin(glm::vec3(8.0f, 0.0f, 0.0f)); bench->get()->rotate(-90.0, glm::vec3(0.0, 1.0, 0.0)); @@ -180,7 +181,7 @@ int main() { Entity *ring = world->create(); ring->assign(); ring->assign(ObjMesh("Resources/ring.obj", ObjMesh::Settings())); - ring->assign("Resources/Gold.jpg", Texture::Settings(true, false)); + ring->assign("Resources/Gold.jpg", Texture::Settings(true), false); ring->assign(0.1, 0.9); ring->get()->set_origin(glm::vec3(-5.0f, 2.0f, 0.0f));