-
Notifications
You must be signed in to change notification settings - Fork 24
/
safeUtilDistanceFunctionsForLowPrecision.sca
195 lines (155 loc) · 4.83 KB
/
safeUtilDistanceFunctionsForLowPrecision.sca
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
using namespace std;
#import < utils >
//following Ognjen Dragoljević's post about Low Precision shader practices
//https://www.facebook.com/groups/SparkARcommunity/permalink/1131916640553710/
//ref https://gist.github.com/BarakChamo/bbaa5080acad2e3f8080e3bdd42325a7
//the built-ins for SparkSL are
//these
// vec2 safeNormalize(vec2 v);
// vec3 safeNormalize(vec3 v);
// vec4 safeNormalize(vec4 v);
// float safeLength(vec2 v);
// float safeLength(vec3 v);
// float safeLength(vec4 v);
// float safeDistance(vec2 p0, vec2 p1);
// float safeDistance(vec3 p0, vec3 p1);
// float safeDistance(vec4 p0, vec4 p1);
// float safeAtan(float y, float x);]
//but below are some more interesting ones
float euclideanDistance(float p1, float p2) {
float d1 = (p1 - p2);
return sqrt(pow(d1, 2.0));
}
float euclideanDistance(vec2 p1, vec2 p2) {
float d1 = (p1.x - p2.x);
float d2 = (p1.y - p2.y);
return sqrt(pow(d1, 2.0) + pow(d2, 2.0));
}
float euclideanDistance(vec3 p1, vec3 p2) {
float d1 = (p1.x - p2.x);
float d2 = (p1.y - p2.y);
float d3 = (p1.z - p2.z);
return sqrt(pow(d1, 2.0) + pow(d2, 2.0) + pow(d3, 2.0));
}
/* Manhattan distance */
/* https://en.wikipedia.org/wiki/Taxicab_geometry */
float manhattanDistance(float p1, float p2) {
float d1 = abs(p1 - p2);
return d1;
}
float manhattanDistance(vec2 p1, vec2 p2) {
float d1 = abs(p1.x - p2.x);
float d2 = abs(p1.y - p2.y);
return d1 + d2;
}
float manhattanDistance(vec3 p1, vec3 p2) {
float d1 = abs(p1.x - p2.x);
float d2 = abs(p1.y - p2.y);
float d3 = abs(p1.z - p2.z);
return d1 + d2 + d3;
}
/* Minkowski distance */
/* https://en.wikipedia.org/wiki/Minkowski_distance */
float minkowskiDistance(float p1, float p2, float power) {
float d1 = pow(abs(p1 - p2), power);
return pow(d1, 1.0 / power);
}
float minkowskiDistance(vec2 p1, vec2 p2, float power) {
float d1 = pow(abs(p1.x - p2.x), power);
float d2 = pow(abs(p1.y - p2.y), power);
return pow(d1 + d2, 1.0 / power);
}
float minkowskiDistance(vec3 p1, vec3 p2, float power) {
float d1 = pow(abs(p1.x - p2.x), power);
float d2 = pow(abs(p1.y - p2.y), power);
float d3 = pow(abs(p1.z - p2.z), power);
return pow(d1 + d2 + d3, 1.0 / power);
}
/* Chebyshev distance */
/* https://en.wikipedia.org/wiki/Chebyshev_distance */
float chebyshevDistance(float p1, float p2) {
float d1 = abs(p1 - p2);
return d1;
}
float chebyshevDistance(vec2 p1, vec2 p2) {
float d1 = abs(p1.x - p2.x);
float d2 = abs(p1.y - p2.y);
return max(d1, d2);
}
float chebyshevDistance(vec3 p1, vec3 p2) {
float d1 = abs(p1.x - p2.x);
float d2 = abs(p1.y - p2.y);
float d3 = abs(p1.z - p2.z);
return max(d1, max(d2, d3));
}
//#define constant Time = getTime();
vec2 hash( vec2 p ) {
p = vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3)));
return fract(sin(p)*18.5453);
}
float random (vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
}
/* distance tesselation */
vec2 tessellate( in vec2 x, in float wf ) {
vec2 n = floor( x );
vec2 f = fract( x );
// weight factor
float w = random(n) * wf;
// MODIFY THIS:
// Maximum distance for distance function
// 2.0 and up should cover the whole distance
// Less will form distance bubbles
vec2 m;
m = vec2( 2.0 );
// m = vec2( 0.5 );
// Cover a unit range around the point
for( int j=-1; j<=1; j++ )
for( int i=-1; i<=1; i++ )
{
// distance point (edges of the unit square around the point)
vec2 g = vec2( float(i), float(j) );
// random point inside the unit square
// Basically, random point inside the tile
vec2 o = hash( n + g );
float Time = getTime();
// move the point around the tile based on sin(time);
vec2 r = g - f + (0.5+0.5*sin(Time+6.2831*o));
float w = random(o) * wf;
// Get the vector's distance from origin
// This is similar to the self dot product operation dot(r,r);
float d;
// MODIFY THIS: try using different functions
d = euclideanDistance(vec2(0), r);
// d = manhattanDistance(vec2(0), r);
d = minkowskiDistance(vec2(0), r, 2.0 + sin(Time * 2.0));
// d = chebyshevDistance(vec2(0), r);
// Additively weight the distance
d += w;
if( d<m.x )
m = vec2( d, o );
}
// Return point distance
return m;
}
out vec4 fragColor;
void main()
{
vec2 st = vUV.st;
// MODIFY THIS:
// Tile the coordinate space
st *= 5.0;
// MODIFY THIS:
// Weight factor applied to a random weight coefficient in the tesselation function
float Time = getTime();
float weightFactor = (1.0 + sin(Time * 5.0)) / 2.0;
// Generate tessellate pattern
vec2 c = tessellate( st, weightFactor );
// Colorize
vec3 col = 0.5 + 0.5 * cos( 2.0 + c.y * 3.0 + c.x + vec3(1.5,0.0,0.0) );
// Add distance-based gradient
col *= clamp(1.0 - 0.2 * pow(c.x, 2.0), 0.0,1.0);
// Draw points
col -= (1.0-smoothstep( 0.01, 0.05, c.x));
fragColor = vec4( col, 1.0 );
}