I’ve been struggling for the last 6 months or so with a number of lighting bugs. The most serious of these is an exception thrown in StructuredUniform.setValue() with the following stack trace:
at StructuredUniform.setValue (three.module.js:18641:20)
at StructuredUniform.setValue (three.module.js:18641:6)
at WebGLUniforms.upload (three.module.js:18770:7)
at setProgram (three.module.js:29423:19)
at WebGLRenderer.renderBufferDirect (three.module.js:28302:20)
at renderObject (three.module.js:28973:11)
at renderObjects (three.module.js:28942:6)
at renderScene (three.module.js:28830:36)
at WebGLRenderer.render (three.module.js:28644:5)
at Engine.render (Engine.ts:235:19)
From what I can tell in the debugger, it’s attempting to set a uniform which is a zero-length array, and accessing element 0, which produces an undefined - and then tries to dereference that undefined.
The bug only happens when I use two renderers - one to render character portraits to an offscreen render target, followed by a render of the main window. The bug does not manifest if I render only one or the other. It appears that somehow the render to the offscreen render target is messing up the uniforms for the main view.
The bug also only happens with a specific shader, however I have checked and rechecked the shader code many times and I don’t see anything in it which would cause this to happen. And as mentioned, shader works fine if I’m only rendering to a single target.
I know of at least two other lighting bugs related to shadow maps and rendering multiple scenes, specifically with portals. However, those are harder to set up a repro case for, and I’m hoping that if this bug gets solved it may fix the other bugs as well.
Reproduction steps
The bug is 100% reproducible in my game engine, but very difficult to reproduce in a small program. So what I have done is spent the last couple days whittling down my game engine from 70K lines of code to just under a hundred source files, with all the game assets hard-coded. I know a hundred seems like a lot, but there’s only 3 files that need to be looked at, the rest can be ignored.
The source can be found in this github repo: GitHub - viridia/three-lighting-bug
To reproduce the bug, git clone the repo, and then:
npm install
npm run build
cd packages/los-editor
npm start
Then navigate to http://localhost:3000/
. The code has been set up to trigger the bug after 1 second - tht is, it renders to a single target for one second, and then renders to a second target, which causes the crash.
As mentioned, most of the sources can be ignored. The only ones you should need to look at are:
- packages/engine/src/world/actors/SkinnedModel.ts
- packages/engine/src/materials/HairMaterial.ts
- packages/engine/src/Engine.ts
In the Engine.ts file, you will find a section called ‘fixLightsHack’ - this is a workaround that avoids the crash, but causes a loss of framerate. Basically what the workaround does is globally disable shadows, do an extra render pass, and then re-enable shadows and then render again. Somehow this causes the uniform data to go back into sync.
(I’m posting this here because when I opened a github ticket I was asked to post on the forum instead.)