-
Notifications
You must be signed in to change notification settings - Fork 0
/
blob_shader.glsl
77 lines (70 loc) · 2.22 KB
/
blob_shader.glsl
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
#pragma language glsl3
uniform int objects = 0;
// uniform vec2 positions[100];
// uniform float radii[100];
uniform sampler2D positionradii;
varying vec2 texPos;
// from 0 (most blending) to 1 (no blending)
uniform float k1 = 0.05; // blob clump boundary smoothness
uniform float k2 = 0.1; // blob wall smoothness
// higher = more blending
uniform float k3 = 30; // blob wall-boundary blending
uniform float borderWidth = 8;
#ifdef VERTEX
vec4 position(mat4 transform_projection, vec4 vertex_position)
{
texPos = vertex_position.xy - love_ScreenSize.xy/2;
return transform_projection * vertex_position;
}
#endif
#ifdef PIXEL
// cubic smooth min (for blending walls and boundaries)
float smin( float a, float b, float k )
{
float h = max( k-abs(a-b), 0.0 )/k;
return min( a, b ) - h*h*h*k*(1.0/6.0);
}
// I use power-based smooth min for walls and boundaries (since it is cumulative)
/* Two-value example:
float smin( float a, float b, float k )
{
float res = exp2( -k*a ) + exp2( -k*b );
return -log2( res )/k;
}
*/
vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords ) {
float mindist = 0;
int closestobj = -1;
float cummin = 0;
for (int i = 0; i < objects; i++) {
vec4 data = texelFetch(positionradii, ivec2(i, 0), 0);
float dist = distance(data.xy, texPos) - data.z;
cummin += exp2( -k1 * dist );
if (closestobj == -1 || dist < mindist) {
mindist = dist;
closestobj = i;
}
}
float finalmin = -log2( cummin )/k1;
// discards pixels not in shape
if (finalmin > 0) discard;
// The next part finds whether or not the
// fragment is a blob to blob boundary based
// on the distance to the midpoint between.
// (these results are also smoothed)
float cummin2 = 0;
for (int j = 0; j < objects; j++) {
if (j == closestobj) continue;
vec4 data = texelFetch(positionradii, ivec2(j, 0), 0);
float dist = distance(data.xy, texPos) - data.z;
cummin2 += exp2( -k2 * abs(dist-mindist));
}
float bordermin = -log2( cummin2 )/k2;
// blend blob-blob boundaries and edge of shape boundary
// then check if result is under the border thickness
if (smin(bordermin, abs(finalmin), k3) < borderWidth) {
color.a = 1;
}
return color;
}
#endif