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