// 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 "#define SHADER_NAME path-layer-vertex-shader-64\n\nattribute vec3 positions;\n\nattribute vec3 instanceStartPositions;\nattribute vec3 instanceEndPositions;\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\n// calculate line join positions\nvec3 lineJoin(\n  vec3 prevPoint, vec3 currPoint, vec3 nextPoint,\n  float relativePosition, bool isEnd, bool isJoint,\n  float width\n) {\n  vec2 deltaA = currPoint.xy - prevPoint.xy;\n  vec2 deltaB = nextPoint.xy - currPoint.xy;\n\n  float lenA = length(deltaA);\n  float lenB = length(deltaB);\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\n  vec2 dirA = lenA > 0. ? normalize(deltaA) : vec2(0.0, 0.0);\n  vec2 dirB = lenB > 0. ? normalize(deltaB) : 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 = isEnd ? perpA : perpB;\n  float L = isEnd ? lenA : lenB;\n\n  // cap super sharp angles\n  float sinHalfA = abs(dot(miterVec, perp));\n  float cosHalfA = abs(dot(dirA, miterVec));\n\n  bool turnsRight = dirA.x * dirB.y > dirA.y * dirB.x;\n\n  float offsetScale = 1.0 / max(sinHalfA, EPSILON);\n\n  float cornerPosition = isJoint ?\n    0.0 :\n    flipIfTrue(turnsRight == (relativePosition > 0.0));\n\n  // do not bevel if line segment is too short\n  cornerPosition *=\n    float(cornerPosition <= 0.0 || sinHalfA < min(lenA, lenB) / width * cosHalfA);\n\n  // trim if inside corner extends further than the line segment\n  if (cornerPosition < 0.0) {\n    offsetScale = min(offsetScale, L / width / max(cosHalfA, EPSILON));\n  }\n\n  vMiterLength = cornerPosition >= 0.0 ?\n    mix(offsetScale, 0.0, cornerPosition) :\n    offsetScale * cornerPosition;\n  vMiterLength -= sinHalfA * jointType;\n\n  float 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\n  vec2 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  // TODO - This has an issue. len is always positive because it is length.\n  // Step returns zero if -lenA<0, so practically this is a comparison of\n  // lenA with zero, with lots of problems because of the -lenA. Can we use EPSILON?\n  bool isStartCap = step(0.0, -lenA) > 0.5;\n  bool isEndCap = step(0.0, -lenB) > 0.5;\n  bool isCap = isStartCap || isEndCap;\n\n  // 0: center, 1: side\n  cornerPosition = isCap ? (1.0 - positions.z) : 0.;\n\n  // start of path: use next - curr\n  if (isStartCap) {\n    offsetVec = mix(dirB, perpB, cornerPosition);\n  }\n\n  // end of path: use curr - prev\n  if (isEndCap) {\n    offsetVec = mix(dirA, perpA, cornerPosition);\n  }\n\n  // extend out a triangle to envelope the round cap\n  if (isCap) {\n    offsetScale = mix(4.0 * jointType, 1.0, cornerPosition);\n    vMiterLength = 1.0 - cornerPosition;\n    offsetDirection = mix(flipIfTrue(isStartCap), positions.y, cornerPosition);\n  }\n\n  vCornerOffset = offsetVec * offsetDirection * offsetScale;\n\n  // Generate variables for dash calculation\n  vDashArray = instanceDashArrays;\n  vPathLength = L / width;\n  // vec2 offsetFromStartOfPath = isEnd ? vCornerOffset + deltaA / width : vCornerOffset;\n  vec2 offsetFromStartOfPath = vCornerOffset;\n  if (isEnd) {\n    offsetFromStartOfPath += deltaA / width;\n  }\n  vec2 dir = isEnd ? dirA : dirB;\n  vPathPosition = dot(offsetFromStartOfPath, dir);\n\n  return currPoint + vec3(vCornerOffset * width, 0.0);\n}\n\n// calculate line join positions\n// extract params from attributes and uniforms\nvec3 lineJoin(vec3 prevPoint, vec3 currPoint, vec3 nextPoint) {\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\n  float relativePosition = positions.y;\n  bool isEnd = positions.x > EPSILON;\n  bool isJoint = positions.z > EPSILON;\n\n  float width = clamp(project_scale(instanceStrokeWidths * widthScale),\n    widthMinPixels, widthMaxPixels) / 2.0;\n\n  return lineJoin(\n    prevPoint, currPoint, nextPoint,\n    relativePosition, isEnd, isJoint,\n    width\n  );\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  vec3 prevPosition = mix(-instanceLeftDeltas, vec3(0.0), isEnd) + instanceStartPositions;\n  prevPosition = project_position(prevPosition);\n\n  vec3 currPosition = mix(instanceStartPositions, instanceEndPositions, isEnd);\n  currPosition = project_position(currPosition);\n\n  vec3 nextPosition = mix(vec3(0.0), instanceRightDeltas, isEnd) + instanceEndPositions;\n  nextPosition = project_position(nextPosition);\n\n  vec3 pos = lineJoin(prevPosition, currPosition, nextPosition);\n\n  gl_Position = project_to_clipspace(vec4(pos, 1.0));\n}\n";
//# sourceMappingURL=path-layer-vertex.glsl.js.map