ShapingCommon.bslinc 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. mixin ShapingCommon
  2. {
  3. code
  4. {
  5. #define EPSILON 0.00001f
  6. #define PI 3.1415926f
  7. float almostIdentity(float x, float m, float n)
  8. {
  9. if(x > m)
  10. return x;
  11. float a = 2.0f * n - m
  12. float b = 2.0f * m - 3.0f * n;
  13. float t = x / m;
  14. return (a * t + b) * t * t + n;
  15. }
  16. float gain(float x, float k)
  17. {
  18. float a = 0;
  19. float res = 0;
  20. if(x < 0.5f)
  21. a = 0.5f * pow(2.0f * x, k);
  22. else
  23. a = 0.5f * pow(2.0f * (1.0f - x), k);
  24. if(x < 0.5f)
  25. res = a;
  26. else
  27. res = 1.0f - a;
  28. return res;
  29. }
  30. float parabola(float x, float k)
  31. {
  32. return pow(4.0f * x * (1.0f - x), k);
  33. }
  34. // Power curve
  35. float pcurve(float x, float a, float b)
  36. {
  37. float k = pow(a + b, a + b) / (pow(a, a) * pow(b, b));
  38. return k * pow(x, a) * pow(1.0f - x, b);
  39. }
  40. // Sinc Curve
  41. float sinc(float x, float k)
  42. {
  43. float a = PI * ((float(k) * x - 1.0f);
  44. return sin(a) / a;
  45. }
  46. // Blinn-Wyvill Approximation to the Raised Inverted Cosine
  47. float cosApprox(float x)
  48. {
  49. float x2 = x * x;
  50. float x4 = x2 * x2;
  51. float x6 = x4 * x2;
  52. float fa = (4.0f / 9.0f);
  53. float fb = (17.0f / 9.0f);
  54. float fc = (22.0f / 9.0f);
  55. return fa * x6 - fb * x4 + fc * x2;
  56. }
  57. // Seat shaped function formed by joining two 3rd order polynomial curves
  58. // The curves meet with a horizontal inflection point at the control coordinate (a, b) in the unit square
  59. float cubicSeat(float x, float a, float b)
  60. {
  61. float minA = 0.0f + EPSILON;
  62. float maxA = 1.0f - EPSILON;
  63. float minB = 0.0f;
  64. float maxB = 1.0f;
  65. float res = 0;
  66. a = min(maxA, max(minA, a));
  67. b = min(maxB, max(minB, b));
  68. if (x <= a)
  69. res = b - b * pow(1 - x / a, 3.0f);
  70. else
  71. res = b + (1 - b) * pow((x - a) / (1 - a), 3.0f);
  72. return res;
  73. }
  74. // Double cubic Seat function uses a single variable to control the location of its inflection point along the diagonal of the unit square
  75. // The second parameter is used to blend the curve with the identity function (y = x)
  76. // Uses the variable b to control the blending amount
  77. float cubicSeatWithLinearBlend(float x, float a, float b)
  78. {
  79. float minA = 0.0f + EPSILON;
  80. float maxA = 1.0f - EPSILON;
  81. float minB = 0.0f;
  82. float maxB = 1.0f;
  83. float res = 0;
  84. a = min(maxA, max(minA, a));
  85. b = min(maxB, max(minB, b));
  86. b = 1.0 - b;
  87. if (x <= a)
  88. res = b * x + (1 - b) * a * (1 - pow(1 - x / a, 3.0f));
  89. else
  90. res = b * x + (1 - b) * (a + (1 - a) * pow((x - a) / (1 - a), 3.0f));
  91. return res;
  92. }
  93. float oddPolynomialSeat(float x, float a, float b, int n)
  94. {
  95. float minA = 0.0f + EPSILON;
  96. float maxA = 1.0f - EPSILON;
  97. float minB = 0.0f;
  98. float maxB = 1.0f;
  99. float res = 0;
  100. a = min(maxA, max(minA, a));
  101. b = min(maxB, max(minB, b));
  102. int p = 2 * n + 1;
  103. if (x <= a)
  104. res = b - b * pow(1 - x / a, p);
  105. else
  106. res = b + (1 - b) * pow((x - a) / (1 - a), p);
  107. return res;
  108. }
  109. float polynomialSigmoid(float x, float a, float b, int n)
  110. {
  111. float res = 0;
  112. if (n % 2 == 0)
  113. {
  114. // Even polynomial
  115. if (x <= 0.5f)
  116. res = pow(2.0f * x, n) / 2.0f;
  117. else
  118. res = 1.0f - pow(2 * (x - 1), n) / 2.0f;
  119. }
  120. else
  121. {
  122. // Odd polynomial
  123. if (x <= 0.5f)
  124. res = pow(2.0f * x, n) / 2.0f;
  125. else
  126. res = 1.0f + pow(2.0f * (x - 1), n) / 2.0f;
  127. }
  128. return res;
  129. }
  130. // Defines a parabola which passes through a user provided point (a, b) in the unit square
  131. float quadraticThroughPoint(float x, float a, float b)
  132. {
  133. float minA = 0.0f + EPSILON;
  134. float maxA = 1.0f - EPSILON;
  135. float minB = 0.0f;
  136. float maxB = 1.0f;
  137. a = min(maxA, max(minA, a));
  138. b = min(maxB, max(minB, b));
  139. float fA = (1 - b) / (1 - a) - (b / a);
  140. float fB = (fA * (a * a) - b) / a;
  141. float res = fA * (x * x) - fB * (x);
  142. return min(1, max(0, res));
  143. }
  144. float exponentialEasing(float x, float a)
  145. {
  146. float minA = 0.0f + EPSILON;
  147. float maxA = 1.0f - EPSILON;
  148. float res = 0;
  149. a = max(minA, min(maxA, a));
  150. if (a < 0.5f)
  151. {
  152. a = 2.0f * a;
  153. res = pow(x, a);
  154. }
  155. else
  156. {
  157. a = 2.0f * (a - 0.5f);
  158. res = pow(x, 1.0f / (1 - a));
  159. }
  160. return res;
  161. }
  162. float exponentialSeat(float x, float a)
  163. {
  164. float minA = 0.0f + EPSILON;
  165. float maxA = 1.0f - EPSILON;
  166. float res = 0;
  167. a = min(maxA, max(minA, a));
  168. if (x <= 0.5f)
  169. res = (pow(2.0f * x, 1 - a)) / 2.0f;
  170. else
  171. res = 1.0f - (pow(2.0f * (1.0f - x), 1 - a)) / 2.0f;
  172. return res;
  173. }
  174. float exponentialSigmoid(float x, float a)
  175. {
  176. float minA = 0.0f + EPSILON;
  177. float maxA = 1.0f - EPSILON;
  178. float res = 0;
  179. a = min(maxA, max(minA, a));
  180. a = 1.0f - a;
  181. if (x <= 0.5f)
  182. res = (pow(2.0f * x, 1.0f / a)) / 2.0f;
  183. else
  184. res = 1.0f - (pow(2.0f * (1.0f - x), 1.0f / a)) / 2.0f;
  185. return res;
  186. }
  187. float logisticSigmoid(float x, float a)
  188. {
  189. float minA = 0.0f + EPSILON;
  190. float maxA = 1.0f - EPSILON;
  191. a = max(minA, min(maxA, a));
  192. a = (1 / (1 - a) - 1);
  193. float fA = 1.0f / (1.0f + exp(0 - ((x - 0.5f) * a * 2.0f)));
  194. float fB = 1.0f / (1.0f + exp(a));
  195. float fC = 1.0f / (1.0f + exp(0 - a));
  196. return (fA - fB) / (fC - fB);
  197. }
  198. // A circular arc for easing in of the unit square.
  199. float circularEaseIn(float x)
  200. {
  201. return 1 - sqrt(1 - x * x);
  202. }
  203. // A circular arc for easing out of the unit square.
  204. float circularEaseOut(float x)
  205. {
  206. return sqrt(1 - pow(1 - x, 2));
  207. }
  208. float circleSeat(float x, float a)
  209. {
  210. float minA = 0.0f;
  211. float maxA = 1.0f;
  212. float res = 0;
  213. a = max(minA, min(maxA, a));
  214. if (x <= a)
  215. res = sqrt(pow(a, 2) - pow(x - a, 2));
  216. else
  217. res = 1 - sqrt(pow(1 - a, 2) - pow(x - a, 2));
  218. return res;
  219. }
  220. float circleSigmoid(float x, float a)
  221. {
  222. float minA = 0.0f;
  223. float maxA = 1.0f;
  224. float res = 0;
  225. a = max(minA, min(maxA, a));
  226. if (x <= a)
  227. res = a - sqrt(a * a - x * x);
  228. else
  229. res = a + sqrt(pow(1 - a, 2) - pow(x - 1, 2));
  230. return res;
  231. }
  232. float ellipticSeat(float x, float a, float b)
  233. {
  234. float minA = 0.0f + EPSILON;
  235. float maxA = 1.0f - EPSILON;
  236. float minB = 0.0f;
  237. float maxB = 1.0f;
  238. float res = 0;
  239. a = max(minA, min(maxA, a));
  240. b = max(minB, min(maxB, b));
  241. if (x <= a)
  242. res = (b / a) * sqrt(pow(a, 2) - pow(x - a, 2));
  243. else
  244. res = 1 - ((1 - b) / (1 - a)) * sqrt(pow(1 - a, 2) - pow(x - a, 2));
  245. return res;
  246. }
  247. float ellipticSigmoid(float x, float a, float b)
  248. {
  249. float minA = 0.0f + EPSILON;
  250. float maxA = 1.0f - EPSILON;
  251. float minB = 0.0f;
  252. float maxB = 1.0f;
  253. float res = 0;
  254. a = max(minA, min(maxA, a));
  255. b = max(minB, min(maxB, b));
  256. if (x <= a)
  257. res = b * (1 - (sqrt(pow(a, 2) - pow(x, 2)) / a));
  258. else
  259. res = b + ((1 - b) / (1 - a)) * sqrt(pow(1 - a, 2) - pow(x - 1));
  260. return res;
  261. }
  262. // Defines a 2nd order Bezier curve with a single spline control point at the coordinate (a, b) in the unit square.
  263. float quadraticBezier(float x, float a, float b)
  264. {
  265. a = max(0, min(1, a));
  266. b = max(0, min(1, b));
  267. if (a == 0.5f)
  268. a += EPSILON;
  269. // Solve t from x (an inverse operation)
  270. float om2a = 1 - 2 * a;
  271. float t = (sqrt(a * a + om2a * x) - a) / om2a;
  272. float res = (1 - 2 * b) * (t * t) + (2 * b) * t;
  273. return res;
  274. }
  275. float slopeFromT(float t, float A, float B, float C)
  276. {
  277. return 1.0f / (3.0f* A * t * t + 2.0f* B * t + C);
  278. }
  279. float xFromT(float t, float A, float B, float C, float D)
  280. {
  281. return A * (t * t * t) + B * (t * t) + C * t + D;
  282. }
  283. float yFromT(float t, float E, float F, float G, float H)
  284. {
  285. return E * (t * t * t) + F * (t * t) + G * t + H;
  286. }
  287. float cubicBezier(float x, float a, float b, float c, float d)
  288. {
  289. float y0a = 0.0f;
  290. float x0a = 0.0f;
  291. float y1a = b;
  292. float x1a = a;
  293. float y2a = d;
  294. float x2a = c;
  295. float y3a = 1.0f;
  296. float x3a = 1.0f;
  297. float A = x3a - 3 * x2a + 3 * x1a - x0a;
  298. float B = 3 * x2a - 6 * x1a + 3 * x0a;
  299. float C = 3 * x1a - 3 * x0a;
  300. float D = x0a;
  301. float E = y3a - 3 * y2a + 3 * y1a - y0a;
  302. float F = 3 * y2a - 6 * y1a + 3 * y0a;
  303. float G = 3 * y1a - 3 * y0a;
  304. float H = y0a;
  305. // Solve for t given x (using Newton-Raphelson), then solve for y given t.
  306. // Assume for the first guess that t = x.
  307. float currentt = x;
  308. int iteration = 5;
  309. for (int i = 0; i < iteration; i++)
  310. {
  311. float currentx = xFromT(currentt, A, B, C, D);
  312. float currentslope = slopeFromT(currentt, A, B, C);
  313. currentt -= (currentx - x) * (currentslope);
  314. currentt = clamp(currentt, 0, 1);
  315. }
  316. float res = yFromT(currentt, E, F, G, H);
  317. return res;
  318. }
  319. float cubicBezierThroughTwoPoints(float x, float a, float b, float c, float d)
  320. {
  321. float minA = 0.0f + EPSILON;
  322. float maxA = 1.0f - EPSILON;
  323. float minB = 0.0f + EPSILON;
  324. float maxB = 1.0f - EPSILON;
  325. float res = 0;
  326. a = max(minA, min(maxA, a));
  327. b = max(minB, min(maxB, b));
  328. float x0 = 0;
  329. float y0 = 0;
  330. float x4 = a;
  331. float y4 = b;
  332. float x5 = c;
  333. float y5 = d;
  334. float x3 = 1;
  335. float y3 = 1;
  336. float x1, y1, x2, y2;
  337. // arbitrary but reasonable
  338. // t-values for interior control points
  339. float t1 = 0.3f;
  340. float t2 = 0.7f;
  341. float B0t1 = (1 - t1) * (1 - t1) * (1 - t1);
  342. float B1t1 = 3.0f * t1 * (1 - t1) * (1 - t1);
  343. float B2t1 = 3.0f * t1 * t1 * (1 - t1);
  344. float B3t1 = t1 * t1 * t1;
  345. float B0t2 = (1 - t2) * (1 - t2) * (1 - t2);
  346. float B1t2 = 3.0f * t2 * (1 - t2) * (1 - t2);
  347. float B2t2 = 3.0f * t2 * t2 * (1 - t2);
  348. float B3t2 = t2 * t2 * t2;
  349. float ccx = x4 - x0 * B0t1 - x3 * B3t1;
  350. float ccy = y4 - y0 * B0t1 - y3 * B3t1;
  351. float ffx = x5 - x0 * B0t2 - x3 * B3t2;
  352. float ffy = y5 - y0 * B0t2 - y3 * B3t2;
  353. x2 = (ccx - (ffx * B1t1) / B1t2) / (B2t1 - (B1t1 * B2t2) / B1t2);
  354. y2 = (ccy - (ffy * B1t1) / B1t2) / (B2t1 - (B1t1 * B2t2) / B1t2);
  355. x1 = (ccx - x2 * B2t1) / B1t1;
  356. y1 = (ccy - y2 * B2t1) / B1t1;
  357. x1 = max(0 + EPSILON, min(1 - EPSILON, x1));
  358. x2 = max(0 + EPSILON, min(1 - EPSILON, x2));
  359. res = cubicBezier(x, x1, y1, x2, y2);
  360. res = max(0, min(1, y));
  361. return res;
  362. }
  363. };
  364. };