#define_import_path utils #import noise_gen::FBN; #import bevy_pbr::prepass_utils::{prepass_depth,prepass_normal}; #import bevy_pbr::mesh_view_bindings::{globals,view,View}; fn hash2(p: vec2) -> vec2 { var p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973)); p3 += dot(p3, p3.yzx + 19.19); let o = fract(vec2((p3.x + p3.y) * p3.z, (p3.x + p3.z) * p3.y)); return o; } fn mod289(x: f32) -> f32 {return x - floor(x * (1.0 / 289.0)) * 289.0;} fn mod289_4(x: vec4f) -> vec4f {return x - floor(x * (1.0 / 289.0)) * 289.0;} fn perm(x: vec4f) -> vec4f {return mod289_4(((x * 34.0) + 1.0) * x);} fn fresnel(ior: f32, I: vec3, N: vec3) -> f32 { let r0 = pow((1.0 - ior) / (1.0 + ior), 2.0); return smoothstep(-1.0, 1.0, r0 + (1.0 - r0) * pow(1.0 - dot(N, I), 5.0)); } // WTFPL License fn noise2(n: vec2) -> f32 { let d = vec2f(0., 1.); let b = floor(n); let f = smoothstep(vec2(0.), vec2(1.), fract(n)); return mix(mix(rand22(b), rand22(b + d.yx), f.x), mix(rand22(b + d.xy), rand22(b + d.yy), f.x), f.y); } fn rand22(n: vec2) -> f32 { return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); } fn fade3(t: vec3f) -> vec3f { return t * t * t * (t * (t * 6. - 15.) + 10.); } fn rand11(n: f32) -> f32 { return fract(sin(n) * 43758.5453123); } fn apply_hue(col: vec3, hueAdjust: f32) -> vec3 { let k = vec3(0.57735, 0.57735, 0.57735); let cosAngle = cos(hueAdjust); return col * cosAngle + cross(k, col) * sin(hueAdjust) + k * dot(k, col) * (1.0 - cosAngle); } /// Signed distance field for a Bezier curve. fn sd_bezier(p: vec2f, A: vec2f, B: vec2f, C: vec2f) -> vec2f { let a = B - A; let b = A - 2. * B + C; let c = a * 2.; let d = A - p; let kk = 1. / dot(b, b); let kx = kk * dot(a, b); let ky = kk * (2. * dot(a, a) + dot(d, b)) / 3.; let kz = kk * dot(d, a); let p1 = ky - kx * kx; let p3 = p1 * p1 * p1; let q = kx * (2.0 * kx * kx - 3.0 * ky) + kz; var h: f32 = q * q + 4. * p3; var res: vec2f; if h >= 0. { h = sqrt(h); let x = (vec2f(h, -h) - q) / 2.; let uv = sign(x) * pow(abs(x), vec2f(1. / 3.)); let t = clamp(uv.x + uv.y - kx, 0., 1.); let f = d + (c + b * t) * t; res = vec2f(dot(f, f), t); } else { let z = sqrt(-p1); let v = acos(q / (p1 * z * 2.)) / 3.; let m = cos(v); let n = sin(v) * 1.732050808; let t = clamp(vec2f(m + m, -n - m) * z - kx, vec2f(0.0), vec2f(1.0)); let f = d + (c + b * t.x) * t.x; var dis: f32 = dot(f, f); res = vec2f(dis, t.x); let g = d + (c + b * t.y) * t.y; dis = dot(g, g); res = select(res, vec2f(dis, t.y), dis < res.x); } res.x = sqrt(res.x); return res; } fn raymarch_clip(position: vec4, center: vec3, radius: f32, color: vec4) -> vec4 { var ro: vec3 = view.world_position; var dst: f32 = 999.0; let rd: vec3 = normalize(position - vec4(ro, 1.0)).xyz; for (var x = 0; x < 50; x++) { dst = sphere_hit(ro, center, radius); ro += rd * dst; if dst < 0.05 { return vec4(1.0); } if dst > 50.0 { break; } } return vec4(0.0); } fn cut_sphere_hit(p: vec3, c: vec3, r: f32) -> f32 { return max(-distance(p, c - vec3(0.2)) - (r + 0.2), distance(p, c) - r); } fn raymarch_hit(position: vec4, center: vec3, radius: f32, fog_color: vec4, steps: u32, prec: f32) -> vec4 { var ro: vec3 = view.world_position; var dst: f32 = 999.0; let rd: vec3 = normalize(position - vec4(ro, 1.0)).xyz; let tolerance = 1.0 / pow(10.0, f32(steps) / prec); var norm: vec3f; for (var x = 0; x < i32(steps); x++) { let noise_offset = FBN(vec4f(vec3((ro)), globals.time / 4.0)); dst = sphere_hit(ro + noise_offset, vec3(0.0), radius); ro += rd * dst; norm = get_ray_normal(ro); if dst < tolerance { let darken_ramp = 1.0 - f32(x) / f32(steps) * 2.0; let diffuse_str = max(0.0, dot(normalize(vec3(5.0, 5.0, 0.0)), norm)); let diffuse = darken_ramp * diffuse_str; // let ref_source = normalize(reflect(-view.world_position, norm)); return vec4(fog_color.rgb * diffuse, 1.0); } if dst > 50.0 { break; } } return vec4(10.0 - dst); } fn sphere_hit(p: vec3, c: vec3, r: f32) -> f32 { return distance(p, c) - r; } fn get_ray_normal(p: vec3f) -> vec3f { let d = vec2(0.01, 0.0); let gx = map(p, p - d.xyy, p + d.xyy, -p + d.xyy, p + d.xyy); let gy = map(p, p - d.yxy, p + d.yxy, -p + d.yxy, p + d.yxy); let gz = map(p, p - d.yyx, p + d.yyx, -p + d.yyx, p + d.yyx); return normalize(vec3(gx, gy, gz)); } fn map(value: vec3f, min1: vec3f, max1: vec3f, min2: vec3f, max2: vec3f) -> f32 { return length(min2 + (value - min1) * (max2 - min2) / (max1 - min1)); } // fn voronoi(p: vec2, depth: f32, dist_fn: u32, exp: f32) -> vec3 { // var md = 10.0; // var med = 10.0; // var tcc: vec2; // var cc: vec2; // let n = floor(p); // var cell_id = 0.0; // for (var x = -1; x <= 1; x++) { // for (var y = -1; y <= 1; y++) { // let g = n + vec2(f32(x), f32(y)); // let cache = voro_cache[i32(g.x) + (i32(g.y) * 10)]; // let o = g + cache.xy; // let r = o - p; // var d: f32 = length(r); // if dist_fn == 1u { // d = abs(o.x - p.x) + abs(o.y - p.y); // } else if dist_fn == 2u { // d = max(abs(o.x - p.x), abs(o.y - p.y)); // } else if dist_fn >= 3u { // d = pow(pow(abs(o.x - p.x), exp) + pow(abs(o.y - p.y), exp), 1.0 / exp); // } if depth < 0.0015 { // let dcc = abs(cc - g); // if !(dcc.x + dcc.y < 0.05) { // let tc = (tcc + r) * 0.5; // let cd = normalize(r - tcc); // let ed = dot(tc, cd); // med = min(med, ed); // } // } // if d < md { // md = d; // cc = g; // tcc = r; // cell_id = cache.z; // if dist_fn == 0u && d < cache.w { // break; // } // } // } // } // return vec3(md, cell_id, med); // } fn sincosbundle(val: f32) -> f32 { return sin(cos(2. * val) + sin(4. * val) - cos(5. * val) + sin(3. * val)) * 0.05; } //random noise function fn nrand(n: vec2f) -> f32 { return fract(sin(dot(n.xy, vec2(12.9898, 78.233))) * 43758.5453); } // 2-tone patterns fn half_tone(rotation: f32) -> mat2x2 { return rotate2D(rotation); } fn wave_texture(freq: f32, amplitude: f32, gain: f32, sharpness: f32) -> f32 { let peak = (1.0 * amplitude + gain) * (1.0 - sharpness); return smoothstep(-peak, peak, sin(freq) * amplitude + gain); } fn grid_texture(uv: vec2, outline: f32) -> f32 { if outline > 1.0 { return abs(floor(uv.x) + floor(uv.y)) % 2.0; } return wave_texture(uv.x, 0.7, 0.5, outline) * wave_texture(uv.y, 0.7, 0.5, outline); } fn hash3(p: vec2f) -> vec3f { let q = vec3f(dot(p, vec2f(127.1, 311.7)), dot(p, vec2f(269.5, 183.3)), dot(p, vec2f(419.2, 371.9))); return fract(sin(q) * 43758.5453); } fn brick_texture(uv: vec2f) -> f32 { let coord = floor(uv); let gv = fract(uv); let movingValue = -sincosbundle(coord.y) * 2.0; let offset = floor(uv.y % 2.0) * 1.5; let verticalEdge = abs(cos(uv.x + offset)); let vrtEdge = step(1. - 0.01, verticalEdge) == 1.; let hrtEdge = gv.y > (0.9) || gv.y < (0.1); if hrtEdge || vrtEdge { return 0.0; } return 1.0; } fn trace(origin: vec3f, r: vec3f) -> f32 { var t = 0.0; for (var i = 0; i < 64; i++) { let p = origin + r * t; let d = mmap(p); t += d * 0.22; } return t ; } fn mmap(ip: vec3f) -> f32 { var p = ip; var q = p; var qa = p; q = pmod3(q, vec3f(0.8, 1.0, 0.23)); qa = pmod3(qa, vec3f(0.8, 1.0, 0.18)); p.x = pmod1(p.x, 1.0); let s1 = sd_sphere(p, 0.75); let s2 = sd_sphere(q, 0.5); let s3 = sd_sphere(qa, 0.555); return min(min(s1, s2), s3); } fn pmod1(in: f32, size: f32) -> f32 { let halfsize = size * 0.5; return (in + halfsize % size) - halfsize; } fn pmod3(in: vec3f, size: vec3f) -> vec3f { let out = (in % size * 0.5) - (size * 0.5); return out; } fn sd_sphere(p: vec3f, radius: f32) -> f32 { return (length(p) - radius); } // fn fade(col: vec4f, uv: vec2f) { // let fade = max(abs(uv.x), abs(uv.y)) - 1.0 ; // This is really cool. // let col = col * (fade / (0.005 + fade)); // return col; // } fn hsv2rgb(c: vec3f) -> vec3f { var rgb: vec3f = clamp( abs((c.x * 6.0 + vec3f(0.0, 4.0, 2.0)) % 6.0 - 3.0) - 1.0, vec3f(0.0), vec3f(1.0) ); return c.z * mix(vec3f(1.0), rgb, c.y); } fn gradient(t: f32) -> vec3f { let h: f32 = 0.6666 * (1.0 - t * t); let s: f32 = 0.75; let v: f32 = 1.0 - 0.9 * (1.0 - t) * (1.0 - t); return hsv2rgb(vec3f(h, s, v)); } /// Clockwise by `theta` fn rotate2D(theta: f32) -> mat2x2 { let c = cos(theta); let s = sin(theta); return mat2x2(c, s, -s, c); }