diff options
Diffstat (limited to 'source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl')
-rw-r--r-- | source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl | 111 |
1 files changed, 72 insertions, 39 deletions
diff --git a/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl b/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl index f5a3aa2c332..c77c89396af 100644 --- a/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl @@ -57,6 +57,34 @@ bvec4 gather_edges(vec2 uv, uint ref) return notEqual(ids, uvec4(ref)); } +/* Clockwise */ +vec2 rotate_90(vec2 v) +{ + return vec2(v.y, -v.x); +} +vec2 rotate_180(vec2 v) +{ + return vec2(-v.x, -v.y); +} +vec2 rotate_270(vec2 v) +{ + return vec2(-v.y, v.x); +} + +/* Counter-Clockwise */ +bvec4 rotate_90(bvec4 v) +{ + return v.yzwx; +} +bvec4 rotate_180(bvec4 v) +{ + return v.zwxy; +} +bvec4 rotate_270(bvec4 v) +{ + return v.wxyz; +} + /* Apply offset to line endpoint based on surrounding edges infos. */ bool line_offset(bvec2 edges, vec2 ofs, inout vec2 line_point) { @@ -79,6 +107,7 @@ bool line_offset(bvec2 edges, vec2 ofs, inout vec2 line_point) /* Use surrounding edges to approximate the outline direction to create smooth lines. */ void straight_line_dir(bvec4 edges1, bvec4 edges2, out vec2 line_start, out vec2 line_end) { + /* Y_POS as reference. Other cases are rotated to match reference. */ line_end = vec2(1.5, 0.5 + PROXIMITY_OFS); line_start = vec2(-line_end.x, line_end.y); @@ -92,53 +121,50 @@ void straight_line_dir(bvec4 edges1, bvec4 edges2, out vec2 line_start, out vec2 } } -/* Compute line direction vector from the bottom left corner. */ -void diag_dir(bvec4 edges, out vec2 line_start, out vec2 line_end) +vec2 diag_offset(bvec4 edges) { - /* TODO Improve diagonal antialiasing. */ + /* X_NEG | Y_POS as reference. Other cases are rotated to match reference. + * So the line is comming from bottom left. */ if (all(edges.wz)) { - line_start = vec2(-3.0, -0.5 + PROXIMITY_OFS); - line_end = vec2(3.0, 0.5 + PROXIMITY_OFS); + /* Horizontal line. */ + return vec2(2.5, 0.5); } else if (all(not(edges.xw))) { - line_start = vec2(-0.5 - PROXIMITY_OFS, -3.0); - line_end = vec2(0.5 - PROXIMITY_OFS, 3.0); + /* Vertical line. */ + return vec2(0.5, 2.5); } else if (edges.w) { - line_start = vec2(-1.0, -0.5 - PROXIMITY_OFS); - line_end = vec2(2.0, 0.5 - PROXIMITY_OFS); + /* Less horizontal Line. */ + return vec2(2.5, 0.5); } else { - line_start = vec2(-0.6, -0.5 + PROXIMITY_OFS); - line_end = vec2(0.6 - PROXIMITY_OFS, 0.5); + /* Less vertical Line. */ + return vec2(0.5, 2.5); } } -/* Clockwise */ -vec2 rotate_90(vec2 v) -{ - return vec2(v.y, -v.x); -} -vec2 rotate_180(vec2 v) -{ - return vec2(-v.x, -v.y); -} -vec2 rotate_270(vec2 v) -{ - return vec2(-v.y, v.x); -} -/* Counter-Clockwise */ -bvec4 rotate_90(bvec4 v) -{ - return v.yzwx; -} -bvec4 rotate_180(bvec4 v) -{ - return v.zwxy; -} -bvec4 rotate_270(bvec4 v) +/* Compute line direction vector from the bottom left corner. */ +void diag_dir(bvec4 edges1, bvec4 edges2, out vec2 line_start, out vec2 line_end) { - return v.wxyz; + /* Negate instead of rotating back the result of diag_offset. */ + edges2 = not(edges2); + edges2 = rotate_180(edges2); + line_end = diag_offset(edges1); + line_end += diag_offset(edges2); + + if (line_end.x == line_end.y) { + /* Perfect diagonal line. Push line start towards edge. */ + line_start = vec2(-1.0, 1.0) * PROXIMITY_OFS * 0.4; + } + else if (line_end.x > line_end.y) { + /* Horizontal Line. Lower line start. */ + line_start = vec2(0.0, PROXIMITY_OFS); + } + else { + /* Vertical Line. Push line start to the right. */ + line_start = -vec2(PROXIMITY_OFS, 0.0); + } + line_end += line_start; } void main() @@ -292,26 +318,33 @@ void main() /* Diagonal */ case DIAG_XNEG_YPOS: extra_edges = gather_edges(uvs + ofs.xy * vec2(1.5), ref); - diag_dir(extra_edges, line_start, line_end); + extra_edges2 = gather_edges(uvs + ofs.xy * vec2(-1.5), ref); + diag_dir(extra_edges, extra_edges2, line_start, line_end); break; case DIAG_XPOS_YNEG: extra_edges = gather_edges(uvs - ofs.xy * vec2(1.5), ref); + extra_edges2 = gather_edges(uvs - ofs.xy * vec2(-1.5), ref); extra_edges = rotate_180(extra_edges); - diag_dir(extra_edges, line_start, line_end); + extra_edges2 = rotate_180(extra_edges2); + diag_dir(extra_edges, extra_edges2, line_start, line_end); line_start = rotate_180(line_start); line_end = rotate_180(line_end); break; case DIAG_XPOS_YPOS: extra_edges = gather_edges(uvs + ofs.xy * vec2(1.5, -1.5), ref); + extra_edges2 = gather_edges(uvs - ofs.xy * vec2(1.5, -1.5), ref); extra_edges = rotate_90(extra_edges); - diag_dir(extra_edges, line_start, line_end); + extra_edges2 = rotate_90(extra_edges2); + diag_dir(extra_edges, extra_edges2, line_start, line_end); line_start = rotate_90(line_start); line_end = rotate_90(line_end); break; case DIAG_XNEG_YNEG: extra_edges = gather_edges(uvs - ofs.xy * vec2(1.5, -1.5), ref); + extra_edges2 = gather_edges(uvs + ofs.xy * vec2(1.5, -1.5), ref); extra_edges = rotate_270(extra_edges); - diag_dir(extra_edges, line_start, line_end); + extra_edges2 = rotate_270(extra_edges2); + diag_dir(extra_edges, extra_edges2, line_start, line_end); line_start = rotate_270(line_start); line_end = rotate_270(line_end); break; |