light toggle in directtools

I have a simple question.

In the directtool on the render style panel there are some toggle buttons - wireframe, light, backface etc. My game looks much better with the lights toggle on - does anyone know how i make the same lighting from my python scipt???

In short how do I toggle on the light (as it is in the directools) from my python scipting?

Any help would be fantastic!

You need to create one or more lights, and put them somewhere, for instance attached to the camera:

light = DirectionalLight()
lightNodePath = camera.attachNewNode(light.upcastToPandaNode())

Then you enable the light, for instance on the whole world:

render.setLight(lightNodePath)

You can parent the lightNodePath under any node you like; it doesn’t have to be the camera. Where you put it determines which direction the light is shining. If you parent it to the camera, it is as if the light is always pointing in the same direction you’re looking.

There is also a chapter in the Panda manual that deals with lighting (https://www.panda3d.org/manual.php?page=fogandlights3), and it talks about the different kinds of lights you can create other than a DirectionalLight. Unfortunately, the information there is just a bit of of date (you don’t need to create a LightAttrib any more) and it’s a little confused anyway about the relationship between Lights, NodePaths, and LightAttribs.

David

Hi David,

Can you give a few more examples of how lights really work?
Or point us to a referrence that is current?

I have looked at the manual and it confuses me completely.

I am trying to highlight one of a number of objects by applying a light to it (either a spotlight or ambient glowing from within).

I can get the ambient to go on but not to come off again.

I tried using your method here for a simpler ambient highlight and nothing happened at all.

I also can’t find any way to get a spotlight to shine onto the object (as I haven’t yet worked out how to define direction)

Any help of clarification would be appriecated,

thanks

Barnaby

Some of the sample programs use lights. Yes, it’s the old-style “LightAttrib” thing, but it does work.

Ok, here’s how it breaks down.

There are a number of types of lights: ambient, point, directional, spotlight. Each of these is represented by a node that lives somewhere in the scene graph. The position and orientation of the light is determined by the basic scene graph operations like setPos(), setHpr(), etc.

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:

spot = Spotlight('spot')
spotNP = render.attachNewNode(spot.upcastToPandaNode())

Now that you have a NodePath that references your spotlight, you can put it wherever in the scene graph you want it to be; for instance, parent this to your car to make a headlight, or leave it under render and just position it somewhere:

spotNP.setPos(10, 0, 2)
spotNP.lookAt(myAvatar)

But so far the light doesn’t actually illuminate anything, it’s just there, invisible. In order to turn the light on, you have to first decide what object or objects will be illuminated by the light. To do this, use the nodePath.setLight() method. If you want your light to illuminate the whole world (or rather, whatever it might be pointing at), that really means everything under render, so you call:


render.setLight(spotNP)

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


render.clearLight(spotNP)

Ambient lights work the same way as spotlights, except it doesn’t matter where they are or which way they’re facing (since ambient lights are by definition uniform everywhere in space). To create an ambient light and apply it just to one object:

amb = Ambient('amb')
ambNP = render.attachNewNode(amb.upcastToPandaNode())
myObject.setLight(ambNP)

And to turn it off again:


myObject.clearLight(ambNP)

Note that the default color for an ambient light is (1, 1, 1, 1), which is also the default illumination you get if there are no lights on an object at all. So the above will have no apparent effect. If you want to be able to see the ambient light, you either need to darken the rest of the world (for instance, by applying a darker ambient light to render), or color the light red or something, like this:


amb.setColor(VBase4(1, 0, 0, 1))

Ironically, using lights can only make things darker than not having lights at all (since if you have no lights, it is as if you had everything fully illuminated, but as soon as you have at least one light, that light determines the brightness level).

If your only purpose is highlighting an object, consider using something like object.setColorScale(1, 0, 0, 1) (and object.clearColorScale()) instead. This is a simpler way to quickly change the color of an object. Again, it can only make things darker, since the default is for things to be as bright as they can be.

David

Dave,

Thank you for your quick and detailed reply.
This really helps a lot and the new format is much simpler than the lightAttrib type.

I am still having a small problem though.
I plan to use this to have a spotlight come on to highlight selected segments or a map.
So I create the spotlight as you describe then position and activate it when required:


    def buildHighlight( self):
        self.highLight = Spotlight('spot')
        self.highLight.setColor(Vec4( .5, 1, .5, 1))
	self.highLightNode = self.mapNode.attachNewNode( self.highLight.upcastToPandaNode())
	self.highLightNode.setPos( 0, 0, 5)

        
    def highlight( self, selectedSegment ):
        self.highLightNode.lookAt( selectedSegment)
	self.mapNode.setLight( self.highLightNode )

The problem is I get a attribute error on Spotlight

I tried your code direct


        spot = Spotlight('spot') 
        spotNP = render.attachNewNode(spot.upcastToPandaNode())

but got the same result

Looking at the inheritance, Spotlight doesn’t inherit from LightNode but from LightLensNode, which does not have upCastToPandaNode.
But I can’t see any other upCast method that would work.

I tried it withouth the upcast and python crashed.
I also tried all the other upcast methods on Spotlight (just in case) but they don’t work because attachNewNode is looking for a PandaNode and Spotlight isn’t one.

Is there something I am doing wrong?
Do I have the wrong version of Panda installed?

Thanks for your help with this, I really appreciate the assistance

Barnaby

Oops, sorry.

In the case of a Spotlight, because of its different inheritance, the correct call is upcastToLensNode().

Also, I forgot to mention that a spotlight requires a lens, so you can specify the field of view of the spotlight’s frustum, and similar parameters. You can give it a default lens:

lens = PerspectiveLens()
self.highLight.setLens(lens)

David

Thanks David,

That is perfect.
Works just as I wanted.

Though I am getting some strange illumination on the surrounding objects.
I will check the lense properties and see if I can work out why.

Do you think should post a “spotlight addendum” with this information as a sticky item on the forum or do you think this post will be enough?

Thanks for all your help, really appreciated!

Barnaby