3D_for_GML:_Point_lights - hpgDesigns/hpgdesigns-dev.io GitHub Wiki
In a previous tutorial we have seen that GM6 allows you to create two types of lights: point lights and directional lights. In that tutorial, directional lighting was described as many points emitting light in one direction while point lighting was described as one point emitting many rays in all directions. The code we used for directional lighting looked like this:
//define light
d3d_light_define_direction(0, 0, 0, -1, c_white);
Index, direction and color of the directional light was defined using that code.
Let’s take a look at the code to define a point light:
d3d_light_define_point(<index> ,<x>, <y>, <z>, <range>, <color>)
It should be apparent that this code is different from the directional lighting code. Again, point lights are numbered using an index (number). And yes, a color is set (last value in the code). But this time no direction is set. In stead, a location is set. This means point lights are located in one point, hence the name: point lights. The code defines a light with a certain index at a certain location using a particular color. But what about the range value? If you think about it, directional lights are endless. Every object in the 3D world is affected by the light, no matter where it is located. Not so with point lights; emitted light is limited to a distance. This distance is set by the range value. Drawn objects beyond the distance set by the range value are out of range and are not lit by the point light.
Lights are not objects. To create a point light, first create a light object, for example: obj_light. In the Create event of this object, put the code that defines the light. Maybe in an initialisation script called init_light, holding code that looks a little like this:
d3d_light_define_point(id, x, y, z, 256, c_white);
The id of the light object will be used as the index of the light defined. Same goes for the location of the light, the light will be defined at the same location. If you want to move the light, you will need to define the light again using this same code (above). Remember, you’re only defining this light in the Create event. If the light object moves, the light will still be defined at the starting point.
Point lights in GM do not look like anything. They have no shape. In fact, they are invisible. While at first this might seem strange, it is actually a good thing. It allows for creating of ambient or creative lighting. In a real movie or theater set, it is always a matter of hiding lights from the camera and/or viewers. In a virtual set lights can be placed at impossible locations without disturbing the scene. Sometimes you will want the player to see the light object itself. You could use a drawing code in the Draw event, something like:
d3d_set_lighting(false);
d3d_draw_ellipsoid(x-2, y+2, z-2, x+2, y-2, z+2, tex, 1, 1, 16);
d3d_set_lighting(true);
This draws an ellipsoid that represents the light object, without it being affected by lighting itself. It will appear as an always bright object, so to speak. Most importantly, do not use the d3d_light_define_pointcode in the draw event unless you have to. Only define when you need to change things like position, range or color. That is when you will want to use the light definition code.
Not much different from lights in the real world , lights in GM need to be switched on before emitting light. The light switch in GM looks like this:
d3d_light_enable(id, true);
This will switch the light on, allowing it to emit light. The index of the light object is used here, as you can see. So, if you have defined light number 0, use this as an index. Each light is numbered. You can use any number. We use the id of the light object as an index for the light itself. To switch a light off, use:
d3d_light_enable(id,false);
This will allow you to switch a light off, in otherwords: disabling it. This is not the same as destroying the light. It’s simply hitting the switch, like in real life. If you have used a light object to define the light, destroying the light object will not undefine the light. In other words: point lights are not destroyed when the object that created the light is destroyed. Lights are not objects. So, be sure to disable the light using the code d3d_light_enable, and then destroy the object. It might look something like this:
d3d_light_enable(id,false); //disable light
instance_destroy(); //destroy light object
Now, about the master switch. You can define lights all you like but none of them will work if lighting itself is disabled. It’s lik ehaving boats in a dried out lake. To fill the lake, use:
d3d_set_lighting(true); //use lighting
This will enable lighting for the whole game. Sometimes you will want to switch lighting off temporarily if you do not want something to be affected by lighting (see: 24.4 Drawing Lights). Finally, a word about shading. Shading is creating smooth surfaces for drawn objects when lighting is used. To set shading to true:
d3d_set_shading(true); //smooth textures when lit
Usually you will want to use shading when lighting is used because it looks so much better. Much more can be learned about lights and lighting.Next time!