前言 学习资料:The Book of Shaders: Shaping functions 
记录-color部分 vec4 vector; vector[0] = vector.r = vector.x = vector.s; vector[1] = vector.g = vector.y = vector.t; vector[2] = vector.b = vector.z = vector.p; vector[3] = vector.a = vector.w = vector.q; 
 
支持swizzle(搅动):vec3 yellow=vec3(1.,1.,0.); yellow.rgb, yellow.rgr, yellow.bgr ……
利用mix()进行color混合:mix(color1,color2,value) ,value从0到1,value越小color1值越多
#ifdef GL_ES precision  mediump  float ;#endif uniform  vec2  u_resolution;uniform  float  u_time;vec3  colorA = vec3 (0.149 ,0.141 ,0.912 ); vec3  colorB = vec3 (1.000 ,0.833 ,0.224 ); void  main() {    vec3  color = vec3 (0.0 );     float  pct = abs (sin (u_time));                color = mix (colorA, colorB, pct);     gl_FragColor  = vec4 (color,1.0 ); } 
 
easing function 用于计算动画的缓动函数easing function 
下面的式子有些作者进行了sin/cos之间的变换,以及命名的风格是sineIn就是上面链接里的easeInSine 
上面网页里,每个函数都有对应的css用法,postcss用法,在元素变换动画里的效果,在颜色渐变混合里的效果,使用该函数进行变换的样例(缩放、移动、透明度变化),也可以调整参数点击go进行对比 
最后一排:css的实现是通过@keyframes,设置不同的条件;函数里面是通过一系列的判断来赋值; 
前四排的都是cube-bezier 函数设置不同的参数得到的效果 
 
在 CSS 中,cubic-bezier 函数用于定义一个三次贝塞尔曲线,广泛应用于动画和过渡效果的时间函数(timing function)。这个函数的四个参数控制曲线的形状,从而影响动画的速度变化。
具体来说,cubic-bezier(.12, 0, .33, 0) 中的四个参数表示的是两个控制点的坐标:
第一个控制点的坐标为 (0.12, 0) 
第二个控制点的坐标为 (0.33, 0) 
 
这四个参数可以这样解释:
**第一个参数 (0.12)**:这是第一个控制点的横坐标,它影响动画开始阶段的加速度。值为 0.12 表示在动画开始阶段,速度从零开始缓慢增加。 
**第二个参数 (0)**:这是第一个控制点的纵坐标,它在这里设为 0,意味着控制点位于起始线上,因此动画起始时会比较平缓,没有立即加速。 
**第三个参数 (0.33)**:这是第二个控制点的横坐标,影响动画结束前的减速过程。值较小(0.33)表明动画在结束前不久开始减速。 
**第四个参数 (0)**:这是第二个控制点的纵坐标,同样为 0,意味着结束时速度减到 0,动画结束的过程也是比较平缓的。 
 
通过调整这些参数,开发者可以精确控制动画的速度曲线,从而创造出各种动画效果。在这个具体例子中,由于两个控制点的纵坐标都是 0,这种曲线通常用于创建某些具有明显起始和结束阶段的动画效果。
 
#ifdef GL_ES precision  mediump  float ;#endif #define PI 3.141592653589793 #define HALF_PI 1.5707963267948966 uniform  vec2  u_resolution;uniform  vec2  u_mouse;uniform  float  u_time;float  linear(float  t) {  return  t; } float  exponentialIn(float  t) {  return  t == 0.0  ? t : pow (2.0 , 10.0  * (t - 1.0 )); } float  exponentialOut(float  t) {  return  t == 1.0  ? t : 1.0  - pow (2.0 , -10.0  * t); } float  exponentialInOut(float  t) {  return  t == 0.0  || t == 1.0      ? t     : t < 0.5        ? +0.5  * pow (2.0 , (20.0  * t) - 10.0 )       : -0.5  * pow (2.0 , 10.0  - (t * 20.0 )) + 1.0 ; } float  sineIn(float  t) {  return  sin ((t - 1.0 ) * HALF_PI) + 1.0 ; } float  sineOut(float  t) {  return  sin (t * HALF_PI); } float  sineInOut(float  t) {  return  -0.5  * (cos (PI * t) - 1.0 ); } float  qinticIn(float  t) {  return  pow (t, 5.0 ); } float  qinticOut(float  t) {  return  1.0  - (pow (t - 1.0 , 5.0 )); } float  qinticInOut(float  t) {  return  t < 0.5      ? +16.0  * pow (t, 5.0 )     : -0.5  * pow (2.0  * t - 2.0 , 5.0 ) + 1.0 ; } float  quarticIn(float  t) {  return  pow (t, 4.0 ); } float  quarticOut(float  t) {  return  pow (t - 1.0 , 3.0 ) * (1.0  - t) + 1.0 ; } float  quarticInOut(float  t) {  return  t < 0.5      ? +8.0  * pow (t, 4.0 )     : -8.0  * pow (t - 1.0 , 4.0 ) + 1.0 ; } float  quadraticInOut(float  t) {  float  p = 2.0  * t * t;   return  t < 0.5  ? p : -p + (4.0  * t) - 1.0 ; } float  quadraticIn(float  t) {  return  t * t; } float  quadraticOut(float  t) {  return  -t * (t - 2.0 ); } float  cubicIn(float  t) {  return  t * t * t; } float  cubicOut(float  t) {  float  f = t - 1.0 ;   return  f * f * f + 1.0 ; } float  cubicInOut(float  t) {  return  t < 0.5      ? 4.0  * t * t * t     : 0.5  * pow (2.0  * t - 2.0 , 3.0 ) + 1.0 ; } float  elasticIn(float  t) {  return  sin (13.0  * t * HALF_PI) * pow (2.0 , 10.0  * (t - 1.0 )); } float  elasticOut(float  t) {  return  sin (-13.0  * (t + 1.0 ) * HALF_PI) * pow (2.0 , -10.0  * t) + 1.0 ; } float  elasticInOut(float  t) {  return  t < 0.5      ? 0.5  * sin (+13.0  * HALF_PI * 2.0  * t) * pow (2.0 , 10.0  * (2.0  * t - 1.0 ))     : 0.5  * sin (-13.0  * HALF_PI * ((2.0  * t - 1.0 ) + 1.0 )) * pow (2.0 , -10.0  * (2.0  * t - 1.0 )) + 1.0 ; } float  circularIn(float  t) {  return  1.0  - sqrt (1.0  - t * t); } float  circularOut(float  t) {  return  sqrt ((2.0  - t) * t); } float  circularInOut(float  t) {  return  t < 0.5      ? 0.5  * (1.0  - sqrt (1.0  - 4.0  * t * t))     : 0.5  * (sqrt ((3.0  - 2.0  * t) * (2.0  * t - 1.0 )) + 1.0 ); } float  bounceOut(float  t) {  const  float  a = 4.0  / 11.0 ;   const  float  b = 8.0  / 11.0 ;   const  float  c = 9.0  / 10.0 ;   const  float  ca = 4356.0  / 361.0 ;   const  float  cb = 35442.0  / 1805.0 ;   const  float  cc = 16061.0  / 1805.0 ;   float  t2 = t * t;   return  t < a     ? 7.5625  * t2     : t < b       ? 9.075  * t2 - 9.9  * t + 3.4        : t < c         ? ca * t2 - cb * t + cc         : 10.8  * t * t - 20.52  * t + 10.72 ; } float  bounceIn(float  t) {  return  1.0  - bounceOut(1.0  - t); } float  bounceInOut(float  t) {  return  t < 0.5      ? 0.5  * (1.0  - bounceOut(1.0  - t * 2.0 ))     : 0.5  * bounceOut(t * 2.0  - 1.0 ) + 0.5 ; } float  backIn(float  t) {  return  pow (t, 3.0 ) - t * sin (t * PI); } float  backOut(float  t) {  float  f = 1.0  - t;   return  1.0  - (pow (f, 3.0 ) - f * sin (f * PI)); } float  backInOut(float  t) {  float  f = t < 0.5      ? 2.0  * t     : 1.0  - (2.0  * t - 1.0 );   float  g = pow (f, 3.0 ) - f * sin (f * PI);   return  t < 0.5      ? 0.5  * g     : 0.5  * (1.0  - g) + 0.5 ; } void  main() {    vec3  colorA = vec3 (0.149 ,0.141 ,0.912 );     vec3  colorB = vec3 (1.000 ,0.833 ,0.224 );     float  t = u_time*0.5 ;     float  pct = cubicInOut( abs (fract (t)*2.0 -1. ) );  	    	       gl_FragColor  = vec4 (vec3 (mix (colorA, colorB, pct)),1.0 ); } 
 
补充说明:
float  t = u_time * 0.5 ;float  pct = cubicInOut(abs (fract (t) * 2.0  - 1.0 ));
 
**时间缩放 (t = u_time * 0.5)**:这里 u_time 被乘以 0.5,意味着 t 的变化速度是 u_time 的一半。如果 u_time 是一个随时间增加的变量,那么 t 的增长速度更慢。 
**计算 pct**:fract(t) 获取 t 的小数部分,这样即使 t 增长到 1 以上,fract(t) 也会重新从 0 开始,实现周期性重置。乘以 2.0 然后减 1.0 是为了将周期变化从 [0,1] 调整到 [-1,1],这样 abs(...) 后的值将在 [0,1] 之间振荡,实现了先增加到 1 然后减少到 0 的周期性变化。 
cubicInOut 动画曲线 :这个函数通常定义了一个缓入缓出的三次曲线,意味着动画开始和结束时速度较慢,中间速度较快。 
 
t = u_time; pct = cubicInOut(abs (fract (t) - 1.0 )); 
 
**时间设置 (t = u_time)**:这里没有对 u_time 进行缩放,因此 t 以原始速度增加。 
**计算 pct**:这里仅使用了 fract(t) 减去 1.0,与上面的代码相比,这样处理会产生从 -1 到 0 的周期性变化(因为 fract(t) 产生 [0,1),减 1 后变为 [-1,0))。应用 abs(...) 后,变化将在 [0,1) 间发生,实现了周期性的从 0 增加到 1。 
 
效果差异:
变化速率 :上面的代码中 t 的变化速度为原始时间的一半,这导致整体动画速度更慢。 
振荡方式 :上面的代码使得振荡从 0 增加到 1 然后减少到 0,形成一个完整的循环,而下面的代码只从 0 增加到 1。 
 
结合这些分析,上面的代码提供了一个更平滑和对称的振荡模式,适用于需要循环动画效果的场景,如呼吸灯效果。下面的代码则更适合于单向的渐进或渐出效果,如日出效果。
颜色的渐变 ...... void main() {     vec3 color = vec3(0.0); 	 vec2 st = gl_FragCoord.xy/u_resolution;     float pct = cubicInOut(st.y);      pct = circularInOut(st.y); // 因为InOut那边的曲线是在很小范围内的自变量下发生了较大的因变量变化,所以分界线会明显,相对上面的来说     // Mix uses pct (a value from 0-1) to     // mix the two colors     color = mix(colorA, colorB, pct);     gl_FragColor = vec4(color,1.0); } 
 
mix对RGB三个通道的控制 可以分别设置RGB三通道的混合方式
示例
#ifdef GL_ES precision  mediump  float ;#endif #define PI 3.14159265359 uniform  vec2  u_resolution;uniform  vec2  u_mouse;uniform  float  u_time;vec3  colorA = vec3 (0.149 ,0.141 ,0.912 );vec3  colorB = vec3 (1.000 ,0.833 ,0.224 );float  plot (vec2  st, float  pct){  return   smoothstep ( pct-0.01 , pct, st.y) -           smoothstep ( pct, pct+0.01 , st.y);  } void  main() {    vec2  st = gl_FragCoord .xy/u_resolution.xy;     vec3  color = vec3 (0.0 );     vec3  pct = vec3 (st.x);     pct.r = smoothstep (0.0 ,1.0 , st.x);     pct.g = sin (st.x*PI);     pct.b = pow (st.x,0.5 );     color = mix (colorA, colorB, pct);          color = mix (color,vec3 (1.0 ,1.0 ,1.0 ),plot(st,pct.r));     color = mix (color,vec3 (1.0 ,1.0 ,1.0 ),plot(st,pct.g));     color = mix (color,vec3 (1.0 ,1.0 ,1.0 ),plot(st,pct.b));     gl_FragColor  = vec4 (color,1.0 ); } 
 
混合加变换的组合
...... void  main() {    vec3  color1 = vec3 (0.149 ,0.141 ,0.912 );     vec3  color2 = vec3 (1.000 ,0.833 ,0.224 );        vec2  st = gl_FragCoord .xy/u_resolution;        vec3  colorA = mix (color1,color2,st.y);     vec3  colorB = mix (color1,color2,1. -st.y*st.x);     float  t = u_time*0.5 ;     float  pct = cubicInOut( abs (fract (t)*2.0 -1. ) );  	    	       gl_FragColor  = vec4 (vec3 (mix (colorA, colorB, pct)),1.0 ); } 
 
HSV 
shadertoy代码:
Smooth HSV (shadertoy.com) 
OpenCV学习笔记——HSV颜色空间超极详解&inRange函数用法及实战_hsv值是什么-CSDN博客 
HSV色彩空间和颜色分量范围 - 友善的狗W - 博客园 (cnblogs.com) 
 
RGB和HSV的互转
#ifdef GL_ES precision  mediump  float ;#endif uniform  vec2  u_resolution;uniform  float  u_time;vec3  rgb2hsb( in  vec3  c ){    vec4  K = vec4 (0.0 , -1.0  / 3.0 , 2.0  / 3.0 , -1.0 );     vec4  p = mix (vec4 (c.bg, K.wz),                  vec4 (c.gb, K.xy),                  step (c.b, c.g));     vec4  q = mix (vec4 (p.xyw, c.r),                  vec4 (c.r, p.yzx),                  step (p.x, c.r));     float  d = q.x - min (q.w, q.y);     float  e = 1.0e-10 ;     return  vec3 (abs (q.z + (q.w - q.y) / (6.0  * d + e)),                 d / (q.x + e),                 q.x); } vec3  hsb2rgb( in  vec3  c ){    vec3  rgb = clamp (abs (mod (c.x*6.0 +vec3 (0.0 ,4.0 ,2.0 ),                              6.0 )-3.0 )-1.0 ,                      0.0 ,                      1.0  );     rgb = rgb*rgb*(3.0 -2.0 *rgb);     return  c.z * mix (vec3 (1.0 ), rgb, c.y); } void  main(){    vec2  st = gl_FragCoord .xy/u_resolution;     vec3  color = vec3 (0.0 );               color = hsb2rgb(vec3 (st.x,1.0 ,st.y));      gl_FragColor  = vec4 (color,1.0 ); } 
 
HSB从笛卡尔坐标映射到极坐标:
获取角度和到屏幕中心点的距离 
使用length()和atan(y,x) 
 
#ifdef GL_ES precision mediump float; #endif #define TWO_PI 6.28318530718 uniform vec2 u_resolution; uniform float u_time; //  Function from Iñigo Quiles //  https://www.shadertoy.com/view/MsS3Wc vec3 hsb2rgb( in vec3 c ){     vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),                              6.0)-3.0)-1.0,                      0.0,                      1.0 );     rgb = rgb*rgb*(3.0-2.0*rgb);     return c.z * mix( vec3(1.0), rgb, c.y); } void main(){     vec2 st = gl_FragCoord.xy/u_resolution;     vec3 color = vec3(0.0);     // Use polar coordinates instead of cartesian     vec2 toCenter = vec2(0.5)-st; // 把纹理坐标空间移到-.5到.5     float angle = atan(toCenter.y,toCenter.x); // 求每个点相对于中心点的角度     float radius = length(toCenter)*2.0; // 长度的范围是0~1     // Map the angle (-PI to PI) to the Hue (from 0 to 1)     // and the Saturation to the radius     color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0)); // 第一个表示h,根据相对于中心点的角度来赋予颜色,同时缩放到了0-1,然后传入;radius: 离中心点越远,radius越大,s值越大;     gl_FragColor = vec4(color,1.0); } 
 
var toCenter = st - vec2(0.5);
这样子,把上述的图旋转180度的效果;
推荐待更新。。。 结合shaping function,呈现不同的颜色过渡;