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