-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathupdate.glsl
105 lines (78 loc) · 3.14 KB
/
update.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
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
precision highp float;
precision highp int;
#define MaxNCompatibleEdges 500
uniform int height; // problem height
uniform int width; // problem width
uniform int nEdges;
uniform int nPoints;
uniform int P; // number of points per edge excluding terminal points
uniform float K;
uniform float S;
uniform sampler2D edges; // width X height
uniform sampler2D compatibility; // MaxNCompatibleEdges*nTiles X height
varying vec2 vTextureCoord;
float W, H; // width and height = nPoints and nEdges
int c; // the point = which column
float r; // the edge row in texture coordinate
int tileNumber; // 0,1,2...
int cOffset; // column offset in case of tiling
float c0, cEnd; // the end points of the edge at 0 and (P+1) in texture coordinate, should be the same for all edges
int edge; // the edge id = which row
vec3 crnt; // current point fetched from texture
vec3 P1, P2; // terminal points of the edge containg the current point
float edgeLength; // distance(P1, P2)
float eps = 1e-6;
vec3 applySpringForce() {
float kP = K/(edgeLength*float(P+1));
vec3 prev = texture2D(edges, vec2((float(c-1+cOffset)+0.5)/W, r)).xyz;
vec3 next = texture2D(edges, vec2((float(c+1+cOffset)+0.5)/W, r)).xyz;
return kP*(prev - 2.*crnt + next);
}
vec3 applyElectrostaticForce() {
vec3 forces = vec3(0.);
vec3 force;
float rr;
int testEdgeTileN = 0, offset = 0;
int testEdge;
float compatibilityWidth = float(width/nPoints*MaxNCompatibleEdges);
// assumed max number of compatibile edges is MaxNCompatibleEdges per edge
for (int e = 0; e < 500; e++) {
testEdge = int(texture2D(compatibility, vec2((float(e+tileNumber*MaxNCompatibleEdges)+0.5)/compatibilityWidth,r)).x);
if (testEdge < 0) {
break;
}
testEdgeTileN = testEdge/height; // tile number of the test edge
rr = (float(testEdge - testEdgeTileN*height)+0.5)/H; // target edge in texture coordinate = row
force = texture2D(edges, vec2( (float(c+testEdgeTileN*nPoints)+0.5)/W, rr)).xyz - crnt;
if (abs(force.x) > eps || abs(force.y) > eps || abs(force.z) > eps) {
forces += normalize(force);
}
}
return forces;
}
void main() {
W = float(width);
H = float(height);
c = int(floor(vTextureCoord.s * W)); // column = point
tileNumber = c/nPoints; // 0, 1, 2 ...
cOffset = tileNumber*nPoints;
c -= cOffset; // remove the offset caused by tiling
r = vTextureCoord.t; // row
edge = tileNumber*height + int(floor(r*H)); // which edge
crnt = texture2D(edges, vTextureCoord).xyz;
vec3 outP = crnt; // output point
bool isInScope = (edge < nEdges);
bool isEndPoint = (c == 0) || (c == P+1);
if (!isEndPoint && isInScope) {
c0 = (float(cOffset)+0.5)/W;
cEnd = (float(P+1+cOffset)+0.5)/W;
// the end points
P1 = texture2D(edges, vec2(c0, r)).xyz;
P2 = texture2D(edges, vec2(cEnd, r)).xyz;
edgeLength = distance(P1, P2);
vec3 springForce = applySpringForce();
vec3 electrostaticForce = applyElectrostaticForce();
outP += S*(springForce + electrostaticForce);
}
gl_FragColor = vec4(outP, 1.);
}