diff --git a/src/doc/languagespec.tex b/src/doc/languagespec.tex index 7c90ed198..68d5b38e9 100644 --- a/src/doc/languagespec.tex +++ b/src/doc/languagespec.tex @@ -3488,42 +3488,43 @@ \section{Pattern generation} performed component-by-component (separately for $x$, $y$, and $z$). \apiend -\apiitem{float {\ce linearstep} (float edge0, float edge1, float x) \\ -\emph{type} {\ce linearstep} (\emph{type} edge0, \emph{type} edge1, \emph{type} x)} +\apiitem{float {\ce linearstep} (float low, float high, float x) \\ +\emph{type} {\ce linearstep} (\emph{type} low, \emph{type} high, \emph{type} x)} \indexapi{linearstep()} -Returns 0 if $x \le {\mathit edge0}$, and 1 if $x \ge {\mathit edge1}$, +Returns 0 if $x \le {\mathit low}$, and 1 if $x \ge {\mathit high}$, and performs a linear -interpolation between 0 and 1 when ${\mathit edge0} < x < {\mathit edge1}$. -This is equivalent to {\cf step(edge0, x)} when {\cf edge0 == edge1}. +interpolation between 0 and 1 when ${\mathit low} < x < {\mathit high}$. +This is equivalent to {\cf step(low, x)} when {\cf low == high}. For \color and \point-like types, the computations are performed component-by-component (separately for $x$, $y$, and $z$). \apiend -\apiitem{float {\ce smoothstep} (float edge0, float edge1, float x) \\ -\emph{type} {\ce smoothstep} (\emph{type} edge0, \emph{type} edge1, \emph{type} x)} +\apiitem{float {\ce smoothstep} (float low, float high, float x) \\ +\emph{type} {\ce smoothstep} (\emph{type} low, \emph{type} high, \emph{type} x)} \indexapi{smoothstep()} -Returns 0 if $x \le {\mathit edge0}$, and 1 if $x \ge {\mathit edge1}$, +Returns 0 if $x \le {\mathit low}$, and 1 if $x \ge {\mathit high}$, and performs a smooth Hermite -interpolation between 0 and 1 when ${\mathit edge0} < x < {\mathit edge1}$. +interpolation between 0 and 1 when ${\mathit low} < x < {\mathit high}$. This is useful in cases where you would want a thresholding function -with a smooth transition. +with a smooth transition. In the degenerate case where ${\mathit high} \le +{\mathit low}$, the return value will be 0 if $x < {\mathit high}$ and 1 if $x +\ge {\mathit high}$, making the behavior identical to `step(high, x)`. The \emph{type} may be any of of \float, \color, \point, \vector, or \normal. For \color and \point-like types, the computations are performed component-by-component. \apiend -\apiitem{float {\ce smooth_linearstep} (float edge0, float edge1, float x, float eps) \\ -\emph{type} {\ce smooth_linearstep} (\emph{type} edge0, \emph{type} edge1, \emph{type} x, \emph{type} eps)} +\apiitem{float {\ce smooth_linearstep} (float low, float high, float x, float eps) \\ +\emph{type} {\ce smooth_linearstep} (\emph{type} low, \emph{type} high, \emph{type} x, \emph{type} eps)} \indexapi{smooth_linearstep()} -This function is strictly linear between ${\mathit edge0}+{\mathit eps}$ and ${\mathit edge1}-{\mathit eps}$ -but smoothly ramps to 0 between ${\mathit edge0}-{\mathit eps}$ and ${\mathit edge0}+{\mathit eps}$ -and smoothly ramps to 1 between ${\mathit edge1}-{\mathit eps}$ and ${\mathit edge1}+{\mathit eps}$. -It is 0 when $x \le {\mathit edge0}-{\mathit eps}$, and 1 if $x \ge {\mathit edge1}+{\mathit eps}$, -and performs a linear -interpolation between 0 and 1 when ${\mathit edge0} < x < {\mathit edge1}$. -For \color and \point-like types, the computations are -performed component-by-component. +This function returns 0 if $x < {\mathit low}-{\mathit eps}$, and 1 if +$x \ge {\mathit high}+{\mathit eps}$, is strictly linear between +${\mathit low}+{\mathit eps}$ and ${\mathit high}-{\mathit eps}$ but smoothly +ramps to 0 between ${\mathit low}-{\mathit eps}$ and ${\mathit low}+{\mathit eps}$ +and smoothly ramps to 1 between ${\mathit high}-{\mathit eps}$ and +${\mathit high}+{\mathit eps}$. For \color and \point-like types, the +computations are performed component-by-component. \apiend diff --git a/src/doc/stdlib.md b/src/doc/stdlib.md index 2fce1e09d..d3e53c870 100644 --- a/src/doc/stdlib.md +++ b/src/doc/stdlib.md @@ -458,36 +458,36 @@ the computations are performed component-by-component (separately for `x`, performed component-by-component (separately for $x$, $y$, and $z$). -`float` **`linearstep`** `(float edge0, float edge1, float x)`
*`type`* **`linearstep`** (*`type`* `edge0`, *`type`* `edge1`, *`type`* `x`) +`float` **`linearstep`** `(float low, float high, float x)`
*`type`* **`linearstep`** (*`type`* `low`, *`type`* `high`, *`type`* `x`) - : Returns 0 if `x` $\le$ `edge0`, and 1 if `x` $\ge$ `edge1`, and performs a - linear interpolation between 0 and 1 when `edge0` $<$ `x` $<$ `edge1`. - This is equivalent to `step(edge0, x)` when `edge0 == edge1`. For `color` + : Returns 0 if `x` $<$ `low`, and 1 if `x` $\ge$ `high`, and performs a + linear interpolation between 0 and 1 when `low` $<$ `x` $<$ `high`. + This is equivalent to `step(low, x)` when `low == high`. For `color` and `point`-like types, the computations are performed component-by-component (separately for $x$, $y$, and $z$). -`float` **`smoothstep`** `(float edge0, float edge1, float x)`
*`type`* **`smoothstep`** (*`type`* `edge0`, *`type`* `edge1`, *`type`* `x`) +`float` **`smoothstep`** `(float low, float high, float x)`
*`type`* **`smoothstep`** (*`type`* `low`, *`type`* `high`, *`type`* `x`) - : Returns 0 if `x` $\le$ `edge0`, and 1 if `x` $\ge$ `edge1`, and performs a - smooth Hermite interpolation between 0 and 1 when `edge0` $<$ `x` $<$ - `edge1`. This is useful in cases where you would want a thresholding - function with a smooth transition. + : Returns 0 if `x` $\le$ `low`, and 1 if `x` $\ge$ `high`, and performs a + smooth Hermite interpolation between 0 and 1 when `low` $<$ `x` $<$ + `high`. This is useful in cases where you would want a thresholding + function with a smooth transition. In the degenerate case where + `high` $\le$ `low`, the return value will be 0 if `x` $<$ `high` and 1 if + `x` $\ge$ `high`, making the behavior identical to `step(high, x)`. The *`type`* may be any of of `float`, `color`, `point`, `vector`, or `normal`. For `color` and `point`-like types, the computations are performed component-by-component. -`float` **`smooth_linearstep`** `(float edge0, float edge1, float x, float eps)`
*`type`* **`smooth_linearstep`** (*`type`* `edge0`, *`type`* `edge1`, *`type`* `x`, *`type`* eps) +`float` **`smooth_linearstep`** `(float low, float high, float x, float eps)`
*`type`* **`smooth_linearstep`** (*`type`* `low`, *`type`* `high`, *`type`* `x`, *`type`* eps) - : This function is strictly linear between `edge0 + eps` and `edge1 - eps` - but smoothly ramps to 0 between `edge0 - eps` and `edge0 + eps` - and smoothly ramps to 1 between `edge1 - eps` and `edge1 + eps`. - It is 0 when `x` $\le$ `edge0-eps,` and 1 if `x` $\ge$ `edge1 + eps`, - and performs a linear interpolation between 0 and 1 when - `edge0` < x < `edge1`. For `color` and `point`-like types, the - computations are performed component-by-component. + : This function returns 0 if `x` $<$ `low-eps`, and 1 if `x` $\ge$ `high + eps`, + is strictly linear between `low + eps` and `high - eps`, but smoothly + ramps to 0 between `low - eps` and `low + eps` and smoothly ramps to 1 + between `high - eps` and `high + eps`. For `color` and `point`-like types, + the computations are performed component-by-component. %## Noise functions diff --git a/src/include/OSL/dual.h b/src/include/OSL/dual.h index a7b5e4063..b3eb8685d 100644 --- a/src/include/OSL/dual.h +++ b/src/include/OSL/dual.h @@ -1311,27 +1311,29 @@ safe_fmod (const Dual& a, const Dual& b) -OSL_HOSTDEVICE OSL_FORCEINLINE float smoothstep(float e0, float e1, float x) { - if (x < e0) return 0.0f; - else if (x >= e1) return 1.0f; - else { - float t = (x - e0)/(e1 - e0); +OSL_HOSTDEVICE OSL_FORCEINLINE float smoothstep(float low, float high, float x) { + if (x >= high) { + return 1.0f; + } else if (x <= low) { + return 0.0f; + } else { + float t = (x - low) / (high - low); return (3.0f-2.0f*t)*(t*t); } } -// f(t) = (3-2t)t^2, t = (x-e0)/(e1-e0) +// f(t) = (3-2t)t^2, t = (x-low)/(high-low) template -OSL_HOSTDEVICE OSL_FORCEINLINE Dual smoothstep (const Dual &e0, const Dual &e1, const Dual &x) +OSL_HOSTDEVICE OSL_FORCEINLINE Dual smoothstep (const Dual &low, const Dual &high, const Dual &x) { - if (x.val() < e0.val()) { - return Dual (T(0)); - } - else if (x.val() >= e1.val()) { - return Dual (T(1)); - } - Dual t = (x - e0)/(e1-e0); - return (T(3) - T(2)*t)*t*t; + if (x.val() >= high.val()) { + return Dual(T(1)); + } else if (x.val() <= low.val()) { + return Dual(T(0)); + } else { + Dual t = (x - low) / (high - low); + return (T(3) - T(2)*t)*t*t; + } } diff --git a/src/shaders/stdosl.h b/src/shaders/stdosl.h index 98ecbf8da..d32771749 100644 --- a/src/shaders/stdosl.h +++ b/src/shaders/stdosl.h @@ -319,73 +319,73 @@ point step (point edge, point x) BUILTIN; vector step (vector edge, vector x) BUILTIN; normal step (normal edge, normal x) BUILTIN; float step (float edge, float x) BUILTIN; -float smoothstep (float edge0, float edge1, float x) BUILTIN; +float smoothstep (float low, float high, float x) BUILTIN; -color smoothstep (color edge0, color edge1, color x) +color smoothstep (color low, color high, color x) { - return color (smoothstep(edge0[0], edge1[0], x[0]), - smoothstep(edge0[1], edge1[1], x[1]), - smoothstep(edge0[2], edge1[2], x[2])); + return color (smoothstep(low[0], high[0], x[0]), + smoothstep(low[1], high[1], x[1]), + smoothstep(low[2], high[2], x[2])); } -vector smoothstep (vector edge0, vector edge1, vector x) +vector smoothstep (vector low, vector high, vector x) { - return vector (smoothstep(edge0[0], edge1[0], x[0]), - smoothstep(edge0[1], edge1[1], x[1]), - smoothstep(edge0[2], edge1[2], x[2])); + return vector (smoothstep(low[0], high[0], x[0]), + smoothstep(low[1], high[1], x[1]), + smoothstep(low[2], high[2], x[2])); } -float linearstep (float edge0, float edge1, float x) { +float linearstep (float low, float high, float x) { float result; - if (edge0 != edge1) { - float xclamped = clamp (x, edge0, edge1); - result = (xclamped - edge0) / (edge1 - edge0); + if (low != high) { + float xclamped = clamp (x, low, high); + result = (xclamped - low) / (high - low); } else { // special case: edges coincide - result = step (edge0, x); + result = step (low, x); } return result; } -color linearstep (color edge0, color edge1, color x) +color linearstep (color low, color high, color x) { - return color (linearstep(edge0[0], edge1[0], x[0]), - linearstep(edge0[1], edge1[1], x[1]), - linearstep(edge0[2], edge1[2], x[2])); + return color (linearstep(low[0], high[0], x[0]), + linearstep(low[1], high[1], x[1]), + linearstep(low[2], high[2], x[2])); } -vector linearstep (vector edge0, vector edge1, vector x) +vector linearstep (vector low, vector high, vector x) { - return vector (linearstep(edge0[0], edge1[0], x[0]), - linearstep(edge0[1], edge1[1], x[1]), - linearstep(edge0[2], edge1[2], x[2])); + return vector (linearstep(low[0], high[0], x[0]), + linearstep(low[1], high[1], x[1]), + linearstep(low[2], high[2], x[2])); } -float smooth_linearstep (float edge0, float edge1, float x_, float eps_) { +float smooth_linearstep (float low, float high, float x_, float eps_) { float result; - if (edge0 != edge1) { + if (low != high) { float rampup (float x, float r) { return 0.5/r * x*x; } - float width_inv = 1.0 / (edge1 - edge0); + float width_inv = 1.0 / (high - low); float eps = eps_ * width_inv; - float x = (x_ - edge0) * width_inv; + float x = (x_ - low) * width_inv; if (x <= -eps) result = 0; else if (x >= eps && x <= 1.0-eps) result = x; else if (x >= 1.0+eps) result = 1; else if (x < eps) result = rampup (x+eps, 2.0*eps); else /* if (x < 1.0+eps) */ result = 1.0 - rampup (1.0+eps - x, 2.0*eps); } else { - result = step (edge0, x_); + result = step (low, x_); } return result; } -color smooth_linearstep (color edge0, color edge1, color x, color eps) +color smooth_linearstep (color low, color high, color x, color eps) { - return color (smooth_linearstep(edge0[0], edge1[0], x[0], eps[0]), - smooth_linearstep(edge0[1], edge1[1], x[1], eps[1]), - smooth_linearstep(edge0[2], edge1[2], x[2], eps[2])); + return color (smooth_linearstep(low[0], high[0], x[0], eps[0]), + smooth_linearstep(low[1], high[1], x[1], eps[1]), + smooth_linearstep(low[2], high[2], x[2], eps[2])); } -vector smooth_linearstep (vector edge0, vector edge1, vector x, vector eps) +vector smooth_linearstep (vector low, vector high, vector x, vector eps) { - return vector (smooth_linearstep(edge0[0], edge1[0], x[0], eps[0]), - smooth_linearstep(edge0[1], edge1[1], x[1], eps[1]), - smooth_linearstep(edge0[2], edge1[2], x[2], eps[2])); + return vector (smooth_linearstep(low[0], high[0], x[0], eps[0]), + smooth_linearstep(low[1], high[1], x[1], eps[1]), + smooth_linearstep(low[2], high[2], x[2], eps[2])); } float aastep (float edge, float s, float dedge, float ds) {