How can I use my normal maps ?
Before we start, know that I decided to write the most complete documentation possible on this subject because there was none before. Thus, I studied, tested and described every solution I found across my research and my experiments. If I still recommend you to read this whole page, I can also save you some time : The best available effect is the Matriax's one. Feel free to directly read its part and disregard the others. However, remember that we never know too much.
Pode's effect : Because it's the first one
Let’s start by what I personally consider the fundament and the first attempt of dynamic lighting in C2 (even if this last statement is abusive) :
The 2D dynamic lighting effect was created by Pode around 2012. This effect is an adaptation of Matt Greer's work regarding 2D dynamic lighting for 2D games engine on our beloved Construct 2. His work is described there. The effect itself is downloadable there. Pode’s solution is basic yet effective.
Please note that it allows you to create one single light source only. Once you have your sprite and its normal map together, you must apply the effect on the normal map, as explained in the previous chapter.
Then, you must set various parameters. You have the Image Color, knowing that higher-value corresponds to darker shadows. In the current version, you need to set all 3 channels to the same color. You can set the light direction with the same values than the screenshot above. The XYZ vectors set the position of the light over your texture. Note that lower Z = ligther shadows.
For instance, you can set the value of the (X,Y,Z) light position like this :
The yellow square is your light source, and it's going to follow your cursor, always facing the center of your sprite. For that, we use an invisible red square placed at the center of the scene. The light is always going to face it.
Of course, you’re not forced to use the red square, you can also use the sprite itself as the object faced by the light, or any image point. You’re not even forced to do that. In the current example, this “light source is always facing stuff” is important because it uses the cosinus and the sinus of the angle “k” to set its lighting. However, it’s certainly possible to proceed differently to avoid that.
I currently don’t know how, though.
The BumpMapping Effect : Because it's there
And now, to finish this one light part, here’s the last interesting effect. The BumpMapping effect. As a pre-installed effect in Construct 2 you can already use it without installing anything else, although you still need a normal map.
Hold on. According to the effect’s name, it works with a bump map. First, what the hell is a bump map, second, why do we use a normal map in that case ?
I assume that nobody really cares in fact. But once again, because a game maker is supposed to know what he's using and what he's doing, I highly recommend you to read this little article on this little blog.
Actually, the effect works with bump map and normal map anyway. The procedure is, once again, exactly the same as before. You have your sprite. Then its normal map. You set the effect on the normal map. You set the parameters related to the effect and so on…
These parameters are pretty simple there. Light direction on X, light direction on Y, light direction on Z and finally, the intensity of the light. It’s very similar to the effect created by Pode, but here, the light doesn’t need to face the center of your sprite every time, so you can easily illuminate several objects at once !
The maths for aligning the light with the bumpmapping effect is totally hacked. I'm sure it could be done much better, I've not looked into the effect properly yet (not even looked at the code for the 'Ghost Shooter' effects demo) says AdamD.
As you may understand, the following event sheet might be obsolete.
It works, but it’s odd.
Now, you know three different alternatives to use dynamic lighting in your games. But you can’t use more than one light source for the moment, which is sad. Actually, it’s possible to use several light sources, but in that case, we would have to modify one of the previous effects by adding various variables.
For example, for each possible light source, you need to set their X, Y and Z vectors, their intensity, maybe their color and stuff. In their current version, you are limited to one single light source anyway. What can we do ?
Matriax's effect : Because perfection does exist
At this point, you have seen three ways to dynamically enlighten your world.
As you have learned, they all work with the same concept, based on two main objects : a diffuse map and a normal map, placed together, one above the other. Matriax’s effect is not different. It uses the same ingredients to work properly.
But. NormalMap Extented is (currently) the best way to deal with dynamic lighting in Construct 2. Yes, I said it. Once again, the effect is similar to Pode’s one, but with a better rendering and…the possibility to use three light source.
You can customize the lighting of each light sources at will. If you want to set the first source much brighter than the others and to color the light of the third one in red, you will have no problem. You can download the effect here.
A demo capX is included, but let’s test it with the real test subject of this tutorial : Cloud Strife. Don’t worry, he likes it. I asked him. Let’s see the results :
I let you judge. To achieve this, you must do the usual procedure (diffuse map, normal map, activate effect on the normal map and blabla…) and then take care of several options. These options are what I mentioned earlier. You have three light sources, so you must set up all the variables that define them.
Let’s take a look at it.
You can now observe the various variables which are required to define one light source in this effect. As stated in the first field, this screenshot shows the variables of the second light source. You can enable or disable it by entering 1 or 0 in this same field. You can define the light on the three vectors XYZ.
The next three variables allow you to define the color of your light thanks to the RGB color model. It's an additive color model in which red, green, and blue light are added together in various ways to reproduce a broad array of colors. In others words, by adjusting the values of each color, you can create one.
The Light luminosity speaks for itself, it’s the intensity of your light.
Four other variables are there to define the ambient luminosity. In brief, the light itself is the luminosity applied on any object near your light sources, while the ambient light is the luminosity on the whole layer. There again, you can set the color you want and the intensity you want for this ambient lighting.
The three last variables define the behavior of your light. The size of the halo in the middle, its entire luminosity (greater is darker) and finally, the light distance. Because you have three light sources, you’ll have to set these variables three times. You don’t have to take care of the center of your objects or any stuff like that here, unlike Pode’s effect. You can set multiple lights, with multiple objects with ease. Now, for the events, everything is kind of simple.
The particularity is that you need to put the window resolution to all the normal maps used to get the light in the desired point. In other words, you must set the parameters like this for your lights :
For X = (LayerToCanvasX(0, "YourObject".x, "YourObject".y))/WindowWidth
For Y = (LayerToCanvasY(0, "YourObject".x, "YourObject".y))/WindowHeight
Note : when using this effect, the preview doesn’t work properly with Firefox. We honestly don’t know why, but everything is perfectly fine with any other browser, so when you want to test your work, just choose Chrome or Opera.
Conclusion : Well ! The presentation of the principal alternatives (currently) available on Construct 2 for the implementation of dynamic lighting is now over. I personally recommend Normal Map Extented by Matriax, because it’s the most complete one, of course. I wanted to write a kind of official documentation about this special lighting, so I decided to present everything I knew about it. As I said, for your own project, you should probably focus on the last effect.
In any case, you’re free to choose the one you need. It’s possible to modify any of these effects to create a new alternative enable to provide more than three light sources, of course. This tutorial (currently) doesn’t take account of that.
According to your choice, you'll have to design your level for one single light source or maximum three. In the future, this tutorial will have a part which will focus on the appropriate procedure to modify one of the effects…certainly the last one.
Random creation on Construct 2 using Matriax's effect :
[page="And God said
Let there be light"]
And God said
Let there be light
It’s time for you to do some experiments. This is the practical part of my tutorial. Here we're going to study a simple way to implement effective dynamic lighting in a very basic platformer game. First of all, we need a level. This is our beautiful level, made with Paint in less than three minutes.
Here, we want to add two light sources, so we will use the Matriax’s effect. Knowing that it's the best effect we can use for the moment, it's not a big surprise anyway. Now, we need to find a character. This is Bob. Bob will be our character. Bob is our test subject this time instead of Cloud Strife.
Bob is happy.
Bob is currently chilling on my desk. He doesn’t understand my amazing wallpaper, and certainly not where the hell he is. We need to implement him in our awful 2D world as soon as possible. You’re supposed to know the fundamentals of Construct 2, thus I will not explain how to implement the level and Bob. As the idea is to stay basic, I give the Solid behavior to every platform of this little level and the platform behavior to Bob. Here we are.
Bob is happy.
We have a world and a living thing on it. Next step : the normal maps. We want to illuminate Bob and his dull environment, so we need four normal maps. Indeed, the level has three platforms plus Bob himself. Our scene has four pieces.
Warning : You must work with pieces. Never ever try to generate the normal map for the whole level at once. You'll lose in quality and details, and it will be extremely difficult to edit the rendering of your platforms or surfaces if they're all agglomered together. It's really important to split your environment into various pieces and then work with those pieces. You can link the resulting normal maps to their sprites afterwards, in Construct 2. For instance :
To make my random creation, I didn't create one single normal map for the whole scenery, but six little ones. I insist on the notion of parts. The environment of this random level is composed of various red, white or black elements. I didn't create a normal map for each element of my 2D scenery, but for each part of it. Keep the difference in mind. Back to Bob's world.
By using one of the five tools described earlier, generate your normal maps then add them in the game. Create a family dedicated to them, then give the NormalMap extented effect to this family. Configure the options this way :
Make sure that every single normal map has the exact same size than its diffuse counterpart and the same position in the scenery. In the events sheet, don't forget to set the position of the normal map related to Bob like this :
Add two other sprites which are going to be used as our light sources now. I use two little squares called LightOne and LightTwo. Give them the Drag&Drop behavior, then in your event sheet, proceed like you did in the previous page :
Note that we haven't worked on more than one sprite until now (minus our little light sources). The situation is quite different, and if you launch the preview of your work, you should obtain an atrocity similar to this one right there :
The strange magenta background of your normal maps is roughly what will become penumbra once the effect is activated. All your normal maps currently have this magenta background, and so have their own penumbras, which is completely useless and ugly. We must fix this mess. And this takes less than five seconds in Paint or Photoshop. For example, here's a correct normal map :
And once we replaced all our normal maps in the game by the fixed ones...
...everything looks fine. The tests are conclusive, now we just have to replace these two colored squares by our real light sources which implies nothing but slight modifications in the events sheet. Let’s change the opacity of the lamps too. And here we are :