#version 450 layout (location = 0) in vec2 texpos; layout (location = 0) out vec4 Color; layout(push_constant) uniform PushConstant { layout (offset = 0) vec4 rand_seed; } push; // Hash function: http://amindforeverprogramming.blogspot.com/2013/07/random-floats-in-glsl-330.html uint hash( uint x ) { x += ( x << 10u ); x ^= ( x >> 6u ); x += ( x << 3u ); x ^= ( x >> 11u ); x += ( x << 15u ); return x; } uint hash(uvec3 v) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ); } float random(uvec3 pos) { const uint mantissaMask = 0x007FFFFFu; const uint one = 0x3F800000u; uint h = hash( pos ); h &= mantissaMask; h |= one; float r2 = uintBitsToFloat( h ); return r2 - 1.0; } float random(vec3 pos) { return random(floatBitsToUint(pos)); } // returns fraction part float separate(float n, out float i) { float frac = modf(n, i); if (n < 0.f) { frac = 1 + frac; // make fraction non-negative and invert (1 - frac) i --; } return frac; } // Perlin: http://www.iquilezles.org/www/articles/morenoise/morenoise.htm float perlin(vec3 pos, out float dnx, out float dny, out float dnz) { float i, j, k; float u, v, w; // Separate integer and fractional part of coordinates u = separate( pos.x, i); v = separate( pos.y, j); w = separate( pos.z, k); float du = 30.0f*u*u*(u*(u-2.0f)+1.0f); float dv = 30.0f*v*v*(v*(v-2.0f)+1.0f); float dw = 30.0f*w*w*(w*(w-2.0f)+1.0f); u = u*u*u*(u*(u*6.0f-15.0f)+10.0f); v = v*v*v*(v*(v*6.0f-15.0f)+10.0f); w = w*w*w*(w*(w*6.0f-15.0f)+10.0f); float a = random( vec3(i+0, j+0, k+0) ); float b = random( vec3(i+1, j+0, k+0) ); float c = random( vec3(i+0, j+1, k+0) ); float d = random( vec3(i+1, j+1, k+0) ); float e = random( vec3(i+0, j+0, k+1) ); float f = random( vec3(i+1, j+0, k+1) ); float g = random( vec3(i+0, j+1, k+1) ); float h = random( vec3(i+1, j+1, k+1) ); float k0 = a; float k1 = b - a; float k2 = c - a; float k3 = e - a; float k4 = a - b - c + d; float k5 = a - c - e + g; float k6 = a - b - e + f; float k7 = - a + b + c - d + e - f - g + h; /* dnx = du * (k1 + k4*v + k6*w + k7*v*w); */ /* dny = dv * (k2 + k5*w + k4*u + k7*w*u); */ /* dnz = dw * (k3 + k6*u + k5*v + k7*u*v); */ return k0 + k1*u + k2*v + k3*w + k4*u*v + k5*v*w + k6*w*u + k7*u*v*w; } // Note: It starts (octave 1) with the highest frequency, `width` float FBM(vec3 pos, int octaves) { float a, b, c; float result = 0; float p; pos *= push.rand_seed.x; // Frequency = pixel /* pos *= 1000; */ const float power = 3; // Higher -> lower frequencies dominate. Normally 2. float pos_factor = 1.f; float strength_factor = 1.f / pow(power, octaves); for (int i = 0; i < octaves; i ++) { p = perlin(pos * pos_factor, a, b, c ); result += (power - 1) * strength_factor * p; pos_factor *= 0.5f; strength_factor *= power; } return result; } void main() { int octaves = 8; float r; r = FBM(vec3(texpos,0) + push.rand_seed.yzw, octaves); r = step(0.5, r); Color = vec4(vec3(r), 1); }