Fix T71621: VSE crashes when playing last frame of audio
[blender.git] / source / blender / gpu / shaders / gpu_shader_gpencil_stroke_geom.glsl
1 uniform mat4 ModelViewProjectionMatrix;
2 uniform vec2 Viewport;
3 uniform int xraymode;
4 uniform int caps_start;
5 uniform int caps_end;
6 uniform int fill_stroke;
7
8 layout(lines_adjacency) in;
9 layout(triangle_strip, max_vertices = 13) out;
10
11 in vec4 finalColor[4];
12 in float finalThickness[4];
13
14 out vec4 mColor;
15 out vec2 mTexCoord;
16
17 #define GP_XRAY_FRONT 0
18 #define GP_XRAY_3DSPACE 1
19 #define GP_XRAY_BACK 2
20
21 #define GPENCIL_FLATCAP 1
22
23 /* project 3d point to 2d on screen space */
24 vec2 toScreenSpace(vec4 vertex)
25 {
26   return vec2(vertex.xy / vertex.w) * Viewport;
27 }
28
29 /* get zdepth value */
30 float getZdepth(vec4 point)
31 {
32   if (xraymode == GP_XRAY_FRONT) {
33     return 0.0;
34   }
35   if (xraymode == GP_XRAY_3DSPACE) {
36     return (point.z / point.w);
37   }
38   if (xraymode == GP_XRAY_BACK) {
39     return 1.0;
40   }
41
42   /* in front by default */
43   return 0.0;
44 }
45
46 /* check equality but with a small tolerance */
47 bool is_equal(vec4 p1, vec4 p2)
48 {
49   float limit = 0.0001;
50   float x = abs(p1.x - p2.x);
51   float y = abs(p1.y - p2.y);
52   float z = abs(p1.z - p2.z);
53
54   if ((x < limit) && (y < limit) && (z < limit)) {
55     return true;
56   }
57
58   return false;
59 }
60
61 void main(void)
62 {
63   float MiterLimit = 0.75;
64
65   /* receive 4 points */
66   vec4 P0 = gl_in[0].gl_Position;
67   vec4 P1 = gl_in[1].gl_Position;
68   vec4 P2 = gl_in[2].gl_Position;
69   vec4 P3 = gl_in[3].gl_Position;
70
71   /* get the four vertices passed to the shader */
72   vec2 sp0 = toScreenSpace(P0);  // start of previous segment
73   vec2 sp1 = toScreenSpace(P1);  // end of previous segment, start of current segment
74   vec2 sp2 = toScreenSpace(P2);  // end of current segment, start of next segment
75   vec2 sp3 = toScreenSpace(P3);  // end of next segment
76
77   /* culling outside viewport */
78   vec2 area = Viewport * 4.0;
79   if (sp1.x < -area.x || sp1.x > area.x) {
80     return;
81   }
82   if (sp1.y < -area.y || sp1.y > area.y) {
83     return;
84   }
85   if (sp2.x < -area.x || sp2.x > area.x) {
86     return;
87   }
88   if (sp2.y < -area.y || sp2.y > area.y) {
89     return;
90   }
91
92   /* determine the direction of each of the 3 segments (previous, current, next) */
93   vec2 v0 = normalize(sp1 - sp0);
94   vec2 v1 = normalize(sp2 - sp1);
95   vec2 v2 = normalize(sp3 - sp2);
96
97   /* determine the normal of each of the 3 segments (previous, current, next) */
98   vec2 n0 = vec2(-v0.y, v0.x);
99   vec2 n1 = vec2(-v1.y, v1.x);
100   vec2 n2 = vec2(-v2.y, v2.x);
101
102   /* determine miter lines by averaging the normals of the 2 segments */
103   vec2 miter_a = normalize(n0 + n1);  // miter at start of current segment
104   vec2 miter_b = normalize(n1 + n2);  // miter at end of current segment
105
106   /* determine the length of the miter by projecting it onto normal and then inverse it */
107   float an1 = dot(miter_a, n1);
108   float bn1 = dot(miter_b, n2);
109   if (an1 == 0) {
110     an1 = 1;
111   }
112   if (bn1 == 0) {
113     bn1 = 1;
114   }
115   float length_a = finalThickness[1] / an1;
116   float length_b = finalThickness[2] / bn1;
117   if (length_a <= 0.0) {
118     length_a = 0.01;
119   }
120   if (length_b <= 0.0) {
121     length_b = 0.01;
122   }
123
124   /* prevent excessively long miters at sharp corners */
125   if (dot(v0, v1) < -MiterLimit) {
126     miter_a = n1;
127     length_a = finalThickness[1];
128
129     /* close the gap */
130     if (dot(v0, n1) > 0) {
131       mTexCoord = vec2(0, 0);
132       mColor = finalColor[1];
133       gl_Position = vec4((sp1 + finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0);
134       EmitVertex();
135
136       mTexCoord = vec2(0, 0);
137       mColor = finalColor[1];
138       gl_Position = vec4((sp1 + finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0);
139       EmitVertex();
140
141       mTexCoord = vec2(0, 0.5);
142       mColor = finalColor[1];
143       gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0);
144       EmitVertex();
145
146       EndPrimitive();
147     }
148     else {
149       mTexCoord = vec2(0, 1);
150       mColor = finalColor[1];
151       gl_Position = vec4((sp1 - finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0);
152       EmitVertex();
153
154       mTexCoord = vec2(0, 1);
155       mColor = finalColor[1];
156       gl_Position = vec4((sp1 - finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0);
157       EmitVertex();
158
159       mTexCoord = vec2(0, 0.5);
160       mColor = finalColor[1];
161       gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0);
162       EmitVertex();
163
164       EndPrimitive();
165     }
166   }
167
168   if (dot(v1, v2) < -MiterLimit) {
169     miter_b = n1;
170     length_b = finalThickness[2];
171   }
172
173   /* generate the start endcap (alpha < 0 used as endcap flag)*/
174   float extend = (fill_stroke > 0) ? 2 : 1;
175   if ((caps_start != GPENCIL_FLATCAP) && is_equal(P0, P2)) {
176     mTexCoord = vec2(1, 0.5);
177     mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0);
178     vec2 svn1 = normalize(sp1 - sp2) * length_a * 4.0 * extend;
179     gl_Position = vec4((sp1 + svn1) / Viewport, getZdepth(P1), 1.0);
180     EmitVertex();
181
182     mTexCoord = vec2(0, 0);
183     mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0);
184     gl_Position = vec4((sp1 - (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0);
185     EmitVertex();
186
187     mTexCoord = vec2(0, 1);
188     mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0);
189     gl_Position = vec4((sp1 + (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0);
190     EmitVertex();
191   }
192
193   /* generate the triangle strip */
194   mTexCoord = vec2(0, 0);
195   mColor = finalColor[1];
196   gl_Position = vec4((sp1 + length_a * miter_a) / Viewport, getZdepth(P1), 1.0);
197   EmitVertex();
198
199   mTexCoord = vec2(0, 1);
200   mColor = finalColor[1];
201   gl_Position = vec4((sp1 - length_a * miter_a) / Viewport, getZdepth(P1), 1.0);
202   EmitVertex();
203
204   mTexCoord = vec2(0, 0);
205   mColor = finalColor[2];
206   gl_Position = vec4((sp2 + length_b * miter_b) / Viewport, getZdepth(P2), 1.0);
207   EmitVertex();
208
209   mTexCoord = vec2(0, 1);
210   mColor = finalColor[2];
211   gl_Position = vec4((sp2 - length_b * miter_b) / Viewport, getZdepth(P2), 1.0);
212   EmitVertex();
213
214   /* generate the end endcap (alpha < 0 used as endcap flag)*/
215   if ((caps_end != GPENCIL_FLATCAP) && is_equal(P1, P3)) {
216     mTexCoord = vec2(0, 1);
217     mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0);
218     gl_Position = vec4((sp2 + (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0);
219     EmitVertex();
220
221     mTexCoord = vec2(0, 0);
222     mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0);
223     gl_Position = vec4((sp2 - (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0);
224     EmitVertex();
225
226     mTexCoord = vec2(1, 0.5);
227     mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0);
228     vec2 svn2 = normalize(sp2 - sp1) * length_b * 4.0 * extend;
229     gl_Position = vec4((sp2 + svn2) / Viewport, getZdepth(P2), 1.0);
230     EmitVertex();
231   }
232
233   EndPrimitive();
234 }