The exposure value shown in the render dialog, the exposure in stops, and the color gains for a white-balance temperature.
How the precision is kept
Exposure is a closed-form base-2 logarithm in 64-bit. White balance goes through published curve fits for the color of a black body and of daylight, and a color matrix written to 7 decimals, so its accuracy is that of the fits and the matrix, not of the arithmetic.
Calculations under this policy
4 calculations in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.
The EV figure the render dialog shows for the chosen f-stop, shutter time and ISO.
EV = log₂(N² ÷ t) − log₂(S ÷ 100)
Two 64-bit base-2 logarithms subtracted. Missing or zero settings fall back to f/8, 1/125 s and ISO 100.
render/pt-camera.js
lines 31 to 34
BimCraft 0.8.1
export function ev100(s) {
const N = s.fstop || 8, t = s.shutter || 1 / 125, S = s.iso || 100;
return Math.log2((N * N) / t) - Math.log2(S / 100);
}
Exposure in stops
64-bit
The stops added to the picture's exposure from the brightness slider and, in camera mode, the f-stop, shutter and ISO.
stops = slider + log₂(t × S × 256 ÷ N²)
One 64-bit expression. The factor 256 makes the camera term zero at f/16, 1/100 s and ISO 100.
render/pt-camera.js
lines 35 to 40
BimCraft 0.8.1
export function cameraStops(s) {
const base = (s && s.exposure) || 0;
if (!s || s.exposureMode !== 'camera') return base;
const N = s.fstop || 8, t = s.shutter || 1 / 125, S = s.iso || 100;
return base + Math.log2((t * S * 256) / (N * N));
}
Color temperature to chromaticity
64-bit
The CIE xy color of light of a given temperature in kelvin.
x = a ÷ T³ + b ÷ T² + c ÷ T + d; y = polynomial in x
Polynomial fits with coefficients written to between 4 and 9 digits: one pair below 4000 K, with a switch at 2222 K, and the daylight formulas above, with a switch at 7000 K. The input is clamped to 1667 K to 25000 K.
render/pt-camera.js
lines 42 to 54
BimCraft 0.8.1
export function cctToXy(T) {
T = Math.min(25000, Math.max(1667, T));
let x, y;
if (T < 4000) {
x = -0.2661239e9 / T ** 3 - 0.2343589e6 / T ** 2 + 0.8776956e3 / T + 0.17991;
y = T < 2222 ? -1.1063814 * x ** 3 - 1.3481102 * x ** 2 + 2.18555832 * x - 0.20219683
: -0.9549476 * x ** 3 - 1.37418593 * x ** 2 + 2.09137015 * x - 0.16748867;
} else {
x = T <= 7000 ? -4.607e9 / T ** 3 + 2.9678e6 / T ** 2 + 0.09911e3 / T + 0.244063 : -2.0064e9 / T ** 3 + 1.9018e6 / T ** 2 + 0.24748e3 / T + 0.23704;
y = -3 * x * x + 2.87 * x - 0.275;
}
return [x, y];
}
White-balance gains
64-bit
The three color gains that make light of the chosen temperature show as white.
gain = (ref ÷ w) × (Y(w) ÷ Y(ref))
Both whites go through the fit above and a color matrix written to 7 decimals, then are divided channel by channel. The division by y in the conversion and by each channel of the chosen white is not guarded. A temperature within 1 K of 6500 K returns gains of exactly 1.
render/pt-camera.js
lines 56 to 65
BimCraft 0.8.1
const XYZ_TO_AP1 = [[1.6410234, -0.3248033, -0.2364247], [-0.6636629, 1.6153316, 0.0167563], [0.0117219, -0.0082844, 0.9883949]];
const ap1OfXy = ([x, y]) => { const X = x / y, Z = (1 - x - y) / y; return XYZ_TO_AP1.map((r) => r[0] * X + r[1] + r[2] * Z); };
const lumAp1 = (c) => 0.2722 * c[0] + 0.6741 * c[1] + 0.0537 * c[2];
export function whiteBalance(K) {
if (!K || Math.abs(K - 6500) < 1) return [1, 1, 1];
const ref = ap1OfXy(cctToXy(6500)), w = ap1OfXy(cctToXy(K));
// gains take that white to the 6500 K white, scaled so its luminance stays: they change colour, not exposure
const k = lumAp1(w) / lumAp1(ref);
return ref.map((v, i) => (v / w[i]) * k);
}
In detail
Method
EV at ISO 100 = log2(N² ÷ t) − log2(S ÷ 100). Color temperature to CIE xy: the cubic fit of Kim et al. 2002 below 4000 K and the CIE daylight locus above, as the file's header cites. Gains are the ratio of the 6500 K white to the chosen white in AP1, scaled to keep luminance.
Number types
64-bit numbers. Fit coefficients written to between 4 and 9 significant digits; matrix terms to 7 decimals; luminance weights to 4 decimals.
Tolerances
A temperature within 1 K of 6500 K gives gains of exactly 1. Temperatures are clamped to 1667 K to 25000 K.
Limits
The two fits meet at 4000 K and are each an approximation of the locus they stand for. An f-stop, shutter time or ISO of 0 is replaced by f/8, 1/125 s or ISO 100.
Approach: 64-bit, stated limit
The arithmetic is 64-bit, but the method or the data sets the accuracy: a solver tolerance, a mesh, a step size, a datum shift, a table. The limit is stated where the result is shown.