/******************************************************************************/ /* Project - MudBun Publisher - Long Bunny Labs http://LongBunnyLabs.com Author - Ming-Lun "Allen" Chou http://AllenChou.net */ /******************************************************************************/ #ifndef MUDBUN_SDF_OPERATORS #define MUDBUN_SDF_OPERATORS #include "../Math/MathConst.cginc" // http://www.iquilezles.org/www/articles/smin/smin.htm // http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm // http://mercury.sexy/hg_sdf #define SQRT_2_INV (0.70710678118f) #define ONE_OVER_4 (0.25f) #define ONE_OVER_6 (0.16666666666f) // union //----------------------------------------------------------------------------- // raw union float sdf_uni(float a, float b) { return min(a, b); } // smooth quadratic polynomial union (C1 continuity, order-dependent concatenation) float sdf_uni_quad(float a, float b, float k) { float h = max(k - abs(a - b), 0.0f) / max(k, kEpsilon); return min(a, b) - h * h * k * ONE_OVER_4; } // smooth cubic polynomial union (C2 continuity, order-dependent concatenation) float sdf_uni_cubic(float a, float b, float k) { float h = max(k - abs(a - b), 0.0f) / max(k, kEpsilon); return min(a, b) - h * h * h * k * ONE_OVER_6; } float sdf_uni_round(float a, float b, float r) { float2 u = max(float2(r - a, r - b), float2(0.0f, 0.0f)); return max(r, min(a, b)) - length(u); } float sdf_uni_chamfer(float a, float b, float r) { return min(min(a, b), (a - r + b) * SQRT_2_INV); } // smooth exponential union (infinite continuity, order-independent concatenation) // max(k, kEpsilon); = 30.0f is a good default #define sdf_uni_exp_concat_term(x, k) (exp2(-(k) * (x))) #define sdf_uni_exp_concat_res(sum, k) (-log2(sum) / (k)) float sdf_uni_exp(float a, float b, float k) // 2-term concatenation { float sum = sdf_uni_exp_concat_term(a, k) + sdf_uni_exp_concat_term(b, k); return sdf_uni_exp_concat_res(sum, k); } // smooth power union (infinite continuity, order-independent concatenation) // max(k, kEpsilon); = 8.0f is a good default #define sdf_uni_pow_concat_term(x, k) (pow((x), (k))) #define sdf_uni_pow_concat_res(sum, prod, k) pow((prod) / (sum), 1.0f / (k)) float sdf_uni_pow(float a, float b, float k) // 2-term concatenation { a = sdf_uni_pow_concat_term(a, k); b = sdf_uni_pow_concat_term(b, k); return sdf_uni_pow_concat_res(a + b, a * b, k); } //----------------------------------------------------------------------------- // end: union // intersection //----------------------------------------------------------------------------- // raw intersection float sdf_int(float a, float b) { return max(a, b); } // smooth quadratic polynomial intersection (C1 continuity, order-dependent concatenation) float sdf_int_quad(float a, float b, float k) { float h = max(k - abs(a - b), 0.0f) / max(k, kEpsilon); return max(a, b) + h * h * k * ONE_OVER_4; } // smooth cubic polynomial intersection (C2 continuity, order-dependent concatenation) float sdf_int_cubic(float a, float b, float k) { float h = max(k - abs(a - b), 0.0f) / max(k, kEpsilon); return max(a, b) + h * h * h * k * ONE_OVER_6; } float sdf_int_round(float a, float b, float r) { float2 u = max(float2(r + a, r + b), float2(0.0f, 0.0f)); return min(-r, max(a, b)) + length(u); } float sdf_int_chamfer(float a, float b, float r) { return max(max(a, b), (a + r + b) * SQRT_2_INV); } //----------------------------------------------------------------------------- // end: intersection // subtraction //----------------------------------------------------------------------------- // raw subtraction float sdf_sub(float a, float b) { return max(a, -b); } // smooth quadratic polynomial subtraction (C1 continuity, order-dependent concatenation) float sdf_sub_quad(float a, float b, float k) { return sdf_int_quad(a, -b, k); } // smooth cubic polynomial subtraction (C2 continuity, order-dependent concatenation) float sdf_sub_cubic(float a, float b, float k) { return sdf_int_cubic(a, -b, k); } float sdf_sub_round(float a, float b, float r) { return sdf_int_round(a, -b, r); } float sdf_sub_chamfer(float a, float b, float r) { return sdf_int_chamfer(a, -b, r); } //----------------------------------------------------------------------------- // end: subtraction // misc. //----------------------------------------------------------------------------- float sdf_pipe(float a, float b, float r) { return length(float2(a, b)) - r; } float sdf_engrave(float a, float b, float r) { return max(a, (a + r - abs(b))) * SQRT_2_INV; } //----------------------------------------------------------------------------- // end: misc. #endif