Skip to content

webgl: use Processing's line vertex shader #2515

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 8, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 77 additions & 30 deletions src/webgl/shaders/line.vert
Original file line number Diff line number Diff line change
@@ -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 / 2.0;

// 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;
}