I've written some helper code to draw nice-looking 2D line segments with decent performance in XNA -- perhaps you will find it useful in your own projects. These lines have several advantages over using hardcoded images or standard Direct3D lines:
I create one vertex buffer that is used for every line. I didn't want to be locking and modifying the VB for different line lengths, so I stretch the line out in the vertex shader. I store some special values in the texture coordinates that tell the VS which vertices to scale and/or translate to get them from "unstretched model space" to "stretched model space." The length and radius are passed in per-line as shader constants. Once the line is stretched, I apply the usual world/view/projection transformation as is done for normal geometry. Blurring and other effects are done in the pixel shader.
The image below shows some Lines:
I looked into using hardware instancing, so a whole list of lines could be drawn in one Direct3D call, but it didn't look to be worth the trouble, and hardware support for instancing varies on the Windows platform.
In the pixel shader, I have information about how far each pixel is from the "true" (zero-thickness) line segment, and I also have the stretched model space X value (ranging from 0 to the length of the segment). There's also a time parameter for animation. These values help enable interesting effects through the pixel shader. The effect file has techniques for each of the following visual effects:
Here's the AnimatedRadial effect:
The Draw function takes a List<Line> rather than a single Line, so the effect setup cost gets amortized across a series of Lines. With each call to Draw, you can pass in a constant radius and/or color to use for all the Lines, or you can have Draw use the individual radius / color stored in each Line. All the Lines have to be drawn with the same technique, though.
I also threw in a Line.DistanceSquaredToPoint() method that returns the distance (squared) from the "true" line segment (ignoring the radius) to a Vector2D. That method isn't used by the demo, but could be handy for collision detection.
One thing that's not perfect about these lines is that you get an artifact with the blurring where two Lines' endpoints overlap. The blur draws once for each endcap, and since the alpha blending uses an additive effect, you end up with a slight "bump" in the blur. I couldn't find a blending mode that would eliminate this artifact. A more sophisticated implementation of the Line code might be able to avoid unnecessary double-drawing of the endcaps, but in most cases it doesn't seem to be a problem.
Also, the blur is currently set to a constant fraction of the line radius, so it may be too little or too much blur depending on the zoom level and/or line radius. It should be dynamic based on the thickness of the line in screen space, in order to blur just the right amount.
The LinesDemo program (attached) shows some examples of various usages of the Line code. I've only tested it on Windows so far. It requires a graphics card that supports shader models VS 1.1 and PS 2.0.
The controls are:
Feel free to use this code in your own projects and customize it as you like to work the way you want. Let me know if you find it helpful!
NOTE (3/20/2009): A newer version of this code is now maintained at http://roundline.codeplex.com . See here for more info.