除了通过加载纹理来给材质添加一些图案,我们还可以通过shader添加,这种方式添加更灵活,性能也更好些
此篇的作用主要是提供一些设色器图案素材
因为uv坐标的特性(左下角为0,0
,右上角为1,1
),可以借助其和一些二GLSL内置函数实现很多有意思的图案
首先如果要所以uv坐标可以直接在顶点着色器中获取到,然后传递给片段着色器:
然后就可以玩玩了
阀门函数
网格状:(添加一个方向即可,使用加法)
**点状:**那是不是可以使用乘法试试:(原理也好理解,取了交叉点)
台阶状:(调整了x方向的阈值)
在上面的代码基础上,继续延伸(其实就是在前面就基础上加了同样的东西)
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);
}
当延伸的代码越来越多时,需要适当的重构代码,使代码结构清晰:
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);
}
向下取整
varying vec2 vUv;
void main(){
float strength = floor(vUv.x * 10.0) / 10.0;
gl_FragColor = vec4(vec3(strength), 1.0);
}
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);
}
varying vec2 vUv;
void main(){
float strength = distance(vUv, vec2(0.5));
gl_FragColor = vec4(vec3(strength), 1.0);
}
varying vec2 vUv;
void main(){
float strength = 1.0 - distance(vUv, vec2(0.5));
gl_FragColor = vec4(vec3(strength), 1.0);
}
varying vec2 vUv;
void main(){
float strength = 0.015 / (distance(vUv, vec2(0.5)));
gl_FragColor = vec4(vec3(strength), 1.0);
}
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);
}
扩展到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);
}
varying vec2 vUv;
void main(){
float angle = atan(vUv.x, vUv.y);
float strength = angle;
gl_FragColor = vec4(vec3(strength), 1.0);
}
#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);
}
#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);
}
#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);
}
#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);
}
下面通过实现一个旋转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:旋转中心
varying vec2 vUv;
void main(){
float strength = step(0.5, distance(vUv, vec2(0.5)) + 0.25);
gl_FragColor = vec4(vec3(strength), 1.0);
}
varying vec2 vUv;
void main(){
float strength = abs(distance(vUv, vec2(0.5)) - 0.25);
gl_FragColor = vec4(vec3(strength), 1.0);
}
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);
}
这里通过改变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);
}
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);
}
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);
}
噪音有助于模拟云、水、火、地形海拔等自然现象,还也可用于模拟风中移动的草或雪制作动画。
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);
}
void main(){
float strength = step(0.0, cnoise(vUv * 10.0));
gl_FragColor = vec4(vec3(strength), 1.0);
}
这不就实现了一个奶牛的纹理
float strength = 1.0 - abs(cnoise(vUv * 10.0));
float strength = sin(cnoise(vUv * 10.0) * 20.0);
float strength = step(0.9, sin(cnoise(vUv * 10.0) * 20.0));
一个常用的颜色混合函数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);
}