学校类网站特点,电脑做服务器发布网站,北京网站建设制作,怎么改wordpress字体大小———————————————————— 前序 ——————————————————— AndroidLearnOpenGL是本博主自己实现的LearnOpenGL练习集合#xff1a; Github地址#xff1a;GitHub - wangyongyao1989/AndroidLearnOpenGL: OpenGL基础及运用 系列文章#xff…———————————————————— 前序 ——————————————————— AndroidLearnOpenGL是本博主自己实现的LearnOpenGL练习集合 Github地址GitHub - wangyongyao1989/AndroidLearnOpenGL: OpenGL基础及运用 系列文章 1、LearnOpenGL之入门基础 2、LearnOpenGL之3D显示 3、LearnOpenGL之摄像机 4、LearnOpenGL之光照 5、LearnOpenGL之3D模型加载 6、LearnOpenGL之文字渲染 7、LearnOpenGL之高级OpenGL1 8、LearnOpenGL之高级OpenGL2 9、LearnOpenGL之骨骼动画 10、LearnOpenGL之Shader编程用算法绘画
—————————————————————————————————————————— —————————————————— 效果展示 ———————————————————— GLSL着色器编程算法绘画 ———————————————— 一、Shader着色器及GLSL概览 如果你曾经有用计算机绘图的经验你就知道在这个过程中你需要画一个圆然后一个长方形一条线一些三角形……直到画出你想要的图像。这个过程很像用手写一封信或一本书 —— 都是一系列的指令需要你一件一件完成。 Shaders 也是一系列的指令但是这些指令会对屏幕上的每个像素同时下达。也就是说你的代码必须根据像素在屏幕上的不同位置执行不同的操作。就像活字印刷你的程序就像一个 function函数输入位置信息输出颜色信息当它编译完之后会以相当快的速度运行。 shaders并行处理: 想象你的 CPU 是一个大的工业管道然后每一个任务都是通过这个管道的某些东西 —— 就像一个生产流水线那样。有些任务要比别的大也就是说要花费更多时间和精力去处理。我们就称它要求更强的处理能力。由于计算机自身的架构这些任务需要串行即一次一个地依序完成。现代计算机通常有一组四个处理器就像这个管道一样运行一个接一个地处理这些任务从而使计算机流畅运行。每个管道通常被称为线程。 另一个 GPU 的魔法是特殊数学函数可通过硬件加速。非常复杂的数学操作可以直接被微芯片解决而无须通过软件。这就表示可以有更快的三角和矩阵运算 —— 和电流一样快。 GLSL GLSL 代表 openGL Shading LanguageopenGL 着色语言。 Uniforms 我们知道了 GPU 如何处理并行线程每个线程负责给完整图像的一部分配置颜色。尽管每个线程和其他线程之间不能有数据交换但我们能从 CPU 给每个线程输入数据。因为显卡的架构所有线程的输入值必须统一uniform而且必须设为只读。也就是说每条线程接收相同的数据并且是不可改变的数据。 这些输入值叫做 uniform 统一值它们的数据类型通常为float, vec2, vec3, vec4, mat2, mat3, mat4, sampler2D and samplerCube。uniform 值需要数值类型前后一致。且在 shader 的开头在设定精度之后就对其进行定义。 GLSL 还有更多惊喜。GPU 的硬件加速支持我们使用角度三角函数和指数函数。这里有一些这些函数的介绍sin(), cos(), tan(), asin(), acos(), atan(), pow(), exp(), log(), sqrt(), abs(), sign(), floor(), ceil(), fract(), mod(), min(), max() 和 clamp()。 gl_FragCoord 就像 GLSL 有个默认输出值 vec4 gl_FragColor 一样它也有一个默认输入值 vec4 gl_FragCoord 。gl_FragCoord存储了活动线程正在处理的像素或屏幕碎片的坐标。有了它我们就知道了屏幕上的哪一个线程正在运转。为什么我们不叫 gl_FragCoord uniform 统一值呢因为每个像素的坐标都不同所以我们把它叫做 varying变化值。
#ifdef GL_ES
precision mediump float;
#endifuniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;void main() {vec2 st gl_FragCoord.xy/u_resolution;gl_FragColor vec4(st.x,st.y,0.0,1.0);
} 运行shader 可以在 editor.thebookofshaders.com/ 上将其作为独立的 Web 应用运行。 GLSL插件安装 以Android Studio为例在Plugins应用市场中搜索glsl 安装插件后glsl文件高亮显示及函数的智能补全及跳转应用等功能 跳转至builtin.glsl里面有着色器的标准函数 builtin内置标准函数的解析网址为Built-in Variable (GLSL) - OpenGL Wiki GLSL ES参考手册 OpenGL ES着色器语言GLSL ES参考文档
二、Shader的造型函数 smoothstep函数 smoothstep函数是GLSL中用于实现平滑插值的函数之一它可以在指定起止边界的范围内将一个给定的值进行平滑插值。smoothstep函数在图形渲染中常常用于平滑过渡例如在着色器计算过程中将颜色值进行平滑渐变从而实现渐变效果。 smoothstep (edge0, edge1, x)
edge0float类型的起始边界edge1float类型的终止边界xfloat类型的输入值返回值返回一个float类型的值这个值的范围在[0, 1]之间代表了输入值经过平滑插值后的结果。 代码实现
float smoothstep (float edge0, float edge1, float x) {// Scale, and clamp x to 0..1 rangex clamp((x - edge0) / (edge1 - edge0));return x * x * (3.0f - 2.0f * x);
}float clamp(float x, float lowerlimit 0.0f,float upperlimit 1.0f) {if (x lowerlimit) return lowerlimit;if (x upperlimit) return upperlimit;return x;
} 下面这个例子实现从黑色到白色的渐变,并画一条红线的着色器代码
#version 320 es
precision mediump float;out vec4 FragColor; //out代表输出至下一个着色器uniform vec2 u_resolution; //视窗的分辨率
uniform float u_time; //传入的时间变量
uniform float uu;// Plot a line on Y using a value between 0.0-1.0
float plot(vec2 st) {//返回一个float类型的值这个值的范围在[0, 1]之间//代表了输入值经过平滑插值后的结果。return smoothstep(0.02f, 0.0f, abs(st.y - st.x));
}void main() {//1.传入每个像素的xy除视窗的分辨率vec2 st gl_FragCoord.xy / u_resolution;//2.获取st的x分量加载uniform中的u_time//得到跟随时间的变换的渐变色vec3 color vec3(st.x,st.x,abs(sin(u_time)));// Plot a linefloat pct plot(st);//3.【(1.0f - pct) * color】表示除直线外的渐变颜色//【pct * vec3(1.0f,0.0f,0.0f)】表示附着直线的颜色。color (1.0f - pct) * color pct * vec3(1.0f,0.0f,0.0f);FragColor vec4(color , 1.0f);
} step()函数 step()插值函数需要输入两个参数。第一个是极限或阈值第二个是我们想要检测或通过的值。对任何小于阈值的值返回 0.0大于阈值则返回 1.0。
#version 320 es
precision mediump float;out vec4 FragColor; //out代表输出至下一个着色器uniform vec2 u_resolution; //视窗的分辨率
uniform float u_time; //传入的时间变量float plot(vec2 st, float pct){return smoothstep( pct-0.02, pct, st.y) -smoothstep( pct, pct0.02, st.y);
}void main() {vec2 st gl_FragCoord.xy/u_resolution;//插值函数需要输入两个参数。第一个是极限或阈值//第二个是我们想要检测或通过的值。对任何小于阈值的值//返回0.0大于阈值则返回1.0。float y step(0.5,st.x);vec3 color vec3(y);float pct plot(st,y);color (1.0-pct)*colorpct*vec3(1.0,0.0,0.0);FragColor vec4(color , 1.0f);
}其他有用的函数
#version 320 es
precision mediump float;#define PI 3.14159265359;out vec4 FragColor;uniform vec2 u_resolution;float plot(vec2 st, float pct){return smoothstep( pct-0.02f, pct, st.y) -smoothstep( pct, pct0.02f, st.y);
}void main() {vec2 st gl_FragCoord.xy / u_resolution;float y;float x st.x;// y mod(x,0.5); // 返回 x 对 0.5 取模的值
// y fract(x); // 仅仅返回数的小数部分y ceil(x); // 向正无穷取整// y floor(x); // 向负无穷取整// y sign(x); // 提取 x 的正负号// y abs(x); // 返回 x 的绝对值// y clamp(x,0.0,1.0); // 把 x 的值限制在 0.0 到 1.0// y min(0.0,x); // 返回 x 和 0.0 中的较小值// y max(0.0,x); // 返回 x 和 0.0 中的较大值// Plot a linefloat pct plot(st,y);vec3 color pct * vec3(1.0f,0.0f,0.0f);FragColor vec4(color , 1.0f);
} 造型函数进阶 更加复杂的造型函数的文档Shaping Functions 多项式造型函数用于在 [0...1] 范围内塑造、补间和缓和信号的多项式函数。如下例子
#version 320 es
precision mediump float;#define PI 3.14159265359;out vec4 FragColor;uniform vec2 u_resolution;float blinnWyvillCosineApproximation (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);float y fa*x6 - fb*x4 fc*x2;return y;
}float doubleCubicSeat (float x, float a, float b){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 min(max_param_a, max(min_param_a, a));b min(max_param_b, max(min_param_b, b));float y 0.00000f;if (x a){y b - (b * pow(1.0-x/a, 3.0));} else {y b (1.0-b)*pow((x-a)/(1.0-a), 3.0);}return y;
}float plot(vec2 st, float pct){return smoothstep(pct-0.02f, pct, st.y) -smoothstep(pct, pct0.02f, st.y);
}void main() {vec2 st gl_FragCoord.xy / u_resolution;float y;float x st.x;// y blinnWyvillCosineApproximation(x);y doubleCubicSeat(x, 5.0f, 5.0f);// Plot a linefloat pct plot(st, y);vec3 color pct * vec3(1.0f, 0.0f, 0.0f);FragColor vec4(color, 1.0f);
}
指数造型函数指数整形函数的实现中控制参数a允许设计者将函数从缓出形式改变为缓入形式。如下例子
#version 320 es
precision mediump float;#define PI 3.14159265359;out vec4 FragColor;uniform vec2 u_resolution;float exponentialEasing (float x, float a){float epsilon 0.00001;float min_param_a 0.0 epsilon;float max_param_a 1.0 - epsilon;a max(min_param_a, min(max_param_a, a));if (a 0.5){// emphasisa 2.0*(a);float y pow(x, a);return y;} else {// de-emphasisa 2.0*(a-0.5);float y pow(x, 1.0/(1.0-a));return y;}
}float plot(vec2 st, float pct){return smoothstep(pct-0.02f, pct, st.y) -smoothstep(pct, pct0.02f, st.y);
}void main() {vec2 st gl_FragCoord.xy / u_resolution;float y;float x st.x;y exponentialEasing(st.x, 0.3);// Plot a linefloat pct plot(st, y);vec3 color pct * vec3(1.0f, 0.0f, 0.0f);FragColor vec4(color, 1.0f);
}
椭圆造型函数圆弧提供了一种快速且易于编码的方法来缓入或缓出单位正方形。然而由于使用平方根该函数的计算效率会降低。
#version 320 es
precision mediump float;#define PI 3.14159265359;out vec4 FragColor;uniform vec2 u_resolution;float doubleCircleSigmoid (float x, float a){float min_param_a 0.0;float max_param_a 1.0;a max(min_param_a, min(max_param_a, a));float y 0.0;if (xa){y a - sqrt(a*a - x*x);} else {y a sqrt(pow((1.0-a), 2.0) - pow((x-1.0), 2.0));}return y;
}float plot(vec2 st, float pct){return smoothstep(pct-0.02f, pct, st.y) -smoothstep(pct, pct0.02f, st.y);
}void main() {vec2 st gl_FragCoord.xy / u_resolution;float y;float x st.x;y doubleCircleSigmoid(st.x, 0.3);// Plot a linefloat pct plot(st, y);vec3 color pct * vec3(1.0f, 0.0f, 0.0f);FragColor vec4(color, 1.0f);
}
贝塞尔造型函数此函数定义一个二阶二次贝塞尔曲线该曲线在单位正方形中具有单个用户指定的样条控制点位于坐标 a,b。此函数保证具有与双线性插值器相同的进入和退出斜率。换句话说此曲线允许用户精确指定其在单位正方形中端点的变化率。
#version 320 es
precision mediump float;#define PI 3.14159265359;out vec4 FragColor;uniform vec2 u_resolution;float quadraticBezier (float x, float a, float b){// adapted from BEZMATH.PS (1993)// by Don Lancaster, SYNERGETICS Inc.// http://www.tinaja.com/text/bezmath.htmlfloat epsilon 0.00001;a max(0.0, min(1.0, a));b max(0.0, min(1.0, b));if (a 0.5){a epsilon;}// solve t from x (an inverse operation)float om2a 1.0 - 2.0*a;float t (sqrt(a*a om2a*x) - a)/om2a;float y (1.0-2.0*b)*(t*t) (2.0*b)*t;return y;
}float plot(vec2 st, float pct){return smoothstep(pct-0.02f, pct, st.y) -smoothstep(pct, pct0.02f, st.y);
}void main() {vec2 st gl_FragCoord.xy / u_resolution;float y;float x st.x;y quadraticBezier(st.x, 0.001, 5.0);// Plot a linefloat pct plot(st, y);vec3 color pct * vec3(1.0f, 0.0f, 0.0f);FragColor vec4(color, 1.0f);
} Impulse造型函数
#version 320 es
precision mediump float;#define PI 3.14159265359;out vec4 FragColor;uniform vec2 u_resolution;// Function from Iñigo Quiles
// www.iquilezles.org/www/articles/functions/functions.htm
float impulse( float k, float x ){float h k*x;return h*exp(1.0-h);
}float plot(vec2 st, float pct){return smoothstep( pct-0.02, pct, st.y) -smoothstep( pct, pct0.02, st.y);
}void main() {vec2 st gl_FragCoord.xy / u_resolution;float y;float x st.x;y impulse(12.0,x);// Plot a linefloat pct plot(st, y);vec3 color pct * vec3(1.0f, 0.0f, 0.0f);FragColor vec4(color, 1.0f);
}
CubicPulse造型函数
#version 320 es
precision mediump float;#define PI 3.14159265359;out vec4 FragColor;uniform vec2 u_resolution;// Function from Iñigo Quiles
// www.iquilezles.org/www/articles/functions/functions.htm
float cubicPulse( float c, float w, float x ){x abs(x - c);if( xw ) return 0.0;x / w;return 1.0 - x*x*(3.0-2.0*x);
}float plot(vec2 st, float pct){return smoothstep( pct-0.02, pct, st.y) -smoothstep( pct, pct0.02, st.y);
}void main() {vec2 st gl_FragCoord.xy / u_resolution;float y;float x st.x;y cubicPulse(0.5,0.2,st.x);// Plot a linefloat pct plot(st, y);vec3 color pct * vec3(1.0f, 0.0f, 0.0f);FragColor vec4(color, 1.0f);
}
ExpStep造型函数
#version 320 es
precision mediump float;#define PI 3.14159265359;out vec4 FragColor;uniform vec2 u_resolution;// Function from Iñigo Quiles
// www.iquilezles.org/www/articles/functions/functions.htm
float expStep(float x, float k, float n){return exp(-k*pow(x, n));
}float plot(vec2 st, float pct){return smoothstep(pct-0.02, pct, st.y) -smoothstep(pct, pct0.02, st.y);
}void main() {vec2 st gl_FragCoord.xy / u_resolution;float y;float x st.x;y expStep(st.x, 10., 1.0);// Plot a linefloat pct plot(st, y);vec3 color pct * vec3(1.0f, 0.0f, 0.0f);FragColor vec4(color, 1.0f);
}
Parabola造型函数
#version 320 es
precision mediump float;#define PI 3.14159265359;out vec4 FragColor;uniform vec2 u_resolution;// Function from Iñigo Quiles
// www.iquilezles.org/www/articles/functions/functions.htm
float parabola(float x, float k){return pow(4.0*x*(1.0-x), k);
}float plot(vec2 st, float pct){return smoothstep(pct-0.02, pct, st.y) -smoothstep(pct, pct0.02, st.y);
}void main() {vec2 st gl_FragCoord.xy / u_resolution;float y;float x st.x;y parabola(st.x, 1.0);// Plot a linefloat pct plot(st, y);vec3 color pct * vec3(1.0f, 0.0f, 0.0f);FragColor vec4(color, 1.0f);
}
Pcurve造型函数
#version 320 es
precision mediump float;#define PI 3.14159265359;out vec4 FragColor;uniform vec2 u_resolution;// Function from Iñigo Quiles
// www.iquilezles.org/www/articles/functions/functions.htm
float pcurve(float x, float a, float b){float k pow(ab, ab) / (pow(a, a)*pow(b, b));return k * pow(x, a) * pow(1.0-x, b);
}float plot(vec2 st, float pct){return smoothstep(pct-0.02, pct, st.y) -smoothstep(pct, pct0.02, st.y);
}void main() {vec2 st gl_FragCoord.xy / u_resolution;float y;float x st.x;y pcurve(st.x, 3.0, 1.0);// Plot a linefloat pct plot(st, y);vec3 color pct * vec3(1.0f, 0.0f, 0.0f);FragColor vec4(color, 1.0f);
} 三、Shader的颜色 GLSL中向量类型的另一大特点是可以用你需要的任意顺序简单地投射和混合变量值。这种能力被形象地称为鸡尾酒。 混合颜色 在GLSL中有个十分有用的函数mix() 这个函数让你以百分比混合两个值。
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器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));// Mix uses pct (a value from 0-1) to// mix the two colorscolor mix(colorA, colorB, pct);FragColor vec4(color, 1.0f);
} 缓动函数 Robert Penner 开发了一些列流行的计算机动画塑形函数被称为缓动函数。
#version 320 es
precision mediump float;#define PI 3.141592653589793f;
#define HALF_PI 1.5707963267948966f;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量// Robert Penners easing functions in GLSL
// https://github.com/stackgl/glsl-easings
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) {float result (t - 1.0) * HALF_PI;return sin(result) 1.0f;
}float sineOut(float t) {float result t * HALF_PI;return sin(result);
}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) {float result 13.0 * t * HALF_PI;return sin(result) * pow(2.0, 10.0 * (t - 1.0));
}float elasticOut(float t) {float result -13.0 * (t 1.0) * HALF_PI;return sin(result) * pow(2.0, -10.0 * t) 1.0;
}float elasticInOut(float t) {float result1 13.0 * HALF_PI;float result2 -13.0 * HALF_PI;return t 0.5? 0.5 * sin(result1 * 2.0 * t) * pow(2.0, 10.0 * (2.0 * t - 1.0)): 0.5 * sin(result2 * ((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) {float result t * PI;return pow(t, 3.0) - t * sin(result);
}float backOut(float t) {float f 1.0 - t;float result f * PI;return 1.0 - (pow(f, 3.0) - f * sin(result));
}float backInOut(float t) {float f t 0.5 ? 2.0 * t : 1.0 - (2.0 * t - 1.0);float result f * PI;float g pow(f, 3.0) - f * sin(result);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 sin(u_time);float pct;
// pct cubicInOut(abs(fract(t)*2.0-1.0));pct elasticIn(t);vec3 color mix(colorA, colorB, pct);FragColor vec4(color, 1.0f);
} 渐变 我们可以输入两个互相匹配的变量类型而不仅仅是单独的 float 变量在我们这个例子中用的是 vec3。这样我们便获得了混合颜色单独通道 .r.g 和 .b的能力。
#version 320 es
precision mediump float;#define PI 3.141592653589793f;out vec4 FragColor;//out代表输出至下一个着色器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);float plot (vec2 st, float pct){return smoothstep(pct-0.01, pct, st.y) -smoothstep(pct, pct0.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);float result st.x * PI;pct.g sin(result);pct.b pow(st.x, 0.5);color mix(colorA, colorB, pct);// Plot transition lines for each channelcolor mix(color, vec3(1.0, 0.0, 0.0), plot(st, pct.r));color mix(color, vec3(0.0, 1.0, 0.0), plot(st, pct.g));color mix(color, vec3(0.0, 0.0, 1.0), plot(st, pct.b));FragColor vec4(color, 1.0f);
} HSB 不能脱离色彩空间来谈论颜色。正如所知除了rgb值有其他不同的方法去描述定义颜色。 HSB代表色相饱和度和亮度或称为值。这更符合直觉也更有利于组织颜色。将x坐标位置映射到Hue值并将y坐标映射到明度我们就得到了五彩的可见光光谱。这样的色彩空间分布实现起来非常方便比起RGB用HSB来拾取颜色更直观。
H(Hue):表示颜色的类型(例如红色,绿色或者黄色).取值范围为0—360.其中每一个值代表一种颜色.S(Saturation):颜色的饱和度从0到1有时候也称为纯度.(0表示灰度图,1表示纯的颜色)B(Brightness or Value):颜色的明亮程度从0到1(0表示黑色,1表示特定饱和度的颜色) 下面是rgb2hsv() 和 hsv2rgb() 函数的例子
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器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);
}// Function from Iñigo Quiles
// https://www.shadertoy.com/view/MsS3Wc
vec3 hsb2rgb(in vec3 c){vec3 rgb clamp(abs(mod(c.x*6.0vec3(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.xy;vec3 color vec3(0.0);color hsb2rgb(vec3(st.x, 1.0, st.y));FragColor vec4(color, 1.0f);
} 四、形状 正方形 下面是一个画一个正方形的代码思路为step()函数会让每一个小于0.1的像素变成黑色vec0.0并将其余的变成白色vec31.0。left 乘 bottom 效果相当于逻辑 AND —— 当 x y 都为 1.0 时乘积才能是 1.0。这样做的效果就是画了两条黑线一个在画布的底边另一个在左边。同理top和right也是这样。
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量void main() {vec2 st gl_FragCoord.xy / u_resolution;vec3 color vec3(0.0);// bottom-leftvec2 bl step(vec2(0.1), st);float pct bl.x * bl.y;// top-rightvec2 tr step(vec2(0.1), 1.0-st);pct * tr.x * tr.y;color vec3(pct);FragColor vec4(color, 1.0f);
} 圆 圆的实现有几种方法
像素到中心的距离从像素到中心的矢量长度从像素到中心的向量的平方根 distance()这个函数其实内部调用length()函数计算不同两点的距离在此例中是像素坐标和画布中心的距离。length()函数内部只不过是用平方根sqrt()计算斜边的方程。
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量void main() {vec2 st gl_FragCoord.xy / u_resolution;vec3 color vec3(0.0);// bottom-leftvec2 bl step(vec2(0.1), st);float pct bl.x * bl.y;// top-rightvec2 tr step(vec2(0.1), 1.0-st);pct * tr.x * tr.y;color vec3(pct);FragColor vec4(color, 1.0f);
} 距离场 我们可也可以从另外的角度思考上面的例子把它当做海拔地图等高线图——越黑的地方意味着海拔越高。想象下你就在圆锥的顶端那么这里的渐变就和圆锥的等高线图有些相似。到圆锥的水平距离是一个常数0.5。这个距离值在每个方向上都是相等的。通过选择从那里截取这个圆锥你就会得到或大或小的圆纹面。 其实我们是通过“空间距离”来重新解释什么是图形。这种技巧被称之为“距离场”从字体轮廓到3D图形被广泛应用。
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量float circle(in vec2 _st, in float _radius){vec2 dist _st-vec2(0.5, 0.3);return 1.-smoothstep(_radius-(_radius*0.01),_radius(_radius*0.01),dot(dist, dist)*5.0);
}void main() {vec2 st gl_FragCoord.xy/u_resolution.xy;//获取屏幕分辨率的长宽比float rateXY u_resolution.x / u_resolution.y;vec2 st1 vec2(st.x * rateXY, st.y);vec3 color vec3(circle(st1, 0.2));FragColor vec4(color, 1.0f);
} 距离场景2
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量void main() {vec2 st gl_FragCoord.xy/u_resolution.xy;st.x * u_resolution.x/u_resolution.y;vec3 color vec3(0.0);float d 0.0;// Remap the space to -1. to 1.st st *2.0-1.0;// Make the distance fieldd length(abs(st)-0.3);// d length( min(abs(st)-.3,0.) );// d length( max(abs(st)-.3,0.) );// Visualize the distance fieldcolor vec3(fract(d*10.0));// Drawing with the distance field// color vec3(step(0.3, d));// color vec3(step(0.3,d) * step(d,0.4));FragColor vec4(color, 1.0f);
} 极坐标图形
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量void main() {vec2 st gl_FragCoord.xy/u_resolution.xy;vec3 color vec3(0.0);vec2 pos vec2(0.5)-st;float r length(pos)*2.0;float a atan(pos.y, pos.x);float f cos(a*3.0);// f abs(cos(a*3.));// f abs(cos(a*2.5))*.5.3;// f abs(cos(a*12.)*sin(a*3.))*.8.1;// f smoothstep(-.5,1., cos(a*10.))*0.20.5;color vec3(1.0-smoothstep(f, f0.02, r));// Drawing with the distance field// color vec3(step(0.3, d));// color vec3(step(0.3,d) * step(d,0.4));FragColor vec4(color, 1.0f);
} 五、Matrices二维矩阵 如上图形 - 而如何移动它们的技巧则是借助移动它们自身的参考坐标系。我们只需要给 st 变量加上一个包含每个片段的位置的向量。这样就移动了整个坐标系。 平移
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量float box(in vec2 _st, in vec2 _size){_size vec2(0.5) - _size*0.5;vec2 uv smoothstep(_size,_sizevec2(0.001),_st);uv * smoothstep(_size,_sizevec2(0.001),vec2(1.0)-_st);return uv.x*uv.y;
}float crossT(in vec2 _st, float _size){return box(_st, vec2(_size, _size/4.0)) box(_st, vec2(_size/4.0, _size));
}void main() {vec2 st gl_FragCoord.xy / u_resolution;vec3 color vec3(0.0);// 为了移动十字架我们移动了空间vec2 translate vec2(cos(u_time), sin(u_time));st translate*0.35;// 在背景上显示空间的坐标color vec3(st.x,st.y,0.0);// 在视窗上添加形状color vec3(crossT(st, 0.15));FragColor vec4(color, 1.0f);
} 矩阵 要移动物体我们同样需要移动整个空间坐标系统。为此我们将使用一个矩阵。矩阵是一个通过行和列定义的一组数。用矩阵乘以一个向量是用一组精确的规则定义的这样做是为了以一组特定的方式来改变向量的值。 GLSL本身支持2维3维和4维方阵mm矩阵mat2、mat3、mat4。GLSL同样支持矩阵相乘 ()和特殊矩阵函数([matrixCompMult()](../glossary/?searchmatrixCompMult))。
矩阵平移基于矩阵的特性我们便有可能构造一个矩阵来产生特定的作用。比如我们可以用一个矩阵来平移一个向量。 矩阵旋转 可以用矩阵来旋转坐标系统。 下面构成2维旋转的矩阵的代码将二维向量绕 vec2(0.0) 点旋转。
mat2 rotate2d(float _angle){return mat2(cos(_angle),-sin(_angle),sin(_angle),cos(_angle));
} 矩阵缩放如果你用过3D建模软件或者 Processing中的 pushmatrix 和 popmatrix 函数你会知道矩阵也可以被用来缩放物体的大小。 根据上面的公式我们知道如何构造一个2D缩放矩阵
mat2 scale(vec2 _scale){return mat2(_scale.x,0.0,0.0,_scale.y);
} 矩阵旋转
#version 320 es
precision mediump float;
#define PI 3.14159265359;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量mat2 rotate2d(float _angle){return mat2(cos(_angle), -sin(_angle),sin(_angle), cos(_angle));
}float box(in vec2 _st, in vec2 _size){_size vec2(0.5) - _size*0.5;vec2 uv smoothstep(_size,_sizevec2(0.001),_st);uv * smoothstep(_size,_sizevec2(0.001),vec2(1.0)-_st);return uv.x*uv.y;
}float crossR(in vec2 _st, float _size){return box(_st, vec2(_size, _size/4.)) box(_st, vec2(_size/4., _size));
}void main() {vec2 st gl_FragCoord.xy / u_resolution;vec3 color vec3(0.0);// 将空间从中心移动到vec20.0st - vec2(0.5);// 旋转空间float angle sin(u_time)*PI;st rotate2d(angle) * st;// 将其移回原位st vec2(0.5);// 在背景上显示空间的坐标color vec3(st.x,st.y,0.0);// 在视窗上添加形状color vec3(crossR(st, 0.4));FragColor vec4(color, 1.0f);
} 矩阵缩放
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量mat2 scale(vec2 _scale){return mat2(_scale.x, 0.0,0.0, _scale.y);
}float box(in vec2 _st, in vec2 _size){_size vec2(0.5) - _size*0.5;vec2 uv smoothstep(_size,_sizevec2(0.001),_st);uv * smoothstep(_size,_sizevec2(0.001),vec2(1.0)-_st);return uv.x*uv.y;
}float crossS(in vec2 _st, float _size){return box(_st, vec2(_size, _size/4.0)) box(_st, vec2(_size/4.0, _size));
}void main() {vec2 st gl_FragCoord.xy / u_resolution;vec3 color vec3(0.0);st - vec2(0.5);st scale(vec2(sin(u_time)1.0)) * st;st vec2(0.5);// 在背景上显示空间的坐标color vec3(st.x, st.y, 0.0);// 在视窗上添加形状color vec3(crossS(st, 0.2));FragColor vec4(color, 1.0f);
} YUV三维矩阵转换
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量// YUV to RGB matrix
mat3 yuv2rgb mat3(1.0, 0.0, 1.13983,
1.0, -0.39465, -0.58060,
1.0, 2.03211, 0.0);// RGB to YUV matrix
mat3 rgb2yuv mat3(0.2126, 0.7152, 0.0722,
-0.09991, -0.33609, 0.43600,
0.615, -0.5586, -0.05639);void main() {vec2 st gl_FragCoord.xy / u_resolution;vec3 color vec3(0.0);// UV值从-1到1// 因此我们需要重新映射st0.0到1.0st - 0.5;// becomes -0.5 to 0.5st * 2.0;// becomes -1.0 to 1.0// 我们将st作为三维向量的yz值传递给正确乘以3x3矩阵color yuv2rgb * vec3(0.5, st.x, st.y);FragColor vec4(color, 1.0f);
} 六、图案 我们的策略依然基于乘以空间坐标0到1之间这样我们的画的在0到1之间的图形就会重复地形成网格。 图案内部应用标量重复 fract()函数它返回一个数的分数部分本质上是除1的余数。换句话说fract()返回小数点后的数。 我们单位化的坐标系变量 (st) 已经是 0.0 到 1.0 之间的了。
#version 320 es
precision mediump float;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量float circle(in vec2 _st, in float _radius){vec2 l _st-vec2(0.5);return 1.0-smoothstep(_radius-(_radius*0.01),_radius(_radius*0.01),dot(l, l)*4.0);
}
void main() {vec2 st gl_FragCoord.xy / u_resolution;st.x * u_resolution.x / u_resolution.y;vec3 color vec3(0.0);st * 5.0;// Scale up the space by 3st fract(st);// Wrap around 1.0// Now we have 9 spaces that go from 0-1color vec3(st, 0.0);color vec3(circle(st, 0.5));FragColor vec4(color, 1.0f);
}
图案内部应用矩阵
#version 320 es
precision mediump float;
#define PI 3.14159265358979323846f;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量vec2 rotate2D(vec2 _st, float _angle){_st - 0.5;_st mat2(cos(_angle), -sin(_angle),sin(_angle), cos(_angle)) * _st;_st 0.5;return _st;
}vec2 tile(vec2 _st, float _zoom){_st * _zoom;return fract(_st);
}float box(vec2 _st, vec2 _size, float _smoothEdges){_size vec2(0.5)-_size*0.5;vec2 aa vec2(_smoothEdges*0.5);vec2 uv smoothstep(_size, _sizeaa, _st);uv * smoothstep(_size, _sizeaa, vec2(1.0)-_st);return uv.x*uv.y;
}void main() {vec2 st gl_FragCoord.xy / u_resolution;st.x * u_resolution.x / u_resolution.y;vec3 color vec3(0.0);// Divide the space in 4st tile(st, 4.0);// Use a matrix to rotate the space 45 degreesfloat angle 0.25f * PI;st rotate2D(st, angle);// Draw a squarecolor vec3(box(st, vec2(0.7), 0.01));// color vec3(st,0.0);FragColor vec4(color, 1.0f);
} 图案偏移
#version 320 es
precision mediump float;
#define PI 3.14159265358979323846f;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量vec2 brickTile(vec2 _st, float _zoom){_st * _zoom;// Here is where the offset is happening_st.x step(1., mod(_st.y,2.0)) * 0.5;return fract(_st);
}float box(vec2 _st, vec2 _size){_size vec2(0.5)-_size*0.5;vec2 uv smoothstep(_size,_sizevec2(1e-4),_st);uv * smoothstep(_size,_sizevec2(1e-4),vec2(1.0)-_st);return uv.x*uv.y;
}void main() {vec2 st gl_FragCoord.xy / u_resolution;st.x * u_resolution.x / u_resolution.y;vec3 color vec3(0.0);// Modern metric brick of 215mm x 102.5mm x 65mm// http://www.jaharrison.me.uk/Brickwork/Sizes.html// st / vec2(2.15,0.65)/1.5;// Apply the brick tilingst brickTile(st,5.0);color vec3(box(st,vec2(0.9)));// Uncomment to see the space coordinatescolor vec3(st,0.0);FragColor vec4(color, 1.0f);
} Truchet瓷砖 目前我们学了如何区分奇数行/列或偶数行/列类似的我们也可能再用这个技巧根据位置来设计元素。Truchet瓷砖即一个单一设计元素可以以四种不同的方式呈现仔细观察 rotateTilePattern() 函数, 它把坐标空间细分成四个单元并赋予每一个旋转值。
#version 320 es
precision mediump float;
#define PI 3.14159265358979323846f;out vec4 FragColor;//out代表输出至下一个着色器uniform vec2 u_resolution;//视窗的分辨率
uniform float u_time;//传入的时间变量vec2 rotate2D (vec2 _st, float _angle) {_st - 0.5;_st mat2(cos(_angle), -sin(_angle),sin(_angle), cos(_angle)) * _st;_st 0.5;return _st;
}vec2 tile (vec2 _st, float _zoom) {_st * _zoom;return fract(_st);
}vec2 rotateTilePattern(vec2 _st){// Scale the coordinate system by 2x2_st * 2.0;// Give each cell an index number// according to its positionfloat index 0.0;index step(1., mod(_st.x, 2.0));index step(1., mod(_st.y, 2.0))*2.0;// |// 2 | 3// |//--------------// |// 0 | 1// |// Make each cell between 0.0 - 1.0_st fract(_st);// Rotate each cell according to the indexif (index 1.0){// Rotate cell 1 by 90 degreesfloat angle 0.5* PI;_st rotate2D(_st, angle);} else if (index 2.0){// Rotate cell 2 by -90 degreesfloat angle - 0.5 * PI;_st rotate2D(_st, angle);} else if (index 3.0){// Rotate cell 3 by 180 degreesfloat angle PI;_st rotate2D(_st, angle);}return _st;
}void main() {vec2 st gl_FragCoord.xy / u_resolution;st.x * u_resolution.x / u_resolution.y;vec3 color vec3(0.0);st tile(st, 3.0);st rotateTilePattern(st);// Make more interesting combinations// st tile(st, 2.0);float angle2D1 - u_time *0.25 *PI;st rotate2D(st, angle2D1);st rotateTilePattern(st*2.0);float angle2D2 u_time*0.25 * PI;st rotate2D(st, angle2D2);// step(st.x,st.y) just makes a bw triangles// but you can use whatever design you want.// Uncomment to see the space coordinatescolor vec3(step(st.x, st.y));FragColor vec4(color, 1.0f);
} 参考资料 The Book of Shader thebookofshader的github地址thebookofshader GitHub - McNopper/OpenGL: OpenGL 3 and 4 with GLSL