我已经看到这个伪随机数生成器用于在这里和那里引用的着色器:
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
Run Code Online (Sandbox Code Playgroud)
它被称为"规范",或"我在网上找到的单行".
这个功能的起源是什么?恒定值是否像它们看起来一样任意或是否有一些艺术选择?有没有讨论这个功能的优点?
编辑:我遇到的这个函数最早的参考是从2008年2月开始的这个档案,原来的页面现在已经从网上消失了.但是那里没有比其他任何地方更多的讨论.
sta*_*ole 41
非常有趣的问题!
我正试图在输入答案的同时解决这个问题:)首先是一个简单的方法来玩它:http://www.wolframalpha.com/input/?i = plot%28 + mod%28 + sinin28x*12.9898 +%2B + Y*78.233%29 +*+ 43758.5453%2C1%29X%3D0..2%2C + Y%3D0..2%29
那么让我们考虑一下我们在这里要做的事情:对于两个输入坐标x,y,我们返回一个"随机数".现在这不是一个随机数.每次输入相同的x,y时都是一样的.这是一个哈希函数!
该函数的第一件事是从2d到1d.这本身并不有意思,但选择的数字使得它们不会重复.我们还有一个浮点加法.从y或x开始会有更多的位,但数字可能只是选择正确,所以它会混合.
然后我们采样黑盒sin()函数.这在很大程度上取决于实施!
最后,它通过乘以和取得分数来放大sin()实现中的错误.
在一般情况下,我不认为这是一个很好的哈希函数.sin()是一个黑盒子,在GPU上,数字上.应该可以通过采用几乎任何哈希函数并转换它来构造一个更好的一个.困难的部分是将cpu散列中使用的典型整数运算转换为浮点(半位或32位)或定点运算,但它应该是可能的.
同样,作为哈希函数的真正问题是sin()是一个黑盒子.
MB *_*lds 19
起源可能是论文:"在y = [(a + x)sin(bx)] mod 1"的帮助下产生随机数,WJJ Rey,第22届欧洲统计学家会议和第7届维尔纽斯概率理论会议和数理统计,1998年8月
编辑:由于我找不到本文的副本,并且"TestU01"参考可能不清楚,这里是伪C中的TestU01中描述的方案:
#define A1 ???
#define A2 ???
#define B1 pi*(sqrt(5.0)-1)/2
#define B2 ???
uint32_t n; // position in the stream
double next() {
double t = fract(A1 * sin(B1*n));
double u = fract((A2+t) * sin(B2*t));
n++;
return u;
}
Run Code Online (Sandbox Code Playgroud)
其中唯一推荐的常量值是B1.
请注意,这是针对流的.转换为1D散列'n'成为整数网格.所以我的猜测是有人看到这个并将't'转换成一个简单的函数f(x,y).使用上面的原始常量将产生:
float hash(vec2 co){
float t = 12.9898*co.x + 78.233*co.y;
return fract((A2+t) * sin(t)); // any B2 is folded into 't' computation
}
Run Code Online (Sandbox Code Playgroud)
常量值是任意的,特别是它们非常大,并且与素数相差几位小数.
高振幅正弦波乘以4000的模数超过4000是周期函数.它就像一个窗帘或波纹金属制成非常小,因为它乘以4000,并由点积转过一个角度.
由于函数是2-D,点积具有使周期函数相对于X和Y轴倾斜的效果.按比例约为13/79.这是低效的,你可以通过做(13x + 79y)的窦实际上达到同样的效果,这也可以实现我想的更少数学的东西.
如果在X和Y中找到函数的周期,则可以对其进行采样,使其看起来像一个简单的正弦波.
这是放大图的图片
我不知道原点,但它与许多其他产品相似,如果你定期在图形中使用它,它往往会产生莫尔条纹,你可以看到它最终再次出现.