// Voronoi fractal steel material // Based on https://www.shadertoy.com/view/4sl3Dr shader_type spatial; uniform vec2 uv_scale = vec2(1.0); uniform float edge_sharpness = 0.25; uniform vec3 base_color: source_color = vec3(1.0); uniform int octaves = 3; uniform float octave_dropoff = 0.7; uniform float octave_scale = 3.0; uniform float metallic = 1.0; uniform float roughness_scale = 1.0; uniform float bump_strength = 1.0; // 1D random numbers float rand(float n) { return fract(sin(n) * 43758.5453123374897); } // 2D random numbers vec2 rand2(vec2 p) { return fract(vec2(sin(p.x * 591.32 + p.y * 154.077), cos(p.x * 391.32 + p.y * 49.077))); } // 1D noise float noise1(float p) { float fl = floor(p); float fc = fract(p); return mix(rand(fl), rand(fl + 1.0), fc); } // voronoi distance noise, based on iq's articles float voronoi(vec2 x) { vec2 p = floor(x); vec2 f = fract(x); vec2 res = vec2(8.0); for(float j = -1.0; j <= 1.0; j ++) { for(float i = -1.0; i <= 1.0; i ++) { vec2 b = vec2(i, j); vec2 r = vec2(b) - f + rand2(p + b); // chebyshev distance, one of many ways to do this float d = max(abs(r.x), abs(r.y)); if(d < res.x) { res.y = res.x; res.x = d; } else if(d < res.y) { res.y = d; } } } return res.y - res.x; } void fragment() { vec2 uv = (UV - 0.5) * 2.0 * uv_scale; float value = 0.0; // Octaves float a = 0.6; float f = 1.0; for(int i = 0; i < octaves; i++) { float v1 = voronoi(uv * f + 5.0); float v2 = 0.0; // Sharp edges v1 = 1.0 - smoothstep(0.0, edge_sharpness, v1); // noise as intensity map v2 = a * (noise1(v1 * 5.5 + 0.1)); value += v2; f *= octave_scale; a *= octave_dropoff; } // Use value as bump map float dZ = 1.0 / bump_strength; vec3 nmap = normalize(vec3(dFdx(value), dFdy(value), dZ)); NORMAL_MAP = nmap / 2.0 + 1.0; ALBEDO = value * base_color; ROUGHNESS = value * roughness_scale; METALLIC = metallic; }