diff --git a/core/src/processing/opengl/PGL.java b/core/src/processing/opengl/PGL.java index 372c9b74d..4620e9cf2 100644 --- a/core/src/processing/opengl/PGL.java +++ b/core/src/processing/opengl/PGL.java @@ -1989,8 +1989,9 @@ public abstract class PGL { String[] src = new String[src0.length+offset]; for (int i = 0; i < src0.length; i++) { String line = src0[i]; - if (line.contains("#version")) { - line = ""; + int versionIndex = line.indexOf("#version"); + if (versionIndex >= 0) { + line = line.substring(0, versionIndex); } for (int j = 0; j < search.length; j++) { line = search[j].matcher(line).replaceAll(replace[j]); @@ -2003,8 +2004,12 @@ public abstract class PGL { protected static boolean containsVersionDirective(String[] shSrc) { for (int i = 0; i < shSrc.length; i++) { String line = shSrc[i]; - if (line.contains("#version")) { - return true; + int versionIndex = line.indexOf("#version"); + if (versionIndex >= 0) { + int commentIndex = line.indexOf("//"); + if (commentIndex < 0 || versionIndex < commentIndex) { + return true; + } } } return false; diff --git a/core/src/processing/opengl/shaders/LineVert.glsl b/core/src/processing/opengl/shaders/LineVert.glsl index b9237451d..7dc290b78 100644 --- a/core/src/processing/opengl/shaders/LineVert.glsl +++ b/core/src/processing/opengl/shaders/LineVert.glsl @@ -34,54 +34,64 @@ attribute vec4 color; attribute vec4 direction; varying vec4 vertColor; - -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 windowToClipVector(vec2 window, vec4 viewport, float clip_w) { - vec2 xypos = (window / viewport.zw) * 2.0; - return vec4(xypos, 0.0, 0.0) * clip_w; -} void main() { vec4 posp = modelviewMatrix * position; - + vec4 posq = modelviewMatrix * (position + vec4(direction.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; - vec4 clipp = projectionMatrix * posp; - float thickness = direction.w; - - if (thickness != 0.0) { - vec4 posq = posp + modelviewMatrix * vec4(direction.xyz, 0); - posq.xyz = posq.xyz * scale; - vec4 clipq = projectionMatrix * posq; - - vec3 window_p = clipToWindow(clipp, viewport); - vec3 window_q = clipToWindow(clipq, viewport); - vec3 tangent = window_q - window_p; - - vec2 perp = normalize(vec2(-tangent.y, tangent.x)); - vec2 offset = perp * thickness; + posq.xyz = posq.xyz * scale; + + vec4 p = projectionMatrix * posp; + vec4 q = projectionMatrix * posq; + + // 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 * viewport.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 direction it points to (+-) + // t = +- normalize( screen_q - screen_p ) + // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*viewport.zw - (p.xy/p.w+<1,1>)*0.5*viewport.zw ) + // + // extract common factor, <1,1> - <1,1> cancels out + // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * viewport.zw ) + // + // convert to common divisor + // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * viewport.zw ) + // + // remove the common scalar divisor/factor, not needed due to normalize and +- + // (keep viewport - 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) * viewport.zw ) + + vec2 tangent = normalize((q.xy*p.w - p.xy*q.w) * viewport.zw); + + // flip tangent to normal (it's already normalized) + vec2 normal = vec2(-tangent.y, tangent.x); + + float thickness = direction.w; + 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 = (projectionMatrix * 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 * viewport.zw); + + gl_Position.xy = p.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0)); + gl_Position.zw = p.zw; - if (0 < perspective) { - // Perspective correction (lines will look thiner as they move away - // from the view position). - gl_Position.xy = clipp.xy + offset.xy; - gl_Position.zw = clipp.zw; - } else { - // No perspective correction. - vec4 offsetp = windowToClipVector(offset, viewport, clipp.w); - gl_Position = clipp + offsetp; - } - } else { - gl_Position = clipp; - } - vertColor = color; } diff --git a/core/src/processing/opengl/shaders/PointVert.glsl b/core/src/processing/opengl/shaders/PointVert.glsl index 481fd1da7..8249e9076 100644 --- a/core/src/processing/opengl/shaders/PointVert.glsl +++ b/core/src/processing/opengl/shaders/PointVert.glsl @@ -32,24 +32,25 @@ attribute vec2 offset; varying vec4 vertColor; -vec4 windowToClipVector(vec2 window, vec4 viewport, float clipw) { - vec2 xypos = (window / viewport.zw) * 2.0; - return vec4(xypos, 0.0, 0.0) * clipw; -} - void main() { vec4 pos = modelviewMatrix * position; vec4 clip = projectionMatrix * pos; - - if (0 < perspective) { - // Perspective correction (points will look thiner as they move away - // from the view position). - gl_Position = clip + projectionMatrix * vec4(offset.xy, 0, 0); - } else { - // No perspective correction. - vec4 cloff = windowToClipVector(offset.xy, viewport, clip.w); - gl_Position = clip + cloff; - } + + // Perspective --- + // convert from world to clip by multiplying with projection scaling factor + // invert Y, projections in Processing invert Y + vec2 perspScale = (projectionMatrix * vec4(1, -1, 0, 0)).xy; + + // 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 * viewport.zw + + // 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 = clip.w / (0.5 * viewport.zw); + + gl_Position.xy = clip.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0)); + gl_Position.zw = clip.zw; vertColor = color; -} \ No newline at end of file +}