Skip to content

Commit ea39329

Browse files
authored
Merge pull request #5032 from Sir-Irk/normalmap_example
[examples] New example: `shaders_normalmap`
2 parents c19c6fc + a06962e commit ea39329

File tree

12 files changed

+565
-0
lines changed

12 files changed

+565
-0
lines changed

examples/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ SHADERS = \
639639
shaders/shaders_mesh_instancing \
640640
shaders/shaders_model_shader \
641641
shaders/shaders_multi_sample2d \
642+
shaders/shaders_normalmap \
642643
shaders/shaders_palette_switch \
643644
shaders/shaders_postprocessing \
644645
shaders/shaders_raymarching \

examples/Makefile.Web

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ SHADERS = \
639639
shaders/shaders_mesh_instancing \
640640
shaders/shaders_model_shader \
641641
shaders/shaders_multi_sample2d \
642+
shaders/shaders_normalmap \
642643
shaders/shaders_palette_switch \
643644
shaders/shaders_postprocessing \
644645
shaders/shaders_raymarching \
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#version 100
2+
3+
precision mediump float;
4+
5+
// Input vertex attributes (from vertex shader)
6+
varying vec3 fragPosition;
7+
varying vec2 fragTexCoord;
8+
varying vec3 fragNormal; //used for when normal mapping is toggled off
9+
varying vec4 fragColor;
10+
varying mat3 TBN;
11+
12+
// Input uniform values
13+
uniform sampler2D texture0;
14+
uniform sampler2D normalMap;
15+
uniform vec4 colDiffuse;
16+
uniform vec3 viewPos;
17+
18+
// NOTE: Add your custom variables here
19+
20+
uniform vec3 lightPos;
21+
uniform bool useNormalMap;
22+
uniform float specularExponent;
23+
24+
void main()
25+
{
26+
vec4 texelColor = texture(texture0, vec2(fragTexCoord.x, fragTexCoord.y));
27+
vec3 specular = vec3(0.0);
28+
vec3 viewDir = normalize(viewPos - fragPosition);
29+
vec3 lightDir = normalize(lightPos - fragPosition);
30+
31+
vec3 normal;
32+
if (useNormalMap)
33+
{
34+
normal = texture(normalMap, vec2(fragTexCoord.x, fragTexCoord.y)).rgb;
35+
36+
//Transform normal values to the range -1.0 ... 1.0
37+
normal = normalize(normal * 2.0 - 1.0);
38+
39+
//Transform the normal from tangent-space to world-space for lighting calculation
40+
normal = normalize(normal * TBN);
41+
}
42+
else
43+
{
44+
normal = normalize(fragNormal);
45+
}
46+
47+
vec4 tint = colDiffuse * fragColor;
48+
49+
vec3 lightColor = vec3(1.0, 1.0, 1.0);
50+
float NdotL = max(dot(normal, lightDir), 0.0);
51+
vec3 lightDot = lightColor * NdotL;
52+
53+
float specCo = 0.0;
54+
55+
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
56+
57+
specular += specCo;
58+
59+
finalColor = (texelColor * ((tint + vec4(specular, 1.0)) * vec4(lightDot, 1.0)));
60+
finalColor += texelColor * (vec4(1.0, 1.0, 1.0, 1.0) / 40.0) * tint;
61+
62+
// Gamma correction
63+
gl_FragColor = pow(finalColor, vec4(1.0 / 2.2));
64+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#version 100
2+
3+
// Input vertex attributes
4+
attribute vec3 vertexPosition;
5+
attribute vec2 vertexTexCoord;
6+
attribute vec3 vertexNormal;
7+
attribute vec4 vertexTangent;
8+
attribute vec4 vertexColor;
9+
10+
// Input uniform values
11+
uniform mat4 mvp;
12+
uniform mat4 matModel;
13+
14+
// Output vertex attributes (to fragment shader)
15+
varying vec3 fragPosition;
16+
varying vec2 fragTexCoord;
17+
varying vec3 fragNormal; //used for when normal mapping is toggled off
18+
varying vec4 fragColor;
19+
varying mat3 TBN;
20+
21+
// NOTE: Add your custom variables here
22+
23+
// https://github.com/glslify/glsl-inverse
24+
mat3 inverse(mat3 m)
25+
{
26+
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
27+
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
28+
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
29+
30+
float b01 = a22 * a11 - a12 * a21;
31+
float b11 = -a22 * a10 + a12 * a20;
32+
float b21 = a21 * a10 - a11 * a20;
33+
34+
float det = a00 * b01 + a01 * b11 + a02 * b21;
35+
36+
return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),
37+
b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),
38+
b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;
39+
}
40+
41+
// https://github.com/glslify/glsl-transpose
42+
mat3 transpose(mat3 m)
43+
{
44+
return mat3(m[0][0], m[1][0], m[2][0],
45+
m[0][1], m[1][1], m[2][1],
46+
m[0][2], m[1][2], m[2][2]);
47+
}
48+
49+
void main()
50+
{
51+
// Compute binormal from vertex normal and tangent. W component is the tangent handedness
52+
vec3 vertexBinormal = cross(vertexNormal, vertexTangent.xyz) * vertexTangent.w;
53+
54+
// Compute fragment normal based on normal transformations
55+
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
56+
57+
// Compute fragment position based on model transformations
58+
fragPosition = vec3(matModel * vec4(vertexPosition, 1.0));
59+
60+
//Create TBN matrix for transforming the normal map values from tangent-space to world-space
61+
fragNormal = normalize(normalMatrix * vertexNormal);
62+
63+
vec3 fragTangent = normalize(normalMatrix * vertexTangent.xyz);
64+
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal) * fragNormal);
65+
66+
vec3 fragBinormal = normalize(normalMatrix * vertexBinormal);
67+
fragBinormal = cross(fragNormal, fragTangent);
68+
69+
TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal));
70+
71+
fragColor = vertexColor;
72+
73+
fragTexCoord = vertexTexCoord;
74+
75+
gl_Position = mvp * vec4(vertexPosition, 1.0);
76+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#version 120
2+
3+
// Input vertex attributes (from vertex shader)
4+
varying vec3 fragPosition;
5+
varying vec2 fragTexCoord;
6+
varying vec3 fragNormal; //used for when normal mapping is toggled off
7+
varying vec4 fragColor;
8+
varying mat3 TBN;
9+
10+
// Input uniform values
11+
uniform sampler2D texture0;
12+
uniform sampler2D normalMap;
13+
uniform vec4 colDiffuse;
14+
uniform vec3 viewPos;
15+
16+
// NOTE: Add your custom variables here
17+
18+
uniform vec3 lightPos;
19+
uniform bool useNormalMap;
20+
uniform float specularExponent;
21+
22+
void main()
23+
{
24+
vec4 texelColor = texture(texture0, vec2(fragTexCoord.x, fragTexCoord.y));
25+
vec3 specular = vec3(0.0);
26+
vec3 viewDir = normalize(viewPos - fragPosition);
27+
vec3 lightDir = normalize(lightPos - fragPosition);
28+
29+
vec3 normal;
30+
if (useNormalMap)
31+
{
32+
normal = texture(normalMap, vec2(fragTexCoord.x, fragTexCoord.y)).rgb;
33+
34+
//Transform normal values to the range -1.0 ... 1.0
35+
normal = normalize(normal * 2.0 - 1.0);
36+
37+
//Transform the normal from tangent-space to world-space for lighting calculation
38+
normal = normalize(normal * TBN);
39+
}
40+
else
41+
{
42+
normal = normalize(fragNormal);
43+
}
44+
45+
vec4 tint = colDiffuse * fragColor;
46+
47+
vec3 lightColor = vec3(1.0, 1.0, 1.0);
48+
float NdotL = max(dot(normal, lightDir), 0.0);
49+
vec3 lightDot = lightColor * NdotL;
50+
51+
float specCo = 0.0;
52+
53+
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
54+
55+
specular += specCo;
56+
57+
finalColor = (texelColor * ((tint + vec4(specular, 1.0)) * vec4(lightDot, 1.0)));
58+
finalColor += texelColor * (vec4(1.0, 1.0, 1.0, 1.0) / 40.0) * tint;
59+
60+
// Gamma correction
61+
gl_FragColor = pow(finalColor, vec4(1.0 / 2.2));
62+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#version 120
2+
3+
// Input vertex attributes
4+
attribute vec3 vertexPosition;
5+
attribute vec2 vertexTexCoord;
6+
attribute vec3 vertexNormal;
7+
attribute vec4 vertexTangent;
8+
attribute vec4 vertexColor;
9+
10+
// Input uniform values
11+
uniform mat4 mvp;
12+
uniform mat4 matModel;
13+
14+
// Output vertex attributes (to fragment shader)
15+
varying vec3 fragPosition;
16+
varying vec2 fragTexCoord;
17+
varying vec3 fragNormal; //used for when normal mapping is toggled off
18+
varying vec4 fragColor;
19+
varying mat3 TBN;
20+
21+
// NOTE: Add your custom variables here
22+
23+
// https://github.com/glslify/glsl-inverse
24+
mat3 inverse(mat3 m)
25+
{
26+
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
27+
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
28+
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
29+
30+
float b01 = a22 * a11 - a12 * a21;
31+
float b11 = -a22 * a10 + a12 * a20;
32+
float b21 = a21 * a10 - a11 * a20;
33+
34+
float det = a00 * b01 + a01 * b11 + a02 * b21;
35+
36+
return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),
37+
b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),
38+
b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;
39+
}
40+
41+
// https://github.com/glslify/glsl-transpose
42+
mat3 transpose(mat3 m)
43+
{
44+
return mat3(m[0][0], m[1][0], m[2][0],
45+
m[0][1], m[1][1], m[2][1],
46+
m[0][2], m[1][2], m[2][2]);
47+
}
48+
49+
void main()
50+
{
51+
// Compute binormal from vertex normal and tangent. W component is the tangent handedness
52+
vec3 vertexBinormal = cross(vertexNormal, vertexTangent.xyz) * vertexTangent.w;
53+
54+
// Compute fragment normal based on normal transformations
55+
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
56+
57+
// Compute fragment position based on model transformations
58+
fragPosition = vec3(matModel * vec4(vertexPosition, 1.0));
59+
60+
//Create TBN matrix for transforming the normal map values from tangent-space to world-space
61+
fragNormal = normalize(normalMatrix * vertexNormal);
62+
63+
vec3 fragTangent = normalize(normalMatrix * vertexTangent.xyz);
64+
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal) * fragNormal);
65+
66+
vec3 fragBinormal = normalize(normalMatrix * vertexBinormal);
67+
fragBinormal = cross(fragNormal, fragTangent);
68+
69+
TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal));
70+
71+
fragColor = vertexColor;
72+
73+
fragTexCoord = vertexTexCoord;
74+
75+
gl_Position = mvp * vec4(vertexPosition, 1.0);
76+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#version 330
2+
3+
// Input vertex attributes (from vertex shader)
4+
in vec3 fragPosition;
5+
in vec2 fragTexCoord;
6+
in vec3 fragNormal; //used for when normal mapping is toggled off
7+
in vec4 fragColor;
8+
9+
// Input uniform values
10+
uniform sampler2D texture0;
11+
uniform sampler2D normalMap;
12+
uniform vec4 colDiffuse;
13+
14+
uniform vec3 viewPos;
15+
uniform vec4 tintColor;
16+
17+
uniform vec3 lightPos;
18+
uniform bool useNormalMap;
19+
uniform float specularExponent;
20+
21+
// Output fragment color
22+
out vec4 finalColor;
23+
24+
in mat3 TBN;
25+
26+
void main()
27+
{
28+
vec4 texelColor = texture(texture0, vec2(fragTexCoord.x, fragTexCoord.y));
29+
vec3 specular = vec3(0.0);
30+
vec3 viewDir = normalize(viewPos - fragPosition);
31+
vec3 lightDir = normalize(lightPos - fragPosition);
32+
33+
vec3 normal;
34+
if (useNormalMap)
35+
{
36+
normal = texture(normalMap, vec2(fragTexCoord.x, fragTexCoord.y)).rgb;
37+
38+
//Transform normal values to the range -1.0 ... 1.0
39+
normal = normalize(normal * 2.0 - 1.0);
40+
41+
//Transform the normal from tangent-space to world-space for lighting calculation
42+
normal = normalize(normal * TBN);
43+
}
44+
else
45+
{
46+
normal = normalize(fragNormal);
47+
}
48+
49+
vec4 tint = colDiffuse * fragColor;
50+
51+
vec3 lightColor = vec3(1.0, 1.0, 1.0);
52+
float NdotL = max(dot(normal, lightDir), 0.0);
53+
vec3 lightDot = lightColor * NdotL;
54+
55+
float specCo = 0.0;
56+
57+
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
58+
59+
specular += specCo;
60+
61+
finalColor = (texelColor * ((tint + vec4(specular, 1.0)) * vec4(lightDot, 1.0)));
62+
finalColor += texelColor * (vec4(1.0, 1.0, 1.0, 1.0) / 40.0) * tint;
63+
64+
// Gamma correction
65+
finalColor = pow(finalColor, vec4(1.0 / 2.2));
66+
//finalColor = vec4(normal, 1.0);
67+
}

0 commit comments

Comments
 (0)