Get Shapes 💖
 
Documentation
 
Changelog
 
Feedback
Bugs & Feature Requests

Index

Shapes

To add shapes to your scene, go to the top menu bar Shapes/Create/...
Line
Lines are defined by a Start point and an End point, along with a configurable Thickness. As with many other shapes, you can set Thickness Space to various units, so you can specify Thickness in either meters, pixels or noots.

Geometry

Flat 2D lines are flat on the local space XY plane, ignoring Z. This is useful for making lines that are locked to a plane, such as in 2D games, or for a 2D surface in a 3D world such as a screen or minimap
Billboard lines are positioned in 3D space, still using a quad mesh, always trying to face the camera. Useful for a cheap way of drawing 3D lines without using much geometry
Volumetric 3D lines are using actual polygons to render a 3D line with the given Thickness

End Caps

No Caps - cuts off immediately at each endpoint
Square Caps - extends by half the Thickness at each endpoint
Round Caps - extends by half the Thickness at each endpoint, rounding the corners

Dashed Lines

Dash Size and Dash Spacing are either in meters, relative to thickness, or a fixed count across the shape, depending on what Dash Space is set to. Dash Offset is always relative to a single period, which means integer values always look the same. Here are some example dashes, when set to Relative dash spacing
size 1, spacing 1
size 2, spacing 1
size 2, spacing 0.5
size 3, spacing 3
size 3, spacing 3, offset 0.5

Blend ModeTransparent vs Opaque
ColorColor of the line, or, the color of the starting point, when two colors are used
Color EndColor of the endpoint when two colors are used
Thickness
StartLocal space starting point
EndLocal space endpoint
GeometryFlat 2D, Billboard, or Volumetric 3D
Color ModeSingle color, or a gradient from start to end
End CapsNo caps, Square caps or Round caps
DashedDashed or solid
Dash SpaceThe space in which Size and Spacing is defined.
  • Meters
  • Relative (to Thickness), which means a dash size of 1 is always a square dash
  • Fixed Count, where Size is the number of repeating periods across the shape, and Spacing is the fraction (0 to 1) of which should be space
Dash SizeLength of a single dash. When Dash Space is set to fixed count, this is the repeat count
Dash SpacingSize of the space between dashes. When Dash Space is set to fixed count, this is a value from 0 to 1, where 0.5 means dashes and spaces have the same size
Dash OffsetOffset of dashes, relative to the repeating period, where 1 = offset by the length of one dash+space, which means that it tiles/repeats at every integer
Dash TypeType of dash, either Basic, Angled or Rounded
Dash SnapSnap Dashes to the full length of the shape.
  • Off
  • Tiling (ensures a repeating pattern, ends with space)
  • End To End (ensures a dash is snapped at each end)
Vertex & Triangle Count
4 verts3 trisFlat 2D or Billboard
98 verts92 trisVolumetric 3D, square or no caps
448 verts768 trisVolumetric 3D, round caps

Polyline
Polylines describe a line drawn along a path made of multiple points. A Closed polyline means it's cyclical, its ends are connected. A non-Closed path on the other hand has two endpoints. The Polyline Points use both a global Color, as well as per-point colors, these are multiplied together! You can think of the color as a tint color.
Just like the lines, you can set Thickness and Thickness Space to various units, scaled by the per-point thickness.

Joins

Simple - corners set thickness by vertex distance. Also known as Bad™ joins. These are the cheapest of all! Useful for when you have high point density and don't want mitering effects, or when you just want something cheap!
Miter - corners are extended to the line's intersection point. Note that they may shoot off into infinity with very sharp corners. Don't cut yourself on these pointybois
Bevel - corners are chipped off at their halfway angle, not sure who uses these joins to be honest but they're like always a thing
Round - corners are rounded off all soft, cuddly and good~

Geometry

Flat 2D polylines are flat on the local space XY plane, ignoring Z. This is useful for making lines that are locked to a plane, such as in 2D games, or for a 2D surface in a 3D world such as a screen or minimap
Billboard polylines are positioned in 3D space, still using a flat mesh, always trying to face the camera. Useful for a cheap way of drawing 3D lines without using much geometry

Blend ModeTransparent vs Opaque
ColorUniform color, tinted by per-point color
ThicknessUniform thickness, scaled by per-point thickness
ClosedOpen ends or closed loop
GeometryFlat 2D or billboard
JoinsMiter, round or bevel joins
PointsPoints and their corresponding colors and thicknesses
Vertex & Triangle Count
2n verts2n-2 trisMiter, Open
2n verts2n trisMiter, Closed
8n-6 verts5n-6 trisBevel, Open
8n vertsn+4 trisBevel, Closed
10n-10 verts3n-2 trisRounded, Open
10n verts3n+4 trisRounded, Closed

Disc
The Disc is a versatile shape encapsulating various Disc Types, including pie, ring and arc.
When in ring or arc mode, Radius is not the distance to the outer edge, but rather distance to the center of a cross section of the ring. This is so that you can specify Thickness and Radius in separate units, with predictable results.
When drawing arcs or pies, you specify a Start Angle and an End Angle. You can select what angular unit you want to use in the inspector. Note that if you access the disc through code, angles are always in radians.

Types

Disc
Pie 🥧
Ring
Arc

Color Modes

Single color
Radial gradient
Angular gradient
Bilinear gradient between 4 colors

Dashed Rings & Arcs

Dash Size and Dash Spacing are either in meters, relative to thickness, or a fixed count across the shape, depending on what Dash Space is set to. Dash Offset is always relative to a single period, which means integer values always look the same. Here are some example dashes, when set to Relative dash spacing
size 1, spacing 1
size 2, spacing 1
size 2, spacing 0.5
size 3, spacing 3
size 3, spacing 3, offset 0.5

Blend ModeTransparent vs Opaque
ColorColor of the disc, Radial Inner, Angular Start or Bilinear Inner Start
Color Outer StartColor of Radial Inner or Bilinear Outer Start
Color Inner EndColor of Angular End or Bilinear Inner End
Color Outer EndColor of Bilinear Outer End
Color ModeSingle, Radial, Angular or Bilinear colors
GeometryFlat 2D or Billboard
Disc TypeDisc, Pie, Ring or Arc
RadiusRadius of Disc & Pie. Radius to center of ring for Ring & Arc
ThicknessThickness of Ring & Arc
Angle StartStart Angle for Pie & Arc, stored as radians in code
Angle EndEnd Angle for Pie & Arc, stored as radians in code
Arc End CapWhether or not the Arc ends should be rounded
DashedDashed or solid
Dash SpaceThe space in which Size and Spacing is defined.
  • Meters
  • Relative (to Thickness), which means a dash size of 1 is always a square dash
  • Fixed Count, where Size is the number of repeating periods across the shape, and Spacing is the fraction (0 to 1) of which should be space
Dash SizeLength of a single dash. When Dash Space is set to fixed count, this is the repeat count
Dash SpacingSize of the space between dashes. When Dash Space is set to fixed count, this is a value from 0 to 1, where 0.5 means dashes and spaces have the same size
Dash OffsetOffset of dashes, relative to the repeating period, where 1 = offset by the length of one dash+space, which means that it tiles/repeats at every integer
Dash TypeType of dash, either Basic, Angled or Rounded
Dash SnapSnap Dashes to the full length of the shape.
  • Off
  • Tiling (ensures a repeating pattern, ends with space)
  • End To End (ensures a dash is snapped at each end)
Vertex & Triangle Count
4 verts2 tris

Rectangle
Rectangles have a Size in width and height, support rounded corners with a specific Radius, as well as optionally being hollow with a given Thickness. In addition, you can set the Pivot to be either in the bottom left or center of the rectangle
Blend ModeTransparent vs Opaque
ColorColor (RGB) & opacity (A)
StyleHard vs rounded corners & hollow vs solid
PivotWhether size should be relative to the center or bottom left
SizeWidth and height
ThicknessThickness, when hollow
RadiusCorner radius, when using rounded corners
Vertex & Triangle Count
4 verts2 tris

Quad
Unlike the rectangle, the quad is positioned with each vertex at an arbitrary point in 3D space. The Quad supports four Color Modes, Single Color, Horizontal Gradient, Vertical Gradient and Per-Corner Colors. Color interpolation across a quad is surprisingly nontrivial though, so in light of that, you can configure quality level by changing QUAD_INTERPOLATION_QUALITY in Shape Config.cginc if you want higher or lower quality depending on your needs
Blend ModeTransparent vs Opaque
ColorColor of A, or color of the whole quad. Left color of h-gradient, bottom of v-gradient
Color BColor of B, or top color for vertical gradients
Color CColor of C, or right color for horizontal gradients
Color DColor of D
Color ModeSingle color, horizontal gradient, vertical gradient or per-corner colors
ALocal space position of A
BLocal space position of B
CLocal space position of C
DLocal space position of D
Auto-Set DAutomatically position D based on the other points to form a planar rhombus/rhomboid
Vertex & Triangle Count
4 verts2 tris

Triangle
Similar to the Quad primitive, Triangles are positioned on a per-vertex basis. Its Color Mode is either Single Color or Per-Corner
Blend ModeTransparent vs Opaque
ColorColor of A for per-corner colors, or color of the quad
Color BColor of B for per-corner colors
Color CColor of C for per-corner colors
Color ModeSingle color or per-corner colors
ALocal space position of A
BLocal space position of B
CLocal space position of C
Vertex & Triangle Count
3 verts1 tri

Regular Polygon
Regular Polygons have equal side lengths and angles. With this shape you can make equilateral triangles, pentagons, hexagons, and any other regular polygon!
Blend ModeTransparent vs Opaque
ColorColor (RGB) & opacity (A)
GeometryFlat 2D or Billboard
SidesNumber of sides
RadiusCenter-to-vertex radius
HollowWhether or not this should be hollow
ThicknessThickness (when hollow)
RoundnessA value from 0 to 1, that can round off corners. 0 is completely sharp, 1 is a perfect circle
AngleAngle of rotation, stored as radians in code
FillGradient color filling
Vertex & Triangle Count
4 verts2 tris

Polygon
The Polygon shape is a 2D surface allowing for any number of points (within, you know, reason). The polygon allows for any non-self-intersecting simple polygons, including concave ones, as long as the Triangulation is set to Ear Clipping. While Polygons don't allow for per-vertex colors, it does have support gradient fills!
Blend ModeTransparent vs Opaque
ColorColor (RGB) & opacity (A)
TriangulationWhat method to use when triangulating this polygon. Fast Convex Only is a faster algorithm, but only allows for convex shapes. Ear Clipping supports concave shapes.
FillGradient color filling
Vertex & Triangle Count
Vertex count = number of points
Triangle count = number of points - 2

Sphere
It's a sphere

Blend ModeTransparent vs Opaque
ColorColor (RGB) & opacity (A)
Radius
Vertex & Triangle Count
423 verts720 tris

Torus
Torus with configurable Radius and Thickness, with separate units. This makes it possible to make a torus with a Radius in meters but a Thickness in, say, pixels, which can be useful for making gizmo-like shapes. The torus is oriented so that the axis of revolution / normal direction is along its Z axis

Blend ModeTransparent vs Opaque
ColorColor (RGB) & opacity (A)
RadiusRadius of the torus, also known as major radius
Thickness
Vertex & Triangle Count
825 verts1536 tris

Cone
A cone with configurable Radius and Length. Optionally, you can toggle the bottom Cap on and off, in case you want a hollow cone
Blend ModeTransparent vs Opaque
ColorColor (RGB) & opacity (A)
RadiusRadius of the base
LengthDistance from base to tip
Fill CapFilled or hollow base
Vertex & Triangle Count
33 verts62 triscapped
33 verts32 trisuncapped

Cuboid
A cuboid! Equivalent to a cube if Size is the same along each axis
Blend ModeTransparent vs Opaque
ColorColor (RGB) & opacity (A)
SizeSize along each axis, end to end
Vertex & Triangle Count
8 verts12 tris

Immediate-Mode Drawing

Shapes.Draw is the main class for immediate mode drawing, and has two core parts:
  • Drawing functions like Draw.Line, Draw.Disc, Draw.Torus...
  • Static global properties for subsequent Draw.X calls, such as Draw.Color, Draw.LineThickness, Draw.BlendMode...
For example, drawing the world xyz basis vectors at the origin, with 4px wide lines using 3D geometry, in OnDrawGizmos:
void OnDrawGizmos(){
	// set up all static parameters. these are used for all following Draw.Line calls
	Draw.LineGeometry = LineGeometry.Volumetric3D;
	Draw.LineThicknessSpace = ThicknessSpace.Pixels;
	Draw.LineThickness = 4; // 4px wide

	// draw lines
	Draw.Line( Vector3.zero, Vector3.right,   Color.red   );
	Draw.Line( Vector3.zero, Vector3.up,      Color.green );
	Draw.Line( Vector3.zero, Vector3.forward, Color.blue  );
}
In this case, we used global properties for many of the line properties, but we set color per-line, overriding the global Draw.Color

You can override all properties in the draw functions too, but, do note that the core draw functions have *many* parameters, most of which you generally don't want to set on a per-call basis. For example, Draw.Line's core draw function has 12 parameters.

You can find all the global properties in DrawState.cs, the core drawing functions for all immediate mode shapes in Draw.cs, and all the shorthands/overloads of the drawing functions in the, uh, incredibly dense DrawOverloads.cs

Drawing Contexts

Drawing in immediate mode with Shapes is equivalent to using Material.SetPass and Graphics.DrawMeshNow. This means that the timing and the context in which you draw matters a lot. Here are a few places you can call immediate mode drawing:

Polylines

Polylines can be drawn in several ways. The first and most flexible one is to create a temporary PolylinePath, then specify its points, and finally drawing it. This method will automatically dispose of mesh data at the end of its scope, since it's in a using block
void OnPostRender(){
	using( var p = new PolylinePath() ){
		p.AddPoint( -1, -1 );
		p.AddPoint( -1,  1 );
		p.AddPoint(  1,  1 );
		p.AddPoint(  1, -1 );
		Draw.Polyline( p, closed:true, thickness:0.1f, Color.red ); // Drawing happens here
	} // Disposing of mesh data happens here
}

The above code will recreate the polyline mesh every time you draw it. If you instead want a persistent polyline that you can modify instead of recreate all the time, you can create a PolylinePath in, say, Awake, and then, importantly, dispose it when you're done with it, usually in OnDestroy or OnDisable. This ensures any mesh data is cleaned up properly
PolylinePath p;
void Awake(){
	p = new PolylinePath();
	p.AddPoint( -1, -1 );
	p.AddPoint( -1,  1 );
	p.AddPoint(  1,  1 );
	p.AddPoint(  1, -1 );
} 
void OnPostRender() => Draw.Polyline( p, closed:true, thickness:0.1f, Color.red ); // Drawing happens here
void OnDestroy() => p.Dispose(); // Disposing of mesh data happens here

Anti-Aliasing

Shapes will look best across the board when your project is using some form of anti-aliasing. 8xMSAA is recommended! Some shapes however, also have built-in local anti-aliasing, which means that they will have smooth edges even when your project has no AA method enabled.

Local Anti-Aliasing

Local anti-aliasing or LAA, is when shapes themselves have built-in AA, even when your project/camera isn't using anti-aliasing as a whole. LAA is available for most 2D shapes when using a non-opaque blending mode, current exceptions are:
  • Quads, Triangles & (non-regular) Polygons
  • Rectangle (partial support)

  • You can disable or change the quality of local anti-aliasing with LOCAL_ANTI_ALIASING_QUALITY in Shapes Config.cginc
    No LAA Fast LAA Corrected LAA
    The difference between Fast and Corrected LAA is subtle - Fast LAA has a slight bias in the diagonal directions, making circular shapes appear ever so slightly rhombous and have a slightly sharper curvature in the orthogonal directions, especially when small. Sometimes the edges in the diagonals are slightly fuzzy as well. Corrected AA fixes both of these issues, but uses a slightly more expensive calculation.

    Line Thinness Fading

    Lines thinner than 1 pixel, will be locked at 1 pixel wide, and instead start fading opacity based on pixel coverage. This is a very useful technique to ensure that thin lines don't get the pixelated wandering ants effect. Note that this is applied regardless of sizing methods - lines with thickness set in meters will also behave this way as soon as it's smaller than 1 pixel on screen.
    Together with MSAA or LAA, you can get very smooth looking lines. Here's a comparison of a billboard polyline arranged in a sphere, with various options toggled
    AA off
    No Thin Fade
    AA on
    No Thin Fade
    AA off
    Thin Fade
    AA on
    Thin Fade

    Blend Modes & Transparency Sorting

    Opaque

    Opaque writes to the depth buffer, and sorts properly even when intersecting other shapes. However, it does not support transparency, unless you have MSAA enabled, in which case it will use alpha to coverage to approximate alpha blending. This is especially useful for short alpha fades, such as the edges of the disk shape. Note that MSAA does not work in the scene view, Opaque shapes in the scene view with alpha less than 0.5 are completely invisible, and those above 0.5 are completely opaque
  • Alpha-to-Coverage fading support with MSAA enabled
  • Writes to the depth buffer
  • Opaque 2D Shapes support LAA if MSAA is enabled
  • Transparent

    Also known as alpha blending - this mode uses the alpha channel of its color as opacity for full transparency support. However, it doesn't write to the depth buffer, which means that intersecting and overlapping shapes using this blend mode may not sort properly
  • Fades based on alpha
  • Order dependent, prone to sorting issues
  • Does not write to the depth buffer
  • LAA support (2D shapes only)
  • Additive

    Additive is good for glowing/brightening effects against dark backgrounds
  • Fades based on alpha, this allows you to fade toward a color while also fading out completely
  • Order independent
  • Does not write to the depth buffer
  • LAA support (2D shapes only)
  • Multiplicative

    Multiplicative is good for tinting/darkening effects against bright backgrounds
  • Fades based on alpha, this allows you to fade toward a color while also fading out completely
  • Order independent
  • Does not write to the depth buffer
  • LAA support (2D shapes only)
  • Meters, Pixels & Noots

    Shapes with a given thickness, width or radius, generally have configurable units to specify in what space the thickness should be in

    Meters, m

    Meters relate to the scale of your world, rather than pixels or any other screen-space unit. A line with a thickness in meters, will look thinner when you're further away, just like any other geometry in your game

    Pixels, px

    Pixels are screen-space units, where 1 unit covers a single pixel on your screen. This means that the distance from the camera to the shape won't affect its thickness on screen, and will instead always have a consistent pixel size

    Noots, nt

    Noots are pixel-density independent screen-space units, defined as a fraction of the minimum dimension of your resolution.
    By default, there are 100 noots across the shortest dimension of your resolution, so if you are running 1920x1080, then 1 noot will be min(1920,1080)/100 = 1080/100 = 10.8 pixels wide.
    You can configure NOOTS_ACROSS_SCREEN in Shapes Config.cginc if you want to change the default 100 to something else

    Degrees, Turns & Radians

    For shapes that involve angles, you can specify the angles in three different units in the inspector

    Degrees

    define a full turn as 360°, meaning a quarter turn is the familiar 90° angle

    Turns

    define a full turn as 1, which is useful when thinking in fractions of a full turn, where 0.5 is halfway around the circle, 0.25 is a quarter way around, and so forth!

    Radians

    define a full turn as 6.28... = 2π = τ, which is useful in math formulas involving angles, arc lengths, and other relationships of the circle. Internally, angles are always in radians, across the entire library of Shapes. If you want to convert from degrees to radians, you can use degrees*Mathf.Deg2Rad, or turns to radians using turns*ShapesMath.TAU

    Performance

    Shapes is designed to be as light on the CPU as possible, by offloading much of the work to the GPU, which means the CPU can focus on your game, while the GPU takes care of all the drawing.

    General performance considerations

  • Shapes is supported on all platforms that support GPU instancing
  • Shapes works on mobile, though you need to keep general optimization things in mind
  • Avoid having expensive shaders covering many pixels. The more feature rich a shape is, the more expensive it is in general. A good example is the Arc, if you enable end caps and use bilinear color and make it dashed, this means it's now more expensive to render, and you should avoid having them cover a large part of the screen
  • Polygons and the Polylines both generate meshes on the fly when they are modified. They might be expensive on the CPU end in some cases, if you use a lot of points

  • Now, performance will also vary depending on what side of the library you are using and what you are doing with Shapes:

    Component Shapes

    These will be part of Unity's regular render pipelines, which means they will gain all the benefits of instancing - most shapes of the same type will be a single draw call, since they can all share the same mesh! However, as a tradeoff, this means that Unity is not able to frustum cull Shapes automatically, so if you construct an entire game using shapes you might start running into performance issues, but in general they'll be very fast. Tweaking parameters like radius and colors and all of that, is essentially free, and all of these things are simple shader parameters in the end! With the exception of polyline, since that one requires a mesh to update if you change points. Though, even that mesh is generated without any heavy math on the CPU, as it's only passing data rather than doing complex miter join calcs etc.

  • Shapes of the same type are GPU instanced
  • Tweaking per-instance parameters like radius and color is free and doesn't break instancing
  • Polylines and Polygons can't be instanced
  • Immediate-Mode Shapes

    Immediate-mode is by nature, well, drawn immediately, which means they will be outside any kind of render pipeline or batching systems, for better or worse!

  • Each immediate-mode draw is one draw call
  • No instancing or batching
  • UI

    To use Shapes in UI, set your UI to either camera-based or world-space UI, this makes Shapes show up!
    Another alternative is to render shapes into a render target, and display the render target in UI

    Overlay UI mode is however, not supported, using canvas renderers, rect transforms and all, unfortunately.
    It was never actually designed as a UI library, so it wasn't the primary use-case I was focusing on getting up and running, but it was a secondary use case I wanted. However, the reason it doesn't support overlay mode is because it's frankly a nightmare, so the workaround will have to do