Feature idea: world scale, or unit scale

“units” in three.js are supposed to be in meters. Some formulas, for example physically correct lights, assume units of meters.

We cannot simply change the .scale of a Scene, because that changes the result of how light renders on objects.

For example, if we scale the scene by 0.001, physically-correct light will render on the scene as if our scene is tiny, 1/1000th the size of real life.

I’m not sure where it would go, but seems like we need some way to define the world scale. For example a value of 1000 would mean our units are in millimeters instead of meters (or kilometers depending on how the concept is applied), and all math formulas would take the scale into account.

Seems useful on the end user side (if we can decide how to specify the value(s)), but is it reasonable on the implementation side?

How would this work?

  • specify unit size on individual objects?
  • unit size on a scene?
  • on renderer?
  • other places?
  • nowhere, expect people to always convert to meters outside of three.js?

Let’s rephrase this statement a bit so it’s more align to the three.js policy. If you want to render physically correct, 1 world unit should be considered as 1 meter. If you don’t care about physically correctness e.g. since you are using NPR techniques, 1 world unit can be anything.

I agree that the unit should a a simple configuration on the renderer, many tools and engines use other units as well for various reasons. For instance 1 centimeter = 1 unit is a common default too (Unreal Engine, C4D e.g) while UE also has a configuration option, especially for the web it turned out to be more stable regarding precision in various cases for shader, for large numbers reaching the end on the other hand then only by using a wrapping space or different world matrix treatment, but then there is basically no early limit on either end anymore, especially not on large numbers.

Other cases can be scenes being generally only in a extreme large or small scale, for these it’s not possible to use a 1 meter unit without hitting one of the ends of 32 bit precision.

For the implementation i think a option on the renderer makes most sense, just how other options that go into shaders are defined.

Yeah, the option will be useful for physically-correct rendering, which will be the default soon.

Interesting, there could be a “PCU” or “physically correct unit” parameter, whereby the default decay is determined by a factor of the unit itself

I’m not sure why this would be necessary. If you need to work in a different frame or with a different unit scale you can create a child with the relevant adjustments to convert to meters so the physical lighting will be right - and / or all measurements can be done in the relevant group frame:

const scene = new Scene();

const kmGroup = new Group();
kmGroup.scale.setScalar( 1e-3 );

const mmGroup = new Group();
mmGroup.scale.setScalar( 1e3 );
3 Likes

I wish it were that easy. An option to specify the world unit solves all of the following issues in the simplest single way:

1), there will be problems like this one, where different 3D modeling programs use different units (and allow configuring the units):

2), I tried to convert one codebase from kilometers to meters, and this introduced a ripple effect of problems (mis-rendering, then having to tweak light biases, camera frustum near/far values, etc, etc) causing too much work (I gave up, no physical lighting in that app for now).

3), if we start from scratch on some new project, we can definitely try to uphold a mapping of some-unit-to-meters for all objects in the app, but that is also going to be cumbersome and tedious compared to a single option that tweaks the physically-correct lighting math.

It is not three’s responsibility to define what a unit is in your application or framework. Why should it?