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);}
传入纹理以生成噪声(通常)是过度设计的。有时它很方便,但在大多数情况下,只计算一个随机数更简单、更快捷。
由于着色器变量在每个片段中都是独立的,因此它们无法重用它们之间的现有变量。那么问题就变成了如何使用“好的”随机数种子之一。无理数似乎一开始就符合要求。那么选择一个好的“置换”函数只是一个“简单”的问题。
这是一些可以解决问题的免费代码:
// Input: It uses texture coords as the random number seed.
// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive.
// Author: Michael Pohoreski
// Copyright: Copyleft 2012 :-)
// NOTE: This has been upgraded to version 3 !!
float random( vec2 p )
{
// We need irrationals for pseudo randomness.
// Most (all?) known transcendental numbers will (generally) work.
const vec2 r = vec2(
23.1406926327792690, // e^pi (Gelfond's constant)
2.6651441426902251); // 2^sqrt(2) (Gelfond–Schneider constant)
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.);
}
将以上内容粘贴到:
我还创建了一个带有 2 个噪声函数和 2 个随机函数的“比较”ShaderToy 示例:
使用噪声“[2TC 15] Speckle Cross Fade”的演示
一个“经典”随机函数,有时被称为snoise3
是这个坏函数:
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
如果您想比较“伪随机”函数,请查看 Dave's Hash without sine shader。