看到shadertoy里面的那么多炫酷的背景是不是很心动?那我们就来把人家的shader搬过来用一下吧!
1.搞个webgl背景板
默认顶点着色器
attribute vec2 pos;
void main(){gl_Position=vec4(pos,0.0,1.0);}
背景板坐标点共六个,两个三角形组成矩形填充满整个webgl
initArrBuffer(
gl,
'pos',
new Float32Array(
flatArr([
[1.0, 1.0],
[1.0, -1.0],
[-1.0, -1.0],
[-1.0, -1.0],
[-1.0, 1.0],
[1.0, 1.0]
])
),
2
);
其他初始化着色器程序流程不变
2.初始化相关参数
mouse
鼠标移动位置
var mouse = {
x: 0, y: 0 };
gl.canvas.addEventListener('pointermove', (ev) => {
mouse.x = ev.clientX / gl.canvas.width;
mouse.y = 1 - ev.clientY / gl.canvas.height;
});
time
(运行时间-开始时间)的秒数
var time = performance.now() - startTime;
resolution
宽高,用于片元坐标转二维坐标
3.画出场景,动起来
function drawScene() {
cleanGl(gl);
gl.uniform2f(gl.getUniformLocation(gl.program, 'resolution'), gl.canvas.width, gl.canvas.height);
var time = performance.now() - startTime;
gl.uniform1f(gl.getUniformLocation(gl.program, 'time'), time / 1000);
gl.uniform2f(gl.getUniformLocation(gl.program, 'mouse'), mouse.x, mouse.y);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
function animate() {
drawScene();
requestAnimationFrame(animate);
}
animate();
4.简单示例:shader画出鼠标点
precision highp float;
uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
void main(void) {
vec2 position = (gl_FragCoord.xy / resolution.x);
//一定要对鼠标点进行转换,否则就会出现很大的偏差
vec2 ms = (mouse * resolution / resolution.x);
//片元左边与鼠标距离
float d = length(position - ms);
//0.1范围内设置为白色
if(d <= 0.1) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
} else {
gl_FragColor = vec4(1.0, 0, 0, 1.0);
}
}
5.搬运shadertoy里面的好看示例
在片元着色器顶部加上进度和变量名,定义成shadertoy名称
//定义精度
#ifdef GL_ES
precision highp float;
#endif
//传入的值
uniform float time;
uniform vec2 resolution;
uniform vec2 mouse;
//定义成shadertoy的变量名
#define iMouse mouse
#define iTime time
#define iResolution resolution
执行生成画面的方法
//shadertoy一般都有这个方法
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
}
void main(void) {
mainImage(gl_FragColor, gl_FragCoord.xy);
}
- 注意:不能照搬照抄,要根据具体情况进行调整或增加glsl里面的参数
6.搬运实践1
https://www.shadertoy.com/view/7sBfDD
- 这个华丽丽的放射线示例中鼠标点需要转换
iMouse = mouse * resolution;
//定义精度
#ifdef GL_ES
precision highp float;
#endif
//传入的值
uniform float time;
uniform vec2 resolution;
uniform vec2 mouse;
//定义成shadertoy的变量名
//#define iMouse mouse
#define iTime time
#define iResolution resolution
//这里的iMouse需要转换
vec2 iMouse = vec2(0.0);
//--------------------- shadertoy start---------------------
#define pi 3.14159
mat2 Rot(float a) {
float c = cos(a), s = sin(a);
return mat2(c, -s, s, c);
}
vec3 pal(in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d) {
return a + b * cos(6.28318 * (c * t + d));
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
vec2 ms = (iMouse.xy - 0.5 * iResolution.xy) / iResolution.y;
// change me! (and uncomment for loop stuff below)
float A = 1.; // -1. // 0.
float r = 0.3; // 0.6
float th = 0.02; // 0.12
vec2 dir = uv - ms;
float a = atan(dir.x, dir.y);
float s = 0.;
// n is higher than it needs to be but works fine
const float n = 20.;
float k = 6. / iResolution.y;
for(float i = n; i > 0.; i--) {
float io = A * 2. * pi * i / n;
float sc = -4. - 0.5 * i + 0.9 * cos(io - 9. * length(dir) + iTime);
vec2 fpos = fract(sc * uv + 0.5 * i * ms) - 0.5;
//fpos = abs(fpos) - 0.25;
fpos *= Rot(a); // a + io // 5. * a // a + 3. * atan(fpos.x, fpos.y)
float d = abs(fpos.x);
s *= 0.865;
s += step(0., s) * smoothstep(-k, k, -abs(d - r) + th);
}
float val = s * 0.1 + 0.72 + 0. * iTime - 0.23 * pow(dot(dir, dir), 0.25);
val = clamp(val, 0.4, 1.);
vec3 e = vec3(1);
vec3 col = 0.5 * pal(val, e, e, e, 0.24 * vec3(0, 1, 2) / 3.);
col = smoothstep(0., 1., col);
fragColor = vec4(col, 1.0);
}
//--------------------- shadertoy end---------------------
void main(void) {
//鼠标点转换
iMouse = mouse * resolution;
//执行生成画面
mainImage(gl_FragColor, gl_FragCoord.xy);
}
7.搬运实战2
https://www.shadertoy.com/view/tdSXzD
- (1)里面采用了贴图噪声,因为存在
GL_EXT_shader_texture_lod
等wegbl2版本扩展不兼容问题,我这里直接改成噪声函数了。 - (2)鼠标点击后奇怪地出现颜色不对,就禁用了,
//定义精度
#ifdef GL_ES
precision highp float;
#endif
//传入的值
uniform float time;
uniform vec2 resolution;
uniform vec2 mouse;
//定义成shadertoy的变量名
// #define iMouse mouse
//静态化鼠标操作,很奇怪,我这里点击后画面奇怪
vec2 iMouse = vec2(0.0);
#define iTime time
#define iResolution resolution
//--------------------- shadertoy start---------------------
//END AURORA STUFF
// 替换噪声函数
// float noise(in vec2 v) {
// return textureLod(iChannel0, (v + .5) / 256., 0.).g;
// }
float rand(vec2 n) {
return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
}
float noise(vec2 p) {
vec2 ip = floor(p);
vec2 u = fract(p);
u = u * u * (3.0 - 2.0 * u);
float res = mix(mix(rand(ip), rand(ip + vec2(1.0, 0.0)), u.x), mix(rand(ip + vec2(0.0, 1.0)), rand(ip + vec2(1.0, 1.0)), u.x), u.y);
return res * res;
}
float mod289(float x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 mod289(vec4 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 perm(vec4 x) {
return mod289(((x * 34.0) + 1.0) * x);
}
float Noise(vec3 p) {
vec3 a = floor(p);
vec3 d = p - a;
d = d * d * (3.0 - 2.0 * d);
vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0);
vec4 k1 = perm(b.xyxy);
vec4 k2 = perm(k1.xyxy + b.zzww);
vec4 c = k2 + a.zzzz;
vec4 k3 = perm(c);
vec4 k4 = perm(c + 1.0);
vec4 o1 = fract(k3 * (1.0 / 41.0));
vec4 o2 = fract(k4 * (1.0 / 41.0));
vec4 o3 = o2 * d.z + o1 * (1.0 - d.z);
vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);
return o4.y * d.y + o4.x * (1.0 - d.y);
}
// // by iq
// 替换噪声函数
// float Noise(in vec3 x) {
// vec3 p = floor(x);
// vec3 f = fract(x);
// f = f * f * (3.0 - 2.0 * f);
// vec2 uv = (p.xy + vec2(37.0, 17.0) * p.z) + f.xy;
// vec2 rg = texture(iChannel0, (uv + 0.5) / 256.0, -100.0).yx;
// return mix(rg.x, rg.y, f.z);
// }
//--------------------- shadertoy end---------------------
void main(void) {
mainImage(gl_FragColor, gl_FragCoord.xy);
}
glsl noise函数参考:
https://blog.csdn.net/qq_28299311/article/details/103654190
github地址
https://github.com/xiaolidan00/awesome-bg
在
shadertoy
和glslsandbox
里面扒拉下来的好多好看的背景。有些shader运行起来真的很耗资源,量力而行打开看看,别把电脑卡死了!
参考
- shadertoy:
https://www.shadertoy.com/
- glslsandbox:
https://glslsandbox.com/