three.js: Problem with Reflector affecting lighting when its texture is rendered.

Description of the problem

I have a problem with changes to lighting when Reflector object is used.

I have distilled the problem down here: https://jsfiddle.net/cmd4/9zLhq9Lf/ You should see that the lighting on the walls changes whenever you rotate the view, as the mirror changes between facing towards and away from the camera.

Note that to show the problem, it seems to require adding the Reflector object before the first render, and the rest of the scene after the first render. i.e. If I create the whole scene before the first render, then I don’t seem to get any issues.

My guess is that the problem may be related to setting up GL state for the point light when rendered for both the main camera and the “virtual” camera created by the Reflector class.

Maybe in this function below, but here I am out of my depth: (from https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLLights.js)

setup( lights, shadows, camera )
 {
...
	var viewMatrix = camera.matrixWorldInverse;
...
	} else if ( light.isSpotLight ) {
                     var uniforms = cache.get( light );
                     uniforms.position.setFromMatrixPosition( light.matrixWorld );
                     uniforms.position.applyMatrix4( viewMatrix ); <<<<HERE???
...

Three.js version
  • Master
  • r88
Browser
  • Chrome
  • Firefox
  • Edge
OS
  • Windows
  • macOS
  • Linux
  • Android
  • iOS

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 23 (1 by maintainers)

Commits related to this issue

Most upvoted comments

Just for info: I can confirm that updating to r90 fixed the problems I was having with Reflector in my application. Thank you! 😃

Oh dear, i think i’ve found the issue 😒

The problem is the setup of light uniforms in WebGLRenderer:

https://github.com/mrdoob/three.js/blob/b50726ac9ddc361111e636c009bc32019c225b1f/src/renderers/WebGLRenderer.js#L1141

The setup of lights is done once per frame. But when a reflector is rendered, it overwrites the lights setup because it executes a rendering of the scene in onBeforeRender(). The problem is now that this setup is not reverted. So depending on the order of the reflector in the render list, subsequent objects are rendered with the wrong light setup. Or to be more precise, with the wrong view matrix (the one of the reflector’s virtual camera).

I think we have to find a way to restore the light setup after possible changes in onBeforeRender().

Could the issue be related to light position uniform setup in the code I referred to in my first comment? If lights are positioned in camera space, it made me wonder if for some reason the light position was using the position for the wrong camera? https://github.com/mrdoob/three.js/blob/14ed22d5b5422f11738016cef85d70927117851f/src/renderers/webgl/WebGLLights.js#L262 This is just a guess based on how the light position seeming to shift when the mirror texture is rendered.

OK, I see that.

Here is the pattern you are implementing:

scene.add( mirror );
renderer.render( scene, camera );
createMirrorTest(); // this function adds lights

You are changing the number of lights after the first render, so you need to recompile the mirror’s shader.

mirror.material.needsUpdate = true; // you need to add this line

updated fiddle: https://jsfiddle.net/9zLhq9Lf/2/