vertexShaderSource = `#version 300 es
in vec2 in_position;
in vec2 in_startPos;
in vec2 in_endPos;
in vec2 in_prevPos;
in vec2 in_nextPos;
in float in_lineWidth;
out vec2 v_startPos;
out vec2 v_endPos;
out vec2 v_startMiterVec;
out vec2 v_endMiterVec;
out float v_lineWidth;
uniform vec2 u_resolution;
mat3 getTransformMatrix(vec2 startPos, vec2 endPos, float lineWidth) {
vec2 centerPos = (startPos + endPos) / 2.;
vec2 delta = endPos - startPos;
float len = length(delta);
float phi = atan(delta.y / delta.x);
mat3 scale = mat3(
len, 0, 0,
0, lineWidth, 0,
0, 0, 1
);
mat3 rotate = mat3(
cos(phi), sin(phi), 0,
-sin(phi), cos(phi), 0,
0, 0, 1
);
mat3 translate = mat3(
1, 0, 0,
0, 1, 0,
centerPos.x, centerPos.y, 1
);
return translate * rotate * scale;
}
vec2 getOffsetVec(vec2 pos, vec2 prev, vec2 next) {
if (pos == prev || pos == next) {
return vec2(0., 0.);
}
vec2 line1 = pos - prev;
vec2 normal1 = normalize(vec2(-line1.y, line1.x));
vec2 line2 = next - pos;
vec2 normal2 = normalize(vec2(-line2.y, line2.x));
vec2 normal = normalize(normal1 + normal2);
vec2 vec = normal * 1. / abs(dot(normal, normal1));
return -vec; // 逆时针向外的向量
}
void main() {
vec2 v1 = getOffsetVec(in_startPos, in_prevPos, in_endPos) * in_lineWidth / 2.;
vec2 v2 = getOffsetVec(in_endPos, in_startPos, in_nextPos) * in_lineWidth / 2.;
vec2 dir = normalize(in_endPos - in_startPos);
vec2 startOffset = (v1 == vec2(0., 0.) ? -in_lineWidth / 2. : dot(v1, dir)) * dir;
vec2 endOffset = (v2 == vec2(0., 0.) ? in_lineWidth / 2. : dot(v2, dir)) * dir;
mat3 transformMatrix = getTransformMatrix(in_startPos + startOffset, in_endPos + endOffset, in_lineWidth);
vec2 pos = (transformMatrix * vec3(in_position, 1.)).xy;
// vec2 pos = in_position * in_lineWidth + in_startPos;
// vec4 pos = u_transform * vec4(in_position, 0., 1.);
// convert the position from pixels to 0.0 to 1.0
vec2 zeroToOne = pos.xy / u_resolution;
// convert from 0->1 to 0->2
vec2 zeroToTwo = zeroToOne * 2.0;
// convert from 0->2 to -1->+1 (clipspace)
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace, 0, 1);
v_startPos = in_startPos;
v_endPos = in_endPos;
v_startMiterVec = v1;
v_endMiterVec = v2;
v_lineWidth = in_lineWidth;
}
`