// Copyright (c) 2023 Lachlan McDonald // This work is licensed under the MIT License (MIT) // https://github.com/lachlanmcdonald/magicavoxel-shaders // // This script utilises or modifies code from other projects or publications. // Please see the attributions below for more information: // // 1. Copyright (c) 2011 Stefan Gustavson // MIT License (MIT) // https://github.com/ashima/webgl-noise/blob/master/LICENSE // // 2. Cubic Pulse noise adapted from "Useful Little Functions" by Inigo Quilez // MIT License (MIT) // https://www.iquilezles.org/www/articles/functions/functions.htm // // xs noise/terrain [Mode] [Direction] [Scale] [Iterations] [Octaves] [Contrast] [Shift] [Gain] [Lacunarity] [Noise] [Tile X] [Tile Y] // // xs_begin // author : '@lmcdx.bsky.social' // arg : { name = 'Mode' var = 'm_mode' range = '0 1' value = '0' step = '1' precision = '0' } // arg : { name = 'Direction' var = 'm_direction' range = '0 1' value = '0' step = '1' precision = '0' } // arg : { name = 'Scale' var = 'm_scale' range = '5 200' value = '50' step = '1' precision = '0' } // arg : { name = 'Iterations' var = 'm_iterations' range = '1 3' value = '3' step = '1' precision = '0' } // arg : { name = 'Octaves' var = 'm_octaves' range = '1 6' value = '5' step = '1' precision = '0' } // arg : { name = 'Contrast' var = 'm_contrast' range = '0 100' value = '50' step = '1' precision = '0' } // arg : { name = 'Shift' var = 'm_shift' range = '0 100' value = '50' step = '1' precision = '0' } // arg : { name = 'Gain' var = 'm_gain' range = '0 100' value = '65' step = '1' precision = '0' } // arg : { name = 'Lacunarity' var = 'm_lacunarity' range = '0 300' value = '201' step = '1' precision = '0' } // arg : { name = 'Noise' var = 'm_noise' range = '0 100' value = '5' step = '1' precision = '0' } // arg : { name = 'Tile X' var = 'tile_x' range = '0 40' value = '0' step = '1' precision = '0' } // arg : { name = 'Tile Y' var = 'tile_y' range = '0 40' value = '0' step = '1' precision = '0' } // xs_end int mode = int(m_mode); int direction = int(m_direction); float scale = m_scale / 100.0; int iterations = int(m_iterations); int octaves = int(m_octaves); float contrast = 1.0 - m_contrast / 100.0; float shift = m_shift / 100.0; float gain = m_gain / 100.0; float lacunarity = m_lacunarity / 100.0; float noise = m_noise / 200.0; vec3 tile = vec3(tile_x, tile_y, 0.0); vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } vec2 mod289(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } vec3 permute(vec3 x) { return mod289(((x * 34.0) + 1.0) * x); } float snoise(vec2 v) { vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439); vec2 i = floor(v + dot(v, C.yy)); vec2 x0 = v - i + dot(i, C.xx); vec2 i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); vec4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1; i = mod289(i); vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0)); vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw ,x12.zw)), 0.0); m = m * m; m = m * m; vec3 x = 2.0 * fract(p * C.www) - 1.0; vec3 h = abs(x) - 0.5; vec3 a0 = x - floor(x + 0.5); m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h); vec3 g; g.x = a0.x * x0.x + h.x * x0.y; g.yz = a0.yz * x12.xz + h.yz * x12.yw; return 130.0 * dot(m, g); } float fbm(vec2 uv, int octaves) { float total = 0.0; float frequency = 0.5; float amplitude = gain; total = snoise(uv); for (int i = 0; i < octaves; i++) { total += snoise(uv * frequency) * amplitude; frequency *= lacunarity; amplitude *= gain; } return (total + 2.0) / 4.0; } float pattern(vec2 p, int iterations, int octaves) { float f = fbm(p, octaves); for (int i = 1; i < iterations; i++) { f = fbm(p + f, octaves); } return f; } float cubicPulse(float c, float w, float x) { x = abs(x - c); if (x > w) { return 0.0; } else { x /= w; return 1.0 - x * x * (3.0 - 2.0 * x); } } float pal(float p) { float f = floor(mix(0.0, float(i_num_color_sels), p)); return color_sel(f); } float map(vec3 v) { vec3 uv = floor(v) / i_volume_size + tile; if (direction == 1) { uv.z = 1.0 - uv.z; } float f = pattern(uv.xy * scale, iterations, octaves); f = cubicPulse(f, contrast, shift); if (mode == 0) { return f > uv.z ? pal(f + snoise(v.xy) * noise) : 0.0; } else if (mode == 1) { return f > uv.z ? pal(f + snoise(v.zz) * noise) : 0.0; } }