// Copyright (c) 2023 Lachlan McDonald // This work is licensed under the MIT License (MIT) // https://github.com/lachlanmcdonald/magicavoxel-shaders // // xs erode [Threshold] [Scale] [Seed] // // xs_begin // author : '@lmcdx.bsky.social' // arg : { name = 'Threshold' var = 'm_threshold' range = '1 25' value = '9' step = '1' precision = '0' } // arg : { name = 'Scale' var = 'm_scale' range = '1 20' value = '6' step = '1' precision = '0' } // arg : { name = 'Seed' var = 'global_seed' range = '1 100' value = '1' step = '1' precision = '0' } // xs_end float scale = m_scale / 4.0; int threshold = int(m_threshold); bool isSelectedPal(float p) { for (int i = 0; i < i_num_color_sels; i += 1) { if (p == color_sel(float(i))) { return true; } } return false; } vec3 hash(vec3 p) { p = vec3(dot(p,vec3(127.1, 311.7, 69.5)), dot(p,vec3(269.5, 183.3, 132.7)), dot(p,vec3(247.3, 108.5, 96.5))); return -1.0 + 2.0 * fract(sin(p) * 43758.5453123); } float perlin(vec3 p) { vec3 i = floor(p); vec3 s = fract(p); float a = dot(hash(i), s); float b = dot(hash(i + vec3(1.0, 0.0, 0.0)), s - vec3(1.0, 0.0, 0.0)); float c = dot(hash(i + vec3(0.0, 1.0, 0.0)), s - vec3(0.0, 1.0, 0.0)); float d = dot(hash(i + vec3(0.0, 0.0, 1.0)), s - vec3(0.0, 0.0, 1.0)); float e = dot(hash(i + vec3(1.0, 1.0, 0.0)), s - vec3(1.0, 1.0, 0.0)); float f = dot(hash(i + vec3(1.0, 0.0, 1.0)), s - vec3(1.0, 0.0, 1.0)); float g = dot(hash(i + vec3(0.0, 1.0, 1.0)), s - vec3(0.0, 1.0, 1.0)); float h = dot(hash(i + vec3(1.0, 1.0, 1.0)), s - vec3(1.0, 1.0, 1.0)); vec3 u = smoothstep(0.0,1.0, s); return mix(mix(mix(a, b, u.x), mix(c, e, u.x), u.y), mix(mix(d, f, u.x), mix(g, h, u.x), u.y), u.z); } float turbulence(vec3 p, float scale) { float f = 0.0; float a = 1.0; p = scale * p; for (int i = 0; i < 4; i++) { f += a * abs(perlin(p)); p = 2.0 * p; a /= 2.0; } return f; } float map(vec3 v) { float index = voxel(v); int adjacent = 0; if (isSelectedPal(index)) { for (float x = -1.0; x <= 1.0; x += 1.0) { for (float y = -1.0; y <= 1.0; y += 1.0) { for (float z = -1.0; z <= 1.0; z += 1.0) { vec3 p = v + vec3(x, y, z); if (p != v && voxel(p) == 0.0) { adjacent += 1; } } } } if (adjacent >= threshold) { vec3 uv = v / i_volume_size; float r = turbulence(uv + vec3(global_seed + i_iter), scale); return r > 0.25 ? index : 0.0; } } return index; }