这个GLSL兰德()单线的起源是什么?

时间:2012-10-18 21:46:48

标签: glsl shader prng

我已经看到这个伪随机数生成器用于引用here and there around the web的着色器:

float rand(vec2 co){
  return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

它被称为“规范”,或“我在网上找到的单行内容”。

这个功能的起源是什么?恒定值是否像它们看起来一样任意或是否有一些艺术选择?有没有讨论这个功能的优点?

编辑:我遇到的这个函数最早的引用是this archive from Feb '08,原始页面现在已经从网上消失了。但是那里没有比其他任何地方更多的讨论。

5 个答案:

答案 0 :(得分:37)

非常有趣的问题!

我正在尝试在输入答案时弄明白这一点:) 首先,一个简单的方法:http://www.wolframalpha.com/input/?i=plot%28+mod%28+sin%28x*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()是一个黑盒子。

答案 1 :(得分:16)

起源可能是纸张:“在y = [(a + x)sin(bx)] mod 1”的帮助下生成随机数,W.J.J。雷伊,第22届欧洲统计学家会议和第7届维尔纽斯概率论与数理统计会议,1998年8月

编辑:由于我找不到本文的副本而且“TestU01”参考可能不清楚,这里是伪C中TestU01中描述的方案:

$query = "INSERT INTO `secure_login`.`user_data_institution` (`id`, `namecontact`, `emailinst`, `nameofinst`, `yearsofexsistance`, `contactinst`, `institutionhour`, `websiteinst`, `address`, `institutionstate`, `institutioncity`, `institutionzipcode`, `aboutinst`, `institutiosizeoffaculty`, `institutionlearninglocatiom`, `nooflocations`, `learningaddress1`, `learninglocality1`, `learningaddress2`, `learninglocality2`, `learningaddress3`, `learninglocality3`, `learningaddress4`, `learninglocality4`, `learningaddress5`, `learninglocality5`, `coursename1`, `coursefeesinstitution1`, `frequencyoffeescollectioninstitution1`, `maxstudentsinstitution1`, `courselength1`, `courselength21`, `demoinstitution1`, `lengthofclassinstitution1`, `coursename2`, `coursefeesinstitution2`, `frequencyoffeescollectioninstitution2`, `maxstudentsinstitution2`, `courselength2`, `courselength22`, `demoinstitution2`, `lengthofclassinstitution2`, `coursename3`, `coursefeesinstitution3`, `frequencyoffeescollectioninstitution3`, `maxstudentsinstitution3`, `courselength3`, `courselength23`, `demoinstitution3`, `lengthofclassinstitution3`, `coursename4`, `coursefeesinstitution4`, `frequencyoffeescollectioninstitution4`, `maxstudentsinstitution4`, `courselength4`, `courselength24`, `demoinstitution4`, `lengthofclassinstitution4`, `coursename5`, `coursefeesinstitution5`, `frequencyoffeescollectioninstitution5`, `maxstudentsinstitution5`, `courselength5`, `courselength25`, `demoinstitution5`, `lengthofclassinstitution5`, `institutiondays1`, `institutiontime1`, `institutiondays2`, `institutiontime2`, `institutiondays3`, `institutiontime3`, `institutiondays4`, `institutiontime4`, `institutiondays5`, `institutiontime5`, `locationsforlearning1`, `locationsforlearning2`, `locationsforlearning3`, `locationsforlearning4`, `locationsforlearning5`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

$stmt = $mysqli->prepare($query);

$stmt->bind_param('i,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s',$userid,$namecontact,$emailinst,$nameofinst,$yearsofexsistance,$contactinst ,$institutionhour,$websiteinst,$address ,$institutionstate ,$institutioncity ,$institutionzipcode ,$aboutinst,$institutiosizeoffaculty,$institutionlearninglocatiom,$nooflocations,$learningaddress1,$learninglocality1,$learningaddress2,$learninglocality2,$learningaddress3,$learninglocality3,$learningaddress4,$learninglocality4,$learningaddress5,$learninglocality5,$coursename1,$coursefeesinstitution1,$frequencyoffeescollectioninstitution1,$maxstudentsinstitution1,$courselength1,$courselength21,$demoinstitution1,$lengthofclassinstitution1,$coursename2,$coursefeesinstitution2,$frequencyoffeescollectioninstitution2,$maxstudentsinstitution2,$courselength2,$courselength22,$demoinstitution2,$lengthofclassinstitution2,$coursename3,$coursefeesinstitution3,$frequencyoffeescollectioninstitution3,$maxstudentsinstitution3,$courselength3,$courselength23,$demoinstitution3,$lengthofclassinstitution3,$coursename4,$coursefeesinstitution4,$frequencyoffeescollectioninstitution4,$maxstudentsinstitution4,$courselength4,$courselength24,$demoinstitution4,$lengthofclassinstitution4,$coursename5,$coursefeesinstitution5,$frequencyoffeescollectioninstitution5,$maxstudentsinstitution5,$courselength5,$courselength25,$demoinstitution5,$lengthofclassinstitution5,$institutiondays1,$institutiontime1,$institutiondays2,$institutiontime2,$institutiondays3,$institutiontime3,$institutiondays4,$institutiontime4,$institutiondays5,$institutiontime5,$locationsforlearning1,$locationsforlearning2,$locationsforlearning3,$locationsforlearning4,$locationsforlearning5);

$stmt->execute();

其中唯一推荐的常量值是B1。

请注意,这是针对流的。转换为1D散列'n'成为整数网格。所以我的猜测是有人看到这个并将't'转换成一个简单的函数f(x,y)。使用上面的原始常量将产生:

#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;
} 

答案 2 :(得分:7)

常量值是任意的,特别是它们非常大,与素数相差几位小数。

高振幅正弦波的1的模数乘以4000是周期函数。它就像一个窗帘或波纹金属制成非常小,因为它乘以4000,然后由点积转过一个角度。

由于函数是2-D,点积具有使周期函数相对于X和Y轴倾斜的效果。按比例约为13/79。这是低效的,你可以通过做(13x + 79y)的窦实际上达到同样的效果,这也可以实现我想的更少的数学...

如果你在X和Y中都找到了该函数的周期,你可以对其进行采样,使其看起来像一个简单的正弦波。

以下是放大graph

的图片

我不知道原点,但它与许多其他产品相似,如果你定期在图形中使用它,它往往会产生莫尔条纹,你可以看到它最终再次出现。

答案 3 :(得分:1)

也许这是一些非经常性的混沌映射,然后它可以解释许多事情,但也可能只是一些大数字的任意操作。

编辑:基本上,函数fract(sin(x)* 43758.5453)是一个简单的类哈希函数,sin(x)提供-1到1之间的平滑sin插值,所以sin(x)* 43758.5453将是插值从-43758.5453到43758.5453。这是一个非常大的范围,因此即使x中的小步骤也会提供大的步骤,并且在小数部分中实际上有很大的变化。需要“fract”才能获得-0.99 ...到0.999范围内的值。 现在,当我们有类似哈希函数的东西时,我们应该从向量中为生产哈希创建函数。最简单的方法是对输入向量的任何y分量调用“hash”separetly。但是,我们将有一些对称的价值观。因此,我们应该从向量中获取一些值,方法是找到一些随机向量并找到该向量的“点”乘积,这里我们去:fract(sin(co(co.xy,vec2(12.9898,78.233))) * 43758.5453); 另外,根据所选择的向量,它的长度应该很长,以便在计算“点”乘积之后有几个“sin”函数的含义。

答案 4 :(得分:1)

我不相信这是真正的起源,但 OP 的代码在 Patricio Gonzalez Vivo 和 Jen Lowe ( https://thebookofshaders.com/10/ ) 的“The Book of Shaders”中作为代码示例提供。在他们的代码中,Patricio Gonzales Vivo 被引用为作者,即“// Author @patriciogv - 2015”

由于 OP 的研究可以追溯到更远的时间(到 08 年),来源至少可以解释其受欢迎程度,作者可能能够阐明他的来源。