更新于2017年7月:我已经使“伪随机性”更加稳定。
// Version 3
float random( vec2 p )
{
vec2 K1 = vec2(
23.14069263277926, // e^pi (Gelfond's constant)
2.665144142690225 // 2^sqrt(2) (Gelfond–Schneider constant)
);
return fract( cos( dot(p,K1) ) * 12345.6789 );
}
这是版本信息:
float random( vec2 p )
{
// e^pi (Gelfond's constant)
// 2^sqrt(2) (Gelfond–Schneider constant)
vec2 K1 = vec2( 23.14069263277926, 2.665144142690225 );
//return fract( cos( mod( 12345678., 256. * dot(p,K1) ) ) ); // ver1
//return fract(cos(dot(p,K1)) * 123456.); // ver2
return fract(cos(dot(p,K1)) * 12345.6789); // ver3
}
// Minified version 3:
float random(vec2 p){return fract(cos(dot(p,vec2(23.14069263277926,2.665144142690225)))*12345.6789);}
将纹理传递到生成噪声中通常是过度设计(通常情况下)。虽然有时使用它会很方便,但在大多数情况下,只需计算随机数即可使代码更简单、更快。
由于着色器变量对每个片段都是独立的,因此它们无法在它们之间重复使用现有变量。那么问题就变成了如何使用“好”的随机数种子。无理数似乎是一个不错的选择。然后就只需要选择一个好的“permute”函数。
以下是一些自由代码,它可以解决这个问题:
float random( vec2 p )
{
const vec2 r = vec2(
23.1406926327792690,
2.6651441426902251);
return fract( cos( mod( 123456789., 1e-7 + 256. * dot(p,r) ) ) );
}
如果我们将这个公式分解成其组成部分,就更容易想象到正在发生什么:
const vec2 k = vec2(23.1406926327792690,2.6651441426902251);
float rnd0( vec2 uv ) {return dot(uv,k); }
float rnd1( vec2 uv ) { return 1e-7 + 256. + dot(uv,k); }
float rnd2( vec2 uv ) { return mod( 123456789., 256. * dot(uv,k) ); }
float rnd3( vec2 uv ) { return cos( mod( 123456789., 256. * dot(uv,k) ) ); }
// We can even tweak the formula
float rnd4( vec2 uv ) { return fract( cos( mod( 1234., 1024. * dot(uv,k) ) ) ); }
float rnd5( vec2 uv ) { return fract( cos( mod( 12345., 1024. * dot(uv,k) ) ) ); }
float rnd6( vec2 uv ) { return fract( cos( mod( 123456., 1024. * dot(uv,k) ) ) ); }
float rnd7( vec2 uv ) { return fract( cos( mod( 1234567., 1024. * dot(uv,k) ) ) ); }
float rnd8( vec2 uv ) { return fract( cos( mod( 12345678., 1024. * dot(uv,k) ) ) ); }
float rnd9( vec2 uv ) { return fract( cos( mod( 123456780., 1024. * dot(uv,k) ) ) ); }
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
mediump vec2 uv = fragCoord.xy / iResolution.xy;
float i = rnd9(uv);
fragColor = vec4(i,i,i,1.);
}
将以上内容复制粘贴至:
我还创建了一个 "比较" ShaderToy 示例,其中包括两个噪声函数和两个随机函数:
演示如何使用噪声的 "[2TC 15] Speckle Cross Fade":
一种"经典"的随机函数,有时被称为
snoise3
, 可以参考这个
不好的函数:
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
如果你想比较“伪随机”函数,可以查看戴夫的无正弦哈希着色器。