视频教学链接:
https://www.bilibili.com/video/av55565296
代码:
https://github.com/zszen/godot_lesson/commit/6a80fad6051a678c26f6673e035d85373a32282c
shader_type canvas_item;
uniform vec3 color = vec3(.35,.48,.7);
uniform int OCTAVES = 4;
float rand(vec2 uv){
return fract(sin(dot(uv, vec2(56,78))*1000.0)*1000.0);
}
float noise(vec2 uv){
vec2 i = floor(uv);
vec2 f = fract(uv);
float a = rand(i);
float b = rand(i+vec2(1.,0.));
float c = rand(i+vec2(.0,1.));
float d = rand(i+vec2(1.,1.));
vec2 cubic = f*f*(3.-2.*f);
// return mix(a,b,f.x)+(c-a)*f.y*(1.-f.x)+(d-b)*f.x*f.y;
return mix(a,b,cubic.x)+(c-a)*cubic.y*(1.-cubic.x)+(d-b)*cubic.x*cubic.y;
}
float fbm(vec2 uv){
float val = 0.;
float scale = .5;
for(int i=0;i<OCTAVES;i++){
val+=noise(uv)*scale;
uv*=2.;
scale*=.5;
}
return val;
}
void fragment(){
vec2 uv = UV*20.;
uv.y*=2.;
vec2 motion = vec2(fbm(uv+vec2(TIME*-.5, sin(TIME*.3+fract(uv.x*uv.y)))));
float final = fbm(uv+motion);
COLOR = vec4(color, rand(uv));
// COLOR = vec4(color, final*.35);
}
解释
-
伪随机数
fract(sin(dot(uv, vec2(56,78))*1000.0)*1000.0);
其中uv和[56,78]点的关系就理解成他们之间的距离就好(非精准)
frac(sin(x*1000.)*1000.0)
的图像
2d
3d -
noise噪点作用是让当前点在其周围四个顶点实现二维连续
-
mix(a,b,f.x)
只能在x方向上连续 -
(c-a)*f.y*(1.-f.x)
和(d-b)*f.x*f.y
都只能y方向上连续 - 整体这样看更直观
(a+(c-a)*f.y)*(1.-f.x)+(b+(d-b)*f.y)*f.x
这个图像的左上角趋近于a,右上角趋近于b, 左下角趋近于c,右下角趋近于d, 记住这个公式就比较明确 -
混合在一起,向四个边缘方向连续
mix(a,b,f.x)
-
(c-a)*f.y*(1.-f.x)
(d-b)*f.x*f.y
合并
Grapher公式: https://pan.baidu.com/s/1wX1VREvjqMipF6dJ0VSf0A 提取码: h28g
- fbm函数用于将多次不同的雾层叠加在一起,多次循环后返回值逼近1,不需要再进行范围处理
- 通关不同方向上的运动,让雾运动起来