Add directional lighting

Description

When we modified the height of our world, it was difficult to see what changed. Everything has the same texture and blended together into a green soup.

We can add some basic lighting to help differentiate the sides of the cubes.

We'll assume the light is coming from the sun, where it shines down at the same angle for all objects. Any faces on the cube that are facing the sun will be lit brighter than those that are not facing the sun.

These calculations happen in the fragment shader. We need to know the angle of the face, which is passed from the vertex shader. This is the surface normal.

Taking the dot product between the vector facing the sun and the surface normal will tell us how much the sun is shining on the surface. We'll discard negative values which mean the surface is facing away from the sun.

We're ignoring any cells that may obstruct the sun.

Screenshot

Commands

git clone git@github.com:atsheehan/iridium
cd iridium
git checkout 7d75e512faabae7e772bc77ca204f25ffac5a7d0
cargo run --release

Code Changes

Modified shaders/cube.fragGitHub

@@ -2,9 +2,24 @@
22
33 out vec4 color;
44 in vec2 vertex_tex_coord;
5+ in vec3 vertex_normal;
56
67 uniform sampler2D tex_sampler;
78
9+ const float PI = 3.1415926535897932384626433832795;
10+
11+ const float sun_heading = PI / 3;
12+ const float sun_pitch = PI / 3;
13+
14+ const float diffuse_factor = 0.5;
15+ const float ambient_factor = 0.5;
16+
817 void main() {
9- color = texture(tex_sampler, vertex_tex_coord);
18+ vec3 sun_direction = vec3(sin(sun_pitch) * cos(sun_heading), sin(sun_pitch) * sin(sun_heading), cos(sun_pitch));
19+
20+ vec4 frag_color = texture(tex_sampler, vertex_tex_coord);
21+ vec4 diffuse_color = frag_color * max(dot(vertex_normal, sun_direction), 0.0) * diffuse_factor;
22+ vec4 ambient_color = frag_color * ambient_factor;
23+
24+ color = diffuse_color + ambient_color;
1025 }
@@ -2,9 +2,24 @@
2
3 out vec4 color;
4 in vec2 vertex_tex_coord;
 
5
6 uniform sampler2D tex_sampler;
7
 
 
 
 
 
 
 
 
8 void main() {
9- color = texture(tex_sampler, vertex_tex_coord);
 
 
 
 
 
 
10 }
@@ -2,9 +2,24 @@
2
3 out vec4 color;
4 in vec2 vertex_tex_coord;
5+ in vec3 vertex_normal;
6
7 uniform sampler2D tex_sampler;
8
9+ const float PI = 3.1415926535897932384626433832795;
10+
11+ const float sun_heading = PI / 3;
12+ const float sun_pitch = PI / 3;
13+
14+ const float diffuse_factor = 0.5;
15+ const float ambient_factor = 0.5;
16+
17 void main() {
18+ vec3 sun_direction = vec3(sin(sun_pitch) * cos(sun_heading), sin(sun_pitch) * sin(sun_heading), cos(sun_pitch));
19+
20+ vec4 frag_color = texture(tex_sampler, vertex_tex_coord);
21+ vec4 diffuse_color = frag_color * max(dot(vertex_normal, sun_direction), 0.0) * diffuse_factor;
22+ vec4 ambient_color = frag_color * ambient_factor;
23+
24+ color = diffuse_color + ambient_color;
25 }

Modified shaders/cube.vertGitHub

@@ -11,6 +11,7 @@
1111 uniform float aspect_ratio = 1.0;
1212
1313 out vec2 vertex_tex_coord;
14+ out vec3 vertex_normal;
1415
1516 void main() {
1617 vec3 near_bottom_left = vec3(0.0, 0.0, 0.0);
@@ -86,6 +87,15 @@
8687 texture_coordinates[5] = vec2(0.0, 0.0);
8788 vertex_tex_coord = texture_coordinates[gl_VertexID % 6];
8889
90+ vec3 normals[6];
91+ normals[0] = vec3(0.0, 0.0, -1.0); // Front
92+ normals[1] = vec3(1.0, 0.0, 0.0); // Right
93+ normals[2] = vec3(0.0, 0.0, 1.0); // Far
94+ normals[3] = vec3(-1.0, 0.0, 0.0); // Left
95+ normals[4] = vec3(0.0, 1.0, 0.0); // Top
96+ normals[5] = vec3(0.0, -1.0, 0.0); // Bottom
97+ vertex_normal = normals[gl_VertexID / 6];
98+
8999 mat4 camera_translation =
90100 mat4(1.0, 0.0, 0.0, -camera_position.x,
91101 0.0, 1.0, 0.0, -camera_position.y,
@@ -11,6 +11,7 @@
11 uniform float aspect_ratio = 1.0;
12
13 out vec2 vertex_tex_coord;
 
14
15 void main() {
16 vec3 near_bottom_left = vec3(0.0, 0.0, 0.0);
@@ -86,6 +87,15 @@
86 texture_coordinates[5] = vec2(0.0, 0.0);
87 vertex_tex_coord = texture_coordinates[gl_VertexID % 6];
88
 
 
 
 
 
 
 
 
 
89 mat4 camera_translation =
90 mat4(1.0, 0.0, 0.0, -camera_position.x,
91 0.0, 1.0, 0.0, -camera_position.y,
@@ -11,6 +11,7 @@
11 uniform float aspect_ratio = 1.0;
12
13 out vec2 vertex_tex_coord;
14+ out vec3 vertex_normal;
15
16 void main() {
17 vec3 near_bottom_left = vec3(0.0, 0.0, 0.0);
@@ -86,6 +87,15 @@
87 texture_coordinates[5] = vec2(0.0, 0.0);
88 vertex_tex_coord = texture_coordinates[gl_VertexID % 6];
89
90+ vec3 normals[6];
91+ normals[0] = vec3(0.0, 0.0, -1.0); // Front
92+ normals[1] = vec3(1.0, 0.0, 0.0); // Right
93+ normals[2] = vec3(0.0, 0.0, 1.0); // Far
94+ normals[3] = vec3(-1.0, 0.0, 0.0); // Left
95+ normals[4] = vec3(0.0, 1.0, 0.0); // Top
96+ normals[5] = vec3(0.0, -1.0, 0.0); // Bottom
97+ vertex_normal = normals[gl_VertexID / 6];
98+
99 mat4 camera_translation =
100 mat4(1.0, 0.0, 0.0, -camera_position.x,
101 0.0, 1.0, 0.0, -camera_position.y,