lines3D.glsl
3.5 KB
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
@export ecgl.lines3D.vertex
uniform mat4 worldViewProjection : WORLDVIEWPROJECTION;
attribute vec3 position: POSITION;
attribute vec4 a_Color : COLOR;
varying vec4 v_Color;
void main()
{
gl_Position = worldViewProjection * vec4(position, 1.0);
v_Color = a_Color;
}
@end
@export ecgl.lines3D.fragment
uniform vec4 color : [1.0, 1.0, 1.0, 1.0];
varying vec4 v_Color;
@import clay.util.srgb
void main()
{
#ifdef SRGB_DECODE
gl_FragColor = sRGBToLinear(color * v_Color);
#else
gl_FragColor = color * v_Color;
#endif
}
@end
@export ecgl.lines3D.clipNear
vec4 clipNear(vec4 p1, vec4 p2) {
float n = (p1.w - near) / (p1.w - p2.w);
// PENDING
return vec4(mix(p1.xy, p2.xy, n), -near, near);
}
@end
@export ecgl.lines3D.expandLine
#ifdef VERTEX_ANIMATION
vec4 prevProj = worldViewProjection * vec4(mix(prevPositionPrev, positionPrev, percent), 1.0);
vec4 currProj = worldViewProjection * vec4(mix(prevPosition, position, percent), 1.0);
vec4 nextProj = worldViewProjection * vec4(mix(prevPositionNext, positionNext, percent), 1.0);
#else
vec4 prevProj = worldViewProjection * vec4(positionPrev, 1.0);
vec4 currProj = worldViewProjection * vec4(position, 1.0);
vec4 nextProj = worldViewProjection * vec4(positionNext, 1.0);
#endif
if (currProj.w < 0.0) {
if (nextProj.w > 0.0) {
currProj = clipNear(currProj, nextProj);
}
else if (prevProj.w > 0.0) {
currProj = clipNear(currProj, prevProj);
}
}
vec2 prevScreen = (prevProj.xy / abs(prevProj.w) + 1.0) * 0.5 * viewport.zw;
vec2 currScreen = (currProj.xy / abs(currProj.w) + 1.0) * 0.5 * viewport.zw;
vec2 nextScreen = (nextProj.xy / abs(nextProj.w) + 1.0) * 0.5 * viewport.zw;
vec2 dir;
float len = offset;
// Start point
if (position == positionPrev) {
dir = normalize(nextScreen - currScreen);
}
// End point
else if (position == positionNext) {
dir = normalize(currScreen - prevScreen);
}
else {
vec2 dirA = normalize(currScreen - prevScreen);
vec2 dirB = normalize(nextScreen - currScreen);
vec2 tanget = normalize(dirA + dirB);
// TODO, simple miterLimit
float miter = 1.0 / max(dot(tanget, dirA), 0.5);
len *= miter;
dir = tanget;
}
dir = vec2(-dir.y, dir.x) * len;
currScreen += dir;
currProj.xy = (currScreen / viewport.zw - 0.5) * 2.0 * abs(currProj.w);
@end
@export ecgl.meshLines3D.vertex
// https://mattdesl.svbtle.com/drawing-lines-is-hard
attribute vec3 position: POSITION;
attribute vec3 positionPrev;
attribute vec3 positionNext;
attribute float offset;
attribute vec4 a_Color : COLOR;
#ifdef VERTEX_ANIMATION
attribute vec3 prevPosition;
attribute vec3 prevPositionPrev;
attribute vec3 prevPositionNext;
uniform float percent : 1.0;
#endif
uniform mat4 worldViewProjection : WORLDVIEWPROJECTION;
uniform vec4 viewport : VIEWPORT;
uniform float near : NEAR;
varying vec4 v_Color;
@import ecgl.common.wireframe.vertexHeader
@import ecgl.lines3D.clipNear
void main()
{
@import ecgl.lines3D.expandLine
gl_Position = currProj;
v_Color = a_Color;
@import ecgl.common.wireframe.vertexMain
}
@end
@export ecgl.meshLines3D.fragment
uniform vec4 color : [1.0, 1.0, 1.0, 1.0];
varying vec4 v_Color;
@import ecgl.common.wireframe.fragmentHeader
@import clay.util.srgb
void main()
{
#ifdef SRGB_DECODE
gl_FragColor = sRGBToLinear(color * v_Color);
#else
gl_FragColor = color * v_Color;
#endif
@import ecgl.common.wireframe.fragmentMain
}
@end