attribute vec3 previous; attribute vec3 next; attribute float side; attribute float width; attribute float counters; uniform vec2 resolution; uniform float lineWidth; uniform vec3 color; uniform float opacity; uniform float sizeAttenuation; uniform float scaleDown; varying vec2 vUV; varying vec4 vColor; varying float vCounters; vec2 intoScreen(vec4 i) { return resolution * (0.5 * i.xy / i.w + 0.5); } void main() { float aspect = resolution.y / resolution.x; mat4 m = projectionMatrix * modelViewMatrix; vec4 currentClip = m * vec4( position, 1.0 ); vec4 prevClip = m * vec4( previous, 1.0 ); vec4 nextClip = m * vec4( next, 1.0 ); vec4 currentNormed = currentClip / currentClip.w; vec4 prevNormed = prevClip / prevClip.w; vec4 nextNormed = nextClip / nextClip.w; vec2 currentScreen = intoScreen(currentNormed); vec2 prevScreen = intoScreen(prevNormed); vec2 nextScreen = intoScreen(nextNormed); float actualWidth = lineWidth * width; vec2 dir; if(nextScreen == currentScreen) { dir = normalize( currentScreen - prevScreen ); } else if(prevScreen == currentScreen) { dir = normalize( nextScreen - currentScreen ); } else { vec2 inDir = currentScreen - prevScreen; vec2 outDir = nextScreen - currentScreen; vec2 fullDir = nextScreen - prevScreen; if(length(fullDir) > 0.0) { dir = normalize(fullDir); } else if(length(inDir) > 0.0){ dir = normalize(inDir); } else { dir = normalize(outDir); } } vec2 normal = vec2(-dir.y, dir.x); if(sizeAttenuation != 0.0) { normal /= currentClip.w; normal *= min(resolution.x, resolution.y); } if (scaleDown > 0.0) { float dist = length(nextNormed - prevNormed); normal *= smoothstep(0.0, scaleDown, dist); } vec2 offsetInScreen = actualWidth * normal * side * 0.5; vec2 withOffsetScreen = currentScreen + offsetInScreen; vec3 withOffsetNormed = vec3((2.0 * withOffsetScreen/resolution - 1.0), currentNormed.z); vCounters = counters; vColor = vec4( color, opacity ); vUV = uv; gl_Position = currentClip.w * vec4(withOffsetNormed, 1.0); }