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 Mode
What blend mode to use when drawing this shape
Color
Color of the line, or, the color of the starting point, when two colors are used
Color End
Color of the endpoint when two colors are used
Thickness
How thick this shape should be, in the given Thickness Space
Thickness Space
What space Thickness is defined in
Start
Local space starting point
End
Local space endpoint
Geometry
Flat 2D, Billboard, or Volumetric 3D
Color Mode
Single color, or a gradient from start to end
End Caps
No caps, Square caps or Round caps
Dashed
Dashed or solid
Dash Space
The 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 Snap
Snap 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)
Dash Size
Length of a single dash. When Dash Space is set to fixed count, this is the repeat count
Dash Spacing
Size 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 Offset
Offset 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 Type
Type of dash, either Basic, Angled or Rounded
Dash Modifier
Changes the shape of certain dash types
Vertex & Triangle Count
4 verts
3 tris
Flat 2D or Billboard
Volumetric 3D lines triangle/vert count depends on your 3D primitive detail in the settings window
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 Mode
What blend mode to use when drawing this shape
Color
Uniform color, tinted by per-point color
Thickness
Uniform thickness, in the given Thickness Space, scaled by per-point thickness
Thickness Space
What space Thickness is defined in
Closed
Open ends or closed loop
Geometry
Flat 2D or billboard
Joins
Miter, round or bevel joins
Points
Points and their corresponding colors and thicknesses
Vertex & Triangle Count
2n verts
2n-2 tris
Miter, Open
2n verts
2n tris
Miter, Closed
8n-6 verts
5n-6 tris
Bevel, Open
8n verts
n+4 tris
Bevel, Closed
10n-10 verts
3n-2 tris
Rounded, Open
10n verts
3n+4 tris
Rounded, 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 Mode
What blend mode to use when drawing this shape
Color
Color of the disc, Radial Inner, Angular Start or Bilinear Inner Start
Color Outer Start
Color of Radial Inner or Bilinear Outer Start
Color Inner End
Color of Angular End or Bilinear Inner End
Color Outer End
Color of Bilinear Outer End
Color Mode
Single, Radial, Angular or Bilinear colors
Geometry
Flat 2D or Billboard
Disc Type
Disc, Pie, Ring or Arc
Radius
Radius of Disc & Pie. Radius to center of ring for Ring & Arc
Thickness
Thickness of Ring & Arc
Angle Start
Start Angle for Pie & Arc, stored as radians in code
Angle End
End Angle for Pie & Arc, stored as radians in code
Arc End Cap
Whether or not the Arc ends should be rounded
Dashed
Dashed or solid
Dash Space
The 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 Snap
Snap 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)
Dash Size
Length of a single dash. When Dash Space is set to fixed count, this is the repeat count
Dash Spacing
Size 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 Offset
Offset 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 Type
Type of dash, either Basic, Angled or Rounded
Dash Modifier
Changes the shape of certain dash types
Vertex & Triangle Count
4 verts
2 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 Mode
What blend mode to use when drawing this shape
Color
Color (RGB) & opacity (A)
Style
Hard vs rounded corners & hollow vs solid
Pivot
Whether size should be relative to the center or bottom left
Width
Width of the rectangle. Displayed as Size X in the inspector
Height
Height of the rectangle. Displayed as Size Y in the inspector
Thickness
How thick this shape should be, in the given Thickness Space
Thickness Space
What space Thickness is defined in
Corner Radius Mode
Whether to use the same radius for all corners, or separate radii
Corner Radius
Gets or sets the corner radius for all four corners, in meters
Corner Radii
Gets or sets each corner radius, in meters (Order is clockwise, starting bottom left)
Dashed
Dashed or solid
Dash Space
The 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 Snap
Snap 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)
Dash Size
Length of a single dash. When Dash Space is set to fixed count, this is the repeat count
Dash Spacing
Size 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 Offset
Offset 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 Type
Type of dash, either Basic, Angled or Rounded
Dash Modifier
Changes the shape of certain dash types
Fill
Gradient color filling
Vertex & Triangle Count
4 verts
2 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 Shapes settings if you want higher or lower quality depending on your needs
Blend Mode
What blend mode to use when drawing this shape
Color
Color of A, or color of the whole quad. Left color of h-gradient, bottom of v-gradient
Color B
Color of B, or top color for vertical gradients
Color C
Color of C, or right color for horizontal gradients
Color D
Color of D
Color Mode
Single color, horizontal gradient, vertical gradient or per-corner colors
A
Local space position of A
B
Local space position of B
C
Local space position of C
D
Local space position of D
Auto-Set D
Automatically position D based on the other points to form a planar rhombus/rhomboid
Vertex & Triangle Count
4 verts
2 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 Mode
What blend mode to use when drawing this shape
Color
Color of A for per-corner colors, or color of the quad
Color B
Color of B for per-corner colors
Color C
Color of C for per-corner colors
Color Mode
Single color or per-corner colors
A
Local space position of A
B
Local space position of B
C
Local space position of C
Border
Whether it should outline the border or fill the shape
Thickness
How thick this shape should be, in the given Thickness Space
Thickness Space
What space Thickness is defined in
Roundness
A value from 0 to 1 that rounds off corners. 0 is completely sharp, 1 is a large round circle
Vertex & Triangle Count
3 verts
1 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 Mode
What blend mode to use when drawing this shape
Color
Color (RGB) & opacity (A)
Geometry
Flat 2D or Billboard
Sides
Number of sides
Radius
Center-to-vertex radius
Radius Space
What space Radius is defined in
Border
Whether it should outline the border or fill the shape
Thickness
How thick this shape should be, in the given Thickness Space
Thickness Space
What space Thickness is defined in
Roundness
A value from 0 to 1 that rounds off corners. 0 is completely sharp, 1 is a large round circle
Angle
Angle of rotation, stored as radians in code
Fill
Gradient color filling
Vertex & Triangle Count
4 verts
2 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 Mode
What blend mode to use when drawing this shape
Color
Color (RGB) & opacity (A)
Triangulation
What 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.
Fill
Gradient color filling
Vertex & Triangle Count
Vertex count = number of points Triangle count = number of points - 2
Sphere
It's a sphere
Blend Mode
What blend mode to use when drawing this shape
Color
Color (RGB) & opacity (A)
Radius
Radius Space
What space Radius is defined in
Sphere triangle/vert count depends on your 3D primitive detail in the settings window
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 Mode
What blend mode to use when drawing this shape
Color
Color (RGB) & opacity (A)
Radius
Radius of the torus, also known as major radius
Radius Space
What space Radius is defined in
Thickness
How thick this shape should be, in the given Thickness Space
Thickness Space
What space Thickness is defined in
Torus triangle/vert count depends on your 3D primitive detail in the settings window
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 Mode
What blend mode to use when drawing this shape
Color
Color (RGB) & opacity (A)
Radius
Radius of the base
Length
Distance from base to tip
Size Space
What space to use when setting the size
Fill Cap
Filled or hollow base
Vertex & Triangle Count
Cone triangle/vert count depends on your 3D primitive detail in the settings window
Cuboid
A cuboid! Equivalent to a cube if Size is the same along each axis
Blend Mode
What blend mode to use when drawing this shape
Color
Color (RGB) & opacity (A)
Size
Size along each axis, end to end
Size Space
What space to use when setting the size
Vertex & Triangle Count
8 verts
12 tris
Immediate-Mode Drawing
Drawing in immediate mode is useful when you want to draw from code, or for shapes that are only temporary, procedural, or where you don't want to deal with the overhead of GameObjects. Immediate mode is instantaneous - it renders only once in the camera you draw in, so if you want to continuously draw, you draw every frame! This means it's very easy to create dynamic setups where what is being drawn can always change with no overhead of destroying or creating GameObjects
Example
[ExecuteAlways] public classMyScript : ImmediateModeShapeDrawer {
publicoverridevoidDrawShapes( Camera cam ){
using( Draw.Command( cam ) ){
// set up static parameters. these are used for all following Draw.Line callsDraw.LineGeometry = LineGeometry.Volumetric3D;
Draw.ThicknessSpace = ThicknessSpace.Pixels;
Draw.Thickness = 4; // 4px wide// set static parameter to draw in the local space of this objectDraw.Matrix = transform.localToWorldMatrix;
// draw linesDraw.Line( Vector3.zero, Vector3.right, Color.red );
Draw.Line( Vector3.zero, Vector3.up, Color.green );
Draw.Line( Vector3.zero, Vector3.forward, Color.blue );
}
}
}
Attach this script to any object, and it will draw three 4px wide 3D lines along each axis at the center of the world, with different colors. Let's break it down:
ImmediateModeShapeDrawer
This is a helper class you can inherit from, that will make drawing in immediate mode a little bit easier when overriding the DrawShapes() method. This method is called once for every active camera, including the scene view if your script is marked with [ExecuteAlways]. Internally, this is just a wrapper for the camera OnPreRender callback, subscribed to in OnEnable and unsubscribed from in OnDisable. If you don't use this class, then it is highly recommended that you use the appropriate OnPreRender callback for your render pipeline when issuing draw commands
Draw.Command(...)
using( Draw.Command( myCamera ) ){} sets up a scope in which you can issue draw commands to the specified camera.
Consecutive draw commands of the same type inside of this scope will be GPU instanced, so avoid alternating between types of shapes if you want to use less draw calls
ImmediateModeShapeDrawer automatically hooks into these functions in a render pipeline agnostic way, so all you need to do is override DrawShapes() and set up the draw command in there
While you can set up draw commands in Update(), it is not recommended. The reason for this is because it's important to not add more commands than you're rendering, as this will stack draw calls. If you're worried about this, you can always go to Shapes/Immediate Mode Monitor in Unity, to make sure nothing is leaking
Shapes.Draw (static properties)
Shapes.Draw is the main class for immediate mode drawing, and has two core parts. First, it contains static styling properties that will configure how all following Shapes should be drawn. For example:
Draw.Color = Color.red; will make all following Shapes default to red
Draw.LineGeometry = LineGeometry.Volumetric3D; will make lines be drawn using 3D geometry instead of flat quads
Draw.ThicknessSpace = ThicknessSpace.Pixels; will set the thickness space of all shapes to use pixels instead of meters
Draw.Thickness = 4; will make all shapes lines have a width of 4 (pixels, in this case)
The list above is just a handful of the many static properties in there that you may find useful! Your IDE should be able to show you all available properties to edit if you type Draw.
Note that when dealing with static properties, it's important to keep in mind that they are global. It's often useful to reset the static states right before issuing your draw commands, so that the states are guaranteed to be consistent, and not unintentionally use values that were set elsewhere
Draw.ResetStyle() will reset all styling properties (but not the matrix)
Draw.ResetMatrix() will reset the matrix (see below)
Draw.ResetAllDrawStates() will reset everything
Shapes.Draw (drawing matrix)
You can also set the matrix to use when drawing. A matrix is like a transform - it contains position, rotation and scale, all in one type. In other words, this allows you to draw relative to something other than world space
Draw.Matrix = Matrix4x4.TRS( pos, rot, scale ); makes drawing relative to this position/rotation/scale
Draw.ResetMatrix() will reset the matrix to the default value of Matrix4x4.identity
Shapes.Draw (draw calls)
Shapes.Draw also contains the actual draw calls - in this case, we are using Draw.Line in order to draw simple line segments, but it contains lots of other shapes
Draw.Line Draws a line between two points
Draw.Polyline Draws a polyline along a path (see usage below)
Draw.Disc Draws a solid disc/filled circle
Draw.Ring Draws a ring/circle with a given thickness
Draw.Pie Draws a pie/circle sector
Draw.Arc Draws a circular arc
Draw.Rectangle Draws a rectangle
Draw.RectangleBorder Draws a rectangle border
Draw.RegularPolygon Draws a regular n-sided polygon
Draw.RegularPolygonBorder Draws a regular n-sided polygon border
Draw.Polygon Draws a filled polygon (see usage below)
Draw.Triangle Draws a triangle given 3 vertex locations in 3D
Draw.TriangleBorder Draws a triangle border given 3 vertex locations in 3D
Draw.Quad Draws a quad given 4 vertex locations in 3D
Draw.Sphere Draws a sphere
Draw.Cuboid Draws a cuboid with a given size along each axis
Draw.Cube Draws a cube with a given size
Draw.Cone Draws a cone with a given radius and length/height
Draw.Torus Draws a torus with a given radius and thickness
Draw.Text Draws text mesh pro text
Draw.Texture Draws a texture within a rectangular region
Now, there are way too many overloads to list here, but all Draw functions follow the same pattern: Draw.ShapeName( [Positioning], [Essentials], [Specials], [Coloring] )
Any unspecified parameters will use the static properties
The first few parameters are always for the positioning of the object
Second we have the essentials, the most common parameters of the shape, such as the radius of a sphere
Third, we have more special case parameters, that you might want to overload that you usually skip
Finally, the color override of the shape is always at the very end
Polylines & Polygons
Polylines and Polygons can be drawn in several ways. The first and most flexible one is to create a temporary PolylinePath/PolygonPath, 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
using( Draw.Command( cam ) ){
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 mesh every time you draw it. If you instead want a persistent one that you can modify instead of recreate all the time, you can create a PolylinePath/PolygonPath 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. (the following example below presumes you're using ImmediateModeShapeDrawer)
PolylinePath p;
voidAwake(){
p = new PolylinePath();
p.AddPoint( -1, -1 );
p.AddPoint( -1, 1 );
p.AddPoint( 1, 1 );
p.AddPoint( 1, -1 );
}
overridevoidDrawShapes( Camera cam ){
using( Draw.Command( cam ) ){
Draw.Polyline( p, closed:true, thickness:0.1f, Color.red ); // Drawing happens here
}
}
voidOnDestroy() => p.Dispose(); // Disposing of mesh data happens here
Drawing Text
Text can be drawn in two ways. The easiest is to use Draw.Text()/Draw.TextRect() directly.
The second method, is to pass a TextElement into the draw methods - this is much more performant.
Internally, TextElement will reserve a text cache for a specific string and style you're drawing, which will help Shapes only update the text data when necessary.
Below is an example implementation using the persistent text helpers
TextElement elemA, elemB;
voidAwake(){
elemA = new TextElement();
elemB = new TextElement();
}
overridevoidDrawShapes( Camera cam ){
using( Draw.Command( cam ) ){
Draw.Text( elemA, "Hello" ); // Draws text using the persistent element elemADraw.Translate( 0, 1 );
Draw.Text( elemB, "This is performant text", Color.red );
}
}
voidOnDestroy(){
elemA.Dispose(); // Important - you have to dispose text elements when you are done with them
elemB.Dispose();
}
Drawing without commands
In some special cases, you may want to draw without using Draw.Command. For example, if you want to draw gizmos using Shapes, you can issue draw calls directly:
voidOnDrawGizmos(){
// set up all static parameters. these are used for all following Draw.Line callsDraw.LineGeometry = LineGeometry.Volumetric3D;
Draw.ThicknessSpace = ThicknessSpace.Pixels;
Draw.Thickness = 4; // 4px wide// draw linesDraw.Line( Vector3.zero, Vector3.right, Color.red );
Draw.Line( Vector3.zero, Vector3.up, Color.green );
Draw.Line( Vector3.zero, Vector3.forward, Color.blue );
}
However, it's important to keep a few things in mind
GPU instancing is not supported without Draw.Command, which means each draw corresponds 1:1 to draw calls on the GPU, which can get expensive with many shapes
This will literally draw as soon as you call each draw call, which means that when during the render pipeline these draw calls happen is absolutely crucial, and in many cases they will simply not work, especially in HDRP and URP
Generally, this is a bit of a legacy/advanced/bad way of drawing, so like, pls use Draw.Command instead~
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. There are some exceptions, which can be found in the feature table below
You can disable or change the quality of local anti-aliasing in the Shapes settings window
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
All lines thinner than 1 pixel, will be locked at 1 pixel wide, and instead start fading opacity based on pixel coverage. This feature is always on, and 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.
Mind that this effect will only work if your blending mode supports fading. Opaque shapes will only be able to fade if you use MSAA. The higher the MSAA level, the more steps of fading you will have.
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
Blend modes specify how the color of shapes should blend with the color behind it, and also whether or not it will write to the depth buffer.
All blend modes use the alpha channel as opacity/strength
All blend modes are order independent except Opaque & Transparent
No blend modes write to the depth buffer, except 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 disc 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
The only blend mode that writes to the depth buffer
is standard "over"-operator blending, similar to having a layer on top of another in photoshop. The shape will affect the color more and more the higher the alpha channel is. A value of 1 means it will just show the color of the shape. A value of 0.5 means it's a halfway blend between the shape and the background, while a value of 0 will be completely invisible, showing only the background.
Uses premultiplied alpha, which is useful when rendering to a render texture
Order dependent, which means that intersecting and overlapping shapes using this blend mode may not sort properly
Linear Dodge (Additive)
is good for glowing/brightening effects against dark backgrounds
Color Dodge
is a harsher non-linear version of additive that goes even brighter when blending with bright colors. Has somewhat unintuitive behaviors when blending with pure black
Screen
sometimes also called "soft additive", is the opposite operation of multiply, softly blending toward white instead of black
Lighten
outputs the lightest of the shape and its background
Linear Burn
darkens linearly. This is the opposite of additive. Unlike multiply, linear burn has a tendency to introduce hue shifting
Color Burn
is a harsher non-linear version of linear burn that goes even darker when blending with dark colors. Has somewhat unintuitive behaviors when blending with pure white
Multiply
is good for tinting/darkening effects against bright backgrounds. It will softly darken toward black, which is the opposite of screen blending which softly brighens to white
Darken
outputs the darkest of the shape and its background
Subtract
subtracts this color from the background. It's like linear burn but the colors are inverted and it's annoying to work with
Draw Order & Depth Testing
Component Shapes
Shapes Components are, internally, mesh renderers, and so they will sort the same way any other mesh renderers in Unity would, respecting GameObject Layers, Sorting Layers, and the camera sorting settings in your project
Shapes with the opaque blend mode render first, then all other blend modes render. Render Queue depends on the blend mode. The Opaque blend mode uses the Geometry (2450) render queue, all other blend modes use the Transparent (3000) render queue
Shapes will also be sorted by Unity's Sorting Layers within the same render queue, and the sorting settings you have in your project, along with being sorted by camera depth
All Shapes use depth testing by default (ie: they don't render if they are behind something), this can be changed at the top of components by changing Depth Test under Sorting & Depth. Note that component based shapes that override these values will not be able to use GPU instancing
Immediate Mode Shapes
Immediate mode shapes do not use sorting layers, render queues, or any other automatic sorting system, as they are raw draw commands being issued to the GPU. Instead, immediate mode shapes are drawn in the order you specify the draw commands, in the order you run each draw call. For the opaque blend mode, this matters less, but for any other blend mode, great care should be taken to issue all drawing in the order you want to draw them in.
Draw Commands will be injected into the render pipeline at the point specified with the second parameter of Draw.Command(). By default, the injection point is:
As a result, the order of separate IM shape drawers, depend on the order they were enabled in
You can explicitly set drawing order by either enabling the objects in a specific order, or changing script execution order in Unity, however...
...I recommend having only one central ImmediateModeShapeDrawer in your scene, then have that call functions in other objects, in order to have full control over draw order.
Shapes drawn inside draw commands will draw in the order you issue the draw calls in
Each draw call will render on top of the previous one, unless something opaque was in front of it
Opaque shapes both write and read from the depth buffer, which means they are automatically rendered with correct depth no matter the order
I recommend drawing all opaque shapes first, so that all following calls can take advantage of being culled by the depth buffer.
For example, if you draw an opaque shape close to the camera, and then another shape, using any blend mode, further behind that line, the closer line will still be on top since it wrote to the depth buffer
Draw.Text currently doesn't support custom depth/stencil settings, as of 4.2.0. More info in the changelog
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 the number of noots across the screen in the Shapes settings window, 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 take advantage of GPU instancing
Immediate Mode Shapes
When drawing using immediate mode, try to have Shapes of the same type issue their draw commands consecutively, that way they will be instanced together into a single draw call. However, if you don't use Draw.Command, then by nature of it drawing directly, each shape is a separate draw call on the GPU, which gets expensive quickly.
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
Shapes Feature Table
Vector Based
is when a shape has "infinite resolution", as in, it's not an approximation of the shape, and you can zoom in however much you want without loss of detail
LAA
is local anti-aliasing support
Cheap Edits
means that changing properties, such as color, radius, etc. of this shape is so cheap it's basically free
GPU Instancing
is whether or not these shapes will be instanced together to group multiple draw calls into one
Dashable
is whether or not it can be dashed (such as dashed lines or dashed rings)
Gradient Fill
is whether or not it supports color gradient fill. "yes" means it has gradients fit to that particular shape, "generic" means it only has a non-shape-specific gradient fill where you can make a linear or radial gradient, in either world space or local space
2D Shapes
Vector Based
LAA
Cheap Edits
GPU Instancing
Dashable
Gradient Fill
Disc
yes
yes
yes
yes
n/a
yes
Pie
yes
yes
yes
yes
n/a
yes
Ring
yes
yes
yes
yes
yes
yes
Arc
yes
yes
yes
yes
yes
yes
Line (flat/billboarded)
yes
yes
yes
yes
yes
yes
Regular Polygon
yes
yes
yes
yes
yes
generic
Rectangle
yes
yes
yes
yes
yes
generic
Triangle
yes[V]
yes
yes
yes
yes
yes
Quad
yes[V]
no
yes
yes
n/a
yes
Polygon
yes[V]
no
depends[PG]
no[I]
n/a
generic
Polyline
yes
yes
depends[PL]
no[I]
no[DP]
yes
Text
yes
yes
n/a[T]
no
n/a
n/a
Texture
n/a
n/a
n/a
no
n/a
n/a
3D Shapes
Line (volumetric)
no
no
yes
yes[IM]
yes[L]
yes
Sphere
no
no
yes
yes[IM]
n/a
no
Cuboid
yes[V]
no
yes
yes[IM]
n/a
no
Cone
no
no
yes
yes[IM]
n/a
no
Torus
no
no
yes
yes[IM]
no
no
[V]
This shape is inherently polygonal/not smooth, there are no curves to smooth out with vector based approaches
[PG]
Changing the polygon points retriangulates the mesh on the CPU, everything else is cheap
[PL]
Changing the polyline points or miter joins recalculates the mesh on the CPU, everything else is cheap
[I]
Polygons and Polylines use unique meshes, and so they cannot be GPU instanced with each other. The one exception is if you are drawing them in immediate mode using the same PolylinePath/PolygonPath in multiple consecutive calls
Shapes doesn't have a text component since Unity already has that in the form of Text Mesh Pro text, but Shapes does have a wrapper for drawing TMP text in immediate mode, which can in some cases be expensive if you have lots of it
[IM]
shapes of the same type using the same detail level will be instanced together
[L]
3D lines have limited dash support. No slanted or rounded dashes, and doesn't look very pretty when using a large thickness