#version 450 layout(location = 1) in vec2 texCoord; layout(location = 0) out vec4 outColor; layout(set = 4, binding = 0) uniform LabelData { vec4 color; vec2 textSize; vec2 bboxCenter; float radius; float arrowLength; float arrowWidth; bool hasRoundedCorners; bool hasArrow; } labelInfo; void main() { if (labelInfo.hasRoundedCorners || labelInfo.hasArrow) { vec2 bbox = vec2(labelInfo.textSize); const float arrowLength = int(labelInfo.hasArrow) * labelInfo.arrowLength; float arrowWidth = labelInfo.arrowWidth; vec2 uvScaled = texCoord; float distX = min(uvScaled.x, bbox.x - uvScaled.x); float distY = min(uvScaled.y - arrowLength, bbox.y - uvScaled.y); float distanceFromCorner = distX * distY; if (distanceFromCorner < labelInfo.radius) { // plain arrow if (labelInfo.hasArrow && !labelInfo.hasRoundedCorners) { // Some bias to prevent line between arrow and label + // check that we are dealing with lower parts of the label where arrow should be drawn, // to prevent discarding fragments from upper corners if (distY <= 0.01 && uvScaled.y < (bbox.y - arrowWidth) && arrowLength != 0.0f) { arrowWidth = arrowWidth * ((arrowLength + distY) / arrowLength); if (distX < (bbox.x - arrowWidth) * 0.5) { discard; } } } // TODO: rounded corners + rounded arrow. // now renders rounded corners and sharp arrow else if (labelInfo.hasArrow && labelInfo.hasRoundedCorners) { if (distY <= 0.05 && uvScaled.y < (bbox.y - arrowWidth) && arrowLength != 0.0f) { arrowWidth = arrowWidth * ((arrowLength + distY) / arrowLength); if (distX < (bbox.x - arrowWidth) * 0.5) { discard; } } else { discard; } } // no arrow, rounded corners else { discard; } } } outColor = labelInfo.color; }