The SVG Loader in threejs
There are a number of options for additional asset loaders in the Github Repository of threejs, one of which is the SVG Loader. Which is a way to go about loading a SVG file asset as an external file into a threejs project as a collection of paths that can then in turn be used to make Shapes. These shapes can then be used with somehting like the Shape Geometry or the Extrude Geometry constructors.
The SVG Loader and what to know first
There is also knowing how to go about making an SVG file first
Although it might be best to still use some kind of image editor to create SVG Graphics, it is still possible to edit the values of SVG with just a plain old text editor as well. Whatever the case may be when it comes to making the SVG assets that you will like to load into threejs by way of the SVG loader, getting into every little detail about SVG is outside of the scope of this post. A few years back I wrote a post on getting started with SVG from the ground up which might prove to be a good starting point. There is also the Modzilla Docs on SVG that do a great job covering everything with elements and attributes of SVG.
More than one file to use beyond just that of threejs alone
Source code and SVG assets are up on my Github
The source code examples that I am writing about here, as well as the SVG assets, and additional notes and files can be found in my test threejs repository up on Github.
Version Numbers Matter
When I first wrote this post I was using r140 of threejs which was released in May of 2022.
1 - Basic Shapes example of SVG Loader
Often I will want to use the Shape Geometry constructor as a way to go about adding svg to a threejs project. So then one way or another I will need to crate one or more Shape objects from the SVG data when loading an SVG file. The good news with this is that there is a static method of the SVG loader to help with this process.
So then when I create an instance of the SVG loader and call the load method of it, in the body of the callback function that I give the load method that will fire the file finishes loading I will have a data object. This data object will contain a property called paths that will be an array of ShapePaths. I can then loop over this paths array then and pass each instance of shapePaths to the THREE.SVGLoader.createShapes method, the returned result of this will then be an array of Shapes. I can then loop over this array of shapes and for each shape object I can use that as a way to create any kind of buffer geometry with a buffer geometry constructor that will take a shape as an argument, such as the THREE.ShapeGeometry constructor.
For this example on making shapes from loaded SVG data then I have a helper function that will create and return an array of shape geometries. I then have another helper function that will create an array of mesh objects by calling this other helper function that creates the array of shape geometries, then making a mesh object for each of them.
For this example with the create mesh objects helper I am using the basic material for starters. Each time I create the instance of the basic material I can use the color data from the svg for each path for setting the defuse color for each basic material. Sense these are 2d shapes that I am adding into threejs I might want to set the depthWrite property to false. Also it would be a good idea to set the side property of the material to the THREE.DocubleSide constant.
2 - Merge Geometry Example
When it comes to loading in SVG data often I will have more than one shape, that will result in more than one shape geometry. This will also mean that I will need to have a group of mesh objects for each shape. Although in many cases this will work fine, and in some cases it will actually be what I want to happen, there may be some situations in which I will want to merge all these shape geometries into one single geometry.
One way to do this is to use the merge buffer geometries method of the buffer geometry utils. This buffer geometry utils is yet another feature that is not baked into the core of threejs itself but must be added by loading an additional external file on top of threejs that can be found in the threejs Github repo.
3 - Extrude Geometry Example
There are other options for creating a geometry from a shape other than that of the THREE.ShapeGeometry constructor, one of which would be the THREE.ExtrudeGeometry constructor. This allows me to create a geometry that is like that of the 2d plain kind of shape of the shape geometry, but I can add a depth option that will extrude out the 2d shape. I have found that when doing so I want to disable bevel and also adjust the options for curveSegments and steps.
4 - data textures, and custom uv generator
So at this point I have covered the basics of using the SVG loader, and that there is creating extrude geometry which is one option as to what can be done with the loaded data. I have all ready covered a basic example of using extrude geometry that seems to work okay, but there is just one little problem that comes up when trying to add some texture to the geometry. With that said I will some times need to work out a custom way to generate the UV attribute of the extrude geometry.
4.2 - Data textures module
This is what I have together for a general data texture module that has been serving me well thus far in various projects. I have a few options here that allow for me to create a data texture on a pixle by pixle basis, one such method I can all directly, and another I can give data that is a color index for each pixle location called fromPXDATA. I have another function that uses the THREE.MathUtils.seededRandom method as a way to create a random noise texture.
So the general idea here is to create some textures, and also to come up with a custom UV Generator functions for the extrude geometry that will be used with the SVG data.
5 - Just working with Paths
In this section I have worked out a number of examples that have to do with just working with the paths data for doing all kinds of various not so typical tasks with SVG data. That is that often I will want to just create a single geometry, or a group of geometries from the SVG data to make one or more mesh objects. However in some cases I might want to do something else with the path data that is not so typical.
5.1 - Box3 from Path
One thing that can be done is to create an array of points from the path data by which I mean an array of THREE.Vector3 class instances. After doing so I can use this kind of array to create a buffer geometry by making use of the set from points method of the buffer geometry class. Once I have a buffer geometry class I can do something like call the compute bounding box method to get an instance of Box3 that I can then use with the box3 helper.
5.2 - create mesh objects for each point
So making a buffer geometry from an array of points and the calling the bound box method of the geometry is one thing. However another thing that comes to mind is to use this array of Vector2 class instances as a way to create a bunch of mesh objects for each point.
6 - Points
Yet even another options would be to create an instance of Points rather than the usual Mesh objects. When it comes to this I am limited in terms of materials as there is only one option which is the Points Material. The only options that I might set for this kind of material are size and color. As I covered in the above examples in the paths option there is not using points and points material by rather running over the array of vector2 class instances and creating a mesh object for each point. When doing things that way I can use any build in geometry constructor and thus any mesh material that I want.
7 - Lines
What if I just want to create some Lines with the SVG data, for that one option might be to use the THREE.Line constructor in place of mesh. When doing so I have two options in terms of materials, one of which is the Line Basic material which is what I would typically use. When setting options for the line basic material certain options will only work with certain platforms and renderers. For the most part then it is only color and the fog Boolean that will work for most renderers and platforms.
The SVG loader is then the official file for loading in SVG data and doing something with the 2d path data that is given in the data result object when loading works fine with the SVG. There is then a number of things that can be done with this 2d path data, that are typical of doing so and also maybe not so typical. For one thing I can do something like create a 2d shape geometry, or an extrude geometry. when doing so things can end up getting a little involved when it comes to getting textures to work they way that I want them to though. There is then also doing things that are maybe not so typical such as using SVG path data as a way to define paths in which I would like to move objects over time. There are all kinds of things that I can do with the array of Vector2 class instances beyond just that of simply making shapes.
Still there are limitations to what can be done with SVG, or things prove to be a little to complex compared to other options. There is not just importing SVG into threejs, but rather importing it into a program like that of blender, and then doing what I need to do in order to create a DAE file from there. In blender I can work out what the deal should be not just with extrusion if that is what I am to do with it, but also it is easier to work out what the deal should be with respect to things like UV Mapping.