This Godot 4.3 plugin renders SVG files at runtime. It achieves the effect of infinite scaling and smooth curves by calculating the curves in shaders drawn on polygons.
To be clear, Godot already has built-in functionality to import SVGs and display them as rasterized (pixel map) textures in-game. This is likely what you should do 90% of the time instead of using this plugin to render every SVG in your game.
This software is in early development.
-
If your SVG has self-intersecting paths, you may see visual bugs. There is a lot of code written to solve this scenario, but it is still being worked on and there are many W3C test suite examples where it is known to not work.
-
You may run into a problem where loading certain SVG files causes Godot to freeze, due to the path solver getting stuck in an infinite loop. To prevent this, don't use SVGs with self-intersecting paths or thin strokes.
-
Check the support table at the bottom before reporting bugs.
Resolving the following issues in Godot core will improve this plugin. Please visit them and give a thumbs up.
- Expose _edit_get_rect, _edit_use_rect to gdscript - SVG2D is set up as a custom node, without this engine feature you cannot resize and rescale it with editor controls (must use the inspector).
Copy the addons/godot-svg
folder in this repository into your Godot project. Make sure the folder sits exactly at the path res://addons/godot-svg
. If you put it somewhere else, some things like icons may break.
In Godot, go to Project -> Project Settings -> Plugins
and check the Enable
checkbox.
- When importing a SVG into Godot, it defaults to "Import As: Texture". Change this dropdown to "Import As: SVG", then re-import.
- Now in a 2D scene, add a SVG2D node. Drag & drop your SVG file to the "SVG" property of this node, and you will see the SVG rendered in realtime!
These nodes share a similar API.
The SVG2D Node:
Use in 2D scenes similar to how you would use a Sprite. The default size of the SVG2D is determined by the viewBox
, width
, and height
attributes on the imported <svg>
element.
The SVGRect Node:
Use in 2D scenes similar to how you would use a TextureRect. How the SVG fits inside of this rectangle is determined by the preserveAspectRatio
attribute on the imported <svg>
element.
Note: If you use any undocumented methods or properties, you risk your code breaking in any future update.
PROPERTIES
Property Name | Value Type | Notes |
---|---|---|
svg | SVG Resource | When importing a SVG file, choose "Import As: SVG". If you try to add a SVG imported as "Texture" here, it will not work. Use Sprite instead for that. |
fixed_scaling_ratio | float | [This feature may not yet be working as expected]. Setting the value above 0 bakes the resolution of masks so they are not redrawn due to scaling at runtime. A value of 1 means it is drawn to look perfect at 100% view box scale (1:1), and if you zoom in further than that you will see pixellated edges. Setting the value to 0 redraws the mask every frame. |
antialiased | bool | Whether or not to use the antialiasing to smooth the shape edges. |
triangulation_method | SVGValueConstant. TriangulationMethod |
Delaunay and Earcut are two different triangulation methods used to fill the interior of the shape. Their accuracy and performance characteristics vary based on the situation. Generally Earcut is faster but less accurate. |
assume_no_self_intersections | bool | This is an optimization that can make the initial construction/animation of the shape faster by not even attempting to solve for self-intersecting shapes. If there are actual intersections, the shape may not draw or may have rendering artifacts. |
assume_no_holes | bool | This is an optimization that can make the initial construction/animation of the shape faster by not even attempting to solve for holes. If there are potential holes, they are ignored. |
disable_render_cache | bool | When you first load a SVG in the editor, it will spend time solving and triangulating the paths. This solution is saved back to the asset for a faster load time. This property disables that process. |
METHODS
Method Signature | Notes |
---|---|
get_element_by_id(id: String) -> Dictionary | Finds the SVG element with the given id attribute. If the node is found, a dictionary is returned in the format { "node": SVGElement2D or SVGElement3D, "resource": SVGResourceElement } . If not found, null is returned. |
get_elements_by_name(name: String) -> Array | Finds all SVG elements with the given tag/node name. An array containing dictionaries is returned, each dictionary in the format { "node": SVGElement2D or SVGElement3D, "resource": SVGResourceElement } . An empty array is returned if nothing is found. |
load_svg_from_buffer(buffer: PoolByteArray) | Loads a SVG on the fly. This is not a good idea for complex SVGs as it blocks the main thread. If you have the SVG contents as a string, you can use String.to_utf8() to convert it to a PoolByteArray . |
SVGElement2D
is returned from SVG2D
methods such as get_element_by_id
or get_elements_by_name
. It represents a single element (e.g. shape, etc.) in the SVG document.
Note: If you use any undocumented methods or properties, you risk your code breaking in any future update.
METHODS
Method Signature | Notes |
---|---|
remove_attribute(name: String) | Removes an attribute with the specified name. |
set_attribute(name: String, value: String) | Sets the value of an attribute with the specified name. It is recommended at the moment to pass a string value, equivalent to what you would type in a SVG document. |
While a SVG3D node exists, this is purely experimental at the moment, and you can expect it to have breaking changes in the future.
The main problem with this node at the moment is Godot doesn't provide an easy way to accurately sort transparent 3D meshes.
SVGs vs Sprites
Godot is generally much faster at drawing raster textures in 2D. Whenever you can get away with it, you should prefer using Sprites with images imported as "Texture" instead of SVGs.
Scaling
If your game uses a lot of scaling operations, and you use special features such as masks and patterns that need to be recalculated during re-scale, consider setting fixed_scaling_ratio to a value above 0.
Masks and Clip Paths
Using masks and clip paths can quickly bring your game to a crawl. Both are rasterized to the game's output resolution before being applied to shapes. This means mask performance is resolution dependent. A masked shape that takes up the entire screen will take exponentially more time to draw than a smaller masked shape that takes up half the screen.
Setting opacity < 1
on group (<g>
) elements is also treated like a mask.
Stylesheets
Avoid SVGs that use stylesheets like the plague. (e.g. avoid the <style>
element). It is technically supported, but it is very expensive to compute up-front. Set inline attributes instead; the inline style attribute (e.g. <rect style="fill:red">
) is OK to use.
Animation
[Note: svg animation not yet implemented] Animating styling attributes that cause the shape of an element to change (such as stroke-dasharray
, d
, r
) will cause the entire shape to be recalculated which can become expensive on a large scale. Animating masked or clip-path shapes regenerates viewport textures on the CPU each frame, which is even more expensive.
Basic Shapes
There is a performance benefit to using basic shapes (circle
, ellipse
, rect
, line
) as opposed to generating the same shape using a path
, polygon
, or polyline
. With the latter, the shapes must be simplified first and have expensive calculations to determine the fill rule.
ELEMENTS
CORE ATTRIBUTES
Name | Support Level | Notes |
---|---|---|
id | Supported | |
lang | Not Yet Supported | |
tabindex | Will Not Support | No use case |
STYLING ATTRIBUTES
Name | Support Level | Notes |
---|---|---|
class | Supported | |
style | Supported |
CONDITIONAL PROCESSING ATTRIBUTES
Name | Support Level | Notes |
---|---|---|
requiredExtensions | Not Yet Supported | |
requiredFeatures | Will Not Support | Deprecated |
systemLanguage | Not Yet Supported |
PRESENTATION ATTRIBUTES