Changelog
Current Version 1.6.0
- Added line charts, linear and logarithmic axes.
Older versions
- Added code support for HDRP. (1.5.2)
- Fixed wrong namespaces. (1.5.2)
- Fixed Texture UV and Normal generation. Some shapes were missing UV coordinates and normals. (1.5.1)
- Added dashed polylines. (1.5.1)
- Added advanced grid shape. (1.4.0)
- Added arrow shapes. (1.3.0)
- Added rounded polygon (1.2.0)
- Added quadrilaterals and planes (1.1.0)
- First release: regular polygons, polylines, ellipses, rings, SVG parser (1.0.0)
Getting Started
You can add VectorizerFigures
to your scene either via the menu
GameObject/Vectorizer/Add ...
or manually by creating an empty GameObject
; then
click on AddComponent
and start typing Vectorizer...
; finally choose the element
you want from the list.
Every VectorizerFigure
will create two child GameObjects
: one representing the
Stroke
part of the figure (if its StrokeThickness
is greater than zero), and
another for the Fill.
Materials
In order to assign the material you wish to use for the figure's Stroke
and
Fill
, remember to do so via the corresponding properties in the root GameObject
.
The library provides a special URP shader (also available as a standard pipeline shader in the
Shaders
folder) called StrokeDepthOffset
. This material applies a customisable
Offset Bias to the rendered figure, to avoid Z-Fighting. In most figures, this is unnecessary. However, in
some complex figures with hundreds of vertices (such as partial rings) or SVG figures (not originally
designed for use in Vectorizer) the stroke might appear to overlap with the fill part. This material, when
applied to the stroke, will make sure that it appears always on top.
There is also another URP shader, called TextureUV
that allows you to visualise UV
coordinates.
Debugging
Click on either the Stroke or Fill child GameObject you wish to debug and add a
VectorizerMeshDebugger
component. This will allow you to inspect the vertices, indices, and
Texture coordinates of the generated figure. Built-in methods allow you to display in the Scene View which
vertex or triangle the values refer to.
It also allows you to save the generated mesh to disk, by clicking on Save Asset
. Files will
be saved in the Assets/Vectorizer
folder.
Samples
In the Assets/Vectorizer/Samples
folder you will find various scenes. The
Overview
scenes provides an example of all the figures currently supported. The
SVG Icons
scene provides different examples of SVG icons rendered in Vectorizer. The SVG code
for those icons comes from the
Bootstrap icon library. The
Texture Coordinates
scene visualise how Texture coordinates are generated on various figures.
The remaining scenes show various variations of the supported figures.
Stroke Thickness
Every VectorizerFigure
provides object-specific properties. One that you can find in every
object is the StrokeThickness
. It defines, in world units, the width to use to draw the
outline of the figure. If it is equal to zero, the Stroke
part of the mesh will not be drawn.
Has Fill
If set to True
, the Fill part of the figure will be generated (marked by
VectorizerInstructions
of type Fill). Otherwise, it will be ignored even if a material is
assigned.
Curve Tolerance
Controls the tessellation of curved lines. The lower, the more vertices are used.
Width and Height
The width
, respectively, the height
of the rectangle, in world units.
Radius
Only for RoundedRectangles
. Controls the radius of the rounded corners, in world units.
Columns and Rows
Indicates how many columns and rows the grid should have. A maximum of 65535
vertices per
figure are allowed.
Cell Width
The length in units of a single (square) grid cell.
Sides
Indicates the number of sides to use to render the polygon. The higher the number, the more it will
approximate a circle. If your intention is to create a circle, do use
VectorizerEllipse
instead. That way, you can control the figure by expressing the length of
the semimajor axis.
Radius
Only for RoundedPolygon
. Controls the radius of the rounded corners, in world units.
Type
Choose between TrapezoidIsosceles
, TrapezoidRight/Left
,
Parallelogram
and Rhombus
.
BaseA, BaseB, and Height
Used in TrapezoidIsosceles
and both TrapezoidRight/Left
. BaseA and BaseB refer
to the bottom and top bases, respectively. Height represents the distance between the two bases.
Rhombus
uses only BaseA and Height. In this figure BaseA and Height are used to determine the
total horizontal and vertical lenghts, respectively.
Parallelogram Angle
Used only for the parallelogram. Represents the angle opposite the height. In this figure, only BaseA and Height are used to determine the horizontal and vertical lengths, respectively.
Side Length
The length of each side of the polygon, in world units.
Columns and Rows
Indicates how many quads the fill area should have. A maximum of 65535
vertices per figure
are allowed.
Tessellation
Indicates the number of sides to use to render the polygon. Use at least 32 vertices to approximate a circle.
Semimajor and Semiminor axes
The semimajor axis is equivalent to the radius of a circle, when both its semi-major and semi-minor axes are equal. If they are different, an ellipse will be rendered.
Points
The number of points the star should have.
Inner and Outer radius
Imagine the star as two circles. The Outer
radius represents the radius of the circle
touching all the points of the star (the circumscribing circle). The Inner
radius represents
the radius of the circle inscribed within the star.
Tessellation
Indicates the number of sides to use to render the polygon. Use at least 32 vertices to approximate a circle.
Outer and Inner Semimajor axis
Represents the length of the semimajor axis for the outer part and inner part. The length of inner semimajor axis cannot be greater than the outer semimajor axis.
Eccentricity
The Eccentricity
controls the shape of the Ellipse. Use 0 for a circle, and a value between
>0 and <1 for an Ellipse.
From and To Angles
Represent the amplitude of the starting and final angle of a partial disk, expressed in degrees. If these correspond to 0 and 360, the ring will be whole.
Clockwise
The direction to use when deciding the direction of the angles.
Cap Ends
Whether or not to cap the outline of a partial ring. Has no effect on whole rings.
Points
A vector containing the coordinates of the polyline's vertices. For a more user friendly way of entering
these vertices, consider extending VectorizerPolyline
and changing the contents of the
Points
property.
Line Style
How to render the joints of the polyline, between Miter, Round, and Bevel.
Radius
Controls the radius of the rounded joints, in world units. Only relevant for the Round
Line Style
.
Closed
If True
an additional segment will be added, connecting the last point to the first.
Points
A vector containing the coordinates of the polyline's vertices. For a more user friendly way of entering
these vertices, consider extending VectorizerPolyline
and changing the contents of the
Points
property.
Dash Style
A vector containing alternating lengths for dashes and gaps. The array length must be a multiple of 2, its components must be positive and non-zero. The 0th element in the array represents the length of the first dash in world units, the 1st element, the length of the first gap. If a 3rd and 4th elements (or more) are present, then they will represent the length of the second dash and second gap in the series, and so on, alternating until the segment is rendered.
Min Dash Length
The minimum length of a (filled) dash that can be rendered.
Closed
If True
an additional segment will be added, connecting the last point to the first.
Data
A string representing valid
SVG path syntax. I.e. the part in the d
attribute of an SVG Path
element.
Base width and height
With an arrow pointing north, the base width refers to the length of the base of the arrow's body or rectangular part, and the height as its length.
Arrow width and height
The width and height refer to the length of the base of the triangular part, respectively its height.
Linear Chart
The Linear Chart
object is a set of different objects: two axes, a background, and the line itself.
You can change the individual properties of these objects by accessing them directly. You can set the points by
accessing the Data
property of the VectorizerLinearChart
object.
See the Samples/Charts
scene for a demonstration.
Notes on Performance
VectorizerFigures
are essentially just meshes. Simple icon-like graphics will likely have
very few vertices, and therefore the performance will be negligible on modern GPUs. Round figures such as
circles, ellipses, paths with Bézier curves, etc. will instead need several vertices, but are still well
within the capabilities of modern hardware. You can control the tessellation of these figures via the
object's properties. In more extreme cases, you can consider saving the generated meshes as an asset via
the built-in Save Asset
feature of the VectorizerMeshDebugger
component.
When I load one of the sample scenes, the editor complains about a missing script on the Camera GameObject. How do I fix it?
Importing errors have been reported. It is most likely related to the script
SimpleCameraController
. You can simply reattach it to the Camera GameObject by removing the
missing component warning (click on the three dots icon next to it, select Remove Component
)
then click on Add Component
and type SimpleCameraController
. You can find it in
the Assets/Vectorizer/Samples/Scripts
folder.
Why is part of my figure not rendering correctly? Some parts flash in and out.
That is Z-Fighting
. It happens because some triangles overlap others (they are on the same
plane). And the GPU does not know which one should be on top. In the case of VectorizerPath
,
make sure no part overlaps itself, by changing the StrokeThickness
for example). Otherwise,
you can assign the Stroke Depth Offset
material to the part of the figure you wish to always
make appear on top (e.g., the stroke). Make sure you assign it to Material slot in the root GameObject,
and not to the Material slot in the generated child GameObjects. You can find this material in the
Assets/Vectorizer/Materials
folder.
The VectorizerPath
is not displaying correctly. It does not look the same as when rendered in
a HTML5 canvas.
In general, SVG figures are not designed around the limitations of 3D mesh vertices. This means that in a software like Adobe Illustrator or other vector graphics design environments, it is not usually a problem if parts of a figure overlap themselves. In Vectorizer, these circumstances might affect how the figure is displayed. If it does not look correct, try splitting the figure in multiple elements, and/or specifying the vertices in counter-clockwise order. Especially if your figure is concave rather than convex.
Does Vectorizer support the SVG fill-rule attribute?
Currently, there is no support for the
SVG fill-rule
attribute. This means these figures should be split into multiple VectorizerPath
objects. See
the SVG Icons
sample for examples.
How do I create custom VectorizerFigures
?
You need to derive from VectorizerFigure
and implement two methods: Rebuild
and
Validate
. Let's look at an example:
[ExecuteInEditMode]
[RequireComponent(typeof(VectorizerMesh))]
public class VectorizerEllipse : VectorizerFigure
{
[Range(3f, 320f)]
public int Tessellation = 32;
[Range(0.001f, 256f)] public float SemiMajorAxis = 8;
[Range(0.001f, 256f)] public float SemiMinorAxis = 8;
public override void Rebuild()
{
// This function is called every time the parameters change.
// Therefore, we need to clear the instructions having old values.
Designer.ClearInstructions();
// We add a new Fill Ellipse instruction based on the current values.
// To avoid an overlap between the interior part and the outline,
// we reduce the length of the semi-major and semi-minor axis
// by half the stroke thickness' width.
Designer.AddInstruction(new FillEllipse(Tessellation, SemiMajorAxis-StrokeThickness/2,
SemiMinorAxis - StrokeThickness / 2));
// If this figure has a stroke part (HasStroke), then we
// need to add the corresponding instructions.
if (HasStroke)
{
Designer.AddInstruction(new DrawEllipse(Tessellation, SemiMajorAxis, SemiMinorAxis,
strokeThickness:StrokeThickness));
// This instruction makes sure that the vertices belonging to the
// interior area have the same exact values as those on the outline,
// to account for floating-point errors.
Designer.AddInstruction(new WeldPolygonVerticesInstruction());
}
}
protected override bool Validate()
{
// return true when the figure is valid according to the current
// value of the parameters.
return SemiMajorAxis >= 0.01f && SemiMinorAxis >= 0.01f;
}
// To make your figure appear in the menu, implement a similar function
[MenuItem(VectorizerMenu.GameObject + "Ellipse")]
public static void CreateEllipse() { Create<VectorizerEllipse>(); }
}
Will Vectorizer implement X Y Z in a future release?
I am happy to expand Vectorizer's features. Please contact me to discuss your suggestion.