// Copyright (c) 2023 Lachlan McDonald // This work is licensed under the MIT License (MIT) // https://github.com/lachlanmcdonald/magicavoxel-shaders // // xs primitive/greebles2 [Mode] [Min] [Max] [Depth] [Seed] // // xs_begin // author : '@lmcdx.bsky.social' // arg : { name = 'Mode' var = 'm_mode' range = '0 2' value = '0' step = '1' precision = '0' } // arg : { name = 'Min' var = 'm_min' range = '1 256' value = '4' step = '1' precision = '0' } // arg : { name = 'Max' var = 'm_max' range = '1 256' value = '8' step = '1' precision = '0' } // arg : { name = 'Depth' var = 'm_depth' range = '1 256' value = '2' step = '1' precision = '0' } // arg : { name = 'Seed' var = 'global_seed' range = '1 100' value = '1' step = '1' precision = '0' } // xs_end int mode = int(m_mode); float size_min = min(m_min, m_max); float size_max = max(m_min, m_max); float depth = m_depth; bool no_axis_mode = all(equal(ivec3(i_axis), ivec3(0))); bvec3 axis_mode = no_axis_mode ? bvec3(true) : equal(ivec3(i_axis), ivec3(1)); struct Series { float index; float size; float local; }; struct Cell { vec2 index; vec2 local; vec2 size; float depth; }; float hash(vec2 p, float seed) { p += seed + global_seed; return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); } Series findSeries(int limit, float seed, vec2 seed_multiplier) { float cell_index = 0.0; float cell_size = 0.0; int last_index = 0; for (int i = 0; i <= limit;) { vec2 pos = vec2(float(i) * size_max) * seed_multiplier; last_index = i; cell_index += 1.0; cell_size = floor(mix(size_min, size_max + 1.0, hash(pos, seed))); i += int(cell_size); } float local_pos = (cell_index == 0.0) ? float(limit) : float(limit - last_index); Series j = Series(cell_index, cell_size, local_pos); return j; } Cell greeble(vec2 v, float seed) { Series x = findSeries(int(v.x), seed, vec2(64.0, 0.0)); Series y = findSeries(int(v.y), seed, vec2( 0.0, 64.0)); vec2 index = vec2(x.index, y.index); vec2 local = vec2(x.local, y.local); vec2 size = vec2(x.size, y.size); float f = hash(index.xy, seed); float d = mix(0.0, depth, f); return Cell(index, local, size, d); } float map(vec3 v) { float count = 0.0; if (axis_mode.x) { if (v.x <= depth) { Cell g = greeble(v.yz, fract(1.0 / 6.0)); if (v.x < g.depth) { count += 1.0; } } if (v.x >= i_volume_size.x - depth) { Cell g = greeble(i_volume_size.yz - v.yz, fract(2.0 / 6.0)); if (i_volume_size.x - v.x < g.depth) { count += 1.0; } } } if (axis_mode.y) { if (v.y <= depth) { Cell g = greeble(v.xz, fract(3.0 / 6.0)); if (v.y < g.depth) { count += 1.0; } } if (v.y >= i_volume_size.y - depth) { Cell g = greeble(i_volume_size.xz - v.xz, fract(4.0 / 6.0)); if (i_volume_size.y - v.y < g.depth) { count += 1.0; } } } if (axis_mode.z) { if (v.z <= depth) { Cell g = greeble(v.xy, fract(5.0 / 6.0)); if (v.z < g.depth) { count += 1.0; } } if (v.z >= i_volume_size.z - depth) { Cell g = greeble(i_volume_size.xy - v.xy, fract(6.0 / 6.0)); if (i_volume_size.z - v.z < g.depth) { count += 1.0; } } } float min_count = (mode == 2) ? 1.0 : 0.0; if (count > min_count) { if (mode == 0 || mode == 2) { return 0.0; } else { return i_color_index; } } else { if (mode == 0 || mode == 2) { return i_color_index; } else { return 0.0; } } }