Adding lights and shadows

Lights and shadows are very important techniques for producing a great presentation. Proper scene lighting sets the mood and also adds depth to an otherwise flat-looking scene, while shadows add more realism, and more importantly, root the shadow-casting objects to the ground, destroying the impression of models floating in mid-air.

This recipe will show you how to add lights to your game scenes and make objects cast shadows to boost your visuals.

Getting ready

You need to create the setup presented in Setting up the game structure found in Chapter 1, Setting Up Panda3D and Configuring Development Tools before proceeding, as this recipe continues and builds upon this base code.

How to do it...

This recipe consists of these tasks:

  1. Add the following code to Application.py:
    from direct.showbase.ShowBase import ShowBase
    from direct.actor.Actor import Actor
    from panda3d.core import *
    class Application(ShowBase):
    def __init__(self):
    ShowBase.__init__(self)
    self.panda = Actor("panda", {"walk": "panda-walk"})
    self.panda.reparentTo(render)
    self.panda.loop("walk")
    cm = CardMaker("plane")
    cm.setFrame(-10, 10, -10, 10)
    plane = render.attachNewNode(cm.generate())
    plane.setP(270)
    self.cam.setPos(0, -40, 6)
    ambLight = AmbientLight("ambient")
    ambLight.setColor(Vec4(0.2, 0.1, 0.1, 1.0))
    ambNode = render.attachNewNode(ambLight)
    render.setLight(ambNode)
    dirLight = DirectionalLight("directional")
    dirLight.setColor(Vec4(0.1, 0.4, 0.1, 1.0))
    dirNode = render.attachNewNode(dirLight)
    dirNode.setHpr(60, 0, 90)
    render.setLight(dirNode)
    pntLight = PointLight("point")
    pntLight.setColor(Vec4(0.8, 0.8, 0.8, 1.0))
    pntNode = render.attachNewNode(pntLight)
    pntNode.setPos(0, 0, 15)
    self.panda.setLight(pntNode)
    sptLight = Spotlight("spot")
    sptLens = PerspectiveLens()
    sptLight.setLens(sptLens)
    sptLight.setColor(Vec4(1.0, 0.0, 0.0, 1.0))
    sptLight.setShadowCaster(True)
    sptNode = render.attachNewNode(sptLight)
    sptNode.setPos(-10, -10, 20)
    sptNode.lookAt(self.panda)
    render.setLight(sptNode)
    render.setShaderAuto()
    
  2. Start the program with the F6 key. You will see the following scene:
How to do it...

How it works...

As we can see when starting our program, the panda is lit by multiple lights, casting shadows onto itself and the ground plane. Let's see how we achieved this effect.

After setting up the scene containing our panda and a ground plane, one of each possible light type is added to the scene. The general pattern we follow is to create new light instances before adding them to the scene using the attachNewNode() method. Finally, the light is turned on with setLight(), which causes the calling object and all of its children in the scene graph to receive light. We use this to make the point light only affect the panda but not the ground plane.

Shadows are very simple to enable and disable by using the setShadowCaster() method, as we can see in the code that initializes the spotlight.

The line render.setShaderAuto() enables the shader generator, which causes the lighting to be calculated pixel perfect. Additionally, for using shadows, the shader generator needs to be enabled. If this line is removed, lighting will look coarser and no shadows will be visible at all.

Note

Watch the amount of lights you are adding to your scene! Every light that contributes to the scene adds additional computation cost, which will hit you if you intend to use hundreds of lights in a scene! Always try to detect the nearest lights in the level to use for lighting and disable the rest to save performance.

There's more...

In the sample code, we add several types of lights with different properties, which may need some further explanation.

Ambient light sets the base tone of a scene. It has no position or direction—the light color is just added to all surface colors in the scene, which avoids unlit parts of the scene to appear completely black. You shouldn't set the ambient color to very high intensities. This will decrease the effect of other lights and make the scene appear flat and washed out.

Directional lights do not have a position, as only their orientation counts. This light type is generally used to simulate sunlight—it comes from a general direction and affects all light-receiving objects equally.

A point light illuminates the scene from a point of origin from which light spreads towards all directions. You can think of it as a (very abstract) light bulb.

Spotlights, just like the headlights of a car or a flashlight, create a cone of light that originates from a given position and points towards a direction. The way the light spreads is determined by a lens, just like the viewing frustum of a camera.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset