# Rim Lighting

Rim lighting is a very beautiful effect that you can use to enhance your overall lighting in your 3D scene. To get this effect in a photo or in real life you must have some lights behind your objects and your view direction must be in front of this object, for this reason in some books or other website you will find it named as **back-lighting. **The special power of Rim lighting is that it creates, as the name implies, a bright contour around the lit object. Now you know that proverb “A picture is worth a thousand words”, so this is the effect that I’m talking about in photography:

And this is the OpenGL scene that I created with Rim lighting (just look at the trees). To implement the rim lighting effect in your 3D scene is very simple, you only need surface Normals, in this case trees normals and the View direction which you already have from a reflection lighting model (I talked about them here).

The easiest way to explain how Rim lighting works in a 3D environment is to rely once again on Lambert’s cosine law with light direction changed by the view direction:

In the image above, we don’t use light direction to get the rim lighting but I just added it to see the concept. Now we know that the dot product of two orthogonal vectors is *0.0* because they form a *90 *degrees angle and cosine of *90 *is equal to *0.0*. The problem is that we actually need that dot product to be *1.0 *instead of *0.0* when we create the rim effect (to brighten the contour). So we can subtract the dot product result from *1.0*:

The only thing left to discuss about Rim lighting implementation is the contribution of light on the surface of the object. There are a couple of ways to deal with this. We can use an **if-else-if** statemant or a **pow** function or a **smoothstep** function. The last two can create a nice cutoff and give some really nice results.

I enhanced my scene by using a lateral diffuse light. In the pictures below I separate the rim and diffuse lights just to see how they behave by themselves (click on the image to enlarge). By the way the ground here is rendered with the same rim lighting shader. Also I introduced a higher gamma to get a dark image. The sun object is rendered with another shader with only ambient and diffuse lighting.

Now let’s see the vertex shader:

#version 330 layout(location = 0) in vec3 in_position; layout(location = 1) in vec3 in_normal; layout(location = 2) in vec2 in_texcoord; uniform mat4 model_matrix, view_matrix, projection_matrix; out vec3 world_pos; out vec3 world_normal; out vec2 texcoord; void main() { //convert in world coords world_pos = mat3(model_matrix) * in_position;//careful here world_normal = normalize(mat3(model_matrix) * in_normal); texcoord = in_texcoord; gl_Position = projection_matrix * view_matrix * model_matrix * vec4(in_position, 1); }

And fragment shader:

#version 330 layout(location = 0) in vec3 in_position; layout(location = 1) in vec3 in_normal; layout(location = 2) in vec2 in_texcoord; uniform mat4 model_matrix, view_matrix, projection_matrix; out vec3 world_pos; out vec3 world_normal; out vec2 texcoord; void main() { //convert in world coords world_pos = mat3(model_matrix) * in_position;//careful here world_normal = normalize(mat3(model_matrix) * in_normal); texcoord = in_texcoord; gl_Position = projection_matrix * view_matrix * model_matrix * vec4(in_position, 1); }

To enhance your scene even more you can add fog or light shafts. Also a skybox can be added to create a complete scene.

Source code: