Integer Hash Test

Just a small reference to test integer hash functions on different devices

Created by marcogomez on Mon, 25 Oct 2021 18:31:26 GMT.


#version 300 es
// ╔═════════════╦════════════════╗
// ║ Marco Gomez ║ https://mgz.me ║
// ╚═════════════╩════════════════╝
precision highp float;

uniform vec2 resolution;
uniform float time;
out vec4 fragColor;

// reference reading: https://nullprogram.com/blog/2018/07/31/

#define hX A // A, B, C, D
#define animate 0 //  0, 1

uint A(uint x) {
  x += (x << 10u);
  x ^= (x >>  6u);
  x += (x <<  3u);
  x ^= (x >> 11u);
  x += (x << 15u);
  return x;
}

uint B(uint x) {
  x ^= x >> 16;
  x *= 0x85ebca6bU;
  x ^= x >> 13;
  x *= 0xc2b2ae35U;
  x ^= x >> 16;
  return x;
}

uint C(uint x) {
  x ^= x >> 16;
  x *= 0x7feb352dU;
  x ^= x >> 15;
  x *= 0x846ca68bU;
  x ^= x >> 16;
  return x;
}

uint D(uint x) {
  x ^= x >> 17;
  x *= 0xed5ad4bbU;
  x ^= x >> 11;
  x *= 0xac4c1b51U;
  x ^= x >> 15;
  x *= 0x31848babU;
  x ^= x >> 14;
  return x;
}

uint hX(uvec2 v) { return hX(v.x ^ hX(v.y)                    ); }
uint hX(uvec3 v) { return hX(v.x ^ hX(v.y) ^ hX(v.z)          ); }
uint hX(uvec4 v) { return hX(v.x ^ hX(v.y) ^ hX(v.z) ^ hX(v.w)); }

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]
}

float random(float x) { return floatConstruct(hX(floatBitsToUint(x))); }
float random(vec2  v) { return floatConstruct(hX(floatBitsToUint(v))); }
float random(vec3  v) { return floatConstruct(hX(floatBitsToUint(v))); }
float random(vec4  v) { return floatConstruct(hX(floatBitsToUint(v))); }

float truchet(vec2 uv) {
  uv *= vec2(1.0, gl_FragCoord.z) * 50.0;
  uv.y -= floor(time * 2.0);
  vec2 gv = fract(uv) - 0.5, id = floor(uv);
  float width = 0.15;
  float r = random(id);
  if (r < 0.5) gv.x *= -1.0;
  float mask = smoothstep(0.01, -0.01, abs(gv.x + gv.y) - width);
  return mask;
}

void main(void) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;
  float trp = truchet(uv) * 0.6;
  #if animate > 0
  vec3 rp = vec3(gl_FragCoord.xy, time * 1e3);
  #else
  vec3 rp = vec3(gl_FragCoord.xy, 1.0);
  #endif
  float rnd = random(rp);
  vec3 color = vec3(rnd) * 0.5;
  if (uv.x >= 0.75) { clamp(color += truchet(uv), 0.0, 1.0); }
  fragColor = vec4(vec3(color.r), 1.0);
}