What values to use for physically correct lights when units are not meters?

It seems that physically correct lighting is based on units being in meters. What if units of a scene are in inches, for example?

Not sure of the answer to this, but it’s probably easier to scale any models you are using to meters rather than converting light units to imperial.

1 Like

That’s what I figure is to use meter units when possible, but in some cases this is inconvenient if, for example, a data set is all in some other unit. It is nice to be able to simply pass data long, which works totally fine with non-physically-correct lights (simply adjust distance), but it falls apart when trying to use physically correct lights.

As an example, I have a unit system that is aligned to the CSS pixels of the app, such that I can lay items out using CSS pixels that align with regular CSS items that use the same px units. Trying to apply physically-correct lights fails in this case because Three.js considers one unit (one pixel) to be one meter, and it isn’t obvious how to correct for this.

The following demo, for example, is measured in pixel units:

and if I update it to have realistic materials with realistic lighting, Three.js sees it as a ginormous set of buttons spanning many meters (so light falls off very abruptly after passing a number of pixels).

In order to keep pixel units for this case, I’d have to create a whole new unit system on top of the Three.js unit system, which would be an undesirable added complexity. This is why I was hoping to adjust lighting measurement instead.

Lighting (and other things in the PBR shading model — volume, refraction) is based on meters as you’ve mentioned. It may be easiest to put a scaled THREE.Group around your content to correct for the different units? I don’t think it’s feasible to just switch the units throughout the three.js codebase otherwise.

1 Like

In this case you’re not using any physical units at all so there’s no relation to your original question of using non-SSI units like inches.

Inches are still physical units and there’s equations to convert SSI light units from SSI to imperial units (e.g. lumens per square foot).

But if you’re using a non-physical unit like PX then no such equation exists. However, you seem to be saying you’ve already set your app up so 1 px = 1 three.js unit (1 meter), is that correct?

In that case @donmccurdy’s suggestion is good. You need to decide how many meters across you want your scene to be then scale accordingly (in other words, you need to decide the physical scale of your scene because it has no natural physical size).

For example, if you decide it should be 10 meters wide and the screen horizontal resolution is 1000px, you would need to scale by 100 and then adjust the camera to get the same view as before.

Yes indeed, web APIs don’t give us physical dimensions of physical pixels (like the affordance that native apps have), but I can as you mention arbitrarily say that my pixels are 1 millimeter or something similar, and at least get somewhat better lighting than currently (I can make heuristics like 1900 page means X size of pixel, etc, similar to having CSS break points).

But scaling the world or objects in the world causes other issues right?

I think that if I can adjust the lighting model instead, it would make more sense. Maybe I can fork the light classes and add an API like unit = "inches" (or something) that can apply the conversion internally based on the chosen value.

I have to study the math just a bit first; shouldn’t be too hard (thanks for that link)…