-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
SignedDistanceBooleanOperations.hlsl
127 lines (109 loc) · 3.6 KB
/
SignedDistanceBooleanOperations.hlsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#ifndef SIGNED_DISTANCE_BOOLEAN_OPERATIONS
#define SIGNED_DISTANCE_BOOLEAN_OPERATIONS
// References:
// https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
// https://iquilezles.org/www/articles/smin/smin.htm
// Smooth min polynomial.
// Not commutative, order dependent.
// Suffers from second order discontinuities.
// k: Controls the radius/distance of the smoothness (k = 0.1).
float smin_pol( float a, float b, float k )
{
float h = clamp(0.5 + 0.5 * (b - a) / k, 0, 1);
return lerp(b, a, h) - k * h * (1 - h);
}
float smin_pol_color( float a, float b, float k, float4 c1, float4 c2, out float4 c )
{
float h = clamp(0.5 + 0.5 * (b - a) / k, 0, 1);
c = lerp(c2, c1, h);
return lerp(b, a, h) - k * h * (1 - h);
}
// Smooth min polynomial cubic.
// Not commutative, order dependent.
// Has second order continuity, important for preventing lighting artifacts.
// k: Controls the radius/distance of the smoothness (k = 0.1).
float smin_cubic( float a, float b, float k )
{
float h = max(k - abs(a - b), 0) / k;
return min(a, b) - h * h * h * k * (1.0 / 6.0);
}
// Smooth min power.
// Generalize to more than two distances.
// k: Controls the radius/distance of the smoothness (k = 8).
float smin_pow( float a, float b, float k )
{
a = pow(a, k); b = pow(b, k);
return pow((a*b) / (a + b), 1.0 / k);
}
// Smooth min exponencial.
// Generalize to more than two distances.
// Commutative when taken in pairs, smin(a, smin(b, c)) is equal to smin(b, smin(a, c)).
// k: Controls the radius/distance of the smoothness (k = 32).
float smin_exp( float a, float b, float k )
{
float res = exp2(-k * a) + exp2(-k * b);
return -log2(res) / k;
}
// Smooth max polynomial.
// Not commutative, order dependent.
// Suffers from second order discontinuities.
// k: Controls the radius/distance of the smoothness (k = 32).
float smax_pol( float a, float b, float k )
{
float h = clamp(0.5 - 0.5 * (b - a) / k, 0, 1);
return lerp(b, a, h) + k * h * (1 - h);
}
float smax_pol_color( float a, float b, float k, float4 c1, float4 c2, out float4 c )
{
float h = clamp(0.5 - 0.5 * (b - a) / k, 0, 1);
c = lerp(c2, c1, h);
return lerp(b, a, h) + k * h * (1 - h);
}
// Union boolean operation.
float opUnion( float d1, float d2 )
{
return min(d1, d2);
}
// Intersection boolean operation.
float opIntersection( float d1, float d2 )
{
return max(d1, d2);
}
// Subtraction boolean operation.
// Not commutative and depending on the order of the operands it will produce different results.
float opSubtraction( float d1, float d2 )
{
return max(-d1, d2);
}
// Union boolean operation.
// k: Controls the radius/distance of the smoothness (k = 0.1).
float opSmoothUnion( float d1, float d2, float k )
{
return smin_pol(d1, d2, k);
}
float opSmoothUnionColor( float d1, float d2, float k, float4 c1, float4 c2, out float4 c )
{
return smin_pol_color(d1, d2, k, c1, c2, c);
}
// Intersection boolean operation.
// k: Controls the radius/distance of the smoothness (k = 0.1).
float opSmoothIntersection( float d1, float d2, float k )
{
return smax_pol(d1, d2, k);
}
float opSmoothIntersectionColor( float d1, float d2, float k, float4 c1, float4 c2, out float4 c )
{
return smax_pol_color(d1, d2, k, c1, c2, c);
}
// Subtraction boolean operation.
// Not commutative and depending on the order of the operands it will produce different results.
// k: Controls the radius/distance of the smoothness (k = 0.1).
float opSmoothSubtraction( float d1, float d2, float k )
{
return smax_pol(-d1, d2, k);
}
float opSmoothSubtractionColor( float d1, float d2, float k, float4 c1, float4 c2, out float4 c )
{
return smax_pol_color(-d1, d2, k, c1, c2, c);
}
#endif