Add normalmap support

Tangents are not yet used, so the normals are currently only correct for the ground.
This commit is contained in:
karl 2020-11-16 13:11:07 +01:00
parent 4073897f74
commit 4951ad3b04
6 changed files with 51 additions and 24 deletions

View File

@ -8,16 +8,22 @@
#include "../../Util/stb_image.h" #include "../../Util/stb_image.h"
struct Texture { struct Texture {
uint id;
uint normal_id;
bool render_transparent = false;
struct Settings { struct Settings {
Settings(bool mipmaps, bool transparent) : mipmaps(mipmaps), transparent(transparent) {} Settings(bool mipmaps) : mipmaps(mipmaps) {}
bool mipmaps = true; bool mipmaps = true;
bool transparent = false;
}; };
explicit Texture(const std::string& path, Settings settings) { // Bind a texture from the given path and return its ID
glGenTextures(1, &id); uint loadTexture(const std::string& path, Settings settings) {
glBindTexture(GL_TEXTURE_2D, id); 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_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
@ -50,11 +56,17 @@ struct Texture {
stbi_image_free(data); stbi_image_free(data);
render_transparent = settings.transparent; return gl_id;
} }
unsigned int id; explicit Texture(const std::string& path, Settings settings, bool transparent) : id(loadTexture(path, settings)), render_transparent(transparent) {}
bool render_transparent = false;
void addNormalmap(const std::string& path, Settings settings) {
normal_id = loadTexture(path, settings);
}
}; };
#endif //ECSGAME_TEXTURE_H #endif //ECSGAME_TEXTURE_H

View File

@ -51,10 +51,11 @@ void renderQuad()
class RenderSystem : public EntitySystem { class RenderSystem : public EntitySystem {
public: public:
struct RenderObject { 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), : matrix(matrix),
origin(origin), origin(origin),
texture_id(textureId), texture_id(textureId),
normal_id(normalId),
mesh(mesh), mesh(mesh),
distance(distance), distance(distance),
material(material) {} material(material) {}
@ -69,6 +70,10 @@ public:
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture_id); 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? // TODO: Not always required (not when rendering shadows) - make functions separate?
shader.setFloat("diffuseStrength", material.diffuse); shader.setFloat("diffuseStrength", material.diffuse);
@ -80,6 +85,7 @@ public:
glm::mat4 matrix; glm::mat4 matrix;
glm::vec3 origin; glm::vec3 origin;
unsigned int texture_id; unsigned int texture_id;
unsigned int normal_id;
Mesh mesh; Mesh mesh;
float distance; float distance;
Material material; Material material;
@ -116,12 +122,13 @@ public:
Material material = materialComponent.isValid() ? materialComponent.get() : Material(); Material material = materialComponent.isValid() ? materialComponent.get() : Material();
unsigned int textureID = textureComponent.isValid() ? textureComponent->id : 0; 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 // Put it into the list of transparent render objects if the texture wants to be rendered transparently
if (textureComponent.isValid() && textureComponent->render_transparent) { 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 { } 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(); Material material = materialComponent.isValid() ? materialComponent.get() : Material();
unsigned int textureID = textureComponent.isValid() ? textureComponent->id : 0; 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 // Put it into the list of transparent render objects if the texture wants to be rendered transparently
if (textureComponent.isValid() && textureComponent->render_transparent) { 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 { } 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));
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 MiB

After

Width:  |  Height:  |  Size: 31 MiB

BIN
Resources/Grass_Normal.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 MiB

View File

@ -8,6 +8,7 @@ in mediump vec4 FragPosLightSpace;
layout(binding=0) uniform sampler2D shadowMap; layout(binding=0) uniform sampler2D shadowMap;
layout(binding=1) uniform sampler2D tex; layout(binding=1) uniform sampler2D tex;
layout(binding=2) uniform sampler2D normalmap;
uniform mediump vec3 lightDirection; uniform mediump vec3 lightDirection;
uniform mediump vec3 cameraPosition; uniform mediump vec3 cameraPosition;
@ -43,20 +44,25 @@ void main()
{ {
mediump vec4 texColor = texture(tex, TexCoord); 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 // Alpha Scissors
if(texColor.a < 0.1) if(texColor.a < 0.1)
discard; discard;
// Lighting // Lighting
// Diffuse // Diffuse
mediump float diff = max(dot(Normal, lightDirection), 0.0); mediump float diff = max(dot(final_normal, lightDirection), 0.0);
// Ambient // Ambient
mediump float ambient = 0.2; mediump float ambient = 0.2;
// Specular // Specular
mediump vec3 viewDir = normalize(cameraPosition - FragPos); 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); mediump float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);

View File

@ -118,7 +118,7 @@ int main() {
monkey->assign<Transform>(); monkey->assign<Transform>();
monkey->assign<LODObjMesh>(std::vector<ObjMesh>{ObjMesh("Resources/Monkey.obj",ObjMesh::Settings(0.0, 8.0, 0.4, 0.6)), monkey->assign<LODObjMesh>(std::vector<ObjMesh>{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))}); ObjMesh("Resources/MonkeySimple.obj", ObjMesh::Settings(8.0, 100.0, 0.4, 0.6))});
monkey->assign<Texture>("Resources/Marble.jpg", Texture::Settings(true, false)); monkey->assign<Texture>("Resources/Marble.jpg", Texture::Settings(true), false);
monkey->assign<SineAnimation>(glm::vec3(0.0, 0.3, 0.0), 0.5); monkey->assign<SineAnimation>(glm::vec3(0.0, 0.3, 0.0), 0.5);
monkey->assign<Material>(0.6, 0.6); monkey->assign<Material>(0.6, 0.6);
monkey->get<Transform>()->set_origin(glm::vec3(0.0f, 2.0f, -6.0f)); monkey->get<Transform>()->set_origin(glm::vec3(0.0f, 2.0f, -6.0f));
@ -127,7 +127,7 @@ int main() {
monkey2->assign<Transform>(); monkey2->assign<Transform>();
monkey2->assign<LODObjMesh>(std::vector<ObjMesh>{ObjMesh("Resources/Monkey.obj",ObjMesh::Settings(0.0, 8.0, 0.4, 0.6)), monkey2->assign<LODObjMesh>(std::vector<ObjMesh>{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))}); ObjMesh("Resources/MonkeySimple.obj", ObjMesh::Settings(8.0, 100.0, 0.4, 0.6))});
monkey2->assign<Texture>("Resources/Marble.jpg", Texture::Settings(true, false)); monkey2->assign<Texture>("Resources/Marble.jpg", Texture::Settings(true), false);
monkey2->assign<SineAnimation>(glm::vec3(0.0, 0.3, 0.0), 0.5); monkey2->assign<SineAnimation>(glm::vec3(0.0, 0.3, 0.0), 0.5);
monkey2->assign<Material>(0.6, 0.6); monkey2->assign<Material>(0.6, 0.6);
monkey2->get<Transform>()->set_origin(glm::vec3(-5.0f, 2.0f, -20.0f)); monkey2->get<Transform>()->set_origin(glm::vec3(-5.0f, 2.0f, -20.0f));
@ -135,21 +135,21 @@ int main() {
Entity *wall1 = world->create(); Entity *wall1 = world->create();
wall1->assign<Transform>(); wall1->assign<Transform>();
wall1->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall1->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall1->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall1->assign<Texture>("Resources/Glass.png", Texture::Settings(true), true);
wall1->assign<Material>(0.2, 0.8); wall1->assign<Material>(0.2, 0.8);
wall1->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, -2.0f)); wall1->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, -2.0f));
Entity *wall2 = world->create(); Entity *wall2 = world->create();
wall2->assign<Transform>(); wall2->assign<Transform>();
wall2->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall2->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall2->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall2->assign<Texture>("Resources/Glass.png", Texture::Settings(true), true);
wall2->assign<Material>(0.2, 0.8); wall2->assign<Material>(0.2, 0.8);
wall2->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, -10.0f)); wall2->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, -10.0f));
Entity *wall3 = world->create(); Entity *wall3 = world->create();
wall3->assign<Transform>(); wall3->assign<Transform>();
wall3->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall3->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall3->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall3->assign<Texture>("Resources/Glass.png", Texture::Settings(true), true);
wall3->assign<Material>(0.2, 0.8); wall3->assign<Material>(0.2, 0.8);
wall3->get<Transform>()->set_origin(glm::vec3(4.0f, 0.0f, -6.0f)); wall3->get<Transform>()->set_origin(glm::vec3(4.0f, 0.0f, -6.0f));
wall3->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0)); wall3->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0));
@ -157,7 +157,7 @@ int main() {
Entity *wall4 = world->create(); Entity *wall4 = world->create();
wall4->assign<Transform>(); wall4->assign<Transform>();
wall4->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings())); wall4->assign<ObjMesh>(ObjMesh("Resources/Wall.obj", ObjMesh::Settings()));
wall4->assign<Texture>("Resources/Glass.png", Texture::Settings(true, true)); wall4->assign<Texture>("Resources/Glass.png", Texture::Settings(true), true);
wall4->assign<Material>(0.2, 0.8); wall4->assign<Material>(0.2, 0.8);
wall4->get<Transform>()->set_origin(glm::vec3(-4.0f, 0.0f, -6.0f)); wall4->get<Transform>()->set_origin(glm::vec3(-4.0f, 0.0f, -6.0f));
wall4->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0)); wall4->get<Transform>()->rotate(90.0, glm::vec3(0.0, 1.0, 0.0));
@ -165,14 +165,15 @@ int main() {
Entity *ground = world->create(); Entity *ground = world->create();
ground->assign<Transform>(); ground->assign<Transform>();
ground->assign<ObjMesh>(ObjMesh("Resources/Ground.obj", ObjMesh::Settings())); ground->assign<ObjMesh>(ObjMesh("Resources/Ground.obj", ObjMesh::Settings()));
ground->assign<Texture>("Resources/Grass.jpg", Texture::Settings(true, false)); ground->assign<Texture>("Resources/Grass.jpg", Texture::Settings(true), false);
ground->get<Texture>()->addNormalmap("Resources/Grass_Normal.jpg", Texture::Settings(true));
ground->assign<Material>(1.0, 0.0); ground->assign<Material>(1.0, 0.0);
ground->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, 0.0f)); ground->get<Transform>()->set_origin(glm::vec3(0.0f, 0.0f, 0.0f));
Entity *bench = world->create(); Entity *bench = world->create();
bench->assign<Transform>(); bench->assign<Transform>();
bench->assign<ObjMesh>(ObjMesh("Resources/bench.obj", ObjMesh::Settings())); bench->assign<ObjMesh>(ObjMesh("Resources/bench.obj", ObjMesh::Settings()));
bench->assign<Texture>("Resources/Wood.jpg", Texture::Settings(true, false)); bench->assign<Texture>("Resources/Wood.jpg", Texture::Settings(true), false);
bench->assign<Material>(0.8, 0.2); bench->assign<Material>(0.8, 0.2);
bench->get<Transform>()->set_origin(glm::vec3(8.0f, 0.0f, 0.0f)); bench->get<Transform>()->set_origin(glm::vec3(8.0f, 0.0f, 0.0f));
bench->get<Transform>()->rotate(-90.0, glm::vec3(0.0, 1.0, 0.0)); bench->get<Transform>()->rotate(-90.0, glm::vec3(0.0, 1.0, 0.0));
@ -180,7 +181,7 @@ int main() {
Entity *ring = world->create(); Entity *ring = world->create();
ring->assign<Transform>(); ring->assign<Transform>();
ring->assign<ObjMesh>(ObjMesh("Resources/ring.obj", ObjMesh::Settings())); ring->assign<ObjMesh>(ObjMesh("Resources/ring.obj", ObjMesh::Settings()));
ring->assign<Texture>("Resources/Gold.jpg", Texture::Settings(true, false)); ring->assign<Texture>("Resources/Gold.jpg", Texture::Settings(true), false);
ring->assign<Material>(0.1, 0.9); ring->assign<Material>(0.1, 0.9);
ring->get<Transform>()->set_origin(glm::vec3(-5.0f, 2.0f, 0.0f)); ring->get<Transform>()->set_origin(glm::vec3(-5.0f, 2.0f, 0.0f));