From 8ea7e32a47aaf0a3e4c5bde19d70e4f39ea09b2e Mon Sep 17 00:00:00 2001 From: Spongman Date: Tue, 2 Jan 2018 15:33:37 -0800 Subject: [PATCH 1/2] borrow processing's line vertex shader --- src/webgl/shaders/line.vert | 107 ++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 30 deletions(-) diff --git a/src/webgl/shaders/line.vert b/src/webgl/shaders/line.vert index 6b6d051c9a..6c258600fe 100644 --- a/src/webgl/shaders/line.vert +++ b/src/webgl/shaders/line.vert @@ -1,42 +1,89 @@ +/* + Part of the Processing project - http://processing.org + Copyright (c) 2012-15 The Processing Foundation + Copyright (c) 2004-12 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation, version 2.1. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +#define PROCESSING_LINE_SHADER + uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; +uniform float uStrokeWeight; uniform vec4 uViewport; - -uniform float uStrokeWeight; +vec3 scale = vec3(1.0); attribute vec4 aPosition; attribute vec4 aDirection; + +void main() { + vec4 posp = uModelViewMatrix * aPosition; + vec4 posq = uModelViewMatrix * (aPosition + vec4(aDirection.xyz, 0)); + // Moving vertices slightly toward the camera + // to avoid depth-fighting with the fill triangles. + // Discussed here: + // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=252848 + posp.xyz = posp.xyz * scale; + posq.xyz = posq.xyz * scale; -vec3 clipToWindow(vec4 clip, vec4 viewport) { - vec3 post_div = clip.xyz / clip.w; - vec2 xypos = (post_div.xy + vec2(1.0, 1.0)) * 0.5 * viewport.zw; - return vec3(xypos, post_div.z * 0.5 + 0.5); -} + vec4 p = uProjectionMatrix * posp; + vec4 q = uProjectionMatrix * posq; -vec4 windowToClipVector(vec2 window, vec4 viewport, float clip_w) { - vec2 xypos = (window / viewport.zw) * 2.0; - return vec4(xypos, 0.0, 0.0) * clip_w; -} + // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height]) + // screen_p = (p.xy/p.w + <1,1>) * 0.5 * uViewport.zw -void main() { - vec4 posMV = uModelViewMatrix * aPosition; - posMV.xyz = posMV.xyz * vec3(0.999,0.999,0.999); - vec4 clipp = uProjectionMatrix * posMV; - float displace = aDirection.w; - - vec4 posq = uModelViewMatrix * vec4(aDirection.xyz, 0.0); - posq.xyz = posq.xyz * vec3(0.999,0.999,0.999); - vec4 clipq = uProjectionMatrix * posq; - clipq.w = 1.0; - - vec3 window_p = clipToWindow(clipp, uViewport); - vec3 window_q = clipToWindow(clipq, uViewport); - vec3 tangent = window_q - window_p; - vec2 perp = normalize(vec2(-tangent.y, tangent.x)); - float halfStroke = uStrokeWeight/2.0; - vec2 offset = vec2(halfStroke,halfStroke) * displace * perp; - gl_Position.xy = clipp.xy + offset.xy; - gl_Position.zw = clipp.zw; + // prevent division by W by transforming the tangent formula (div by 0 causes + // the line to disappear, see https://github.com/processing/processing/issues/5183) + // t = screen_q - screen_p + // + // tangent is normalized and we don't care which aDirection it points to (+-) + // t = +- normalize( screen_q - screen_p ) + // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*uViewport.zw - (p.xy/p.w+<1,1>)*0.5*uViewport.zw ) + // + // extract common factor, <1,1> - <1,1> cancels out + // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * uViewport.zw ) + // + // convert to common divisor + // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * uViewport.zw ) + // + // remove the common scalar divisor/factor, not needed due to normalize and +- + // (keep uViewport - can't remove because it has different components for x and y + // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181) + // t = +- normalize( (q.xy*p.w - p.xy*q.w) * uViewport.zw ) + + vec2 tangent = normalize((q.xy*p.w - p.xy*q.w) * uViewport.zw); + + // flip tangent to normal (it's already normalized) + vec2 normal = vec2(-tangent.y, tangent.x); + + float thickness = aDirection.w * uStrokeWeight; + vec2 offset = normal * thickness; + + // Perspective --- + // convert from world to clip by multiplying with projection scaling factor + // to get the right thickness (see https://github.com/processing/processing/issues/5182) + // invert Y, projections in Processing invert Y + vec2 perspScale = (uProjectionMatrix * vec4(1, -1, 0, 0)).xy; + + // No Perspective --- + // multiply by W (to cancel out division by W later in the pipeline) and + // convert from screen to clip (derived from clip to screen above) + vec2 noPerspScale = p.w / (0.5 * uViewport.zw); + + //gl_Position.xy = p.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0)); + gl_Position.xy = p.xy + offset.xy * perspScale; + gl_Position.zw = p.zw; } From 871067ed8a355d80f52a048527811b39b6723e35 Mon Sep 17 00:00:00 2001 From: piersh Date: Sun, 7 Jan 2018 15:47:24 -0800 Subject: [PATCH 2/2] halve thickeness --- src/webgl/shaders/line.vert | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webgl/shaders/line.vert b/src/webgl/shaders/line.vert index 6c258600fe..4fee2ab029 100644 --- a/src/webgl/shaders/line.vert +++ b/src/webgl/shaders/line.vert @@ -70,7 +70,7 @@ void main() { vec2 normal = vec2(-tangent.y, tangent.x); float thickness = aDirection.w * uStrokeWeight; - vec2 offset = normal * thickness; + vec2 offset = normal * thickness / 2.0; // Perspective --- // convert from world to clip by multiplying with projection scaling factor