Files
glsl_playground/utilities/flong.glsl

268 lines
6.1 KiB
GLSL

// these are shaping functions taken from various places of https://flong.com
// Polynominal shaping
float blinn_wyvill_cos_approx(float x) {
float x2 = x*x;
float x4 = x2*x2;
float x6 = x4*x2;
float fa = ( 4.0/9.0);
float fb = (17.0/9.0);
float fc = (22.0/9.0);
return fa*x6 - fb*x4 + fc*x2;
}
// TODO: factor out clamping
float double_cubic_seat(float x, vec2 ab) {
float epsilon = 0.00001;
float min_param_a = 0.0 + epsilon;
float max_param_a = 1.0 - epsilon;
float min_param_b = 0.0;
float max_param_b = 1.0;
float a = clamp(ab.x, min_param_a, max_param_a);
float b = clamp(ab.y, min_param_b, max_param_b);
if (x <= a){
return b - b*pow(1.-x/a, 3.0);
}
return b + (1.-b)*pow((x-a)/(1.-a), 3.0);
}
float double_cubic_seat_linear_blend(float x, vec2 ab) {
float epsilon = 0.00001;
float min_param_a = 0.0 + epsilon;
float max_param_a = 1.0 - epsilon;
float min_param_b = 0.0;
float max_param_b = 1.0;
float a = clamp(ab.x, min_param_a, max_param_a);
float b = clamp(ab.y, min_param_b, max_param_b);
b = 1.0 - b;
if (x<=a){
return b*x + (1.-b)*a*(1.-pow(1.-x/a, 3.));
}
return b*x + (1.-b)*(a + (1.-a)*pow((x-a)/(1.-a), 3.));
}
float double_odd_polynomial_seat(float x, float a, float b, float n) {
float epsilon = 0.00001;
float min_param_a = 0.0 + epsilon;
float max_param_a = 1.0 - epsilon;
float min_param_b = 0.0;
float max_param_b = 1.0;
a = clamp(a, min_param_a, max_param_a);
b = clamp(b, min_param_b, max_param_b);
float p = 2.*n + 1.;
if (x <= a){
return b - b*pow(1.-x/a, p);
}
return b + (1.-b)*pow((x-a)/(1.-a), p);
}
float double_poly_sigmoid(float x, float a, float b, float n) {
if(mod(n, 2.) == 0.) {
if(x <= 0.5) {
return pow(2.0*x, n)/2.0;
}
return 1.0 - pow(2.*(x-1.), n)/2.0;
} else {
if (x<=0.5){
return pow(2.0*x, n)/2.0;
}
return 1.0 + pow(2.0*(x-1.), n)/2.0;
}
}
float quad_through_point(float x, vec2 ab) {
float epsilon = 0.00001;
float min_param_a = 0.0 + epsilon;
float max_param_a = 1.0 - epsilon;
float min_param_b = 0.0;
float max_param_b = 1.0;
float a = clamp(ab.x, min_param_a, max_param_a);
float b = clamp(ab.y, min_param_b, max_param_b);
float A = (1.-b)/(1.-a) - (b/a);
float B = (A*(a*a)-b)/a;
float y = A*(x*x) - B*(x);
y = clamp(0., 1., y);
return y;
}
// exponential shaping
float exp_easing(float x, float a) {
float e = 0.00001;
a = clamp(a, 0.+e, 1.-e);
if (a < 0.5) {
a = 2.0*(a);
return pow(x, a);
}
a = 2.*(a-.5);
return pow(x, 1./(1.-a));
}
float double_exp_seat(float x, float a) {
float e = 0.00001;
a = clamp(a, .0+e, 1.-e);
if (x<=0.5) {
return pow(2.*x, 1.-a)/2.0;
}
return 1. - pow(2.*(1.-x), 1.-a)/2.;
}
float double_exp_sigmoid(float x, float a) {
float e = 0.00001;
a = 1.-clamp(a, .0+e, 1.-e);
if (x<=0.5){
return pow(2.0*x, 1.0/a)/2.0;
}
return 1.0 - (pow(2.0*(1.0-x), 1.0/a))/2.0;
}
float normalized_log_sigmoid(float x, float a) {
float e = 0.0001;
a = 1./(1.-clamp(a, 0.+e, 1.-e)) - 1.;
float b = 1.0 / (1.0 + exp(a));
float c = 1.0 / (1.0 + exp(0.-a));
a = 1. / (1. + exp(0. -((x-.5)*a*2.)));
return (a-b)/(c-b);
}
// bezier shaping
float quad_bezier(float x, vec2 ab) {
float e = 0.00001;
float a = clamp(ab.x, 0., 1.);
float b = clamp(ab.y, 0., 1.);
if (a == 0.5) a += e;
float om2a = 1. - 2.*a;
float t = (sqrt(a*a + om2a*x) - a)/om2a;
return (1.-2.*b)*(t*t) + (2.*b)*t;
}
// cubic bezier begin
float slope_from_t(float t, float A, float B, float C) {
return 1.0/(3.0*A*t*t + 2.0*B*t + C);
}
float x_from_t(float t, float A, float B, float C, float D) {
return A*(t*t*t) + B*(t*t) + C*t + D;
}
float y_from_t(float t, float E, float F, float G, float H) {
return E*(t*t*t) + F*(t*t) + G*t + H;
}
float cubic_bezier(float x, vec2 a, vec2 b) {
float y0a = 0.00;
float x0a = 0.00;
float y1a = a.y;
float x1a = a.x;
float y2a = b.y;
float x2a = b.x;
float y3a = 1.00;
float x3a = 1.00;
float A = x3a - 3.*x2a + 3.*x1a - x0a;
float B = 3.*x2a - 6.*x1a + 3.*x0a;
float C = 3.*x1a - 3.*x0a;
float D = x0a;
float E = y3a - 3.*y2a + 3.*y1a - y0a;
float F = 3.*y2a - 6.*y1a + 3.*y0a;
float G = 3.*y1a - 3.*y0a;
float H = y0a;
float currentt = x;
for (int i=0; i < 5; i++){
float currentx = x_from_t(currentt, A, B, C, D);
float currentslope = slope_from_t(currentt, A, B, C);
currentt -= (currentx - x)*(currentslope);
currentt = clamp(currentt, 0., 1.);
}
float y = y_from_t(currentt, E, F, G, H);
return y;
}
// cubic bezier end
// cubic bezier through points (requires cubic bezier) begin
float b0 (float t){
return (1.-t)*(1.-t)*(1.-t);
}
float b1 (float t){
return 3.*t* (1.-t)*(1.-t);
}
float b2 (float t){
return 3.*t*t* (1.-t);
}
float b3 (float t){
return t*t*t;
}
float findx(float t, float x0, float x1, float x2, float x3) {
return x0*b0(t) + x1*b1(t) + x2*b2(t) + x3*b3(t);
}
float findy(float t, float y0, float y1, float y2, float y3) {
return y0*b0(t) + y1*b1(t) + y2*b2(t) + y3*b3(t);
}
float cubic_bezier_through(float x, vec2 a, vec2 b) {
float y = 0.;
float e = 0.00001;
float minp = 0. + e;
float maxp = 1. - e;
a = clamp(a, minp, maxp);
b = clamp(b, minp, maxp);
float x0 = 0.;
float y0 = 0.;
float x4 = a.x;
float y4 = a.y;
float x5 = b.x;
float y5 = b.y;
float x3 = 1.;
float y3 = 1.;
float x1,y1,x2,y2;
// arbitrary but reasonable
float t1 = 0.3;
float t2 = 0.7;
float b0t1 = b0(t1);
float b1t1 = b1(t1);
float b2t1 = b2(t1);
float b3t1 = b3(t1);
float b0t2 = b0(t2);
float b1t2 = b1(t2);
float b2t2 = b2(t2);
float b3t2 = b3(t2);
float ccx = x4 - x0*b0t1 - x3*b3t1;
float ccy = y4 - y0*b0t1 - y3*b3t1;
float ffx = x5 - x0*b0t2 - x3*b3t2;
float ffy = y5 - y0*b0t2 - y3*b3t2;
x2 = (ccx - (ffx*b1t1)/b1t2) / (b2t1 - (b1t1*b2t2)/b1t2);
y2 = (ccy - (ffy*b1t1)/b1t2) / (b2t1 - (b1t1*b2t2)/b1t2);
x1 = (ccx - x2*b2t1) / b1t1;
y1 = (ccy - y2*b2t1) / b1t1;
x1 = clamp(x1, minp, maxp);
x2 = clamp(x2, minp, maxp);
y = cubic_bezier(x, vec2(x1,y1), vec2(x2,y2));
return clamp(y, 0., 1.);
}
// cubic bezier through points end