VectorLine

Author: Eric Haines (Eric5h5)

Description
Draws a vector line on the screen based on normalized viewport coordinates. The line can have an arbitrary width, color, and number of segments, and is defined by an array of Vector2s. Requires Unity Pro, since it uses the GL class.



Usage
Put this script on a camera. The public variables control the number of points in the line, its color, its thickness, and whether the line should be drawn or not (because disabling the script doesn't stop the OnPostRender function from running). The linePoints array is an array of Vector2s in normalized viewport coordinates (i.e. (0, 0) is the lower-left corner of the screen and (1,1) is the upper-right). Currently only one contiguous line is supported, but it would be easy enough to modify it to use an array of Vector2s in order to draw multiple separate lines, if so inclined. A sample routine, which results in the image above:

This should be in the same script with the VectorLine code, below.

VectorLines.cs
The following is a version of the C# script that handles multiple lines at once, updated via UpdateLines each frame.  using UnityEngine; using System.Collections; using System.Collections.Generic;

[RequireComponent(typeof (Camera))] public class VectorLines : MonoBehaviour {	// Lists of properties for each line public Color lineColor; public int lineWidth; public bool drawLines = true; // Material and camera private Material lineMaterial; private Camera cam; // List of lines (each a list of vertices) and getter/setter private List> linePoints; void Awake {		lineMaterial = new Material( "Shader \"Lines/Colored Blended\" {" +       "SubShader { Pass {" +        "   BindChannels { Bind \"Color\",color }" +        "   Blend SrcAlpha OneMinusSrcAlpha" +        "   ZWrite Off Cull Off Fog { Mode Off }" +        "} } }"); lineMaterial.hideFlags = HideFlags.HideAndDontSave; lineMaterial.shader.hideFlags = HideFlags.HideAndDontSave; cam = camera; }	public void InitializeLines(List> newPointsList) {		// Creates new list of points linePoints = new List>; for (int i = 0; i < newPointsList.Count; ++i) {			List newList = new List; for (int j = 0; j < newPointsList[i].Count; ++j) {				newList.Add(newPointsList[i][j]); }			linePoints.Add(newList); }	}	public void UpdateLines(List> updatedPoints) {		// Sets all points of list to update list of points for (int i = 0; i < linePoints.Count; ++i) for (int j = 0; j < linePoints[i].Count; ++j) linePoints[i][j] = updatedPoints[i][j]; }	void OnPostRender {		// Cycles through each separate line for (int i = 0; i < linePoints.Count; ++i) {			if (!drawLines || linePoints == null || linePoints[i].Count < 2) return; float nearClip = cam.nearClipPlane + 0.00001f; int end = linePoints[i].Count - 1; float thisWidth = 1f/Screen.width * lineWidth * 0.5f; lineMaterial.SetPass(0); GL.Color(lineColor); if (lineWidth == 1) {		       GL.Begin(GL.LINES); for (int j = 0; j < end; ++j) {		           GL.Vertex(cam.ViewportToWorldPoint(new Vector3(linePoints[i][j].x, linePoints[i][j].y, nearClip))); GL.Vertex(cam.ViewportToWorldPoint(new Vector3(linePoints[i][j+1].x, linePoints[i][j+1].y, nearClip))); }	   	}	    	else {		       GL.Begin(GL.QUADS); for (int j = 0; j < end; ++j) {		           Vector3 perpendicular = (new Vector3(linePoints[i][j+1].y, linePoints[i][j].x, nearClip) -		                                 new Vector3(linePoints[i][j].y, linePoints[i][j+1].x, nearClip)).normalized * thisWidth; Vector3 v1 = new Vector3(linePoints[i][j].x, linePoints[i][j].y, nearClip); Vector3 v2 = new Vector3(linePoints[i][j+1].x, linePoints[i][j+1].y, nearClip); GL.Vertex(cam.ViewportToWorldPoint(v1 - perpendicular)); GL.Vertex(cam.ViewportToWorldPoint(v1 + perpendicular)); GL.Vertex(cam.ViewportToWorldPoint(v2 + perpendicular)); GL.Vertex(cam.ViewportToWorldPoint(v2 - perpendicular)); }	   	}	    	GL.End; }	}	void OnApplicationQuit {		DestroyImmediate(lineMaterial); } }