Lights

In this tutorial we will be using the Maya camera from the Cameras tutorial. Note that this tutorial does not cover volumetric lighting using GB.Scene.VolumeLightSceneNode or creating shadows using GB.Scene.ShadowVolumeSceneNode. The following topics are covered:

  1. Creating a project
  2. Lighting material flag of models
  3. Global illumination (Ambient lighting)
  4. GB.Scene.LightSceneNode lights

The tutorial's code files and media files are installed along with Ginjo-Builder and can be accessed from the 'Project' window that is shown when the editor starts. This tutorial is called '05_Lights' in the 'Tutorials' tab.

1. Creating a project

First we create a project and compiler options XML file. (See Render loop for a more detailed description of creating a project.)

  1. Create a new project through the Project menu.
  2. Right click on project's top level tree node named "New GBP(Unsaved)" and select Rename folder. Rename the folder to "Lights".
  3. Save the project as "LightsProject.gbp" from the Project menu.
  4. Add a new file to the project tree and save it as "scenelighting.gbc"
  5. Add a new file to the project tree and save it as "Lights.xml". (The XML file must have the same name as the top level tree node.)

Open "Lights.xml" and just like in Render loop add the <exe> and <startup> elements. We will also import the GB namespace so we don't have to type it out every time. (For the full list of XML tags see Compiler options.)

<?xml version="1.0" encoding="utf-8"?>
<root>
   <exe path=".\game.exe" />
   <startup name="scenelighting.main" />
   
   <ImportSymbols>
      <namespace name="GB"  />
   </ImportSymbols>
</root>

2. Lighting material flag of models

In our XML file we specified the startup function as "scenelighting.main". Double-click on "scenelighting.gbc" in the project tree to open it, and add the "main" function from the Cameras tutorial and use the Maya camera so that the camera moves based on the mouse movement. As in the previous tutorial we initialize the Irrlicht engine, add the drone model and the render loop. However, this time around we comment out the line where we set the Lighting material flag of the model to false.

function main(var:string cmdArgs[]) returns Int32
{
   var:gb.IrrlichtCreationParameters options=new gb.IrrlichtCreationParameters()
   //Without anti-aliasing our model edges would be jagged 
   options.AntiAliasing=255
   //Tell Irrlicht to use OpenGL for graphics
   options.DriverType=gb.video.DriverType.OpenGL
   //Turn off logging, we won't be using it for now
   options.LoggingLevel=gb.LogLevel.None
   
   var:gb.IrrlichtDevice engine = gb.IrrlichtDevice.CreateDevice(options)
   //Also set our window's title
   engine.SetWindowCaption('Lighting the scene')
   
   var:video.VideoDriver driver=engine.VideoDriver
   var:Scene.SceneManager smgr=engine.SceneManager

   //add camera 
   var:core.Vector3Df position=new gb.core.Vector3Df(0, 60, -180)
   var:core.Vector3Df lookat=new gb.core.Vector3Df(10, 10, 0)
   var:CameraSceneNode camera = smgr.AddCameraSceneNodeMaya()
   camera.Position=position
   camera.Target=lookat
   
   //load model from relative path ..\media\GlobalHawk.obj 
   var:scene.Mesh drone = smgr.GetMesh('..\media\GlobalHawk.obj')
   //add model to scene 
   var:Scene.MeshSceneNode droneNode = smgr.AddMeshSceneNode(drone)
   if(!isNull(droneNode)){
      droneNode.Position=new gb.core.Vector3Df(0, 0, 0)
      droneNode.Rotation=new gb.core.Vector3Df(0, 45, 0)
      droneNode.Scale=new gb.core.Vector3Df(0.2, 0.2, 0.2)
         //THIS LINE COMMENTED OUT:
      //droneNode.SetMaterialFlag(gb.video.MaterialFlag.Lighting, false)
    }
	
    var:video.Color background=new video.Color(160, 160, 160)
    while (engine.Run()){
        driver.BeginScene(video.ClearBufferFlag.All, background)
        smgr.DrawAll()
        driver.EndScene()
    }
}

When you run the program you will now see a completely black model:

3. Global illumination (Ambient lighting)

Global illumination in Irrlicht is accomplished with ambient lighting. An ambient light source models how light can be scattered or reflected many times producing a uniform lighting effect. It is a fixed-intensity and fixed-color light source that affects all objects in the scene equally. Upon rendering, all objects in the scene are brightened with the specified intensity and color. To add ambient light to the scenes specify the scene managers ambient light property using GB.Scene.SceneManager.AmbientLight:

smgr.AmbientLight=new gb.video.Colorf(0.96, 0.96, 0.96)

Note that you can use the IntelliDoc Symbol Info feature to look-up symbol types and definitions. The 'lightbulb' button on the toolbar looks-up the symbol type for the current cursor location and displays it in a tooltip. Pressing F1 also shows the tooltip.

Now when you run the program you will see a completely black model just like before. Materials in the real world do not reflect light uniformly, and the Irrlicht engine takes that into account. We need to specify how the model's materials reflect light. Modify to drones block of code as follows:

if(!isNull(droneNode)){
   droneNode.Position=new gb.core.Vector3Df(0, 0, 0)
   droneNode.Rotation=new gb.core.Vector3Df(0, 45, 0)
   droneNode.Scale=new gb.core.Vector3Df(0.2, 0.2, 0.2)
   for(var:Int32 i=0; i<droneNode.MaterialCount; i+=1){
      droneNode.GetMaterial(i).AmbientColor=new gb.video.Color(255,255,255)
   }
}

Now when you run the program you should see the model.

4. GB.Scene.LightSceneNode lights

The GB.Scene.LightSceneNode supports three types of lights: point, directional and spot lights. We will discuss each in turn, but first we need to modify how much of the ambient light is reflected by the model's materials. In the previous section we set it to reflect completely. However, we need to lower the reflective color, otherwise the model is fully illuminated and we won't see the effects of the light source we are going to add. Change the line that sets the ambient color of the model's materials to the following:

droneNode.GetMaterial(i).AmbientColor=new gb.video.Color(220,220,220)

The default light type for the GB.Scene.LightSceneNode is Video.LightType.Point. A LightSceneNode can be configured using it's LightData property. However, in this tutorial we will be using the default settings for the most part.

Video.LightType.Point

A point light produces light in all directions, thus the Rotation and Direction values of the LightData property are meaningless. Add the following lines of code after the drone's code, but before the render loop:

var:scene.LightSceneNode light=smgr.AddLightSceneNode(droneNode, new core.Vector3Df(100))
light.LightType=gb.video.LightType.Point
light.LightData.DiffuseColor=new video.Colorf(0.96, 0.96, 0.96, 0.6)
light.Radius=70

When you run the program you should see that the light, which is at position core.Vector3Df(100) relative to the drone illuminates the model. Rotate the model by holding down the left mouse button and moving the mouse. Try changing the Radius of the light to 1 and run the program again.

Video.LightType.Directional

A directional light illuminates all objects equally from a given direction, like an area light of infinite size and infinite distance from the scene. The direction of the light can be changed using the Rotation property. Replace the point light code with the following:

var:scene.LightSceneNode light=smgr.AddLightSceneNode(droneNode, new core.Vector3Df(100))
light.LightType=gb.video.LightType.Directional
light.LightData.DiffuseColor=new video.Colorf(0.96, 0.96, 0.96, 0.6)
light.Rotation=new core.Vector3Df(100)

Video.LightType.Spot

Light from a spotlight originates from a single point and spreads outward in a cone shape in a given direction. The direction of a spotlight is calculated from its rotation. Spot lights have a bright inner cone and a larger outer cone (both defined by an angle), with the brightness of the light decreasing gradually from the inner cone to the outer cone. Replace the previously added lighting code with the following:

var:scene.LightSceneNode light=smgr.AddLightSceneNode(droneNode, new core.Vector3Df(200,200,100))
light.LightType=gb.video.LightType.Spot
light.LightData.DiffuseColor=new video.Colorf(0.4, 0, 0, 0.1)
light.Rotation=new core.Vector3Df(0,-140,-300)
light.LightData.OuterCone=30
light.LightData.InnerCone=5

When you run the program you should see that the red light, which is at position core.Vector3Df(100) relative to the drone illuminates the model.