Is there a good GLSL hash function?
Asked Answered
C

2

6

So I am still getting upvotes for my ancient comment on this question: What's the origin of this GLSL rand() one-liner?

And it got me thinking, what would a good GLSL hash function look like? There are obvious use cases for it like Perlin noise. There are some properties that I would look for in a good implementation.

  • Stable under different precisions (mediump,highp). This could be configurable.
  • Should be usable in ES2, so it can not use integer support
  • ALU only, no textures
  • Not looking for cryptographic qualities, but for large periods and "perceptual" randomness
  • Should ideally produce the same results on a bare minimum spec ES2 implementation

Practically I think most people just mix x,y inputs by multiplying them with some prime numbers, adding them, multiplying them again, and looking the result coordinate up in a tiling texture of random numbers with nearest sampling.

So this question is less about looking for "the answer" but curiosity if there is a good way to do this. I would also like to know arguments about why it is not possible.

Caskey answered 27/4, 2014 at 4:9 Comment(0)
T
3

"Murmur" style of hash functions seem to perform very well for this kind of application, check out https://nullprogram.com/blog/2018/07/31/ and https://www.shadertoy.com/view/WttXWX. Quoting from the later:

//bias: 0.17353355999581582 ( very probably the best of its kind )
uint lowbias32(uint x)
{
    x ^= x >> 16;
    x *= 0x7feb352dU;
    x ^= x >> 15;
    x *= 0x846ca68bU;
    x ^= x >> 16;
    return x;
}


// bias: 0.020888578919738908 = minimal theoretic limit
uint triple32(uint x)
{
    x ^= x >> 17;
    x *= 0xed5ad4bbU;
    x ^= x >> 11;
    x *= 0xac4c1b51U;
    x ^= x >> 15;
    x *= 0x31848babU;
    x ^= x >> 14;
    return x;
}
Tarra answered 7/1, 2022 at 12:2 Comment(0)
L
2

This question is the top result on Google, so I'd like to direct any hapless passersby to a blog post by Nathan Reed based on this paper, which concluded that the best trade-off in terms of performance and quality for visual noise is a very simple hash called PCG Hash:

uint pcg_hash(uint input)
{
    uint state = input * 747796405u + 2891336453u;
    uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
    return (word >> 22u) ^ word;
}

Source: https://www.reedbeta.com/blog/hash-functions-for-gpu-rendering/

Lecialecithin answered 6/2 at 2:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.