this could theoretically result in bad seaming and/or cracks on the // side we don't put it on. If the tangents are nearly equivalent then we leave the join // double-sided. float sinEpsilon = 1e-2; // ~= sin(180deg / 3000) bool tangentsNearlyParallel = (abs(turn) * inversesqrt(dot(tan0, tan0) * dot(tan1, tan1))) < sinEpsilon; if (!tangentsNearlyParallel || dot(tan0, tan1) < 0) { // There are two edges colocated at the beginning. Leave the first one double sided // for seaming with the previous stroke. (The double sided edge at the end will // actually come from the section of our strip that belongs to the stroke.) if (combinedEdgeID >= 0) { strokeOutset = (turn < 0) ? min(strokeOutset, 0) : max(strokeOutset, 0); } } combinedEdgeID = max(combinedEdgeID, 0); } else { // We belong to the stroke. Unless NUM_RADIAL_SEGMENTS_PER_RADIAN is incredibly high, // clamping to maxCombinedSegments will be a no-op because the draw call was invoked with // sufficient vertices to cover the worst case scenario of 180 degree rotation. float maxCombinedSegments = NUM_TOTAL_EDGES - numEdgesInJoin - 1; numRadialSegments = max(ceil(abs(rotation) * NUM_RADIAL_SEGMENTS_PER_RADIAN), 1); numRadialSegments = min(numRadialSegments, maxCombinedSegments); numParametricSegments = min(numParametricSegments, maxCombinedSegments - numRadialSegments + 1); } // Additional parameters for emitTessellationCode(). float radsPerSegment = rotation / numRadialSegments; float numCombinedSegments = numParametricSegments + numRadialSegments - 1; bool isFinalEdge = (combinedEdgeID >= numCombinedSegments); if (combinedEdgeID > numCombinedSegments) { strokeOutset = 0; // The strip has more edges than we need. Drop this one. }