Reduce artifacts in parametric curve calculation (#6219)

This commit is contained in:
Jonathan Bieler 2021-06-12 21:07:44 +02:00 committed by GitHub
parent d02ed52e00
commit 3248e6b003
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 12 deletions

View File

@ -142,11 +142,19 @@ protected:
double lx = xlog(x); double lx = xlog(x);
return m2 * x + (1.0 - m2) * (2.0 - xexp(k * lx)) * xexp(l * lx); return m2 * x + (1.0 - m2) * (2.0 - xexp(k * lx)) * xexp(l * lx);
} }
static inline double basel_alt(double x)
{
return (2.0 - x) * x * x * x;
}
// basic concave function between (0,0) and (1,1). m1 and m2 controls the slope at the start and end point // basic concave function between (0,0) and (1,1). m1 and m2 controls the slope at the start and end point
static inline double baseu(double x, double m1, double m2) static inline double baseu(double x, double m1, double m2)
{ {
return 1.0 - basel(1.0 - x, m1, m2); return 1.0 - basel(1.0 - x, m1, m2);
} }
static inline double baseu_alt(double x)
{
return x * (2.0 + (x - 2.0) * x * x);
}
// convex curve between (0,0) and (1,1) with slope m at (0,0). hr controls the highlight recovery // convex curve between (0,0) and (1,1) with slope m at (0,0). hr controls the highlight recovery
static inline double cupper(double x, double m, double hr) static inline double cupper(double x, double m, double hr)
{ {
@ -448,6 +456,13 @@ protected:
{ {
return (1 - sh) * (1 - hl) * p00(x, prot) + sh * hl * p11(x, prot) + (1 - sh) * hl * p01(x, prot) + sh * (1 - hl) * p10(x, prot); return (1 - sh) * (1 - hl) * p00(x, prot) + sh * hl * p11(x, prot) + (1 - sh) * hl * p01(x, prot) + sh * (1 - hl) * p10(x, prot);
} }
static inline double pfull_alt(double x, double sh, double hl)
{
double t = (1.0 - sh) * (1.0 - hl) * CurveFactory::basel_alt(x) + sh * hl * CurveFactory::baseu_alt(x);
return x <= 0.5
? t + (1.0 - sh) * hl * CurveFactory::basel_alt(2.0 * x) * 0.5 + sh * (1.0 - hl) * CurveFactory::baseu_alt(2.0 * x) * 0.5
: t + (1.0 - sh) * hl * (0.5 + CurveFactory::baseu_alt(2.0 * x - 1.0) * 0.5) + sh * (1.0 - hl) * (0.5 + CurveFactory::basel_alt(2.0 * x - 1.0) * 0.5);
}
void fillHash(); void fillHash();
void fillDyByDx(); void fillDyByDx();

View File

@ -116,8 +116,8 @@ DiagonalCurve::DiagonalCurve (const std::vector<double>& p, int poly_pn)
} }
mc = -xlog(2.0) / xlog(x[2]); mc = -xlog(2.0) / xlog(x[2]);
double mbase = pfull (0.5, x[8], x[6], x[5]); double mbase = pfull_alt (0.5, x[6], x[5]);
mfc = mbase <= 1e-14 ? 0.0 : xexp(xlog(mbase) / mc); // value of the curve at the center point mfc = xexp(xlog(mbase) / mc); // value of the curve at the center point
msc = -xlog(2.0) / xlog(x[1] / x[2]); msc = -xlog(2.0) / xlog(x[1] / x[2]);
mhc = -xlog(2.0) / xlog((x[3] - x[2]) / (1 - x[2])); mhc = -xlog(2.0) / xlog((x[3] - x[2]) / (1 - x[2]));
} }
@ -424,7 +424,6 @@ void DiagonalCurve::catmull_rom_set()
/*****************************************************************************/ /*****************************************************************************/
double DiagonalCurve::getVal (double t) const double DiagonalCurve::getVal (double t) const
{ {
@ -435,20 +434,25 @@ double DiagonalCurve::getVal (double t) const
return 0.0; return 0.0;
} }
double tv = xexp(mc * xlog(t)); double tv = xexp(max(mc * xlog(t),-236.0)); // prevents numerical issues when calling pfull, at the cost of minor artifacts
double base = pfull (tv, x[8], x[6], x[5]); double base = pfull_alt (tv, x[6], x[5]);
double stretched = base <= 1e-14 ? 0.0 : xexp(xlog(base) / mc); double stretched = xexp(xlog(base) / mc);
if (t < x[2]) { if (t < x[2]) {
// add shadows effect: // add shadows effect:
double stv = xexp(msc * xlog(stretched / mfc)); double stv = xexp(max(msc * xlog(stretched / mfc),-236.0));
double sbase = pfull (stv, x[8], x[7], 0.5); double sbase = pfull_alt (stv, x[7], 0.5);
return mfc * (sbase <= 1e-14 ? 0.0 : xexp(xlog(sbase) / msc)); return mfc * xexp(xlog(sbase) / msc);
} else { } else {
// add highlights effect: // add highlights effect:
double htv = xexp(mhc * xlog((stretched - mfc) / (1 - mfc))); double htv = xexp(max(mhc * xlog((stretched - mfc) / (1.0 - mfc)),-236.0));
double hbase = pfull (htv, x[8], 0.5, x[4]); double hbase = pfull_alt (htv, 0.5, x[4]);
return mfc + (1 - mfc) * (hbase <= 1e-14 ? 0.0 : xexp(xlog(hbase) / mhc)); //this part of the curve isn't affected by highlight, return the base curve
if (hbase < 1e-6 ){
return stretched;
} else {
return mfc + (1.0 - mfc) * xexp(xlog(hbase) / mhc);
}
} }
break; break;