数字孪生混乱中生成世界9 PsrdNoise 坐标系Wrapping FlowNoise

159 阅读3分钟

欢迎继续一起踏上 The Journey of Chaos, 关于 Shader 生成技术的一些基础性学习。噪声会分为以下几篇内容学习

  1. 随机函数与白噪声

  2. 值噪声 ValueNoise

  3. 柏林噪声 Gradient Noise

  4. 多维柏林噪声

  5. 柏林噪声优化 Simplex Noise

  6. Cell Noise

  7. SmoothVoronoi 与VoroNoise

  8. Simplex Noise变种PsrdNoise

  9. PsrdNoise 应用 FlowNoise(本篇)

  10. CurlNoise

  11. FBM深入

在了解完 PsrdNoise基本原理后,作者提出了一个名为 FlowNoise的用法,其主要思路就是用上一层的梯度值扭曲下一层噪声的坐标。 也就是以下函数中的第 4 个参数作用于第二层的第一个参数.

noise = PsrdNoise(coord, peroid, rotation, gradient)

通过这种玩法可以达到 Ken Perlin and Fabrice Neyret 在 Siggraph的湍流 turbulent 漩涡图案。下图为 2503065302 这种思路我看最早是 IQ提出来的,他称之为 Domain Warping, IQ的原文 iquilezles.org/articles/wa… 下图为 IQ通过 做出来的图形

f(p) = fbm(p+fbm(p+fbm(p)))\

2503075401

2503075401

Flow Noise

用上一层的梯度值扭曲下一层噪声的坐标, 这个有点不直观,查看下面的演示。 2503074320 最关键的就是下面这段代码,通过先生成噪声,然后将上层的噪声去扭曲下一层的坐标,另外为了看出分别,warp的程度从上到下依次递减,从grid和 arrow也可以看出来

 float warpamount = clamp(1.1-st.t*1.2, 0.0, 1.0); n += 0.4 * psrdnoise(v, p, alpha, g); gsum = g; vec2 warped_v = v*2.0+0.15*warpamount*gsum; n += 0.2 * psrdnoise(warped_v, p*2.0, alpha*2.0, g); vec3 noisecolor = vec3(n);

如烟, 如电

2503070557 依然,warp的程度从上到下依次递减, 上面这个烟雾就是通过 FBM组合出来,就是不断的将 uv放大,并把值缩小,核心代码结构非常类似,优美

 float warp = 0.13*clamp(1.1-st.t*1.2, 0.0, 1.0);     float n = 0.5;          warped_v = v * 1.0 + warp*gsum;     n += 0.4 * psrdnoise(warped_v, p, alpha, g);     gsum += g * 1.0;          warped_v = v * 2.0 + warp*gsum;     n += 0.2 * psrdnoise(warped_v, p, alpha + n , g);     gsum += g * 0.5;          warped_v = v * 4.0 + warp*gsum;     n += 0.1 * psrdnoise(warped_v, p, alpha + n, g);     gsum += g * 0.25;          warped_v = v * 8.0 + warp*gsum;     n += 0.05 * psrdnoise(warped_v, p, alpha + n, g);

当然我们可以通过 for循环来组织分型层次

 float warp = 0.13; // Nice "puffy clouds" warping    float n = 0.0;  // noise    float w = 1.0;  // 分型度数    float s = 1.0;  // scale    gsum = vec2(0.0);    for(float i = 0.0; i<5.0; i++) {      n += w*psrdnoise(s*v + warp*gsum, s*p, s*alpha, g);      gsum += w * g;      w *= 0.5;      s *= 2.0;    }    return vec3(1.0) * (0.5+0.4*n);

这个时候如果我们把最后一句话变成反向,类似于取反,会得到蓝色闪电?

    return vec3(0.322,0.384,0.878) * (0.5 - 0.4 * n);

2503072045

2503072045

恶心的绿色涌动

2503070010 上面这张效果看起来挺恶心的,其高光的效果赋予了很强的体积感。 实现原理非常简单. 首先首先为梯度增加一个 1.0 的 z值,然后判断这个向量与 vec3(1.0) 反射光的方向是否趋同,如果与反射光方向越相似越应该是亮面。 于是乎其核心代码如下

 vec3 N = normalize(vec3(gsum, 1.0)); vec3 L = normalize(vec3(1.0)); float s = pow(max(dot(N,L), 0.0), 10.0); // Shiny! vec3 scolor = vec3(0.929,0.941,0.157); vec3 ncolor = n*vec3(0.5, 1.0, 0.2); // Gooey green            return mix(ncolor, scolor, s);

资料

  1. ken perlin noise userpages.cs.umbc.edu/olano/s2002…