-
Notifications
You must be signed in to change notification settings - Fork 211
/
2D_SDF.cginc
161 lines (127 loc) · 5.1 KB
/
2D_SDF.cginc
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#ifndef SDF_2D
#define SDF_2D
//transforms
float2 rotate(float2 samplePosition, float rotation){
const float PI = 3.14159;
float angle = rotation * PI * 2 * -1;
float sine, cosine;
sincos(angle, sine, cosine);
return float2(cosine * samplePosition.x + sine * samplePosition.y, cosine * samplePosition.y - sine * samplePosition.x);
}
float2 translate(float2 samplePosition, float2 offset){
//move samplepoint in the opposite direction that we want to move shapes in
return samplePosition - offset;
}
float2 scale(float2 samplePosition, float scale){
return samplePosition / scale;
}
//combinations
///basic
float merge(float shape1, float shape2){
return min(shape1, shape2);
}
float intersect(float shape1, float shape2){
return max(shape1, shape2);
}
float subtract(float base, float subtraction){
return intersect(base, -subtraction);
}
float interpolate(float shape1, float shape2, float amount){
return lerp(shape1, shape2, amount);
}
/// round
float round_merge(float shape1, float shape2, float radius){
float2 intersectionSpace = float2(shape1 - radius, shape2 - radius);
intersectionSpace = min(intersectionSpace, 0);
float insideDistance = -length(intersectionSpace);
float simpleUnion = merge(shape1, shape2);
float outsideDistance = max(simpleUnion, radius);
return insideDistance + outsideDistance;
}
float round_intersect(float shape1, float shape2, float radius){
float2 intersectionSpace = float2(shape1 + radius, shape2 + radius);
intersectionSpace = max(intersectionSpace, 0);
float outsideDistance = length(intersectionSpace);
float simpleIntersection = intersect(shape1, shape2);
float insideDistance = min(simpleIntersection, -radius);
return outsideDistance + insideDistance;
}
float round_subtract(float base, float subtraction, float radius){
return round_intersect(base, -subtraction, radius);
}
///champfer
float champfer_merge(float shape1, float shape2, float champferSize){
const float SQRT_05 = 0.70710678118;
float simpleMerge = merge(shape1, shape2);
float champfer = (shape1 + shape2) * SQRT_05;
champfer = champfer - champferSize;
return merge(simpleMerge, champfer);
}
float champfer_intersect(float shape1, float shape2, float champferSize){
const float SQRT_05 = 0.70710678118;
float simpleIntersect = intersect(shape1, shape2);
float champfer = (shape1 + shape2) * SQRT_05;
champfer = champfer + champferSize;
return intersect(simpleIntersect, champfer);
}
float champfer_subtract(float base, float subtraction, float champferSize){
return champfer_intersect(base, -subtraction, champferSize);
}
/// round border intersection
float round_border(float shape1, float shape2, float radius){
float2 position = float2(shape1, shape2);
float distanceFromBorderIntersection = length(position);
return distanceFromBorderIntersection - radius;
}
float groove_border(float base, float groove, float width, float depth){
float circleBorder = abs(groove) - width;
float grooveShape = subtract(circleBorder, base + depth);
return subtract(base, grooveShape);
}
// space repetition
void mirror(inout float2 position){
position.x = abs(position.x);
}
float2 cells(inout float2 position, float2 period){
//find cell index
float2 cellIndex = position / period;
cellIndex = floor(cellIndex);
//negative positions lead to negative modulo
position = fmod(position, period);
//negative positions now have correct cell coordinates, positive input positions too high
position += period;
//second mod doesn't change values between 0 and period, but brings down values that are above period.
position = fmod(position, period);
return cellIndex;
}
float radial_cells(inout float2 position, float cells, bool mirrorEverySecondCell = false){
const float PI = 3.14159;
float cellSize = PI * 2 / cells;
float2 radialPosition = float2(atan2(position.x, position.y), length(position));
float cellIndex = fmod(floor(radialPosition.x / cellSize) + cells, cells);
radialPosition.x = fmod(fmod(radialPosition.x, cellSize) + cellSize, cellSize);
if(mirrorEverySecondCell){
float flip = fmod(cellIndex, 2);
flip = abs(flip-1);
radialPosition.x = lerp(cellSize - radialPosition.x, radialPosition.x, flip);
}
sincos(radialPosition.x, position.x, position.y);
position = position * radialPosition.y;
return cellIndex;
}
void wobble(inout float2 position, float2 frequency, float2 amount){
float2 wobble = sin(position.yx * frequency) * amount;
position = position + wobble;
}
//shapes
float circle(float2 samplePosition, float radius){
//get distance from center and grow it according to radius
return length(samplePosition) - radius;
}
float rectangle(float2 samplePosition, float2 halfSize){
float2 componentWiseEdgeDistance = abs(samplePosition) - halfSize;
float outsideDistance = length(max(componentWiseEdgeDistance, 0));
float insideDistance = min(max(componentWiseEdgeDistance.x, componentWiseEdgeDistance.y), 0);
return outsideDistance + insideDistance;
}
#endif