由于GPU驱动供应商通常不会费心在GLSL中实现noiseX,我正在寻找一个“图形随机化瑞士军刀”实用函数集,最好是在GPU着色器中优化使用。我更喜欢GLSL,但是任何语言的代码对我来说都可以,我可以把它翻译成GLSL。

具体来说,我希望:

a)伪随机函数- n维,均匀分布于[-1,1]或[0,1]之上,从m维种子(理想情况下是任何值,但我同意将种子限制在,比如说,0..1为结果均匀分布)。喜欢的东西:

float random  (T seed);
vec2  random2 (T seed);
vec3  random3 (T seed);
vec4  random4 (T seed);
// T being either float, vec2, vec3, vec4 - ideally.

b)连续的噪声,比如柏林噪声——同样是n维,+-均匀分布,有约束的值集,看起来不错(一些配置外观的选项,比如柏林电平也很有用)。我希望签名是这样的:

float noise  (T coord, TT seed);
vec2  noise2 (T coord, TT seed);
// ...

我对随机数生成理论不太感兴趣,所以我最渴望的是一个现成的解决方案,但我也很喜欢这样的回答:“这里有一个非常好的,高效的1D rand(),让我解释一下如何在它的基础上制作一个好的n维rand()……”.


当前回答

在2010年首次发布这个问题之后,在良好的随机函数和硬件支持方面发生了很大的变化。

从今天的角度来看,这个算法抽取的随机数的一致性很差。均匀性受到输入值大小的很大影响,当从输入值中采样时,例如射线/路径跟踪应用程序,可见的工件/模式将变得明显。

There have been many different functions (most of them integer hashing) being devised for this task, for different input and output dimensionality, most of which are being evaluated in the 2020 JCGT paper Hash Functions for GPU Rendering. Depending on your needs you could select a function from the list of proposed functions in that paper and simply from the accompanying Shadertoy. One that isn't covered in this paper but that has served me very well without any noticeably patterns on any input magnitude values is also one that I want to highlight.

其他类型的算法使用低差异序列来绘制伪随机数,例如带有Owen-Nayar置乱的Sobol序列。Eric Heitz在这一领域做了一些惊人的研究,以及他在Screen Space论文中将蒙特卡罗误差分布为蓝色噪声的低差异采样器。 另一个例子是(迄今为止最新的)JCGT论文基于实用哈希的Owen置乱,它将Owen置乱应用于不同的哈希函数(即Laine-Karras)。

然而,其他类别使用算法来产生具有理想频谱的噪声模式,例如蓝色噪声,它特别“取悦”眼睛。

(我意识到好的StackOverflow答案应该提供算法作为源代码,而不是链接,因为那些可能会中断,但现在有太多不同的算法,我打算把这个答案作为今天已知的好算法的总结)

其他回答

Gustavson的实现使用1D纹理

不,从2005年开始就没有了。只是人们坚持下载旧版本。您提供的链接上的版本仅使用8位2D纹理。

我和阿希玛的Ian McEwan共同开发的新版本没有使用纹理,但是在典型的桌面平台上,纹理带宽很大,运行速度只有它的一半左右。在移动平台上,无纹理版本可能更快,因为纹理通常是一个重要的瓶颈。

我们积极维护的源存储库是:

https://github.com/ashima/webgl-noise

这里是无纹理和使用纹理的噪音版本的集合(只使用2D纹理):

http://www.itn.liu.se/~stegu/simplexnoise/GLSL-noise-vs-noise.zip

如果您有任何具体的问题,请直接给我发电子邮件(我的电子邮件地址可以在经典噪声*中找到)。glsl来源。)

一个直的、锯齿状的1d柏林版本,本质上是一个随机的lfo之字形。

half  rn(float xx){         
    half x0=floor(xx);
    half x1=x0+1;
    half v0 = frac(sin (x0*.014686)*31718.927+x0);
    half v1 = frac(sin (x1*.014686)*31718.927+x1);          

    return (v0*(1-frac(xx))+v1*(frac(xx)))*2-1*sin(xx);
}

我还在shadertoy所有者inigo quilez perlin教程网站上找到了1-2-3-4d perlin噪音,voronoi等等,他有完整的快速实现和代码。

在2010年首次发布这个问题之后,在良好的随机函数和硬件支持方面发生了很大的变化。

从今天的角度来看,这个算法抽取的随机数的一致性很差。均匀性受到输入值大小的很大影响,当从输入值中采样时,例如射线/路径跟踪应用程序,可见的工件/模式将变得明显。

There have been many different functions (most of them integer hashing) being devised for this task, for different input and output dimensionality, most of which are being evaluated in the 2020 JCGT paper Hash Functions for GPU Rendering. Depending on your needs you could select a function from the list of proposed functions in that paper and simply from the accompanying Shadertoy. One that isn't covered in this paper but that has served me very well without any noticeably patterns on any input magnitude values is also one that I want to highlight.

其他类型的算法使用低差异序列来绘制伪随机数,例如带有Owen-Nayar置乱的Sobol序列。Eric Heitz在这一领域做了一些惊人的研究,以及他在Screen Space论文中将蒙特卡罗误差分布为蓝色噪声的低差异采样器。 另一个例子是(迄今为止最新的)JCGT论文基于实用哈希的Owen置乱,它将Owen置乱应用于不同的哈希函数(即Laine-Karras)。

然而,其他类别使用算法来产生具有理想频谱的噪声模式,例如蓝色噪声,它特别“取悦”眼睛。

(我意识到好的StackOverflow答案应该提供算法作为源代码,而不是链接,因为那些可能会中断,但现在有太多不同的算法,我打算把这个答案作为今天已知的好算法的总结)

散列: 现在有webGL2.0,所以整数可以在(w)GLSL中使用。 ->用于高质量的便携式哈希(成本与丑陋的浮动哈希相似),我们现在可以使用“严肃的”哈希技术。 IQ在https://www.shadertoy.com/view/XlXcW4中实现了一些(以及更多)

例如:

  const uint k = 1103515245U;  // GLIB C
//const uint k = 134775813U;   // Delphi and Turbo Pascal
//const uint k = 20170906U;    // Today's date (use three days ago's dateif you want a prime)
//const uint k = 1664525U;     // Numerical Recipes

vec3 hash( uvec3 x )
{
    x = ((x>>8U)^x.yzx)*k;
    x = ((x>>8U)^x.yzx)*k;
    x = ((x>>8U)^x.yzx)*k;

    return vec3(x)*(1.0/float(0xffffffffU));
}

这里还有一个由McEwan和@StefanGustavson描述的很好的实现,看起来像柏林噪声,但“不需要任何设置,即不需要纹理或统一数组。只需将它添加到你的着色器源代码,并在任何你想要的地方调用它”。

这非常方便,特别是考虑到Gustavson早期的实现,@dep链接到,使用1D纹理,这在GLSL ES (WebGL的着色语言)中是不支持的。