Brightness & Contrast: negative settings invert the positive curves, as After Effects

In After Effects 2026 the non-legacy curve of Brightness -40 is the inverse
of Brightness +40 (within 2.6/255 on a full black-to-white ramp) and Contrast
-50 the inverse of Contrast +50. EffectCraft fitted the negative brightness
with its own power (2^(1.32 |b|) on v), 20/255 off AE at -40; the negatives
now use the reciprocal exponents of the positive curves: Brightness -40 max
6.2/255 (was 19.8), Contrast -50 4.1 (was 7.0); positives unchanged (40:
5.5, 80: 7.8, Contrast 50: 2.7, 90: 5.0; B20 C30: 6.6, which confirms
brightness before contrast). The #681 oracle samples still pass. CPU and GPU.
The positive curves' remaining 5-8/255 needs a better curve family (a
two-point spline fits each capture within 1.6/255), left open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
vangel76
2026-10-19 16:15:02 +02:00
co-authored by Claude Opus 5.5
parent 515cc3d5f7
commit dc9f15ada1
3 changed files with 48 additions and 12 deletions
+11 -5
View File
@@ -624,14 +624,20 @@ fn pointwise(@builtin(global_invocation_id) gid: vec3<u32>) {
} else if (P.u[0].y == 2u) {
// Brightness & Contrast tone curves (effects crate bc_modern, AE-fitted #681).
var o = c;
let g = max(1.0 + 0.53 * ct, 0.05);
// Negative settings invert the positive curves (reciprocal exponents).
var g = max(1.0 + 0.53 * abs(ct), 0.05);
if (ct < 0.0) {
g = 1.0 / g;
}
var e = exp2(1.24 * abs(br));
if (br < 0.0) {
e = 1.0 / e;
}
for (var i = 0; i < 3; i++) {
if (c[i] < 1.0) {
var v = max(c[i], 0.0);
if (br > 0.0) {
v = 1.0 - powz(1.0 - v, exp2(1.24 * br));
} else if (br < 0.0) {
v = powz(v, exp2(-1.32 * br));
if (br != 0.0) {
v = 1.0 - powz(1.0 - v, e);
}
if (ct != 0.0) {
if (v < 0.5) {