分形布朗运动 fbm
FBM(Fractal Brownian Motion,分形布朗运动)实际上通常是由其他基础噪声(如 Perlin 噪声或 Simplex 噪声)组合而成的一种噪声生成技术 如云层、岩石、木纹 如山脉、丘陵 如水流、波浪、烟雾
乘以fbm前
乘以fbm后
着色器中常用的五个函数
- noise/texture: 用于生成随机噪声或查找纹理,以产生细节、图案或模拟自然现象。如 fbm
- Perlin Noise(柏林噪声):
- 描述:一种渐进且平滑的噪声函数,适用于生成自然现象的纹理,如山脉、云彩等。Perlin噪声具有较好的视觉质量和连续性,常用于程序生成内容。
- Simplex Noise(简单噪声):
- 描述:由Ken Perlin发明,是一种比传统Perlin噪声更高效且在维度扩展时表现更好的噪声函数。Simplex噪声在生成复杂形状和纹理时通常产生更自然的效果,尤其是在高维空间中。
- White Noise(白噪声):
- 描述:一种非常基础的噪声类型,包含在所有频率上均匀分布的随机值。这种噪声通常用于添加随机性,创建粗糙表面或偶然事件的模拟。
- Perlin Noise(柏林噪声):
- mix/mixColors: 在两个值或颜色之间进行线性插值,常用于渐变、过渡或合成效果。
- dot: 计算两个向量的点积,常用于计算光照、角度和纹理坐标的相似度。
- normalize: 将一个向量标准化为单位向量,用于方向和光照计算,确保数值稳定性。
- clamp: 限制值在特定范围内(例如0到1),用于确保颜色和亮度值不超过有效范围。
c
pow() (求x的y次幂)
y = mod(x,0.5); // 返回 x 对 0.5 取模的值
//y = fract(x); // 仅仅返回数的小数部分
//y = ceil(x); // 向正无穷取整
//y = floor(x); // 向负无穷取整
//y = sign(x); // 提取 x 的正负号
//y = abs(x); // 返回 x 的绝对值
//y = clamp(x,0.0,1.0); // 把 x 的值限制在 0.0 到 1.0
//y = min(0.0,x); // 返回 x 和 0.0 中的较小值
//y = max(0.0,x); // 返回 x 和 0.0 中的较大值
uv.xyx
的意思是构造一个新的 vec3
向量
风场化函数 makeColor
c
#define FBM_ITERS 9// 分形布朗运动迭代次数
// 逻辑斯谛函数
vec2 logistic(vec2 v) {
return vec2(16.0 / (1.0 + 10.0 * exp(-0.75 * v.x)),
1.0 / (1.0 + 10.0 * exp(-1.95 * v.y)));
}
// 高斯函数
vec3 gaussian(float x) {
vec3 disp = x - vec3(0.3, 0.6, 0.9);
return exp(-16.0 * disp * disp - 4.0);
}
// 哈希函数
float hash13(vec3 p) {
p = fract(p * 0.3183099 + 0.1);
p *= 17.0;
return fract(p.x * p.y * p.z * (p.x + p.y + p.z));
}
// 3D 噪声函数
float noise3(vec3 x) {
vec3 p = floor(x);
vec3 f = fract(x);
f = f * f * (3.0 - 2.0 * f);
return mix(mix(mix(hash13(p + vec3(0,0,0)),
hash13(p + vec3(1,0,0)), f.x),
mix(hash13(p + vec3(0,1,0)),
hash13(p + vec3(1,1,0)), f.x), f.y),
mix(mix(hash13(p + vec3(0,0,1)),
hash13(p + vec3(1,0,1)), f.x),
mix(hash13(p + vec3(0,1,1)),
hash13(p + vec3(1,1,1)), f.x), f.y), f.z);
}
// 分形布朗运动 (FBM) 函数
float fbm(vec3 pos) {
float result = 0.0;
float amplitude = 1.0;
for(int i = 0; i < FBM_ITERS; i++) {
result += noise3(amplitude * pos) / amplitude;
amplitude *= 2.15926535;
}
return result;
}
// 生成颜色的主要函数
vec3 makeColor(vec3 p) {
float noiseValue = 100.0 * fbm(5.*p);
return noiseValue * vec3(.5,.5,.5) * gaussian((p.x+p.y+p.z)/3.);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// 将像素坐标归一化到 [-1, 1] 范围
vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
// 创建一个随时间变化的 3D 点
vec3 p = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
// 使用 makeColor 函数生成颜色
vec3 col = makeColor(p);
// 输出颜色
fragColor = vec4(col, 1.0);
}
绘制高斯函数
- 红色 (R) 曲线:对应
x - 0.3
- 绿色 (G) 曲线:对应
x - 0.6
- 蓝色 (B) 曲线:对应
x - 0.9
c
vec3 gaussian(float x) {
vec3 disp = x - vec3(0.3, 0.6, 0.9);
return exp(-16.0 * disp * disp - 4.0);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// 将坐标原点移到画布中心,并调整比例
vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
// 调整 x 的范围,例如 -1 到 1
float x = uv.x * 2.0;
// 计算高斯函数值
vec3 color = gaussian(x + 0.5); // 加0.5是为了将函数向左平移,使其更好地居中
// 增加 y 轴的缩放因子
float yScale = 11.5; // 你可以调整这个值来改变曲线的高度
// 绘制函数图像
float thickness = 0.003;
vec3 graphColor = vec3(0.1, 0.1, 0.1); // 深灰色背景
if (abs(uv.y - color.r * yScale) < thickness) graphColor.r = 1.0;
if (abs(uv.y - color.g * yScale) < thickness) graphColor.g = 1.0;
if (abs(uv.y - color.b * yScale) < thickness) graphColor.b = 1.0;
// 绘制坐标轴
if (abs(uv.x) < thickness || abs(uv.y) < thickness) {
graphColor = vec3(0.5); // 灰色坐标轴
}
// 输出颜色
fragColor = vec4(graphColor, 1.0);
}
绘制逻辑斯谛函数 (输出值在 (0, 1) 之间)
c
vec2 logistic(vec2 v) {
return vec2(16.0 / (1.0 + 10.0 * exp(-0.75 * v.x)),
1.0 / (1.0 + 10.0 * exp(-1.95 * v.y)));
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// 将坐标原点移到画布中心,并调整比例
vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
// 调整 x 的范围,例如 -10 到 10
float x = uv.x * 20.0;
// 计算 logistic 函数值
vec2 output1 = logistic(vec2(x, 0.0));
vec2 output2 = logistic(vec2(0.0, x));
// 绘制函数图像
float thickness = 0.003;
vec3 graphColor = vec3(0.1); // 深灰色背景
// 红色曲线表示 x 对第一个输出的影响
if (abs(uv.y - output1.x / 16.0) < thickness) graphColor.r = 1.0;
// 绿色曲线表示 y 对第二个输出的影响
if (abs(uv.y - output2.y) < thickness) graphColor.g = 1.0;
// 绘制坐标轴
if (abs(uv.x) < thickness || abs(uv.y) < thickness) {
graphColor = vec3(0.5); // 灰色坐标轴
}
// 输出颜色
fragColor = vec4(graphColor, 1.0);
}
微分 就是切线
导数 就是瞬时斜率
“偏导数”中的“偏”字是指导数计算时只对函数的一个变量进行求导,而保持其他变量不变
- 多变量函数:
- 在多变量函数中,函数的输出值依赖于多个输入变量。例如,( f(x, y) ) 是一个以 ( x ) 和 ( y ) 为变量的函数。
- 偏导数定义:
- 计算偏导数时,我们关注的是函数相对于某一个变量的变化。例如,( f ) 对 ( x ) 的偏导数记作 ( \frac{\partial f}{\partial x} )。
- 在计算 ( \frac{\partial f}{\partial x} ) 时,我们将 ( y ) 看作常数,不考虑其变化影響,从而只研究 ( x ) 变化对函数 ( f ) 的影响。
- 为什么是“偏”:
- “偏”字强调了求导过程的局部性:在偏导数的计算中,实际上只关注函数对一个特定变量的“偏向”变化,而忽略了其他变量的影响。