three.js使用着色器绘制图案

除了通过加载纹理来给材质添加一些图案,我们还可以通过shader添加,这种方式添加更灵活,性能也更好些

此篇的作用主要是提供一些设色器图案素材

[1]uv坐标的玩法

因为uv坐标的特性(左下角为0,0,右上角为1,1),可以借助其和一些二GLSL内置函数实现很多有意思的图案
首先如果要所以uv坐标可以直接在顶点着色器中获取到,然后传递给片段着色器:
然后就可以玩玩了
image.png
image.png
image.png

[2]内置函数图案

mod

image.png

step

阀门函数
image.png
网格状:(添加一个方向即可,使用加法)
image.png
**点状:**那是不是可以使用乘法试试:(原理也好理解,取了交叉点)
image.png
台阶状:(调整了x方向的阈值)
image.png
在上面的代码基础上,继续延伸(其实就是在前面就基础上加了同样的东西)

varying vec2 vUv;
void main(){
  float strength = step(0.4, mod(vUv.x * 10.0, 1.0));
  strength *= step(0.8, mod(vUv.y * 10.0, 1.0));
  strength += step(0.8, mod(vUv.x * 10.0, 1.0)) * step(0.4, mod(vUv.y * 10.0, 1.0));
  gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
当延伸的代码越来越多时,需要适当的重构代码,使代码结构清晰:

varying vec2 vUv;
void main(){
  float barX = step(0.4, mod(vUv.x * 10.0 - 0.2, 1.0)) * step(0.8, mod(vUv.y * 10.0, 1.0));
  float barY = step(0.8, mod(vUv.x * 10.0, 1.0)) * step(0.4, mod(vUv.y * 10.0 - 0.2, 1.0));
  float strength = barX + barY;
  gl_FragColor = vec4(vec3(strength), 1.0);
}

添加偏移量:
给上面的图案添加偏移量来使原图案发生变化

varying vec2 vUv;
void main(){
  float barX = step(0.4, mod(vUv.x * 10.0 - 0.2, 1.0)) * step(0.8, mod(vUv.y * 10.0, 1.0));
  float barY = step(0.8, mod(vUv.x * 10.0, 1.0)) * step(0.4, mod(vUv.y * 10.0 - 0.2, 1.0));
  float strength = barX + barY;
  gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png

abs

绝对值函数也好理解
image.png
加上y方向:
image.png

floor

向下取整

varying vec2 vUv;
void main(){
  float strength = floor(vUv.x * 10.0) / 10.0;
  gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
还可以扩展为x、y轴

varying vec2 vUv;
void main(){
  float strength = floor(vUv.x * 10.0) / 10.0 * floor(vUv.y * 10.0) / 10.0;
  gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png

distance

varying vec2 vUv;
void main(){
  float strength = distance(vUv, vec2(0.5));
  gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
反转一下

varying vec2 vUv;
void main(){
  float strength = 1.0 - distance(vUv, vec2(0.5));
  gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
还可以使用该函数创建镜头光效果:

varying vec2 vUv;
void main(){
  float strength = 0.015 / (distance(vUv, vec2(0.5)));
  gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
在x轴上拉伸:

varying vec2 vUv;
void main(){
  float strength = 0.15 / (distance(vec2(vUv.x, (vUv.y - 0.5) * 5.0 + 0.5), vec2(0.5)));
  gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
扩展到x、y(这不就是可以拿来实现粒子模型那个纹理贴图了):

varying vec2 vUv;
void main(){
  float strength = 0.15 / (distance(vec2(vUv.x, (vUv.y - 0.5) * 5.0 + 0.5), vec2(0.5)));
  strength *= 0.15 / (distance(vec2(vUv.y, (vUv.x - 0.5) * 5.0 + 0.5), vec2(0.5)));
  gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png

atan

varying vec2 vUv;

void main(){
    float angle = atan(vUv.x, vUv.y);
    float strength = angle;
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
上面的效果没上面意思,主要是基于这个扩展:

#define PI 3.1415926535897932384626433832795
varying vec2 vUv;

void main(){
   float angle = atan(vUv.x - 0.5, vUv.y - 0.5);
    angle /= PI * 2.0;
    angle += 0.5;
    float strength = angle;
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
取mod

#define PI 3.1415926535897932384626433832795
varying vec2 vUv;

void main(){
   float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
    float strength = mod(angle * 20.0, 1.0);
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
该用sin

#define PI 3.1415926535897932384626433832795
varying vec2 vUv;

void main(){
   float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
    float strength = sin(angle * 100.0);
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
波浪:

#define PI 3.1415926535897932384626433832795
varying vec2 vUv;

void main(){
   float angle = atan(vUv.x - 0.5, vUv.y - 0.5) / (PI * 2.0) + 0.5;
    float radius = 0.25 + sin(angle * 100.0) * 0.02;
    float strength = 1.0 - step(0.01, abs(distance(vUv, vec2(0.5)) - radius));
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png

[3]旋转uv

下面通过实现一个旋转uv坐标的函数来实现对图形的旋转:

#define PI 3.1415926535897932384626433832795

varying vec2 vUv;

vec2 rotate(vec2 uv, float rotation, vec2 mid){
    return vec2(
        cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
        cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
    );

}
void main(){
    vec2 rotatedUv = rotate(vUv, PI * 0.25, vec2(0.5));//旋转1/8圈
    float strength = 0.15 / (distance(vec2(rotatedUv.x, (rotatedUv.y - 0.5) * 5.0 + 0.5), vec2(0.5)));
    strength *= 0.15 / (distance(vec2(rotatedUv.y, (rotatedUv.x - 0.5) * 5.0 + 0.5), vec2(0.5)));
    gl_FragColor = vec4(vec3(strength), 1.0);
}

uv:要旋转的uv
rotation:旋转的角度
mid:旋转中心

image.png

[4]绘制圆

varying vec2 vUv;

void main(){
    float strength = step(0.5, distance(vUv, vec2(0.5)) + 0.25);
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png

varying vec2 vUv;

void main(){
    float strength = abs(distance(vUv, vec2(0.5)) - 0.25);
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png

varying vec2 vUv;

void main(){
    float strength = step(0.02, abs(distance(vUv, vec2(0.5)) - 0.25));
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png

[5]改变uv

这里通过改变uv坐标将原先规则的圆形

varying vec2 vUv;

void main(){
    vec2 wavedUv = vec2(
        vUv.x,
        vUv.y + sin(vUv.x * 30.0) * 0.1
    );
    float strength = 1.0 - step(0.01, abs(distance(wavedUv, vec2(0.5)) - 0.25));
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
这样就可以在此基础上扩展添加一些有意思的东西了:

varying vec2 vUv;

void main(){
    //x、y都扭一下啊
    vec2 wavedUv = vec2(
        vUv.x + sin(vUv.y * 30.0) * 0.1,
        vUv.y + sin(vUv.x * 30.0) * 0.1
    );
    float strength = 1.0 - step(0.01, abs(distance(wavedUv, vec2(0.5)) - 0.25));
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
在扩展,添加以下sin的频率:

varying vec2 vUv;

void main(){
    //x、y都扭一下啊
    vec2 wavedUv = vec2(
        vUv.x + sin(vUv.y * 100.0) * 0.1,
        vUv.y + sin(vUv.x * 100.0) * 0.1
    );
    float strength = 1.0 - step(0.01, abs(distance(wavedUv, vec2(0.5)) - 0.25));
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png

[6]噪声

噪音有助于模拟云、水、火、地形海拔等自然现象,还也可用于模拟风中移动的草或雪制作动画。
https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
上面是一些经典且常见的柏林噪声实现,不过有些代码可能需要做一些修改才能实现。
例如下面一个经典的2D噪声效果

#define PI 3.1415926535897932384626433832795
varying vec2 vUv;
//  Classic Perlin 2D Noise 
//  by Stefan Gustavson
//

vec4 permute(vec4 x){
    return mod(((x*34.0)+1.0)*x, 289.0);
}
vec2 fade(vec2 t){
    return t*t*t*(t*(t*6.0-15.0)+10.0);
}

float cnoise(vec2 P){
    vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
    vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
    Pi = mod(Pi, 289.0); // To avoid truncation effects in permutation
    vec4 ix = Pi.xzxz;
    vec4 iy = Pi.yyww;
    vec4 fx = Pf.xzxz;
    vec4 fy = Pf.yyww;
    vec4 i = permute(permute(ix) + iy);
    vec4 gx = 2.0 * fract(i * 0.0243902439) - 1.0; // 1/41 = 0.024...
    vec4 gy = abs(gx) - 0.5;
    vec4 tx = floor(gx + 0.5);
    gx = gx - tx;
    vec2 g00 = vec2(gx.x,gy.x);
    vec2 g10 = vec2(gx.y,gy.y);
    vec2 g01 = vec2(gx.z,gy.z);
    vec2 g11 = vec2(gx.w,gy.w);
    vec4 norm = 1.79284291400159 - 0.85373472095314 * vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11));
    g00 *= norm.x;
    g01 *= norm.y;
    g10 *= norm.z;
    g11 *= norm.w;
    float n00 = dot(g00, vec2(fx.x, fy.x));
    float n10 = dot(g10, vec2(fx.y, fy.y));
    float n01 = dot(g01, vec2(fx.z, fy.z));
    float n11 = dot(g11, vec2(fx.w, fy.w));
    vec2 fade_xy = fade(Pf.xy);
    vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
    float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
    return 2.3 * n_xy;
}

void main(){
   float strength = cnoise(vUv * 10.0);
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png
改一下:

void main(){
   float strength = step(0.0, cnoise(vUv * 10.0));
    gl_FragColor = vec4(vec3(strength), 1.0);
}

image.png

这不就实现了一个奶牛的纹理

float strength = 1.0 - abs(cnoise(vUv * 10.0));

image.png

float strength = sin(cnoise(vUv * 10.0) * 20.0);

image.png

float strength = step(0.9, sin(cnoise(vUv * 10.0) * 20.0));

image.png

[7]混合颜色

一个常用的颜色混合函数mix:这个函数可以实现百分比混合两个颜色值

void main(){
   float strength = step(0.9, sin(cnoise(vUv * 10.0) * 20.0));
   vec3 blackColor = vec3(0.0);
   vec3 uvColor = vec3(vUv, 1.0);
   vec3 mixedColor = mix(blackColor, uvColor, strength);
    gl_FragColor = vec4(vec3(mixedColor), 1.0);
}

image.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

seeooco

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值