如何在Metal Shader中获取一个随机数?

时间:2017-11-26 18:21:23

标签: random metal

如何在Metal Shader中获取随机数?

我搜索"随机"在金属着色语言规范中,但一无所获。

2 个答案:

答案 0 :(得分:1)

所以我正在为另一个项目开发一个随机数生成器,并希望将它打包成一个整洁的框架一段时间。

你的问题促使我这样做。如果您不介意无耻的插件,here是一个非常简单的框架,它将在金属着色器中为您生成一个随机数,基于(最多)您提供的三个种子。该代码基于following research paper,该{{3}}描述了如何在并行处理器上为蒙特卡罗模拟创建随机数。它还具有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();

我还在回购中包含了一个示例项目,以便您可以看到它是如何使用的。

答案 1 :(得分:0)

请看一下[pcg-random],它非常简单和快速,更重要的是它很快。修改Metal的C代码非常容易。 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);