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);
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
static inline double baseu(double x, double m1, double 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
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);
}
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 fillDyByDx();

View File

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