「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」
在glsl中并没有提供生成随机数函数公式,如果需要实现随机数函数利用glsl现有公式模拟出随机数值。随机数在glsl中有很多应用像是噪点图就是利用随机数来实现。因此在实现噪点图之前先了解如何生成随机数函数。
随机数生成
一维随机函数
可以利用正弦sin函数模拟一维随机数。sin函数值域范围在[-1,1]之间,在这个范围内可以将正弦函数值乘以一个比较大的值例如1000,然后使用fract函数只取小数部分的值,就能模拟打散成伪随机数。最后结果会发现相乘的数值越大sin函数获取到的结果越离散越没有规律。
float random(float x)
{
float y = fract(sin(x)*100000.0);
return y;
}
| y = fract(sin(x)*1.0) | y = fract(sin(x)*100.0) | y = fract(sin(x)*1000.0) |
|---|---|---|
二维随机函数
了解一维随机函数之后可以将它应用到二维随机上。在glsl纹理顶点上有x轴和y轴,就需要将二维向量转化成一维浮点数。这里将二维uv向量使用dot函数将各分量分别相乘后相加,这里相乘的分量值是vec2(12.9898,78.233)(若有必要可以修改该向量值)。最后和一维随机函数一样执行sin函数和fract函数获取最终伪随机数。
float random (vec2 uv)
{
return fract(sin(dot(uv.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
随机数加强
在glsl中通过取巧的方式生成随机数其实是一个伪随机的过程。在实验过程中使用一维随机数生成函数会发现使用sin函数在-1.5707和1.5707上会有较大波动。或许可以通过一些方法让伪随机数更加“伪随机”,例如两个伪随机函数相乘,开平方根等方法。
float y = random(x) * random(x);
float y = sqrt(random(x));
float y = pow(random(x),5.)
// 二维特殊处理方式
fract(52.9829189f
* frac(uv.x * 0.06711056f
+ uv.y * 0.00583715f))
总结
在glsl上虽然无法做到完全意义上的随机,但已经能够在日常开发应用中起到重要作用。类似开篇说到噪点图确实能够提供方法支持实现,可以使用二维随机函数实现噪点图效果。