PointLight global space coordinates

Hi all,
A quick question, is there a way to get the position in global space of the brightest point of a pointLight? Also, is there a way to get the radius in global space units, of the area of effect of a pointLight? I’m terribly sorry if this is a question with an obvious answer (say, by fiddling with the attenuation coefficients), but it doesn’t appear to have been explained that well by looking at the available documentation.

Thanks in advance.

Well, that should just be the position of the PointLight object itself, as a PointLight is brightest at its centre, I believe.

This is tricky: after all, what is the “area of effect” of a PointLight?

That is, I believe that a PointLight technically has no bounds on its effect–its illumination extends off to ostensible-infinity. The only question is that of at what threshold of light you consider it to be “attenuated enough” to be deemed “no longer effective”.

Once you know that value, you should be able to calculate the relevant distance from the light-attenuation equation. (Which should be available somewhere online; I presume that our equation is just the standard one.)

1 Like

In my scene, the source of the light isn’t at the centre, it appears to come from the periphery and is being cast forward. I’m not sure why this is. Is there a way to get and change the point from which the light is being cast?

To the best of my knowledge, no: a PointLight should be just as I described; there is no moving of its point-of-origin relative to the light itself.

Are you perhaps just seeing a specular reflection, the apparent position of which would depend on the position from which you’re viewing the light…?

No:


The smiley model is parented to the pointLight and hence should show the origin of the light. As you can see, it appears to come from the periphery. To put the light in the scene all I did was this:

       plight = PointLight('plight')
       plight.setColor((0.5, 0.5, 0.5, 1))
       plight.setShadowCaster(True, 512,512)
       camMask=BitMask32()
       camMask.setBit(4)
       plight.setCameraMask(camMask)
       plnp = render.attachNewNode(plight)
       
       plnp.setZ(plnp,10)
       plight.attenuation = (2.2, 0, 0)
       smi = loader.loadModel('smiley')
       smi.reparentTo(plnp)
       render.setLight(plnp)

Just to add: it seems that the point from which the light is cast changes as the pointLight moves. In my scene, the nodepath connected to the pointLight follows the player around and I notice that it seems the origin of the light changes with the position of the pointLight itself. This is how I move the nodepath connected to the pointLight around:

           gotPosOne=sentLight.getPos()
           gotPosTwo=gotPlayer.getPos()
           gotPosOne.z=0
           gotPosTwo.z=0
           distIs=(gotPosOne-gotPosTwo).length()
           if(distIs>sentDistance):
               oldHpr=sentLight.getHpr(render)
               sentLight.lookAt(gotPlayer)
               sentLight.setH(sentLight.getH()+180)
               sentLight.setR(0)
               sentLight.setP(0)
               sentLight.setY(sentLight,-40*globalClock.getDt())
               sentLight.setHpr(render,oldHpr)

Is that just the way the pointLight is supposed to behave, when the nodepath it’s connected to is moved around the scene?

I see! That’s very strange–I don’t know what might be causing that!

Indeed, I performed a quick test, placing a light very like yours into a little test-scene, and I see the light centred on its location:

[edit]
I’ve changed the screenshot, thinking that a “pole” passing vertically through both the light and the terrain might be more demonstrative of the light’s location.)


[/edit]

I also note that the falloff of your light looks odd for a point-light… If anything, it looks a bit like a Spotlight!

Presuming that it’s not a Spotlight, are you perhaps using a custom shader…?

I updated my response, please take a look at it if it’s not too much to ask. I noticed that the position of the pointLight seems to modify the point from which it is cast. I am not using a custom shader or anything fancy at all.

Ah, I did miss that you’d updated your response–thank you for pointing that out! :slight_smile:

To respond to the update:

Yes, it is, I do believe: the light NodePath defines the position of the light. (And hence, any object parented to the light NodePath should move with the light.)

In your code, what is “sentLight”? How are you getting that object?

The “sentLight” is just the pointLight, shown in my response with the screenshot:

   def lightFollowPlayer(self,sentLight,sentDistance):
       gotPlayer=render.find("=playerResource")
       if(gotPlayer):
           gotPosOne=sentLight.getPos()
           gotPosTwo=gotPlayer.getPos()
           gotPosOne.z=0
           gotPosTwo.z=0
           distIs=(gotPosOne-gotPosTwo).length()
           if(distIs>sentDistance):
               oldHpr=sentLight.getHpr(render)
               sentLight.lookAt(gotPlayer)
               sentLight.setH(sentLight.getH()+180)
               sentLight.setR(0)
               sentLight.setP(0)
               sentLight.setY(sentLight,-40*globalClock.getDt())
               sentLight.setHpr(render,oldHpr)
...
self.lightFollowPlayer(plnp,30)

So if you move a pointLight around, the point from which the light is cast changes? At times it’s cast from the centre, other times it is not, depending on how you move it?

No: The light is always cast from the centre-point, but the entire light can be moved.

Let me illustrate: Here’s a modification of the scene in the screenshot that I posted above, in which I now move the light via a call to “setX”:
lightMovement

Note that the “pole”, which is again attached to the light via “reparentTo”, remains at the centre as the light is moved; the light always emanates from the location of its NodePath.

[edit]
You know, looking again at your screenshot, I note that the landscape falls away into the distance. I’m wondering whether it’s not just the effect of that drop in elevation that we’re seeing:

After all, the higher the landscape, the closer its surface is to the light, and thus the smaller will be the circle of light cast on it. (As a result of the angle between surface and incoming light more-quickly becoming obtuse.) Conversely, as the landscape becomes lower relative to the light’s position, the larger will be the circle of light cast on it.

That is, on a landscape that falls away as does this one, the parts of the landscape “uphill” from the light will have a smaller circle of light, and the parts “downhill” from it will have a circle of light larger the lower they are. Thus there will be more light “downhill”, and so we will see what appears to be an offset in the light’s position–even though the illumination is actually still emanating from the centre of the light.

So, what happens if you make your landscape flat? Do you see the same apparent offset?

Yes, it persists:

Maybe something else is causing this (could it be the normals?), that I’d have to look more into. It’s not that big a deal anyways, it’d just be more convenient if I always knew where the centre of the pointLight was. I’ll look into it more later, thank you so much for your insights.

Very strange indeed!

I suppose that it could be the normals of the terrain… Otherwise–and this seems unlikely–but maybe your terrain is tilted somehow…?

Oh, one more thought! What happens if you go to that flat region show in your most recent screenshot, and then rotate the camera around the light? Does the light’s apparent offset remain the same?

No, the terrain is not tilted, the hpr is always 0.

Yes, it remains the same and isn’t modified by the camera’s transform.

Very weird! I’m afraid that I don’t know what’s going on, then. :/ (Although your idea of it being the terrain-normals does seem worth checking.)

So upon further investigation, it indeed was the normals. For the terrain, I was using the formula provided in the procedural geometry sample to create them:


def normalized(*args):
    myVec = LVector3(*args)
    myVec.normalize()
    return myVec

...
normal.addData3(normalized(2 * x1 - 1, 2 * y1 - 1, 2 * z1 - 1))

As opposed to just setting the normals “up” like this:

normal.addData3(0,0,1)

So the orientation of the normals significantly affected the way all types of lights, point, direction, etc., interacted with the procedural model.

1 Like

Aaah, of course–yes, that would indeed do it! Well-uncovered! :slight_smile:

1 Like