// 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. Interweaved gradient noise adapted from "Next Generation Post Processing in Call of Duty Advanced Warfare" // by Jorge Jimenez (Graphics R&D Technical Director - Activision Blizzard) // http://advances.realtimerendering.com/s2014/index.html // // 2. Copyright (c) 2020 ValgoBoi <https://github.com/ValgoBoi/clover-noise> // MIT License (MIT) // https://github.com/ValgoBoi/clover-noise/blob/master/LICENSE // // xs brush/gradient [Mode] [Direction] [Dither] [Seed] // // xs_begin // author : '@lmcdx.bsky.social' // arg : { name = 'Mode' var = 'm_mode' range = '0 5' value = '0' step = '1' precision = '0' } // arg : { name = 'Direction' var = 'm_direction' range = '0 5' value = '0' step = '1' precision = '0' } // arg : { name = 'Dither' var = 'm_noise' range = '0 50' value = '0' 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 direction = int(m_direction); float noise = m_noise / 100.0; float pal(float p) { float f = floor(mix(0.0, float(i_num_color_sels), p)); return color_sel(f); } 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)))); } float hash(vec3 co, float seed) { float r = hash(co.xy, seed); return hash(vec2(r, co.z), seed); } float interleavedGradientNoise(vec2 co) { return fract(52.9829189 * fract(dot(co + global_seed, vec2(0.06711056, 0.00583715)))); } float interleavedGradientNoise(vec3 co) { float r = interleavedGradientNoise(co.xy); return interleavedGradientNoise(vec2(r, co.z)); } float scanLines(vec3 co) { return mod(co.z, 2.0) / 2.0; } float scanLineshash(vec3 co) { float r = hash(co.zz, 0.0); return mod(co.z, 2.0) / 2.0 + r - 0.5; } float wavehash(vec3 co) { float r = hash(co.xy, 0.0); return mod(co.z, 2.0) / 2.0 + r - 0.5; } float orderedDither(vec3 co) { co = co - 0.5; mat4 m = mat4(0.0, 0.5, 0.125, 0.625, 0.75, 0.25, 0.875, 0.375, 0.1875, 0.6875, 0.0625, 0.5625, 0.9375, 0.4375, 0.8125, 0.3125); int x = int(mod(co.x + co.y, 4.0)); int z = int(mod(co.z, 4.0)); return m[x][z]; } float map(vec3 v) { if (direction == 1) { v.z = i_volume_size.z - v.z; } else if (direction == 2) { v.xz = v.zx; } else if (direction == 3) { v.x = i_volume_size.x - v.x; v.xz = v.zx; } else if (direction == 4) { v.yz = v.zy; } else if (direction == 5) { v.y = i_volume_size.y - v.y; v.yz = v.zy; } vec3 p = floor(v) / i_volume_size; float r; if (mode == 0) { r = interleavedGradientNoise(v); } else if (mode == 1) { r = hash(v, 0.0); } else if (mode == 2) { r = scanLineshash(v); } else if (mode == 3) { r = scanLines(v); } else if (mode == 4) { r = wavehash(v); } else if (mode == 5) { r = orderedDither(v); } vec3 k = p + ((r - 0.5) * noise); return pal(k.z); }