Drawing content with StereoKit

Generally, the first thing you want to do is get content on-screen! Or in-visor? However it’s said, in this guide we’re going to explore the various ways to display some holograms!

At its core, drawing things in 3D is done through a combination of Meshes and Materials. A Mesh is a collection of triangles in 3D space that describe where the surface of that 3D object is. And a Material is then a collection of parameters, Textures (2d images), and Shader code that are combined to describe the visual properties of the Mesh’s surface!

Meshes are made from triangles! Meshes are made from triangles!

And in addition to that, you’ll need to know a little bit about matrices, which are a math construct used to describe the location, orientation and scale of geometry within the 3D space! A Matrix isn’t difficult the way we’re using it, so don’t worry if math isn’t your thing.

And then StereoKit also has a Model, which is a high level combination of Meshes, Material, Matrices, and a few more things! Most of the time, you’ll probably be drawing Models loaded from file, but it’s important to have options.

Then lastly, StereoKit has easy systems for drawing Lines, Text, Sprites and various other things! These are still based on Meshes and Materials under the hood, but have some complex features that can make them difficult to build from scratch.

Meshes and Materials

To simplify things here, we’re going to use the built-in assets, Mesh.Sphere and Material.Default. Mesh.Sphere is a built-in mesh generated using math when StereoKit starts up, and Material.Default is a high performance simple Material that serves as StereoKit’s default Material. (For more built-in assets, see the Defaults)

Mesh.Sphere.Draw(Material.Default, Matrix.Identity);

Default sphere and material Drawing the default sphere Mesh with the default Material.

Matrix.Identity can be though of as a ‘No transform’ Matrix, so this is drawing the sphere at the origin of the 3D space.

That’s pretty straightforward! StereoKit will get this Mesh/Material pair onto the screen this frame. Remember that StereoKit is generally an immediate mode API, so this won’t show up for more than the current frame. If you want it to draw every frame, you’ll have to call Draw every frame!

So how do you get a Mesh to begin with? In most cases you’ll just be working with Models, but you can get a Mesh directly from a few places:

And where do you get a Material? Well,

Matrix basics

If you like math, this explanation is not really for you! But if you like results, this will get you going where you need to go. The important thing to know about a Matrix, is that it’s a good way to represent an object’s transform (Translation, Rotation, and Scale).

StereoKit provides a number of Matrix creation methods that allow you to easily create Translation/Rotation/Scale matrices.

// The identity matrix is the matrix equivalent of '1'. You can also
// think of it as a 'no-transform' matrix.
Matrix transform = Matrix.Identity;

// Translates points 1 meter up the Y axis
transform = Matrix.T(0, 1, 0);

// Scales a point by (2,2,2), rotates it 180 on the X axis, and
// then translates it up 1 meter up the Y axis.
transform = Matrix.TRS(
	new Vec3(0,1,0),
	Quat.FromAngles(180, 0, 0),
	new Vec3(2,2,2));

// To draw a cube at (0,-10,0) that's rotated 45 degrees around its Y
// axis:
Mesh.Cube.Draw(Material.Default, Matrix.TR(0,-10,0, Quat.FromAngles(0,45,0)));

The TRS methods have a lot of permutations that can help make your matrix creation code a bit shorter. Like, if you don’t need to add scale to your TRS matrix, there’s the TR variant! No rotation? Try TS! Etc. etc.

Now. Even more interesting, is that many Matrices can be combined into a single Matrix representing multiple transforms! This is done via multiplication, and an important note here is that matrix multiplication is not commutative, that is: A*B != B*A, so the order in which you combine your matrices is important.

This can let you do things like, rotate around a pivot point, or build a hierarchy of transforms! A parent/child position hierarchy can be described pretty easily this way:

Matrix parentTransform = Matrix.TR(10, 0, 0, Quat.FromAngles(0, 45, 0));
Matrix childTransform  = Matrix.TS( 1, 1, 0, 0.2f);

Mesh.Cube.Draw(Material.Default, parentTransform);
Mesh.Cube.Draw(Material.Default, childTransform * parentTransform);

Combining matrices The smaller childTransform is relative to parentTransform via multiplication.

Models

The easiest way to draw complex content is through a Model! A Model is basically a small scene of Mesh/Material pairs at positions with hierarchical relationships to eachother. If you’re creating art in a 3D modeling tool such as Blender, then this is basically a full representation of the scene you’ve created there.

Since a model already has all its information within it, all you need to do is provide it with a location!

model.Draw(Matrix.T(10, 10, 0));

Drawing a model StereoKit’s main format is the .gltf file.

So… that was also pretty simple! The only real trick with Models is getting one in the first place, but even that’s not too hard. There’s a lot you can do with a Model beyond just drawing it, so for more details on that, check out the Model guide (coming soon)!

But here’s the quick list of where you can get a Model to begin with:

Lines

Being able to easily draw a line is incredibly useful for debugging, and generally quite practical for many other purposes as well! StereoKit has the Lines class to assist with this, and is pretty straightforward to use. There’s a few variations, but at it’s simplest, it’s a few points, a color, and a thickness.

Lines.Add(
	new Vec3(2, 2, 0),
	new Vec3(3, 2.5f, 0),
	Color.Black, 1*U.cm);

Drawing a line You can also draw Rays, Poses, and multicolored lists of lines!

Text

Text is drawn with a collection of rectangular quads, each mapped to a character glyph on a texture. StereoKit supports rendering any unicode glyphs yout throw at it, as long as the active Font has that glyph defined in it! This means you can work with all sorts of different languages right away, without any baking or preparation.

To draw text with the default Font, you can do this!

Text.Add("こんにちは", Matrix.T(-10, 10,0));

Drawing text ‘Hello’ in Japanese, I’m pretty sure.

You can create additional font styles and fonts to use with text drawing, and there are a number of overloads for Text.Add that allow you to change the layout or constrain to a particular area. Check the docs for the method for more information about that!

Cool!

So that’s the highlights! There’s plenty more to draw and more tricks to be learned, but this is a great start! There’s treasures in the documentation, so hunt around in there for more samples. You may also be interested in the Materials guide for advanced rendering code, or the Model guide (coming soon), for managing your visible content!

If you’d like to see all the code for this document, check it out here!




Found an issue with these docs, or have some additional questions? Create an Issue on Github!