Skip to content

Commit c5f560a

Browse files
committed
Normal maps
1 parent 3ab1b0f commit c5f560a

9 files changed

Lines changed: 61 additions & 11 deletions

File tree

defines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ typedef double float64;
1818
struct Vertex {
1919
glm::vec3 position;
2020
glm::vec3 normal;
21+
glm::vec3 tangent;
2122
glm::vec2 textureCoord;
2223
};

mesh.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class Mesh {
3636
emissiveLocation = GLCALL(glGetUniformLocation(shader->getShaderId(), "u_material.emissive"));
3737
shininessLocation = GLCALL(glGetUniformLocation(shader->getShaderId(), "u_material.shininess"));
3838
diffuseMapLocation = GLCALL(glGetUniformLocation(shader->getShaderId(), "u_diffuse_map"));
39+
normalMapLocation = GLCALL(glGetUniformLocation(shader->getShaderId(), "u_normal_map"));
3940
}
4041
~Mesh() {
4142
delete vertexBuffer;
@@ -50,6 +51,10 @@ class Mesh {
5051
glUniform1f(shininessLocation, material.material.shininess);
5152
GLCALL(glBindTexture(GL_TEXTURE_2D, material.diffuseMap));
5253
GLCALL(glUniform1i(diffuseMapLocation, 0));
54+
GLCALL(glActiveTexture(GL_TEXTURE1));
55+
GLCALL(glBindTexture(GL_TEXTURE_2D, material.normalMap));
56+
GLCALL(glActiveTexture(GL_TEXTURE0));
57+
GLCALL(glUniform1i(normalMapLocation, 1));
5358
GLCALL(glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0));
5459
}
5560
private:
@@ -63,6 +68,7 @@ class Mesh {
6368
int emissiveLocation;
6469
int shininessLocation;
6570
int diffuseMapLocation;
71+
int normalMapLocation;
6672
};
6773

6874
class Model {
@@ -164,6 +170,9 @@ class Model {
164170
input.read((char*)&vertex.normal.x, sizeof(float));
165171
input.read((char*)&vertex.normal.y, sizeof(float));
166172
input.read((char*)&vertex.normal.z, sizeof(float));
173+
input.read((char*)&vertex.tangent.x, sizeof(float));
174+
input.read((char*)&vertex.tangent.y, sizeof(float));
175+
input.read((char*)&vertex.tangent.z, sizeof(float));
167176
input.read((char*)&vertex.textureCoord.x, sizeof(float));
168177
input.read((char*)&vertex.textureCoord.y, sizeof(float));
169178
vertices.push_back(vertex);

models/fern.bmf

9.4 KB
Binary file not shown.

shaders/basic.fs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
layout(location = 0) out vec4 f_color;
44

5-
in vec3 v_normal;
65
in vec3 v_position;
76
in vec2 v_tex_coord;
7+
in mat3 v_tbn;
88

99
struct Material {
1010
vec3 diffuse;
@@ -50,12 +50,17 @@ uniform DirectionalLight u_directional_light;
5050
uniform PointLight u_point_light;
5151
uniform SpotLight u_spot_light;
5252
uniform sampler2D u_diffuse_map;
53+
uniform sampler2D u_normal_map;
5354

5455
void main()
5556
{
5657
// Vector from fragment to camera (camera always at 0,0,0)
5758
vec3 view = normalize(-v_position);
58-
vec3 normal = normalize(v_normal);
59+
60+
// Normal from normal map
61+
vec3 normal = texture(u_normal_map, v_tex_coord).rgb;
62+
normal = normalize(normal * 2.0 - 1.0f);
63+
normal = normalize(v_tbn * normal);
5964

6065
vec4 diffuseColor = texture(u_diffuse_map, v_tex_coord);
6166
if(diffuseColor.w < 0.9) {

shaders/basic.vs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
layout(location = 0) in vec3 a_position;
44
layout(location = 1) in vec3 a_normal;
5-
layout(location = 2) in vec2 a_tex_coord;
5+
layout(location = 2) in vec3 a_tangent;
6+
layout(location = 3) in vec2 a_tex_coord;
67

7-
out vec3 v_normal;
88
out vec3 v_position;
99
out vec2 v_tex_coord;
10+
out mat3 v_tbn;
1011

1112
uniform mat4 u_modelViewProj;
1213
uniform mat4 u_modelView;
@@ -15,7 +16,14 @@ uniform mat4 u_invModelView;
1516
void main()
1617
{
1718
gl_Position = u_modelViewProj * vec4(a_position, 1.0f);
18-
v_normal = mat3(u_invModelView) * a_normal;
19+
20+
vec3 t = normalize(mat3(u_invModelView) * a_tangent);
21+
vec3 n = normalize(mat3(u_invModelView) * a_normal);
22+
t = normalize(t - dot(t, n) * n); // Reorthogonalize with Gram-Schmidt process
23+
vec3 b = normalize(mat3(u_invModelView) * cross(n, t));
24+
mat3 tbn = transpose(mat3(t, b, n)); // transpose is equal to inverse in this case
25+
v_tbn = tbn;
26+
1927
v_position = vec3(u_modelView * vec4(a_position, 1.0f));
2028
v_tex_coord = a_tex_coord;
2129
}

shaders_old/basic.fs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#version 120
22

3-
varying vec3 v_normal;
43
varying vec3 v_position;
54
varying vec2 v_tex_coord;
5+
varying mat3 v_tbn;
66

77
struct Material {
88
vec3 diffuse;
@@ -48,11 +48,17 @@ uniform DirectionalLight u_directional_light;
4848
uniform PointLight u_point_light;
4949
uniform SpotLight u_spot_light;
5050
uniform sampler2D u_diffuse_map;
51+
uniform sampler2D u_normal_map;
5152

5253
void main()
5354
{
55+
// Vector from fragment to camera (camera always at 0,0,0)
5456
vec3 view = normalize(-v_position);
55-
vec3 normal = normalize(v_normal);
57+
58+
// Normal from normal map
59+
vec3 normal = texture2D(u_normal_map, v_tex_coord).rgb;
60+
normal = normalize(normal * 2.0 - 1.0f);
61+
normal = normalize(v_tbn * normal);
5662

5763
vec4 diffuseColor = texture2D(u_diffuse_map, v_tex_coord);
5864
if(diffuseColor.w < 0.9) {

shaders_old/basic.vs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
attribute vec3 a_position;
44
attribute vec3 a_normal;
5+
attribute vec3 a_tangent;
56
attribute vec2 a_tex_coord;
67

7-
varying vec3 v_normal;
88
varying vec3 v_position;
99
varying vec2 v_tex_coord;
10+
varying mat3 v_tbn;
1011

1112
uniform mat4 u_modelViewProj;
1213
uniform mat4 u_modelView;
@@ -15,7 +16,14 @@ uniform mat4 u_invModelView;
1516
void main()
1617
{
1718
gl_Position = u_modelViewProj * vec4(a_position, 1.0f);
18-
v_normal = mat3(u_invModelView) * a_normal;
19+
20+
vec3 t = normalize(mat3(u_invModelView) * a_tangent);
21+
vec3 n = normalize(mat3(u_invModelView) * a_normal);
22+
t = normalize(t - dot(t, n) * n); // Reorthogonalize with Gram-Schmidt process
23+
vec3 b = normalize(mat3(u_invModelView) * cross(n, t));
24+
mat3 tbn = transpose(mat3(t, b, n)); // transpose is equal to inverse in this case
25+
v_tbn = tbn;
26+
1927
v_position = vec3(u_modelView * vec4(a_position, 1.0f));
2028
v_tex_coord = a_tex_coord;
2129
}

tools/modelexporter.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct BMFMaterial {
3434
struct Mesh {
3535
std::vector<Position> positions;
3636
std::vector<Position> normals;
37+
std::vector<Position> tangents;
3738
std::vector<Position2D> uvs;
3839
std::vector<uint32_t> indices;
3940
int materialIndex;
@@ -57,6 +58,12 @@ void processMesh(aiMesh* mesh, const aiScene* scene) {
5758
normal.z = mesh->mNormals[i].z;
5859
m.normals.push_back(normal);
5960

61+
Position tangent;
62+
tangent.x = mesh->mTangents[i].x;
63+
tangent.y = mesh->mTangents[i].y;
64+
tangent.z = mesh->mTangents[i].z;
65+
m.tangents.push_back(tangent);
66+
6067
Position2D uv;
6168
assert(mesh->mNumUVComponents > 0);
6269
uv.x = mesh->mTextureCoords[0][i].x;
@@ -157,7 +164,7 @@ int main(int argc, char** argv) {
157164
}
158165

159166
Assimp::Importer importer;
160-
const aiScene* scene = importer.ReadFile(argv[argc-1], aiProcess_PreTransformVertices | aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph | aiProcess_JoinIdenticalVertices | aiProcess_ImproveCacheLocality);
167+
const aiScene* scene = importer.ReadFile(argv[argc-1], aiProcess_PreTransformVertices | aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph | aiProcess_JoinIdenticalVertices | aiProcess_ImproveCacheLocality | aiProcess_CalcTangentSpace);
161168
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE, !scene->mRootNode) {
162169
std::cout << "Error while loading model with assimp: " << importer.GetErrorString() << std::endl;
163170
return 1;
@@ -212,6 +219,10 @@ int main(int argc, char** argv) {
212219
output.write((char*)&mesh.normals[i].y, sizeof(float));
213220
output.write((char*)&mesh.normals[i].z, sizeof(float));
214221

222+
output.write((char*)&mesh.tangents[i].x, sizeof(float));
223+
output.write((char*)&mesh.tangents[i].y, sizeof(float));
224+
output.write((char*)&mesh.tangents[i].z, sizeof(float));
225+
215226
output.write((char*)&mesh.uvs[i].x, sizeof(float));
216227
output.write((char*)&mesh.uvs[i].y, sizeof(float));
217228
}

vertex_buffer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ struct VertexBuffer {
1717
glEnableVertexAttribArray(1);
1818
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(struct Vertex,normal));
1919
glEnableVertexAttribArray(2);
20-
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(struct Vertex,textureCoord));
20+
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(struct Vertex,tangent));
21+
glEnableVertexAttribArray(3);
22+
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(struct Vertex,textureCoord));
2123

2224
glBindVertexArray(0);
2325
}

0 commit comments

Comments
 (0)