Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/modes/shaders')
-rw-r--r--source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl38
-rw-r--r--source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl91
-rw-r--r--source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl47
-rw-r--r--source/blender/draw/modes/shaders/armature_axes_vert.glsl30
-rw-r--r--source/blender/draw/modes/shaders/armature_dof_vert.glsl30
-rw-r--r--source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl15
-rw-r--r--source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl156
-rw-r--r--source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl18
-rw-r--r--source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl55
-rw-r--r--source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl101
-rw-r--r--source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl47
-rw-r--r--source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl11
-rw-r--r--source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl36
-rw-r--r--source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl102
-rw-r--r--source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl81
-rw-r--r--source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl82
-rw-r--r--source/blender/draw/modes/shaders/armature_stick_frag.glsl13
-rw-r--r--source/blender/draw/modes/shaders/armature_stick_vert.glsl88
-rw-r--r--source/blender/draw/modes/shaders/common_fullscreen_vert.glsl10
-rw-r--r--source/blender/draw/modes/shaders/common_fxaa_lib.glsl677
-rw-r--r--source/blender/draw/modes/shaders/common_globals_lib.glsl80
-rw-r--r--source/blender/draw/modes/shaders/common_hair_lib.glsl199
-rw-r--r--source/blender/draw/modes/shaders/common_hair_refine_vert.glsl55
-rw-r--r--source/blender/draw/modes/shaders/common_view_lib.glsl14
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl96
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl15
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl31
-rw-r--r--source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl22
-rw-r--r--source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl39
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl53
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl19
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl31
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl7
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl28
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl152
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl119
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl211
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl7
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl22
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl49
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl102
-rw-r--r--source/blender/draw/modes/shaders/edit_normals_geom.glsl15
-rw-r--r--source/blender/draw/modes/shaders/edit_normals_vert.glsl30
-rw-r--r--source/blender/draw/modes/shaders/object_empty_axes_vert.glsl29
-rw-r--r--source/blender/draw/modes/shaders/object_empty_image_frag.glsl33
-rw-r--r--source/blender/draw/modes/shaders/object_empty_image_vert.glsl32
-rw-r--r--source/blender/draw/modes/shaders/object_grid_frag.glsl246
-rw-r--r--source/blender/draw/modes/shaders/object_grid_vert.glsl63
-rw-r--r--source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl34
-rw-r--r--source/blender/draw/modes/shaders/object_mball_handles_vert.glsl34
-rw-r--r--source/blender/draw/modes/shaders/object_outline_detect_frag.glsl88
-rw-r--r--source/blender/draw/modes/shaders/object_outline_expand_frag.glsl37
-rw-r--r--source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl10
-rw-r--r--source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl40
-rw-r--r--source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl16
-rw-r--r--source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl27
-rw-r--r--source/blender/draw/modes/shaders/object_particle_dot_frag.glsl52
-rw-r--r--source/blender/draw/modes/shaders/object_particle_dot_vert.glsl35
-rw-r--r--source/blender/draw/modes/shaders/object_particle_prim_vert.glsl56
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl10
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl7
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl57
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl127
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl177
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_frag.glsl11
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_vert.glsl15
-rw-r--r--source/blender/draw/modes/shaders/paint_vert_frag.glsl26
-rw-r--r--source/blender/draw/modes/shaders/paint_vertex_frag.glsl18
-rw-r--r--source/blender/draw/modes/shaders/paint_vertex_vert.glsl21
-rw-r--r--source/blender/draw/modes/shaders/paint_weight_frag.glsl97
-rw-r--r--source/blender/draw/modes/shaders/paint_weight_vert.glsl15
-rw-r--r--source/blender/draw/modes/shaders/paint_wire_frag.glsl25
-rw-r--r--source/blender/draw/modes/shaders/paint_wire_vert.glsl14
-rw-r--r--source/blender/draw/modes/shaders/particle_strand_frag.glsl23
-rw-r--r--source/blender/draw/modes/shaders/particle_strand_vert.glsl73
-rw-r--r--source/blender/draw/modes/shaders/sculpt_mask_vert.glsl19
-rw-r--r--source/blender/draw/modes/shaders/volume_velocity_vert.glsl115
77 files changed, 4806 insertions, 0 deletions
diff --git a/source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl b/source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl
new file mode 100644
index 00000000000..d9d59880e99
--- /dev/null
+++ b/source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl
@@ -0,0 +1,38 @@
+
+layout(lines) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+uniform int lineThickness = 2;
+
+in vec4 finalColor_geom[];
+in vec2 ssPos[];
+
+out vec4 finalColor;
+
+vec2 compute_dir(vec2 v0, vec2 v1)
+{
+ vec2 dir = normalize(v1 - v0 + 1e-8);
+ dir = vec2(-dir.y, dir.x);
+ return dir;
+}
+
+void main(void)
+{
+ vec2 t;
+ vec2 edge_dir = compute_dir(ssPos[0], ssPos[1]) / viewportSize;
+
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+
+ finalColor = finalColor_geom[0];
+ t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[0].gl_Position.w : 1.0));
+ gl_Position = gl_in[0].gl_Position + vec4(t, 0.0, 0.0); EmitVertex();
+ gl_Position = gl_in[0].gl_Position - vec4(t, 0.0, 0.0); EmitVertex();
+
+ finalColor = finalColor_geom[1];
+ t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[1].gl_Position.w : 1.0));
+ gl_Position = gl_in[1].gl_Position + vec4(t, 0.0, 0.0); EmitVertex();
+ gl_Position = gl_in[1].gl_Position - vec4(t, 0.0, 0.0); EmitVertex();
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl b/source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl
new file mode 100644
index 00000000000..276f4004fb6
--- /dev/null
+++ b/source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl
@@ -0,0 +1,91 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ViewProjectionMatrix;
+uniform vec2 viewportSize;
+
+uniform int frameCurrent;
+uniform int frameStart;
+uniform int frameEnd;
+uniform int cacheStart;
+uniform bool selected;
+uniform bool useCustomColor;
+uniform vec3 customColor;
+
+in vec3 pos;
+
+out vec2 ssPos;
+out vec4 finalColor_geom;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+#define SET_INTENSITY(A, B, C, min, max) (((1.0 - (float(C - B) / float(C - A))) * (max - min)) + min)
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * vec4(pos, 1.0);
+
+ ssPos = proj(gl_Position);
+
+ int frame = gl_VertexID + cacheStart;
+
+ float intensity; /* how faint */
+
+ vec3 blend_base = (abs(frame - frameCurrent) == 1) ? colorCurrentFrame.rgb : colorBackground.rgb; /* "bleed" cframe color to ease color blending */
+
+ /* TODO: We might want something more consistent with custom color and standard colors. */
+ if (frame < frameCurrent) {
+ if (useCustomColor) {
+ /* Custom color: previous frames color is darker than current frame */
+ finalColor_geom.rgb = customColor * 0.25;
+ }
+ else {
+ /* black - before frameCurrent */
+ if (selected) {
+ intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.25, 0.75);
+ }
+ else {
+ intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.68, 0.92);
+ }
+ finalColor_geom.rgb = mix(colorWire.rgb, blend_base, intensity);
+ }
+ }
+ else if (frame > frameCurrent) {
+ if (useCustomColor) {
+ /* Custom color: next frames color is equal to user selected color */
+ finalColor_geom.rgb = customColor;
+ }
+ else {
+ /* blue - after frameCurrent */
+ if (selected) {
+ intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.25, 0.75);
+ }
+ else {
+ intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.68, 0.92);
+ }
+
+ finalColor_geom.rgb = mix(colorBonePose.rgb, blend_base, intensity);
+ }
+ }
+ else {
+ if (useCustomColor) {
+ /* Custom color: current frame color is slightly darker than user selected color */
+ finalColor_geom.rgb = customColor * 0.5;
+ }
+ else {
+ /* green - on frameCurrent */
+ if (selected) {
+ intensity = 0.5f;
+ }
+ else {
+ intensity = 0.99f;
+ }
+ finalColor_geom.rgb = clamp(mix(colorCurrentFrame.rgb, colorBackground.rgb, intensity) - 0.1, 0.0, 0.1);
+ }
+ }
+
+ finalColor_geom.a = 1.0;
+}
diff --git a/source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl b/source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl
new file mode 100644
index 00000000000..3b2f170ca22
--- /dev/null
+++ b/source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl
@@ -0,0 +1,47 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+uniform int pointSize = 2;
+uniform int frameCurrent;
+uniform int cacheStart;
+uniform bool showKeyFrames = true;
+uniform bool useCustomColor;
+uniform vec3 customColor;
+
+in vec3 pos;
+in int flag;
+
+#define MOTIONPATH_VERT_SEL (1 << 0)
+#define MOTIONPATH_VERT_KEY (1 << 1)
+
+out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = float(pointSize + 2);
+
+ int frame = gl_VertexID + cacheStart;
+ finalColor = (useCustomColor) ? vec4(customColor, 1.0) : vec4(1.0);
+
+ /* Bias to reduce z fighting with the path */
+ gl_Position.z -= 1e-4;
+
+ if (showKeyFrames) {
+ if ((flag & MOTIONPATH_VERT_KEY) != 0) {
+ gl_PointSize = float(pointSize + 5);
+ finalColor = colorVertexSelect;
+ /* Bias more to get these on top of regular points */
+ gl_Position.z -= 1e-4;
+ }
+ /* Draw big green dot where the current frame is.
+ * NOTE: this is only done when keyframes are shown, since this adds similar types of clutter
+ */
+ if (frame == frameCurrent) {
+ gl_PointSize = float(pointSize + 8);
+ finalColor = colorCurrentFrame;
+ /* Bias more to get these on top of keyframes */
+ gl_Position.z -= 1e-4;
+ }
+ }
+}
diff --git a/source/blender/draw/modes/shaders/armature_axes_vert.glsl b/source/blender/draw/modes/shaders/armature_axes_vert.glsl
new file mode 100644
index 00000000000..53b2a3d3b3b
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_axes_vert.glsl
@@ -0,0 +1,30 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screenVecs[3];
+
+/* ---- Instantiated Attribs ---- */
+in float axis; /* position on the axis. [0.0-1.0] is X axis, [1.0-2.0] is Y, etc... */
+in vec2 screenPos;
+in vec3 colorAxis;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 color;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ vec3 chosen_axis = InstanceModelMatrix[int(axis)].xyz;
+ vec3 y_axis = InstanceModelMatrix[1].xyz;
+ vec3 bone_loc = InstanceModelMatrix[3].xyz;
+ vec3 wpos = bone_loc + y_axis + chosen_axis * fract(axis);
+ vec3 spos = screenVecs[0].xyz * screenPos.x + screenVecs[1].xyz * screenPos.y;
+ /* Scale uniformly by axis length */
+ spos *= length(chosen_axis);
+
+ gl_Position = ViewProjectionMatrix * vec4(wpos + spos, 1.0);
+
+ finalColor.rgb = mix(colorAxis, color.rgb, color.a);
+ finalColor.a = 1.0;
+}
diff --git a/source/blender/draw/modes/shaders/armature_dof_vert.glsl b/source/blender/draw/modes/shaders/armature_dof_vert.glsl
new file mode 100644
index 00000000000..5c89cf644d6
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_dof_vert.glsl
@@ -0,0 +1,30 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instantiated Attribs ---- */
+in vec2 pos;
+
+/* ---- Per instance Attribs ---- */
+/* Assumed to be in world coordinate already. */
+in mat4 InstanceModelMatrix;
+in vec4 color;
+in vec2 amin;
+in vec2 amax;
+
+flat out vec4 finalColor;
+
+vec3 sphere_project(float ax, float az)
+{
+ float sine = 1.0 - ax * ax - az * az;
+ float q3 = sqrt(max(0.0, sine));
+
+ return vec3(-az * q3, 0.5 - sine, ax * q3) * 2.0;
+}
+
+void main()
+{
+ vec3 final_pos = sphere_project(pos.x * abs((pos.x > 0.0) ? amax.x : amin.x),
+ pos.y * abs((pos.y > 0.0) ? amax.y : amin.y));
+ gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(final_pos, 1.0));
+ finalColor = color;
+}
diff --git a/source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl b/source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl
new file mode 100644
index 00000000000..cecc5447c7c
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl
@@ -0,0 +1,15 @@
+
+flat in vec3 finalStateColor; /* UNUSED */
+flat in vec3 finalBoneColor; /* UNUSED */
+in vec3 normalView;
+
+out vec4 fragColor;
+
+uniform vec4 color = vec4(1.0, 1.0, 1.0, 0.2);
+
+void main()
+{
+ float n = normalize(normalView).z;
+ n = 1.0 - clamp(-n, 0.0, 1.0);
+ fragColor = color * n;
+}
diff --git a/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl
new file mode 100644
index 00000000000..307c7276184
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl
@@ -0,0 +1,156 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ViewMatrixInverse;
+uniform mat4 ViewProjectionMatrix;
+uniform mat4 ProjectionMatrix;
+
+uniform vec2 viewportSize;
+uniform float lineThickness = 2.0;
+
+/* ---- Instantiated Attribs ---- */
+in vec2 pos0;
+in vec2 pos1;
+in vec2 pos2;
+
+/* ---- Per instance Attribs ---- */
+/* Assumed to be in world coordinate already. */
+in vec4 headSphere;
+in vec4 tailSphere;
+in vec4 outlineColorSize;
+in vec3 xAxis;
+
+flat out vec4 finalColor;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+vec2 compute_dir(vec2 v0, vec2 v1, vec2 v2)
+{
+ vec2 dir = normalize(v2 - v0);
+ dir = vec2(dir.y, -dir.x);
+ return dir;
+}
+
+mat3 compute_mat(vec4 sphere, vec3 bone_vec, out float z_ofs)
+{
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+ vec3 cam_ray = (is_persp) ? sphere.xyz - ViewMatrixInverse[3].xyz
+ : -ViewMatrixInverse[2].xyz;
+
+ /* Sphere center distance from the camera (persp) in world space. */
+ float cam_dist = length(cam_ray);
+
+ /* Compute view aligned orthonormal space. */
+ vec3 z_axis = cam_ray / cam_dist;
+ vec3 x_axis = normalize(cross(bone_vec, z_axis));
+ vec3 y_axis = cross(z_axis, x_axis);
+ z_ofs = 0.0;
+
+ if (is_persp) {
+ /* For perspective, the projected sphere radius
+ * can be bigger than the center disc. Compute the
+ * max angular size and compensate by sliding the disc
+ * towards the camera and scale it accordingly. */
+ const float half_pi = 3.1415926 * 0.5;
+ float rad = sphere.w;
+ /* Let be :
+ * V the view vector origin.
+ * O the sphere origin.
+ * T the point on the target circle.
+ * We compute the angle between (OV) and (OT). */
+ float a = half_pi - asin(rad / cam_dist);
+ float cos_b = cos(a);
+ float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0));
+
+ x_axis *= sin_b;
+ y_axis *= sin_b;
+ z_ofs = -rad * cos_b;
+ }
+
+ return mat3(x_axis, y_axis, z_axis);
+}
+
+struct Bone { vec3 vec; float sinb; };
+
+bool bone_blend_starts(vec3 p, Bone b)
+{
+ /* we just want to know when the head sphere starts interpolating. */
+ return dot(p, b.vec) > -b.sinb;
+}
+
+vec3 get_outline_point(
+ vec2 pos, vec4 sph_near, vec4 sph_far,
+ mat3 mat_near, mat3 mat_far, float z_ofs_near, float z_ofs_far, Bone b)
+{
+ /* Compute outline position on the nearest sphere and check
+ * if it penetrates the capsule body. If it does, put this
+ * vertex on the farthest sphere. */
+ vec3 wpos = mat_near * vec3(pos * sph_near.w, z_ofs_near);
+ if (bone_blend_starts(wpos, b)) {
+ wpos = sph_far.xyz + mat_far * vec3(pos * sph_far.w, z_ofs_far);
+ }
+ else {
+ wpos += sph_near.xyz;
+ }
+ return wpos;
+}
+
+void main()
+{
+ float dst_head = distance(headSphere.xyz, ViewMatrixInverse[3].xyz);
+ float dst_tail = distance(tailSphere.xyz, ViewMatrixInverse[3].xyz);
+ // float dst_head = -dot(headSphere.xyz, ViewMatrix[2].xyz);
+ // float dst_tail = -dot(tailSphere.xyz, ViewMatrix[2].xyz);
+
+ vec4 sph_near, sph_far;
+ if ((dst_head > dst_tail) && (ProjectionMatrix[3][3] == 0.0)) {
+ sph_near = tailSphere;
+ sph_far = headSphere;
+ }
+ else {
+ sph_near = headSphere;
+ sph_far = tailSphere;
+ }
+
+ vec3 bone_vec = (sph_far.xyz - sph_near.xyz) + 1e-8;
+
+ Bone b;
+ float bone_lenrcp = 1.0 / max(1e-8, sqrt(dot(bone_vec, bone_vec)));
+ b.sinb = (sph_far.w - sph_near.w) * bone_lenrcp * sph_near.w;
+ b.vec = bone_vec * bone_lenrcp;
+
+ float z_ofs_near, z_ofs_far;
+ mat3 mat_near = compute_mat(sph_near, bone_vec, z_ofs_near);
+ mat3 mat_far = compute_mat(sph_far, bone_vec, z_ofs_far);
+
+ vec3 wpos0 = get_outline_point(pos0, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b);
+ vec3 wpos1 = get_outline_point(pos1, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b);
+ vec3 wpos2 = get_outline_point(pos2, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b);
+
+ vec4 V = ViewMatrix * vec4(wpos1, 1.0);
+ float pres_fac = (ProjectionMatrix[3][3] == 0.0) ? abs(V.z) : 1.0;
+
+ vec4 p0 = ViewProjectionMatrix * vec4(wpos0, 1.0);
+ vec4 p1 = ProjectionMatrix * V;
+ vec4 p2 = ViewProjectionMatrix * vec4(wpos2, 1.0);
+
+ /* compute position from 3 vertex because the change in direction
+ * can happen very quicky and lead to very thin edges. */
+ vec2 ss0 = proj(p0);
+ vec2 ss1 = proj(p1);
+ vec2 ss2 = proj(p2);
+ vec2 edge_dir = compute_dir(ss0, ss1, ss2);
+
+ bool outer = ((gl_VertexID & 1) == 1);
+ vec2 t = outlineColorSize.w * (lineThickness / viewportSize);
+ t *= pres_fac;
+ t = (outer) ? t : vec2(0.0);
+
+ gl_Position = p1;
+ gl_Position.xy += t * edge_dir;
+
+ finalColor = vec4(outlineColorSize.rgb, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl
new file mode 100644
index 00000000000..78b29296601
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl
@@ -0,0 +1,18 @@
+
+uniform float alpha = 0.6;
+
+flat in vec3 finalStateColor;
+flat in vec3 finalBoneColor;
+in vec3 normalView;
+
+out vec4 fragColor;
+
+void main()
+{
+ /* Smooth lighting factor. */
+ const float s = 0.2; /* [0.0-0.5] range */
+ float n = normalize(normalView).z;
+ float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0);
+ fragColor.rgb = mix(finalStateColor, finalBoneColor, fac);
+ fragColor.a = alpha;
+}
diff --git a/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl
new file mode 100644
index 00000000000..11935e9001f
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl
@@ -0,0 +1,55 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ViewMatrixInverse;
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instantiated Attribs ---- */
+in vec3 pos;
+
+/* ---- Per instance Attribs ---- */
+/* Assumed to be in world coordinate already. */
+in vec4 headSphere;
+in vec4 tailSphere;
+in vec3 xAxis;
+in vec3 stateColor;
+in vec3 boneColor;
+
+flat out vec3 finalStateColor;
+flat out vec3 finalBoneColor;
+out vec3 normalView;
+
+void main()
+{
+ vec3 bone_vec = tailSphere.xyz - headSphere.xyz;
+ float bone_len = max(1e-8, sqrt(dot(bone_vec, bone_vec)));
+ float bone_lenrcp = 1.0 / bone_len;
+#ifdef SMOOTH_ENVELOPE
+ float sinb = (tailSphere.w - headSphere.w) * bone_lenrcp;
+#else
+ const float sinb = 0.0;
+#endif
+
+ vec3 y_axis = bone_vec * bone_lenrcp;
+ vec3 z_axis = normalize(cross(xAxis, -y_axis));
+ vec3 x_axis = cross(y_axis, z_axis); /* cannot trust xAxis to be orthogonal. */
+
+ vec3 sp, nor;
+ nor = sp = pos.xyz;
+
+ /* In bone space */
+ bool is_head = (pos.z < -sinb);
+ sp *= (is_head) ? headSphere.w : tailSphere.w;
+ sp.z += (is_head) ? 0.0 : bone_len;
+
+ /* Convert to world space */
+ mat3 bone_mat = mat3(x_axis, y_axis, z_axis);
+ sp = bone_mat * sp.xzy + headSphere.xyz;
+ nor = bone_mat * nor.xzy;
+
+ normalView = mat3(ViewMatrix) * nor;
+
+ gl_Position = ViewProjectionMatrix * vec4(sp, 1.0);
+
+ finalStateColor = stateColor;
+ finalBoneColor = boneColor;
+}
diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl
new file mode 100644
index 00000000000..bcfa097b277
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl
@@ -0,0 +1,101 @@
+
+layout(lines_adjacency) in;
+layout(triangle_strip, max_vertices = 6) out;
+
+in vec4 pPos[];
+in vec3 vPos[];
+in vec2 ssPos[];
+in vec2 ssNor[];
+in vec4 vColSize[];
+
+flat out vec4 finalColor;
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+uniform float lineThickness = 2.0;
+
+vec2 compute_dir(vec2 v0, vec2 v1)
+{
+ vec2 dir = normalize(v1 - v0);
+ dir = vec2(-dir.y, dir.x);
+ return dir;
+}
+
+void emit_edge(vec2 edge_dir, vec2 hidden_dir, vec2 thick, bool is_persp)
+{
+ float fac = dot(-hidden_dir, edge_dir);
+ edge_dir *= (fac < 0.0) ? -1.0 : 1.0;
+
+ vec2 t = thick * (is_persp ? abs(vPos[1].z) : 1.0);
+ gl_Position = pPos[1];
+ EmitVertex();
+ gl_Position.xy += t * edge_dir;
+ EmitVertex();
+
+ t = thick * (is_persp ? abs(vPos[2].z) : 1.0);
+ gl_Position = pPos[2];
+ EmitVertex();
+ gl_Position.xy += t * edge_dir;
+ EmitVertex();
+}
+
+void emit_corner(const int e, vec2 thick, bool is_persp)
+{
+ vec2 corner_dir = ssNor[e];
+ vec2 t = thick * (is_persp ? abs(vPos[e].z) : 1.0);
+
+ gl_Position = pPos[e] + vec4(t * corner_dir, 0.0, 0.0);
+ EmitVertex();
+}
+
+void main(void)
+{
+ finalColor = vec4(vColSize[0].rgb, 1.0);
+
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+
+ vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0);
+ vec3 v10 = vPos[0] - vPos[1];
+ vec3 v12 = vPos[2] - vPos[1];
+ vec3 v13 = vPos[3] - vPos[1];
+
+ vec3 n0 = cross(v12, v10);
+ vec3 n3 = cross(v13, v12);
+
+ float fac0 = dot(view_vec, n0);
+ float fac3 = dot(view_vec, n3);
+
+ /* If one of the face is perpendicular to the view,
+ * consider it and outline edge. */
+ if (abs(fac0) > 1e-5 && abs(fac3) > 1e-5) {
+ /* If both adjacent verts are facing the camera the same way,
+ * then it isn't an outline edge. */
+ if (sign(fac0) == sign(fac3))
+ return;
+ }
+
+ /* Don't outline if concave edge. */
+ if (dot(n0, v13) > 0.0001)
+ return;
+
+ vec2 thick = vColSize[0].w * (lineThickness / viewportSize);
+ vec2 edge_dir = compute_dir(ssPos[1], ssPos[2]);
+
+ vec2 hidden_point;
+ /* Take the farthest point to compute edge direction
+ * (avoid problems with point behind near plane).
+ * If the chosen point is parallel to the edge in screen space,
+ * choose the other point anyway.
+ * This fixes some issue with cubes in orthographic views.*/
+ if (vPos[0].z < vPos[3].z) {
+ hidden_point = (abs(fac0) > 1e-5) ? ssPos[0] : ssPos[3];
+ }
+ else {
+ hidden_point = (abs(fac3) > 1e-5) ? ssPos[3] : ssPos[0];
+ }
+ vec2 hidden_dir = normalize(hidden_point - ssPos[1]);
+
+ emit_corner(1, thick, is_persp);
+ emit_edge(edge_dir, hidden_dir, thick, is_persp);
+ emit_corner(2, thick, is_persp);
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl
new file mode 100644
index 00000000000..7619d8018f9
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl
@@ -0,0 +1,47 @@
+
+uniform mat3 NormalMatrix;
+
+uniform mat4 ViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+
+/* ---- Instantiated Attribs ---- */
+in vec3 pos;
+in vec3 snor;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 outlineColorSize;
+
+out vec4 pPos;
+out vec3 vPos;
+out vec2 ssPos;
+out vec2 ssNor;
+out vec4 vColSize;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+void main()
+{
+ /* This is slow and run per vertex, but it's still faster than
+ * doing it per instance on CPU and sending it on via instance attrib */
+ mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix)));
+
+ vec4 viewpos = ViewMatrix * (InstanceModelMatrix * vec4(pos, 1.0));
+
+ vPos = viewpos.xyz;
+ pPos = ProjectionMatrix * viewpos;
+
+ /* TODO FIX: there is still a problem with this vector
+ * when the bone is scaled or in persp mode. But it's
+ * barelly visible at the outline corners. */
+ ssNor = normalize((NormalMatrix * snor).xy);
+
+ ssPos = proj(pPos);
+
+ vColSize = outlineColorSize;
+}
diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl
new file mode 100644
index 00000000000..45748bf5644
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl
@@ -0,0 +1,11 @@
+
+uniform float alpha = 0.6;
+
+in vec4 finalColor;
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(finalColor.rgb, alpha);
+}
diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl
new file mode 100644
index 00000000000..7abbf7f3d25
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl
@@ -0,0 +1,36 @@
+
+uniform mat3 NormalMatrix;
+uniform mat4 ViewMatrixInverse;
+uniform mat4 ViewProjectionMatrix;
+
+uniform mat4 ViewMatrix;
+uniform mat4 ProjectionMatrix;
+
+/* ---- Instantiated Attribs ---- */
+in vec3 pos;
+in vec3 nor;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec3 boneColor;
+in vec3 stateColor;
+
+out vec4 finalColor;
+
+void main()
+{
+ mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix)));
+ vec3 normal = normalize(NormalMatrix * nor);
+
+ /* Do lighting at an angle to avoid flat shading on front facing bone. */
+ const vec3 light = vec3(0.1, 0.1, 0.8);
+ float n = dot(normal, light);
+
+ /* Smooth lighting factor. */
+ const float s = 0.2; /* [0.0-0.5] range */
+ float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0);
+ finalColor.rgb = mix(stateColor, boneColor, fac);
+ finalColor.a = 1.0;
+
+ gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(pos, 1.0));
+}
diff --git a/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl
new file mode 100644
index 00000000000..0c1fefbf814
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl
@@ -0,0 +1,102 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+uniform float lineThickness = 2.0;
+
+/* ---- Instantiated Attribs ---- */
+in vec2 pos0;
+in vec2 pos1;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 outlineColorSize;
+
+flat out vec4 finalColor;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+vec2 compute_dir(vec2 v0, vec2 v1, vec2 c)
+{
+ vec2 dir = normalize(v1 - v0);
+ dir = vec2(dir.y, -dir.x);
+ /* The model matrix can be scaled negativly.
+ * Use projected sphere center to determine
+ * the outline direction. */
+ vec2 cv = c - v0;
+ dir = (dot(dir, cv) > 0.0) ? -dir : dir;
+ return dir;
+}
+
+void main()
+{
+ mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix;
+ mat4 sphereMatrix = inverse(model_view_matrix);
+
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+
+ /* This is the local space camera ray (not normalize).
+ * In perspective mode it's also the viewspace position
+ * of the sphere center. */
+ vec3 cam_ray = (is_persp) ? model_view_matrix[3].xyz : vec3(0.0, 0.0, -1.0);
+ cam_ray = mat3(sphereMatrix) * cam_ray;
+
+ /* Sphere center distance from the camera (persp) in local space. */
+ float cam_dist = length(cam_ray);
+
+ /* Compute view aligned orthonormal space. */
+ vec3 z_axis = cam_ray / cam_dist;
+ vec3 x_axis = normalize(cross(sphereMatrix[1].xyz, z_axis));
+ vec3 y_axis = cross(z_axis, x_axis);
+ float z_ofs = 0.0;
+
+ if (is_persp) {
+ /* For perspective, the projected sphere radius
+ * can be bigger than the center disc. Compute the
+ * max angular size and compensate by sliding the disc
+ * towards the camera and scale it accordingly. */
+ const float half_pi = 3.1415926 * 0.5;
+ const float rad = 0.05;
+ /* Let be (in local space):
+ * V the view vector origin.
+ * O the sphere origin.
+ * T the point on the target circle.
+ * We compute the angle between (OV) and (OT). */
+ float a = half_pi - asin(rad / cam_dist);
+ float cos_b = cos(a);
+ float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0));
+
+ x_axis *= sin_b;
+ y_axis *= sin_b;
+ z_ofs = -rad * cos_b;
+ }
+
+ /* Camera oriented position (but still in local space) */
+ vec3 cam_pos0 = x_axis * pos0.x + y_axis * pos0.y + z_axis * z_ofs;
+ vec3 cam_pos1 = x_axis * pos1.x + y_axis * pos1.y + z_axis * z_ofs;
+
+ vec4 V = model_view_matrix * vec4(cam_pos0, 1.0);
+ vec4 p0 = ProjectionMatrix * V;
+ vec4 p1 = ProjectionMatrix * (model_view_matrix * vec4(cam_pos1, 1.0));
+ vec4 c = ProjectionMatrix * vec4(model_view_matrix[3].xyz, 1.0);
+
+ vec2 ssc = proj(c);
+ vec2 ss0 = proj(p0);
+ vec2 ss1 = proj(p1);
+ vec2 edge_dir = compute_dir(ss0, ss1, ssc);
+
+ bool outer = ((gl_VertexID & 1) == 1);
+
+ vec2 t = outlineColorSize.w * (lineThickness / viewportSize);
+ t *= (is_persp) ? abs(V.z) : 1.0;
+ t = (outer) ? t : vec2(0.0);
+
+ gl_Position = p0;
+ gl_Position.xy += t * edge_dir;
+
+ finalColor = vec4(outlineColorSize.rgb, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl
new file mode 100644
index 00000000000..a0fdd55931f
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl
@@ -0,0 +1,81 @@
+
+#extension GL_ARB_conservative_depth : enable
+
+uniform mat4 ViewMatrixInverse;
+uniform mat4 ProjectionMatrix;
+uniform float alpha = 0.4;
+
+flat in vec3 finalStateColor;
+flat in vec3 finalBoneColor;
+flat in mat4 sphereMatrix;
+in vec3 viewPosition;
+
+#ifdef GL_ARB_conservative_depth
+/* Saves a lot of overdraw! */
+layout(depth_greater) out float gl_FragDepth;
+#endif
+
+out vec4 fragColor;
+
+#define cameraPos ViewMatrixInverse[3].xyz
+
+float get_depth_from_view_z(float z)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ z = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2];
+ }
+ else {
+ z = z * ProjectionMatrix[2][2] / (1.0 - ProjectionMatrix[3][2]);
+ }
+ return z * 0.5 + 0.5;
+}
+
+void main()
+{
+ const float sphere_radius = 0.05;
+
+ bool is_perp = (ProjectionMatrix[3][3] == 0.0);
+ vec3 ray_ori_view = (is_perp) ? vec3(0.0) : viewPosition.xyz;
+ vec3 ray_dir_view = (is_perp) ? viewPosition : vec3(0.0, 0.0, -1.0);
+
+ /* Single matrix mul without branch. */
+ vec4 mul_vec = (is_perp) ? vec4(ray_dir_view, 0.0) : vec4(ray_ori_view, 1.0);
+ vec3 mul_res = (sphereMatrix * mul_vec).xyz;
+
+ /* Reminder :
+ * sphereMatrix[3] is the view space origin in sphere space (sph_ori -> view_ori).
+ * sphereMatrix[2] is the view space Z axis in sphere space. */
+
+ /* convert to sphere local space */
+ vec3 ray_ori = (is_perp) ? sphereMatrix[3].xyz : mul_res;
+ vec3 ray_dir = (is_perp) ? mul_res : -sphereMatrix[2].xyz;
+ float ray_len = length(ray_dir);
+ ray_dir /= ray_len;
+
+ /* Line to sphere intersect */
+ const float sphere_radius_sqr = sphere_radius * sphere_radius;
+ float b = dot(ray_ori, ray_dir);
+ float c = dot(ray_ori, ray_ori) - sphere_radius_sqr;
+ float h = b * b - c;
+ float t = -sqrt(max(0.0, h)) - b;
+
+ /* Compute dot product for lighting */
+ vec3 p = ray_dir * t + ray_ori; /* Point on sphere */
+ vec3 n = normalize(p); /* Normal is just the point in sphere space, normalized. */
+ vec3 l = normalize(sphereMatrix[2].xyz); /* Just the view Z axis in the sphere space. */
+
+
+ /* Smooth lighting factor. */
+ const float s = 0.2; /* [0.0-0.5] range */
+ float fac = clamp((dot(n, l) * (1.0 - s)) + s, 0.0, 1.0);
+ fragColor.rgb = mix(finalStateColor, finalBoneColor, fac);
+
+ /* 2x2 dither pattern to smooth the lighting. */
+ float dither = (0.5 + dot(vec2(ivec2(gl_FragCoord.xy) & ivec2(1)), vec2(1.0, 2.0))) * 0.25;
+ dither *= (1.0 / 255.0); /* Assume 8bit per color buffer. */
+
+ fragColor = vec4(fragColor.rgb + dither, alpha);
+
+ t /= ray_len;
+ gl_FragDepth = get_depth_from_view_z(ray_dir_view.z * t + ray_ori_view.z);
+}
diff --git a/source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl
new file mode 100644
index 00000000000..7cbc0c5bc3a
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl
@@ -0,0 +1,82 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ProjectionMatrix;
+
+/* ---- Instantiated Attribs ---- */
+in vec2 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec3 stateColor;
+in vec3 boneColor;
+
+flat out vec3 finalStateColor;
+flat out vec3 finalBoneColor;
+flat out mat4 sphereMatrix;
+out vec3 viewPosition;
+
+/* Sphere radius */
+const float rad = 0.05;
+
+void main()
+{
+ mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix;
+ sphereMatrix = inverse(model_view_matrix);
+
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+
+ /* This is the local space camera ray (not normalize).
+ * In perspective mode it's also the viewspace position
+ * of the sphere center. */
+ vec3 cam_ray = (is_persp) ? model_view_matrix[3].xyz : vec3(0.0, 0.0, -1.0);
+ cam_ray = mat3(sphereMatrix) * cam_ray;
+
+ /* Sphere center distance from the camera (persp) in local space. */
+ float cam_dist = length(cam_ray);
+
+ /* Compute view aligned orthonormal space. */
+ vec3 z_axis = cam_ray / cam_dist;
+ vec3 x_axis = normalize(cross(sphereMatrix[1].xyz, z_axis));
+ vec3 y_axis = cross(z_axis, x_axis);
+
+ float z_ofs = -rad - 1e-8; /* offset to the front of the sphere */
+ if (is_persp) {
+ /* For perspective, the projected sphere radius
+ * can be bigger than the center disc. Compute the
+ * max angular size and compensate by sliding the disc
+ * towards the camera and scale it accordingly. */
+ const float half_pi = 3.1415926 * 0.5;
+ /* Let be (in local space):
+ * V the view vector origin.
+ * O the sphere origin.
+ * T the point on the target circle.
+ * We compute the angle between (OV) and (OT). */
+ float a = half_pi - asin(rad / cam_dist);
+ float cos_b = cos(a);
+ float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0));
+#if 1
+ /* Instead of choosing the biggest circle in screenspace,
+ * we choose the nearest with the same angular size. This
+ * permit us to leverage GL_ARB_conservative_depth in the
+ * fragment shader. */
+ float minor = cam_dist - rad;
+ float major = cam_dist - cos_b * rad;
+ float fac = minor / major;
+ sin_b *= fac;
+#else
+ z_ofs = -rad * cos_b;
+#endif
+ x_axis *= sin_b;
+ y_axis *= sin_b;
+ }
+
+ /* Camera oriented position (but still in local space) */
+ vec3 cam_pos = x_axis * pos.x + y_axis * pos.y + z_axis * z_ofs;
+
+ vec4 V = model_view_matrix * vec4(cam_pos, 1.0);
+ gl_Position = ProjectionMatrix * V;
+ viewPosition = V.xyz;
+
+ finalStateColor = stateColor;
+ finalBoneColor = boneColor;
+}
diff --git a/source/blender/draw/modes/shaders/armature_stick_frag.glsl b/source/blender/draw/modes/shaders/armature_stick_frag.glsl
new file mode 100644
index 00000000000..d03cf4c0366
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_stick_frag.glsl
@@ -0,0 +1,13 @@
+
+noperspective in float colorFac;
+flat in vec4 finalWireColor;
+flat in vec4 finalInnerColor;
+
+out vec4 fragColor;
+
+void main()
+{
+ float fac = smoothstep(1.0, 0.2, colorFac);
+ fragColor.rgb = mix(finalInnerColor.rgb, finalWireColor.rgb, fac);
+ fragColor.a = 1.0;
+}
diff --git a/source/blender/draw/modes/shaders/armature_stick_vert.glsl b/source/blender/draw/modes/shaders/armature_stick_vert.glsl
new file mode 100644
index 00000000000..58fc48e608e
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_stick_vert.glsl
@@ -0,0 +1,88 @@
+
+uniform mat4 ProjectionMatrix;
+uniform mat4 ViewProjectionMatrix;
+uniform mat4 ViewMatrix;
+uniform vec2 viewportSize;
+
+/* ---- Instantiated Attribs ---- */
+in vec2 pos; /* bone aligned screen space */
+in uint flag;
+
+#define COL_WIRE 1u /* (1 << 0) */
+#define COL_HEAD 2u /* (1 << 1) */
+#define COL_TAIL 4u /* (1 << 2) */
+#define COL_BONE 8u /* (1 << 3) */
+
+#define POS_HEAD 16u /* (1 << 4) */
+#define POS_TAIL 32u /* (1 << 5) */ /* UNUSED */
+#define POS_BONE 64u /* (1 << 6) */
+
+/* ---- Per instance Attribs ---- */
+in vec3 boneStart;
+in vec3 boneEnd;
+in vec4 wireColor; /* alpha encode if we do wire. If 0.0 we dont. */
+in vec4 boneColor; /* alpha encode if we do bone. If 0.0 we dont. */
+in vec4 headColor; /* alpha encode if we do head. If 0.0 we dont. */
+in vec4 tailColor; /* alpha encode if we do tail. If 0.0 we dont. */
+
+#define do_wire (wireColor.a > 0.0)
+#define is_head bool(flag & POS_HEAD)
+#define is_bone bool(flag & POS_BONE)
+
+noperspective out float colorFac;
+flat out vec4 finalWireColor;
+flat out vec4 finalInnerColor;
+
+uniform float stickSize = 5.0; /* might be dependent on DPI setting in the future. */
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+void main()
+{
+ finalInnerColor = ((flag & COL_HEAD) != 0u) ? headColor : tailColor;
+ finalInnerColor = ((flag & COL_BONE) != 0u) ? boneColor : finalInnerColor;
+ finalWireColor = (do_wire) ? wireColor : finalInnerColor;
+ /* Make the color */
+ colorFac = ((flag & COL_WIRE) == 0u) ? ((flag & COL_BONE) != 0u) ? 1.0 : 2.0 : 0.0;
+
+ vec4 v0 = ViewMatrix * vec4(boneStart, 1.0);
+ vec4 v1 = ViewMatrix * vec4(boneEnd, 1.0);
+
+ /* Clip the bone to the camera origin plane (not the clip plane)
+ * to avoid glitches if one end is behind the camera origin (in persp). */
+ float clip_dist = (ProjectionMatrix[3][3] == 0.0) ? -1e-7 : 1e20; /* hardcoded, -1e-8 is giving gliches. */
+ vec3 bvec = v1.xyz - v0.xyz;
+ vec3 clip_pt = v0.xyz + bvec * ((v0.z - clip_dist) / -bvec.z);
+ if (v0.z > clip_dist) {
+ v0.xyz = clip_pt;
+ }
+ else if (v1.z > clip_dist) {
+ v1.xyz = clip_pt;
+ }
+
+ vec4 p0 = ProjectionMatrix * v0;
+ vec4 p1 = ProjectionMatrix * v1;
+
+ float h = (is_head) ? p0.w : p1.w;
+
+ vec2 x_screen_vec = normalize(proj(p1) - proj(p0) + 1e-8);
+ vec2 y_screen_vec = vec2(x_screen_vec.y, -x_screen_vec.x);
+
+ /* 2D screen aligned pos at the point */
+ vec2 vpos = pos.x * x_screen_vec + pos.y * y_screen_vec;
+ vpos *= (ProjectionMatrix[3][3] == 0.0) ? h : 1.0;
+ vpos *= (do_wire) ? 1.0 : 0.5;
+
+ if (finalInnerColor.a > 0.0) {
+ gl_Position = (is_head) ? p0 : p1;
+ gl_Position.xy += stickSize * (vpos / viewportSize);
+ gl_Position.z += (is_bone) ? 0.0 : 1e-6; /* Avoid Z fighting of head/tails. */
+ }
+ else {
+ gl_Position = vec4(0.0);
+ }
+}
diff --git a/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl
new file mode 100644
index 00000000000..fc5cc1cdcc3
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl
@@ -0,0 +1,10 @@
+
+in vec2 pos;
+in vec2 uvs;
+out vec4 uvcoordsvar;
+
+void main()
+{
+ uvcoordsvar = vec4(uvs, 0.0, 0.0);
+ gl_Position = vec4(pos, 0.0, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/common_fxaa_lib.glsl b/source/blender/draw/modes/shaders/common_fxaa_lib.glsl
new file mode 100644
index 00000000000..236ac5c67f0
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_fxaa_lib.glsl
@@ -0,0 +1,677 @@
+//----------------------------------------------------------------------------------
+// File: es3-kepler\FXAA/FXAA3_11.h
+// SDK Version: v3.00
+// Email: gameworks@nvidia.com
+// Site: http://developer.nvidia.com/
+//
+// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of NVIDIA CORPORATION nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//----------------------------------------------------------------------------------
+
+/* BLENDER MODIFICATIONS:
+ *
+ * - (#B1#) Compute luma on the fly using BT. 709 luma function
+ * - (#B2#) main function instead of #include, due to lack of
+ * ARB_shading_language_include in 3.3
+ * - (#B3#) version and extension directives
+ * - removed "FXAA Console" algorithm support and shader parameters
+ * - removed HLSL support shims
+ * - (#B4#) change luma sampling to compute, not use A channel
+ * (this also removes GATHER4_ALPHA support)
+ * - removed all the console shaders (only remaining algorithm is "FXAA PC
+ * Quality")
+ *
+ * Note that this file doesn't follow the coding style guidelines.
+ */
+
+/*============================================================================
+ FXAA QUALITY - TUNING KNOBS
+------------------------------------------------------------------------------
+NOTE the other tuning knobs are now in the shader function inputs!
+============================================================================*/
+#ifndef FXAA_QUALITY__PRESET
+ //
+ // Choose the quality preset.
+ // This needs to be compiled into the shader as it effects code.
+ // Best option to include multiple presets is to
+ // in each shader define the preset, then include this file.
+ //
+ // OPTIONS
+ // -----------------------------------------------------------------------
+ // 10 to 15 - default medium dither (10=fastest, 15=highest quality)
+ // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)
+ // 39 - no dither, very expensive
+ //
+ // NOTES
+ // -----------------------------------------------------------------------
+ // 12 = slightly faster then FXAA 3.9 and higher edge quality (default)
+ // 13 = about same speed as FXAA 3.9 and better than 12
+ // 23 = closest to FXAA 3.9 visually and performance wise
+ // _ = the lowest digit is directly related to performance
+ // _ = the highest digit is directly related to style
+ //
+ #define FXAA_QUALITY__PRESET 12
+#endif
+
+/*============================================================================
+
+ FXAA QUALITY - PRESETS
+
+============================================================================*/
+
+/*============================================================================
+ FXAA QUALITY - MEDIUM DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 10)
+ #define FXAA_QUALITY__PS 3
+ #define FXAA_QUALITY__P0 1.5
+ #define FXAA_QUALITY__P1 3.0
+ #define FXAA_QUALITY__P2 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 11)
+ #define FXAA_QUALITY__PS 4
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 3.0
+ #define FXAA_QUALITY__P3 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 12)
+ #define FXAA_QUALITY__PS 5
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 4.0
+ #define FXAA_QUALITY__P4 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 13)
+ #define FXAA_QUALITY__PS 6
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 4.0
+ #define FXAA_QUALITY__P5 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 14)
+ #define FXAA_QUALITY__PS 7
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 4.0
+ #define FXAA_QUALITY__P6 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 15)
+ #define FXAA_QUALITY__PS 8
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 4.0
+ #define FXAA_QUALITY__P7 12.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - LOW DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 20)
+ #define FXAA_QUALITY__PS 3
+ #define FXAA_QUALITY__P0 1.5
+ #define FXAA_QUALITY__P1 2.0
+ #define FXAA_QUALITY__P2 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 21)
+ #define FXAA_QUALITY__PS 4
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 22)
+ #define FXAA_QUALITY__PS 5
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 23)
+ #define FXAA_QUALITY__PS 6
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 24)
+ #define FXAA_QUALITY__PS 7
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 3.0
+ #define FXAA_QUALITY__P6 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 25)
+ #define FXAA_QUALITY__PS 8
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 4.0
+ #define FXAA_QUALITY__P7 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 26)
+ #define FXAA_QUALITY__PS 9
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 4.0
+ #define FXAA_QUALITY__P8 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 27)
+ #define FXAA_QUALITY__PS 10
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 4.0
+ #define FXAA_QUALITY__P9 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 28)
+ #define FXAA_QUALITY__PS 11
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 4.0
+ #define FXAA_QUALITY__P10 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 29)
+ #define FXAA_QUALITY__PS 12
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 2.0
+ #define FXAA_QUALITY__P10 4.0
+ #define FXAA_QUALITY__P11 8.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - EXTREME QUALITY
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 39)
+ #define FXAA_QUALITY__PS 12
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.0
+ #define FXAA_QUALITY__P2 1.0
+ #define FXAA_QUALITY__P3 1.0
+ #define FXAA_QUALITY__P4 1.0
+ #define FXAA_QUALITY__P5 1.5
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 2.0
+ #define FXAA_QUALITY__P10 4.0
+ #define FXAA_QUALITY__P11 8.0
+#endif
+
+#define FxaaSat(x) clamp(x, 0.0, 1.0)
+
+#ifdef FXAA_ALPHA
+
+#define FxaaTexTop(t, p) textureLod(t, p, 0.0).aaaa
+#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o).aaaa
+#define FxaaLuma(rgba) rgba.a
+
+#else
+
+#define FxaaTexTop(t, p) textureLod(t, p, 0.0)
+#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
+
+/* (#B1#) */
+float FxaaLuma(vec4 rgba) {
+ // note: sqrt because the sampled colors are in a linear colorspace!
+ // this approximates a perceptual conversion, which is good enough for the
+ // algorithm
+ return sqrt(dot(rgba.rgb, vec3(0.2126, 0.7152, 0.0722)));
+}
+
+#endif
+
+/*============================================================================
+
+ FXAA3 QUALITY - PC
+
+============================================================================*/
+/*--------------------------------------------------------------------------*/
+vec4 FxaaPixelShader(
+ //
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy} = center of pixel
+ vec2 pos,
+ //
+ // Input color texture.
+ // {rgb_} = color in linear or perceptual color space
+ sampler2D tex,
+ //
+ // Only used on FXAA Quality.
+ // This must be from a constant/uniform.
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ vec2 fxaaQualityRcpFrame,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__SUBPIX define.
+ // It is here now to allow easier tuning.
+ // Choose the amount of sub-pixel aliasing removal.
+ // This can effect sharpness.
+ // 1.00 - upper limit (softer)
+ // 0.75 - default amount of filtering
+ // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)
+ // 0.25 - almost off
+ // 0.00 - completely off
+ float fxaaQualitySubpix,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // The minimum amount of local contrast required to apply algorithm.
+ // 0.333 - too little (faster)
+ // 0.250 - low quality
+ // 0.166 - default
+ // 0.125 - high quality
+ // 0.063 - overkill (slower)
+ float fxaaQualityEdgeThreshold,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // 0.0833 - upper limit (default, the start of visible unfiltered edges)
+ // 0.0625 - high quality (faster)
+ // 0.0312 - visible limit (slower)
+ float fxaaQualityEdgeThresholdMin
+) {
+/*--------------------------------------------------------------------------*/
+ vec2 posM;
+ posM.x = pos.x;
+ posM.y = pos.y;
+ vec4 rgbyM = FxaaTexTop(tex, posM);
+ float lumaM = FxaaLuma(rgbyM); // (#B4#)
+ float lumaS = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 0, 1), fxaaQualityRcpFrame.xy));
+ float lumaE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1, 0), fxaaQualityRcpFrame.xy));
+ float lumaN = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 0,-1), fxaaQualityRcpFrame.xy));
+ float lumaW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 0), fxaaQualityRcpFrame.xy));
+/*--------------------------------------------------------------------------*/
+ float maxSM = max(lumaS, lumaM);
+ float minSM = min(lumaS, lumaM);
+ float maxESM = max(lumaE, maxSM);
+ float minESM = min(lumaE, minSM);
+ float maxWN = max(lumaN, lumaW);
+ float minWN = min(lumaN, lumaW);
+ float rangeMax = max(maxWN, maxESM);
+ float rangeMin = min(minWN, minESM);
+ float rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
+ float range = rangeMax - rangeMin;
+ float rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
+ bool earlyExit = range < rangeMaxClamped;
+/*--------------------------------------------------------------------------*/
+ if(earlyExit) {
+ return rgbyM;
+ }
+/*--------------------------------------------------------------------------*/
+ float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1,-1), fxaaQualityRcpFrame.xy));
+ float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1, 1), fxaaQualityRcpFrame.xy));
+ float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1,-1), fxaaQualityRcpFrame.xy));
+ float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 1), fxaaQualityRcpFrame.xy));
+/*--------------------------------------------------------------------------*/
+ float lumaNS = lumaN + lumaS;
+ float lumaWE = lumaW + lumaE;
+ float subpixRcpRange = 1.0/range;
+ float subpixNSWE = lumaNS + lumaWE;
+ float edgeHorz1 = (-2.0 * lumaM) + lumaNS;
+ float edgeVert1 = (-2.0 * lumaM) + lumaWE;
+/*--------------------------------------------------------------------------*/
+ float lumaNESE = lumaNE + lumaSE;
+ float lumaNWNE = lumaNW + lumaNE;
+ float edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
+ float edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
+/*--------------------------------------------------------------------------*/
+ float lumaNWSW = lumaNW + lumaSW;
+ float lumaSWSE = lumaSW + lumaSE;
+ float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
+ float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
+ float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
+ float edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
+ float edgeHorz = abs(edgeHorz3) + edgeHorz4;
+ float edgeVert = abs(edgeVert3) + edgeVert4;
+/*--------------------------------------------------------------------------*/
+ float subpixNWSWNESE = lumaNWSW + lumaNESE;
+ float lengthSign = fxaaQualityRcpFrame.x;
+ bool horzSpan = edgeHorz >= edgeVert;
+ float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
+/*--------------------------------------------------------------------------*/
+ if(!horzSpan) lumaN = lumaW;
+ if(!horzSpan) lumaS = lumaE;
+ if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
+ float subpixB = (subpixA * (1.0/12.0)) - lumaM;
+/*--------------------------------------------------------------------------*/
+ float gradientN = lumaN - lumaM;
+ float gradientS = lumaS - lumaM;
+ float lumaNN = lumaN + lumaM;
+ float lumaSS = lumaS + lumaM;
+ bool pairN = abs(gradientN) >= abs(gradientS);
+ float gradient = max(abs(gradientN), abs(gradientS));
+ if(pairN) lengthSign = -lengthSign;
+ float subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
+/*--------------------------------------------------------------------------*/
+ vec2 posB;
+ posB.x = posM.x;
+ posB.y = posM.y;
+ vec2 offNP;
+ offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
+ offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
+ if(!horzSpan) posB.x += lengthSign * 0.5;
+ if( horzSpan) posB.y += lengthSign * 0.5;
+/*--------------------------------------------------------------------------*/
+ vec2 posN;
+ posN.x = posB.x - offNP.x * FXAA_QUALITY__P0;
+ posN.y = posB.y - offNP.y * FXAA_QUALITY__P0;
+ vec2 posP;
+ posP.x = posB.x + offNP.x * FXAA_QUALITY__P0;
+ posP.y = posB.y + offNP.y * FXAA_QUALITY__P0;
+ float subpixD = ((-2.0)*subpixC) + 3.0;
+ float lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
+ float subpixE = subpixC * subpixC;
+ float lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
+/*--------------------------------------------------------------------------*/
+ if(!pairN) lumaNN = lumaSS;
+ float gradientScaled = gradient * 1.0/4.0;
+ float lumaMM = lumaM - lumaNN * 0.5;
+ float subpixF = subpixD * subpixE;
+ bool lumaMLTZero = lumaMM < 0.0;
+/*--------------------------------------------------------------------------*/
+ lumaEndN -= lumaNN * 0.5;
+ lumaEndP -= lumaNN * 0.5;
+ bool doneN = abs(lumaEndN) >= gradientScaled;
+ bool doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1;
+ bool doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1;
+/*--------------------------------------------------------------------------*/
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 3)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 4)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 5)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 6)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 7)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 8)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 9)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 10)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 11)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 12)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12;
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+/*--------------------------------------------------------------------------*/
+ float dstN = posM.x - posN.x;
+ float dstP = posP.x - posM.x;
+ if(!horzSpan) dstN = posM.y - posN.y;
+ if(!horzSpan) dstP = posP.y - posM.y;
+/*--------------------------------------------------------------------------*/
+ bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
+ float spanLength = (dstP + dstN);
+ bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
+ float spanLengthRcp = 1.0/spanLength;
+/*--------------------------------------------------------------------------*/
+ bool directionN = dstN < dstP;
+ float dst = min(dstN, dstP);
+ bool goodSpan = directionN ? goodSpanN : goodSpanP;
+ float subpixG = subpixF * subpixF;
+ float pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
+ float subpixH = subpixG * fxaaQualitySubpix;
+/*--------------------------------------------------------------------------*/
+ float pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
+ float pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
+ if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
+ if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
+ return vec4(FxaaTexTop(tex, posM).xyz, lumaM);
+}
+/*==========================================================================*/
diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl
new file mode 100644
index 00000000000..69ba304ca24
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl
@@ -0,0 +1,80 @@
+
+/* keep in sync with GlobalsUboStorage */
+layout(std140) uniform globalsBlock {
+ vec4 colorWire;
+ vec4 colorWireEdit;
+ vec4 colorActive;
+ vec4 colorSelect;
+ vec4 colorTransform;
+ vec4 colorLibrarySelect;
+ vec4 colorLibrary;
+ vec4 colorLamp;
+ vec4 colorSpeaker;
+ vec4 colorCamera;
+ vec4 colorEmpty;
+ vec4 colorVertex;
+ vec4 colorVertexSelect;
+ vec4 colorVertexUnreferenced;
+ vec4 colorVertexMissingData;
+ vec4 colorEditMeshActive;
+ vec4 colorEdgeSelect;
+ vec4 colorEdgeSeam;
+ vec4 colorEdgeSharp;
+ vec4 colorEdgeCrease;
+ vec4 colorEdgeBWeight;
+ vec4 colorEdgeFaceSelect;
+ vec4 colorEdgeFreestyle;
+ vec4 colorFace;
+ vec4 colorFaceSelect;
+ vec4 colorFaceFreestyle;
+ vec4 colorNormal;
+ vec4 colorVNormal;
+ vec4 colorLNormal;
+ vec4 colorFaceDot;
+ vec4 colorDeselect;
+ vec4 colorOutline;
+ vec4 colorLampNoAlpha;
+
+ vec4 colorBackground;
+
+ vec4 colorHandleFree;
+ vec4 colorHandleAuto;
+ vec4 colorHandleVect;
+ vec4 colorHandleAlign;
+ vec4 colorHandleAutoclamp;
+ vec4 colorHandleSelFree;
+ vec4 colorHandleSelAuto;
+ vec4 colorHandleSelVect;
+ vec4 colorHandleSelAlign;
+ vec4 colorHandleSelAutoclamp;
+ vec4 colorNurbUline;
+ vec4 colorNurbVline;
+ vec4 colorNurbSelUline;
+ vec4 colorNurbSelVline;
+ vec4 colorActiveSpline;
+
+ vec4 colorBonePose;
+
+ vec4 colorCurrentFrame;
+
+ vec4 colorGrid;
+ vec4 colorGridEmphasise;
+ vec4 colorGridAxisX;
+ vec4 colorGridAxisY;
+ vec4 colorGridAxisZ;
+
+ float sizeLampCenter;
+ float sizeLampCircle;
+ float sizeLampCircleShadow;
+ float sizeVertex;
+ float sizeEdge;
+ float sizeEdgeFix;
+ float sizeFaceDot;
+
+ float gridDistance;
+ float gridResolution;
+ float gridSubdivisions;
+ float gridScale;
+
+ float pad_globalsBlock;
+};
diff --git a/source/blender/draw/modes/shaders/common_hair_lib.glsl b/source/blender/draw/modes/shaders/common_hair_lib.glsl
new file mode 100644
index 00000000000..594a7b31f0b
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_hair_lib.glsl
@@ -0,0 +1,199 @@
+/**
+ * Library to create hairs dynamically from control points.
+ * This is less bandwidth intensive than fetching the vertex attributes
+ * but does more ALU work per vertex. This also reduce the number
+ * of data the CPU has to precompute and transfert for each update.
+ **/
+
+/**
+ * hairStrandsRes: Number of points per hair strand.
+ * 2 - no subdivision
+ * 3+ - 1 or more interpolated points per hair.
+ **/
+uniform int hairStrandsRes = 8;
+
+/**
+ * hairThicknessRes : Subdiv around the hair.
+ * 1 - Wire Hair: Only one pixel thick, independent of view distance.
+ * 2 - Polystrip Hair: Correct width, flat if camera is parallel.
+ * 3+ - Cylinder Hair: Massive calculation but potentially perfect. Still need proper support.
+ **/
+uniform int hairThicknessRes = 1;
+
+/* Hair thickness shape. */
+uniform float hairRadRoot = 0.01;
+uniform float hairRadTip = 0.0;
+uniform float hairRadShape = 0.5;
+uniform bool hairCloseTip = true;
+
+uniform mat4 hairDupliMatrix;
+
+/* -- Per control points -- */
+uniform samplerBuffer hairPointBuffer; /* RGBA32F */
+#define point_position xyz
+#define point_time w /* Position along the hair length */
+
+/* -- Per strands data -- */
+uniform usamplerBuffer hairStrandBuffer; /* R32UI */
+
+/* Not used, use one buffer per uv layer */
+//uniform samplerBuffer hairUVBuffer; /* RG32F */
+//uniform samplerBuffer hairColBuffer; /* RGBA16 linear color */
+
+void unpack_strand_data(uint data, out int strand_offset, out int strand_segments)
+{
+#if 0 /* Pack point count */
+ // strand_offset = (data & 0x1FFFFFFFu);
+ // strand_segments = 1u << (data >> 29u); /* We only need 3 bits to store subdivision level. */
+#else
+ strand_offset = int(data & 0x00FFFFFFu);
+ strand_segments = int(data >> 24u);
+#endif
+}
+
+/* -- Subdivision stage -- */
+/**
+ * We use a transform feedback to preprocess the strands and add more subdivision to it.
+ * For the moment theses are simple smooth interpolation but one could hope to see the full
+ * children particle modifiers being evaluated at this stage.
+ *
+ * If no more subdivision is needed, we can skip this step.
+ **/
+
+#ifdef HAIR_PHASE_SUBDIV
+int hair_get_base_id(float local_time, int strand_segments, out float interp_time)
+{
+ float time_per_strand_seg = 1.0 / float(strand_segments);
+
+ float ratio = local_time / time_per_strand_seg;
+ interp_time = fract(ratio);
+
+ return int(ratio);
+}
+
+void hair_get_interp_attribs(out vec4 data0, out vec4 data1, out vec4 data2, out vec4 data3, out float interp_time)
+{
+ float local_time = float(gl_VertexID % hairStrandsRes) / float(hairStrandsRes - 1);
+
+ int hair_id = gl_VertexID / hairStrandsRes;
+ uint strand_data = texelFetch(hairStrandBuffer, hair_id).x;
+
+ int strand_offset, strand_segments;
+ unpack_strand_data(strand_data, strand_offset, strand_segments);
+
+ int id = hair_get_base_id(local_time, strand_segments, interp_time);
+
+ int ofs_id = id + strand_offset;
+
+ data0 = texelFetch(hairPointBuffer, ofs_id - 1);
+ data1 = texelFetch(hairPointBuffer, ofs_id);
+ data2 = texelFetch(hairPointBuffer, ofs_id + 1);
+ data3 = texelFetch(hairPointBuffer, ofs_id + 2);
+
+ if (id <= 0) {
+ /* root points. Need to reconstruct previous data. */
+ data0 = data1 * 2.0 - data2;
+ }
+ if (id + 1 >= strand_segments) {
+ /* tip points. Need to reconstruct next data. */
+ data3 = data2 * 2.0 - data1;
+ }
+}
+#endif
+
+/* -- Drawing stage -- */
+/**
+ * For final drawing, the vertex index and the number of vertex per segment
+ **/
+
+#ifndef HAIR_PHASE_SUBDIV
+int hair_get_strand_id(void)
+{
+ return gl_VertexID / (hairStrandsRes * hairThicknessRes);
+}
+
+int hair_get_base_id(void)
+{
+ return gl_VertexID / hairThicknessRes;
+}
+
+/* Copied from cycles. */
+float hair_shaperadius(float shape, float root, float tip, float time)
+{
+ float radius = 1.0 - time;
+
+ if (shape < 0.0) {
+ radius = pow(radius, 1.0 + shape);
+ }
+ else {
+ radius = pow(radius, 1.0 / (1.0 - shape));
+ }
+
+ if (hairCloseTip && (time > 0.99)) {
+ return 0.0;
+ }
+
+ return (radius * (root - tip)) + tip;
+}
+
+void hair_get_pos_tan_binor_time(
+ bool is_persp, mat4 invmodel_mat, vec3 camera_pos, vec3 camera_z,
+ out vec3 wpos, out vec3 wtan, out vec3 wbinor, out float time, out float thickness, out float thick_time)
+{
+ int id = hair_get_base_id();
+ vec4 data = texelFetch(hairPointBuffer, id);
+ wpos = data.point_position;
+ time = data.point_time;
+ if (time == 0.0) {
+ /* Hair root */
+ wtan = texelFetch(hairPointBuffer, id + 1).point_position - wpos;
+ }
+ else {
+ wtan = wpos - texelFetch(hairPointBuffer, id - 1).point_position;
+ }
+
+ wpos = (hairDupliMatrix * vec4(wpos, 1.0)).xyz;
+ wtan = mat3(hairDupliMatrix) * wtan;
+
+ vec3 camera_vec = (is_persp) ? wpos - camera_pos : -camera_z;
+ wbinor = normalize(cross(camera_vec, wtan));
+
+ thickness = hair_shaperadius(hairRadShape, hairRadRoot, hairRadTip, time);
+
+ if (hairThicknessRes > 1) {
+ thick_time = float(gl_VertexID % hairThicknessRes) / float(hairThicknessRes - 1);
+ thick_time = thickness * (thick_time * 2.0 - 1.0);
+
+ /* Take object scale into account.
+ * NOTE: This only works fine with uniform scaling. */
+ float scale = 1.0 / length(mat3(invmodel_mat) * wbinor);
+
+ wpos += wbinor * thick_time * scale;
+ }
+}
+
+vec2 hair_get_customdata_vec2(const samplerBuffer cd_buf)
+{
+ int id = hair_get_strand_id();
+ return texelFetch(cd_buf, id).rg;
+}
+
+vec3 hair_get_customdata_vec3(const samplerBuffer cd_buf)
+{
+ int id = hair_get_strand_id();
+ return texelFetch(cd_buf, id).rgb;
+}
+
+vec4 hair_get_customdata_vec4(const samplerBuffer cd_buf)
+{
+ int id = hair_get_strand_id();
+ return texelFetch(cd_buf, id).rgba;
+}
+
+vec3 hair_get_strand_pos(void)
+{
+ int id = hair_get_strand_id() * hairStrandsRes;
+ return texelFetch(hairPointBuffer, id).point_position;
+}
+
+#endif
diff --git a/source/blender/draw/modes/shaders/common_hair_refine_vert.glsl b/source/blender/draw/modes/shaders/common_hair_refine_vert.glsl
new file mode 100644
index 00000000000..9f412c57db3
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_hair_refine_vert.glsl
@@ -0,0 +1,55 @@
+
+/* To be compiled with common_hair_lib.glsl */
+
+out vec4 outData;
+
+vec4 get_weights_cardinal(float t)
+{
+ float t2 = t * t;
+ float t3 = t2 * t;
+#if defined(CARDINAL)
+ float fc = 0.71;
+#else /* defined(CATMULL_ROM) */
+ float fc = 0.5;
+#endif
+
+ vec4 weights;
+ /* GLSL Optimized version of key_curve_position_weights() */
+ float fct = t * fc;
+ float fct2 = t2 * fc;
+ float fct3 = t3 * fc;
+ weights.x = ( fct2 * 2.0 - fct3) - fct;
+ weights.y = ( t3 * 2.0 - fct3) + (-t2 * 3.0 + fct2) + 1.0;
+ weights.z = (-t3 * 2.0 + fct3) + ( t2 * 3.0 - (2.0 * fct2)) + fct;
+ weights.w = fct3 - fct2;
+ return weights;
+}
+
+/* TODO(fclem): This one is buggy, find why. (it's not the optimization!!) */
+vec4 get_weights_bspline(float t)
+{
+ float t2 = t * t;
+ float t3 = t2 * t;
+
+ vec4 weights;
+ /* GLSL Optimized version of key_curve_position_weights() */
+ weights.xz = vec2(-0.16666666, -0.5) * t3 + (0.5 * t2 + 0.5 * vec2(-t, t) + 0.16666666);
+ weights.y = ( 0.5 * t3 - t2 + 0.66666666);
+ weights.w = ( 0.16666666 * t3);
+ return weights;
+}
+
+vec4 interp_data(vec4 v0, vec4 v1, vec4 v2, vec4 v3, vec4 w)
+{
+ return v0 * w.x + v1 * w.y + v2 * w.z + v3 * w.w;
+}
+
+void main(void)
+{
+ float interp_time;
+ vec4 data0, data1, data2, data3;
+ hair_get_interp_attribs(data0, data1, data2, data3, interp_time);
+
+ vec4 weights = get_weights_cardinal(interp_time);
+ outData = interp_data(data0, data1, data2, data3, weights);
+}
diff --git a/source/blender/draw/modes/shaders/common_view_lib.glsl b/source/blender/draw/modes/shaders/common_view_lib.glsl
new file mode 100644
index 00000000000..d261d263a6f
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_view_lib.glsl
@@ -0,0 +1,14 @@
+/* keep in sync with DRWManager.view_data */
+layout(std140) uniform viewBlock {
+ /* Same order as DRWViewportMatrixType */
+ mat4 ViewProjectionMatrix;
+ mat4 ViewProjectionMatrixInverse;
+ mat4 ViewMatrix;
+ mat4 ViewMatrixInverse;
+ mat4 ProjectionMatrix;
+ mat4 ProjectionMatrixInverse;
+
+ vec4 CameraTexCoFactors;
+
+ vec4 clipPlanes[2];
+};
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl
new file mode 100644
index 00000000000..7bc9b381bad
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl
@@ -0,0 +1,96 @@
+
+#define VERTEX_ACTIVE 1 << 0
+#define VERTEX_SELECTED 1 << 1
+#define ACTIVE_NURB 1 << 2 /* Keep the same value of `ACTIVE_NURB` in `draw_cache_imp_curve.c` */
+#define EVEN_U_BIT 1 << 3
+
+layout(lines) in;
+layout(triangle_strip, max_vertices = 10) out;
+
+uniform vec2 viewportSize;
+uniform bool showCurveHandles;
+
+flat in int vertFlag[];
+
+out vec4 finalColor;
+
+void output_line(vec2 offset, vec4 color)
+{
+ finalColor = color;
+
+ gl_Position = gl_in[0].gl_Position;
+ gl_Position.xy += offset * gl_in[0].gl_Position.w;
+ EmitVertex();
+
+ gl_Position = gl_in[1].gl_Position;
+ gl_Position.xy += offset * gl_in[1].gl_Position.w;
+ EmitVertex();
+}
+
+void main()
+{
+ vec4 v1 = gl_in[0].gl_Position;
+ vec4 v2 = gl_in[1].gl_Position;
+
+ int is_active_nurb = (vertFlag[1] & ACTIVE_NURB);
+ int color_id = (vertFlag[1] >> 4);
+
+ /* Don't output any edges if we don't show handles */
+ if (!showCurveHandles && (color_id < 5))
+ return;
+
+ bool edge_selected = (((vertFlag[1] | vertFlag[0]) & VERTEX_SELECTED) != 0);
+
+ vec4 inner_color;
+ if (color_id == 0) inner_color = (edge_selected) ? colorHandleSelFree : colorHandleFree;
+ else if (color_id == 1) inner_color = (edge_selected) ? colorHandleSelAuto : colorHandleAuto;
+ else if (color_id == 2) inner_color = (edge_selected) ? colorHandleSelVect : colorHandleVect;
+ else if (color_id == 3) inner_color = (edge_selected) ? colorHandleSelAlign : colorHandleAlign;
+ else if (color_id == 4) inner_color = (edge_selected) ? colorHandleSelAutoclamp : colorHandleAutoclamp;
+ else {
+ bool is_selected = (((vertFlag[1] & vertFlag[0]) & VERTEX_SELECTED) != 0);
+ bool is_u_segment = (((vertFlag[1] ^ vertFlag[0]) & EVEN_U_BIT) != 0);
+ if (is_u_segment) {
+ inner_color = (is_selected) ? colorNurbSelUline : colorNurbUline;
+ }
+ else {
+ inner_color = (is_selected) ? colorNurbSelVline : colorNurbVline;
+ }
+ }
+
+ vec4 outer_color = (is_active_nurb != 0)
+ ? mix(colorActiveSpline, inner_color, 0.25) /* Minimize active color bleeding on inner_color. */
+ : vec4(inner_color.rgb, 0.0);
+
+ vec2 v1_2 = (v2.xy/v2.w - v1.xy/v1.w);
+ vec2 offset = sizeEdge * 4.0 / viewportSize; /* 4.0 is eyeballed */
+
+ if (abs(v1_2.x * viewportSize.x) < abs(v1_2.y * viewportSize.y)) {
+ offset.y = 0.0;
+ }
+ else {
+ offset.x = 0.0;
+ }
+
+ /* draw the transparent border (AA). */
+ if (is_active_nurb != 0) {
+ offset *= 0.75; /* Don't make the active "halo" appear very thick. */
+ output_line(offset * 2.0, vec4(colorActiveSpline.rgb, 0.0));
+ }
+
+ /* draw the outline. */
+ output_line(offset, outer_color);
+
+ /* draw the core of the line. */
+ output_line(vec2(0.0), inner_color);
+
+ /* draw the outline. */
+ output_line(-offset, outer_color);
+
+ /* draw the transparent border (AA). */
+ if (is_active_nurb != 0) {
+ output_line(offset * -2.0, vec4(colorActiveSpline.rgb, 0.0));
+ }
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl
new file mode 100644
index 00000000000..d3f9deedf0c
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl
@@ -0,0 +1,15 @@
+
+/* Draw Curve Handles */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in int data;
+
+flat out int vertFlag;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vertFlag = data;
+}
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl
new file mode 100644
index 00000000000..85e38ba3b43
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl
@@ -0,0 +1,31 @@
+
+/* Draw Curve Vertices */
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec3 pos;
+in int data;
+
+out vec4 finalColor;
+
+#define VERTEX_ACTIVE (1 << 0)
+#define VERTEX_SELECTED (1 << 1)
+
+void main()
+{
+ if ((data & VERTEX_SELECTED) != 0) {
+ if ((data & VERTEX_ACTIVE) != 0) {
+ finalColor = colorEditMeshActive;
+ }
+ else {
+ finalColor = colorVertexSelect;
+ }
+ }
+ else {
+ finalColor = colorVertex;
+ }
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = sizeVertex * 2.0;
+}
diff --git a/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl
new file mode 100644
index 00000000000..e78462b6915
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl
@@ -0,0 +1,22 @@
+
+flat in int vertFlag;
+
+#define VERTEX_SELECTED (1 << 0)
+#define VERTEX_ACTIVE (1 << 1)
+
+out vec4 FragColor;
+
+void main()
+{
+ /* TODO: vertex size */
+
+ if ((vertFlag & VERTEX_SELECTED) != 0) {
+ FragColor = colorVertexSelect;
+ }
+ else if ((vertFlag & VERTEX_ACTIVE) != 0) {
+ FragColor = colorEditMeshActive;
+ }
+ else {
+ FragColor = colorVertex;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl
new file mode 100644
index 00000000000..0cbc66a2b1f
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl
@@ -0,0 +1,39 @@
+
+/* Draw Lattice Vertices */
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec3 pos;
+in int data;
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out int vertFlag;
+flat out int clipCase;
+
+/* See fragment shader */
+noperspective out vec4 eData1;
+flat out vec4 eData2;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+void main()
+{
+ clipCase = 0;
+
+ vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ /* only vertex position 0 is used */
+ eData1 = eData2 = vec4(1e10);
+ eData2.zw = proj(pPos);
+
+ vertFlag = data;
+
+ gl_PointSize = sizeVertex;
+ gl_Position = pPos;
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl
new file mode 100644
index 00000000000..b37862f2037
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl
@@ -0,0 +1,53 @@
+#define EDGE_EXISTS (1 << 0)
+#define EDGE_ACTIVE (1 << 1)
+#define EDGE_SELECTED (1 << 2)
+#define EDGE_SEAM (1 << 3)
+#define EDGE_SHARP (1 << 4)
+#define EDGE_FREESTYLE (1 << 5)
+#define EDGE_VERTEX_ACTIVE (1 << (0 + 8))
+#define EDGE_VERTEX_SELECTED (1 << (1 + 8))
+#define EDGE_VERTEX_EXISTS (1 << (2 + 8))
+
+#define VERTEX_ACTIVE (1 << 0)
+#define VERTEX_SELECTED (1 << 1)
+#define VERTEX_EXISTS (1 << 2)
+
+#define FACE_ACTIVE (1 << 3)
+#define FACE_SELECTED (1 << 4)
+#define FACE_FREESTYLE (1 << 5)
+
+uniform bool doEdges = true;
+
+vec4 EDIT_MESH_edge_color_outer(int edge_flag, bool face_active, float crease, float bweight)
+{
+ vec4 color = vec4(0.0);
+ color = ((edge_flag & EDGE_FREESTYLE) != 0) ? colorEdgeFreestyle : color;
+ color = ((edge_flag & EDGE_SHARP) != 0) ? colorEdgeSharp : color;
+ color = (crease > 0.0) ? vec4(colorEdgeCrease.rgb, crease) : color;
+ color = (bweight > 0.0) ? vec4(colorEdgeBWeight.rgb, bweight) : color;
+ color = ((edge_flag & EDGE_SEAM) != 0) ? colorEdgeSeam : color;
+
+ if (face_active) {
+ color = colorEditMeshActive;
+ }
+ return color;
+}
+
+vec4 EDIT_MESH_edge_color_inner(int edge_flag, bool face_active)
+{
+ vec4 color = colorWireEdit;
+#ifdef EDGE_SELECTION
+ color = ((edge_flag & EDGE_SELECTED) != 0) ? colorEdgeSelect : color;
+ color = ((edge_flag & EDGE_ACTIVE) != 0) ? colorEditMeshActive : color;
+#else
+ color = (doEdges && (edge_flag & EDGE_SELECTED) != 0) ? colorEdgeSelect : color;
+#endif
+ return color;
+}
+
+vec4 EDIT_MESH_vertex_color(int vertex_flag)
+{
+ vec4 color = colorWireEdit;
+ color = (doEdges && (vertex_flag & (VERTEX_ACTIVE | VERTEX_SELECTED)) != 0) ? colorEdgeSelect : color;
+ return color;
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl
new file mode 100644
index 00000000000..71cc1ccde8d
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl
@@ -0,0 +1,19 @@
+
+flat in int isSelected;
+#ifdef VERTEX_FACING
+flat in float facing;
+#endif
+
+out vec4 FragColor;
+
+void main()
+{
+ if (isSelected != 0)
+ FragColor = colorFaceDot;
+ else
+ FragColor = colorVertex;
+
+#ifdef VERTEX_FACING
+ FragColor.a *= 1.0 - abs(facing) * 0.4;
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl
new file mode 100644
index 00000000000..50f6f3e2cf8
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl
@@ -0,0 +1,31 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec4 norAndFlag;
+
+flat out int isSelected;
+
+#ifdef VERTEX_FACING
+uniform mat4 ProjectionMatrix;
+uniform mat4 ModelViewMatrix;
+uniform mat3 NormalMatrix;
+
+flat out float facing;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ /* Bias Facedot Z position in clipspace. */
+ gl_Position.z -= 0.00035;
+ gl_PointSize = sizeFaceDot;
+ isSelected = int(norAndFlag.w);
+#ifdef VERTEX_FACING
+ vec3 view_normal = normalize(NormalMatrix * norAndFlag.xyz);
+ vec3 view_vec = (ProjectionMatrix[3][3] == 0.0)
+ ? normalize((ModelViewMatrix * vec4(pos, 1.0)).xyz)
+ : vec3(0.0, 0.0, 1.0);
+ facing = dot(view_vec, view_normal);
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl
new file mode 100644
index 00000000000..2e729009a38
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl
@@ -0,0 +1,7 @@
+flat in vec4 faceColor;
+out vec4 FragColor;
+
+void main()
+{
+ FragColor = faceColor;
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl
new file mode 100644
index 00000000000..eb68eb9b0dc
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl
@@ -0,0 +1,28 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform ivec4 dataMask = ivec4(0xFF);
+
+in vec3 pos;
+in ivec4 data;
+
+flat out vec4 faceColor;
+
+#define FACE_ACTIVE (1 << 3)
+#define FACE_SELECTED (1 << 4)
+#define FACE_FREESTYLE (1 << 5)
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ ivec4 data_m = data & dataMask;
+
+ if ((data_m.x & FACE_ACTIVE) != 0)
+ faceColor = colorFaceSelect;
+ else if ((data_m.x & FACE_SELECTED) != 0)
+ faceColor = colorFaceSelect;
+ else if ((data_m.x & FACE_FREESTYLE) != 0)
+ faceColor = colorFaceFreestyle;
+ else
+ faceColor = colorFace;
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl
new file mode 100644
index 00000000000..8d7a653c2fe
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl
@@ -0,0 +1,152 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+uniform float faceAlphaMod;
+uniform float edgeScale;
+uniform bool isXray = false;
+
+flat in vec3 edgesCrease;
+flat in vec3 edgesBweight;
+flat in vec4 faceColor;
+flat in ivec3 flag;
+#ifdef VERTEX_SELECTION
+in vec3 vertexColor;
+#endif
+
+#ifdef EDGE_FIX
+flat in vec2 ssPos[3];
+#else
+in vec3 barycentric;
+#endif
+
+#ifdef VERTEX_FACING
+in float facing;
+#endif
+
+out vec4 FragColor;
+
+/* Vertex flag is shifted and combined with the edge flag */
+#define FACE_ACTIVE_ (FACE_ACTIVE << 8)
+
+#define LARGE_EDGE_SIZE 2.15
+
+/* Enough to visually fill gaps and not enough to mess the AA gradient too much. */
+#define EDGE_FIX_ALPHA 0.67
+
+void distToEdgesAndPoints(out vec3 edges, out vec3 points)
+{
+#ifdef EDGE_FIX
+ vec2 e0 = normalize(ssPos[1] - ssPos[0] + 1e-8);
+ vec2 e1 = normalize(ssPos[2] - ssPos[1] + 1e-8);
+ vec2 e2 = normalize(ssPos[0] - ssPos[2] + 1e-8);
+ e0 = vec2(-e0.y, e0.x);
+ e1 = vec2(-e1.y, e1.x);
+ e2 = vec2(-e2.y, e2.x);
+ vec2 p0 = gl_FragCoord.xy - ssPos[0];
+ vec2 p1 = gl_FragCoord.xy - ssPos[1];
+ vec2 p2 = gl_FragCoord.xy - ssPos[2];
+ edges.z = abs(dot(e0, p0));
+ edges.x = abs(dot(e1, p1));
+ edges.y = abs(dot(e2, p2));
+#else
+ vec3 dx = dFdx(barycentric);
+ vec3 dy = dFdy(barycentric);
+ /* per component derivative */
+ vec2 d0 = vec2(dx.x, dy.x);
+ vec2 d1 = vec2(dx.y, dy.y);
+ vec2 d2 = vec2(dx.z, dy.z);
+ vec3 d = vec3(length(d0), length(d1), length(d2));
+
+ edges = abs(vec3(barycentric / d));
+#endif
+
+#if defined(VERTEX_SELECTION) && defined(EDGE_FIX)
+ points.x = dot(p0, p0);
+ points.y = dot(p1, p1);
+ points.z = dot(p2, p2);
+ points = sqrt(points);
+#else
+ points = vec3(1e10);
+#endif
+}
+
+void colorDist(vec4 color, float dist)
+{
+ FragColor = (dist < 0) ? color : FragColor;
+}
+
+#ifdef ANTI_ALIASING
+void colorDistEdge(vec4 color, float dist)
+{
+ FragColor.rgb *= FragColor.a;
+ FragColor = mix(color, FragColor, clamp(dist, 0.0, 1.0));
+ FragColor.rgb /= max(1e-8, FragColor.a);
+}
+#else
+#define colorDistEdge colorDist
+#endif
+
+void main()
+{
+ vec3 e, p;
+ distToEdgesAndPoints(e, p);
+
+ /* Face */
+ FragColor = faceColor;
+ FragColor.a *= faceAlphaMod;
+
+ /* Edges */
+ float sizeEdgeFinal = sizeEdge * edgeScale;
+
+ for (int v = 0; v < 3; ++v) {
+ if ((flag[v] & EDGE_EXISTS) != 0) {
+ /* Outer large edge */
+ float largeEdge = e[v] - sizeEdgeFinal * LARGE_EDGE_SIZE;
+
+ vec4 large_edge_color = EDIT_MESH_edge_color_outer(flag[v], (flag[0] & FACE_ACTIVE_) != 0, edgesCrease[v], edgesBweight[v]);
+#ifdef EDGE_FIX
+ large_edge_color *= isXray ? 1.0 : EDGE_FIX_ALPHA;
+#endif
+ if (large_edge_color.a != 0.0) {
+ colorDistEdge(large_edge_color, largeEdge);
+ }
+
+ /* Inner thin edge */
+ float innerEdge = e[v] - sizeEdgeFinal;
+#ifdef ANTI_ALIASING
+ innerEdge += 0.4;
+#endif
+
+#ifdef VERTEX_SELECTION
+ vec4 inner_edge_color = vec4(vertexColor, 1.0);
+#else
+ vec4 inner_edge_color = EDIT_MESH_edge_color_inner(flag[v], (flag[0] & FACE_ACTIVE_) != 0);
+#endif
+#ifdef EDGE_FIX
+ inner_edge_color *= isXray ? 1.0 : EDGE_FIX_ALPHA;
+#endif
+ colorDistEdge(inner_edge_color, innerEdge);
+ }
+ }
+
+#if defined(VERTEX_SELECTION) && defined(EDGE_FIX)
+ /* Points */
+ for (int v = 0; v < 3; ++v) {
+ if ((flag[v] & EDGE_VERTEX_EXISTS) != 0) {
+ float size = p[v] - sizeVertex;
+ vec4 point_color = colorVertex;
+ point_color = ((flag[v] & EDGE_VERTEX_SELECTED) != 0) ? colorVertexSelect : point_color;
+ point_color = ((flag[v] & EDGE_VERTEX_ACTIVE) != 0) ? vec4(colorEditMeshActive.xyz, 1.0) : point_color;
+ colorDist(point_color, size);
+ }
+ }
+#endif
+
+#ifdef VERTEX_FACING
+ FragColor.a *= 1.0 - abs(facing) * 0.4;
+#endif
+
+ /* don't write depth if not opaque */
+ if (FragColor.a == 0.0) discard;
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl
new file mode 100644
index 00000000000..1a44e4a9e4f
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl
@@ -0,0 +1,119 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+layout(lines) in;
+layout(triangle_strip, max_vertices=4) out;
+
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec4 pPos[];
+in ivec4 vData[];
+#ifdef VERTEX_FACING
+in float vFacing[];
+#endif
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out vec3 edgesCrease;
+flat out vec3 edgesBweight;
+flat out vec4 faceColor;
+flat out ivec3 flag;
+#ifdef VERTEX_SELECTION
+out vec3 vertexColor;
+#endif
+#ifdef VERTEX_FACING
+out float facing;
+#endif
+
+/* See fragment shader */
+flat out vec2 ssPos[3];
+
+/* Some bugged AMD drivers need these global variables. See T55961 */
+#ifdef VERTEX_SELECTION
+vec3 vertex_color[3];
+#endif
+
+#ifdef VERTEX_FACING
+float v_facing[3];
+#endif
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+void doVertex(int v, vec4 pos)
+{
+#ifdef VERTEX_SELECTION
+ vertexColor = vertex_color[v];
+#endif
+
+#ifdef VERTEX_FACING
+ facing = v_facing[v];
+#endif
+
+ gl_Position = pos;
+
+ EmitVertex();
+}
+
+void main()
+{
+ /* Face */
+ faceColor = vec4(0.0);
+
+ /* Proj Vertex */
+ vec2 pos[2] = vec2[2](proj(pPos[0]), proj(pPos[1]));
+
+ /* little optimization use a vec4 to vectorize
+ * following operations */
+ vec4 dirs1, dirs2;
+
+ /* Edge normalized vector */
+ dirs1.xy = normalize(pos[1] - pos[0]);
+
+ /* perpendicular to dir */
+ dirs1.zw = vec2(-dirs1.y, dirs1.x);
+
+ /* Make it view independent */
+ dirs1 *= sizeEdgeFix / viewportSize.xyxy;
+
+ dirs2 = dirs1;
+
+ /* Perspective */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ dirs1 *= pPos[0].w;
+ dirs2 *= pPos[1].w;
+ }
+
+#ifdef VERTEX_SELECTION
+ vertex_color[0] = EDIT_MESH_vertex_color(vData[0].x).rgb;
+ vertex_color[1] = EDIT_MESH_vertex_color(vData[1].x).rgb;
+#endif
+
+#ifdef VERTEX_FACING
+ /* Weird but some buggy AMD drivers need this. */
+ v_facing[0] = vFacing[0];
+ v_facing[1] = vFacing[1];
+#endif
+
+ /* Edge / Vert data */
+ ssPos[0] = ssPos[2] = pos[0];
+ ssPos[1] = pos[1];
+ flag[0] = flag[2] = (vData[0].x << 8);
+ flag[1] = (vData[1].x << 8);
+ doVertex(0, pPos[0] + vec4( dirs1.zw, 0.0, 0.0));
+ doVertex(0, pPos[0] + vec4(-dirs1.zw, 0.0, 0.0));
+
+ flag[2] |= vData[0].y;
+ edgesCrease[2] = vData[0].z / 255.0;
+ edgesBweight[2] = vData[0].w / 255.0;
+
+ doVertex(1, pPos[1] + vec4( dirs2.zw, 0.0, 0.0));
+ doVertex(1, pPos[1] + vec4(-dirs2.zw, 0.0, 0.0));
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl
new file mode 100644
index 00000000000..a04494d2ec4
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl
@@ -0,0 +1,211 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+layout(triangles) in;
+
+/* To fix the edge artifacts, we render
+ * an outline strip around the screenspace
+ * triangle. Order is important.
+ * TODO diagram
+ */
+layout(triangle_strip, max_vertices=12) out;
+
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+uniform bool isXray = false;
+
+in vec4 pPos[];
+in ivec4 vData[];
+#ifdef VERTEX_FACING
+in float vFacing[];
+#endif
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out vec3 edgesCrease;
+flat out vec3 edgesBweight;
+flat out vec4 faceColor;
+flat out ivec3 flag;
+
+flat out vec2 ssPos[3];
+#ifdef VERTEX_SELECTION
+out vec3 vertexColor;
+#endif
+#ifdef VERTEX_FACING
+out float facing;
+#endif
+
+#ifdef ANTI_ALIASING
+#define Z_OFFSET -0.0005
+#else
+#define Z_OFFSET 0.0
+#endif
+
+/* Some bugged AMD drivers need these global variables. See T55961 */
+#ifdef VERTEX_SELECTION
+vec3 vertex_color[3];
+#endif
+
+#ifdef VERTEX_FACING
+float v_facing[3];
+#endif
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+void doVertex(int v)
+{
+#ifdef VERTEX_SELECTION
+ vertexColor = vertex_color[v];
+#endif
+
+#ifdef VERTEX_FACING
+ facing = v_facing[v];
+#endif
+ gl_Position = pPos[v];
+
+ EmitVertex();
+}
+
+void doVertexOfs(int v, vec2 fixvec)
+{
+#ifdef VERTEX_SELECTION
+ vertexColor = vertex_color[v];
+#endif
+
+#ifdef VERTEX_FACING
+ facing = v_facing[v];
+#endif
+ float z_ofs = Z_OFFSET * ((ProjectionMatrix[3][3] == 0.0) ? 1.0 : 0.0);
+ gl_Position = pPos[v] + vec4(fixvec * pPos[v].w, z_ofs, 0.0);
+
+ EmitVertex();
+}
+
+void mask_edge_flag(int v, ivec3 eflag)
+{
+ int vaf = (v + 1) % 3;
+
+ /* Only shade the edge that we are currently drawing.
+ * (fix corner bleeding) */
+ flag = eflag & ~EDGE_VERTEX_EXISTS;
+ flag[vaf] &= ~EDGE_EXISTS;
+ flag[v] &= ~EDGE_EXISTS;
+}
+
+vec2 compute_fixvec(int i)
+{
+ int i1 = (i + 1) % 3;
+ int i2 = (i + 2) % 3;
+ /* This fix the case when 2 vertices are perfectly aligned
+ * and corner vectors have nowhere to go.
+ * ie: length(cornervec[i]) == 0 */
+ const float epsilon = 1e-2; /* in pixel so not that much */
+ const vec2 bias[3] = vec2[3](
+ vec2( epsilon, epsilon),
+ vec2(-epsilon, epsilon),
+ vec2( 0.0, -epsilon)
+ );
+ vec2 v1 = ssPos[i] + bias[i];
+ vec2 v2 = ssPos[i1] + bias[i1];
+ vec2 v3 = ssPos[i2] + bias[i2];
+ /* Edge normalized vector */
+ vec2 dir = normalize(v2 - v1);
+ vec2 dir2 = normalize(v3 - v1);
+ /* perpendicular to dir */
+ vec2 perp = vec2(-dir.y, dir.x);
+ /* Backface case */
+ if (dot(perp, dir2) > 0.0) {
+ perp = -perp;
+ }
+ /* Make it view independent */
+ return perp * sizeEdgeFix / viewportSize;
+}
+
+void main()
+{
+ /* Edge */
+ ivec3 eflag;
+ for (int v = 0; v < 3; ++v) {
+ eflag[v] = vData[v].y | (vData[v].x << 8);
+ edgesCrease[v] = vData[v].z / 255.0;
+ edgesBweight[v] = vData[v].w / 255.0;
+ }
+
+ /* Face */
+ vec4 fcol;
+ if ((vData[0].x & FACE_ACTIVE) != 0)
+ fcol = colorFaceSelect;
+ else if ((vData[0].x & FACE_SELECTED) != 0)
+ fcol = colorFaceSelect;
+ else if ((vData[0].x & FACE_FREESTYLE) != 0)
+ fcol = colorFaceFreestyle;
+ else
+ fcol = colorFace;
+
+ /* Vertex */
+ ssPos[0] = proj(pPos[0]);
+ ssPos[1] = proj(pPos[1]);
+ ssPos[2] = proj(pPos[2]);
+
+#ifdef VERTEX_SELECTION
+ vertex_color[0] = EDIT_MESH_vertex_color(vData[0].x).rgb;
+ vertex_color[1] = EDIT_MESH_vertex_color(vData[1].x).rgb;
+ vertex_color[2] = EDIT_MESH_vertex_color(vData[2].x).rgb;
+#endif
+
+#ifdef VERTEX_FACING
+ /* Weird but some buggy AMD drivers need this. */
+ v_facing[0] = vFacing[0];
+ v_facing[1] = vFacing[1];
+ v_facing[2] = vFacing[2];
+#endif
+
+ /* Remember that we are assuming the last vertex
+ * of a triangle is the provoking vertex (decide what flat attribs are). */
+
+ if ((eflag[2] & EDGE_EXISTS) != 0) {
+ /* Do 0 -> 1 edge strip */
+ faceColor = vec4(fcol.rgb, 0.0);
+ mask_edge_flag(0, eflag);
+
+ vec2 fixvec = compute_fixvec(0);
+ doVertexOfs(0, fixvec);
+ doVertexOfs(1, fixvec);
+ }
+
+ doVertex(0);
+ doVertex(1);
+
+ /* Do face triangle */
+ faceColor = fcol;
+ flag = (isXray) ? ivec3(0) : eflag;
+ doVertex(2);
+ faceColor.a = 0.0; /* to not let face color bleed */
+
+ if ((eflag[0] & EDGE_EXISTS) != 0) {
+ /* Do 1 -> 2 edge strip */
+ mask_edge_flag(1, eflag);
+
+ vec2 fixvec = compute_fixvec(1);
+ doVertexOfs(1, fixvec);
+ doVertexOfs(2, fixvec);
+ }
+ EndPrimitive();
+
+ if ((eflag[1] & EDGE_EXISTS) != 0) {
+ /* Do 2 -> 0 edge strip */
+ mask_edge_flag(2, eflag);
+ doVertex(2);
+ doVertex(0);
+
+ vec2 fixvec = compute_fixvec(2);
+ doVertexOfs(2, fixvec);
+ doVertexOfs(0, fixvec);
+ EndPrimitive();
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl
new file mode 100644
index 00000000000..3fd4d263aa2
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl
@@ -0,0 +1,7 @@
+
+in vec2 pos;
+
+void main()
+{
+ gl_Position = vec4(pos, 1.0, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl
new file mode 100644
index 00000000000..8f94a105332
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl
@@ -0,0 +1,22 @@
+
+out vec4 FragColor;
+
+uniform sampler2D wireColor;
+uniform sampler2D wireDepth;
+uniform sampler2D sceneDepth;
+uniform float alpha;
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ float wire_depth = texelFetch(wireDepth, uv, 0).r;
+ float scene_depth = texelFetch(sceneDepth, uv, 0).r;
+ vec4 wire_color = texelFetch(wireColor, uv, 0).rgba;
+
+ FragColor = wire_color;
+
+ /* Modulate alpha if occluded */
+ if (wire_depth > scene_depth) {
+ FragColor.a *= alpha;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl
new file mode 100644
index 00000000000..3886213ce49
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl
@@ -0,0 +1,49 @@
+
+uniform mat3 NormalMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat4 ModelViewMatrix;
+uniform mat4 ModelViewProjectionMatrix;
+uniform float ofs = 3e-5;
+
+in vec3 pos;
+in ivec4 data;
+#ifdef VERTEX_FACING
+in vec3 vnor;
+#endif
+
+out vec4 finalColor;
+
+void main()
+{
+ finalColor = colorVertex;
+ finalColor = ((data.x & VERTEX_SELECTED) != 0) ? colorVertexSelect : finalColor;
+ finalColor = ((data.x & VERTEX_ACTIVE) != 0) ? vec4(colorEditMeshActive.xyz, 1.0) : finalColor;
+
+ gl_PointSize = sizeVertex * 2.0;
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_Position.z -= ofs * ((ProjectionMatrix[3][3] == 0.0) ? 1.0 : 0.0);
+
+ /* Make selected and active vertex always on top. */
+ if ((data.x & VERTEX_SELECTED) != 0) {
+ gl_Position.z -= 1e-7;
+ }
+ if ((data.x & VERTEX_ACTIVE) != 0) {
+ gl_Position.z -= 1e-7;
+ }
+
+#ifdef VERTEX_FACING
+ vec4 vPos = ModelViewMatrix * vec4(pos, 1.0);
+ vec3 view_normal = normalize(NormalMatrix * vnor);
+ vec3 view_vec = (ProjectionMatrix[3][3] == 0.0)
+ ? normalize(vPos.xyz)
+ : vec3(0.0, 0.0, 1.0);
+ float facing = dot(view_vec, view_normal);
+
+ finalColor.a *= 1.0 - abs(facing) * 0.4;
+#endif
+
+ if ((data.x & VERTEX_EXISTS) == 0) {
+ gl_Position = vec4(0.0);
+ gl_PointSize = 0.0;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
new file mode 100644
index 00000000000..e4268188e09
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
@@ -0,0 +1,102 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+uniform mat3 NormalMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat4 ModelViewMatrix;
+uniform mat4 ModelViewProjectionMatrix;
+uniform ivec4 dataMask = ivec4(0xFF);
+
+uniform float ofs = 1e-5;
+
+uniform isamplerBuffer dataBuffer;
+
+in vec3 pos;
+#ifdef VERTEX_FACING
+in vec3 vnor;
+#endif
+
+#ifdef EDGE_FIX
+in ivec4 data;
+
+out vec4 pPos;
+out ivec4 vData;
+# ifdef VERTEX_FACING
+out float vFacing;
+# endif
+
+void main()
+{
+ pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ pPos.z -= ofs * ((ProjectionMatrix[3][3] == 0.0) ? 1.0 : 0.0);
+ vData = data & dataMask;
+# ifdef VERTEX_FACING
+ vec4 vpos = ModelViewMatrix * vec4(pos, 1.0);
+ vec3 view_normal = normalize(NormalMatrix * vnor);
+ vec3 view_vec = (ProjectionMatrix[3][3] == 0.0)
+ ? normalize(vpos.xyz)
+ : vec3(0.0, 0.0, 1.0);
+ vFacing = dot(view_vec, view_normal);
+# endif
+}
+
+#else /* EDGE_FIX */
+
+flat out vec3 edgesCrease;
+flat out vec3 edgesBweight;
+flat out vec4 faceColor;
+flat out ivec3 flag;
+# ifdef VERTEX_SELECTION
+out vec3 vertexColor;
+# endif
+# ifdef VERTEX_FACING
+out float facing;
+# endif
+
+out vec3 barycentric;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_Position.z -= ofs * ((ProjectionMatrix[3][3] == 0.0) ? 1.0 : 0.0);
+
+ int v_0 = (gl_VertexID / 3) * 3;
+ int vidx = gl_VertexID % 3;
+ barycentric = vec3(equal(ivec3(0, 1, 2), ivec3(vidx)));
+
+ /* Edge */
+ ivec4 vData[3], data = ivec4(0);
+ ivec3 eflag;
+ for (int v = 0; v < 3; ++v) {
+ data = texelFetch(dataBuffer, v_0 + v);
+ vData[v] = data & dataMask;
+ flag[v] = eflag[v] = vData[v].y | (vData[v].x << 8);
+ edgesCrease[v] = vData[v].z / 255.0;
+ edgesBweight[v] = vData[v].w / 255.0;
+ }
+
+ /* Face */
+ if ((vData[0].x & FACE_ACTIVE) != 0)
+ faceColor = colorFaceSelect;
+ else if ((vData[0].x & FACE_SELECTED) != 0)
+ faceColor = colorFaceSelect;
+ else if ((vData[0].x & FACE_FREESTYLE) != 0)
+ faceColor = colorFaceFreestyle;
+ else
+ faceColor = colorFace;
+
+# ifdef VERTEX_SELECTION
+ vertexColor = EDIT_MESH_vertex_color(vData[vidx].x).rgb;
+# endif
+# ifdef VERTEX_FACING
+ vec4 vPos = ModelViewMatrix * vec4(pos, 1.0);
+ vec3 view_normal = normalize(NormalMatrix * vnor);
+ vec3 view_vec = (ProjectionMatrix[3][3] == 0.0)
+ ? normalize(vPos.xyz)
+ : vec3(0.0, 0.0, 1.0);
+ facing = dot(view_vec, view_normal);
+# endif
+}
+
+#endif
diff --git a/source/blender/draw/modes/shaders/edit_normals_geom.glsl b/source/blender/draw/modes/shaders/edit_normals_geom.glsl
new file mode 100644
index 00000000000..d17823f2f5a
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_normals_geom.glsl
@@ -0,0 +1,15 @@
+
+layout(points) in;
+layout(line_strip, max_vertices=2) out;
+
+flat in vec4 v1[1];
+flat in vec4 v2[1];
+
+void main()
+{
+ gl_Position = v1[0];
+ EmitVertex();
+ gl_Position = v2[0];
+ EmitVertex();
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/edit_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_vert.glsl
new file mode 100644
index 00000000000..3ce7e618511
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_normals_vert.glsl
@@ -0,0 +1,30 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+uniform mat4 ProjectionMatrix;
+uniform float normalSize;
+
+in vec3 pos;
+
+#ifdef LOOP_NORMALS
+in vec3 lnor;
+#define nor lnor
+
+#elif defined(FACE_NORMALS)
+in vec4 norAndFlag;
+#define nor norAndFlag.xyz
+#else
+
+in vec3 vnor;
+#define nor vnor
+#endif
+
+flat out vec4 v1;
+flat out vec4 v2;
+
+void main()
+{
+ v1 = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 n = normalize(NormalMatrix * nor); /* viewspace */
+ v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0);
+}
diff --git a/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl b/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl
new file mode 100644
index 00000000000..10e8805ef55
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screenVecs[3];
+
+/* ---- Instantiated Attribs ---- */
+in float axis; /* position on the axis. [0.0-1.0] is X axis, [1.0-2.0] is Y, etc... */
+in vec2 screenPos;
+
+/* ---- Per instance Attribs ---- */
+in vec3 color;
+in float size;
+in mat4 InstanceModelMatrix;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ float draw_size = 4.0 * size;
+ vec3 chosen_axis = InstanceModelMatrix[int(axis)].xyz;
+ vec3 loc = InstanceModelMatrix[3].xyz;
+ vec3 wpos = loc + chosen_axis * fract(axis) * draw_size;
+ vec3 spos = screenVecs[0].xyz * screenPos.x + screenVecs[1].xyz * screenPos.y;
+ /* Scale uniformly by axis length */
+ spos *= length(chosen_axis) * draw_size;
+
+ gl_Position = ViewProjectionMatrix * vec4(wpos + spos, 1.0);
+
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
new file mode 100644
index 00000000000..e47b28d80c6
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
@@ -0,0 +1,33 @@
+
+flat in vec4 finalColor;
+
+#ifndef USE_WIRE
+in vec2 texCoord_interp;
+#endif
+
+out vec4 fragColor;
+
+#ifndef USE_WIRE
+uniform sampler2D image;
+#endif
+
+uniform int depthMode;
+
+void main()
+{
+#ifdef USE_WIRE
+ fragColor = finalColor;
+#else
+ fragColor = finalColor * texture(image, texCoord_interp);
+#endif
+
+ if (depthMode == DEPTH_BACK) {
+ gl_FragDepth = 0.999999;
+ }
+ else if (depthMode == DEPTH_FRONT) {
+ gl_FragDepth = 0.000001;
+ }
+ else if (depthMode == DEPTH_UNCHANGED) {
+ gl_FragDepth = gl_FragCoord.z;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl
new file mode 100644
index 00000000000..3469e37358e
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl
@@ -0,0 +1,32 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform float aspectX;
+uniform float aspectY;
+uniform float size;
+uniform vec2 offset;
+#ifdef USE_WIRE
+uniform vec3 color;
+#else
+uniform vec4 objectColor;
+#endif
+
+in vec2 texCoord;
+in vec2 pos;
+
+flat out vec4 finalColor;
+
+#ifndef USE_WIRE
+out vec2 texCoord_interp;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(
+ (pos + offset) * (size * vec2(aspectX, aspectY)),
+ 0.0, 1.0);
+#ifdef USE_WIRE
+ finalColor = vec4(color, 1.0);
+#else
+ texCoord_interp = texCoord;
+ finalColor = objectColor;
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl
new file mode 100644
index 00000000000..35a95e809df
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl
@@ -0,0 +1,246 @@
+
+/* Infinite grid
+ * Author: Clément Foucault */
+
+out vec4 FragColor;
+
+uniform mat4 ProjectionMatrix;
+uniform vec3 cameraPos;
+uniform vec3 planeNormal;
+uniform vec3 planeAxes;
+uniform vec3 eye;
+uniform vec4 gridSettings;
+uniform vec2 viewportSize;
+uniform vec4 screenvecs[3];
+uniform float lineKernel = 0.0;
+uniform float gridOneOverLogSubdiv;
+uniform sampler2D depthBuffer;
+
+#define gridDistance gridSettings.x
+#define gridResolution gridSettings.y
+#define gridScale gridSettings.z
+#define gridSubdiv gridSettings.w
+
+uniform int gridFlag;
+
+#define AXIS_X (1 << 0)
+#define AXIS_Y (1 << 1)
+#define AXIS_Z (1 << 2)
+#define GRID (1 << 3)
+#define PLANE_XY (1 << 4)
+#define PLANE_XZ (1 << 5)
+#define PLANE_YZ (1 << 6)
+#define GRID_BACK (1 << 9) /* grid is behind objects */
+
+#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */
+
+/**
+ * We want to know how much a pixel is covered by a line.
+ * We replace the square pixel with acircle of the same area and try to find the intersection area.
+ * The area we search is the circular segment. https://en.wikipedia.org/wiki/Circular_segment
+ * The formula for the area uses inverse trig function and is quite complexe.
+ * Instead, we approximate it by using the smoothstep function and a 1.05 factor to the disc radius.
+ **/
+#define DISC_RADIUS (M_1_SQRTPI * 1.05)
+#define GRID_LINE_SMOOTH_START (0.5 - DISC_RADIUS)
+#define GRID_LINE_SMOOTH_END (0.5 + DISC_RADIUS)
+
+float get_grid(vec2 co, vec2 fwidthCos, float grid_size)
+{
+ float half_size = grid_size / 2.0;
+ /* triangular wave pattern, amplitude is [0, half_size] */
+ vec2 grid_domain = abs(mod(co + half_size, grid_size) - half_size);
+ /* modulate by the absolute rate of change of the coordinates
+ * (make lines have the same width under perspective) */
+ grid_domain /= fwidthCos;
+
+ /* collapse waves */
+ float line_dist = min(grid_domain.x, grid_domain.y);
+
+ return 1.0 - smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, line_dist - lineKernel);
+}
+
+vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size)
+{
+ vec3 axes_domain = abs(co);
+ /* modulate by the absolute rate of change of the coordinates
+ * (make line have the same width under perspective) */
+ axes_domain /= fwidthCos;
+
+ return 1.0 - smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, axes_domain - (line_size + lineKernel));
+}
+
+vec3 get_floor_pos(vec2 uv, out vec3 wPos)
+{
+ vec3 camera_vec, camera_pos, corner_pos;
+ vec3 floored_pos = planeAxes * floor(screenvecs[2].xyz);
+ corner_pos = screenvecs[2].xyz - floored_pos;
+
+ vec3 pixel_pos = corner_pos + uv.x * screenvecs[0].xyz + uv.y * screenvecs[1].xyz;
+
+ /* if perspective */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ camera_pos = cameraPos - floored_pos;
+ camera_vec = normalize(pixel_pos - camera_pos);
+ }
+ else {
+ camera_pos = pixel_pos;
+ camera_vec = normalize(eye);
+ }
+
+ float plane_normal_dot_camera_vec = dot(planeNormal, camera_vec);
+ float p = -dot(planeNormal, camera_pos);
+ if (plane_normal_dot_camera_vec != 0) {
+ p /= plane_normal_dot_camera_vec;
+ }
+ vec3 plane = camera_pos + camera_vec * p;
+
+ /* fix residual imprecision */
+ plane *= planeAxes;
+
+ /* Recover non-offseted world position */
+ wPos = plane + floored_pos;
+
+ return plane;
+}
+
+void main()
+{
+ vec2 sPos = gl_FragCoord.xy / viewportSize; /* Screen [0,1] position */
+
+ /* To reduce artifacts, use a local version of the positions
+ * to compute derivatives since they are not position dependent.
+ * This gets rid of the blocky artifacts. Unfortunately we still
+ * need the world position for the grid to scale properly from the origin. */
+ vec3 gPos, wPos; /* Grid pos., World pos. */
+ gPos = get_floor_pos(sPos, wPos);
+
+ vec3 fwidthPos = fwidth(gPos);
+
+ float dist, fade;
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ vec3 viewvec = cameraPos - wPos;
+ dist = length(viewvec);
+ viewvec /= dist;
+
+ float angle;
+ if ((gridFlag & PLANE_XZ) != 0) {
+ angle = viewvec.y;
+ }
+ else if ((gridFlag & PLANE_YZ) != 0) {
+ angle = viewvec.x;
+ }
+ else {
+ angle = viewvec.z;
+ }
+
+ angle = 1.0 - abs(angle);
+ angle *= angle;
+ fade = 1.0 - angle * angle;
+ fade *= 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance);
+ }
+ else {
+ dist = abs(gl_FragCoord.z * 2.0 - 1.0);
+ fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5);
+ dist = 1.0; /* avoid branch after */
+
+ if ((gridFlag & PLANE_XY) != 0) {
+ float angle = 1.0 - abs(eye.z);
+ dist = 1.0 + angle * 2.0;
+ angle *= angle;
+ fade *= 1.0 - angle * angle;
+ }
+ }
+
+ if ((gridFlag & GRID) != 0) {
+ float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv;
+
+ float blend = fract(-max(grid_res, 0.0));
+ float lvl = floor(grid_res);
+
+ /* from biggest to smallest */
+ float scaleA = gridScale * pow(gridSubdiv, max(lvl - 1.0, 0.0));
+ float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0));
+ float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0));
+
+ vec2 grid_pos, grid_fwidth;
+ if ((gridFlag & PLANE_XZ) != 0) {
+ grid_pos = wPos.xz;
+ grid_fwidth = fwidthPos.xz;
+ }
+ else if ((gridFlag & PLANE_YZ) != 0) {
+ grid_pos = wPos.yz;
+ grid_fwidth = fwidthPos.yz;
+ }
+ else {
+ grid_pos = wPos.xy;
+ grid_fwidth = fwidthPos.xy;
+ }
+
+ float gridA = get_grid(grid_pos, grid_fwidth, scaleA);
+ float gridB = get_grid(grid_pos, grid_fwidth, scaleB);
+ float gridC = get_grid(grid_pos, grid_fwidth, scaleC);
+
+ FragColor = colorGrid;
+ FragColor.a *= gridA * blend;
+ FragColor = mix(FragColor, mix(colorGrid, colorGridEmphasise, blend), gridB);
+ FragColor = mix(FragColor, colorGridEmphasise, gridC);
+ }
+ else {
+ FragColor = vec4(colorGrid.rgb, 0.0);
+ }
+
+ if ((gridFlag & (AXIS_X | AXIS_Y | AXIS_Z)) != 0) {
+ /* Setup axes 'domains' */
+ vec3 axes_dist, axes_fwidth;
+
+ if ((gridFlag & AXIS_X) != 0) {
+ axes_dist.x = dot(wPos.yz, planeAxes.yz);
+ axes_fwidth.x = dot(fwidthPos.yz, planeAxes.yz);
+ }
+ if ((gridFlag & AXIS_Y) != 0) {
+ axes_dist.y = dot(wPos.xz, planeAxes.xz);
+ axes_fwidth.y = dot(fwidthPos.xz, planeAxes.xz);
+ }
+ if ((gridFlag & AXIS_Z) != 0) {
+ axes_dist.z = dot(wPos.xy, planeAxes.xy);
+ axes_fwidth.z = dot(fwidthPos.xy, planeAxes.xy);
+ }
+
+ /* Computing all axes at once using vec3 */
+ vec3 axes = get_axes(axes_dist, axes_fwidth, 0.1);
+
+ if ((gridFlag & AXIS_X) != 0) {
+ FragColor.a = max(FragColor.a, axes.x);
+ FragColor.rgb = (axes.x < 1e-8) ? FragColor.rgb : colorGridAxisX.rgb;
+ }
+ if ((gridFlag & AXIS_Y) != 0) {
+ FragColor.a = max(FragColor.a, axes.y);
+ FragColor.rgb = (axes.y < 1e-8) ? FragColor.rgb : colorGridAxisY.rgb;
+ }
+ if ((gridFlag & AXIS_Z) != 0) {
+ FragColor.a = max(FragColor.a, axes.z);
+ FragColor.rgb = (axes.z < 1e-8) ? FragColor.rgb : colorGridAxisZ.rgb;
+ }
+ }
+
+ /* Add a small bias so the grid will always
+ * be on top of a mesh with the same depth. */
+ float grid_depth = gl_FragCoord.z - 6e-8 - fwidth(gl_FragCoord.z);
+ float scene_depth = texture(depthBuffer, sPos).r;
+ if ((gridFlag & GRID_BACK) != 0) {
+ fade *= (scene_depth == 1.0) ? 1.0 : 0.0;
+ }
+ else {
+ /* Manual, non hard, depth test:
+ * Progressively fade the grid below occluders
+ * (avoids popping visuals due to depth buffer precision) */
+ /* Harder settings tend to flicker more,
+ * but have less "see through" appearance. */
+ const float test_hardness = 1e7;
+ fade *= 1.0 - clamp((grid_depth - scene_depth) * test_hardness, 0.0, 1.0);
+ }
+
+ FragColor.a *= fade;
+}
diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl
new file mode 100644
index 00000000000..a346973a597
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl
@@ -0,0 +1,63 @@
+
+/* Infinite grid
+ * Clément Foucault */
+
+uniform mat4 ViewProjectionMatrix;
+uniform mat4 ProjectionMatrix;
+uniform vec3 cameraPos;
+uniform vec4 gridSettings;
+
+#define gridDistance gridSettings.x
+#define gridResolution gridSettings.y
+#define gridScale gridSettings.z
+#define gridSubdiv gridSettings.w
+
+uniform int gridFlag;
+
+#define PLANE_XY (1 << 4)
+#define PLANE_XZ (1 << 5)
+#define PLANE_YZ (1 << 6)
+#define CLIP_Z_POS (1 << 7)
+#define CLIP_Z_NEG (1 << 8)
+
+in vec3 pos;
+
+void main()
+{
+ vec3 vert_pos, proj_camera_pos;
+
+ /* Project camera pos to the needed plane */
+ if ((gridFlag & PLANE_XY) != 0) {
+ vert_pos = vec3(pos.x, pos.y, 0.0);
+ proj_camera_pos = vec3(cameraPos.x, cameraPos.y, 0.0);
+ }
+ else if ((gridFlag & PLANE_XZ) != 0) {
+ vert_pos = vec3(pos.x, 0.0, pos.y);
+ proj_camera_pos = vec3(cameraPos.x, 0.0, cameraPos.z);
+ }
+ else {
+ vert_pos = vec3(0.0, pos.x, pos.y);
+ proj_camera_pos = vec3(0.0, cameraPos.y, cameraPos.z);
+ }
+
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ vert_pos *= gridDistance * 2.0;
+ }
+ else {
+ float viewdist = 1.0 / min(abs(ProjectionMatrix[0][0]), abs(ProjectionMatrix[1][1]));
+ vert_pos *= viewdist * gridDistance * 2.0;
+ }
+
+ vec3 realPos = proj_camera_pos + vert_pos;
+
+ /* Used for additional Z axis */
+ if ((gridFlag & CLIP_Z_POS) != 0) {
+ realPos.z = max(realPos.z, 0.0);
+ }
+ if ((gridFlag & CLIP_Z_NEG) != 0) {
+ realPos.z = min(-realPos.z, 0.0);
+ }
+
+ gl_Position = ViewProjectionMatrix * vec4(realPos, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl
new file mode 100644
index 00000000000..bcdf5adca55
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl
@@ -0,0 +1,34 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+uniform float sphere_size;
+uniform ivec3 grid_resolution;
+uniform vec3 corner;
+uniform vec3 increment_x;
+uniform vec3 increment_y;
+uniform vec3 increment_z;
+uniform vec3 screen_vecs[2];
+
+uniform int call_id; /* we don't want the builtin callId which would be 0. */
+uniform int baseId;
+
+flat out uint finalId;
+
+void main()
+{
+ vec3 ls_cell_location;
+ /* Keep in sync with update_irradiance_probe */
+ ls_cell_location.z = float(gl_VertexID % grid_resolution.z);
+ ls_cell_location.y = float((gl_VertexID / grid_resolution.z) % grid_resolution.y);
+ ls_cell_location.x = float(gl_VertexID / (grid_resolution.z * grid_resolution.y));
+
+ vec3 ws_cell_location = corner +
+ (increment_x * ls_cell_location.x +
+ increment_y * ls_cell_location.y +
+ increment_z * ls_cell_location.z);
+
+ gl_Position = ViewProjectionMatrix * vec4(ws_cell_location, 1.0);
+ gl_PointSize = 2.0f;
+
+ finalId = uint(baseId + call_id);
+}
diff --git a/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl b/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl
new file mode 100644
index 00000000000..b1c10feb62c
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl
@@ -0,0 +1,34 @@
+
+/* This shader takes a 2D shape, puts it in 3D Object space such that is stays aligned with view,
+ * and scales the shape according to per-instance attributes
+ * Note that if the stiffness is zero, it assumes the scale is directly multiplied by the radius */
+
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screen_vecs[2];
+
+/* ---- Instantiated Attribs ---- */
+in vec2 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat3x4 ScaleTranslationMatrix;
+in float radius;
+in vec3 color;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ mat3 Scamat = mat3(ScaleTranslationMatrix);
+ vec4 world_pos = vec4(
+ ScaleTranslationMatrix[0][3],
+ ScaleTranslationMatrix[1][3],
+ ScaleTranslationMatrix[2][3],
+ 1.0);
+
+ vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y;
+ world_pos.xyz += Scamat * (screen_pos * radius);
+
+ gl_Position = ViewProjectionMatrix * world_pos;
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl
new file mode 100644
index 00000000000..dbf7f411a20
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl
@@ -0,0 +1,88 @@
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform usampler2D outlineId;
+uniform sampler2D outlineDepth;
+uniform sampler2D sceneDepth;
+
+uniform int idOffsets[3];
+
+uniform float alphaOcclu;
+uniform vec2 viewportSize;
+
+vec4 convert_id_to_color(int id)
+{
+ if (id == 0) {
+ return vec4(0.0);
+ }
+ if (id < idOffsets[1]) {
+ return colorActive;
+ }
+ else if (id < idOffsets[2]) {
+ return colorSelect;
+ }
+ else {
+ return colorTransform;
+ }
+}
+
+void main()
+{
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+
+#ifdef GPU_ARB_texture_gather
+ vec2 texel_size = 1.0 / vec2(textureSize(outlineId, 0).xy);
+ vec2 uv = ceil(gl_FragCoord.xy) * texel_size;
+
+ /* Samples order is CW starting from top left. */
+ uvec4 tmp1 = textureGather(outlineId, uv - texel_size);
+ uvec4 tmp2 = textureGather(outlineId, uv);
+
+ uint ref_id = tmp1.y;
+ uvec4 id = uvec4(tmp1.xz, tmp2.xz);
+#else
+ uvec4 id;
+ uint ref_id = texelFetch(outlineId, texel, 0).r;
+ id.x = texelFetchOffset(outlineId, texel, 0, ivec2(-1, 0)).r;
+ id.y = texelFetchOffset(outlineId, texel, 0, ivec2( 0, -1)).r;
+ id.z = texelFetchOffset(outlineId, texel, 0, ivec2( 0, 1)).r;
+ id.w = texelFetchOffset(outlineId, texel, 0, ivec2( 1, 0)).r;
+#endif
+
+#ifdef WIRE
+ /* We want only 2px outlines. */
+ /* TODO optimize, don't sample if we don't need to. */
+ id.xy = uvec2(ref_id);
+#endif
+
+ bool outline = any(notEqual(id, uvec4(ref_id)));
+
+ ivec2 depth_texel = texel;
+ /* If texel is an outline but has no valid id ...
+ * replace id and depth texel by a valid one.
+ * This keeps the outline thickness consistent everywhere. */
+ if (ref_id == 0u && outline) {
+ depth_texel = (id.x != 0u) ? texel + ivec2(-1, 0) : depth_texel;
+ depth_texel = (id.y != 0u) ? texel + ivec2( 0, -1) : depth_texel;
+ depth_texel = (id.z != 0u) ? texel + ivec2( 0, 1) : depth_texel;
+ depth_texel = (id.w != 0u) ? texel + ivec2( 1, 0) : depth_texel;
+
+ ref_id = (id.x != 0u) ? id.x : ref_id;
+ ref_id = (id.y != 0u) ? id.y : ref_id;
+ ref_id = (id.z != 0u) ? id.z : ref_id;
+ ref_id = (id.w != 0u) ? id.w : ref_id;
+ }
+
+ float ref_depth = texelFetch(outlineDepth, depth_texel, 0).r;
+ float scene_depth = texelFetch(sceneDepth, depth_texel, 0).r;
+
+ /* Avoid bad cases of zfighting for occlusion only. */
+ const float epsilon = 3.0 / 8388608.0;
+ bool occluded = (ref_depth > scene_depth + epsilon);
+
+ FragColor = convert_id_to_color(int(ref_id));
+ FragColor.a *= (occluded) ? alphaOcclu : 1.0;
+ FragColor.a = (outline) ? FragColor.a : 0.0;
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl
new file mode 100644
index 00000000000..7e288cde236
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl
@@ -0,0 +1,37 @@
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D outlineColor;
+
+uniform float alpha;
+uniform bool doExpand;
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ FragColor = texelFetch(outlineColor, uv, 0).rgba;
+
+ vec4 color[4];
+ color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2( 1, 0)).rgba;
+ color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, 1)).rgba;
+ color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-1, 0)).rgba;
+ color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, -1)).rgba;
+
+ vec4 values = vec4(color[0].a, color[1].a, color[2].a, color[3].a);
+
+ vec4 tests = step(vec4(1e-6), values); /* (color.a != 0.0) */
+ bvec4 btests = equal(tests, vec4(1.0));
+
+ if (FragColor.a != 0.0) {
+ return;
+ }
+
+ FragColor = (btests.x) ? color[0] : FragColor;
+ FragColor = (btests.y) ? color[1] : FragColor;
+ FragColor = (btests.z) ? color[2] : FragColor;
+ FragColor = (btests.w) ? color[3] : FragColor;
+
+ FragColor.a *= (!doExpand) ? 0.0 : 1.0;
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl
new file mode 100644
index 00000000000..776adb787ad
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl
@@ -0,0 +1,10 @@
+uniform int callId;
+uniform int baseId;
+
+/* using uint because 16bit uint can contain more ids than int. */
+out uint outId;
+
+void main()
+{
+ outId = uint(baseId + callId);
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl
new file mode 100644
index 00000000000..1fa0a9137c0
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl
@@ -0,0 +1,40 @@
+
+layout(lines_adjacency) in;
+layout(line_strip, max_vertices = 2) out;
+
+uniform mat4 ProjectionMatrix;
+
+in vec4 pPos[];
+in vec3 vPos[];
+
+void main()
+{
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+
+ vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0);
+
+ vec3 v10 = vPos[0] - vPos[1];
+ vec3 v12 = vPos[2] - vPos[1];
+ vec3 v13 = vPos[3] - vPos[1];
+
+ vec3 n0 = cross(v12, v10);
+ vec3 n3 = cross(v13, v12);
+
+ float fac0 = dot(view_vec, n0);
+ float fac3 = dot(view_vec, n3);
+
+ /* If both adjacent verts are facing the camera the same way,
+ * then it isn't an outline edge. */
+ if (sign(fac0) == sign(fac3))
+ return;
+
+ /* Don't outline if concave edge. */
+ /* That would hide a lot of non useful edge but it flickers badly.
+ * TODO revisit later... */
+ // if (dot(n0, v13) > 0.01)
+ // return;
+
+ gl_Position = pPos[1]; EmitVertex();
+ gl_Position = pPos[2]; EmitVertex();
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl
new file mode 100644
index 00000000000..ba824a7c007
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl
@@ -0,0 +1,16 @@
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+
+out vec4 pPos;
+out vec3 vPos;
+
+void main()
+{
+ vPos = (ModelViewMatrix * vec4(pos, 1.0)).xyz;
+ pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ /* Small bias to always be on top of the geom. */
+ pPos.z -= 1e-3;
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl
new file mode 100644
index 00000000000..964ebe72e81
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl
@@ -0,0 +1,27 @@
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D outlineBluredColor;
+uniform vec2 rcpDimensions;
+
+void main()
+{
+#ifdef USE_FXAA
+ float aa_alpha = FxaaPixelShader(
+ uvcoordsvar.st,
+ outlineBluredColor,
+ rcpDimensions,
+ 1.0,
+ 0.166,
+ 0.0833
+ ).r;
+#endif
+
+ FragColor = texture(outlineBluredColor, uvcoordsvar.st).rgba;
+
+#ifdef USE_FXAA
+ FragColor.a = aa_alpha;
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl b/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl
new file mode 100644
index 00000000000..e8bf7884701
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl
@@ -0,0 +1,52 @@
+
+uniform vec3 color;
+uniform vec3 outlineColor;
+uniform sampler1D ramp;
+
+in vec4 radii;
+flat in float finalVal;
+
+out vec4 fragColor;
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure outline color
+// --- 2 ---
+// smooth transition
+// --- 3 ---
+// pure point color
+// ...
+// dist = 0 at center of point
+
+ float midStroke = 0.5 * (radii[1] + radii[2]);
+
+ if (dist > midStroke) {
+ if (finalVal < 0.0) {
+ fragColor.rgb = outlineColor;
+ }
+ else {
+ fragColor.rgb = texture(ramp, finalVal).rgb;
+ }
+
+ fragColor.a = mix(1.0, 0.0, smoothstep(radii[1], radii[0], dist));
+ }
+ else {
+ if (finalVal < 0.0) {
+ fragColor.rgb = mix(color, outlineColor, smoothstep(radii[3], radii[2], dist));
+ }
+ else {
+ fragColor.rgb = texture(ramp, finalVal).rgb;
+ }
+
+ fragColor.a = 1.0;
+ }
+
+ if (fragColor.a == 0.0) {
+ discard;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl
new file mode 100644
index 00000000000..6dfc212a776
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl
@@ -0,0 +1,35 @@
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform float pixel_size;
+uniform float size;
+
+in vec3 pos;
+in float val;
+
+out vec4 radii;
+flat out float finalVal;
+
+void main() {
+ gl_Position = ModelViewMatrix * vec4(pos, 1.0);
+
+ float psize = (ProjectionMatrix[3][3] == 0.0) ? (size / (-gl_Position.z * pixel_size)) : (size / pixel_size);
+
+ gl_PointSize = psize;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * psize;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - 1.0;
+ radii[3] = radius - 2.0;
+
+ // convert to PointCoord units
+ radii /= psize;
+
+ gl_Position = ProjectionMatrix * gl_Position;
+
+ finalVal = val;
+}
diff --git a/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl
new file mode 100644
index 00000000000..54ae319307a
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl
@@ -0,0 +1,56 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ViewProjectionMatrix;
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform int screen_space;
+uniform float draw_size;
+uniform vec3 color;
+uniform sampler1D ramp;
+
+in vec3 pos;
+in vec4 rot;
+in float val;
+in vec3 inst_pos;
+in int axis;
+
+flat out vec4 finalColor;
+
+vec3 rotate(vec3 vec, vec4 quat)
+{
+ /* The quaternion representation here stores the w component in the first index */
+ return vec + 2.0 * cross(quat.yzw, cross(quat.yzw, vec) + quat.x * vec);
+}
+
+void main()
+{
+ if (screen_space == 1) {
+ gl_Position = ModelViewMatrix * vec4(pos, 1.0) + vec4(inst_pos * draw_size, 0.0);
+ gl_Position = ProjectionMatrix * gl_Position;
+ }
+ else {
+ float size = draw_size;
+
+ if (axis > -1) {
+ size *= 2;
+ }
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos + rotate(inst_pos * size, rot), 1.0);
+ }
+
+#ifdef USE_AXIS
+ if (axis == 0)
+ finalColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (axis == 1)
+ finalColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ finalColor = vec4(0.0, 0.0, 1.0, 1.0);
+#else
+ if (val < 0.0) {
+ finalColor = vec4(color, 1.0);
+ }
+ else {
+ finalColor = vec4(texture(ramp, val).rgb, 1.0);
+ }
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl b/source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl
new file mode 100644
index 00000000000..5b0ad7863d1
--- /dev/null
+++ b/source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl
@@ -0,0 +1,10 @@
+uniform vec3 color_towards = vec3(0.0, 0.0, 1.0);
+uniform vec3 color_outwards = vec3(1.0, 0.0, 0.0);
+
+out vec4 fragColor;
+
+
+void main()
+{
+ fragColor = vec4(gl_FrontFacing ? color_towards: color_outwards, 0.7);
+}
diff --git a/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl
new file mode 100644
index 00000000000..d8a72f28eee
--- /dev/null
+++ b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl
@@ -0,0 +1,7 @@
+uniform mat4 ModelViewProjectionMatrix;
+in vec3 pos;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl
new file mode 100644
index 00000000000..69af4858a48
--- /dev/null
+++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl
@@ -0,0 +1,57 @@
+#ifndef SELECT_EDGES
+uniform vec3 wireColor;
+uniform vec3 rimColor;
+
+in float facing;
+in vec3 barycentric;
+
+# ifdef LIGHT_EDGES
+flat in vec3 edgeSharpness;
+# endif
+
+out vec4 fragColor;
+#endif
+
+float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); }
+float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); }
+
+/* In pixels */
+uniform float wireSize = 0.0; /* Expands the core of the wire (part that is 100% wire color) */
+const float wire_smooth = 1.2; /* Smoothing distance after the 100% core. */
+
+/* Alpha constants could be exposed in the future. */
+const float front_alpha = 0.35;
+const float rim_alpha = 0.75;
+
+void main()
+{
+#ifndef SELECT_EDGES
+ vec3 dx = dFdx(barycentric);
+ vec3 dy = dFdy(barycentric);
+ vec3 d = vec3(
+ length(vec2(dx.x, dy.x)),
+ length(vec2(dx.y, dy.y)),
+ length(vec2(dx.z, dy.z))
+ );
+ vec3 dist_to_edge = barycentric / d;
+
+# ifdef LIGHT_EDGES
+ vec3 fac = abs(dist_to_edge);
+# else
+ float fac = min_v3(abs(dist_to_edge));
+# endif
+
+ fac = smoothstep(wireSize + wire_smooth, wireSize, fac);
+
+ float facing_clamped = clamp((gl_FrontFacing) ? facing : -facing, 0.0, 1.0);
+
+ vec3 final_front_col = mix(rimColor, wireColor, 0.05);
+ fragColor = mix(vec4(rimColor, rim_alpha), vec4(final_front_col, front_alpha), facing_clamped);
+
+# ifdef LIGHT_EDGES
+ fragColor.a *= max_v3(fac * edgeSharpness);
+# else
+ fragColor.a *= fac;
+# endif
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl
new file mode 100644
index 00000000000..8abb6ecc737
--- /dev/null
+++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl
@@ -0,0 +1,127 @@
+
+/* This shader is only used for intel GPU where the Geom shader is faster
+ * than doing everything thrice in the vertex shader. */
+
+layout(triangles) in;
+#ifdef SELECT_EDGES
+layout(line_strip, max_vertices = 6) out;
+#else
+layout(triangle_strip, max_vertices = 3) out;
+#endif
+
+uniform vec2 wireStepParam;
+
+in vec2 ssPos[];
+in float facingOut[];
+
+#ifndef SELECT_EDGES
+out vec3 barycentric;
+out float facing;
+#endif
+
+#ifdef LIGHT_EDGES
+in vec3 obPos[];
+in vec3 vNor[];
+in float forceEdge[];
+
+# ifndef SELECT_EDGES
+flat out vec3 edgeSharpness;
+# endif
+#endif
+
+#define NO_EDGE vec3(10000.0);
+
+vec3 get_edge_normal(vec3 n1, vec3 n2, vec3 edge)
+{
+ edge = normalize(edge);
+ vec3 n = n1 + n2;
+ float p = dot(edge, n);
+ return normalize(n - p * edge);
+}
+
+float get_edge_sharpness(vec3 fnor, vec3 vnor)
+{
+ float sharpness = abs(dot(fnor, vnor));
+ return smoothstep(wireStepParam.x, wireStepParam.y, sharpness);
+}
+
+vec3 get_barycentric(bvec3 do_edge, const int v)
+{
+ int v_n = v;
+ int v_n1 = (v + 1) % 3;
+ int v_n2 = (v + 2) % 3;
+ vec3 bary;
+ bary[v_n] = do_edge[v_n] ? 0.0 : 1.0;
+ bary[v_n1] = 1.0;
+ bary[v_n2] = do_edge[v_n2] ? 0.0 : 1.0;
+ return bary;
+}
+
+void main(void)
+{
+ vec3 facings = vec3(facingOut[0], facingOut[1], facingOut[2]);
+ bvec3 do_edge = greaterThan(abs(facings), vec3(1.0));
+ facings = fract(facings) - clamp(-sign(facings), 0.0, 1.0);
+
+#ifdef SELECT_EDGES
+ vec3 edgeSharpness;
+#endif
+
+#ifdef LIGHT_EDGES
+ vec3 edges[3];
+ edges[0] = obPos[1] - obPos[0];
+ edges[1] = obPos[2] - obPos[1];
+ edges[2] = obPos[0] - obPos[2];
+ vec3 fnor = normalize(cross(edges[0], -edges[2]));
+
+ edgeSharpness.x = get_edge_sharpness(fnor, get_edge_normal(vNor[0], vNor[1], edges[0]));
+ edgeSharpness.y = get_edge_sharpness(fnor, get_edge_normal(vNor[1], vNor[2], edges[1]));
+ edgeSharpness.z = get_edge_sharpness(fnor, get_edge_normal(vNor[2], vNor[0], edges[2]));
+ edgeSharpness.x = (forceEdge[0] == 1.0) ? 1.0 : edgeSharpness.x;
+ edgeSharpness.y = (forceEdge[1] == 1.0) ? 1.0 : edgeSharpness.y;
+ edgeSharpness.z = (forceEdge[2] == 1.0) ? 1.0 : edgeSharpness.z;
+#endif
+
+#ifdef SELECT_EDGES
+ const float edge_select_threshold = 0.3;
+ if (edgeSharpness.x > edge_select_threshold) {
+ gl_Position = gl_in[0].gl_Position;
+ EmitVertex();
+ gl_Position = gl_in[1].gl_Position;
+ EmitVertex();
+ EndPrimitive();
+ }
+
+ if (edgeSharpness.y > edge_select_threshold) {
+ gl_Position = gl_in[1].gl_Position;
+ EmitVertex();
+ gl_Position = gl_in[2].gl_Position;
+ EmitVertex();
+ EndPrimitive();
+ }
+
+ if (edgeSharpness.z > edge_select_threshold) {
+ gl_Position = gl_in[2].gl_Position;
+ EmitVertex();
+ gl_Position = gl_in[0].gl_Position;
+ EmitVertex();
+ EndPrimitive();
+ }
+#else
+ barycentric = get_barycentric(do_edge, 0);
+ gl_Position = gl_in[0].gl_Position;
+ facing = facings.x;
+ EmitVertex();
+
+ barycentric = get_barycentric(do_edge, 1);
+ gl_Position = gl_in[1].gl_Position;
+ facing = facings.y;
+ EmitVertex();
+
+ barycentric = get_barycentric(do_edge, 2);
+ gl_Position = gl_in[2].gl_Position;
+ facing = facings.z;
+ EmitVertex();
+ EndPrimitive();
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
new file mode 100644
index 00000000000..828bc551cad
--- /dev/null
+++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
@@ -0,0 +1,177 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+uniform vec2 wireStepParam;
+uniform float nearDist;
+
+uniform samplerBuffer vertData;
+uniform usamplerBuffer faceIds;
+
+#ifdef USE_SCULPT
+in vec3 pos;
+in vec3 nor;
+#endif
+
+float short_to_unit_float(uint s)
+{
+ int value = int(s) & 0x7FFF;
+ if ((s & 0x8000u) != 0u) {
+ value |= ~0x7FFF;
+ }
+ return float(value) / float(0x7FFF);
+}
+
+vec3 get_vertex_nor(uint id)
+{
+ int v_id = int(id) * 5; /* See vertex format for explanation. */
+ /* Fetch compressed normal as float and unpack them. */
+ vec2 data;
+ data.x = texelFetch(vertData, v_id + 3).r;
+ data.y = texelFetch(vertData, v_id + 4).r;
+
+ uvec2 udata = floatBitsToUint(data);
+
+ vec3 nor;
+ nor.x = short_to_unit_float(udata.x & 0xFFFFu);
+ nor.y = short_to_unit_float(udata.x >> 16u);
+ nor.z = short_to_unit_float(udata.y & 0xFFFFu);
+ return nor;
+}
+
+vec3 get_vertex_pos(uint id)
+{
+ int v_id = int(id) * 5; /* See vertex format for explanation. */
+ vec3 pos;
+ pos.x = texelFetch(vertData, v_id).r;
+ pos.y = texelFetch(vertData, v_id + 1).r;
+ pos.z = texelFetch(vertData, v_id + 2).r;
+ return pos;
+}
+
+vec3 get_edge_normal(vec3 n1, vec3 n2, vec3 edge)
+{
+ edge = normalize(edge);
+ vec3 n = n1 + n2;
+ float p = dot(edge, n);
+ return normalize(n - p * edge);
+}
+
+float get_edge_sharpness(vec3 fnor, vec3 vnor)
+{
+ float sharpness = abs(dot(fnor, vnor));
+ return smoothstep(wireStepParam.x, wireStepParam.y, sharpness);
+}
+
+#ifdef USE_GEOM_SHADER
+
+# ifdef LIGHT_EDGES
+out vec3 obPos;
+out vec3 vNor;
+out float forceEdge;
+# endif
+out float facingOut; /* abs(facing) > 1.0 if we do edge */
+
+void main()
+{
+# ifndef USE_SCULPT
+ uint v_id = texelFetch(faceIds, gl_VertexID).r;
+
+ bool do_edge = (v_id & (1u << 30u)) != 0u;
+ bool force_edge = (v_id & (1u << 31u)) != 0u;
+ v_id = (v_id << 2u) >> 2u;
+
+ vec3 pos = get_vertex_pos(v_id);
+ vec3 nor = get_vertex_nor(v_id);
+# else
+ const bool do_edge = true;
+ const bool force_edge = false;
+# endif
+
+ facingOut = normalize(NormalMatrix * nor).z;
+ facingOut += (do_edge) ? ((facingOut > 0.0) ? 2.0 : -2.0) : 0.0;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+# ifdef LIGHT_EDGES
+ obPos = pos;
+ vNor = nor;
+ forceEdge = float(force_edge); /* meh, could try to also encode it in facingOut */
+# endif
+}
+
+#else /* USE_GEOM_SHADER */
+
+# ifdef LIGHT_EDGES
+flat out vec3 edgeSharpness;
+# endif
+out float facing;
+out vec3 barycentric;
+
+void main()
+{
+ int v_0 = (gl_VertexID / 3) * 3;
+ int v_n = gl_VertexID % 3;
+ int v_n1 = (gl_VertexID + 1) % 3;
+ int v_n2 = (gl_VertexID + 2) % 3;
+
+ /* Getting the same positions for each of the 3 verts. */
+ uvec3 v_id;
+ v_id.x = texelFetch(faceIds, v_0).r;
+ v_id.y = texelFetch(faceIds, v_0 + 1).r;
+ v_id.z = texelFetch(faceIds, v_0 + 2).r;
+
+ bvec3 do_edge, force_edge;
+ do_edge.x = (v_id.x & (1u << 30u)) != 0u;
+ do_edge.y = (v_id.y & (1u << 30u)) != 0u;
+ do_edge.z = (v_id.z & (1u << 30u)) != 0u;
+ force_edge.x = (v_id.x & (1u << 31u)) != 0u;
+ force_edge.y = (v_id.y & (1u << 31u)) != 0u;
+ force_edge.z = (v_id.z & (1u << 31u)) != 0u;
+ v_id = (v_id << 2u) >> 2u;
+
+ vec3 pos[3];
+ vec4 p_pos[3];
+
+ pos[v_n] = get_vertex_pos(v_id[v_n]);
+ gl_Position = p_pos[v_n] = ModelViewProjectionMatrix * vec4(pos[v_n], 1.0);
+
+ bvec3 bary = equal(ivec3(0, 1, 2), ivec3(v_n1));
+ /* This is equivalent to component wise : (do_edge ? bary : 1.0) */
+ barycentric = vec3(lessThanEqual(ivec3(do_edge), ivec3(bary)));
+
+# ifndef LIGHT_EDGES
+ vec3 nor = get_vertex_nor(v_id[v_n]);
+# else
+ p_pos[v_n1] = ModelViewProjectionMatrix * vec4(pos[v_n1], 1.0);
+ p_pos[v_n2] = ModelViewProjectionMatrix * vec4(pos[v_n2], 1.0);
+
+ pos[v_n1] = get_vertex_pos(v_id[v_n1]);
+ pos[v_n2] = get_vertex_pos(v_id[v_n2]);
+
+ vec3 edges[3];
+ edges[0] = pos[1] - pos[0];
+ edges[1] = pos[2] - pos[1];
+ edges[2] = pos[0] - pos[2];
+ vec3 fnor = normalize(cross(edges[0], -edges[2]));
+
+ vec3 nors[3];
+ nors[0] = get_vertex_nor(v_id.x);
+ nors[1] = get_vertex_nor(v_id.y);
+ nors[2] = get_vertex_nor(v_id.z);
+ edgeSharpness.x = get_edge_sharpness(fnor, get_edge_normal(nors[0], nors[1], edges[0]));
+ edgeSharpness.y = get_edge_sharpness(fnor, get_edge_normal(nors[1], nors[2], edges[1]));
+ edgeSharpness.z = get_edge_sharpness(fnor, get_edge_normal(nors[2], nors[0], edges[2]));
+ edgeSharpness.x = force_edge.x ? 1.0 : edgeSharpness.x;
+ edgeSharpness.y = force_edge.y ? 1.0 : edgeSharpness.y;
+ edgeSharpness.z = force_edge.z ? 1.0 : edgeSharpness.z;
+
+ vec3 nor = nors[v_n];
+# endif
+
+ facing = normalize(NormalMatrix * nor).z;
+}
+
+#endif /* USE_GEOM_SHADER */
diff --git a/source/blender/draw/modes/shaders/paint_texture_frag.glsl b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
new file mode 100644
index 00000000000..4305e20ce7b
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
@@ -0,0 +1,11 @@
+
+in vec2 uv_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+uniform float alpha = 1.0;
+
+void main()
+{
+ fragColor = vec4(texture(image, uv_interp).rgb, alpha);
+}
diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
new file mode 100644
index 00000000000..4ce12e048fa
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
@@ -0,0 +1,15 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 uv;
+in vec3 pos;
+
+out vec2 uv_interp;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ uv_interp = uv;
+
+}
diff --git a/source/blender/draw/modes/shaders/paint_vert_frag.glsl b/source/blender/draw/modes/shaders/paint_vert_frag.glsl
new file mode 100644
index 00000000000..5ea8c11ff9a
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_vert_frag.glsl
@@ -0,0 +1,26 @@
+
+flat in int finalFlag;
+out vec4 fragColor;
+
+#define VERTEX_SELECTED (1 << 0)
+#define VERTEX_HIDE (1 << 4)
+
+void main()
+{
+ if (bool(finalFlag & VERTEX_HIDE)) {
+ discard;
+ }
+
+ vec2 centered = gl_PointCoord - vec2(0.5);
+ float dist_squared = dot(centered, centered);
+ const float rad_squared = 0.25;
+ const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0);
+ const vec4 colUnsel = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // round point with jaggy edges
+ if (dist_squared > rad_squared) {
+ discard;
+ }
+
+ fragColor = bool(finalFlag & VERTEX_SELECTED) ? colSel : colUnsel;
+}
diff --git a/source/blender/draw/modes/shaders/paint_vertex_frag.glsl b/source/blender/draw/modes/shaders/paint_vertex_frag.glsl
new file mode 100644
index 00000000000..3ff264a5e22
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_vertex_frag.glsl
@@ -0,0 +1,18 @@
+
+in vec3 finalColor;
+
+out vec4 fragColor;
+uniform float white_factor = 1.0;
+
+vec3 linear_to_srgb_attrib(vec3 c) {
+ c = max(c, vec3(0.0));
+ vec3 c1 = c * 12.92;
+ vec3 c2 = 1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055;
+ return mix(c1, c2, step(vec3(0.0031308), c));
+}
+
+void main()
+{
+ fragColor.rgb = mix(linear_to_srgb_attrib(finalColor), vec3(1.0), white_factor);
+ fragColor.a = 1.0;
+}
diff --git a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
new file mode 100644
index 00000000000..178f77c6b9c
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
@@ -0,0 +1,21 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec3 color;
+
+out vec3 finalColor;
+
+vec3 srgb_to_linear_attrib(vec3 c) {
+ c = max(c, vec3(0.0));
+ vec3 c1 = c * (1.0 / 12.92);
+ vec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4));
+ return mix(c1, c2, step(vec3(0.04045), c));
+}
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ finalColor = srgb_to_linear_attrib(color);
+}
diff --git a/source/blender/draw/modes/shaders/paint_weight_frag.glsl b/source/blender/draw/modes/shaders/paint_weight_frag.glsl
new file mode 100644
index 00000000000..faa36f5535e
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_weight_frag.glsl
@@ -0,0 +1,97 @@
+
+in vec2 weight_interp; /* (weight, alert) */
+
+out vec4 fragColor;
+
+uniform float opacity = 1.0;
+uniform sampler1D colorramp;
+
+uniform bool drawContours = false;
+
+float contours(float value, float steps, float width_px, float max_rel_width, float gradient)
+{
+ /* Minimum visible and minimum full strength line width in screen space for fade out. */
+ const float min_width_px = 1.3, fade_width_px = 2.3;
+ /* Line is thinner towards the increase in the weight gradient by this factor. */
+ const float hi_bias = 2.0;
+
+ /* Don't draw lines at 0 or 1. */
+ float rel_value = value * steps;
+
+ if (rel_value < 0.5 || rel_value > steps - 0.5)
+ return 0.0;
+
+ /* Check if completely invisible due to fade out. */
+ float rel_gradient = gradient * steps;
+ float rel_min_width = min_width_px * rel_gradient;
+
+ if (max_rel_width <= rel_min_width)
+ return 0.0;
+
+ /* Main shape of the line, accounting for width bias and maximum weight space width. */
+ float rel_width = width_px * rel_gradient;
+
+ float offset = fract(rel_value + 0.5) - 0.5;
+
+ float base_alpha = 1.0 - max(offset * hi_bias, -offset) / min(max_rel_width, rel_width);
+
+ /* Line fadeout when too thin in screen space. */
+ float rel_fade_width = fade_width_px * rel_gradient;
+
+ float fade_alpha = (max_rel_width - rel_min_width) / (rel_fade_width - rel_min_width);
+
+ return clamp(base_alpha, 0.0, 1.0) * clamp(fade_alpha, 0.0, 1.0);
+}
+
+vec4 contour_grid(float weight, float weight_gradient)
+{
+ /* Fade away when the gradient is too low to avoid big fills and noise. */
+ float flt_eps = max(1e-8, 1e-6 * weight);
+
+ if (weight_gradient <= flt_eps)
+ return vec4(0.0);
+
+ /* Three levels of grid lines */
+ float grid10 = contours(weight, 10.0, 5.0, 0.3, weight_gradient);
+ float grid100 = contours(weight, 100.0, 3.5, 0.35, weight_gradient) * 0.6;
+ float grid1000 = contours(weight, 1000.0, 2.5, 0.4, weight_gradient) * 0.25;
+
+ /* White lines for 0.1 and 0.01, and black for 0.001 */
+ vec4 grid = vec4(1.0) * max(grid10, grid100);
+
+ grid.a = max(grid.a, grid1000);
+
+ return grid * clamp((weight_gradient - flt_eps) / flt_eps, 0.0, 1.0);
+}
+
+void main()
+{
+ float alert = weight_interp.y;
+ vec4 color;
+
+ /* Missing vertex group alert color. Uniform in practice. */
+ if (alert > 1.1) {
+ color = colorVertexMissingData;
+ }
+ /* Weights are available */
+ else {
+ float weight = weight_interp.x;
+ vec4 weight_color = texture(colorramp, weight, 0);
+
+ /* Contour display */
+ if (drawContours) {
+ /* This must be executed uniformly for all fragments */
+ float weight_gradient = length(vec2(dFdx(weight), dFdy(weight)));
+
+ vec4 grid = contour_grid(weight, weight_gradient);
+
+ weight_color = grid + weight_color * (1 - grid.a);
+ }
+
+ /* Zero weight alert color. Nonlinear blend to reduce impact. */
+ color = mix(weight_color, colorVertexUnreferenced, alert * alert);
+ }
+
+ /* mix with 1.0 -> is like opacity when using multiply blend mode */
+ fragColor = vec4(mix(vec3(1.0), color.rgb, opacity), 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/paint_weight_vert.glsl b/source/blender/draw/modes/shaders/paint_weight_vert.glsl
new file mode 100644
index 00000000000..78a3695c82c
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_weight_vert.glsl
@@ -0,0 +1,15 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in float weight;
+in vec3 pos;
+
+out vec2 weight_interp; /* (weight, alert) */
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ /* Separate actual weight and alerts for independent interpolation */
+ weight_interp = max(vec2(weight, -weight), 0.0);
+}
diff --git a/source/blender/draw/modes/shaders/paint_wire_frag.glsl b/source/blender/draw/modes/shaders/paint_wire_frag.glsl
new file mode 100644
index 00000000000..c5d6198fc21
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_wire_frag.glsl
@@ -0,0 +1,25 @@
+
+flat in int finalFlag;
+out vec4 fragColor;
+
+#define VERTEX_SELECTED (1 << 0)
+#define VERTEX_HIDE (1 << 4)
+
+void main()
+{
+ if (bool(finalFlag & VERTEX_HIDE)) {
+ discard;
+ }
+
+ /* Apply depth offset by taking slope and distance into account. */
+ gl_FragDepth = gl_FragCoord.z - mix(exp2(-10), exp2(-23), gl_FragCoord.z) - 2.0 * fwidth(gl_FragCoord.z);
+
+#ifdef VERTEX_MODE
+ vec4 colSel = colorEdgeSelect;
+ colSel.rgb = clamp(colSel.rgb - 0.2, 0.0, 1.0);
+#else
+ const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0);
+#endif
+
+ fragColor = bool(finalFlag & VERTEX_SELECTED) ? colSel : colorWire;
+}
diff --git a/source/blender/draw/modes/shaders/paint_wire_vert.glsl b/source/blender/draw/modes/shaders/paint_wire_vert.glsl
new file mode 100644
index 00000000000..253c21745e2
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_wire_vert.glsl
@@ -0,0 +1,14 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in int data;
+
+flat out int finalFlag;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ finalFlag = data;
+}
diff --git a/source/blender/draw/modes/shaders/particle_strand_frag.glsl b/source/blender/draw/modes/shaders/particle_strand_frag.glsl
new file mode 100644
index 00000000000..8bb213dbd30
--- /dev/null
+++ b/source/blender/draw/modes/shaders/particle_strand_frag.glsl
@@ -0,0 +1,23 @@
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec4 finalColor;
+#ifdef USE_POINTS
+in vec2 radii;
+#endif
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor;
+
+#ifdef USE_POINTS
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+ fragColor.a = mix(finalColor.a, 0.0, smoothstep(radii[1], radii[0], dist));
+
+ if (fragColor.a == 0.0) {
+ discard;
+ }
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/particle_strand_vert.glsl b/source/blender/draw/modes/shaders/particle_strand_vert.glsl
new file mode 100644
index 00000000000..9db62a581cb
--- /dev/null
+++ b/source/blender/draw/modes/shaders/particle_strand_vert.glsl
@@ -0,0 +1,73 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in float color;
+
+out vec4 finalColor;
+#ifdef USE_POINTS
+out vec2 radii;
+#endif
+
+vec3 weight_to_rgb(float weight)
+{
+ vec3 r_rgb;
+ float blend = ((weight / 2.0) + 0.5);
+
+ if (weight <= 0.25) { /* blue->cyan */
+ r_rgb[0] = 0.0;
+ r_rgb[1] = blend * weight * 4.0;
+ r_rgb[2] = blend;
+ }
+ else if (weight <= 0.50) { /* cyan->green */
+ r_rgb[0] = 0.0;
+ r_rgb[1] = blend;
+ r_rgb[2] = blend * (1.0 - ((weight - 0.25) * 4.0));
+ }
+ else if (weight <= 0.75) { /* green->yellow */
+ r_rgb[0] = blend * ((weight - 0.50) * 4.0);
+ r_rgb[1] = blend;
+ r_rgb[2] = 0.0;
+ }
+ else if (weight <= 1.0) { /* yellow->red */
+ r_rgb[0] = blend;
+ r_rgb[1] = blend * (1.0 - ((weight - 0.75) * 4.0));
+ r_rgb[2] = 0.0;
+ }
+ else {
+ /* exceptional value, unclamped or nan,
+ * avoid uninitialized memory use */
+ r_rgb[0] = 1.0;
+ r_rgb[1] = 0.0;
+ r_rgb[2] = 1.0;
+ }
+
+ return r_rgb;
+}
+
+#define DECOMPRESS_RANGE 1.0039
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+#ifdef USE_WEIGHT
+ finalColor = vec4(weight_to_rgb(color * DECOMPRESS_RANGE), 1.0);
+#else
+ finalColor = mix(colorWire, colorEdgeSelect, color);
+#endif
+
+#ifdef USE_POINTS
+ gl_PointSize = sizeVertex;
+
+ /* calculate concentric radii in pixels */
+ float radius = 0.5 * sizeVertex;
+
+ /* start at the outside and progress toward the center */
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+
+ /* convert to PointCoord units */
+ radii /= sizeVertex;
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl b/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl
new file mode 100644
index 00000000000..e76d21eb43a
--- /dev/null
+++ b/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl
@@ -0,0 +1,19 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in float msk;
+
+#ifdef SHADE_FLAT
+flat out vec4 finalColor;
+#else
+out vec4 finalColor;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ float mask = 1.0 - msk * 0.75;
+ finalColor = vec4(mask, mask, mask, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/volume_velocity_vert.glsl b/source/blender/draw/modes/shaders/volume_velocity_vert.glsl
new file mode 100644
index 00000000000..574c434920e
--- /dev/null
+++ b/source/blender/draw/modes/shaders/volume_velocity_vert.glsl
@@ -0,0 +1,115 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+uniform sampler3D velocityX;
+uniform sampler3D velocityY;
+uniform sampler3D velocityZ;
+uniform float displaySize = 1.0;
+uniform float slicePosition;
+uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
+
+flat out vec4 finalColor;
+
+const vec3 corners[4] = vec3[4](
+ vec3(0.0, 0.2, -0.5),
+ vec3(-0.2 * 0.866, -0.2 * 0.5, -0.5),
+ vec3(0.2 * 0.866, -0.2 * 0.5, -0.5),
+ vec3(0.0, 0.0, 0.5)
+);
+
+const int indices[12] = int[12](0, 1, 1, 2, 2, 0, 0, 3, 1, 3, 2, 3);
+
+/* Straight Port from BKE_defvert_weight_to_rgb()
+ * TODO port this to a color ramp. */
+vec3 weight_to_color(float weight)
+{
+ vec3 r_rgb = vec3(0.0);
+ float blend = ((weight / 2.0) + 0.5);
+
+ if (weight <= 0.25) { /* blue->cyan */
+ r_rgb.g = blend * weight * 4.0;
+ r_rgb.b = blend;
+ }
+ else if (weight <= 0.50) { /* cyan->green */
+ r_rgb.g = blend;
+ r_rgb.b = blend * (1.0 - ((weight - 0.25) * 4.0));
+ }
+ else if (weight <= 0.75) { /* green->yellow */
+ r_rgb.r = blend * ((weight - 0.50) * 4.0);
+ r_rgb.g = blend;
+ }
+ else if (weight <= 1.0) { /* yellow->red */
+ r_rgb.r = blend;
+ r_rgb.g = blend * (1.0 - ((weight - 0.75) * 4.0));
+ }
+ else {
+ /* exceptional value, unclamped or nan,
+ * avoid uninitialized memory use */
+ r_rgb = vec3(1.0, 0.0, 1.0);
+ }
+
+ return r_rgb;
+}
+
+mat3 rotation_from_vector(vec3 v)
+{
+ /* Add epsilon to avoid NaN. */
+ vec3 N = normalize(v + 1e-8);
+ vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0,0.0,1.0) : vec3(1.0,0.0,0.0);
+ vec3 T = normalize(cross(UpVector, N));
+ vec3 B = cross(N, T);
+ return mat3(T, B, N);
+}
+
+void main()
+{
+#ifdef USE_NEEDLE
+ int cell = gl_VertexID / 12;
+#else
+ int cell = gl_VertexID / 2;
+#endif
+
+ ivec3 volume_size = textureSize(velocityX, 0);
+ float voxel_size = 1.0 / float(max(max(volume_size.x, volume_size.y), volume_size.z));
+
+ ivec3 cell_ofs = ivec3(0);
+ ivec3 cell_div = volume_size;
+ if (sliceAxis == 0) {
+ cell_ofs.x = int(slicePosition * float(volume_size.x));
+ cell_div.x = 1;
+ }
+ else if (sliceAxis == 1) {
+ cell_ofs.y = int(slicePosition * float(volume_size.y));
+ cell_div.y = 1;
+ }
+ else if (sliceAxis == 2) {
+ cell_ofs.z = int(slicePosition * float(volume_size.z));
+ cell_div.z = 1;
+ }
+
+ ivec3 cell_co;
+ cell_co.x = cell % cell_div.x;
+ cell_co.y = (cell / cell_div.x) % cell_div.y;
+ cell_co.z = cell / (cell_div.x * cell_div.y);
+ cell_co += cell_ofs;
+
+ vec3 pos = (vec3(cell_co) + 0.5) / vec3(volume_size);
+ pos = pos * 2.0 - 1.0;
+
+ vec3 velocity;
+ velocity.x = texelFetch(velocityX, cell_co, 0).r;
+ velocity.y = texelFetch(velocityY, cell_co, 0).r;
+ velocity.z = texelFetch(velocityZ, cell_co, 0).r;
+
+ finalColor = vec4(weight_to_color(length(velocity)), 1.0);
+
+#ifdef USE_NEEDLE
+ mat3 rot_mat = rotation_from_vector(velocity);
+ vec3 rotated_pos = rot_mat * corners[indices[gl_VertexID % 12]];
+ pos += rotated_pos * length(velocity) * displaySize * voxel_size;
+#else
+ pos += (((gl_VertexID % 2) == 1) ? velocity : vec3(0.0)) * displaySize * voxel_size;
+#endif
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+}