Fix T56692: The edges are not highlighted in Mark Freestyle Edge
[blender.git] / source / blender / draw / modes / shaders / edit_mesh_overlay_geom_tri.glsl
1
2 /* Solid Wirefram implementation
3  * Mike Erwin, ClĂ©ment Foucault */
4
5 /* This shader follows the principles of
6  * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
7
8 layout(triangles) in;
9
10 /* This is not perfect. Only a subset of intel gpus are affected.
11  * This fix have some performance impact.
12  * TODO Refine the range to only affect GPUs. */
13
14 #ifdef EDGE_FIX
15 /* To fix the edge artifacts, we render
16  * an outline strip around the screenspace
17  * triangle. Order is important.
18  * TODO diagram
19  */
20
21 #ifdef VERTEX_SELECTION
22 layout(triangle_strip, max_vertices=23) out;
23 #else
24 layout(triangle_strip, max_vertices=17) out;
25 #endif
26 #else
27 layout(triangle_strip, max_vertices=3) out;
28 #endif
29
30 uniform mat4 ProjectionMatrix;
31 uniform vec2 viewportSize;
32
33 in vec4 vPos[];
34 in vec4 pPos[];
35 in ivec4 vData[];
36 #ifdef VERTEX_FACING
37 in float vFacing[];
38 #endif
39
40 /* these are the same for all vertices
41  * and does not need interpolation */
42 flat out vec3 edgesCrease;
43 flat out vec3 edgesBweight;
44 flat out vec4 faceColor;
45 flat out ivec3 flag;
46 flat out int clipCase;
47 #ifdef VERTEX_SELECTION
48 out vec3 vertexColor;
49 #endif
50 #ifdef VERTEX_FACING
51 out float facing;
52 #endif
53
54 /* See fragment shader */
55 flat out vec2 ssPos[3];
56
57 #define FACE_ACTIVE     (1 << 2)
58 #define FACE_SELECTED   (1 << 3)
59 #define FACE_FREESTYLE  (1 << 4)
60
61 /* project to screen space */
62 vec2 proj(vec4 pos)
63 {
64         return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
65 }
66
67 void doVertex(int v)
68 {
69 #ifdef VERTEX_SELECTION
70         vertexColor = EDIT_MESH_vertex_color(vData[v].x).rgb;
71 #endif
72
73 #ifdef VERTEX_FACING
74         facing = vFacing[v];
75 #endif
76
77         gl_Position = pPos[v];
78
79         EmitVertex();
80 }
81
82 void doLoopStrip(int v, vec3 offset)
83 {
84         doVertex(v);
85
86         gl_Position.xyz += offset;
87
88         EmitVertex();
89 }
90
91 #ifdef ANTI_ALIASING
92 #define Z_OFFSET 0.008
93 #else
94 #define Z_OFFSET 0.0
95 #endif
96
97 void main()
98 {
99         /* Edge */
100         ivec3 eflag;
101         for (int v = 0; v < 3; ++v) {
102                 flag[v] = eflag[v] = vData[v].y | (vData[v].x << 8);
103                 edgesCrease[v] = vData[v].z / 255.0;
104                 edgesBweight[v] = vData[v].w / 255.0;
105         }
106
107         /* Face */
108         if ((vData[0].x & FACE_ACTIVE) != 0)
109                 faceColor = colorFaceSelect;
110         else if ((vData[0].x & FACE_SELECTED) != 0)
111                 faceColor = colorFaceSelect;
112         else if ((vData[0].x & FACE_FREESTYLE) != 0)
113                 faceColor = colorFaceFreestyle;
114         else
115                 faceColor = colorFace;
116
117         /* Vertex */
118         ssPos[0] = proj(pPos[0]);
119         ssPos[1] = proj(pPos[1]);
120         ssPos[2] = proj(pPos[2]);
121
122         doVertex(0);
123         doVertex(1);
124         doVertex(2);
125
126 #ifdef EDGE_FIX
127         vec2 fixvec[6];
128         vec2 fixvecaf[6];
129         vec2 cornervec[3];
130
131         /* This fix the case when 2 vertices are perfectly aligned
132          * and corner vectors have nowhere to go.
133          * ie: length(cornervec[i]) == 0 */
134         const float epsilon = 1e-2; /* in pixel so not that much */
135         const vec2 bias[3] = vec2[3](
136                 vec2( epsilon,  epsilon),
137                 vec2(-epsilon,  epsilon),
138                 vec2(     0.0, -epsilon)
139         );
140
141         for (int i = 0; i < 3; ++i) {
142                 int i1 = (i + 1) % 3;
143                 int i2 = (i + 2) % 3;
144
145                 vec2 v1 = ssPos[i] + bias[i];
146                 vec2 v2 = ssPos[i1] + bias[i1];
147                 vec2 v3 = ssPos[i2] + bias[i2];
148
149                 /* Edge normalized vector */
150                 vec2 dir = normalize(v2 - v1);
151                 vec2 dir2 = normalize(v3 - v1);
152
153                 cornervec[i] = -normalize(dir + dir2);
154
155                 /* perpendicular to dir */
156                 vec2 perp = vec2(-dir.y, dir.x);
157
158                 /* Backface case */
159                 if (dot(perp, dir2) > 0) {
160                         perp = -perp;
161                 }
162
163                 /* Make it view independent */
164                 perp *= sizeEdgeFix / viewportSize;
165                 cornervec[i] *= sizeEdgeFix / viewportSize;
166                 fixvec[i] = fixvecaf[i] = perp;
167
168                 /* Perspective */
169                 if (ProjectionMatrix[3][3] == 0.0) {
170                         /* vPos[i].z is negative and we don't want
171                          * our fixvec to be flipped */
172                         fixvec[i] *= -vPos[i].z;
173                         fixvecaf[i] *= -vPos[i1].z;
174                         cornervec[i] *= -vPos[i].z;
175                 }
176         }
177
178         /* to not let face color bleed */
179         faceColor.a = 0.0;
180
181         /* Start with the same last vertex to create a
182          * degenerate triangle in order to "create"
183          * a new triangle strip */
184         for (int i = 2; i < 5; ++i) {
185                 int vbe = (i - 1) % 3;
186                 int vaf = (i + 1) % 3;
187                 int v = i % 3;
188
189                 doLoopStrip(v, vec3(fixvec[v], Z_OFFSET));
190
191                 /* Only shade the edge that we are currently drawing.
192                  * (fix corner bleeding) */
193                 flag[vbe] |= (EDGE_EXISTS & eflag[vbe]);
194                 flag[vaf] &= ~EDGE_EXISTS;
195                 flag[v]   &= ~EDGE_EXISTS;
196                 doLoopStrip(vaf, vec3(fixvecaf[v], Z_OFFSET));
197
198                 /* corner vertices should not draw edges but draw point only */
199                 flag[vbe] &= ~EDGE_EXISTS;
200 #ifdef VERTEX_SELECTION
201                 doLoopStrip(vaf, vec3(cornervec[vaf], Z_OFFSET));
202 #endif
203         }
204
205         /* finish the loop strip */
206         doLoopStrip(2, vec3(fixvec[2], Z_OFFSET));
207 #endif
208
209         EndPrimitive();
210 }