Three.js: Wrong position of Spotlight shadow in three.js r85

Created on 3 May 2017  ·  7Comments  ·  Source: mrdoob/three.js

Description of the problem

In creating a shadow for one scene, the basic processes include creating an available light, a cast shadow object, a receive shadow object. The problem I met is in the light's part.

I create a spotlight with specifying its target to be a cube, adding the shadow camera to one camerahelper and then rendering them, but results seem different in two different three.js versions. The grammar and APIs I obeyed is the newest document in three.js website, can be accessed here.

A code snippet in two different three.js version shows here (the same codes with just different three.js version included):

I also took some screenshots to show the differences between them:

image

The abnormal one (r85) with shadow doesn't displayed in the right place, as well as the shadow camera fixed to vec(0,0,0). The shadow camera scope is emphasized with yellow lines in the picture.

image

The good (r84) one with shadow displayed in the right position, but the shadow camera still fixed to vec(0,0,0), which I think it's not supposed to be that, since a good shadow camera should follow the position of its belonged light? (such as the following pic)

image

It seems r85 can't display shadow in spotlight normally, but there is no problem in r84; on the other hand, these two versions both have a wrong shadow camera position in spotlight environment.

Three.js version
  • [x] r85
Browser

I didn't test all the browsers but I think it is apparently not the browser internal issues.

  • [ ] All of them
  • [x] Chrome
  • [x] Firefox
  • [ ] Internet Explorer (Not test)
OS
  • [] All of them
  • [ ] Windows
  • [ ] macOS
  • [x] Linux
  • [ ] Android
  • [ ] iOS
Hardware Requirements (graphics card, VR Device, ...)

Just follow the basic requirements of three.js' runtime environment is enough to catch this problem.

Bug

Most helpful comment

@jostschmithals @Mugen87 In the spotlight example,controls.update() is dispatching a change event and forcing a call to render(), hence there are two render() calls. The first one renders incorrectly; the second one correctly.

The problem can be duplicated in the same example by removing the call to render() at the bottom of the file.

// render();

The problem can be mitigated by adding this line in the example init() function:

spotLight.shadow.update( spotLight );

Obviously, we don't want users to have to do this:

spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 20;
spotLight.shadow.camera.far = 200;

spotLight.shadow.update( spotLight );

So perhaps the recent changes should be revisited to track this down further. That is as far as I will be able to pursue this for now.

All 7 comments

I noticed that in both of your fiddles the shadow camera's position and rotation (and the shadow itself) seem to be ok, if obj.render() is called twice. Perhaps this observation could be a starting point for debugging the source code.

Similar observation in https://threejs.org/examples/?q=spotlight#webgl_lights_spotlight:

Replacing the line controls.update() by camera.lookAt(mshBox.position) causes the shadow to display wrong. The first zooming or orbiting corrects the shadow immediately.

/ping @jaxry There is maybe be an issue in WebGLShadowMap.

@jostschmithals @Mugen87 In the spotlight example,controls.update() is dispatching a change event and forcing a call to render(), hence there are two render() calls. The first one renders incorrectly; the second one correctly.

The problem can be duplicated in the same example by removing the call to render() at the bottom of the file.

// render();

The problem can be mitigated by adding this line in the example init() function:

spotLight.shadow.update( spotLight );

Obviously, we don't want users to have to do this:

spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 20;
spotLight.shadow.camera.far = 200;

spotLight.shadow.update( spotLight );

So perhaps the recent changes should be revisited to track this down further. That is as far as I will be able to pursue this for now.

Fortunately the shadow problem seems to be solved by @jaxry's bugfix 👍

But the other issue seems to be independent from this (and must be an older one, undetected up to now):

To set the shadow camera helper’s position and rotation correctly the user still has to call render() twice – otherwise in https://threejs.org/examples/?q=spotlight#webgl_lights_spotlight as well as in the two fiddles posted by @hijiangtao the shadow camera helper keeps position (0,0,0) and rotation (0,0,0) until there is a second render call from outside, for example by OrbitControls – even in the fiddle which uses r84.

@jostschmithals It seems the problem can be found in https://threejs.org/examples/?q=spotlight#webgl_lights_spotlight if I remove all the codes related to OrbitControls.js file, as described by @WestLangley and yourself. Thanks for @jaxry work.

For another problem-the shadow camera's position, I tried other version of three.js and found all versions after r73 (not included itself) had the same problem, for example the result in r74. But I am not sure if the problem had already existed in an even older version yet, it seems some APIs had been changed after version r73, so I can't get results from my current codes with loading three.js with versions before r74.

Closing. The shadow problem is fixed, the problem with helpers is tracked here: #14801

Certain helpers are "frame late". They rely on matrixWorld from their base object (e.g. camera) which _might_ represent the state of the last frame (and not the current one). On first rendering, it's the identity matrix and thus the helper is positioned at the origin.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Bandit picture Bandit  ·  3Comments

filharvey picture filharvey  ·  3Comments

yqrashawn picture yqrashawn  ·  3Comments

boyravikumar picture boyravikumar  ·  3Comments

seep picture seep  ·  3Comments