Example goes black on r105 -> r155 upgrade

Here’s the example on r105:

Here’s the same example, with only the Three.js version updated to r155, and the cube goes black:

I bet this has to do with physical lights being the default.

How would you update the broken example to get roughly the same output without setting useLegacyLights to true?

By setting a higher intensity of the light:

var light2 = new THREE.PointLight('#348EDD', 2500000);

Large intensity values with point lights are not unusual since its unit is now candela. However, you could also think about decreasing the scale of your scene and also update the camera. The visual result will be the same but your lights can be parameterized in a more real world manner.

Ah I see. What’s the mental model to be able to come up with a value like 2,500,000, while keeping the units?

This requires some special consideration. One of my use cases will be 1 unit → 1px for normal website user interfaces, but decorated with 3D effects. I suppose I could convert all units to meters, make the UI in terms of approximately the meter sizes that a user has on their display (which is impossible to determine with web APIs unfortunately), but it means my code would need to have conversions for every single unit that exists in the app; not a simple undertaking.

You can find tables for the brightness of outdoor scenes and so on, but roughly 1 is the brightness of a small candle, and 120,000 is the brightness of a noon-day outdoor scene. Whether it looks like a candle or an outdoor scene will depend heavily on distance to the light, and scene exposure.

If you are going to use physically-based brightness units, I’d also encourage you to get comfortable adjusting exposure. That’s part of the process, as in photography.

Personally, I prefer to adjust exposure in “stops” in the range [-10, +10], as shown below. It’s easier [for me] than using exposure [0, ∞], and gives finer control in a UI slider.

renderer.toneMapping = THREE.LinearToneMapping;
renderer.toneMappingExposure = Math.pow(2, stops);

If you don’t need lights to decay, you could also reduce decay to 0, and not have to worry about the attenuation. Wouldn’t lose sleep over decay not being physically-based, if it makes your life easier. :slight_smile:


Great explanation, thank you!

I think this is exactly what I needed! Thanks for pointing this out! Great for many non-real cases, for “effect” (f.e. light up a UI, don’t care about physical units).

1 Like