diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-04-22 23:49:36 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-05-02 21:49:38 +0300 |
commit | e493a1a1aedcd6bc00f0f016aa6ef707742e3825 (patch) | |
tree | e479cb1f54c0029e92446dc6b0cfc263fe1bfb56 /source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl | |
parent | 77b481fd5ae2e8b503aed714ae3335ba637c84b6 (diff) |
DRW: Armature: New bone outline shader.
This fix the issue with the zfighting we were getting at bones edges.
Moreover, this enables us to render arbitrarly large outline with
varying thickness.
Diffstat (limited to 'source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl')
-rw-r--r-- | source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl | 95 |
1 files changed, 95 insertions, 0 deletions
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..3d3cb692634 --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl @@ -0,0 +1,95 @@ + +/* TODO: See perf with multiple invocations. */ +layout(triangles_adjacency) in; +layout(triangle_strip, max_vertices = 16) out; + +in vec4 pPos[]; +in float vZ[]; +in float vFacing[]; +in vec2 ssPos[]; +in vec2 ssNor[]; +in vec4 vCol[]; + +flat out vec4 finalColor; +uniform mat4 ProjectionMatrix; +uniform vec2 viewportSize; +uniform float lineThickness = 3.0; + +vec2 compute_dir(vec2 v0, vec2 v1) +{ + vec2 dir = normalize(v1 - v0); + dir = vec2(-dir.y, dir.x); + return dir; +} + +void emit_edge(const ivec3 edges, vec2 thick, bool is_persp) +{ + vec2 edge_dir = compute_dir(ssPos[edges.x], ssPos[edges.y]); + vec2 hidden_dir = normalize(ssPos[edges.z] - ssPos[edges.x]); + + float fac = dot(-hidden_dir, edge_dir); + + vec2 t = thick * (is_persp ? vZ[edges.x] : 1.0); + gl_Position = pPos[edges.x]; + EmitVertex(); + gl_Position.xy += t * edge_dir * sign(fac); + EmitVertex(); + + t = thick * (is_persp ? vZ[edges.y] : 1.0); + gl_Position = pPos[edges.y]; + EmitVertex(); + gl_Position.xy += t * edge_dir * sign(fac); + EmitVertex(); +} + +void emit_corner(const int e, vec2 thick, bool is_persp) +{ + vec2 corner_dir = ssNor[e]; + vec2 t = thick * (is_persp ? vZ[e] : 1.0); + + gl_Position = pPos[e] + vec4(t * corner_dir, 0.0, 0.0); + EmitVertex(); +} + +void main(void) +{ + finalColor = vCol[0]; + + vec2 thick = lineThickness / viewportSize; + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + + const ivec3 edges = ivec3(0, 2, 4); + vec4 facing = vec4(vFacing[1], vFacing[3], vFacing[5], vFacing[0]); + bvec4 do_edge = greaterThanEqual(facing, vec4(0.0)); + + /* Only generate outlines from backfaces. */ + if (do_edge.w) + return; + + if (do_edge.x) { + emit_corner(edges.x, thick, is_persp); + emit_edge(edges.xyz, thick, is_persp); + } + + if (any(do_edge.xy)) { + emit_corner(edges.y, thick, is_persp); + } + + if (do_edge.y) { + emit_edge(edges.yzx, thick, is_persp); + } + else { + EndPrimitive(); + } + + if (any(do_edge.yz)) { + emit_corner(edges.z, thick, is_persp); + } + + if (do_edge.z) { + emit_edge(edges.zxy, thick, is_persp); + emit_corner(edges.x, thick, is_persp); + } + + EndPrimitive(); +} |