How to comprehend the pointLight shadowMaxZ and shadowMinZ?

DirectionalLight has properties autoCalcShadowZBounds to fit the shadow z range.
I refer to the implementation of directionalLight to calculate the shadow z range of spotLight and pointLight.
spotLight PG:

pointLight PG:

In my understanding,the depth map is created by projection.Whether it is orthographic projection or perspective projection,both of them have near plane and far plane.And the near\far plane is shadowMaxZ\MinZ.

In spotLight PG,it seems correctly.
But in pointLight PG,box2 has no shadow.And the depth texture miss the depth of box2.
PointLight use cubeMap,and i calculated in six directions.Why it miss the depth of box2.
Or the cubeMap is not created by six directions?

That’s correct.

Depending on the filtering method (none, PCF, etc), the light frustum may need to be extended to be large enough to encompass the full shadows of all the objects.

For eg, if you select PCF in the spotlight PG, you will see the shadow is truncated:

In this case, you need to raise the shadowMaxZ value so that the light frustum is big enough.

Regarding the point light case, it’s a bit different, shadowMinZ/shadowMaxZ are both the near/far planes of the projection matrix but also the min and max distances to consider when computing shadows. So, you should compute those values like this:

(see new lines 55-57)


I don’t understand that why pointLight computes shadows should consider shadowMinZ/maxZ.In pointLight depth cubeMap,box2’s depth is not written in depth cubeMap.
I know that when we use PCF,shadows will be truncated by far plane.
Like you said:

I think that the pointLight shadow should be same in spotLight shadows with setting PCF?

In addition,i think that we can add property autoCalcShadowZRange(or zbounds) in spot/pointLight. :innocent:

Yes it is (note that it is a distance cubeMap, though, not a depth cubeMap), but as a normalized value between 0 and 1. The computation is normDist=(dist+shadowMinZ)/(shadowMinZ + shadowMaxZ). If dist is near to shadowMaxZ the value is ~1 and you won’t see the difference from a white pixel in the depth texture.

No because the computation is not the same, everything is distance based in the point light case, we are not using the u/v coordinates to clip the shadow to the depth texture (as we don’t have a depth texture but a cube map).

I think it’s a good idea!


Thank!Is there any way for me to learn more about the light design of BJS :smile:?I didn’t know that everything is distance based in the point light case and i want to learn more how we design BJS.

↑ :+1:

I delete the lines 59 ~ 69 and shadowMinZ is the min distance.But it seems uncorrectly.

There is the source code in github :slight_smile:

There are only a few articles in the docs about implementations in BJS and most of the time you would want to look at the source code if you want a better understanding of what’s going on under the hood.

That’s because the near plane is too far because what we compute is a distance and not a depth. That’s why I had kept the code you commented out.

Okay~Thanks for your reply!

Yes,i kept your code for calculating the distance and commented out the one that calculates the depth. Why the near plane being calculated uncorrectly(the near plane is too far,though i computed it by distance)?

Because the near plane value (shadowMinZ) is not used as a distance when computing the projection matrix but as a depth: the Z coordinate value only and not sqrt(x*x+y*y+z*z).

Better explained with a drawing:

We see the scene from above and there’s a box in the scene.

If we use distances, the smallest one is the black dotted line. If we use this value as the near plane, we end up with the blue plane (length of red dotted line == length of black dotted line), which is wrong as you can see, one part of the box is in front of the near plane. We need to use the z coordinate of point A as the near plane value instead.


I get it!!!
Thank you for your detailed answer! :heart: