// Copyright (c) 2015 - 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

export default "\n#define SHADER_NAME path-layer-vertex-shader\n\nattribute vec3 positions;\n\nattribute vec3 instanceStartPositions;\nattribute vec3 instanceEndPositions;\nattribute vec4 instanceStartEndPositions64xyLow;\nattribute vec3 instanceLeftDeltas;\nattribute vec3 instanceRightDeltas;\nattribute float instanceStrokeWidths;\nattribute vec4 instanceColors;\nattribute vec3 instancePickingColors;\nattribute vec2 instanceDashArrays;\n\nuniform float widthScale;\nuniform float widthMinPixels;\nuniform float widthMaxPixels;\nuniform float jointType;\nuniform float miterLimit;\n\nuniform float opacity;\n\nvarying vec4 vColor;\nvarying vec2 vCornerOffset;\nvarying float vMiterLength;\nvarying vec2 vDashArray;\nvarying float vPathPosition;\nvarying float vPathLength;\n\nconst float EPSILON = 0.001;\nconst float PIXEL_EPSILON = 0.1;\n\nfloat flipIfTrue(bool flag) {\n  return -(float(flag) * 2. - 1.);\n}\n\nvec3 lineJoin(vec2 prevPoint64[2], vec2 currPoint64[2], vec2 nextPoint64[2]) {\n\n  float width = clamp(project_scale(instanceStrokeWidths * widthScale),\n    widthMinPixels, widthMaxPixels) / 2.0;\n\n  vec2 deltaA64[2];\n  vec2 deltaB64[2];\n\n  vec2_sub_fp64(currPoint64, prevPoint64, deltaA64);\n  vec2_sub_fp64(nextPoint64, currPoint64, deltaB64);\n\n  vec2 lengthA64 = vec2_length_fp64(deltaA64);\n  vec2 lengthB64 = vec2_length_fp64(deltaB64);\n\n  vec2 deltaA = vec2(deltaA64[0].x, deltaA64[1].x);\n  vec2 deltaB = vec2(deltaB64[0].x, deltaB64[1].x);\n\n  float lenA = lengthA64.x;\n  float lenB = lengthB64.x;\n\n  vec2 offsetVec;\n  float offsetScale;\n  float offsetDirection;\n\n  // when two points are closer than PIXEL_EPSILON in pixels,\n  // assume they are the same point to avoid precision issue\n  lenA = lenA > PIXEL_EPSILON ? lenA : 0.0;\n  lenB = lenB > PIXEL_EPSILON ? lenB : 0.0;\n  vec2 dirA = lenA > 0. ? deltaA / lenA : vec2(0.0, 0.0);\n  vec2 dirB = lenB > 0. ? deltaB / lenB : vec2(0.0, 0.0);\n\n  vec2 perpA = vec2(-dirA.y, dirA.x);\n  vec2 perpB = vec2(-dirB.y, dirB.x);\n\n  // tangent of the corner\n  vec2 tangent = vec2(dirA + dirB);\n  tangent = length(tangent) > 0. ? normalize(tangent) : perpA;\n  // direction of the corner\n  vec2 miterVec = vec2(-tangent.y, tangent.x);\n  // width offset from current position\n  vec2 perp = mix(perpB, perpA, positions.x);\n  float L = mix(lenB, lenA, positions.x);\n\n  // cap super sharp angles\n  float sinHalfA = abs(dot(miterVec, perp));\n  float cosHalfA = abs(dot(dirA, miterVec));\n  bool turnsRight = dirA.x * dirB.y > dirA.y * dirB.x;\n\n  // relative position to the corner:\n  // -1: inside (smaller side of the angle)\n  // 0: center\n  // 1: outside (bigger side of the angle)\n  float cornerPosition = mix(\n    flipIfTrue(turnsRight == (positions.y > 0.0)),\n    0.0,\n    positions.z\n  );\n\n  offsetScale = 1.0 / max(sinHalfA, EPSILON);\n\n  // do not bevel if line segment is too short\n  cornerPosition *= float(cornerPosition <= 0.0 || sinHalfA < min(lenA, lenB) / width * cosHalfA);\n  // trim if inside corner extends further than the line segment\n  offsetScale = mix(\n    offsetScale,\n    min(offsetScale, L / width / max(cosHalfA, EPSILON)),\n    float(cornerPosition < 0.0)\n  );\n\n  vMiterLength = mix(\n    offsetScale * cornerPosition,\n    mix(offsetScale, 0.0, cornerPosition),\n    step(0.0, cornerPosition)\n  ) - sinHalfA * jointType;\n  offsetDirection = mix(\n    positions.y,\n    mix(\n      flipIfTrue(turnsRight),\n      positions.y * flipIfTrue(turnsRight == (positions.x == 1.)),\n      cornerPosition\n    ),\n    step(0.0, cornerPosition)\n  );\n  offsetVec = mix(miterVec, -tangent, step(0.5, cornerPosition));\n  offsetScale = mix(offsetScale, 1.0 / max(cosHalfA, 0.001), step(0.5, cornerPosition));\n\n  // special treatment for start cap and end cap\n  // using a small number as the limit for determining if the lenA or lenB is 0\n  float isStartCap = step(lenA, 1.0e-5);\n  float isEndCap = step(lenB, 1.0e-5);\n  float isCap = max(isStartCap, isEndCap);\n\n  // 0: center, 1: side\n  cornerPosition = isCap * (1.0 - positions.z);\n\n  // start of path: use next - curr\n  offsetVec = mix(offsetVec, mix(dirB, perpB, cornerPosition), isStartCap);\n  // end of path: use curr - prev\n  offsetVec = mix(offsetVec, mix(dirA, perpA, cornerPosition), isEndCap);\n\n  // extend out a triangle to envelope the round cap\n  offsetScale = mix(\n    offsetScale,\n    mix(4.0 * jointType, 1.0, cornerPosition),\n    isCap\n  );\n  vMiterLength = mix(vMiterLength, 1.0 - cornerPosition, isCap);\n\n  offsetDirection = mix(\n    offsetDirection,\n    mix(flipIfTrue(isStartCap > 0.), positions.y, cornerPosition),\n    isCap\n  );\n\n  vCornerOffset = offsetVec * offsetDirection * offsetScale;\n\n  // Generate variables for dash calculation\n  vDashArray = instanceDashArrays;\n  vPathLength = L / width;\n  float isEnd = positions.x;\n  vec2 offsetFromStartOfPath = mix(vCornerOffset, vCornerOffset + deltaA / width, isEnd);\n  vec2 dir = mix(dirB, dirA, isEnd);\n  vPathPosition = dot(offsetFromStartOfPath, dir);\n\n  return vec3(vCornerOffset * width, 0.0);\n}\n\nvoid main() {\n  vColor = vec4(instanceColors.rgb, instanceColors.a * opacity) / 255.;\n\n  // Set color to be rendered to picking fbo (also used to check for selection highlight).\n  picking_setPickingColor(instancePickingColors);\n\n  float isEnd = positions.x;\n\n  // Calculate current position 64bit\n\n  vec3 currPosition = mix(instanceStartPositions, instanceEndPositions, isEnd);\n  vec2 currPosition64xyLow = mix(instanceStartEndPositions64xyLow.xy, instanceStartEndPositions64xyLow.zw, isEnd);\n  vec2 projected_curr_position[2];\n  project_position_fp64(currPosition.xy, currPosition64xyLow, projected_curr_position);\n  float projected_curr_position_z = project_scale(currPosition.z);\n\n  // Calculate previous position\n\n  vec3 prevPosition = mix(-instanceLeftDeltas, vec3(0.0), isEnd) + instanceStartPositions;\n\n  // Calculate prev position 64bit\n\n  vec2 projected_prev_position[2];\n  project_position_fp64(prevPosition.xy, instanceStartEndPositions64xyLow.xy, projected_prev_position);\n\n  // Calculate next positions\n  vec3 nextPosition = mix(vec3(0.0), instanceRightDeltas, isEnd) + instanceEndPositions;\n\n  // Calculate next position 64bit\n\n  vec2 projected_next_position[2];\n  project_position_fp64(nextPosition.xy, instanceStartEndPositions64xyLow.zw, projected_next_position);\n\n  vec3 pos = lineJoin(projected_prev_position, projected_curr_position, projected_next_position);\n  vec2 vertex_pos_modelspace[4];\n\n  vertex_pos_modelspace[0] = sum_fp64(vec2(pos.x, 0.0), projected_curr_position[0]);\n  vertex_pos_modelspace[1] = sum_fp64(vec2(pos.y, 0.0), projected_curr_position[1]);\n  vertex_pos_modelspace[2] = vec2(pos.z + projected_curr_position_z, 0.0);\n  vertex_pos_modelspace[3] = vec2(1.0, 0.0);\n\n  gl_Position = project_to_clipspace_fp64(vertex_pos_modelspace);\n}\n";
//# sourceMappingURL=path-layer-vertex-64.glsl.js.map