我该如何在Metal着色器中获取随机数?
我在《Metal Shading Language Specification》中搜索了“random”,但没有找到相关内容。
2^121
,因此它应该适用于大多数可以在GPU上进行的合理计算。您只需在着色器中调用初始化程序,然后调用rand()
即可:
// Initialize a random number generator, seeds 2 and 3 are optional
Loki rng = Loki(seed1, seed2, seed3);
// get a random float [0,1)
float random_float = rng.rand();
我在存储库中还包含了一个示例项目,以便您可以看到它的使用方式。
看起来没有一个内置的函数。这个关于 MetalShaderShowcase/AAPLWoodShader.metal 的示例代码定义了它自己简单的rand
函数。
// Generate a random float in the range [0.0f, 1.0f] using x, y, and z (based on the xor128 algorithm)
float rand(int x, int y, int z)
{
int seed = x + y * 57 + z * 241;
seed= (seed<< 13) ^ seed;
return (( 1.0 - ( (seed * (seed * seed * 15731 + 789221) + 1376312589) & 2147483647) / 1073741824.0f) + 1.0f) / 2.0f;
}
[pcg-random]
,它非常简单和快速,更重要的是它很快。而且,将其C代码修改为Metal非常容易。https://www.pcg-random.org/
typedef struct { uint64_t state; uint64_t inc; } pcg32_random_t;
void pcg32_srandom_r(thread pcg32_random_t* rng, uint64_t initstate, uint64_t initseq)
{
rng->state = 0U;
rng->inc = (initseq << 1u) | 1u;
pcg32_random_r(rng);
rng->state += initstate;
pcg32_random_r(rng);
}
uint32_t pcg32_random_r(thread pcg32_random_t* rng)
{
uint64_t oldstate = rng->state;
rng->state = oldstate * 6364136223846793005ULL + rng->inc;
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
uint32_t rot = oldstate >> 59u;
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}
我该如何使用它?
float randomF(thread pcg32_random_t* rng)
{
//return pcg32_random_r(rng)/float(UINT_MAX);
return ldexp(float(pcg32_random_r(rng)), -32);
}
pcg32_random_t rng;
pcg32_srandom_r(&rng, pos_grid.x*int_time, pos_grid.y*int_time);
auto randomFloat = randomF(&rng);
不必在GPU上计算随机数,您也可以在CPU上计算一堆随机数,然后使用uniform / MTLBuffer
将它们传递到着色器中。