vertex = () => `
uniform float subdivisions;
uniform float thickness;
uniform vec2 start;
uniform vec2 end;
uniform vec2 control;
varying vec2 vCoord;
#define PI 3.14
vec3 sample (float t) {
// We can also adjust the per-vertex curve thickness by modifying this 0..1 number
float volume = 1.0;
// Try replacing the above with:
// float volume = 1.0 * sin(t * PI);
// Solve the quadratic curve with the start, control and end points:
float dt = (1.0 - t);
float dtSq = dt * dt;
float tSq = t * t;
float x = dtSq * start.x + 2.0 * dt * t * control.x + tSq * end.x;
float y = dtSq * start.y + 2.0 * dt * t * control.y + tSq * end.y;
return vec3(x, y, volume);
// Alternatively, you can replace the above with a linear mix() operation
// This will produce a straight line between the start and end points
// return vec3(mix(start, end, t), volume);
}
void main () {
// Get the "arc length" in 0..1 space
float arclen = (position.x * 0.5 + 0.5);
// How far to offset the line thickness for this vertex in -1..1 space
float extrusion = position.y;
// Find next sample along curve
float nextArclen = arclen + (1.0 / subdivisions);
// Sample the curve in two places
// XY is the 2D position, and the Z component is the thickness at that vertex
vec3 current = sample(arclen);
vec3 next = sample(nextArclen);
// Now find the 2D perpendicular to form our line segment
vec2 direction = normalize(next.xy - current.xy);
vec2 perpendicular = vec2(-direction.y, direction.x);
// Extrude
float computedExtrusion = extrusion * (thickness / 2.0) * current.z;
vec3 offset = current.xyz + vec3(perpendicular.xy, 0.0) * computedExtrusion;
// Compute final position
gl_Position = projectionMatrix * modelViewMatrix * vec4(offset.xyz, 1.0);
// Pass along the coordinates for texturing/effects
vCoord = position.xy;
}
`