mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-12 21:32:52 +00:00
#3487, #3488, #3489, #3490, #3491: Levels (Individual Controls): bound the curve only where it would overflow
The 1e6 bound also capped curves that were finite before (gamma 0.1 on an HDR value 4 x Input White is 4^10, about 1.05e6). The bound is now 1e30: 1e30 times the widest output range (2e4) is still finite, and every curve below it renders as before. A test pins 4^10.
This commit is contained in:
3 files changed
+11
-6
No files matched your search
@@ -257,11 +257,12 @@ impl Lv {
|
||||
}
|
||||
}
|
||||
|
||||
/// How far Levels (Individual Controls)' curve may reach, far beyond any image value: with gamma
|
||||
/// down to 0 (rendered as 0.01, an exponent of 100) an HDR value a few times Input White would
|
||||
/// overflow `f32`, and an infinite curve times an empty output range is NaN. Bounded, the output
|
||||
/// stays finite over the whole valid range (levels ±10000). The GPU (`fxt_lv`) uses the same.
|
||||
const LEVELS_IC_CURVE_LIMIT: f32 = 1e6;
|
||||
/// How far Levels (Individual Controls)' curve may reach: with gamma down to 0 (rendered as 0.01,
|
||||
/// an exponent of 100) an HDR value a few times Input White overflows `f32`, and an infinite curve
|
||||
/// times an empty output range is NaN. 1e30 times the widest output range (2e4) is still finite
|
||||
/// (`f32::MAX` is 3.4e38), and every curve that was finite before stays as it was below it. The
|
||||
/// GPU (`fxt_lv`) uses the same.
|
||||
const LEVELS_IC_CURVE_LIMIT: f32 = 1e30;
|
||||
|
||||
fn levels_ic(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let lv = LV_IDS.map(|ids| Lv {
|
||||
|
||||
@@ -294,6 +294,10 @@ fn levels_ic_stays_finite_over_the_whole_range() {
|
||||
let out = run("ec.color.levelsic", &img, &lv);
|
||||
assert!(out.data.iter().flatten().all(|v| v.is_finite()), "{ib} {iw} {ob} {ow}: {:?}", out.data[0]);
|
||||
}
|
||||
// The bound only stops the overflow: an HDR value that was finite before keeps its level
|
||||
// (gamma 0.1 at 4 x Input White: 4^10).
|
||||
let bright = run("ec.color.levelsic", &Image::filled(1, 1, [4.0, 4.0, 4.0, 1.0]), &[("rgb/rgbGamma", num(0.1)), ("clipToOutputWhite", Value::Enum(0))]);
|
||||
assert_eq!(bright.data[0][0], 4.0f32.powf(10.0));
|
||||
// Gamma 0 is the limit of a small gamma: below Input White the curve goes to 0.
|
||||
let dark = run("ec.color.levelsic", &Image::filled(1, 1, [0.5, 0.5, 0.5, 1.0]), &[("rgb/rgbGamma", num(0.0))]);
|
||||
assert!(dark.data[0][0] < 1e-6, "{:?}", dark.data[0]);
|
||||
|
||||
@@ -41,7 +41,7 @@ fn fxt_lv(i: u32, v: f32, clip_b: bool, clip_w: bool) -> f32 {
|
||||
t = min(t, 1.0);
|
||||
}
|
||||
// color2::LEVELS_IC_CURVE_LIMIT keeps the curve finite.
|
||||
let curve = clamp(fxt_gamma(t, max(data[o + 2u], 0.01)), -1e6, 1e6);
|
||||
let curve = clamp(fxt_gamma(t, max(data[o + 2u], 0.01)), -1e30, 1e30);
|
||||
return data[o + 3u] + (data[o + 4u] - data[o + 3u]) * curve;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user