// Copyright (c) 2023 Lachlan McDonald // This work is licensed under the MIT License (MIT) // https://github.com/lachlanmcdonald/magicavoxel-shaders // // xs primitive/greebles1 [Mode] [Count] [Width] [Height] [Depth] [Seed] // // xs_begin // author : '@lmcdx.bsky.social' // arg : { name = 'Mode' var = 'm_mode' range = '0 1' value = '0' step = '1' precision = '0' } // arg : { name = 'Count' var = 'm_count' range = '1 256' value = '32' step = '8' precision = '0' } // arg : { name = 'Width' var = 'm_width' range = '1 256' value = '4' step = '1' precision = '0' } // arg : { name = 'Height' var = 'm_height' range = '1 256' value = '4' step = '1' precision = '0' } // arg : { name = 'Depth' var = 'm_depth' range = '1 256' value = '4' 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); int count = int(m_count); vec3 dim_min = vec3(1.0); vec3 dim_max = vec3(m_width, m_height, 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 Box { ivec3 lower; ivec3 upper; }; float hash(vec2 p) { p += global_seed; return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); } float roundf(float f) { return fract(f) > 0.5 ? ceil(f) : floor(f); } int imix(float a, float b, float f) { return int(roundf(mix(a, b, f))); } float max3(vec3 a) { return max(max(a.x, a.y), a.z); } Box region(vec3 dim_min, vec3 dim_max, float iter, float seed) { float max_size = max3(i_volume_size); float r[5]; r[0] = hash(vec2(iter * seed)); r[1] = hash(vec2(iter * seed + 16.0 * 1.0)); r[2] = hash(vec2(iter * seed + 16.0 * 2.0)); r[3] = hash(vec2(iter * seed + 16.0 * 3.0)); r[4] = hash(vec2(iter * seed + 16.0 * 4.0)); int x = imix(0.0, max_size, r[0]); int y = imix(0.0, max_size, r[1]); ivec3 p = ivec3(x, y, 0); ivec3 dim = ivec3(imix(dim_min.x, dim_max.x, r[2]), imix(dim_min.y, dim_max.y, r[3]), imix(dim_min.z, dim_max.z, r[4])); ivec3 lower = p - ivec3(floor(vec3(dim) / 2.0)); ivec3 upper = p + ivec3(ceil(vec3(dim) / 2.0)); return Box(lower, upper); } bool lowerRegion(ivec3 iv, vec3 dim_min, vec3 dim_max, float seed) { for (int i = 0; i < count; i += 1) { Box j = region(dim_min, dim_max, float(i), seed); if (all(greaterThanEqual(iv, j.lower)) && all(lessThan(iv, j.upper))) { return true; } } return false; } bool upperRegion(ivec3 iv, vec3 dim_min, vec3 dim_max, float seed) { for (int i = 0; i < count; i += 1) { Box j = region(dim_min, dim_max, float(i), seed); if (all(greaterThan(iv, j.lower)) && all(lessThanEqual(iv, j.upper))) { return true; } } return false; } float map(vec3 v) { ivec3 iv = ivec3(v); ivec3 ivs = ivec3(i_volume_size); if (axis_mode.x) { if (lowerRegion(iv.zyx, dim_min.yxz, dim_max.yxz, 64.0 * 1.0)) { return (mode == 0) ? 0.0 : i_color_index; } if (upperRegion((ivs - iv).zyx, dim_min.yxz, dim_max.yxz, 64.0 * 2.0)) { return (mode == 0) ? 0.0 : i_color_index; } } if (axis_mode.y) { if (lowerRegion(iv.xzy, dim_min.xyz, dim_max.xyz, 64.0 * 3.0)) { return (mode == 0) ? 0.0 : i_color_index; } if (upperRegion((ivs - iv).xzy, dim_min.xyz, dim_max.xyz, 64.0 * 4.0)) { return (mode == 0) ? 0.0 : i_color_index; } } if (axis_mode.z) { if (lowerRegion(iv, dim_min.yxz, dim_max.yxz, 64.0 * 5.0)) { return (mode == 0) ? 0.0 : i_color_index; } if (upperRegion(ivs - iv, dim_min.yxz, dim_max.yxz, 64.0 * 6.0)) { return (mode == 0) ? 0.0 : i_color_index; } } return (mode == 0) ? i_color_index : 0.0; }