Working With SVG: Best Practices?

Godot Version

4.6

Question

I’m using Inkscape. I’m not very good at it yet but I wanted to ask if there are any best practices when it comes to making svg art and using it in Godot? In my gmae i use a 32x32 grid at the moment. I’ve heard that we should make sure the lines are on integers, which I guess makes sense but is there anything else? How can I make sure the rasterization Godot does will always result in the best result?

Thanks in advance

SVG in Godot is using the ThorVG. If you want to use SVGs, there are some limitations:

SVG (.svg) - SVGs are rasterized using ThorVG when importing them. Support is limited; complex vectors may not render correctly. Text must be converted to paths; otherwise, it won’t appear in the rasterized image. You can check whether ThorVG can render a certain vector correctly using its web-based viewer. For complex vectors, rendering them to PNGs using Inkscape is often a better solution. This can be automated thanks to its command-line interface.

My personal notes for SVG when I’m using AI for SVGs:
~~~
:memo: Godot SVG (ThorVG) Guidelines

:white_check_mark: Allowed (Best Practices)

  • Inline Attributes: Apply styles directly to elements (e.g., fill="#RRGGBB", stroke-width="2"). Avoid CSS classes.
  • Simple Shapes: <rect>, <circle>, <path>, <polygon> work reliably.
  • Organization: Use <g transform="..."> for grouping and positioning.
  • ViewBox: Mandatory. Always define viewBox="0 0 W H" to ensure correct aspect ratio and scaling during import.

:cross_mark: Forbidden (Avoid!)

  • Text Tags: <text> elements are not rendered.
    • Fix: Convert all text to geometry (“Object to Path”) in your vector software before export.
  • CSS Blocks: <style> .class { ... } </style> blocks are frequently ignored or cause parsing errors.
  • Reusability Features: Avoid <defs>, <use>, and <symbol>. Support is unreliable in Godot’s importer; shapes may fail to render or appear at incorrect coordinates.
  • Complex Filters: Blur, DropShadow, and other filter effects are ignored.

:warning: Clean Geometry (PBR & Tiling Critical)

  • Avoid “Grunge” Overlays: Do not use large, diagonal lines or random “splatter” shapes (<path>, <circle>) that span across the entire texture.
    • Reason (Seams): SVGs are rasterized into bitmaps with anti-aliasing on import. Diagonal edges create semi-transparent pixels at the borders. When tiled, these transparent edges create visible “seams” or grid lines where the background shows through.
    • Solution: Detail geometry must be localized to the center of the tile/stone. Edges intended for tiling should be straight (pixel-aligned) or include “bleed” (extend slightly beyond the viewport) to prevent semi-transparent gaps.

:information_source: Additional Technical Notes

  • Rasterization on Import: Godot converts SVGs to bitmaps (Texture2D) upon import. They are not vector data at runtime.
    • Tip: To get sharp graphics at higher resolutions, increase the Scale in the Import dock (e.g., set to 2.0 or 4.0), do not just scale the Sprite2D node.
  • Self-Intersections: Be careful with complex paths that cross themselves (like a figure-8). Fill rules (Non-Zero vs. Even-Odd) can behave inconsistently; simplify paths using “Union” boolean operations if possible.

~~~

EDIT:
All supported elements:

There are:

DPITextures are not vector, they rasterize to a specific size and will re-rasterize if a new size is needed. DPITexture is also not the default import settings for SVG, they will be imported by default as pre-rastered Texture2D.

1 Like

This is a way to make vector illustrations always clear. Yeah, they are resized in real time to the current resolution. This is mentioned in their description.

1 Like

There’s also GitHub - Teaching-myself-Godot/ez-curved-lines-2d which is more impressive than the github account name or repo name suggests.

2 Likes