Panda3D Manual: Lighting
  <<prev top next>>     

Panda3D defines four different kinds of light objects: point, directional, ambient, and spotlight. Each kind of light has a slightly different effect when it is enabled; the differences between the lights are discussed below.

Each light is a node that should be attached somewhere within the scene graph. All lights have a color, which is specified by light.setColor(VBase4(r, g, b, a)). The default color is full white: setColor(VBase4(1, 1, 1, 1)). The alpha component is largely irrelevant.

Most lights also have a position and/or orientation, which is determined by the basic scene graph operations like setPos(), setHpr(), etc. The lookAt() method is particularly useful for pointing spotlights and directional lights at a particular object.

Note that, unlike a real, physical light bulb, the light objects are not themselves directly visible. Although you can't see a Panda light itself, you can see the effect it has on the geometry around it. If you want to make a light visible, one simple trick is to load a simple model (like a sphere) and parent it directly to the light itself.

In general, you can create a light and add it into the scene graph like any other node. However, because of a problem with multiple inheritance, for the moment you have to call upcastToPandaNode() to put a light in the scene graph, like this:

dlight = DirectionalLight('dlight')
dlnp = render.attachNewNode(dlight.upcastToPandaNode())

If you forget to use upcastToPandaNode(), Panda will almost certainly crash. Note that this will no longer be true in Panda3D 1.1. In version 1.1, you can treat the light as an ordinary node without having to upcast it first.

Simply creating the light and putting it in the scene graph doesn't, by itself, have any visible effect. In order to turn the light on, you have to first decide which object or objects will be illuminated by the light. To do this, use the nodePath.setLight() method, which turns on the light for the indicated NodePath and everything below it in the scene graph.

In the simplest case, you want all of your lights to illuminate everything they can, so you turn them on at render, the top of the scene graph:

render.setLight(dlnp)

To turn the light off again, you can remove the light setting from render:

render.clearLight(dlnp)

You could also apply the setLight() call to a sub-node in the scene graph, so that a given light only affects a particular object or group of objects.

Note that there are two (or more) different NodePaths involved here: the NodePath of the light itself, which defines the position and/or orientation of the light, and the NodePath(s) on which you call setLight(), which determines what subset of the scene graph the light illuminates. There's no requirement for these two NodePaths to be related in any way.

Point Lights

Point lights are the easiest kind of light to understand: a point light simulates a light originating from a single point in space and shining in all directions, like a very tiny light bulb. A point light's position is important, but its orientation doesn't matter.

plight = PointLight('plight')
plight.setColor(VBase4(0.2, 0.2, 0.2, 1))
plnp = render.attachNewNode(plight.upcastToPandaNode())
plnp.setPos(10, 20, 0)
render.setLight(plnp)

Directional Lights

A directional light is an infinite wave of light, always in the same direction, like sunlight. A directional light's position doesn't matter, but its orientation is important. The default directional light is shining down the forward (+Y) axis; you can use nodePath.setHpr() or nodePath.lookAt() to rotate it to face in a different direction.

dlight = DirectionalLight('dlight')
dlight.setColor(VBase4(0.8, 0.8, 0.5, 1))
dlnp = render.attachNewNode(dlight.upcastToPandaNode())
dlnp.setHpr(0, -60, 0)
render.setLight(dlnp)

Ambient Lights

An ambient light is used to fill in the shadows on the dark side of an object, so it doesn't look completely black. The light from an ambient light is uniformly distributed everywhere in the world, so the ambient light's position and orientation are irrelevant.

Usually you don't want to create an ambient light without also creating one of the other kinds of lights, since an object illuminated solely by ambient light will be completely flat shaded and you won't be able to see any of its details. Typically, ambient lights are given a fairly dark gray color, so they don't overpower the other lights in the scene.

alight = AmbientLight('alight')
alight.setColor(VBase4(0.2, 0.2, 0.2, 1))
alnp = render.attachNewNode(alight.upcastToPandaNode())
render.setLight(alnp)

Spotlights

Spotlights represent the most sophisticated kind of light. A spotlight has both a point and a direction, and a field-of-view. In fact, a spotlight contains a lens, just like a camera does; the lens should be a PerspectiveLens and is used to define the area of effect of the light (the light illuminates everything within the field of view of the lens).

Note that the English word "spotlight" is one word, as opposed to the other kinds of lights, which are two words. Thus, the class name is correctly spelled "Spotlight", not "SpotLight".

Also, because a spotlight has a different inheritance than the other kinds of lights, you need to use upcastToLensNode() instead of upcastToPandaNode().

slight = Spotlight('slight')
slight.setColor(VBase4(1, 1, 1, 1))
lens = PerspectiveLens()
slight.setLens(lens)
slnp = render.attachNewNode(slight.upcastToLensNode())
slnp.setPos(10, 20, 0)
slnp.lookAt(myObject)
render.setLight(slnp)

  <<prev top next>>