Kos*_*Kos 167 random shader glsl noise perlin-noise
由于GPU驱动程序供应商通常不愿意noiseX在GLSL中实现,我正在寻找"图形随机化瑞士军刀"效用函数集,最好在GPU着色器中进行优化.我更喜欢GLSL,但任何语言代码都可以为我做,我可以将它自己翻译成GLSL.
具体来说,我希望:
a)伪随机函数 - 在[-1,1]或[0,1]上的N维,均匀分布,从M维种子计算出来(理想情况下是任何值,但我可以将种子限制在内比方说,0..1表示统一的结果分配).就像是:
float random (T seed);
vec2 random2 (T seed);
vec3 random3 (T seed);
vec4 random4 (T seed);
// T being either float, vec2, vec3, vec4 - ideally.
Run Code Online (Sandbox Code Playgroud)
b)像Perlin Noise这样的连续噪声 - 再次,N维,+ - 均匀分布,具有约束的值集合,并且看起来很好(配置外观像Perlin级别的一些选项也可能是有用的).我希望签名如下:
float noise (T coord, TT seed);
vec2 noise2 (T coord, TT seed);
// ...
Run Code Online (Sandbox Code Playgroud)
我不太关注随机数生成理论,所以我最急切地想要一个预先制定的解决方案,但我也很感激"这是一个非常好,高效的1D兰特()这些答案,让我解释一下你如何在它上面制作一个好的N维兰特()...".
app*_*pas 250
对于非常简单的伪随机内容,我使用我在互联网上找到的oneliner:
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
Run Code Online (Sandbox Code Playgroud)
您还可以使用您喜欢的任何PRNG生成噪声纹理,然后以正常方式上传并在着色器中对值进行采样; 如果你愿意,我可以稍后挖掘一下代码示例.
另外,请参阅Stefan Gustavson的这个文件,了解Perlin和Simplex噪声的GLSL实现.
小智 71
Gustavson的实现使用了一维纹理
不,它不是,自2005年以来.只是人们坚持下载旧版本.您提供的链接上的版本仅使用8位2D纹理.
Ashima和我自己的Ian McEwan的新版本没有使用纹理,但在具有大量纹理带宽的典型桌面平台上以大约一半的速度运行.在移动平台上,无纹理版本可能更快,因为纹理通常是一个重要的瓶颈.
我们积极维护的源代码库是:
https://github.com/ashima/webgl-noise
这里使用无纹理和纹理使用版本的噪声集合(仅使用2D纹理):
http://www.itn.liu.se/~stegu/simplexnoise/GLSL-noise-vs-noise.zip
如果您有任何具体问题,请随时给我发电子邮件(我的电子邮件地址可以在classicnoise*.glsl消息来源中找到.)
Spa*_*ial 70
我发现你可以使用一个简单的整数哈希函数并将结果插入到float的尾数中.IIRC GLSL规范保证32位无符号整数和IEEE binary32浮点表示,因此它应该是完全可移植的.
我刚才试了一下.结果非常好:它看起来与我尝试的每个输入都是静态的,根本没有可见的模式.相比之下,流行的sin/fract片段在我的GPU上具有相当明显的对角线,给定相同的输入.
一个缺点是它需要GLSL v3.30.尽管看起来足够快,但我没有凭经验量化其性能.AMD的Shader Analyzer声称HD5870上的vec2版本每时钟13.33像素.对于sin/fract片段,每个时钟16像素的对比度.所以它肯定有点慢.
这是我的实施.我把它留在了这个想法的各种排列中,以便更容易从中派生自己的函数.
/*
static.frag
by Spatial
05 July 2013
*/
#version 330 core
uniform float time;
out vec4 fragment;
// A single iteration of Bob Jenkins' One-At-A-Time hashing algorithm.
uint hash( uint x ) {
x += ( x << 10u );
x ^= ( x >> 6u );
x += ( x << 3u );
x ^= ( x >> 11u );
x += ( x << 15u );
return x;
}
// Compound versions of the hashing algorithm I whipped together.
uint hash( uvec2 v ) { return hash( v.x ^ hash(v.y) ); }
uint hash( uvec3 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ); }
uint hash( uvec4 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ^ hash(v.w) ); }
// Construct a float with half-open range [0:1] using low 23 bits.
// All zeroes yields 0.0, all ones yields the next smallest representable value below 1.0.
float floatConstruct( uint m ) {
const uint ieeeMantissa = 0x007FFFFFu; // binary32 mantissa bitmask
const uint ieeeOne = 0x3F800000u; // 1.0 in IEEE binary32
m &= ieeeMantissa; // Keep only mantissa bits (fractional part)
m |= ieeeOne; // Add fractional part to 1.0
float f = uintBitsToFloat( m ); // Range [1:2]
return f - 1.0; // Range [0:1]
}
// Pseudo-random value in half-open range [0:1].
float random( float x ) { return floatConstruct(hash(floatBitsToUint(x))); }
float random( vec2 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( vec3 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( vec4 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
void main()
{
vec3 inputs = vec3( gl_FragCoord.xy, time ); // Spatial and temporal inputs
float rand = random( inputs ); // Random per-pixel value
vec3 luma = vec3( rand ); // Expand to RGB
fragment = vec4( luma, 1.0 );
}
Run Code Online (Sandbox Code Playgroud)
截图:

我在图像编辑程序中检查了屏幕截图.有256种颜色,平均值为127,这意味着分布均匀并涵盖预期范围.
Dom*_*ano 23
黄金噪音
// Gold Noise ©2015 dcerisano@standard3d.com
// - based on the Golden Ratio
// - uniform normalized distribution
// - fastest static noise generator function (also runs at low precision)
float PHI = 1.61803398874989484820459; // ? = Golden Ratio
float gold_noise(in vec2 xy, in float seed){
return fract(tan(distance(xy*PHI, xy)*seed)*xy.x);
}
Run Code Online (Sandbox Code Playgroud)
截至2017年9月9日,此函数改进了@appas'答案中当前函数的随机分布:
@appas函数也是不完整的,因为没有提供种子(uv不是种子 - 每帧都相同),并且不适用于低精度芯片组.默认情况下,Gold Noise以低精度运行(更快).
Kai*_*ack 14
在 2010 年首次发布这个问题之后,良好的随机函数和硬件支持领域发生了很多变化。
从今天的角度来看,该算法所得出的随机数的均匀性非常差。根据输入值的大小,均匀性会受到很大影响,并且在针对光线/路径追踪应用等进行采样时,可见伪影/图案将变得明显。
为此任务设计了许多不同的函数(其中大多数是整数哈希),针对不同的输入和输出维度,其中大多数正在 2020 年 JCGT 论文《GPU 渲染的哈希函数》中进行评估。根据您的需要,您可以从该论文中建议的函数列表中选择一个函数,也可以从随附的 Shadertoy 中选择一个函数。 本文未涵盖但对我非常有用的一个,在任何输入幅度值上没有任何明显的模式,这也是我想强调的一个。
其他类别的算法使用低差异序列来提取伪随机数,例如带有 Owen-Nayar 置乱的 Sobol 序列。Eric Heitz 在这一领域做了一些令人惊叹的研究,以及他的《将蒙特卡罗误差分布为屏幕空间中的蓝色噪声的低差异采样器》论文。另一个例子是(迄今为止最新的)JCGT 论文Practical Hash-based Owen Scrambling,它将 Owen Scrambling 应用于不同的哈希函数(即 Laine-Karras)。
另一种可能性是所谓的“同余生成器”,“线性同余生成器”(LCG) 或“置换同余生成器”(PCG),其与基于散列的算法的不同之处在于 LCG 和 PCG 具有“状态”和关联的“状态”。函数改变这个状态,从中提取伪随机数。因此,它们不依赖于任何“输入”来计算哈希值,而只是转移/排列/变异一个状态,然后在函数的多次调用中进行。PCG 的一种应用可以在Nvidia 的“Mini Path-Tracer Tutorial”中找到。
还有一些类别使用的算法可以产生具有所需频谱的噪声模式,例如蓝色噪声,这对眼睛来说特别“令人愉悦”。
(我意识到好的StackOverflow 答案应该以源代码的形式提供算法,而不是以链接的形式提供,因为它们可能会损坏,但现在有太多不同的算法,我打算让这个答案成为当今已知的良好算法的摘要)
hash:现在有了 webGL2.0,因此 (w)GLSL 中可以使用整数。-> 对于高质量的便携式哈希(与丑陋的浮点哈希的成本相似),我们现在可以使用“严肃的”哈希技术。IQ 在https://www.shadertoy.com/view/XlXcW4中实现了一些(以及更多)
例如:
const uint k = 1103515245U; // GLIB C
//const uint k = 134775813U; // Delphi and Turbo Pascal
//const uint k = 20170906U; // Today's date (use three days ago's dateif you want a prime)
//const uint k = 1664525U; // Numerical Recipes
vec3 hash( uvec3 x )
{
x = ((x>>8U)^x.yzx)*k;
x = ((x>>8U)^x.yzx)*k;
x = ((x>>8U)^x.yzx)*k;
return vec3(x)*(1.0/float(0xffffffffU));
}
Run Code Online (Sandbox Code Playgroud)
小智 5
使用这个:
highp float rand(vec2 co)
{
highp float a = 12.9898;
highp float b = 78.233;
highp float c = 43758.5453;
highp float dt= dot(co.xy ,vec2(a,b));
highp float sn= mod(dt,3.14);
return fract(sin(sn) * c);
}
Run Code Online (Sandbox Code Playgroud)
不要使用这个:
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
Run Code Online (Sandbox Code Playgroud)
您可以在OpenGL ES 2.0 的规范单行 GLSL rand() 的改进中找到解释
| 归档时间: |
|
| 查看次数: |
153815 次 |
| 最近记录: |