当个快乐的WebGL炫酷背景搬运工!

简介: 看到shadertoy里面的那么多炫酷的背景是不是很心动?那我们就来把人家的shader搬过来用一下吧!

看到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);
    }
}

20230507_231040.gif

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

20230507_231656.gif

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

20230508_010655.gif

  • (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

shadertoyglslsandbox里面扒拉下来的好多好看的背景。有些shader运行起来真的很耗资源,量力而行打开看看,别把电脑卡死了!

20230508_015228.gif

参考

  • shadertoy:https://www.shadertoy.com/
  • glslsandbox:https://glslsandbox.com/
相关文章
|
3月前
对游戏设计案例杂谈1
对游戏设计案例杂谈1
|
5月前
|
前端开发 JavaScript 数据可视化
元宇宙基础案例 | 大帅老猿threejs特训
元宇宙基础案例 | 大帅老猿threejs特训
|
Java API Android开发
Compose 动画艺术探索之灵动岛
Compose 动画艺术探索之灵动岛
176 0
Compose 动画艺术探索之灵动岛
|
前端开发 JavaScript API
贝塞尔曲线在前端,走近她,然后爱上她
今天我们聊聊我们经常用的CSS3动画里面的贝尔赛曲线,希望能做到,她认识你,你也熟悉她! 本文源码: Bezier 看完你就懂了一半,动手你就成功了另外一半!
200 0
贝塞尔曲线在前端,走近她,然后爱上她
|
前端开发 JavaScript
Three.js - 走进3D的奇妙世界
本文将通过Three.js的介绍及示例带我们走进3D的奇妙世界。
|
人工智能 小程序 数据库
给 AI 讲故事,如何教它脑补画面?| 开发者必读(105期)
最炫的技术新知、最热门的大咖公开课、最有趣的开发者活动、最实用的工具干货,就在《开发者必读》!
811 0
带你读《流动的色彩—— 一本探索自由水彩世界的技法书》之二:绘画技法
水彩画清新透明的质感、水色交融的画面,如同抒情诗或轻音乐般柔美。本书是一本从入门到精通式的水彩画技法教程,内容全面实用,讲解浅显易懂,编排清晰直观,既适合初学者,也适合有一定基础的绘画爱好者。希望本书能让读者在学习的过程中感受用画笔记录身边美好事物的乐趣。
|
Java 图形学
java游戏开发杂谈 - 游戏物体
java游戏开发杂谈 - 游戏物体现实生活中,有很多物体,每个物体的长相、行为都不同。 物体存在于不同的空间内,它只在这个空间内发生作用。 物体没用了,空间就把它剔除,不然既占地方,又需要花精力管理。
1175 0
|
前端开发 容器 Web App开发
如何用纯 CSS 创作一只愤怒小鸟中的黑炮
效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。 https://codepen.io/comehope/pen/vaoQqa 可交互视频 此视频是可以交互的,你可以随时暂停视频,编辑视频中的代码。
924 0
|
前端开发 容器 流计算
如何用纯 CSS 创作一只徘徊的果冻怪兽
效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。 https://codepen.io/comehope/pen/VdOKQG 可交互视频 此视频是可以交互的,你可以随时暂停视频,编辑视频中的代码。
885 0