猴子都能看懂的噪声(noise)专题

背景

除了生成各种奇形怪状与自然景观,噪声也有其他美妙的用途!

工作原因,经常接触与噪声相关的画面效果(火焰啊,画面扰动啊之类的),做的时候一知半解,傻傻分不清楚各种形态的noise,也不知道三维noise和二维noise的具体区别,只知道在shadertoy上找到相似的噪声然后ctrl c/v一下,特别是在具体的业务场景中,比如设计需要这种形态的火焰,需要那种形态的画面扰动,对我来说简直是挠破了脑袋,噪声调半天都不一定能调出一个满意的结果😂

刚好近期的工作需要分析ae的效果控件【分形杂色】【湍流杂色】,找到一篇原作者对【分形杂色】效果原理的说明,再次引起了对噪声的兴趣,也更希望能啃啃这块软骨!
因此有了这篇文档,是我对各种噪声的学习理解,(有时间的话)下篇再来展示下各种噪声的(画面上的)应用,名字我都想好了!就叫【猴子都会使用的噪声(noise)专题】🤣

前提

接下来的所有代码都能在shadertoy上运行,下面的图像也基本都生成于shadertoy
参考的各种资料文档,也会在相应地方提供出处,但不用阅读出处的具体细节,也能理解本篇的内容!(自信)
由于还是有些内容没理解明白,所以会有一些问题会以斜体引用的形式出现在文档中,用来质问愚蠢的自己,希望自己未来能解决掉提出的问题吧,也希望如果有好哥哥知道答案,能在评论区中留下你的箴言,赞美太阳☀!

(例子)呐,莱纳,为什么妈妈会被巨人吃掉呢?


Hash/White Noise(杂乱/白噪声)

在shadertoy中涉及噪声相关的效果,都不难发现有hash函数(有时候是random函数),再参考一下wiki对white noise的描述(实际上white noise的定义会更加广泛,不局限于图像中),也跟hash函数产生的图像极其相似,所以这里把hash跟white放在一块

不太理解这函数为啥叫hash,而不是white,还是我理解错了hash跟white不能划等号

对于图像来说,每个像素都有其位置,即uv,把uv作为hash函数的输入,可以得到伪随机的结果
这里hash函数的实现挺自由的,各种magic number,而且用到dot,fract,sin等函数或是这些函数的组合,虽然出来的结果大同小异,但还是有些区别的,特别是利用sin作为hash的实现,在放大uv的时候会有规律性的artifact

参考:生成Sinhash和Fracthash Noise

参考上文的实践,建议还是用dot/fract作为hash的实现,如果用带有sin的hash函数,接下来的噪声实现在uv放大后都有周期性的表现,而且在不同的机子中(比如安卓/ios)由于高频下精度不同会导致sin函数输出的结果有差异,可能会有不同设备输出结果不一致的问题

float hash(vec2 p) {
    vec3 p3  = fract(vec3(p.xyx) * .1031); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); }

float hash_with_sin(vec2 _st) {
    return fract(sin(dot(_st.xy, vec2(12.9898,78.233)))*43758.5453123); }

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
   
    vec2 uv = fragCoord/iResolution.xy;

    float i = floor(uv.x);
    
    float scale = 1000.; // 尝试放大这个值,会发现hash_with_sin与hash的区别
    vec3 col = vec3(random(uv*scale + iTime*0.001))*step(.5, uv.x);//RIGHT
    vec3 colsin = vec3(randomSin(uv*scale + iTime*0.001))*(1.-step(.5, uv.x));//LEFT
    
    vec3 line = vec3(smoothstep(.5, .5, uv.x)) - vec3(smoothstep(.51, .51, uv.x));

    // Output to screen
    fragColor = vec4(col + colsin + line,1.0);
}

在这里插入图片描述
左hash_with_sin,右hash,就算是观察静止的图片也能看到左边呈现一些规律性,如果加上iTime会更加明显

参考另外一个链接的hash库,无敌了:【shader】超级噪声库,附代码(fbm、Perlin、Simplex、Worley、Tiling、Curl等,很全很全)

hash库,不用纠结具体怎么实现,里面的magic number也不需要额外关心,随意就行

float hash11(float p) {
    p = fract(p * .1031); p *= p + 33.33; p *= p + p; return fract(p); }
float hash21(vec2 p) {
    vec3 p3  = fract(vec3(p.xyx) * .1031); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); }
float hash31(vec3 p3) {
    p3  = fract(p3 * .1031); p3 += dot(p3, p3.zyx + 31.32); return fract((p3.x + p3.y) * p3.z); }
vec2 hash12(float p) {
    vec3 p3 = fract(vec3(p) * vec3(.1031, .1030, .0973));
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Git是一种分布式版本控制系统,它可以帮助我们管理代码的版本以及协调多人协作开发。猴子也能理解git的基本概念和使用方法。 首先,了解Git的工作流程对于猴子学习Git很重要。Git将代码存储在仓库(repository)中,它存在本地仓库和远程仓库两种形式。我们可以通过git init命令来创建本地仓库,通过git clone命令从远程仓库中复制一份代码到本地。 一旦代码被提交到本地仓库中,我们可以使用git add命令将修改的文件添加到暂存区(staging area),然后使用git commit命令将暂存区的代码快照保存到本地仓库中。这样,我们就可以轻松地在不同的代码版本之间切换。 另外,Git还可以帮助我们协调多人协作开发。每个开发者都可以拥有自己的本地仓库,并从远程仓库中获取代码进行开发。当一个人的代码修改完成后,可以通过git push命令将代码推送到远程仓库,供其他人查看和使用。同时,其他人可以通过git pull命令从远程仓库获取最新的代码更新到本地。 此外,Git还提供了分支(branch)的功能,让多人协作更加便捷。开发者可以创建自己的分支,进行独立的开发工作,不会影响到其他分支上的代码。当开发完成后,可以将自己的分支合并到主分支(master branch)上,保持整体代码的稳定。 总之,Git是一个强大且易于使用的版本控制系统,猴子只需要简单了解它的基本概念和使用方法,就可以轻松管理代码和与其他开发者进行协作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值