Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Open Brush is completely free on all platforms. (Tilt Brush is still available and is still being charged for. This is still the only way to get the app on Playstation VR)
Only the main official release is available on most of the links below. If you want the experimental build then try Itch.io - or read about the other alternate versions that are available
Steam Oculus Store Viveport Itch.io
Oculus Applab SideQuest Itch.io
There is no VR headset currently supported on the Mac but Open Brush does have some limited support for working as a normal desktop app.
On your Open Brush panels, you’ll see a number of different options and features. Learn more about them in the pages that follow.
Eraser, Dropper, Re-Color, Camera, Teleport, Selection, Mirror, and Straight Edge are all on the top level of the Tools panel. on the "More..." panel, which is originally below the Tools panel, you can access Environment, Lights, Backdrop, Guides, and Poly Library.
At the bottom of the palette is the Menu panel which opens when you hover over it. In both Beginner and Advanced Mode, this Menu panel contains the Sketchbook, My Profile, Beginner/Advanced Mode, Clear Sketch, Save Sketch, and Upload. When you are in Advanced Mode, the "More Options..." button will also appear within the Menu panel and contains the Tips 'N Tricks, Labs, and Settings.
Additionally, you can find the Brush, Dropper, re-color, Selection, Model Pin, and Eraser on the Quick Tools panel.
The Quick Tools panel is accessed:
Most devices (eg Quest, Rift, Pico, Vive XR): From the B button if you're right handed (or more generally the secondary button on your painting hand).
HTC Vive: From the Menu Button on top of the thumbpad.
Windows Mixed Reality: From the Menu button, in between the thumbpad and thumbstick
Eraser Tool. You can use the eraser tool to erase entire brush strokes. To select the tool:
Point your painting controller towards the palette and select the eraser .
Position the tool anywhere on the brush stroke and press the trigger to erase.
To disable the eraser, select the icon again.
Note: To erase your last brush stroke quickly, you can also use Undo. To use Undo, press the left side of the palette controller’s disk. You can also use Undo if you accidentally erase a brush stroke.
Dropper Tool. To select the brush and color used for a stroke or the color in a reference image:
Position your controller on the brush stroke or the color in an image you want.
Press the trigger to confirm. Your brush type, color and size will be copied.
To disable the dropper, click the icon again
Camera Tool. Use Cameras to save your creation in various formats.
Point your painting controller towards the palette and select Cameras.
On your painting controller, swipe the thumbpad (HTC Vive) or thumbstick (Oculus Rift and Windows Mixed Reality) right or left to access the Camera options.
After selecting your option, your image file will save to the "Open Brush" folder inside "Documents" on your computer.
You can then share photos, videos, and GIFs or your artwork online.
PC users can record still images, animated GIFs or video. The Quest only supports still images and GIFs.
For better quality you can record re-render videos offline. Long-press the camera tool to access the camera settings:
Teleport Tool. To virtually hop to a different spot in your environment, use Teleport.
Point your painting controller towards the palette and select Teleport.
On your painting hand, press the thumbpad or trigger to move around the x and y axis.
You will see footprints on the ground, which represent your landing spot.
To disable Teleport, select the icon again.
Note: The distance which you can teleport varies in each environment.
Selection Tool. Use Selection to select and duplicate strokes and models in your scene.
Select strokes using the trigger. You can also flip into deselect mode by tapping the thumbpad (HTC Vive and Windows Mixed Reality) or “A/X” button (Oculus Rift).
If you want to move your selection, grab it as you would any other model in your scene. To delete a selected group of strokes, just throw it away.
Duplicate selections by either: a) holding the thumbpad (HTC Vive and Windows Mixed Reality) or “A/X” button (Oculus Rift) while intersecting your controller with selected strokes or... b) using the same button but whilst moving a selection The first method creates a duplicate slightly offset from the original whilst the second leaves a copy behind at the exact spot where you pressed the button.
To select everything in a scene, long press on the Select button on the Tools panel and the Select All button will appear.
To invert a selection that you have just made, long press on the Select button on the Tools panel and the Invert Selection button will appear.
Combines the currently selected strokes into a single group. They will move and scale as one. You can ungroup them easily by clicking again.
Mirror Tool. Use the mirror mode tool to paint symmetrically. To use the tool:
Point your painting controller towards the palette and select Mirror Mode.
To grab and move the mirror, use the Grip button on the sides of your controllers.
To adjust the mirror back to default, grab and move the mirror onto the snapback widget.
To spin the mirror, grab the mirror using the Grip button on the right side of your painting controller. Throw the mirror to spin it in an infinite loop. You can then paint within this loop.
If you long-press the mirror tool you get the following options:
Straight Edge Tool. Use the straight edge tool to paint in straight lines between two points.
Fly Tool
Snip Tool (currently beta only)
Join Tool (currently beta only)
The following tools only appear in Advanced Mode
Dropper
Repaint
Selection
Fly
Snip
Join
Additionally in Advanced Mode the Environment Panel button moves to the Extras Panel
Top row of buttons (Left to right): i. Help: Pops up links to various useful web pages ii. About: Pops up our About page iii. Contribute: Pops up a link giving info on how you can contribute iv. Ruler
Pointer Angle: This changes the angle the brush pointer is at. Find a settings you feel comfortable with.
Quality
Simplification
Current Sketch Cost
Super Secret Hidden Buttons: Absolutely nothing happens if you click here.
Tiltasaurus: A word game inside Open Brush
Icosa Library: was Google Poly but our replacement is coming soon
Pin: Locks groups and 3d models in place so you don't accidentally move or select them
Spectator Camera (PC Only): Allows you to place the camera for your desktop view
Selection Tray Buttons: Select All
The second button is the Mirror Recall button. This will recall a Mirror that is out of reach. (If you like the mirror - you might want to check out the multi-mirror )
This section only lists features currently in the main release. There is also a with new features. There's also plenty more stuff in .
Bear in mind this gives a misleading impression of the amount of work that has been put in. There's been a ton of effort on things that don't result in user-visible features but will help ease future development. Special props to for the amazing automated build system.
The Settings Panel can be opened from a button on the .
Second row of buttons (Left to right): i. Autosimplify ii. Experimental Mode: Toggles on or off next time you open the app iii. Swap Hands: Swaps the brush between the left and right hands iv. Reset First Use: If you click this then next time you launch Open Brush you will get the short tutorial you saw when you ran it the first time. Also turns off and switches back to Beginners Mode where most of the tools are hidden.
Twitch Chat:
YouTube Chat:
Use Lights to modify your scene's primary and secondary lighting colors and positioning.
The sun is your primary light, and it casts shadows.
The sun is the brighter light.
The moon is your secondary light, it doesn’t cast shadows.
The fill light floods the scene with an equal distribution of color and light. It's effects are most easily seen in the shadow color of your scene.
You can grab and move the sun and moon by selecting with the trigger.
You can change the color of all three light sources.
The lighting effect is best observed on environments with a ground and object (i.e. pedestal), and in those sketches where there are at least a few strokes.
The sphere the lights pivot around can be used as a representation/quick preview for placement of lights in the world.
Custom lights save with sketches.
If you hold down your Wand trigger (the left hand if you're using Open Brush right-handed) when you first select a stroke with the Selection Tool, only brushstrokes that use that brush will be added to the selection as you continue to select strokes.
You only have to be careful with the first stroke you select, and then after that, you can just wave the selection or erase tools with reckless abandon and it will only select strokes using the same brush type.
The admin panel is always attached to your wand - which is the controller in your non-dominant hand (which is your left hand by default unless you've switched hands on the settings panel)
The large central button opens the Sketchbook Panel.
Around the outside are buttons for:
Save Sketch
Tutorial
(small button underneath) Reset Panels: resets all panels to their default position/visibility
Beginner/Advanced mode toggle
New Sketch
Use the sphere, cube, and pill guides to create perfect shapes.
Guides are moved and scaled similar to other widgets, using the Grip buttons.
Use Backdrop to modify your scene's backdrop color gradient and fog.
Grab anywhere on the backdrop sphere to move or turn it by selecting with the trigger
The backdrop sphere represents the sky dome (skybox) in the world.
Change the backdrop gradient by selecting different colors.
Change the fog intensity by adjusting the slider, and you can change the color by clicking on the fog rectangle.
Reset your environment at any time by reloading it from the environment panel.
Custom environments save with sketches
Some environments already have textured sky dome. In that case, you will be prompted to turn off that custom skybox before you can modify it.
Upload Panel
The 3 dots "more" button opens this: A popup with:
: You can choose a number of different virtual environments to paint in. For example, you can paint in Studio, Night Sky, Space or on a Dress Form. The lighting in the environment will affect the color of the brush stroke, but switching environments will not affect your existing brush strokes.
The location of the tools differ slightly between basic mode and advanced mode. In advanced mode environment moves to the "More Tools" panel and undo/redo are removed (you can access these via your wand instead) .
eraser
eraser
straightedge
straightedge
environment
environment
cameras
cameras
teleport
teleport
mirror
mirror
undo
redo
dropper
recolor
selection
fly
lights
backdrop
guides
poly library
camera paths
Paint in 3D with Open Brush, an app that runs on the HTC Vive , Valve Index , Oculus Rift , Oculus Quest, and Windows Mixed Reality virtual reality systems. You can use different brushes, effects, and tools to paint your virtual creations.
To paint in 3D with Open Brush, you’ll need to have a VR headset that supports SteamVR or any Oculus headset.
HTC Vive / Valve Index
Set up your HTC Vive or Valve Index.
If you haven't already, install Steam.
Download the Open Brush app.
To open Open Brush, open the Steam Library > select Games > Open Brush.
The system requirements for running Open Brush are the same system requirements for the HTC Vive and Valve Index.
Oculus Rift
Rift users can either use the SteamVR build as described above for the HTC Vive / Valve Index, or the Rift-specific build described here:
Set up your Oculus Rift.
Download the Open Brush app.
To open Open Brush, open the Oculus Home Library > Open Brush.
The system requirements for running Open Brush are the same system requirements for the Oculus Rift.
Oculus Quest
Oculus Quests can either be used standalone or tethered to a PC. For tethered ("PCVR" mode), see the instructions above for the SteamVR build for HTC Vive / Valve index. For standalone mode (which has some performance limitations compared to being connected to a PC), follow these instructions:
Set up your Oculus Quest.
Download the Open Brush app, currently on App Lab.
To open Open Brush, open the Oculus Home Library > Open Brush.
Windows Mixed Reality
Set up your Windows Mixed Reality headset.
If you haven't already, install Steam.
Download the Open Brush app.
To open Open Brush, open the Steam Library > select Games > Open Brush.
The system requirements for running Open Brush are the same system requirements for the Windows Mixed Reality headsets.
Make sure you are in Advanced Mode.
On your palette, go to Tools > More > Tips ‘N Tricks.
This will run you through an overview of your Open Brush controllers and where the various buttons are.
Note that left handed users can switch the left and right controllers by tapping (gently!) the base of the two controllers together, so that the left hand controller will paint and the right hand controller will contain the various panels and settings. You can also swap left and right hands in the Settings Panel
When you run Open Brush for the very first time, you'll be shown an introductory tutorial teaching you how to paint and use the palette.
Every time the app is started after that initial run, your palette hand will by default open to the Sketchbook. In the Sketchbook, you can choose between viewing some featured sketches by the community and your own saved sketches. You can also choose to start a new sketch.
VR controllers can sometimes be a little too accurate and responsive, making it difficult to create smooth curves at low movement speeds. The Lazy Input feature will exchange responsiveness for control by applying real-time input smoothing.
Toggle it by HOLDING your off-hand trigger and TAPPING the button marked with the rabbit/turtle.
Snap selections to a grid. Duplicate selections at precise positions
Draw brush strokes that align with the grid (especially useful with the hull brush)
Snap the rotation of selections to a chosen angle (i.e. 15, 45 or 90 degrees)
Drawing along straight x, y or z lines. Building regular structures up by making multiple copies of brush strokes
Click the button shown above on the Extras Panel to open the new Snap Settings panel:
Click the Snap Angle or Snap Grid buttons to cycle through angles and grid sizes.
The Jitter button is the same as the the button on the Color Picker. It's included here for convenience as position jitter and other settings can be useful with snapped brush strokes.
This panel contains some features that are only enabled if you've switched to Experimental Mode in the Settings
Drafting Mode (deprecated - use Layers instead)
Multimirror
Save Strokes to Media Library (deprecated - consider merging strokes via the Sketchbook Panel three dots menu instead)
Enable Profiling (deprecated - and not very useful for non-developers)
Warning, not for the easily nauseated! While holding both grab buttons to change the scale, you’ll see a padlock on one of the action buttons. Click it, and you’ll now be able to orientate the world to any position you want!
It expands on the previous Recolor tool which is now renamed to "Repaint". The following features can be used individually or in any combination:
Same as before (but see the "jitter" feature below which adds new functionality to Recolo)
Similar to "Recolor" except it repaints existings strokes with a different brush. This is the same as the"Rebrush" tool in previous experimental builds. That feature is now part of this Repaint Tool)
Change the brush size of existing strokes.
When this option is turned on, recolor and resize will add random variations based on your current Jitter settings.
In addition to the Repaint Tool, this build adds some new features to the existing "Color Jitter" settings on the Color picker (the Dice icon near the bottom)
This slider controls how much the stroke size varies from stroke to stroke. All the way to the left behaves normally. As you move the slider more to the right, each stroke will have more randomness applied to it's stroke size.
This slider controls how much randomness is applied to each point on a brush stroke. . All the way to the left behaves normally. As you move the slider more to the right, each point of the stroke will be randomly shifted from it's usual position. At higher settings and with some brushes this will cause the brush stroke to actually split and form multiple small strokes.
Try a high setting for "Jitter positions" and press the trigger to draw but don't move your hand. You'll get a small spherical "squiggle" that can be very interesting with some brushes.
Draw something regular with the Hull brush and make copies of it. Then use the "Repaint Tool" with a low setting for "Jitter positions" to add random variation to each copy
Position jitter can cause strokes to break into many small strokes. This depends on the brush you use and amount of jitter. Try really low jitter settings, try smaller brush sizes and try different brush types such as tube brushes (they tend not to break up as much)
Modifying parts of existing sketches. Adding random variation after you've already painted something. Trying out different brushes and reusing parts of a sketch with different properties. (try duplicating some strokes and then repainting the duplicate)
The Recolor button on the Tools Panel has been replaced with "Repaint". When you select it, a side panel appears with 4 toggle buttons: Recolor, Resize, Rebrush and Jitter.
Any combination of these 4 options can be selected at any time. If you choose "jitter" then set your chosen amount of jitter using the button with the dice icon at the bottom of the Color Picker Panel
This is a 3D-version of bimanual tape drawing sometimes used in automotive drafting.
Holding the off-hand trigger down will constrain the brush to move in a straight line towards the off-hand controller.
You can curve the line by using your off-hand controller to control the stroke's direction while using your main-hand controller to move the cursor closer to the off-hand controller and control the stroke's orientation.
The Revolver adds a lathe function to the Wand Stroke Guide. Activate the Revolver by tapping the button marked with a bulls-eye icon while the Wand Stroke Guide is active.
The radius of the revolving arc constraint is dependent on the distance between the main hand controller and the Wand Stroke Guide Axis. You can tap the bulls-eye button to adjust the radius.
The revolver can also be made to automatically sweep around the axis by using the joystick.
If you are having issues using Open Brush, check out your options below.
If you have tried to export or save a file but you don’t see anything in Open Brush, the file has probably saved to your computer. Flip over your painting controller and check the history panel. It will display a list of all of your most recent actions or exports.
Open Brush makes saves of your work in Documents\Open Brush\Sketches\Autosave. Each new sketch you create will have a separate autosave file, and Open Brush will store autosaves from your last five sketches. If you need to access an autosave, just drag it into the Sketches folder using Windows Explorer - it will have a Open Brush logo as its thumbnail in the Sketchbook.
This is commonly an issue with using an out-of-date version of DirectX. Make sure you're on the latest version of DirectX, and that you're running Open Brush on a PC that matches the minimum specs of the VR device you're using.
Antivirus software can sometimes interfere with Open Brush. Try disabling any AV or Firewall software you're running, and try starting Open Brush again.
If you downloaded Open Brush through Steam, try refreshing the cache by choosing to "Verify Integrity of Game Files..." for Open Brush through the Properties window.
Every time Open Brush is run, a log file is generated "output_log.txt". That log file can typically be found at: C:\Users\<your name>\AppData\LocalLow\Icosa Foundation\Open Brush
You can join our or post to our or the . At the time of writing Google still hosts the old Tilt Brush .
This means your Head Mounted Display is not detected, and you'll need troubleshoot your HMD. or your
Open Brush regularly saves your work into your Documents/Open Brush/Sketches/Autosave folder. Each sketch you make has a separate autosave file, and Open Brush keeps autosaves from your last five sketches. If you need to access an autosave, move it into your Documents/Open Brush/Sketches folder using Windows Explorer—it will have an Open Brush logo as its thumbnail in the Sketchbook.
When you are finished with your 3D creation, you can save your Open Brush sketch to your computer, or share it to Icosa or Sketchfab. You can also take snapshot, GIFs or videos of your art to send to friends or post online.
While painting, you can save your sketch to avoid losing changes.
Take a snapshot of your sketch to use as a thumbnail image.
Your sketch is now added to your Sketchbook.
Your sketch file is saved to your computer at Documents/Open Brush/Sketches.
If you're having issues saving your sketch, check that you have administration privileges on your machine. Antivirus software can also sometimes interfere with the ability to save sketches.
While in your sketch, go to Tools > Cameras.
With your painting controller, swipe the thumbpad to toggle between Auto GIF, 5-second GiF, video, and snapshot.
After selecting your option, your image file will save to the Documents folder on your computer.
You can then share photos, videos, and GIFs or your artwork online.
Note: Using Cameras will not save the sketch file to gallery.
Select 5-second GIF from the Cameras menu.
On your painting controller, hold down the trigger to start recording. You can release the trigger to reposition or paint, then hold down the trigger again to continue recording.
When the recording hits 5-seconds, the GIF will be saved to your desktop under Documents/Open Brush/Snapshots.
Select Video from the Cameras menu.
On your painting controller, tap the trigger to start recording. Tap the trigger again to stop.
Your captured video will be saved to your desktop under Documents/Open Brush/Videos
If you are an advanced user, you can also generate a high resolution video using offline rendering. Detailed instructions can be found in our release notes.
Select Video from the Cameras menu.
On your painting controller, tap the trigger to start recording. Tap the trigger again to stop.
Hold down the thumbpad after a video has finished recording to go into Preview mode.
If you like the video you’ve captured, hold down the checkmark to upload.
If you haven't already, you will need to sign-into your YouTube account in your default desktop browser.
.fbx is a popular format for 3D modeling, and can be used in applications like Blender and Maya.
From the Tools panel, select "More Options..." > Labs > Export.
A folder will be created in Open Brush/exports that contains subfolders for each 3d file format currently supported. Each folder may also contain brush textures
For more information see Exporting Open Brush Sketches to Other Apps
To create a 360 video, follow the instructions here. Note: this is an advanced feature, and requires some working knowledge of the command line.
Google had various stages for a new feature to make it's way into Tilt Brush. It would start off available only to a closed group of testers and developers. After that it might be added to the Labs panel in the official release. And finally it would be released as an officially supported feature.
When Tilt Brush was released as open source, we discovered all the features that had been previously available to a select few and we made these available for everyone to try.
Note that using experimental mode used to require running a separate build of Open Brush (prior to 2.0). This is no longer the case - all versions can switch to experimental mode by going in to settings, hitting the toggle button and restarting the app.
Simply open up the Settings Panel, click the button and restart Open Brush.
The main thing to be aware of with "Experimental Mode" builds is the new brushes. Any sketch you save that contains these new brushes may not look correct when you export it to another piece of software or load it in a non-experimental version of Open Brush.
We also have a special version of Open Brush Unity SDK with support for most of the experimental brushes. See the notes for the latest release.
There are 50 new brushes - although some duplicate existing brushes and were included for technical reasons. That still leaves plenty of cool new brushes to play with. But be warned - they might not look correct when you export your sketches. Which is why they are still in "experimental mode" only.
This is for PC only (not Quest). As well as importing still images and videos you can import 3D models (fbx/obj/gltf). The importer is rather fussy and doesn't work reliably. We'd like to improve this and move it to the main release.
Combined with the new Drafting Brush, this gives an easy way to sketch out guides and construction lines for yourself. This button quickly toggles them on and off so you can see them while you paint and then quickly see how your sketch will appear to others when you export it without the drafting lines.
If the mirror tool is great, then a double mirror is twice as great. Instant 4-way symmetry. ( If you're interested in painting with more complex symmetry then you can also check out the Multi-Mirror Feature build)
This will save the currently selected strokes to your Local Media Library so you can use them in other sketches like you can imported 3d models.
Not as interesting as it sounds. Mainly useful for developers testing changes or new hardware.
To try out newer features, you can open up the Labs panel. Here you will find some of the latest additions to Open Brush.
(If you're really interested in cutting edge features then you might also want to look at installing alternate or experimental builds.)
Make sure you are in Advanced Mode.
Below your palette, go to the Menu panel and select "More Options...".
On your paint palette, swipe to the Tools panel and select More.
Select Labs.
Tiltasaurus is a virtual reality game where your friends can guess what you're drawing in Open Brush. To play Tiltasaurus:
In Open Brush, make sure you are in Advanced Mode.
Go to the Menu panel (below your palette) and select "More Options..." > Labs > Tiltasaurus.
The player wearing the headset will see a card with a word or phrase to draw.
The player who is not wearing the headset will see a category displayed on the computer desktop, but will not see the word or phrase on the card.
As the player in the headset begins to draw, the player looking at the desktop can guess the word or phrase.
Once they guess correctly, you can switch and start again. Clear the current drawing and get a new word or phrase by hitting Refresh on the card.
Adding Tiltasaurus.json to the Documents/Open Brush folder will let you add your own list of words.
See Importing Images, Videos or 3D Models
(docs coming)
See the section on Exporting
(docs coming)
See the section on Scripting Open Brush
See the section on Snapping
Reference Images allow you to view image files inside your Open Brush sketch. This can be useful for getting inspiration while drawing, or to incorporate as media in your sketch.
Reference Images are in version 21.0+ on Oculus Quest.
The Reference Images Panel can be found on the Labs Panel. The Labs Panel is located in the 'More Options...' section of the Admin Panel in Advanced Mode.
If you are in Beginner Mode, point to the Admin Panel on your menu hand. On the bottom-left is a button to switch to Advanced Mode. Click this.
Once in Advanced Mode, point to the Admin Panel on your menu hand. On the bottom-right is a button that reads, 'More Options...'. Click this.
A popup will appear with a few choices. Click 'Labs'.
The Labs Panel will spin out. Point at it and find the 'Reference Images' button. Click this.
The Reference Images Panel will spin out.
On the Reference Images Panel, click any thumbnail to load the image. After it loads, click it again to bring it in to your sketch.
Once connected to a PC, look for, 'Quest' in Windows Explorer. Click this.
Navigate to '..Quest\Internal shared storage\Open Brush\Media Library\Images\'
Copy image files (.jpg or .png) into this folder.
Images take up video memory inside Open Brush and including too many will cause Open Brush to crash. There are some restrictions on image files.
Only .jpg and .png file types.
Max image file size is 10Mb.
Max image dimension (height and width) is 1024.
eIf you want to see an image or 3D model while you paint in Open Brush, you can add it to your scene. You can move, change, or delete reference images.
Make sure you are in Advanced Mode.
Below your palette, go to the Menu panel and select "More Options...".
On your paint palette, swipe to the Tools panel and select More.
Click this icon to open the Media Library:
On a computer, copy a PNG or JPG file to Documents/Open Brush/Media Library/Images.
In Open Brush, make sure you are in Advanced Mode.
Go to the Menu panel (below your palette) and select "More Options..." > Labs > Local Media Library > Local Images.
Switch between selecting images and models using the icons in the top left.
Add a 3D model
On a computer, copy the model files to Documents/Open Brush/Media Library/Models.
In Open Brush, make sure you are in Advanced Mode. On the Quest you also need to switch Experimental Mode on in the settings.
Go to the Menu panel (below your palette) and select "More Options..." > Labs > Local Media Library > Local Models.
Switch between selecting images and models using the icons in the top left.
See "Supported Formats" below to see which file types you can use.
Move an image or model: Position your controller on the image, press and hold a grip button on the side of your controller. Then, drag the image to the new location and release the grip button.
Resize an image or model: With your controllers near the image, press and hold both grip buttons. Then, move the controllers farther apart or closer together.
Pin an image or model: While holding your selection with the grip, pull the trigger to pin. Alternatively, you can use the Pin tool to pin images, models, or guides.
Remove an image or model: With your controller near the reference image, press and hold a grip button. Then, flick the controller away from your body and release the grip button.
We have an alternative version of GLB export which can have some advantages over the importer we released in v2.4.
You may notice a number of brush stroke options are labeled as audio reactive. These are special types of brush strokes which can react to music or audio playing from your desktop.
Begin playing audio from your computer desktop.
Point your painting controller on Brushes page and click the wavy audio reactive icon.
You will see a message that Open Brush is listening for audio.
Once audio is detected, press the trigger on your painting controller and begin to lay down your brush strokes.
Different types of audio reactive brush strokes react to music in various ways - like pulsing, bouncing, or lighting up. You can use them to create an audio visualizer within your artwork.
Remixing allows others to download, edit, and republish your sketch. If you allow remixing, your content will be published under a CC-BY license. We’ll automatically show attribution on any remixed content we publish.
You can choose whether your content can be remixed by selecting from the "Allow remixes" or "Don't allow remixes" options under "Remixes" each time you publish. By default this option is set to "Allow remixes". You can change this setting at any time.
Attribution is required under the CC BY license. Any remix we publish will automatically show the source sketch’s title and author underneath the 3D viewer. You retain your copyright and other users get to reuse your work subject to the terms of the license.
If you delete content that was once remixable, or change the settings to remove remix rights, existing copies of your content used for remixes won’t be deleted.
Please understand that you may only mark your published sketches as remixable if it consists entirely of content licensable by you under the CC BY license. Some examples of such licensable content are:
Your originally created content
Other sketches marked with a CC BY license
How to Import OpenBrush FBX files & edit Materials to appear correctly
This example uses models that are best viewed without lighting. In UE5's scene view, change the scene lighting to "UNLIT" (top left of window).
Drag the FBX from Windows Explorer into the UE5 scene
An FBX Import Option menu will come up:
Make sure to select: Advanced > Vertex Color Import Option [REPLACE]
Upon importing the FBX, the Content Drawer will include the meshes and materials
Create a subfolder for MATERIALS and TEXTURES
Select the imported materials, drag and drop them into the newly created MATERIALS folder
The materials are pretty terribly named. I highly recommend renaming them. The brush material names are at the end of the filename:
From Windows Explorer, drag optimized PNG brush textures into the UE5 TEXTURES folder:
From the CONTENT DRAWER, drag and drop the meshes into the scene. I recommend creating a folder in the OUTLINER window and drag all the mesh objects into there:
Selecting all the model mesh objects, it may help to update these DETAILS:
Location: 0,0,0 Scale: 0.5,0.5,0.5
I also recommend turning off visibility of all the other non-mesh objects in the OUTLINER tab (e.g. Atmospheric Fog, Floor, etc.)
Edit Vertex Colors to Materials that only need Vertex Colors:
In CONTENT DRAWER > MATERIALS, double click the "Flat" material file. The Material Graph window will popup
Right click on the empty grid, type in VERTEX COLOR to add the node
Connect the top white dot to BASE COLOR in the "FLAT" window.
Click on "FLAT" so you can see its DETAILS on the left menu
Update: BLEND MODE - MASKED Two Sided - [checked]
That's it! Be sure to save these edits or CTRL + S. The edits won't show up on the main scene window until these Material changes are saved.
Repeat for the other three materials listed above that only need Vertex Colors associated to the materials.
Edit Materials that need Vertex Colors and Texture Sample:
Do the same steps above to add VERTEX COLOR to the BASE COLOR
Do the same steps above to update the Material Details to (same as before): BLEND MODE - MASKED Two Sided - [checked]
Right click the empty grid space and type in TEXTURE SAMPLE to bring up a node where you'll associate the texture png files
Click on the TEXTURE SAMPLE node window so you can edit the DETAILS
In the section for "Material Expression Texture Base" click on the dropdown to select the texture name that matches with the material name.
NOTE: The DoubleTaperedMarker material can use the "Marker" texture
Connect the TEXTURE SAMPLE node's "RGBA" dot to the Material's "Opacity Mask" dot
REPEAT for the other materials with same properties
Edit Materials that need Vertex Colors, Texture Sample, and Transparency:
Do the same steps above to add VERTEX COLOR to the BASE COLOR
Update the Material Details: BLEND MODE - ADDITIVE Two Sided - [checked] "Additive" will allow these brushes to appear semi-transparent, foggy, smokey.
Do the same steps as above to associate textures to TEXTURE SAMPLE node
Connect the TEXTURE SAMPLE node's "RGBA" dot to the Material's "Opacity" [not Opacity Mask as previous materials]
REPEAT for the other materials with same properties
Make sure to save all of your Material window edits!
Make sure to view this in "unlit" mode.
Also hide the Light Source, etc to prevent any shadows from showing up in the scene.
Reward yourself with ice cream.
Open Brush sketches can be exported by clicking the ‘Export’ button found on the Labs panel. The Labs panel can be found under ‘More…’ on the Tools panel.
Each sketch exported from Open Brush creates a separate folder in Documents/Open Brush/Exports which contains the geometry in the following formats:
(.glb is closely related to .gltf and most software will support both. We output binary glTF version 2)
python convert_to_fbx.py "c:\Users\username\Documents\Open Brush\Exports\Untitled_1.json"
Each script has a set of command-line options that fine-tune the generated file.
Add both to your Flipside Unity project
Export your Open Brush sketch and import the .glb file into the Flipside project
Follow the Flipside instructions for uploading a Unity scene as a Flipside Set
After importing the FBX file into Maya you will need to turn off the Alpha is Luminance attribute in the Color Balance section for each texture node. To see the brush colors in the viewport turn on the Display Colors attribute and set Material Blend to Multiply in the Mesh Component Display section on each mesh shape node.
To render with the vertex colors you can use the mentalrayVertexColors shader node to access the stroke color in your material.
Mozilla Spoke (the Hubs editor) gives an error when you try to import our .glb file directly. However importing first into Blender and then re-exporting will fix this. Not all brushes work correctly but the simpler brushes should import fairly well.
To post to Sketchfab you will need to upload the FBX file and the textures.
We are working with Sketchfab to have Open Brush import correctly, but if the strokes look wrong you can try opening the 3D Settings Editor in Sketchfab and under the Materials tab set the material properties manually.
To upload your work to Styly, you'll need to remove all traces of the audio-reactivity scripts in the Open Brush toolkit.
Delete the following folders from your Unity project window:
ThirdParty/CSCore
ThirdParty/Reaktion
Delete the following files from you Unity project window:
TiltBrush/Scripts:/VisualizerAudioInput
TiltBrush/Scripts:/VisualizerManager
TiltBrush/Scripts/Editor/VisualizerManagerEditor
Also in the project window, drag the entire TiltBrush/Scripts/Gltf folder so it's inside TiltBrush/Scripts/Editor
Carry on where you left off with the Styly docs.
You'll need to delete the following 2 scripts if you want to build for Unity WebGL targets: GenericAudioInputEditor.cs
and GenericAudioInput.cs
To export sketches from the command line, use the --export option to specify a file or set of files to export. --export supports wildcards, and multiple files can be specified with a single --export flag. Filenames without a path are assumed to be found in the Open Brush Sketches directory.
You can override the destination folder of exports using the --exportPath flag.
We suggest you also specify the -batchmode option if you don’t want the Open Brush window to appear.
Navigate to the Tools panel in the palette, and select the Save icon:
To share your creations outside of Open Brush, click Upload to publish your sketch to Icosa. Once you have published your sketch, you can share the link to your sketch on social networks like Facebook, Twitter, and Google+.
To add more images to the Reference Images Panel, you need to connect your Oculus Quest to a PC. Use to learn how to do that.
Select Labs to open the
Video support varies across OS and hardware versions. See: for more detailed information.
To switch to the new importer (UnityGLTF which replaces GLTFast added in the v2.4 release) you need to edit your and add this entry after "Flags":
licenses provide a standard way for content creators to grant someone else permission to use their work. If you allow remixing, your content will be published under a license. These sketches are then accessible to other Open Brush Sketches users for use, even commercially, in their own sketches.
If you don't allow remixing, your content will be published under the standard Google .
Docs contributed by . Additional thanks to
.latk is an interchange format for 3d brush strokes:
The .json is a “raw” format which you can use if you need a different file format. See the for sample scripts that convert the raw .json to .obj.
The USD contains both geometry and curve information. If your DCC tool doesn’t support USD, the contains a Python 2.7 script that can convert the .tilt file to a Collada .dae containing the curves.
Follow the instructions for installing and configuring
Download the .unitypackage for the latest release of the
You'll also need the from the same page
Follow the instructions for setting up Styly in Unity here: but stop when you get to the section about half-way through headed "Upload from Unity to STYLY"
Download the Open Brush Unity SDK unitypackage as described here:
We recommend using the and the .glb format. Open Brush Toolkit also understands the .fbx format. More info
Images
PNG
JPEG
SVG
SVGs are rasterized on import.
HDR
Video
MP4
See notes below.
MKV
See notes below.
MOV
See notes below.
WEBM
See notes below. Must use VP8 codec. Supports transparency on Windows only.
3d Models
GLTF/GLB
OBJ
PC/Mac only.
FBX
PC/Mac only.
USD
PC/Mac only. Support is rather outdated and experimental
PLY
Point clouds only. Binary little-endian format.
Material Name
NODE: Vertex Color
NODE: Texture Sample
Material Details
Flat
✓
No
Blend Mode: MASKED ☑ Two Sided
MatteHull
✓
No
Blend Mode: MASKED ☑ Two Sided
UnlitHull
✓
No
Blend Mode: MASKED ☑ Two Sided
Wire
✓
No
Blend Mode: MASKED ☑ Two Sided
Material Name
NODE: Vertex Color
NODE: Texture Sample
Material Details
DiamondHull
✓
✓ RGBA connects to Opacity Mask
Blend Mode: MASKED ☑ Two Sided
Dots
✓
✓ RGBA connects to Opacity Mask
Blend Mode: MASKED ☑ Two Sided
DoubleTaperedMarker
✓
✓ RGBA connects to Opacity Mask
Blend Mode: MASKED ☑ Two Sided
Embers
✓
✓ RGBA connects to Opacity Mask
Blend Mode: MASKED ☑ Two Sided
Marker
✓
✓ RGBA connects to Opacity Mask
Blend Mode: MASKED ☑ Two Sided
Material Name
NODE: Vertex Color
NODE: Texture Sample
Material Details
Highlighter
✓
✓ RGBA connects to Opacity
Blend Mode: ADDITIVE ☑ Two Sided
Smoke
✓
✓ RGBA connects to Opacity
Blend Mode: ADDITIVE ☑ Two Sided
SoftHighlighter
✓
✓ RGBA connects to Opacity
Blend Mode: ADDITIVE ☑ Two Sided
GLTF/GLB
FBX
OBJ
USD
JSON
LATK
WRL
STL
The Open Brush config file can be used to tweak various options for advanced users. A blank Open Brush.cfg file will be created in the Open Brush folder on application startup if one does not exist.
Example PC path: C:\Users\<username>\Documents\Open Brush\Open Brush.cfg.
On an Oculus Quest, you can find this file in /sdcard/Open Brush. You can use either adb or the SideQuest file viewer to access this file. You could also sideload a text editor if you want to edit the file directly.
The file must be valid json. If it's not working check to see if you've missed any commas or brackets. Using a JSON Validator can help if you're stuck.
Example of an empty Open Brush.cfg:
Sample contents of a Open Brush.cfg with various fields filled in:
Author: The name you use here will be stored in files uploaded to Icosa, Sketchfab etc.
AddTagsToBrushes: See Brush Tags
RemoveTagsFromBrushes: See Brush Tags
IncludeTags: See Brush Tags
ExcludeTags: See Brush Tags
Encoder: (h.264) This setting specifies the video codec used for encoding exported videos. Currently, the only supported codec is h.264.
PostEffectsOnCapture: (true | false) This setting determines whether post-processing effects will be applied to captured images or videos. When set to true, effects will be applied; when set to false, they will not.
ShowWatermark: (true | false) This setting controls the visibility of the Open Brush watermark on exported images and videos. When set to true, the watermark will be visible; when set to false, it will be hidden.
ShowHeadset: (true | false) This setting determines whether the user's VR headset will be visible in the final exported images or videos. When set to true, the headset will be shown; when set to false, it will not.
UnlockScale: (true | false) This setting allows users to scale their artwork beyond the default limits. When set to true, users can scale their artwork to larger sizes; when set to false, scaling will be limited to the default range.
SnapshotWidth: (1 - some reasonably large number) This setting controls the width (in pixels) of exported images. Users can specify a value between 1 and a reasonably large number to set the desired image width.
SnapshotHeight: (1 - some reasonably large number) This setting controls the height (in pixels) of exported images. Users can specify a value between 1 and a reasonably large number to set the desired image height.
FOV: (1 - 179) This setting determines the field of view (FOV) for the camera used during image or video capture. Users can specify a value between 1 and 179 degrees to set the desired FOV.
DisableAudio: (true | false) This setting allows users to disable audio playback within Open Brush. When set to true, audio playback will be disabled; when set to false, audio playback will function as normal.
AdvancedKeyboardShortcuts: (true | false) Enables some extra keyboard shortcuts that were previously available in Experimental Mode
SkipIntro: (true | false) Skips the intro scene that appears when Open Brush finishes loading
EnableMonoscopicMode: (true | false) See Using Open Brush without a VR headset
DisableXrMode: (true | false) See Using Open Brush without a VR headset
ExportBinaryFbx: (true | false) This setting controls whether exported FBX files will be in binary format. When set to true, binary FBX files will be exported; when set to false, ASCII FBX files will be exported.
ExportFbxVersion: (FBX201600 | FBX201400 | FBX201300 | FBX2012 | FBX201100) This setting specifies the version of the FBX file format to be used when exporting 3D models. Users can choose from FBX201600, FBX201400, FBX201300, FBX2012, or FBX201100. If not specified in the config file, the default version is FBX201400. If users experience issues importing the FBX file into older software, they may need to select an older version.
ExportStrokeTimestamp: (true | false) This will put timing information into texcoord2 for all GLB exports. Timestamps are a vec3: x,y = the earliest/latest timestamp in the stroke which contains that vertex. z = the timestamp for that vertex. This setting defaults to true but can be disabled to reduce file size.
Any of the above settings in the Open Brush.cfg file can also be specified on the command line (not applicable to Quest users). The format is --Section.Setting <value>. For example:
http://localhost:40074/cameraview is a convenient endpoint you can call to get the current desktop view as a png. It will either be the headset or monoscopic user view - or the spectator camera if that is active.
Image size is based on the current desktop window size. Combined with API commands to move the spectator camera around, this can be used to automate complex renders or your own custom camera paths.
In a web page you can use this for a simple (nearly) realtime preview:
Be careful calling it too often as it's not terribly efficient and will slow down Open Brush. The above example refreshes once per second. We plan to implement a much more efficient WebRTC streaming endpoint at some stage but that will be more complex for client scripts to implement so this simple endpoint will still remain useful.
If you want to access the preview image from a different device to the one running Open Brush, you'll need to allow external connections to the API: https://docs.openbrush.app/alternate-and-experimental-builds/experimental-builds/open-brush-api#how-do-i-configure-it
This page was generated from the output directly from Open Brush API server. It's not always totally up to date. When you're running Open Brush then use the live commands list you get from http://localhost:40074/help/commands as that will always be current.
The "Try It" links assume that a version of Open Brush with API support is currently running on this computer. They won't work if Open Brush isn't running. You can run a monoscopic version if you don't have a VR headset attached.
To run commands just send a request to this url with http://localhost:40074/api/v1?
Commands are query string parameters. Like this: command.name=parameters
Separate multiple commands with: &
Example: http://localhost:40074/api/v1?brush.turn.y=45&brush.draw=1
If you want to send a lot of commands or especially long commands (complex paths etc) then you can just http POST instead of GET. The commands should be form-encoded in the body of the request (exactly as if you submitted a html form with the form name as the command name and the form value as the command parameters)
You can also send multiple requests although because of the nature of http, these can sometimes arrive in a different order to how yousent them. We will soon support websockets which should be a better way to send realtime streams of commands.
draw.paths (string jsonString) Try it
Draws a series of paths at the current brush position [[[x1,y1,z1],[x2,y2,z2], etc...]]. Does not move the brush position
draw.path (string jsonString) Try it
Draws a path at the current brush position [[x1,y1,z1],[x2,y2,z2], etc...]. Does not move the brush position
draw.polygon (int sides, float radius, float angle) Try it
Draws a polygon at the current brush position. Does not move the brush position
showfolder.scripts Try it
Opens the user's Scripts folder on the desktop
showfolder.exports Try it
Opens the user's Exports folder on the desktop
draw.text (string text) Try it
Draws the characters supplied at the current brush position
draw.svg (string svgPathString) Try it
Draws the path supplied as an SVG Path string at the current brush position
brush.type (string brushType) Try it
Changes the brush. brushType can either be the brush name or it's guid. brushes are listed in the localhost:40074/help screen
color.add.hsv (Vector3 hsv) Try it
Adds the supplied values to the current color. Values are hue, saturation and value
color.add.rgb (Vector3 rgb) Try it
Adds the supplied values to the current color. Values are red green and blue
color.set.rgb (Vector3 rgb) Try it
Sets the current color. Values are hue, saturation and value
color.set.hsv (Vector3 hsv) Try it
Sets the current color. Values are red, green and blue
color.set.html (string color) Try it
Sets the current color. colorString can either be a hex value or a css color name.
brush.size.set (float size) Try it
Sets the current brush size
brush.size.add (float amount) Try it
Changes the current brush size by 'amount'
camera.move.to (Vector3 position) Try it
Moves the spectator or non-VR camera to the given position
camera.move.by (Vector3 amount) Try it
Moves the spectator or non-VR camera by the given amount
camera.turn.y (float angle) Try it
Turns the spectator or non-VR camera left or right.
camera.turn.x (float angle) Try it
Changes the angle of the spectator or non-VR camera up or down.
camera.turn.z (float angle) Try it
Tilts the angle of the spectator or non-VR camera clockwise or anticlockwise.
camera.lookat (Vector3 direction) Try it
Points the spectator or non-VR camera to look in the specified direction. Angles are given in x,y,z degrees
brush.move.to (Vector3 position) Try it
Moves the brush to the given coordinates
brush.move.by (Vector3 offset) Try it
Moves the brush by the given amount
brush.move (float distance) Try it
Moves the brush forward by 'distance' without drawing a line
brush.draw (float distance) Try it
Moves the brush forward by 'distance' and draws a line
brush.turn.y (float angle) Try it
Changes the brush direction to the left or right. Angle is measured in degrees
brush.turn.x (float angle) Try it
Changes the brush direction up or down. Angle is measured in degrees
brush.turn.z (float angle) Try it
Rotates the brush clockwise or anticlockwise. Angle is measured in degrees
brush.lookat (Vector3 direction) Try it
Changes the brush direction to look at the specified point
brush.look.forwards Try it
Changes the brush direction to look forwards
brush.look.up Try it
Changes the brush direction to look upwards
brush.look.down Try it
Changes the brush direction to look downwards
brush.look.left Try it
Changes the brush direction to look to the left
brush.look.right Try it
Changes the brush direction to look to the right
brush.look.backwards Try it
Changes the brush direction to look backwards
brush.home Try it
Resets the brush position and direction
brush.home.set Try it
Sets the current brush position and direction as the new home
brush.transform.push Try it
Stores the current brush position and direction on to a stack
brush.transform.pop Try it
Pops the most recent current brush position and direction from the stack
debug.brush Try it
Logs some info about the brush
stroke.delete (int index) Try it
Delete strokes by their index. If index is 0 the most recent stroke is deleted. -1 etc steps back in time
stroke.select (int index) Try it
Selects a stroke by it's index. 0 is the most recent stroke, -1 is second to last, 1 is the first.
strokes.select (int start, int end) Try it
Select multiple strokes by their index. 0 is the most recent stroke, -1 is second to last, 1 is the first.
selection.recolor Try it
Recolors the currently selected strokes
selection.rebrush Try it
Rebrushes the currently selected strokes
selection.resize Try it
Changes the brush size the currently selected strokes
selection.trim (int count) Try it
Removes a number of points from the currently selected strokes
selection.points.addnoise (string axis, Vector3 scale) Try it
Moves the position of all control points in the selection using a noise function
selection.points.quantize (Vector3 grid) Try it
Snaps all the points in selected strokes to a grid (buggy)
stroke.join Try it
Joins a stroke with the previous one
strokes.join (int start, int end) Try it
Joins all strokes between the two indices (inclusive)
stroke.add (int index) Try it
Adds a point at the current brush position to the specified stroke
tool.sketchsurface Try it
Activates the SketchSurface
tool.selection Try it
Activates the Selection Tool
tool.colorpicker Try it
Activates the Color Picker
tool.brushpicker Try it
Activates the Brush Picker
tool.brushandcolorpicker Try it
Activates the Brush And Color Picker
tool.sketchorigin Try it
Activates the SketchOrigin Tool
tool.autogif Try it
Activates the AutoGif Tool
tool.canvas Try it
Activates the Canvas Tool
tool.transform Try it
Activates the Transform Tool
tool.stamp Try it
Activates the Stamp Tool
tool.freepaint Try it
Activates the FreePaint Tool
tool.eraser Try it
Activates the Eraser Tool
tool.screenshot Try it
Activates the Screenshot Tool
tool.dropper Try it
Activates the Dropper Tool
tool.saveicon Try it
Activates the SaveIcon Tool
tool.threedofviewing Try it
Activates the ThreeDofViewing Tool
tool.multicam Try it
Activates the MultiCam Tool
tool.teleport Try it
Activates the Teleport Tool
tool.repaint Try it
Activates the Repaint Tool
tool.recolor Try it
Activates the Recolor Tool
tool.rebrush Try it
Activates the Rebrush Tool
tool.pin Try it
Activates the Pin Tool
tool.camerapath Try it
Activates the CameraPath Tool
tool.fly Try it
Activates the Fly Tool
save.overwrite Try it
Save the current scene overwriting the last save if it exists
save Try it
Saves the current scene in a new slot
export.all Try it
Exports all the scenes in the users's sketch folder
drafting.visible Try it
Shows all strokes made with the drafting brush fully opaque
drafting.transparent Try it
Shows all strokes made with the drafting brush semi-transparent
drafting.hidden Try it
Hides all strokes made with the drafting brush
load.user (int slot) Try it
Loads the sketch in the given slot number from the user's sketch folder
load.curated (int slot) Try it
Loads the sketch in the given slot number from the curated sketch list
load.liked (int slot) Try it
Loads the sketch in the given slot number from the user's liked sketches
load.drive (int slot) Try it
Loads the sketch in the given slot number from the user's Google Drive
load.named (string filename) Try it
Loads the sketch with the given name from the user's sketch folder
new Try it
Clears the current sketch
symmetry.mirror Try it
Sets the symmetry mode to 'mirror'
symmetry.doublemirror Try it
Sets the symmetry mode to 'double mirror'
straightedge.toggle Try it
Toggles the straight edge tool on or off
autoorient.toggle Try it
Toggles autoorientate on or off
undo Try it
Undoes the last action
redo Try it
Redo the last action
panels.reset Try it
Reset the position of all panels
sketch.origin Try it
Enables the sketch origin tool
viewonly.toggle Try it
Toggles 'view only' mode on or off
dropcam.toggle Try it
Toggles the Drop Cam widget on or off
autosimplify.toggle Try it
Toggles 'auto-simplify' mode on or off
export Try it
Exports the current sketch to the user's Exports folder
showfolder.sketch (int index) Try it
Opens the user's Sketches folder on the desktop
stencils.disabled Try it
Disables all stencils
disco Try it
Starts a party
selection.duplicate Try it
Create a duplicate of the current selection
selection.group Try it
Groups the current selection
export.selected Try it
Exports the selected strokes to the user's Media Library
camerapath.render Try it
Renders the current camera path to a video
profiling.toggle Try it
Toggles profiling mode on or off
settings.toggle Try it
Toggles the settings panel on or off
mirror.summon Try it
Summons the mirror origin to the user's position
selection.invert Try it
Inverts the current selection
select.all Try it
Selects all strokes and widgets in the scene
selection.flip Try it
Mirrors the current selection
postprocessing.toggle Try it
Toggles post-processing effects on or off
watermark.toggle Try it
Toggles the watermark on or off
camerapath.togglevisuals Try it
Toggles the camera path visuals on or off
camerapath.togglepreview Try it
Toggles the camera path preview on or off
camerapath.delete Try it
Deletes the current camera path
camerapath.record Try it
Starts recording a camera path
Currently the brush panel is cluttered with a large number of brushes and is likely to grow larger in the future. As a first step toward better organizing them, this feature serves to classify each brush with a list of tags and a couple of filtering options.
Via OpenBrush.cfg (UserConfig), the brushes that show up in the panel can be limited by using the following options:
IncludeTags - specifies all of the brushes that may be included included in the panel
ExcludeTags - specifies all of the brush that must be excluded (even if they are also in "include").
To test, try the following:
Declare include
{ "User": { }, "Brushes": { "IncludeTags": ["classroom"], }, "Video": { }, "Flags": { }, "Export": { }, }
Result should be only a single page of brushes that have been tagged with "classroom".
Add a new tag called "test" to a few brush descriptors that also have "classroom" and then declare inlude and exclude
{ "User": { }, "Brushes": { "IncludeTags": ["classroom"], "ExcludeTags": ["test"] }, "Video": { }, "Flags": { }, "Export": { }, }
Result should be only a single page of brushes that have been tagged with "classroom" minus the brush tagged with "test".
Exclude only case
{ "User": { }, "Brushes": { "ExcludeTags": ["classroom"] }, "Video": { }, "Flags": { }, "Export": { }, }
Result should be all of the brushes minus those tagged with classroom.
In addition, tags can be added and removed. Here is an example that includes this usage:
NOTE: Not all Tilt Brush brushes will export (e.g. particle brushes) The most reliable are the flat brushes and the Wire brush. Also, this process might not be compatible with Tilt Brush on the Quest as the export function works differently than the Rift.
NOTE: Tilt Brush’s settings exports the FBX as an ASCII model. Blender won’t accept it, and you’ll receive an error message in Blender: "ASCII FBX files are not supported"
To change the Tilt Brush FBX configuration from ASCII to Binary, follow these instructions to set up your Tilt Brush.cfg file: https://docs.google.com/document/d/11ZsHozYn9FnWG7y3s3WAyKIACfbfwb4PbaS8cZ_xjvo/preview#heading=h.g9ac8b39hgn0
Add this CFG setting if it's not already there:
Within Tilt Brush (in VR):
Swipe to the Tools panel
Select "More Options..." > Labs > Export.
An .fbx file, brush texture, and geometry will be saved to your desktop computer’s Documents/Tilt Brush/Exports folder.
For most optimization, consider taking the exported .PNGs and processing them thru https://tinypng.com/ to compress them even more.
In Blender
This helps merge vertices that are close together, and saves on polys
On the MESH subtab, go to Clean-up > Decimate Geometry
Export the FBX
Import the decimated FBX model from Blender
Rename Materials, (ex: from “13981290382_Marker” to “Marker”)
Drag and drop the TinyPNG optimized imgs into the Lens Studio > Resources > Textures folder
In the Resources > [ 3D Model Name ] folder > Materials, select the Material.
In the Inspector for the Material:
For the Blend Mode, select anything other than “Disabled” — I preferred Normal or Alpha to Coverage
For the Vertex Color dropdown, select “Base Color”
For the Base Texture, check to enable, add the Tilt Brush texture here
Docs contributed by Estella Tse. Additional thanks to Jose Andres Rosero
We've changed how export in general is configured. Previously all supported formats were exported whether you needed them or not. Some were pretty slow for large scenes (STL - looking at you) and you probably only needed a couple of them. Now you can choose which are available using the config file:
ExportBinaryFbx: This setting specifies the version of the FBX file format to be used when exporting 3D models. Users can choose from FBX201600, FBX201400, FBX201300, FBX2012, or FBX201100. If not specified in the config file, the default version is FBX201400. If users experience issues importing the FBX file into older software, they may need to select an older version.
ExportFbxVersion: Controls whether exported FBX files will be in binary format. When set to true, binary FBX files will be exported; when set to false, ASCII FBX files will be exported.
ExportStrokeTimestamp: (true | false) This will put timing information into texcoord2 for all GLB exports. Timestamps are a vec3: x,y = the earliest/latest timestamp in the stroke which contains that vertex. z = the timestamp for that vertex. This setting defaults to true but can be disabled to reduce file size.
ExportStrokeMetadata: includes extra information with each stroke that might be useful to developers writing their own importers
KeepStrokes: Each stroke will be exported as a separate mesh rather than grouped by brush type (export will take longer and may fail on complex scenes)
KeepGroups: Maintains groups on export (export will take longer and may fail on complex scenes)
Formats: Each item in here corresponds to an existing export format except for "newglb". This is also a glb file but we use the new export code to generate it.
Note that formats not supported on your platform will be ignored. See below for platform support.
Extensions supported by GLTFast but not UnityGLTF:
EXT_mesh_gpu_instancing
KHR_materials_pbrSpecularGlossiness (legacy extension - superseded by KHR_materials_specular which is only supported by UnityGLTF)
Extensions supported by UnityGLTF but not GLTFast:
KHR_materials_clearcoat
KHR_materials_emissive_strength
KHR_materials_ior
KHR_materials_iridescence
KHR_materials_specular
KHR_materials_transmission (soon)
KHR_materials_volume (soon)
MSFT_lod
Extensions supported by both:
KHR_draco_mesh_compression
KHR_lights_punctual
KHR_materials_unlit
KHR_mesh_quantization
KHR_texture_basisu
KHR_texture_transform
(The above list may change as we implement missing features in UnityGLTF. GLTFast also has announced plans to support KHR_materials_variants, EXT_lights_image_based and KHR_materials_transmission)
UnityGLTF has some other differences:
Model hierarchy should be faithfully preserved. GLTFast on the other hand doesn't support sub-meshes so any mesh that contains multiple materials will be split into separate objects. (this might be desirable in some cases)
In general 3d models should be more robustly handled if you round-trip between Open Brush and other 3D apps
Please report any other differences you find. The reason we are keeping both importers around is to gather feedback on their strengths and weaknesses.
The use of the new exporter is currently optional and we will continue to support the old exporter until the new one is a full replacement.
If you're using the existing Open Brush Unity Toolkit/SDK then use the older GLB format
If you're manually uploading to Icosa Gallery then use the older GLB format
If you're use the Icosa three.js loader this also works best with the older exporter.
The new GLB export format should work better in Blender and other 3D animation apps although we still have work to do to fix support for particle brushes, transparent brushes and other features.
Imported 3D models will export much better with the new GLB exporter
In general new features in the beta or from other experimental branches will work better using the new exporter.
FBX
✘
✔
GLB
✔
✔
NEWGLB
✔
✔
JSON
✔
✔
LATK
✔
✔
OBJ
✘
✔
STL
✔
✔
USD
✘
✔
WRL
✔
✔
This build supports a new feature - The existing "group/ungroup" button on the pop-out tray that appears when you activate the Selection Tool now works on imported models - if they consist of multiple parts. Just select a single imported model and if it does have sub-parts the button will show "ungroup" as an option - the same as if you select a normal grouped set of objects.
If your imported model contains lights then these will appear in the scene and will act upon other objects the same as the Environment Lights. Furthermore imported lights support point lights and spot lights - whereas the existing environment lights only support directional lights.
If you break apart a model containing lights, the lights themselves can't be selected or moved.
Using Open Brush with Unity
The Open Brush Unity SDK allows you to import your Open Brush sketches into Unity. The SDK includes:
All of Open Brush’s brush materials
An importer script that automatically assigns Open Brush materials to imported .glb files
Open Brush’s audio reactivity functionality that make brushes react to music
The SDK has these requirements:
Your project must use Unity 2019.4 or higher
Macs running on Apple Silicon (i.e. M1 or M2) need to remove Audio Reactivity to fix errors related to "CSCore".
Download the latest version of the toolkit from: https://github.com/icosa-foundation/open-brush-toolkit/releases
The SDK comes in the form of a Unity Package. To import:
Open Unity
Create a project or open an existing one
Double click the downloaded .unitypackage file, or go to Assets > Import Package > Custom Package.
Import the package
To use a Tilt Brush sketch inside of Unity, you need to export it and copy the exported .gltf file into your project. You do _not _need any of the .png files that come with the export. The SDK will use its own, Tilt Brush materials instead.
The SDK will process .glb files on import and assign the correct materials.
To export a sketch:
Open Tilt Brush, load your sketch
Click the [...] icon in the settings area of your hand menu
Click the **Labs **icon
Hit Export in the floating window that pops up
To import a sketch into your scene:
Find the exported files:
On a PC or Mac look in Documents/Open Brush/Exports
If you created the sketch on a standalone Quest thenconnect it to your PC/Mac by following these instructions and then browse to the Quest in Explorer/Finder and look in Internal Shared Storage/Open Brush/Exports
Copy the .glb file into your Unity project
Drag the file from the Project window into the Hierarchy
Notes:
The Open Brush Unity SDK doesn’t load .tilt files.
You don’t need to copy the textures included with the .glb into your project
At the moment the plugin used for Audio Reactivity doesn't work on some platforms. If you see errors related to "CSCore" or anything that looks audio related deleting the following files from your project:
The folder ThirdParty\CSCore
The folder ThirdParty\Reaktion
These files:
TiltBrush\Scripts\VisualizerManager
TiltBrush\Scripts\VisualizerAudioInput
TiltBrush\Scripts\Editor\VisualizerManagerEditor
For historical reasons Open Brush uses gamma mode for color blending. We may offer the option to switch to linear in the future but it will change the appearance of sketches so gamma will always be an option when the hardware allows it.
If your Unity project is set to linear mode (Projects > Player Settings) then imported sketches may look different. For example here's some smoke brush strokes in Open Brush:
And here's the same sketch in Unity set to linear mode:
The v11 toolkit shaders support both sRGB (Gamma) and Linear color spaces. The shaders are set to Gamma mode by default. If you wish to use Linear, add this call somewhere in your program.
Note: while this improves the colour accuracy, due to fundamental differences between linear and gamma rendering, brushes may still not exactly replicate the look of their gamma counterparts.
You can make the brushes wiggle to the audio in your scene:
Drag the** [Tilt Brush Audio Reactivity] prefab** into your scene
Add an audio source to your scene, if there’s none
If the brushes aren’t moving, you can select the prefab in Play mode to visualize the audio data the shaders are receiving:
Import the Standard Assets “Effects” package (Assets menu / Import Package / Effects)
Internally, Open Brush uses a modified version of Sonic Ether bloom, which has been released as open source.
The following gives an approximate measure of how "expensive" each brush is and how much it will contribute to your memory limit. For example you could have twice as many Duct Tape strokes (weight=1.5) as you could Disco (weight=3) before hitting your limit:
This is a list of the brushes that are only available in any "Experimental Mode" Builds:
Open Brush accepts the following command line arguments:
--noQuickLoad
--captureOds
--outputPath odsOutputPath
--outputPrefix odsOutputPrefix
--preview
--noCorrection
--turnTable
--numFrames
--fps
--export (followed by full path to .tilt file)
--exportPath (defaults to [Open Brush folder]/Exports
-batchmode / -nographics
--renderCameraPath
(filename of .tilt file in Sketches folder to load automatically)
(Any valid user config setting and value)
In the pop-up menu for Decimate, enter the ratio of how much to decimate. I entered 0.25. (https://drive.google.com/file/d/1qSM1ss9mMXxbh689WwgDVJP8ZIxPjGkE/view?usp=sharing)
You can achieve_ an Open Brush look_ by adding Bloom, using Unity’s built-in shaders:
**Important: **Enable your camera’s HDR checkbox
Add the Bloom post-processing effect, these are recommended settings:
Open Brush comes with a wide selection of brushes and there are even more if you switch on . But be warned that the experimental brushes can be more problemmatic if you need to export to other apps. See the docs on the and on for more information. We plan to move many of the experimental brushes into normal mode when we're satisfied that they work everywhere the regular brushes work.
This requires you to learn your way around Unity a little bit: Brushes created this way won't export to other apps correctly without manual shader editing. Using them in other Unity projects via the is possible but requires manual editing of the Unity shaders and materials.
Tim Aidley has created a feature that allows editing of brushes via config files:
Developed on top of Tim's work is a work-in-progress feature that allows editing brushes directly in VR. However it's experimental, doesn't currently work on the native Quest version of Open Brush and has had only a very small amount of testing so far:
(If you're not sure how to launch an app with command line arguments I found this tutorial via Google: - suggestions for a better link gratefully received)
Concave Hull
Dance Floor
Dot Marker
Faceted Tube
Plasma
3D Printing Brush
Tube Toon Inverted
Waveform FFT
Waveform Particles
Waveform Tube
Wireframe
Bubble Wand
Candy Cane
Buggy. Breaks "Undo"
Charcoal
Digital
Double Flat
Drafting
Use with the "Toggle Drafting Mode" button
Dry Brush
Duct Tape (Geometry)
Fairy
Feather
Fire2
Gouache
Guts
Tree
Buggy. Breaks "Undo"
Ink (Geometry)
Keijiro Tube
Lacewing
Leaky Pen
Wire (Lit)
Lofted (Hue Shift)
Marbled Rainbow
Muscle
Mylar Tube
Braid
Buggy. Breaks "Undo"
Race
Rain
Rising Bubbles
Single Sided
Smooth Hull
Snowflake
Buggy. Breaks "Undo"
Space
Sparks
Square Flat
TaperedHueShift
Tapered Wire
Leaves2
Geom/Thick (Duct Tape)
Tube (Highlighter)
Wind
Type: Most brushes fall into one of three categories: Flat (ribbon shaped), Tube (a cylinder or other shape with thickness) or Particle (the brush stroke generates multiple small objects that only roughly follow the path of the stroke)
Animated?: Does the brush stroke have any automatic movement either to it's shape or texture?
Self-lit?: A self-lit brush doesn't react to lighting and will still be visible even without any lights in the scene. It appears to give off it's own light (although brush strokes don't actually illuminate other objects nearby)
Audio Reactive?: Does the brush respond to audio when you turn on audio reactivity
Bubbles
Particle
Yes
Yes
No
Cel Vinyl
Flat
No
Yes
No
Chromatic Wave
Tube
Yes
Yes
Yes
Coarse Bristles
Spray
No
No
No
Comet
Tube
Yes
Yes
Yes
Concave Hull
No
No
No
Dance Floor
Yes
Yes
Yes
Diamond
Hull
No
No
No
Disco
Tube
Yes
Yes
Yes
Dot Marker
Spray
No
Yes
No
Dots
No
Yes
Yes
Pinched Flat
Flat
No
No
No
Pinched Marker
Flat
No
Yes
No
Duct Tape
Flat
No
No
No
Electricity
Flat
Yes
Yes
Yes
Embers
Particle
Yes
Yes
Yes
Faceted Tube
Tube
No
Yes
No
Felt
Flat
No
No
No
Fire
Flat
Yes
Yes
Yes
Flat
Flat
No
No
No
Highlighter
Flat
No
Yes
No
Hypercolor
Flat
Yes
Yes
Yes
Hyper Grid
No
Yes
Yes
Icing
Tube
No
No
No
Ink
Flat
No
No
No
Leaves
Spray
No
No
No
Light
Flat
No
Yes
Yes
Light Wire
Tube
Yes
Yes
Yes
Lofted
Tube
No
No
No
Marker
Flat
No
Yes
No
Matte Hull
Hull
No
No
No
Oil Paint
Flat
No
No
No
Paper
Flat
No
No
No
Petal
Tube
No
No
No
Plasma
Flat
Yes
Yes
Yes
Rainbow
Flat
Yes
Yes
Yes
Shiny Hull
Hull
No
No
No
Smoke
Particle
Yes
Yes
No
Snow
Particle
Yes
Yes
Yes
Soft Highlighter
Flat
No
Yes
Yes
Spikes
Tube
No
No
No
Splatter
Spray
No
No
No
3D Printing Brush
No
No
No
Stars
Particle
Yes
Yes
Yes
Streamers
Flat
Yes
Yes
Yes
Taffy
Flat
Yes
No
Tapered Flat
Flat
No
No
No
Tapered Highlighter
Flat
No
Yes
No
Tapered Marker
Flat
No
Yes
No
Thick Paint
Flat
No
No
No
Toon
Tube
No
Yes
Yes
Tube Toon Inverted
Tube
No
Yes
No
Unlit Hull
Hull
No
Yes
No
Velvet Ink
Flat
No
Yes
Yes
Waveform
Flat
Yes
Yes
Yes
Waveform FFT
Flat
Yes
Yes
Yes
Waveform Particles
Yes
Yes
Yes
Neon Pulse
Tube
Yes
Yes
Yes
Waveform Tube
Tube
Yes
Yes
Yes
Wet Paint
Flat
No
No
No
Dr. Wigglez
Flat
Yes
No
Yes
Wire
Tube
No
Yes
No
Wireframe
No
Yes
Yes
Bubble Wand
Tube
No
No
Charcoal
Flat
No
No
Digital
Flat
Yes
Double Flat
Flat
No
No
Drafting
Flat
No
Dry Brush
Flat
No
No
Duct Tape (Geometry)
Flat
No
No
Fairy
Flat
Yes
Feather
Flat
Yes
Fire2
Flat
Yes
Yes
Flat Geometry
Flat
No
No
Gouache
Flat
No
No
Guts
Tube
No
No
Diffuse
No
No
Ink (Geometry)
Flat
No
No
Keijiro Tube
Tube
Yes
No
Lacewing
Flat
No
Leaky Pen
Flat
No
Wire (Lit)
Tube
No
No
Lofted (Hue Shift)
Tube
Yes
Marbled Rainbow
Flat
Yes
Marker (Geometry)
Flat
Yes
No
Muscle
Tube
No
No
Mylar Tube
Tube
No
Oil Paint (Geometry)
Flat
No
No
Paper (Geometry)
Flat
No
No
Race
Flat
Yes
Yes
Rain
Tube
No
Rising Bubbles
Particle
Yes
No
Single Sided
Flat
No
No
Smooth Hull
Hull
No
No
Space
Flat
Yes
Sparks
Tube
No
Square Flat
No
No
TaperedHueShift
Flat
Yes
TaperedMarkerGeo
Flat
Yes
No
Tapered Wire
Tube
No
No
Leaves2
Spray
No
No
Geom/Thick (Duct Tape)
No
No
Tube (Highlighter)
Tube
Yes
No
Tube (Flat)
Tube
No
No
Tube (Marker)
Tube
Yes
No
Watercolor Paper
Flat
No
No
Watercolor Paper (Geometry)
Flat
No
No
Wet Paint (Geometry)
Flat
No
No
Wind
Flat
Yes
No
Post your work on social media and make sure to name check us to spread awareness.
Join the Discord or other Open Brush related groups. Give feedback to help us prioritize. support other users who need help.
Tell people about Open Brush in places where digital artists already hang-out and let them know what we're up to.
Create tutorials or guides. Show people the techniques you've developed or tricks you've discovered.
Help us improve and document workflows to other content creation apps. Share your experiences and pain points.
Try out the beta version or one of the experimental builds and share bugs you find or any other feedback.
Download the repo and read the developer notes and start tinkering.
Create your own fork, add a feature, fix a bug and send us a pull request.
Help improve to developer docs or create a developer tutorial
Check out the API and make something cool with it
Create a wrapper library or other integration to automate or add features via the API
Tell people about our API or suggest new use-cases or features
Create tutorials or live stream yourself using the API to do stuff nobody else is doing.
Suggest improvements to the app itself or help us plan new features.
Help out on the main website or the docs
If you know a little scripting then prototype something using the API. Or partner with a dev to make an innovative add-on tool.
Open Brush is fully open source. That makes us unique among creative VR apps - you can change how Open Brush works and tailor it to fit specific niche purposes.
Open Brush is also a brilliant place for students to learn what it's like to contribute to a real-world open source project. Any of the roles mentioned elsewhere on this page could be valuable experience for students across a range of disciplines
Use Open Brush as part of your teaching or research and then share/publish your findings.
Come and talk to us. Either email or via the Discord. Let us know your ideas about using Open Brush in new ways.
We suck at marketing. We need help telling the world how great we are. Write about us or help us write about us!
Can you believe there's people who don't know we're completely open source and volunteer-run?
And they don't know about all the cool stuff we've been doing. Help us get the word out.
Enough funding for a couple of full-time staff would make a vast difference. That's small change to you, right? :-)
This page is outdated. There is no longer a separate build for this mode. The current release combines "normal" and "experimental" builds into one. You can simply flip a toggle in the settings and restart the app. See the docs on Experimental Mode
However - there are still plenty of interesting Experimental Builds to try!
Oculus PC VR(Rift, Quest via Link cable...)
SteamVR and other PC VR(Vive, Index, Reverb...)
Other Builds (Pico, Pimax etc)
Tilt Brush was previously tightly integrated with Google Poly - a website for publishing, sharing and browsing 3D models and Tilt Brush Sketches. This was both an easy way to allow others to view your work and a resource to find 3d elements that you can use to build your scene. It made it easy to produce sketches that combined elements drawn in with brushes in Tilt Brush with low-poly models created in Blocks.
We've created the Icosa Gallery - a replacement for the Google Poly website and restored all the publically shared artwork that was saved from the shutdown of Poly by volunteers from Archive Team and other groups. We've also restored and even improved upon the integration with Open Brush and Blocks and have integration planned with Blender, Godot and other 3d apps and platforms.
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest: https://uploadvr.com/sideloading-quest-how-to/
TODO
TODO
Come over to the Open Brush Discord: https://discord.com/invite/fS69VdFXpk and chat to @seethrough ).
We're mostly on UK time but we check in fairly regularly.
These were the last release notes that were put out by Google and contain some useful information not found elsewhere.
Added Google Drive Backup (in Beta for now!).
Requires signing-in with a Google account.
Enable Google Drive Backup on Accounts popup or Sketchbook.
Can optionally configure Google Drive Backup to backup Sketches, Snapshots, Media Library, Exports, and Videos.
Backup is disabled if Google Drive has less than 0.5 Gb of storage free.
Added upload to Sketchfab.
Requires a Sketchfab account.
Added Camera Path.
Open Camera Paths Panel from More Panel.
Allows defining a spline to record a video. Spline is defined by various points.
Anchor Points define spline position. Use tangent controls to modify curves.
Direction Points define camera facing at that point on the path. While manipulating, use trigger to preview camera.
Speed Points define camera speed at that point on the path. Use cone control to adjust speed value.
Zoom Points define camera zoom at that point on the path. Use frustum control to adjust zoom value. While manipulating, use trigger to preview camera.
Added support for .glb / .gltf files in the Media Library.
Added Ellipsoid guide.
Changed max snapshot dimensions from 8192 to 16000. Note that very large snapshots may crash your computer.
Changed Profile popup to Accounts popup, to support multiple accounts.
Modified Upload popup to support multiple accounts.
Info cards (like, “Sketch loaded!”) don’t fall away immediately, allowing you a little more time to read them. Tap them to dismiss.
Removed h265 support.
Tilt Brush regularly saves your work into your Documents/Tilt Brush/Sketches/Autosave folder. Each sketch you make has a separate autosave file, and Tilt Brush keeps autosaves from your last five sketches. If you need to access an autosave, move it into your Documents/Tilt Brush/Sketches folder using Windows Explorer—it will have a Tilt Brush logo as its thumbnail in the Sketchbook.
Outdated See Open Brush Config File
Tilt Brush sketches can be exported by clicking the ‘Export’ button found on the Labs panel. The Labs panel can be found under ‘More…’ on the Tools panel.
Each sketch exported from Tilt Brush creates a separate folder in Documents/Tilt Brush/Exports which contains the geometry in the following formats:
.glb (binary glTF version 2)
.fbx (Desktop only)
.usd (Desktop only)
.json (Desktop only)
The .json is a “raw” format which you can use if you need a different file format. See the Tilt Brush Toolkit for sample Python 2.7 scripts that convert the raw .json to .obj.
python convert_to_fbx.py "c:\Users\username\Documents\Tilt Brush\Exports\Untitled_1.json"
Each script has a set of command-line options that fine-tune the generated file.
The USD contains both geometry and curve information. If your DCC tool doesn’t support USD, the Tilt Brush Toolkit contains a Python 2.7 script that can convert the .tilt file to a Collada .dae containing the curves.
After importing the FBX file into Maya you will need to turn off the Alpha is Luminance attribute in the Color Balance section for each texture node. To see the brush colors in the viewport turn on the Display Colors attribute and set Material Blend to Multiply in the Mesh Component Display section on each mesh shape node.
To render with the vertex colors you can use the mentalrayVertexColors shader node to access the stroke color in your material.
To post to Sketchfab you will need to upload the FBX file and the textures.
We are working with Sketchfab to have Tilt Brush import correctly, but if the strokes look wrong you can try opening the 3D Settings Editor in Sketchfab and under the Materials tab set the material properties manually.
We recommend using the Tilt Brush Toolkit and the .glb format. Tilt Brush Toolkit also understands the .fbx format.
To export sketches from the command line, use the --export option to specify a file or set of files to export. --export supports wildcards, and multiple files can be specified with a single --export flag. Filenames without a path are assumed to be found in the Tilt Brush Sketches directory.
You can override the destination folder of exports using the --exportPath flag.
We suggest you also specify the -batchmode option if you don’t want the Tilt Brush window to appear.
When you create a video from inside Tilt Brush using the Camera tool, Tilt Brush will create a Windows batch file alongside the video (In Documents\Tilt Brush\Videos) that you can run to re-render the video at a higher resolution. For example:
Untitled_13_00.mp4
Untitled_13_00.HQ_Render.bat
Double-clicking the ".bat" batch file will give you several options for re-rendering your video:
Press the number corresponding to the format you prefer. It will then launch Tilt Brush, which will reload your sketch and render the video. Once it is done, Tilt Brush will exit. As rendering at higher quality tends to affect the framerate, it is suggested that you do not wear your headset until this process completes.
“No Quick Load” option (#6) will forego quick loading of the sketch and will force it to load at normal speed. It is recommended that the time spent recording should exceed the normal loading time of the sketch or else the video may end before the sketch completes loading.
Rendering offline videos is achieved by saving off the path the camera took when the video was taken, and then re-using that to recreate the video. The camera path is saved off in ASCII USD (Universal Scene Description) format, so if you have an application that can read and write USD, you may be able to use it to edit camera paths. Camera paths can also be combined with USD exports from Tilt Brush, to exactly recreate how the camera moved through the scene.
If you want to render a camera path from the command line directly, rather than using the batch file detailed above, you can use the following:
When you render an ODS video, you may find things like the floor is missing, or parts of your objects get clipped off.
The reason this happens is that it’s often easier to scale down your sketch to make it easy to move the camera when you take your original video, but when you render out an ODS file, the objects are too close to the camera.
To fix this, you can change a value in the .usda file. Open it up in your favorite text editor and look at around line 30 for:
If you reduce this value, the render will feel bigger, and the camera is less likely to clip with parts of your sketch. A good value to try out is:
Then you can just try re-rendering with the batch file.
Videos can be rendered ‘offline’ faster and at a much higher resolution and framerate than using the internal Multicam tool
Editing Tilt Brush cfg file
Go to C:\Documents\Tilt Brush\Tilt Brush cfg
Under "Video" add the flag "SaveCameraPath": true,
Save Tilt Brush cfg
Camera Setup
Load the sketch you would like to render
Find a good spot from which you would like to capture your 360 video
Be sure to look around in all directions to make sure no objects are too close to the point of capture
Save your sketch
Record your video by moving camera or keeping camera stationary
After saving, exit Tilt Brush
Rendering ****Note: When you create a video from inside Tilt Brush using the Camera tool with configuration "SaveCameraPath" flag set to true, Tilt Brush will create a Windows batch file alongside the video (In Documents\Tilt Brush\Videos) that you can run to re-render the video at a higher resolution
Go to C:\Documents\Tilt Brush\Videos . There should be .usda, .bat and video file which corresponds to the .tilt file
Double click on .bat file
Once the render is complete, it will pop open the “VRVideos” folder which should contain an video file with your stereo render.
Uploading to Youtube
Upload the new “injected” video file to YouTube
Note that it takes YouTube some additional time to process 360 videos, until this process is finished, you may see the raw over/under and the “View in Cardboard” option will not be available.
Once processing is done, you should see this icon when viewing the video on your phone, indicating that it’s ready to be viewed in VR:
Use these with geometry you export from Tilt Brush and import into Unity. However, you should prefer to use the Tilt Brush Toolkit, which comes with Tilt Brush shaders.
The .tilt file format can also be parsed by the Tilt Brush Toolkit.
A .tilt is a zip-format file with a prepended header:
Inside the zip, the strokes are stored in a custom binary format in a file, "data.sketch":
The orientation is that of the controller. Curve and surface frames must be reconstructed.
Stroke extensions:
0
uint32 bitfield. Bit 0: IsGroupContinue
Control point extensions:
1
uint32 timestamp, in milliseconds
Also inside the zip is "metadata.json", the metadata for the sketch in json format. Here are some of the fields that can be found there:
"Authors": an array of author names.
"SceneTransformInRoomSpace": the transform of the scene relative to the room.
"ThumbnailCameraTransformInRoomSpace": the transform used to generate the sketch as an array of:
translation (array of 3 floats)
rotation quaternion (array of 4 floats)
scale (single float)
"ModelIndex": an array of models imported into the sketch. Each model can have the following:
"FilePath": location of the model
"PinStates": an array to indicate whether each instance of the model should initially be pinned.
"RawTransforms": an array of transforms for each instance of the model.
Added Groups to Selection tool.
Grouping allows brush strokes and widgets to share selection state. Select part of a group and the whole group is selected with it.
Grouping status data is saved with the sketch.
When a sketch is exported, each group is written to a separate node in the exported file. This allows easier sketch manipulation in editing tools, post-export.
“Group Selection” is one of the buttons available on the new selection tray that pops out next to the selection button when the selection tool is on.
Added Reference Videos support.
New tab added to Media Library Panel for videos.
Videos are taken from the Tilt Brush\Media Library\Videos directory.
Videos, like reference images, are not stored in the .tilt file and are not uploaded to Poly.
You can link to an online video by putting its URL into a .txt file inside the videos directory.
Audio from videos is supported, but is ‘2D’ only.
Known bugs:
Reference Videos do not currently work in offline renders.
Export Improvements.
Tilt Brush exports .glb (glTF 2.0) instead of .glb1 (glTF 1.1). glTF 2.0 is supported by more tools and is slightly more efficient.
Export now works on Oculus Quest (.glb only)
Tilt Brush Toolkit supports both .glb and .glb1.
glb: Added timing information to .glb exports.
Tilt Brush Toolkit will put timing information into texcoord2.
Timestamps are a vec3.
x,y = the earliest/latest timestamp in the stroke which contains that vertex.
z = the timestamp for that vertex.
This can be disabled in the Tilt Brush config Export section with “ExportStrokeTimestamp”: false
glb, fbx: Media Library models are now included in exports.
glb, fbx: Various quality of life improvements in the exported file.
New tool tip descriptions.
Tool tips have a new cleaner and consistent look.
Deterministic Geometry Generation.
Some stroke behavior is randomized—for example, brush textures and Light Wire light colors. This behavior is now saved into the .tilt, so when you re-load a sketch you will see the same thing as when you drew it.
Quest release only.
Added Labs Panel.
Contains Reference Image Panel, Pin Tool, Export, and experimental Cameras.
Added Reference Image support.
Requires connecting your Quest to a PC and side loading images into a Tilt Brush folder. Some restrictions apply.
See the Help Center for a more detailed explanation of how to use Reference Images.
Added Export to .glb1 (binary glTF).
Updated Tilt Brush Toolkit to support .glb1 import.
Previously, Reference Images would appear in the export as as empty transform nodes. They are now included in the export.
Added Cameras.
Experimental version of Snapshot and Gif Capture cameras.
Tilt Brush files moved to “/sdcard/Tilt Brush” on Quest.
This prevents work from being lost when Tilt Brush is uninstalled.
PC release only.
Add Valve Index support.
Update to latest SteamVR plugin to support custom input bindings.
Added Logitech VR Ink Pilot Edition.
Drastically decreased the amount of memory allocated during sketch quick-loading.
Variety of performance optimizations pulled from the Oculus Quest version.
Oculus Quest release only.
Deviations from PC.
Labs Panel has been removed.
Export not supported.
Spectator Camera not supported.
Twitch Chat not supported.
YouTube Chat not supported.
Local Media Library not supported.
Tiltasaurus game not supported.
MultiCam has been removed.
Photo capture, video capture, and streaming are all supported by the Oculus Dash platform.
Select All has been disabled.
Invert Selection has been disabled.
Flip Selection has been disabled.
Autosave has been disabled. Be careful!
Added Memory Warning Mode.
Memory allocation can be viewed in the Settings Panel.
After crossing a memory threshold, the app will enter a ‘Memory Warning’ state.
Deleting a Sketch will reset allocated memory.
Sketches above a certain triangle limit will display a warning in the Showcase and Liked Sketches section of the Sketchbook.
Sketches above a certain larger triangle limit will display a more severe warning in the Liked Sketches section of the Sketchbook.
New audio for all brushes.
Each brush sound is now unique, and subtly reacts to the way you are painting.
Flip Selection.
Long press on Selection Tool icon in Advanced mode.
Allow tuning of MultiCam field of view.
Requires “Tilt Brush.cfg”, stored in: Documents/Tilt Brush
Format:
Added a button in the Settings to link to the Help Center.
Import and apply normal maps for .fbx models in Media Library.
Fix screen tearing bugs with video recording.
Added a frame counter for offline rendering.
Fix some Poly models not loading.
Visible error was, “No usable geometry found!”.
Added controller support for Windows Mixed Reality headsets on SteamVR
NEW BRUSHES! 12 brand new brushes for your enjoyment:
Wet Paint - Glossy, high shine paint
Dr Wigglez - Animated sketchy charcoal
Cel Vinyl - A flat cartoon brush with a black outline
Petal - 3d flower-like brush, also great for hair
Icing - A lit tube brush with a light texture
Spikes - 3d spikes
Lofted - 3d calligraphic brush
Comet - A new spin on a 3D animated fire brush
Hull brushes - create volumes by sweeping out the brush with a few different shading options:
Shiny
Matte
Unlit
Diamond
Beginner & Advanced modes.
New “Beginner” mode with a more limited set of tools, well suited for new users, and when giving demos.
Panel layout saved session to session in Advanced mode.
New Main Menu Panel design.
New Pin tool.
New dedicated tool for quickly pinning and unpinning models, guides and images.
Located on the Labs Panel.
Select All and Invert Selection.
Long press on Select Tool icon in Advanced mode.
Recall Mirror.
Long press on Mirror Tool icon in Advanced mode.
Useful for retrieving the mirror when it is out of arm's reach.
Rapid Undo / Redo.
Press & hold the Undo or Redo button on the controller to repeat the action repeatedly.
New UI audio.
Stroke Simplification Slider.
Allows vertex reduction on sketches. Useful for low performance PCs and simplifying geometry before export.
Located on the Settings Panel.
Pixar's Universal Scene Description (USD) is now exported when pressing ‘Export’ on the Labs Panel.
This new export includes geometry, models, brush curves, and stroke timing.
Support for changing eye scale when rendering ODS 360 videos.
You can now create a camera path with everything scaled down, and then scale the camera back up when doing an offline render.
General performance improvements.
Sped up rendering of UI.
Sped up rendering of several brushes.
Support for importing any object uploaded to Poly (w/ CC-BY license)
The “Poly” panel is located inside Tilt Brush: "Tools" panel -> “More Tools...” -> “Poly”.
Any CC-BY Blocks model or .obj you like on Poly will appear on that panel (assuming you’re signed-in with the same account).
You can remix Blocks models and uploaded .objs in your Tilt Brush sketches, and share remixed sketches back to Poly!
Note: you cannot import published Tilt Brush sketches into Tilt Brush sketches at this time.
New intro flow and updated Sketchbook panel
Starting with the second time users open Tilt Brush, we now show a more illustrative “intro” screen.
The controllers also default to having the Sketchbook open, highlighting sketches featured from Poly.
Selection improvements
Stamp mode: when gripping a selection with your painting controller, you can now stamp duplicates of your selection in your scene
New contextual tooltips for actions and features
We’ve added contextual tooltips to instruct users how to use certain features.
Specifically: grip to grab, toss to dismiss, selection, and sharing sketches to Poly.
Video Recording
360 videos now render 5x as fast.
Added the option to use “h.264” encoder, see user config for details.
Videos can now be rendered ‘offline’ at a higher resolution and framerate than feasible from inside Tilt Brush. See Rendering ‘Offline’ Videos.
Blocks Library:
Accessible on the “Tools” panel, the Blocks Library allows you to add remixable featured and liked Blocks objects to your Tilt Brush sketches.
Tilt Brush sketches using Blocks objects can now be published to vr.google.com/sketches.
*Only* remixable Blocks objects will appear in the Blocks Library.
Selection Tool:
With the new “Selection Tool”, you can select and duplicate strokes and models in your scene.
“Selection” is found next to the “Eraser” button on the Tools panel.
Select strokes using the trigger. You can also flip into deselect mode by tapping the thumbpad (Vive) or “A/X” button (Rift).
If you want to move your selection, grab it as you would any other model in your scene. To delete a selected group of strokes, just throw it away.
Duplicate selections by holding the thumbpad (Vive) or “A/X” button (Rift) while intersecting your controller with selected strokes.
Quick Tool:
Holding the “menu” button (Vive) or “Y/B” (Rift) on the controller now triggers a “Quick Tool” menu, letting you quickly swap tools without reaching back to the palette.
Palette icon reorganization:
Reshuffled icons on the palette, based on common usage patterns
Moved the user profile button to the Menu Panel
Introduced a new “More…” menu where we’re moving more advanced tools and features.
We did not remove any Tools - if you’re looking for something and can’t find it, it is probably either in a “More…” menu or under “Labs.”
Relaxed limit on model scale:
Imported models can be scaled to much smaller and larger sizes.
At certain large scales you may find performance hitches -- your fate is in your hands.
Fixed duplicate upload bug:
Now when you upload sketches to vr.google.com/sketches, new drafts of a sketch will overwrite the last draft (instead of creating a new one).
Doesn’t affect published sketches.
Tiltasaurus tweaks:
Now sketches are saved automatically when a new word is chosen.
Internal version that was either too good to release, or the dev team suffered from triskaidekaphobia.
Ability to “repaint” stroke colors
Allows you to change the color of any strokes in your scene
Accessible through the “Labs” panel
“Featured” sketches in Tilt Brush pull from tiltbrush.com/sketches
Share your sketches to the web for a chance to be featured in Tilt Brush!
Featured sketches are found in the “Sketchbook” panel in the app
Ability to view rights reserved sketches liked on tiltbrush.com/sketches
Added a parameter in "Tilt Brush.cfg" to control camera smoothing for video captures
UI polish
Refreshed panel form factor (rounded edges, same sizes, all elements aligned to a grid)
Refreshed the visual style of the icons
Added lights/backdrop to the undo/redo stack
Changes to lights’ color and orientation are on undo stack
Changes to skybox (unlocking, changing color and orientation) are on undo stack
Changes to fog color and density are on undo stack
Changing environments is on undo stack
Camera movement for 360 stereo video export (example)
Two sketches can now be specified when rendering with --captureOds
Save the same sketch twice: the first with your starting camera angle, and the second with the camera where you want the path to end
The camera will move on a path from the first camera location to the second in a single 360 video
See “Exporting 360 Videos” below for details
Faster video encoding
The video camera now encodes faster, which enables higher resolution videos and higher frame rates. See “Using the Tilt Brush.cfg file” below for details on how to adjust resolution and frame rate.
Integrated Google VR spatial audio
Sketches exported to FBX include transforms for Media Library assets. This means you can easily rebuild your scenes (including those Media Library assets) in another 3D package. Formal support is in place for Unity and Maya.
100% Brush Parity in the Tilt Brush Toolkit (including all particles)
Linear lighting support in The Tilt Brush Toolkit
Previously, there were issues with color disparity between Linear & Gamma lighting modes.
If you export with Version 10 or above, you should use the new Toolkit. Otherwise, your colors will look incorrect.
Sharing
Share sketches to the online gallery!
Use the Share button on the Save/Trash Panel to upload the active sketch. Requires logging in with a Google account.
Unsaved sketches shared to the online gallery are automatically saved to your Sketchbook.
Imported models, images, and guides currently do not upload to the online gallery.
Environment models, like the Snowman and Moon, currently do not upload to the online gallery.
Added ‘Likes’ tab to Sketchbook
Sketches ‘Liked’ on the online gallery show up in this tab. Browse here!
Sketches flagged as ‘Don’t Allow Remixing’ on the online gallery will not show up in the Likes section of your Sketchbook (for now).
Added Profile to Sketchbook
Log in with your Google account to Share sketches to the online gallery and to view Liked sketches from the gallery.
Logging in must be done through a web browser, which will open when clicking the Profile button or Share button.
Lighting Panel
Control the color of the ambient lighting.
Control the colors, intensities, and directions of one shadow-casting and one non shadow-casting light.
Custom lighting is saved with the sketch.
Backdrop Panel
Change the sky to a two-colored gradient.
Each of the two colors can be customized.
The orientation of the gradient can be customized.
Change the color and density of the fog.
Custom sky and fog is saved with the sketch.
Detachable and Customizable UI Panes
Grab any Panel with the grip button to adjust its position on the Pane, or to remove it from the Pane.
The Save/Trash Panel cannot be removed from the Pane.
Panels opened in the ••• Panel selection popup can be attached to a Pane.
Panel configuration can be reset by clicking the Refresh button in the ••• Panel selection popup.
Changed save flow to allow Save and Save New
An unsaved sketch must have a thumbnail captured before saving.
A previously saved sketch can be saved over with Save, or copied to a new file with Save New.
Honestly, it works like every application ever and exactly as you’d expect.
Added Disaster Recovery functionality
Active sketch is periodically backed up to C:\Users\<username>\Documents\Tilt Brush\Sketches\Autosave folder. More info.
Increased performance of particle brushes.
Greatly increased performance of Eraser and Brush Picker.
Fix material leaking bug which caused large hitches after long periods of usage.
Colors in .fbx exports are now in linear space.
Fixes to add more compatible brushes in the Unity SDK.
Color Picker type saved between sessions.
Custom Color Palette is shared across all color pickers.
Updated SteamVR plugin to v1.2.0.
Oculus Rift support on Oculus Home
Oculus Rift support on SteamVR
Added customizable Color Palette to Color Picker.
Color Palette is saved with sketch.
Fixed bug allowing false positives when Eraser was at the origin.
Revised loading overlay to be consistent across multiple platforms.
Added 'ShowControllers' flag to config for toggling controller visibility. Intended use for performances, galleries, and mixed reality.
Disabled saving videos under a second in length, as they were confusing YouTube upload.
Sharing directly from Tilt Brush to YouTube
When you record a video, you now have the option to upload to YouTube.
Hold down the thumbpad after a video has finished recording to go into Preview mode.
If you like the video you’ve captured, hold down the checkmark to upload.
YouTube sharing requires that you sign-into your YouTube account in your default desktop browser.
If your video includes audio you may be affected by YouTube’s copyright policies. Read about them here.
Hint: Want to record audio from your microphone? Go to the Recording tab in Windows Sound properties, select Properties for your microphone then check Listen to this device. Make sure the Video Recorder has found audio before beginning a recording!
Guides for easily constraining strokes to cubes, spheres, and other shapes.
Access through Tools -> More… -> Guides.
Use the sphere, cube, and pill guides to create perfect shapes.
Guides are moved and scaled similar to other widgets, using the Grip buttons.
Straightedge now shows the final stroke you’re painting.
Increased size range for a couple dozen brushes.
“DisableAudio” field added to the Tilt Brush.cfg.
Change to save file naming.
Fixed bug where Tilt Brush would be unplayable when the Documents folder was moved or inaccessible due to virus detection software.
Minor improvements to models.
Models can now be grabbed while inside them.
Model materials support alpha cut-out and transparency.
FBX format models are now supported.
Minor placement fixes to the Mirror tool.
Added in-app reminder instructions for skipping the intro tutorial.
Media Library Improvements
Support for importing multiple models and images.
Added ability to pin models and images, disabling movement.
While holding a model or image, pull Trigger to pin and unpin.
Models and images save with sketch.
Models and images contribute to Tilt Meter.
Model and image interactions added to the undo stack.
Images support binary alpha.
Updated visuals for highlighting objects that can be grabbed with Grip button.
Improved Snapping
While holding a snappable object, hold Trackpad to snap.
Snappable objects include: models, images, mirror, Tips ‘N Tricks, and brush strokes, when Straightedge is selected.
Removed auto-snap on Mirror and Straightedge.
Model, image, and Tips ‘N Tricks snap to cardinal orientations.
Mirror snaps to flat horizontal, as well as 15 degree increments where n=(x, 0, z).
Straightedge snaps to up, down, 45 degrees, and 0 degrees.
Models and images can snap to center of environment.
In the Pedestal environment, models and images snap to the pedestal.
Video Recorder Improvements
Video capture now records with audio.
Ability to customize video resolution, FPS, container type in the Tilt Brush.cfg. How to use the Tilt Brush config file.
Misc. improvements
"Animal Ruler" shows relative size when using the scale feature.
Mirror position saved with sketch.
Mirror position added to undo stack.
Added unsaved work warning before loading a sketch.
Added clock to Controller Console.
Animate grip and trigger buttons on controller meshes.
Added new tips to the Tips ‘N Tricks.
Updated SteamVR plugin to v1.1.1.
“Author” field added to the Tilt Brush.cfg.
When the Author field is set, all sketches created will have the author name embedded in saved .tilt files.
Support scripts have moved to the Tilt Brush Toolkit.
Rotate and Resize
Hold both grip buttons at the same time to move, turn, or resize yourself.
While resizing, click the trackpad to reset yourself to original size.
Any changes to size or rotation are saved with sketches.
Media Library
Added ability for users to import an .obj model into their sketch.
Moved reference images and models to “Media Library” panel accessed through the “More…” menu on the Tools panel.
Models are pulled from the Documents/Tilt Brush/Media Library/Models folder, images are pulled from the Documents/Tilt Brush/Media Library/Images folder.
See Tilt Brush/Media Library/MediaLibraryReadme.txt for details on how to use Media Library.
Tiltasaurus
Added new game to the Labs panel.
See the Help Center for instructions how to play.
Adding Tiltasaurus.json to the Documents/Tilt Brush folder will let you add your own list of words.
Format:
Controller Swapping
Point the controllers away from each other and tap the bottoms to swap the palette and paint brush.
High resolution snapshot mode
Added flag “HighResolutionSnapshots” to the Tilt Brush.cfg. How to use the Tilt Brush config file.
Setting the flag to true causes the Camera tool to take snapshots at 6x the default resolution (11,880 x 6,588px).
Exporting to Sketchfab
Many important material properties are now preserved when exporting .fbx files and then uploading to Sketchfab. Posting to Sketchfab.
Misc. improvements
More aggressive video camera stabilization.
Fire brush bloom effect fixed on “Future Desktop” settings.
Cleaned up the progress bar images, added info text during loading.
Added new tips to the Tips ‘N Tricks.
Changed video file extension to .mp4.
Exports binary FBX by default, configurable in Tilt Brush.cfg. How to use the Tilt Brush config file.
Pressing the pad no longer activates teleport with Teleport Tool. Trigger only.
Teleport Tool boundaries are extended when the sketch has been resized.
Changed selection icon for Sketchbook to trash can.
References to models are saved with sketches, but the file data is not embedded within the .tilt file. If a sketch is loaded without the referenced model in the Media Library, a missing model icon will be displayed.
Added ‘About’ button to Settings for viewing really exciting third party notices.
Audio reactive brushes
Added new “Audio Reactive” mode for brushes.
Toggle Audio Reactive mode on the Brushes panel.
Audio Reactive mode scans the computer’s audio out signals and connects to the first found active signal.
Audio Reactive mode will respond to any computer audio.
Added 15 new brushes and deprecated 3 (Taffy, Leaves, and Plasma)
Updated many brushes to add audio-reactive behaviour.
Cameras
Renamed from “MultiCam”.
Added Video mode to “Cameras”.
Added vignetting and depth of field effects to snapshots and videos.
Interface improvements
Streamlined the UI down to 3 panels.
Added dedicated Sketchbook panel, below Tools panel.
Added toggleable measurements to Straightedge tool.
Enable this feature on the Settings panel.
Undo/Redo can be used when a panel has focus.
Swiping on the brush controller thumbpad scrolls through the pages of the Brushes panel.
Added new “More” menu.
Changed Teleport tool icon visual from “Pin” to “Feet”.
Application button on the brush controller now toggles the last tool.
New visual design for the Color and Brush Picker tool.
Grabbable object improvements
Moveable UI panels now move out of each other’s way.
Mirror can be reset by dragging it to the target above the center of the floor.
Mirror now snaps to vertical and horizontal planes.
Added Tips ‘N Tricks tutorial section, under “More” menu.
Export button now generates textured .fbx files. See the Exporting Tilt Brush Sketches section below for more details.
Improved visual quality at all performance levels.
Unlit brushes made more efficient by using single-sided geometry.
Added progress bar when exporting or loading sketches.
Switch versioning numbers to be more open-ended.
Added 5-Second Gif mode to MultiCam.
Export button now auto-generates .fbx, along with old .json intermediate file.
Color picker works on reference images.
Revised controller pad visuals for MultiCam.
Fix help text on Twitch Chat window.
Allow controller pad click to teleport.
Added Teleport Tool.
Added ability to view YouTube Live chat while streaming. (see notes below)
Replaced IRC support with dedicated Twitch Chat support. (see notes below)
Labs Panel can be dismissed by tossing.
Improved Undo/Redo trackpad click functionality.
Reference Image widget resets position when a new image is selected.
Moved Quick-Load tip to Palette controller so user can teleport during sketch load.
Labs Panel
YouTube Chat
Requires “Tilt Brush.cfg”, stored in: Documents/Tilt Brush
Format:
Use Grip button to move chat widget.
Use both Grip buttons to scale chat widget.
Toss the widget to dismiss it.
Twitch Chat
Requires “Tilt Brush.cfg”, stored in: Documents/Tilt Brush
Format:
Use Grip button to move chat widget.
Use both Grip buttons to scale chat widget.
Toss the widget to dismiss it.
Improved guide for Spectator Camera in Circle Mode.
Added Mirror snap functionality.
Added basic Export support.
Added ability to view .jpgs and .pngs as Reference Images.
Added visual notification when an important message is on the Controller Console.
Added a button to Sketch Gallery for easy viewing Sketches on disk.
Added ability to connect to an IRC channel for assisting live streamers.
Added a ‘Labs’ button on the Settings panel for advanced and experimental features.
Skip the intro tutorial by holding down both trigger buttons.
Labs Panel
Reference Images
Used for viewing external images while inside Tilt Brush.
Loads .png and .jpg images stored in Documents/Tilt Brush/Reference Images.
Use Grip button to move image widget.
Use both Grip buttons to scale image widget.
Toss the widget to dismiss it.
Caution! Extra large images, such as 4k, may cause performance hitches in Tilt Brush.
Export
Exports current scene's metadata and 3D geometry to a json file in Documents/Tilt Brush/Exports.
Tilt Brush ships with sample Python 2.7 scripts to convert the .json to .obj and .fbx formats. These scripts are in the Support/bin folder, which is next to TiltBrush.exe. The fbx conversion also requires the Autodesk FBX Python SDK. To find TiltBrush.exe from Steam, right-click "Tilt Brush" → Properties → Local Files → Browse Local Files...
Example script usage:
python convert_to_fbx.py "c:\Users\username\Documents\Tilt Brush\Exports\Untitled_1.json"
Each script has a set of command-line options that fine-tune the generated file.
Note that this initial preview does not export textures or materials. In addition, the .obj file format does not support vertex colors. We’re looking into solutions to provide users with more of this data, but didn’t want to delay sharing what we have now. The .fbx does support vertex colors, but to see them you will need to apply a shader that uses vertex color information like the two example Unity shaders below.
Please let us know how you use this functionality!
IRC
Requires “Tilt Brush.cfg”, stored in: Documents/Tilt Brush
Format:
}
Note: How to get an OAuth key for Twitch.
Use Grip button to move chat widget.
Use both Grip buttons to scale chat widget.
Toss the widget to dismiss it.
Watermark
The Tilt Brush logo watermark can be disabled. This also requires a "Tilt Brush.cfg" file, stored in Documents/Tilt Brush. The format is
Quest and other Standalone Headset Users - exporting video directly from within Open Brush is currently only supported for PC VR only. See the section below
If you are using Open Brush on PC VR / SteamVR, there are three types of cameras available to you. If you are using a version of the software that is run directly on a stand-alone headset such as the Oculus Quest 2 or 3 headsets, then there are limitations on some video functions because standalone headsets cannot process the video without being tethered to a PC. Steam VR allows the PC’s processors to handle the heavy lifting that is required to record Video in VR. This can be done with either a wired or wireless connection between the PC and the headset.
The types of cameras available are:
The Cameras Tool is a set of camera tools options that are available in both the Beginners and Advanced Palates.
In the Beginner’s mode, the camera icon is a single function tool, opening the Cameras tool on your brush controller. The Cameras tool has these options:
1. Auto-Gif
2. 5 Second Gif
3. Snapshot
4. Video (not present in some versions of Open Brush)
The Cameras tools are all handheld and controlled with the brush controller where you will find the viewfinder and the record function. Using the thumbpad left and right shuffles through the four camera options. Clicking with the trigger initiates the process of recording in all options.
The 5 Second Gif requires you to hold down the trigger for the 5 seconds. You can release the trigger and repull it to stop and start from the same place in the 5 second timeline. The video function begins when you pull the trigger and continues until you pull it again to stop the recording.
The video function allows for a lot of control because you can move with 6 Degrees of Freedom through the scene limited only by your ability to control the direction, speed and orientation of the camera with your brush controller. This results in a handheld video, and the strengths and weaknesses of that approach are the same as real world handheld videography. It is hard to steady a camera being supported by your body.
Any videos created with any of the Cameras options will show up in the /Documents/Open Brush/Videos folder.
When switching to the Advanced Palate, the Cameras icon changes to be a multi-function button. This is visually shown by a triangle on the lower right corner of the icon.
To access the Cameras sub-menu do a click and hold.
In the sub menu you have the option to go into a Camera Options menu.
Within the Camera Options menu you can:
· Turn the Open Brush Watermark on or off,
· Adjust field of view and smoothing variables, and
· Toggle Post Effects.
The series of images below demonstrates the differences in the captures with Field of View set to 140, 70 and 10. The first image shows the capture with the Watermark turned on, in the rest it has been toggle off. Understanding how this affects the image the camera captures allows you to better control the way you capture the scene.
The video below is a demonstration of the tools mentioned above. It was recorded as a screen capture utilizing the Spectator Camera.
The Spectator Camera does not record images or videos. Instead, it is used to send an image to a monitor. To capture images or videos, a screen capture function is required to record the video that is sent to the monitor. But the Spectator Camera is the only camera that shows the whole environment, including tools and camera paths.
There are four options with the spectator Camera:
Headset: Sends the video from the view of the headset. This is a view that moves along with your head, focusing on what is directly in front of your face as you wear the headset. This is a relatively jerky method of video capture because it moves every time your head moves.
Stationary: This allows you to place a camera inside the scene and it captures either the stationary image in front of the camera, or you can use this as a handheld camera by grabbing and using the tool as you would a tangible camera.
Figure 8: This is the same camera as the stationary, but it makes a continuous figure 8 moving around a fixed point which is established by where you place the spectator camera.
Circle: Again, this is the same camera, but it revolves around the scene in a horizontal circle on a fixed path through or around the scene.
Because the Spectator Camera does not record, recording of video lies outside of the scope of this document in that it becomes a discussion of a hundred separate toolboxes. You will need screen capture software that allows system audio to be captured along with the video (if you want to include audio in the recording).
Note: You may not be able to capture audio from some sources because of DMCA rules in place that allow listening but not recording. Recording of your microphone does not have this limitation. Recording a music video in Spectator Mode can present some challenges that were intentionally put in place to protect copyright. Understanding that there are protections in place to prevent recording of some audio sources is an important part of the planning and production process. You will not be able to record audio from platforms such as Spotify. You can feed the audio into a scene and the audio responsive brushes will react, but there are digital blocks that prevent you from recording.
A strength of the spectator camera is that it is easy to establish your camera path because it is limited to the preprogrammed options (Stationary, Figure 8, and Circle). You can also use the stationary option as a handheld option and move the camera around the scene.
Another strength of the spectator camera is that it shows the environment including tools, controls, headset and controllers. It can also provide the opportunity to record the scene as it is rendered, providing a stroke-by-stroke perspective of how the scene is created.
The weakness of the Spectator Camera is that it is limited to the preprogrammed options, and because recording with the Spectator Camera Option requires screen capture software that is not part of Open Brush.
The Field of View setting in the /Cameras/Camera Options tool does not affect the Spectator Camera. Rather, when establishing the Spectator Camera shot, you can visibly see lines that illustrate the capture field for all of the spectator Camera settings except headset.
Camera Paths is an extremely important set of tools for Recording Video, or Virtual Cinematography in Open Brush. The tools are pretty basic, but learning to use them effectively and efficiently is the key to turning out high quality videos where you are in total control of how you capture the scene.
Camera Paths is a set of tools that allow you to control the way that a camera captures the scene as the camera travels along a path you create through the scene. This method gives you a great deal of control and flexibility in your approach to filming the scene. But, once you click the record button, all other functions are locked until it has completed filming the path. There is an option to stop the recording while it is in process, but you will lose the video that was in process if it does not complete the defined path.
The tools you can use to manipulate the path include:
Add New Path Tool
This is the only option when you enter the Camera Paths Tools if there are not already established camera paths. To establish a path, you need to click the Add Anchor Point tool and then create a path consisting of 2 or more points. Once you have a path, additional tools become available to you.
· Select Path: allows you to choose which of the existing paths you want to work with.
· Show Paths: Makes Paths Visible in the Sketch so they can be manipulated.
· Delete Path: Allows you to delete an entire path.
· Record Path: After you have created and edited your path, this tool will launch the video recorder that will go through the entire path making a video record. Videos will show up in the /Documents/Open Brush/Videos folder. Recording cannot be paused. Recording can be cancelled by clicking the X on the bush controller while it is in the recording process.
· New Anchor Point: Adds an additional anchor point to the path. If the anchor point is added at either end of a path, it will stay activated allowing you to add additional points to the path.
· Delete Anchor Point: Deletes any controls form the timeline. This includes anchor, direction, speed, and zoom points.
· Camera Direction Point: Controls the Direction the camera is pointed at the point in the timeline where it is placed. This type of point interacts with previous direction pointsand the path to determine the transition between camera direction points creating a flowing camera direction instead of a jumping camera direction.
· Camera Speed Point: Provides values from .1 to 100 to control the speed the camera moves down the path at a given point. This type of point interacts with previous speed points and the path to determine the transitional speed between points.
· Camera Zoom Point: Provides values from 10 to 140 to control the Field of View as the camera moves down the path at a given point. This type of point interacts with previous zoom points and the path to determine the transitional zoom between points.
The strength of the Camera Path is its flexibility. The weakness is that you are locked into the defined path once recording has started. The camera paths tool is not accessible until a sketch is fully rendered, and once the recording has started, all other tools are locked until the recording has completed. That means it cannot capture the rendering of a scene, so all videos start with a fully rendered scene.
Creating a camera path can be quite time consuming. In addition to the various tools, you need to work with the way that adding a point to the timeline can affect the elements ahead of and behind it on the path. Effective use of the Camera Paths requires the use of a lot of control points (each tool creates a control point when it is attached to a location on the camera path). The flexibility you can achieve comes at the cost of spending time learning each of the tools and how they interact with other points on the timeline.
There are several useful settings you can change in the config file.
Below is a sample Open Brush.cfg file showing the fields related to Video that can be used to control the video capture / render.
{
"User": {
"Author":"Kevin W. Tharp, LLC"
},
"Video": {
"Resolution":1920,
"OfflineResolution":1920,
"FPS":30,
"OfflineFPS":30,
"ContainerType":"mp4",
"CameraSmoothing":0.98,
"Encoder":"h.264",
"SaveCameraPath":true,
"FOV":129
},
"Flags": {
"PostEffectsOnCapture":true,
"ShowWatermark":false,
"ShowHeadset":false,
"ShowControllers":true,
"DisableAudio":false
},
One of the Key variables is the number of frames you see per second (FPS). In virtual reality itself, this is the refresh rate. The refresh rate is important to the Virtual Reality experience but does not affect the virtual cinematography because videos of the scene are rendered at a fixed FPS rate. The number of frames per second affects the memory as each frame is processed in the memory. Using a lower FPS for recording impacts the memory by requiring less memory.
When you are recording live, this can be a significant impact because the system renders the scene twice, once for each eye, so that you can see it in VR. Then you add the recording on top of that and you are really taxing the memory available for your display/recording function. If you run out of memory, the VR experience gets glitchy or fails completely. A glitchy VR experience is a bad thing, because it can lead rapidly to VR sickness and poor quality or failed recording.
To minimize this impact, offline rendering allows your system to redirect some of those memory resources to the function of recording the video. It does this by running a batch process. While the batch process requires the sketch to load in the headset, it disables all the interaction and dedicates all the memory to rendering and recording the scene. As such, it is recommended that you not wear the headset while batch rendering is going on, as the display may be glitchy or inconsistent as it is not prioritized during the offline recording process.
When you create a video from inside Open Brush using the Camera tool and you've set "SaveCameraPath" to True in the Open Brush config file - Open Brush will create a Windows batch file alongside the video (In Documents\Open Brush\Videos) that you can run to re-render the video at a higher resolution. For example:
Untitled_13_00.mp4
Untitled_13_00.HQ_Render.bat
Double-clicking the ".bat" batch file will give you several options for re-rendering your video:
Press the number corresponding to the format you prefer. It will then launch Open Brush, which will reload your sketch and render the video. Once it is done, Open Brush will exit. As rendering at higher quality tends to affect the framerate, it is suggested that you do not wear your headset until this process completes.
“No Quick Load” option (#6) will forego quick loading of the sketch and will force it to load at normal speed. It is recommended that the time spent recording should exceed the normal loading time of the sketch or else the video may end before the sketch completes loading.
Note: Video Camera Paths is not the same thing as the Camera Paths Tools. Video Camera Paths track a camera through a scene and save the spatial data for offline rendering, whereas the Camera Paths Tools create a path that a video will take through a scene while recording.
Rendering offline videos is achieved by saving off the path the camera took when the video was taken, and then re-using that to recreate the video. The camera path is saved off in ASCII USD (Universal Scene Description) format, so if you have an application that can read and write USD, you may be able to use it to edit camera paths. Camera paths can also be combined with USD exports from Open Brush, to exactly recreate how the camera moved through the scene.
If you want to render a camera path from the command line directly, rather than using the batch file detailed above, you can use the following:
When you render an ODS video, you may find things like the floor is missing, or parts of your objects get clipped off.
The reason this happens is that it’s often easier to scale down your sketch to make it easy to move the camera when you take your original video, but when you render out an ODS file, the objects are too close to the camera.
To fix this, you can change a value in the .usda file. Open it up in your favorite text editor and look at around line 30 for:
If you reduce this value, the render will feel bigger, and the camera is less likely to clip with parts of your sketch. A good value to try out is:
Then you can just try re-rendering with the batch file.
If you're rendering stereoscopic video then reducing eyeScale will reduce the strength of the stereo effect as well. It's often better to scale your scene in this case.
Videos can be rendered ‘offline’ faster and at a much higher resolution and framerate than using the internal Multicam tool
Editing Open Brush cfg file
Go to C:\Documents\Open Brush\Open Brush.cfg
Under "Video" add the flag "SaveCameraPath": true,
Save Open Brush.cfg
Camera Setup
Load the sketch you would like to render
Find a good spot from which you would like to capture your 360 video
Be sure to look around in all directions to make sure no objects are too close to the point of capture
Save your sketch
Record your video by moving camera or keeping camera stationary
After saving, exit Open Brush
Rendering ****Note: When you create a video from inside Open Brush using the Camera tool with configuration "SaveCameraPath" flag set to true, Tilt Brush will create a Windows batch file alongside the video (In Documents\Open Brush\Videos) that you can run to re-render the video at a higher resolution
Go to C:\Documents\Open Brush\Videos . There should be .usda, .bat and video file which corresponds to the .tilt file
Double click on .bat file
Once the render is complete, it will pop open the “VRVideos” folder which should contain an video file with your stereo render.
Uploading to Youtube
Upload the new “injected” video file to YouTube
Note that it takes YouTube some additional time to process 360 videos, until this process is finished, you may see the raw over/under and the “View in Cardboard” option will not be available.
Once processing is done, you should see an icon when viewing the video on your phone, indicating that it’s ready to be viewed in VR.
Currently Open Brush doesn't support recording video directly on the headset. There are two main ways to work around this limitation.
Standalone headsets like the Quest have the same Camera Path Tool as PC VR - the difference is that the record button is currently disabled. However any paths you create are saved with your sketch and can be copied to a PC or Mac and rendered there. The PC doesn't need to be a VR-capable PC - you can run Open Brush in a mode that doesn't require a VR headset.
There is an example script you can use to help you generate the video.
Launch Open Brush at least once to ensure the correct folders are created in your Documents folder.
Copy the sketch from your headset to the Open Brush/Sketches folder on your PC or Mac
If your sketch contains any images, videos or 3d models that appear in your video then copy those from the Quest's Media Library folder to the equivalent location on your PC or Mac.
Ensure you have got Open Brush running on the PC or Mac. Switch to your web browser and enter this address: http://localhost:40074/help/
Click on the Example Scripts link and then click on /examplescripts/record_camera_path.html
Click browse and select the sketch you copied from the Quest earlier
Click "Go"
This will generate the video as if you'd recorded the path inside the headset
This allows you to record what you can see and record by moving through the scene. The quality will be lower than the above method and you may need to ensure that UI elements are hidden (The Spectator script can help with this)
One of the biggest bottlenecks that stops us releasing more features more quickly is the lack of people prepared to test features that are either already in the beta version or are ready for merging into the beta version ("pull requests").
The beta version is usually fairly solid but testing is invaluable - especially if you use Open Brush in depth (our testing is often from the perspective of a casual user) or you use a headset other than a Quest 2 (currently we do the bulk of our testing using Quest 2 via Link or standalone. Testing intesively on a wide range of headsets is a major chore). The best way to help test is to switch to using it instead of the normal version of Open Brush and to report any issues you find by posting to our Support Forum on Discord (or if you need to chat before you're confident enough to report a bug, just post in the General channel)
To help you focus on testing the right things you can see a list of changes and new features in the beta version here.
"Pull Requests" are simply requests to pull in a new feature or bug fix to the main codebase. Once a pull request is approved it's automatically released as part of the current beta version.
Testing new features is a bottleneck for us at the moment We need feedback on the feature itself and help finding bugs that are serious enough for us to fix before merging in to the beta release.
In return you'll get to try out the real cutting edge features first and potentially influence the design choices we make.
On Github there is a list of open pull requests. You can click on any one and then scroll down to the bottom:
Click on any of the blue "details" links and then click "Summary" on the left followed by the number underneath "Artifacts" on the right:
You'll then be taken to the bottom of the page where there is a list of all the builds:
Just click on the name that matches your headset and it will begin to download a zip file.
(You might need to sign-up/sign-in to Github first)
Experimental builds are the real bleeding edge. Some of the features might never make it into the official release. They can vary from "nearly ready" all the way to "barely working".
However - early on in the development of a new feature is when feedback is most likely to be useful and most likely to alter the direction a feature takes. These are the builds you want to be testing if you want to have a say in Open Brush development.
New features are usually developed on a separate branch of the project until they are ready to be merged into the current beta release. In most cases you can download builds of these branches and try them out yourself.
In the sidebar to the left we list the major alternative versions that are currently available, explain their features and what state they are currently in.
Some features are might spend months or years as separate builds. The person who started them might have got too busy to continue the work or they might just not be suitable in their current state. In most cases we will attempt to keep them up to date with the main release so they will have all the current beta release features as well as the extra things they bring to the table.
List of changes in the current beta version
Whenever any new change is added to Open Brush, before it's released to the various stores and sites, there is an engineering "pre-release" version available. If you'd like to help beta test new versions, you can get these builds as soon as the new code is added (generally within 20 minutes!). Windows (SteamVR) and Quest/Quest 2 versions are built automatically which you can get from the Github releases page. Versions of the form "vX.Y.0" are official releases, whereas versions that do not end in .0 are made available for testing purposes only, with no guarantees as to their quality.
These builds share a save location with the official Open Brush release, but can be installed alongside the formal version. The Oculus build, like all sideloaded content, will be listed in "Unknown Sources", and will have the word "Github" appended to the name (with a different package name as well) to differentiate it from the official release).
Whilst Open Brush was still Tilt Brush, the original team had a bunch of features and brushes they felt weren't quite ready to be released in the official app. As soon as Tilt Brush was made open source, everyone immediately leapt on these features with great excitement.
Generally - when someone is working on a new feature, they create a new build to work on until the features is ready to merge back into the main release.
You can download these builds to try out new features. Sometimes the sketches you create with these builds won't open correctly in the main release (but not always) and like all pre-release versions these builds might contain bugs or incomplete features.
Multibrush is mostly an experimental mode build with two extra features:
1. Post-processing effects that change the appearance of your entire scene. 2. Multiuser support: multiple people can paint at the same time and use voice chat in realtime.
Multibrush does not currently include most of the features that we have added to Open Brush since release.
Tilt Brush. Running in a browser!
A VR-embedded tutorial system that supplements video tutorials with 3D and contextual aids directly in the user's VR environment.
There's more features that are being worked on that listed above. We've omitted them because they are either too incomplete for users to try out or they have put on hold for some reason (usually that we're too busy to finish them at the moment!)
Here's the complete list that contains many items above plus a few more!
(If you can help out with any of these - please get in touch!)
Developed by Benji Costin with support from The Icosa Foundation and Open Brush community
Oculus PC VR(Rift, Quest via Link cable...)
SteamVR and other PC VR(Vive, Index, Reverb...)
Other Builds (Pico, Pimax etc)
Both hand-drawn ("flipbook style") animation and tweening. Inspired by the classic Flash timeline - add motion to your Open Brush sketches.
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest: https://uploadvr.com/sideloading-quest-how-to/
TODO
TODO
Come over to the Open Brush Discord: https://discord.com/invite/fS69VdFXpk and chat to @seethrough ).
We're mostly on UK time but we check in fairly regularly.
This build is the pre-release version of Open Brush and may contain untested new features.
Remember, these pre-release builds are labelled beta for a reason, and some features may contain bugs. Make sure to back up your important sketches before proceeding!
Right Click on Open Brush in your Steam Library and choose "Properties"
2. Choose "Betas" on the left, and in the dropdown, select whether you want to opt into the beta or experimental mode version. You can also return to the normal release version by choosing "None"
Wait for Open Brush to update.
Find Open Brush in your Library, click the 3 dots menu and choose "Settings"
Click "Release Channels"
Choose "Beta"
Wait for Open Brush to appear in your list of updates and choose "Update"
Or find Open Brush in the mobile app:
Choose "Beta". (Or you can switch back to "LIVE" if you want to go back to the normal release version. Note: If LIVE has a lower release number than Beta, you'll need to uninstall Open Brush first before downloading the LIVE version again.)
Wait for Open Brush to update.
We also host some beta versions on our Itch.io page.
If you can't find a version to suit your platform anywhere else then this page on Github has the latest beta build for all the platforms we support.
Oculus PC VR (Rift, Quest via Link cable...)
SteamVR and other PC VR (Vive, Index, Reverb...)
Other Builds (Pico, Pimax etc)
The core feature is support for low-poly 3d models that can be modified directly inside Open Brush. Currently the focus is on procedural shapes based on symmetry and repeating patterns.
Creating symmetrical patterns, geometric forms and complex 3d shapes.
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest: https://uploadvr.com/sideloading-quest-how-to/
(Make sure you've switch off beginner mode) Find the "Experimental Tools" panel which is usually attached to your wand.
There will be a new icon at the bottom that looks like a wireframe cube. Click that to activate the 3D shape tool.
A tray will appear on the right of the panel with some new buttons. You can pick from a range of shapes by clicking the top button "Shape Gallery".
Draw your chosen shape using the trigger on your drawing hand. Click once to start and release when you're happy with the size.
WARNING! There are currently no limits in place preventing you creating very complex shapes. It's quite easy to make everything super slow and potentially even cause Open Brush to crash.
There are four buttons on the tray that appears when the Polyhedra tool is active:
This opens a popup with a selection of built-in shapes to get you started.
Clicking this button cycles through the options for what kind of object you create when you click and drag the trigger on your drawing hand:
Create a 3D Shape: This will create a 3D shape in the scene based on your current choice of shape. A 3D shape is similar to an imported 3D model except it is generated on the fly based on settings that you choose.
Create brush strokes based on shape faces: Instead of creating a 3D shape this uses your current chosen shape as a template to draw brush strokes around the edges of each face.
Create brush strokes based on shape edges: This is similar to the above except it creates shorter brush strokes (but more of them). One for each edge in the shape. Experiment with these two different modes. Some will work better for one combination of brush and shape than the other.
Create a new custom guide: This creates a new guide based on your current chosen shape. It has the limitation that only convex shapes are allowed so if you have a concave shape the the "convex hull" of it will be used to make the guide.
Create a custom mirror: This creates a custom mirror that works in a similar way to the normal mirror tool. However instead of two copies of your brush strokes, the custom mirror can create multiple strokes - one for every face of your chosen shape.
Clicking this button cycles through the options for what the secondary button on your drawing hand does (the "A" button on the Oculus controller or trackpad click on the Vive controller). In all cases you hold down the secondary button whilst moving your controller over existing editable models in your scene:
Apply settings: picks up the Shape Designer settings from the model and loads those settings into the Shape Designer panel.
Grab settings: Applies the current Shape Designer Settings to the model.
Apply color: Changes all faces on the model to the current selected brush color.
Draw brush strokes on faces: Create brush strokes on the model. One brush stroke for every face.
Draw brush strokes on edges: Create brush strokes on the model. One brush stroke for every edge.
This opens a new panel that gives you access to the powerful underlying procedural generation engine. See the section below for detailed information on the Shape Designer
There's nothing to stop you creating extremely complex shapes that can slow everything down and even cause Open Brush to crash.
Exported scenes work best in the gltf/glb format. Face colours will appear correctly. Currently the various materials don't export. Other formats don't support exporting face colours. (FBX actually does but you'll need to edit the material in your 3d app and set it to use "Vertex colours")
Duplicating models using the selection tool sometimes produces changes in scale.
You can't scale the custom mirror. Instead scale your scene.
Custom mirror stroke colours are sometimes unpredictable.
(docs coming soon)
The symmetry mode only affects normal paint strokes. You can't currently use symmetry to create multiple copies of the polyhedra tool.
You can grab the symmetry widget and change it's position and orientation.
(docs coming soon)
Come over to the Open Brush Discord: https://discord.com/invite/fS69VdFXpk and chat to me ( andybak#5425 ).
I'm on UK time but I check in fairly regularly.
(docs coming soon)
Open Brush (or at least currently the experimental build that supports plugins) ships with a selection of plugins that are both useful in their own right, great examples of what is possible and hopefully good starting points for people that want to write their own plugins.
This page will list the included plugins along with a brief explanation of what each one does. It is aimed mainly at users. If you're interested in understanding how each plugin was written, then the source code is hopefully clearly written and contains enough comments to make it easy to follow.
Try different brushes. Plugins can have wildly different results for some brush types. Try the hull brushes in particular with some of the Tool Plugins. Also try various animated brushes such as Neon Pulse or Keijiro Brush
You can have more than one plugin type active at once and the combinations can be wild. Try combining a Symmetry Plugin with a Pointer Plugin. Or use a Background Plugin that animates a layer whilst drawing on it with an animated Pointer Plugin. Or maybe all three at once!
Try spinning the Symmetry Widget with a flick of your hand while drawing. A slow spin gives very different results to a fast spin.
Many of the Symmetry Plugins have additional parameters for color shift. These allow you to create anything from a wild rainbow of different colored strokes, down to subtle shifts of your base color that gives a more natural effect.
Don't forget to try different parameter values. The same plugin can look massively different based on the settings you choose.
Use the Copy button to copy the script to your Open Brush folder and then open it up in a text editor (ideally something like VS Code). Try changing some of the values or modifying a line of lua code here or there.
Social painting. Create with others.
Collaborate on a sketch or invite people to watch you create.
There's a new button on the main admin panel. You enter a room name of your choice (or accept the random one provided). Share that room name with anyone you want to join.
Undo is disabled when in multiplayer mode.
Loading sketches is disabled in multiplayer mode
People that join the room will see the strokes you have made this session but they won't see any strokes that you loaded from saved sketch.
Our next priority is to fix the last issue. After that we will probably release the multiplayer functionality into the main beta release so it's easier for people to try it out. However - the more testing and feedback we can get at this stage, the better the beta release will be so please try out this build.
TODO
Changing the way Open Brush responds to user actions. Adding new mirror modes or creating a new custom brush tool.
Some API commands are untested. Please report bugs on the plugins and scripting channel on Discord. There's lots more I want to do with this including scripted 3d object creation, better UI for parameters (different input widgets etc).
It's an attempt to provide a runtime UI for Tim Aidley's "User Brushes" feature:
See:
Currently it:
Allows you to create a new user brush by duplicating an built-in brush
It exposes shader parameters as sliders and shows a preview stroke changing in realtime as you adjust the sliders
Making your own crazy brushes!
There's a new button on the Experimental Features panel that opens the Brush Editing panel. Select a brush and then click the button to create an editable duplicate. (at the moment you have to scroll to the end of the Brushes panel to select the new brush but this should happen automatically)
Lots. It's an early proof of concept
I made a quick video showing an early stage example:
For Pointer, Symmetry and Tool plugins, you can only have one of each type active at any one time. The large button on the left of each row activates and deactivates that plugin type.
The left and right arrow buttons cycle through each installed plugin.
The cog button opens up a panel with controls specific to the currently active plugin. These usually have sliders to change various parameters.
The final button will copy the currently selected plugin into your Plugins folder. You can then view the code, modify it or use it as a starting point for writing your own plugin.
Background Plugins have an extra button and work slightly differently in terms of activating and deactivating. The reason for this is that you can have multiple Background Plugins active at once. The large button on the left will enable or disable all currently active Background Plugins. To turn individual plugins on or off you can click the button with the eye icon when that plugin has been selected with the arrow buttons.
Plugins can define various parameters so you can easily change how they work without needing to edit the script. Each slider will show a tooltip when you hover over it.
Drag the slider to change it's value. If you need more precision you can:
While hovering you can
Move the thumbstick on your brush controller left and right to change the value
Click the small arrows at either end to apply a set increment to the value
When you've finished you can click the tick button at the bottom or simply move your hand away from the panel to close it.
Place plugins inside your Open Brush/Plugins folder. Some plugins might use extra libraries. These should be placed in Plugins/LuaModules
The previous stroke you drew is used as a template and multiple copies of the pointer are spread along it as you draw
Point Spacing: The distance to space out the copies along the stroke
Like spinning the mirror by hand but with precise control
Speed: How fast to spin
Angle X: The axis tilt in the X direction
Angle Y: The axis tilt in the Y direction
A flock of pointers follows your hand using simple rules to control how they fly
Number of copies: How many boids in the flock
Separation Amount: How strongly each boid tries to stay away from others
Alignment Amount: How closely the boids try and follow the flocks path
Pointer Attraction: How strongly each boid is attracted to your brush position
The pointers follow your brush position but each one moves towards a point where your hand was further back in time
Copies: The number of strokes to draw at once
Delay per copy: How far back in time (in frames) for each copy
Amount: How far between the current and past position to move towards. 0.5 is the midpoint between past and current
Copies of your stroke forming an ellipse - with optional color shifts
Copies: The number of strokes to draw at once
Eccentricity: How elliptical the shape is
Axis Consistency: Controls how much the elliptical axis follows your brush position
A simple frame of points following your brush position
Copies: The number of strokes to draw at once
Linear copies of your stroke with optional color shifts
Copies: The number of strokes to draw at once
Distance: How far each copy is from the next
Radial copies of your stroke with optional color shifts
Copies: The number of strokes to draw at once
Autolathe but with multiple lathes.
Speed: The speed the lathe is spinning
Angle X: The axis tilt in the X direction
Angle Y: The axis tilt in the Y direction
Speed X: How fast to spin the X axis
Speed Y: How fast to spin the Y axis
Multiple copies of your brush spaced between your left and right hand positions
Copies: The number of strokes to draw at once
Copies of your stroke forming an polygon
Copies: The number of strokes to draw at once
Sides: The number of sides of the polygon
Copies of your stroke forming an rectangle
Number of points along width: How many points along the sides
Number of points along height: How many points along the top and bottom
Spacing: The distance between each point
Exterior Only: Whether to create copies just around the perimeter or also fill in the middle
Multiple copies of your brush spinning around your actual brush position
Copies: The number of strokes to draw at once
Speed: How fast the extra pointers are rotating
Radius: The radius of the circle they are rotating around
Copies: The number of strokes to draw at once
n: The parameter that controls the overall shape of the superellipse
Eccentricity: How elliptical to make the shape
Axis Consistency: Controls how much the elliptical axis follows your brush position
An example of using an SVG file as a template for symmetry patterns
Point Spacing: The distance between each pointer around the shape
(Currently removed while I fix a bug)
A line of copies between a guide and the symmetry widget
Copies: The number of strokes to draw at once
Copies: The number of strokes to draw at once
(Currently removed while I fix a bug)
Connects the two most recent strokes with a series of lines. Draw one stroke then another. As you finish the second stroke you will see new lines added
Number of sections: How many connecting lines to draw
Stops and restarts the stroke at regular intervals as you draw resulting in a dashed line.
Frequency: How many dashes there are in a given distance. Shorter values gives a result closer to a dotted line.
Spacing: Controls the spacing between dashes
The script callsBrush:ForcePaintingOn
and Brush:ForcePaintingOn
based on the value of Brush:DistanceDrawn
Locks movement of the pointer to either the x, y or z axis depending on which direction your hand is mostly moving.
Speed: How fast the pointer can move as it tries to keep up with your hand movements
Frames Between Changes: To avoid creating weird unintended artifacts, the plugin ignores changes of direction that happen too soon after the last one. You can control how many frames a direction is "locked in" here.
Draw slowly and deliberately. It can be tricky to get the hang of initially.
The pointer position cycles back and forth between the current position and where your hand was a short time before. The result is either loops or scribbles depending on the parameters and how quickly you move.
Delay: How many frames back in time to get the other position from
Frequency: How quickly to cycle between past and present positions
Amplitude: Controls the amount of "overshoot". This exaggerates the difference between the past and present positions
The choice of parameters and choice of brush can radically change how this plugin looks. Play around!
The pointer continues moving in the direction you were pointing when you initially pressed the trigger. Pew pew...
Speed: The speed of the beam
You definitely want to try this in conjunction with Symmetry Plugins - especially if you also spin the mirror widget.
The pointer moves around a circlular path with your current hand position as it's center.
Speed: The speed of the pointer
Radius: The size of the circle it moves around
Similar to [LaserBeam](example-pointer-plugins.md#laserbeam) except that you can steer the brush stroke as it moves.
Speed: The speed of the missile
Control your pointer with multiple waveforms to create patterns
X Waveform Type: The waveform used along the x axis
X Frequency: The frequency for the x axis waveform
Y Waveform Type: The waveform used along the y axis
Y Frequency: The frequency for the y axis waveform
Y Phase: The phase of the y waveform relative to x
Radius: A scaling factor applied to both axes
Tips
The values for waveform type are as follows:
0=Linear
1=Cosine
2=Triangle
3=Sawtooth
4=Square
5=Pulse(0.8)
6=Pulse(0.2)
7=Exponent
8=Power(2)
9=Power(0.5)
10=Parabolic
11=Exponential Sawtooth
12=Perlin Noise
13=White Noise
14=Brown Noise
15=Blue Noise
The brush draws a path around your current hand position similar to [Loops](example-pointer-plugins.md#loops) - except the path is a polygon instead of a circle.
Points: How many sides the polygon has
Size: The outer radius of the polygon
At regular intervals, ends a stroke and starts a new one with a different color. The effect is similar to dashes but with the smallest possible gap between sections of the stroke.
Rate: The number of frames between color changes.
Hue Shift Frequency: How fast to cycle the hue
Hue Shift Amount: How much the hue changes
Moves the pointer in a simple wave pattern as you draw.
Frequency: How close together the peaks of the waveform are
Amplitude: The height of the waveform
Creates spherical patterns around the initial point you start drawing. The distance you move affects the patterns progress but the position is always centered around the initial point.
U Scaling: The rate of change of the pattern horizontally around the sphere
V Scaling: The rate of change vertically around the sphere
Radius: The size of the sphere
The brush stroke moves in a circle but the radius increases the longer you keep the trigger pressed.
Speed: Controls the tightness of the spiral via changing the rate at which the pointer rotates around the brush position
Radius: The overall size of the spiral
Additional lines are drawn from the initial point you started drawing to your current brush position.
Rate: How many frames to wait before drawing another connecting line
As you draw you only control the x and z position of the stroke. The y position (the height) is determined by a noise function that maps out hills and valleys.
Scale: The scale of the terrain. Larger values spread out hills and valleys more, smaller values make them smaller
Height: The height of the terrain. (Scales everything in the vertical direction)
Offset: The starting distance of the terrain off the floor
As you draw the position is controlled by your hand as normal. However the orientation of the stroke spins around by itself
Speed: How fast to spin around the axis
Try this with a broad flat brush like Paper or a brush that has an interesting profile shape such as Faceted Tube
This spins around the z-axis. i.e. the direction your brush is pointing. You will only see an effect of you draw strokes forwards or backwards along this axis.
The brush position cycles back and forth between your brush hand and your other hand. Paint with both hands for a change...
Frequency: The speed to oscillate between the brush and the wand
Amplitude: Controls how much to move. 0 is just the midpoint between both hands, 1 will reach both hands, 2 will overshoot both hands
Move your hands close together or further apart to see different effects
The brush stroke wanders off in random directions while you hold the trigger
Speed: How fast the pointer should move
Frames Per Path: After this many frames, the stroke is restarted from the current brush position
Randomizes the brush position
Wiggle Amount: The amount of randomness to add to the brush position
Like Wiggle but uses a smooth noise function
Position Amount: The amount the noise affects the brush position
Rotation Amount: The amount the noise affects the brush orientation
Frequency: The scale of the noise function (higher = more jagged)
If you run that batch file a command window will appear giving you several options for re-rendering your video: Press a number to get whichever format you prefer. It will then launch Tilt Brush, which will reload your sketch, and re-render the video. Once it is done, Tilt Brush will exit. As rendering at higher quality tends to affect the framerate, it is suggested that you do not wear your headset while this process completes.
Converting into 360 video 1. Download the 360° Video Metadata app for Mac or Windows. The dialog should look like this: 2. Unzip the file, then open the 360 Video Metadata app. If you're on a Mac, you may need to right-click the app and then click Open. 3. Select the video file. 4. Select the checkbox for My Video is stereoscopic 3D (top/bottom layout) 5. Click Inject Metadata 6. Enter a name for the file that will be created. 7. Save the file. A new file will be created automatically in the same location as the original file.
If you run that batch file a command window will appear giving you several options for re-rendering your video: Press a number to get whichever format you prefer. It will then launch Open Brush, which will reload your sketch, and re-render the video. Once it is done, Open Brush will exit. As rendering at higher quality tends to affect the framerate, it is suggested that you do not wear your headset while this process completes.
Converting into 360 video 1. Download the 360° Video Metadata app for Mac or Windows. The dialog should look like this: 2. Un-zip the file, then open the 360 Video Metadata app. If you're on a Mac, you may need to right-click the app and then click Open. 3. Select the video file. 4. Select the checkbox for My Video is stereoscopic 3D (top/bottom layout) 5. Click Inject Metadata 6. Enter a name for the file that will be created. 7. Save the file. A new file will be created automatically in the same location as the original file.
(the rabbit/tortoise switch on your brush) is especially effective with some plugins. The smooth strokes you can with tortoise mode can combine beautifly with animated Pointer or Symmetry plugins.
(Rift, Quest via Link cable...)
(Vive, Index, Reverb...)
(Pico, Pimax etc)
This is in the .
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest:
You must switch to before joining a room. Currently only basic mode features are supported.
Come over to the and chat to Riccardo ( @sbanca ) or me ( @andybak#5425 ). We're both on UK time.
(Rift, Quest via Link cable...)
(Vive, Index, Reverb...)
(Pico, Pimax etc)
Unlike the existing , plugin scripting is designed to run small scripts that directly modify the behaviour of various features while you are actually using them. For example a script might move the pointer as you are painting or add new strokes in response to your actions.
a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest:
See
See
Come over to the and chat to me ( @andybak#5425 ). I'm on UK time but I check in fairly regularly.
(Rift, Quest via Link cable...)
(Vive, Index, Reverb...)
(Pico, Pimax etc)
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest:
Come over to the and chat to me ( @andybak#5425 ). I'm on UK time (currently UTC+1) but I check in fairly regularly.
You can open the Scripts Panel from a button on the Experimental Panel (You'll need to be in ).
We won't be using the buttons on the bottom row at the moment. These are related to the older which are are useful for controlling Open Brush remotely. However the new plugin scripts are much more powerful and can add new features and modify how Open Brush works interactively.
The other four rows of buttons each relates to a different type of plugin. From the top down they are , , and .
These are the simplest type of plugin. They can change how your brush works while you are painting brush strokes. They can't (currently) create new types of brush but they can change the motion, size, color of the stroke. And they can start and end strokes (for example to create dashed lines). They can even add extra strokes as you paint (for example to create a web of lines back to your starting point). Here are some of the included .
Symmetry plugins supercharge the Mirror tool. Instead of simply adding a single extra stroke mirrored horizontally, Symmetry Plugins can create multiple copies of your brush stroke in any arrangement. The strokes can be mirrored, rotated, reflected or even scaled. They can be oriented around the mirror widget - or they can follow your brush like a flock of birds. Each stroke can have a different color, size or even use a different brush type. Here are some of the included .
The previous two types of plugin work in conjunction with the regular Brush Tool and simply change or add to the brush strokes you draw. Tool Plugins are are more powerful and can implement entirely new tools. They might create new objects in one go - or modify existing ones. Each plugin can behave in different ways so check each script's instructions to understand what it does. Here are some of the included .
The final type of plugin takes the flexibility one step further. Background plugins can do almost anything. They are more complicated to write but they have less restrictions. For a start they run all the time and can listen in to button presses, track controller movement and react accordingly. They can create repeating animations by moving layers around, they can perform actions based on timers or external signals. And you can have multiple Background Plugins active at once (You can only activate one of each of the other plugin types at any one time). Here are some of the included .
Eventually we hope to have an "App Store" for plugins so you can browse and install ones that the community have created. In the meantime you can check our for info on any plugins.
Like except the widget always moves to where you start drawing
Like but you can vary the axis orientation
Copies of your stroke forming a
Similar to but centered around the Symmetry Widget
Based on - this was originally a bug but I liked it so here it is.
If you use this in conjunction with then you'll need to draw very slowly on the default settings Dashes.
If you want to use a hull brush then draw small patches or else any valleys will be filled in. For hull style results you will probably be better off using the
Plugins are written in the scripting language Lua which is designed to be simple to learn and easy to understand. There's plenty of tutorials online and Lua is widely used in games and applications such as Factorio, Garry's Mod, Roblox, LÖVR and many others.
If you've written scripts in any other language then you'll find it easy to pick up.
If you've never programmed at all then Lua is a great place to start. Copy an example script to your Open Brush folder (there's a button next to each Plugin type that does this for you), open it up in a text editor and try changing things.
As soon as you save your changes, Open Brush will load the new version. If you've made a mistake then the console on the back of your brush hand will tell you what line the error is on.
In addition to the API commands you can use most of the Lua Standard Library. Another included library is Lume which you can use via require "lume"
The following realtime values from the sketch are examples of values that are available to use in your scripts. There are many more. Here is a full list of methods and properties for each type.
Brush.position: The current position of the brush pointer relative to the canvas
Brush.rotation: The current orientation of the brush pointer relative to the canvas
Brush.colorRgb: The current brush color
Brush.colorHsv: The current brush colour converted to HSV
Brush.size: The current brush size
Brush.pressure: The current pressure of the brush pointer (how hard the trigger is being pressed)
Brush.type: The current brush name
App.time: The time in seconds since Open Brush was launched
App.currentScale: The current scale of the canvas
Sketch.strokes A list of strokes in the current sketch
Scripts can specify parameters that appear as UI widgets such as sliders. These appear in a popup when you click the "3 dots" button on the right of each row. For example you might want a script to have sliders to control "speed" or "wigglyness".
You define the widgets for each parameter in your script. Here's an example:
Here we have defined two widgets. Both are floats (rather than integers) and we have defined a minimum, a maximum and a default value. You can set the ltext abel that appears when you hover over each slider.
The name of each widget (here "speed" and "radius") are then available to the script as variables.
By default each script type works relative to an origin and has a rotation that makes sense for each of the three types. Pointer and Tool Scripts are relative to the user's brush hand and Symmetry Scripts are relative to the Symmetry Widget.
You can override this. For example, here's a PointerScript that is relative to the canvas. We can then position the pointer so it is always at y=0 (the floor) but still tracks the pointer in the x and z directions:
Note that we have to manually specific pointer.position.x and pointer.position.y. If we were using space="pointer" (the default) then we wouldn't need to as coordinates are automatically relative to pointer.position
Valid spaces are currently "pointer" or "canvas".
Allows you to precisely control the spin speed of the symmetry widget
Cycles through all layers, fading one out as the next one fades in. An example of using shader parameters to fade strokes in and out
An example of drawing procedurally on startup and then using shader parameters to animate the strokes it has created
An example of drawing continuously. It draws random straight lines for as long as the script is active.
Randomly downloads a panorama from Openverse and sets it as the current skybox. Not every skybox is valid so you might need to toggle the script a few times. Also - they are quite large files. If you're short of space - make sure you have a clear out occasionally!
Background Plugins run all the time when activated. They are useful for animating layers or continually generating new shapes. You can still check for user actions such as pressing the trigger and change the action accordingly. They are very versatile but because they run continuously in they background, they can affect performance (especially if you run several at the same time).
Always use one of the other script types in preference if it is more suitable.
Unlike other plugin types, Background Plugins don't expect you to return a value and they don't do anything with any values you do return.
In contrast other plugin types use return values as follows:
Pointer Plugins use the returned value to change the pointer position, rotation or scale.
Symmetry Plugins use the returned values to create multiple new pointers.
Tool Plugins can use the returned value as the path of a new brush stroke which is drawn immediately.
You can of course draw in a Background Plugin but it's left to you to do so explicitly:
There are some potentially new details to be aware of here:
We are defining our own function to generate a random position around the current brush position
We are using the Random
class to generate a point that is never more than a certain distance away from the origin. We then add that to the current brush position
We are manually drawing the path with myPath:Draw()
Symmetry Plugins are similar to Pointer plugins with a few differences:
They can return a list of transforms that represent multiple pointers.
They can modify the color, size and brush type for each of the strokes separately.
They have access to the Symmetry Widget which can be used as a point of origin for each pointer. If you've used the Mirror or MultiMirror features in Open Brush then the Symmetry Widget is like the Mirror Widget that controls the reflection plane and center for those mirrors.
Bear in mind - the number of pointers you generate cannot change once a brush stroke has begun, but can change between each brush stroke.
Make sure you name your symmetry plugin scripts with the prefix "SymmetryScript". For example SymmetryScript.MyMirror.lua
Let's start with the simplest possible Symmetry Plugin:
In lua you can define a list of items by enclosing them in curly braces. This example is almost identical to the simplest possible Pointer plugin except that we wrap the transform in curly braces.
You might expect that it behaves the same - i.e. nothing changes and you paint as normal. However if you try it, you'll find that's not the case. In fact - you can't paint at all - your pointer remains stubbornly stuck to the center of the Symmetry Widget.
Why is this? By default Pointer Plugins and Symmetry Plugins use a different coordinate space. This is how we describe how where the origin is and how translations and rotations are interpreted. Pointer plugins default to using the current brush controller position as the origin so all coordinates are relative to that. Symmetry plugins on the other hand default to using the Symmetry Widget as the origin. So returning a transform that does nothing means that the pointer is stuck at the widget's center.
You can change the default coordinate space by adding a value to the script settings:
This plugin will now behave the same as the "do nothing" pointer plugin example. Using space="pointer"
in a Symmetry Plugin is useful if you want to ignore the widget and have all the pointers move relative to the brush controller.
Let's do something more interesting in our Symmetry Plugin:
Here we are returning a list of 4 transforms so we will have four separate pointers all creating a stroke at the same time.
Transform.Lerp
is a method that takes two transforms as input and blends them by an amount given by the third number. So Transform.Lerp(a, b, 0.5)
will return a transform that is exactly half-way between a and b. It's position will be at the midpoint of a and b and will have a rotation and scale exactly halfway between those of a and b.
What are we passing into Transform.Lerp? origin
is set to Transform.identity
which is our do-nothing transform. As mentioned before - in this case it will be the center point of the symmetry widget.
brushOffset
is a Transform with it's position set to the value ofSymmetry.brushOffset
. This is a Vector3 which represents the position of the user's brush controller relative to the symmetry widget. It is a special value that only makes sense in the context of a Symmetry plugin and you won't use it in other types of plugin script.
Usually the value of the user's brush controller is given byBrush.position
. This is because by default, symmetry scripts use coordinates centered on the symmetry widget and you'd have to do a some complicated calculations to get from there to the current brush position. If you use symmetry.brushOffset
this is done for you.
So this script will create 4 pointers that are spaced evenly between the symmetry widget and the user's brush controller as they paint. Give it a try!
Finally - let's look at one last symmetry script.
Some things to note here:
Instead of creating a list of transforms using curly braces we are creating a Path
object and then using Insert
to add pointers to it one at a time. Path is just a class that stores a list of transforms. It has some useful methods for transforming and modifying itself so is often more useful than just a simple list.
We are using a loop: for i = 1, copies do
You should have come across similar constructs in other scripting languages. Any lua tutorial will explain some small differences with lua loops but in general they should behave as you would expect.
angleStep
is always 36 in this case but if you wanted to,copies
could be a slider that the user sets so we calculate how many degrees to add to the angle for each copy of the pointer.
You don't have to calculate the position of each pointer around the circle. This is done automatically for you. The final position is calculated based on the symmetry widget's transform and the rotation value you return for each pointer. This saves you from having to do some pretty gnarly maths yourself in symmetry plugins.
Tool Plugins can do many different things but they are often used for drawing a lot of brush strokes all in one go. For example you could draw an entire spiral shape whenever the user clicks the trigger. Or you could use the positions: where they first pressed the trigger in and where their brush controller was when they released the trigger - to get the size of a region and create a shape that filled that space.
To create a Tool Plugin name your script with the prefix "ToolScript". For example: ToolScript.Circle.lua
Tool Scripts should usually return a list of transforms. If they do then this defines an entire brush stroke that is then created for you.
We previously started by showing the simplest possible plugin script - one that does nothing. Because a tool plugin does nothing by default that would be an empty file! But let's put a bit of scaffolding in so you have a starting point for a plugin that actually does something.
It checks to see if the user pressed the trigger and if so it returns an empty list. So this plugin does nothing and it does it every time the user presses the trigger. Great, huh?
Let's make it do something:
This returns a path with 5 points forming a square. A square has 4 corners so why 5 points? The last point is the same as the first so that the square closes on itself.
If you try this, you'll notice the square isn't very square. This is because Open Brush tries to smooth brush strokes. It expects you to be hand-drawing smooth curvy lines in space - not carefully placing precise geometric paths.
We can fix this by adding extra points:
This time we create a Path
object instead of just using a list of transforms. This allows us to use any of the handy methods that are provided by Path
- in this case it's the SubdivideSegments
method. This modifies the path by inserting as many new points as we ask for in each path segment. In this case we ask for 5 new points so the square that previously had 5 points (and thus 4 segments) will now have 4 x 5 = 20 points. (I'll let you work out how many segments!)
Next let's draw a circle:
There's a few new things here:
a loop that begins for...do
, this is a standard lua construct and works similarly to loops in other languages.
we first calculate a 2d vector using Vector2:PointOnCircle(angle)
. A Vector2 is very similar to the Vector3
that we used previously for specifying a position. The difference is that it only has two coordinates: x and y.
We convert the Vector2
into a Vector3
on the next line by using the OnZ()
method. This creates a Vector3
where x and y are taken from the Vector2
the z value is set to 0. Therefore it lies on the plane perpendicular to the z axis (it could probably have been named on OnXY()
but this sounded better to me)
We are using triggerReleasedThisFrame
instead of triggerPressedThisFrame
. In this example we wait for the user to release the trigger before we do anything. This means we know both the start point (where they pressed the trigger) and the end point (where they released it). These two points are used to determine how the path we return is scaled and rotated. You don't need to do this scaling and rotating yourself - it happens automatically if you return a value representing a brush stroke.
When you paint freehand in Open Brush, the application is constantly recording your hand's position and orientation. Therefore internally a stroke is defined as a list of transforms. Scale isn't used but the position and rotation are key in defining the shape of the resulting stroke.
There are several situations when you might need to define a stroke when writing a plugin:
The most common use-case is with Tool Plugins. The value you return from the Main() function in a Tool Plugin is drawn as a brush stroke
You can paths explicitly using Path:Draw(), PathList:Draw() or the draw methods provided by classes such as SVG
In both these cases you must define the path as a list of transforms. Both the position and rotation are used to define the shape of the stroke. It matches what happens when you draw a stroke by hand - at each point in time you control both the position of the brush and it's orientation. Orientation doesn't matter for all brushes (a tube brush looks much the same whatever the rotation of the brush controller at each point is) but other brushes such as flat stroke brushes do make use of the rotation values you provide.
In the simple case where you are returning a value from the Main function of a Tool Plugin, you can return a normal lua array (or "table" as they are also called) containing two or more Transform instances:
It's simple to use a lua list like this: {} but there is also a class specifically for definition a list of transforms and it's called Path
. The advantage of using this class is that also has many useful methods for modifying paths.
(The various Draw()
methods insist that you use a Path object - so you can't use a simple lua array when you use those.)
Open Brush usually assumes a brush stroke is drawn by hand. Some simplification is done depending on your settings but a stroke is still usually made up of a lot of points forming a smooth curve as the app samples your controller position and orientation many times a second.
When you draw paths via code in a plugin script, you often send only the exact points you want. For example if you were drawing a square then you'd simply define the four points that make up the corners of the square (although you usually repeat the first point at the end if you want a closed shape)
The problem is that by default Open Brush tries to smooth the path you give it so your nice precise square becomes a rounded squiggle. The end result actually varies depending on the brush you use - different brushes use different rules for how to smooth the input points.
But generally speaking - if you want to draw a precise geometric shape then you need to add extra points - and the Path object has some useful methods to do this.
To make trying out multiple features easier I maintain a "Kitchen Sink" build that combines multiple feature builds in one. Sometimes these features might not work perfectly in combination and this build probably gets tested less than the individual feature builds.
If you're using this build and find a bug, it would be really helpful if you could check to see if that bug also appears on the relevant single feature build.
Currently this build combines all the features in the beta release plus the following features:
Oculus PC VR (Rift, Quest via Link cable...)
SteamVR and other PC VR (Vive, Index, Reverb...)
Other Builds (Pico, Pimax etc...)
Generally - when someone is working on a new feature, they create a new build to work on until the features is ready to merge back into the main release.
You can download these builds to try out new features. Sometimes the sketches you create with these builds won't open correctly in the main release (but not always) and like all pre-release versions these builds might contain bugs or incomplete features.
In theory you could use any text editor to write and edit your plugin scripts: Notepad on Windows or TextEdit on MacOS.
However an editor that is designed for writing code has many useful features to make your life easier. You might already have a favourite editor. However one thing to consider it whether it supports Lua properly - and also if allows you to use the autocomplete hints that we automatically provide.
These hints will allow your editor to suggest method names, offer tooltips for parameters and even spot errors in the types you're using in your code.
If you're not sure then the simplest thing to do is just use Visual Studio Code:
If you look in your Documents/Open Brush/Plugins folder there is a subfolder called LuaModules and in there are a few commonly used libraries, that will provide some useful features.
However one file is different. It contains empty definitions for all available API methods and properties along with special comments that can be used by the EmmyLua plugin to give you working autocomplete, intellisense and tooltips. This makes writing scripts and finding bugs much easier.
If you're using Visual Studio Code then follow these steps: 1. Launch the Plugins build of Open Brush at least once so that it creates the Open Brush/Plugins folder.
Launch Visual Studio Code.
Search for "Lua" and look for the sumneko extension:
Click to install it and wait for it to finish installing
Now we've finished with settings we want to make sure it all works. We will start a simple script to check the code completion is working. Create a new file in your Documents/Open Brush/Plugins folder (not inside LuaModules) and name it PointerScript.Test.lua Then start typing:
As soon as you type the period you should see a list of suggestions that match the "App" part:
If not - check you've followed all the steps above.
Any variables you define via Script Parameters will show a warning saying they are Undefined Globals. This is because the Lua plugin used in Visual Studio Code doesn't understand that Open Brush will read the Parameters table and add these variables names into your script. You can ignore these warnings for your Script Parameters.
Visual Studio Code allows you to open the entire Plugins folder as a "workspace". Although this does allow convenient navigation between scripts it does have an unintended side effect. The VS Code lua plugin assumes that all the scripts will share a single scope. Therefore it will treat global variables in one script as also existing in all other scripts. This might result in some warnings not being displayed or incorrect warnings being displayed. It's probably best if you open each plugin script separately into it's own instance of VS Code
Now you've got a code editor installed and a plugin to help make things easier, you can move on to tweaking the example plugins and maybe even writing your own plugins from scratch.
A great way to get comfortable with how plugin scripting works - especially if you've never coded before - is to look at existing scripts and modify how they work in small (or maybe not so small!) ways.
(If this button isn't visible then a script of that name already exists in your plugins folder - you've probably already clicked the button for that particular plugin).
Once a plugin script does exist in your plugins folder you can edit it. Any changes you make will take effect immediately - there's no need to restart either Open Brush or the plugin itself. Any syntax errors might stop the plugin working. If so these are displayed on the console on the back of your brush controller. They will tell you which script and which line number has the problem.
Pointer Plugins can modify the pointer position and/or rotation every frame. You can get the current position and rotation so you can simply add an offset to those - or you could create an entirely new position or rotation based on any of the other context variables that are available to the script.
Name a Pointer Script with the prefix "PointerScript". For example: PointerScript.MyPlugin.lua
Assuming your script is valid (i.e. it has no syntax errors) then giving it a valid prefix is all you need for it to appear in the Scripts Panel.
By default a Pointer Script returns a Transform which represents how the pointer moves relative to it's normal position (which in this case is wherever the user moves their brush hand)
The simplest possible pointer plugin would be something like this:
This does nothing at all. It returns a transform called "identity" which means "no change at all". There are several other ways to express the same thing:
There's no difference between these - it's just sometimes more convenient or clearer to write things in different ways.
So - a plugin script that does nothing isn't much fun. Let's change it so it does something.
Vector3.up is another shorthand - this time it's shorthand for Vector3:New(0, 1, 0) this is a vector with:
x is 0 (no change in the left/right direction) y is 1 (a shift of 1 in the up direction) z is 0 (meaning "no change in the forward/back direction")
So - this plugin tells Open Brush "the user's pointer should be moved up by 1 unit from whereever they are painting". If you try it you should see your pointer is about 10cm above wherever you move your brush hand.
So this is not very useful - but we at least we can see we are changing something now.
Let's try something slightly more interesting.
App.time is a property of the App class where you can access various properties of Open Brush app itself. As you might have guessed App.time measures time - specifically the number of seconds since you launched Open Brush.
This plugin script will result in your strokes being painted somewhere way higher than the user's brush hand. How high depends on how long since they opened the app! Let's rein things in a bit.
That single return line is getting a bit complicated. Let's split things over two lines to make it easier to read:
If you've done any programming or scripting before, you should recognise what we've done here. "y" is a variable. We chose "y" as the variable name but we could call it anything we want.
We've assigned a value to "y" which is the result of calculating a waveform shaped like a triangle
The output of the Waveform:Triangle method takes two parameters as input time and frequency. It returns a value that varies between -1 and +1. If you've configured your editor as explained in Getting Started then you should have seen a hint pop up when you typed the first open bracket:
So we now have a plugin that moves the pointer up and down over time. You can change the second parameter to control the speed.
Let's go one step further - allow the user the control the speed without needing to edit the plugin script:
We've now told Open Brush that this plugin should show a slider in it's Parameters popup which changes the frequency that the pointer moves.
Made by Chingiz Dadashov-Khandan as a project for The University of Groningen
Status: Experimental. Saved sketches are incompatible with official builds
Oculus PC VR(Rift, Quest via Link cable...)
SteamVR and other PC VR(Vive, Index, Reverb...)
Other Builds (Pico, Pimax etc)
Allows you to modify brush stroke meshes like digital clay
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest: https://uploadvr.com/sideloading-quest-how-to/
Switch to advanced mode and use the new sculpting tool on any brush strokes. Works best on hull brushes.
WARNING - Saved files are currently incompatible with official builds of Open Brush. Don't save over any sketches you want to open in other builds.
Come over to the Open Brush Discord: https://discord.com/invite/fS69VdFXpk and chat to me @andybak).
I'm on UK time but I check in fairly regularly.
TODO
This build was intended to streamline the UI with a subset of features to:
Not overwhelm the user with complexity. This essentially meant that it should look as similar to basic mode as possible.
Contain only features deemed useful for classroom-style usage. This includes filtering the brushes down and rearranging several tools found in various panels into a single panel.
Both #1 and #2 were accomplished by creating a new "classroom" panel mode in addition to the normal "basic" and "advanced".
The future of Open Brush begins here!
We have been hard at work updating Open Brush to the latest version of Unity and it's new XR Framework. This will enable us to keep up to date with new features that are only available with modern VR SDKs such as hand tracking and passthrough. In addition it will make it much easier to support new platforms and devices moving forward.
As this is a big fundamental change in how Open Brush interacts with devices, we need your help testing our new builds before we release it generally.
Our desktop build is now powered by OpenXR! To make it easy to access, we have added a new beta channel on Steam.
First, grab Open Brush from the Steam store. Once you have added it to your library, right click on the listing and choose 'Properties...'
Select 'Betas' from the sidebar. In the text box, add the access code: openbrushxrbeta
and click 'Check Code'. A blue banner will appear below, confirming your access!
You can now access the openxr and openxr-experimental betas. select your desired beta from the dropdown and Steam will automatically install that version! The name of the game in your Steam library will be appended with [openxr].
When you click Launch from within Steam, make sure to select 'Launch Open Brush in OpenXR Mode'!
SideQuest have just released a new in-headset installer which you can find on the guide above! If you're using this method, simply search for 'Open Brush Beta' from within the SideQuest app to install the beta. From your app drawer, in the top right, there is a dropdown to filter types of apps. Select it, scroll to the bottom, and select 'Unknown Sources'. You will see an app called 'Open Brush (feature_xr_v2
). Click it to begin testing!
Make sure your Quest is connected to your device. In the SideQuest app on your computer, search for 'Open Brush Beta'. On the app page, click 'DOWNLOAD APP (SIDELOAD)'. The app will install!
In your headset, open the app drawer. In the top right, there is a dropdown to filter types of apps. Select it, scroll to the bottom, and select 'Unknown Sources'. You will see an app called 'Open Brush (feature_xr_v2
). Click it to begin testing!
Click the long link beside the name of the build you wish to use (i.e. Windows Rift). A quick reminder that Windows Rift is the build you want if you're using Quest linked to your PC!
Note: before you begin, you may need to set Oculus as your active XR Runtime. this may appear as a banner on the Oculus Desktop app. Go to Settings, General and under 'OpenXR Runtime', click 'Set Oculus as Active'. You may need to restart your PC afterwards. Double click the downloaded zip file. Press the Extract all button, and unzip the folder to a known location. You may want to use your Desktop or Documents folder. Once unzipped, open the StandaloneWindows64-Oculus folder, and double click 'OpenBrush-featurexrvr2.exe' to run the program! Windows may scan the folder for viruses as it's an unknown folder, which will prevent the program launching until complete. This is perfectly normal, and the program will launch by itself once finished.
Organize your sketch into layers that can be turned on and off separately. Exports use only the layers you've set as visible so you can create layer just for guides strokes or construction lines.
I'm on UK time (currently UTC+1) but I check in fairly regularly.
Click on the button on the left that shows the Extensions sidebar:
Click the small cog icon and then open the Extension Settings:
Optionally you can hide a lot of spurious warnings by disabling "lowercase-global" warnings under Lua> Diagnostics: Disable: (In our plugins we're using upper and lower case initial letters to distinguish your stuff from the API supplied-things but standard lua style is to use it to differentiate local from global. Don't worry for now...)
Scroll down to Lua> Workspace: Library and add the path to your LuaModules folder:
Any of the example plugins can be copied to your Open Brush plugins folder simply by clicking the copy button for that plugin type:
Note: Released in
This build was successfully utilized to teach aspects of raytracing as show in the video below and its git repository can be found .
Status: Released in
Thank you very much! Please join our and give yourself the 'Beta Testers' role from our #welcome-rules
channel (click the button!) to receive important updates about new builds. We're discussing this huge change in a dedicated channel, called #unity-xr
. Come and say hi!\
Remember that this is a beta release, so if you do any important work with Open Brush, please back up your files!
This section is very detailed per platform, so here's some quick links to your preferred version: Already set up? Jump to:
We have created a special page for installation of the Quest beta. If you are already know what you're doing with SideQuest, proceed onwards! If you haven't used SideQuest before, please take some time to follow their on setting up your Quest for development builds.
Due to the way the Oculus Desktop store versioning works, we can't automate builds without disrupting the main build! Instead, you can access a manual build from .
In short, everything you can! The previous SDKs were woven throughout the fabric of the app, so our changes impacted a lot of features. We have over on our GitHub with suggestions of things to test (anything already ticked is assumed to be working).
If you are a GitHub user, please feel free to add a comment to our where we are keeping track of validation.
Otherwise, please join our if you haven't already and post a message in the #unity-xr
channel, we'll log it on your behalf!
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest:
Come over to the Open Brush Discord: and chat to me ( andybak#5425 ).
This feature has now been merged into the main release
The current GLTF import in Open Brush fails to open many valid GLTF files. This feature build replaces it with a much more up to date library GLTFast
Importing a wide range of GLTF files into Open Brush including animated models.
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest: https://uploadvr.com/sideloading-quest-how-to/
Just import gltf models as you normally would.
When you load a sketch containing GLTF models, the models do not appear. The workaround is to open the sketch a second time.
Some models are improperly sized in the 3D model panel and obscure other models.
There's no way to control the animation for animated models and selecting them can sometimes be tricky.
Come over to the Open Brush Discord and chat to me ( @andybak#5425 ). I'm on UK time (currently UTC+1) but I check in fairly regularly.
Not yet.
At the time of writing - the current beta version has added a new View Sketches mode and has made Monoscopic Mode available without needing to download a separate version of Open Brush. This is probably the direction we will be taking - rather than directly incorporating Rapka's work.
User @rapka on Github (@collige on the Discord) is working on a new, revamped version of the existing Monoscopic Mode - the mode that allows you to use Open Brush without VR using keyboard and mouse. It's still not quite ready but it's more intuitive than the existing monoscopic mode and uses the WASD keyboard controls familiar to anyone who is used to standard PC game controls.
https://github.com/rapka/open-brush/tree/monoscopic-controls
A new panel allows for precise position/rotation/scale changes to brush strokes and imported objects.
Enter an exact value to change the position, rotation or scale of the current selection
Lock any axis so you can only move the selection along a line or in a plane
Lock rotation axes in a similar fashion.
Control which axes respond to the snap grid
Align all the objects or brush strokes you've selected in various ways
Distribute all the objects or brush strokes you've selected so they are spaced evenly.
We've improved the Snap Settings panel:
You can turn position and rotation snapping on or off for each axis independently
You can also snap all the currently selected objects
You can turn on or off the ability to snap the selected objects to guides
Creating regular arrangements of strokes or precisely positioning/orientating parts of your sketch.
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest: https://uploadvr.com/sideloading-quest-how-to/
It should appear automatically.
(To do)
Come over to the Open Brush Discord: https://discord.com/invite/fS69VdFXpk and chat to me ( andybak#5425 ).
I'm on UK time but I check in fairly regularly.
(To do)
This page is a placeholder - I'm going to collect case studies and examples and expand it later into a comprehensive list of real-world examples.
Creating a virtual costume in Tiltbrush
Status: Released in v2.8
Adds new optional GLTF import and export workflows. Allow import of lights, breaking apart of imported models and other new features that the updated libraries enable.
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest: https://uploadvr.com/sideloading-quest-how-to/
To switch to the new importer (which replaces GLTFast that we added in v2.4 with UnityGLTF you need to edit your Open Brush config file and add this entry after "Flags":
We've changed how export in general is configured. Previously all supported formats were exported whether you needed them or not. Some were pretty slow for large scenes (STL - looking at you) and you probably only needed a couple of them. Now you can choose which are available using the config file:
ExportBinaryFbx and ExportFbxVersion are existing options - but the rest of the entries here are new.
ExportStrokeMetadata: todo
KeepStrokes: todo
KeepGroups: todo
Formats: Each item in here corresponds to an existing export format except for "newglb" which is a glb file but we use the new export code to generate it. Note that formats not supported on your platform will be ignored. See below for platform support.
Extensions supported by GLTFast but not UnityGLTF:
EXT_mesh_gpu_instancing
KHR_materials_pbrSpecularGlossiness (legacy extension - superseded by KHR_materials_specular which is only supported by UnityGLTF)
Extensions supported by UnityGLTF but not GLTFast:
KHR_materials_clearcoat
KHR_materials_emissive_strength
KHR_materials_ior
KHR_materials_iridescence
KHR_materials_specular
KHR_materials_transmission (soon)
KHR_materials_volume (soon)
MSFT_lod
Extensions supported by both:
KHR_draco_mesh_compression
KHR_lights_punctual
KHR_materials_unlit
KHR_mesh_quantization
KHR_texture_basisu
KHR_texture_transform
(The above list may change as we implement missing features in UnityGLTF. GLTFast also has announced plans to support KHR_materials_variants, EXT_lights_image_based and KHR_materials_transmission)
UnityGLTF has some other differences:
Model hierarchy should be faithfully preserved. GLTFast on the other hand doesn't support sub-meshes so any mesh that contains multiple materials will be split into separate objects. (this might be desirable in some cases)
In general 3d models should be more robustly handled if you round-trip between Open Brush and other 3D apps
Please report any other differences you find. The reason we are keeping both importers around is to gather feedback on their strengths and weaknesses.
The use of the new exporter is currently optional and we will continue to support the old exporter until the new one is a full replacement.
Currently - if you use the Open Brush Toolkit Unity SDK then use the existing exported GLB file
Use the existing exporter for uploads to Icosa.
Similarly - if you use the Icosa three.js loader this works best with the existing exporter
The new GLB export should work better in Blender and other 3D animation apps although we still have work to do to fix support for particle brushes, transparent brushes and other features.
Imported 3D models will export much better with the new GLB exporter
In general new features in the beta or from other experimental branches will work better using the new exporter.
FBX
✘
✔
GLB
✔
✔
NEWGLB
✔
✔
JSON
✔
✔
LATK
✔
✔
OBJ
✘
✔
STL
✔
✔
USD
✘
✔
WRL
✔
✔
This build supports a new feature - The existing "group/ungroup" button on the pop-out tray that appears when you activate the Selection Tool now works on imported models - if they consist of multiple parts. Just select a single imported model and if it does have sub-parts the button will show "ungroup" as an option - the same as if you select a normal grouped set of objects.
If your imported model contains lights then these will appear in the scene and will act upon other objects the same as the Environment Lights. Furthermore imported lights support point lights and spot lights - whereas the existing environment lights only support directional lights.
If you break apart a model containing lights, the lights themselves can't be selected or moved.
Come over to the Open Brush Discord: https://discord.com/invite/fS69VdFXpk and chat to me @andybak).
I'm on UK time but I check in fairly regularly.
Big expansion to the mirror to support many different types of symmetry:
Point symmetry: Symmetry around a point. 7 familiies of axial symmetry plus 3 (soon to be 7) unique polyhedral symmetries.
Wallpaper symmetry: 17 types of tiling symmetry
Duplicate selections using symmetry: Create multiple clones of a selection aligned in a pattern
Draw with multiple colours at the same time: The colour of each stroke can be varied in interesting new ways
Creating symmetrical patterns. Drawing multiple strokes at the same time. Arranging models or images into grids or other regular patterns.
Hold down the mirror button on the Experimental Panel for a second or two:
This will bring up the Symmetry settings panel which contains three tabs:
Point symmetry creates copies arranged around the center of the mirror widget. Each icon selects one of the 14 different types of symmetry. This is the symmetry of molecules and polyhedra. It can create shapes such as stars, explosions, vases, octopi or plants and flowers.
For the first 7 point symmetry types, the slider controls how many copies are arranged around the center axis. (The other 7 types are based on tetrahedra, cubes and icosohedron and have a fixed number of copies)
Wallpaper symmetry repeats your strokes in various types grid pattern - reflecting or rotating in specific ways. You can create wallpaper, floor tiles crystal lattices or any other repeating patterns.
For all symmetry types you have control over the number of copies in x and y directions. For some you can also change the scale of the grid in both the x and y directions and skew the grid cells themselves in either direction.
This screen allows you to vary the colour of each stroke based on waveforms of your choosing. Colors can cycle based on hue, saturation or brightness and the amount, frequency and type of the variance can be precisely controlled.
You can also create symmetrical copies from existing strokes. Simple select the strokes you want to use and duplicate them in the same way you do without the mirror (Press the secondary button on the controller you paint with)
Currently disabled while I iron out the bugs
Be aware that there are currently no limits in place. If you create copies of complex objects or even if you create lots and lots of copies of simple objects, then Open Brush can become unresponsive or even crash.
Currently disabled while I iron out the bugs
It's very easy to create so many strokes or duplicates of 3D models that Open Brush becomes unresponsive or even crashes. We plan to add limits and warnings once we figure out how best to calculate them.
Duplicating brush strokes currently positions copies incorrectly if you've transformed the selection since selecting it. A workaround is to deselect and reselect first.
Duplicating brush strokes can position things incorrectly if you've scaled the world or moved the symmetry widget.
A few symmetry modes move the main pointer so your main stroke is rotated somewhere else. It takes a bit of getting used to but it doesn't actually prevent you painting in these modes.
The slider on the settings panel can glitch the Open Brush UI if you drag it past it's limits.
I'm on UK time but I check in fairly regularly.
This page lists various useful sources of information for using or tinkering with Icosa Gallery and Open Brush and about the community around them both.
Social media:
Unity Downloads:
Custom brushes, new features and multiplayer interaction social posts.
_Open Brush.._In progress
Google - Tilt Brush
Make a donation
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest:
(This feature currently has some bugs. See )
As well as duplicating brush strokes, if you have such as images, video or 3D objects then you can select those and create copies that follow the current symmetry settings.
Come over to the Open Brush Discord: and chat to me ( andybak#5425 ).
If you’re mainly interested in getting into the actual Open Brush codebase then you probably want to look at the as well.
There’s some really useful info in the last that isn’t included here.
Join our
Threads and forum posts from Discord are mirrored here:
We are mods on the It's pretty quiet but we check in occasionally.
Same for
(known forks and features)
A good explanation for non technical people about “Open Source and Tilt Brush”:
Our Discord Bots: Bot
(big list of tutorials, tweets, videos, ideas etc)
A big list of random stuff here:
Guidelines
under
1-28-2021
PunktVR
Dandelion Brush
1-28-2021
PunktVR
Lacey Leaf Brush
1-29-2021
Open Brush
Youtube
Experimental Brushes display
1-28-2021
Andybak / Cabbibo
Twitter / itch.io
Crystal shaders
1-29-2021
M2
WebXR version called - Silk Brush
1-29-2021
PatrickHackett
Youtube Brush
2-1-2021
SabbyLife
Youtube
Hearts, Jelly Brush, & Seed Brushes
Welcome to the Open Brush Documentation
There is content here for both users of Open Brush and for people that want to contribute to its development.
It's currently a massive work in progress and various links and info will be incorrect but we're just trying to get all the information currently available in one place.
Writing good docs takes time. We'd love people to help. Hop on our Discord or just write some docs and let us know about them. There's a bunch of you out there who know more about actually using Open Brush than we as developers do and your contribution would be invaluable.
On your painting controller, use your index finger to pull the trigger.
Hold the trigger down and move the controller to paint.
Note: You can switch which hand is your painting controller and which is your palette controller by tapping the bottoms of the two controllers together. This is great to use if a right and left handed person are sharing controllers.
On your palette controller, use your thumb to swipe left or right across the thumbpad (HTC Vive) or thumbstick (Oculus Rift and Windows Mixed Reality).
This will allow you to rotate between the three faces of the palette.
Using your painting controller, angle your controller towards the palette in order to select items on the palette.
Focus the pointer and press trigger to make selections.
You can also use the grips on your painting controller to grab panels spawned into the world, and place them onto your palette.
To change the width of your brush strokes:
On your painting controller, slide your thumb left or right along the thumbpad (HTC Vive) or toggle the thumbstick left or right (Oculus Rift and Windows Mixed Reality).
Sliding or toggling left will make the brush stroke finer. Sliding or toggling right will make the brush stroke larger.
If you would like to undo or redo brush strokes you have just made, you can use Undo and Redo in the Tools Panel (in Beginner Mode) or these shortcuts (in Beginner or Advanced Mode):
To undo an action:
HTC Vive: On the palette controller, click the left side of the thumbpad.
Oculus Rift: On the palette controller, click the X button (right handed) or A button (left handed).
Windows Mixed Reality: On the palette controller, click the left side of the thumbpad.
To redo an action:
HTC Vive: On the palette controller, click the right side of the thumbpad.
Oculus Rift: On the palette controller, click the Y button (right handed) or B button (left handed).
Windows Mixed Reality: On the palette controller, click the right side of the thumbpad.
To quickly undo or redo, press and hold the controller button specified above.
To scale, rotate, or move your sketch, you can hold down both of the grip buttons on the sides of your controllers to grab the sketch. Then, move your hands to shrink, enlarge, or spin the sketch.
Allows you to control Open Brush using commands sent from your web browser or a script you write. You can use nearly any programming language or even just type commands into your browser address bar.
It even works on computers that don't support VR. You can create Tilt Brush sketches on a Mac and export them to view in a web browser.
Example of a script that uses a web form for input:
Example output from the form shown above:
Some output from other example scripts that are included:
Almost anything! See the command list or the examples. These can be accessed via the help as described below.
You can write scripts to modify existing sketches ("change the color of all strokes to a sequence of rainbow hues"), draw entirely new ones ("draw me a landscape based on this satellite data"), automate tasks ("sign my name and export this sketch"), automatically import a directory full of 3d models and distribute them around your scene, draw fractals or complicated geometry and whatever else you can think of.
There are commands for features that are currently not exposed in the Open Brush UI such as resizing strokes and adding points to existing strokes. The example scripts should give you plenty of ideas.
Yep. All you need to do is to create a text file called "startup.sketchscript"
Make sure the file extension is .sketchscript and not .txt
Place this file in your Open Brush folder inside your user documents folder. It should go into the "Scripts" subfolder in your Open Brush folder
(Usually in C:\Users[your user name]\Documents\Open Brush - This folder is created automatically the first time you launch the API build but you can create it yourself as well)
Each line in this file is a single command that Open Brush will run when you open it. For example:
This will load a sketch from your Sketch folder called "startup.tilt", switch to fly tool and turn on "viewonly" mode which disables all the panels. If you want to try this you can either rename one of your sketches to "startup.tilt" or you can change the first line in the script above. As long as the first line matches the name of a file in your Sketches folder then it should work.
If you want to distribute a sketch without people having access to the original .tilt file then you could change this slightly. Instead of loading a sketch, load an exported version of your sketch. For example, export your sketch and rename it to mysketch.glb. Place it in your Media Libary/Models folder and use this startup script:
Voila - a way to let people fly around your sketches without being able to modify them.
There are two new settings you can change in your main Open Brush.cfg Both belong in the "flags" section of the config file
Defaults:
These two settings are for security and default to "false" but you may want to set them both to "true" if you want to control Open Brush remotely.
You should do this if you're on a private network. Disable it or configure a firewall to restrict access to known devices if you plan to use Open Brush on public Wifi such as at an event or show.
EnableApiRemoteCalls - by default the API only accept commands from the same machine that is running Open Brush. Set this to true to allow API commands to be sent from other computers. In most cases this will only be machines on the same local network. You will need to configure your router to accept connections on port 40074 if you want to accept commands from remote devices as well. Apps such as ngrok or localtunnel can make this simpler to set up.
EnableApiCorsHeaders: By default browsers are blocked from sending commands via javascript to another domain. Setting this to true will relax that restriction.
See Monoscopic mode
Monoscopic mode is a bit tricky to get the hang of but for using it as a quick way to experiment with the API then all you really need to know is how to pan the camera to look in different directions.
Just hold down Alt (Cmd on a Mac) and drag your mouse in the viewport.
Currently there's no controls to move the camera but we plan to add this in soon.
A few other notes on monoscopic mode:
Left click and drag to draw on the drawing plane (the grid shown in front of you)
Dragging with the right button down will bring the drawing plane nearer or further.
Ctrl+mouse will rotate the drawing plane
Clicking in the game window will capture your mouse cursor.
Just type a command into the address bar of your browser whilst running one of the builds you've downloaded from this page.
You can also add html files to your Scripts folder. These can have standard form elements for input and some simple javascript to send commands based on those chosen values to Open Brush.
Check out the simple form examples included: http://localhost:40074/examplescripts
Visit http://localhost:40074/help while you've got the custom Open Brush running to access the help.
A full list of commands can be viewed by going to http://localhost:40074/help/commands
Each command has a "try it" link that will open a new browser tab with an example of the command in the address bar.
If you want to view commands when Open Brush isn't running: API Commands List (not neccesarily as up to date as the list you get directly from the app)
The help has got some example scripts to look at.
Here's a simple piece of code to send a single command:
Any language that can send http requests should work.
Currently the brush 'cursor' (or the 'turtle' if you want to think of this as a kind of LOGO system) doesn't store it's full rotation - only it's bearing.
With a custom build running you can visit:
and follow links to useful info such as a full list of commands, examples scripts etc
This page has been update to reflect changes in the current beta version. Sketch Viewer mode is a new feature and Monoscopic Mode was previously only available as a separate download.
If you launch Open Brush without a headset attached (platforms where we don't currently have VR support), the app will start in "Sketch Viewer Mode" where you can load any of the available sketches and navigate around with the keyboard and mouse or the touchscreen.
Use the mouse or touch to look around
Press I to invert up/down
W,A,S,D: move forward/back/left/right
Q,E: move up/down
Hold shift to move faster
On touchscreen devices there are onscreen buttons to emulate W, A, S and D.
If you do have a VR headset attached you can still access Sketch Viewer Mode by adding a "DisableXrMode" entry to your Open Brush config file in the "Flags" section and setting it to true. For example:
You can return to normal either by removing the entry or by setting it to false.
Open Brush has got a secret mode where it can be used without a VR headset - and even works on Mac! This mode was never released to the public and is clunky in places.
It also works very nicely when using Open Brush via the API allowing you to control Open Brush from a web browser.
You can access Monoscopic mode by adding a "EnableMonoscopicMode" entry to your Open Brush config file in the "Flags" section and setting it to true. For example:
You can return to normal either by removing the entry or by setting it to false.
Alt+mousing will rotate your viewpoint.
Panels become focused when roughly centered in your view. Your cursor is then locked to the panel boundary making it easier to click the buttons.
Dragging with the right button down will bring the drawing plane nearer or further.
Ctrl+mouse drag will rotate the drawing plane
Clicking in the game window will capture your mouse cursor. Escape will return full control (so you can interact with Unity etc)
In most cases you can alt+mouse to left or right to view the tool panels and choose tools/brushes with the mouse.
Rotating with “Alt” whilst pressing shift will allow you to move the panel you were currently focused on.
Sometimes panels appear in weird places. Try looking behind you or down at your feet.
The file Scripts/InputManager.cs lists all the keyboard controls. Also see Open Brush: Keyboard Controls and VR Input However many aren’t relevant, aren’t implemented or only apply in particular modes. The more useful ones are listed below.
Action
Shortcut
Notes
LockToHead
LeftShift
Use with Alt. Can move panels with this.
PivotRotation
LeftControl
Use with Alt
Scale
Tab
Only when not drawing. Hold tab and move mouse up or down to scale tool
Reset
Space
Resets the UI not the sketch
Undo
Z
Redo
X
SaveNew
S
ExportAll
A
ViewOnly
H
Doesn't disable drawing. Just hidesUI
PreviousTool
LeftArrow
5 tools are available: sketch surface, brush selection, color selection, BrushNColor, Erase
NextTool
RightArrow
CycleSymmetryMode
F2
Export
E
StoreHeadTransform
O
Use with Right Shift
RecallHeadTransform
O
(without Right Shift)
ResetScene
Return
Doesn't delete sketch
StraightEdge
CapsLock
Buggy
Save
S
PositionMonoCamera
Alt
Draws a circle centered on the position you first press the trigger with the radius and orientation controlled by where you release the trigger.
Similar to Circle except it creates a camera path instead of a brush stroke
Sides: The circle is approximated by a polygon. This controls the number of sides.
Draws a cube centered on the position you first press the trigger with the size and orientation controlled by where you release the trigger.
Point Spacing: The distance between control points for the strokes that make up the cube
Inset Amount: How much to inset each face towards it's center
Draws tiles that follow a hilly landscape as you hold the trigger.
Scale: The scale of the landscape. Smaller values make hills and valleys closer together
Height: The height of the landscape (Controls the vertical scaling)
Offset: The distance from the floor to position the landscape
Grid Size: The size of the grid used. Bigger values are more "low poly"
Calls an API to generate a random SVG icon using the MultiAvatar library
Calls an API to generate a random SVG icon using the Iconify library
Draws lines from the position you start drawing to your current position.
Spacing: How often to draw a new stroke
(Currently removed while I fix a bug)
Instantly draws a brush stroke based on the path of the last brush stroke you drew
Switches to the Hull Brush and draws cubes of random size and color as you move your brush",
Maximum Size: Controls how big the cubes can be
Spread: Larger values allow cubes to be placed further from your brush position
Amount: 0.5 gives a random 50/50 chance of creating a new cube each frame. Smaller values produce less cubes, larger values more.
Draws a conical spiral.
Number of turns:
Number of steps per turn:
Draws a spherical spiral.
Steps:
Turns:
Draws a superellipse.
n:
Draws a supershape using the Super Formula
Symmetry:
n1:
n2:
n3:
Draws a heart shape using an SVG Path
Point Spacing:
Draws a blocky landscape (best used with a hull brush).
Horizontal Spacing:
Verticle Spacing:
Draws regular blocks in space as you draw (best used with the hull brush)
Grid Size:
Draws words that follows your brush. Tries to access the clipboard so try copying in some text.
Size:
Spacing:
THIS BRANCH HAS BEEN SUPERCEDED BY A NEW COMPLETELY WRITTEN VERSION WITH MANY MORE FEATURES
See the new 3D Shapes feature instead!
Oculus PC VR (Rift, Quest via Link cable...)
SteamVR (Vive, Index, Reverb...)
Other Builds (Non-VR, Linux, Mac...)
Mainly two related things:
Adds a polyhedra tool that can create a wide variety of polyhedra and grid patterns using brush strokes
Adds a custom symmetry tool similar to the existing mirror except it creates multiple strokes for each face of your selected polyhedra or grid
Creating regular patterns and geometry forms.
Download a build for your headset from the link above and unzip it. You can run the Windows exe directly. To install the Quest apk use SideQuest: https://uploadvr.com/sideloading-quest-how-to/
Switch out of beginner mode and you'll see the "Experimental Tools" panel on your wand.
There is a new icon at the bottom that looks like a wireframe cube. Click that to activate the polyhedra tool.
Draw a cube with your brush hand. Click once to start and release when you're happy with the size and rotation.
The "A" button or trackpad left click will cycle through various snapping angles. Try setting it to 90 to draw shapes level with the ground plane
The panel that opens when you first clicked the button let's you select various shape.
If you want to change the default colours simply add some custom colours at the bottom of the standard colour picker panel.
There's nothing to stop you creating extremely complex shapes that might slow everything down
There's currently no colour controls but you can use the standard recolor tool on your shapes.
Snapping is a bit unpredictable sometimesree paint mode. You need to select the polyhedra tool every time you change brushes.
Scene scale and brush size interact in a slightly confusing way.
The button is on the bottom right of the Experimental tools panel. Use the same panel you used with the polyhedra tool to change the shape that controls the symmetry strokes.
The symmetry mode only affects normal paint strokes. You can't currently use symmetry to create multiple copies of the polyhedra tool.
You can grab the symmetry widget and change it's position and orientation.
It's possible to create very complex sketches very quickly.
There's no control over the color variation of the symmetry strokes.
You can't scale the grids. Instead scale your scene
I haven't added any way to control the colours of the additional strokes yet.
Come over to the Open Brush Discord: https://discord.com/invite/fS69VdFXpk and chat to me ( andybak#5425 ).
I'm on UK time (currently UTC+1) but I check in fairly regularly.
Here's an earlier version of the polyhedra tool:
Here's a video with terrible audio showing the symmetry tool:
and another without any audio:
Yeah. I really need to do better videos. Please share anything you make that I can use to show off the features.
Tutorials and Write ups for Modifying Tilt Brush:
Customising Tilt Brush - Part Two: Adding Flight (nb the "Flight" feature itself is now included in the main release but the tutorial is still useful as a guide for adding your own features)
Spreadsheets with some useful info:
It’s often quicker while developing to avoid jumping in and out of VR. Monoscopic mode is very useful for this.
Under "Flags" set EnableMonoscopicMode to true in your Open Brush Config file
Sometimes panels are placed over other panels. To move a panel hold shift at the same time as holding Alt to rotate the viewpoint (see below)
Entering play mode should now allow you to draw and control the app using the mouse and keyboard.
You can learn more about using Open Brush without a headset
Important note: Unity serializes enums as ints. Therefore if you change the order of enums then any scene or asset with a reference to them will suddenly point at the wrong entry.
This is especially a problem when merging branches. If you’re working on a feature that you will eventually want to merge with another branch you want to ensure that your enum values don’t change when the files are merged.
The best way to do this is to explicitly number your enums
Now the only problem is to ensure you use numbers that other branches haven’t already used. We’ve settled on a simple low tech solution for now. Just go to this Google Sheet and reserve a block of 1000: Open Brush enum reservations****
SketchControlsScript.GlobalCommands: Commands are actions that (usually) record Undo state.
BasePanel.PanelType: Panels are the persistent UI elements (as opposed to popups which tend to be transitory)
BaseTool.ToolType: “Tools” are usually modal states that determine what actions happen when you use the controls on your main controller (the “brush” controller)
PointerManager.SymmetryMode: The only symmetry mode enabled by default is the normal mirror. But there is a double mirror hidden behind the experimental flag and a “debug” symmetry mode that can only be enabled via code.
Add an entry to BasePanel.PanelType (see the note above about enums clashing)
If you think you’ll need custom functionality in the Panel class itself then create a new class inheriting from BasePanel:
Otherwise you can just use BasePanel directly in the next step.
It's easiest to copy an existing panel prefab (from Prefabs\Panels). If it's using a subclass of BasePanel different to yours, then change the script type for the panel (neat trick to swap scripts on existing components here: https://answers.unity.com/questions/1125244/what-happened-to-conveniently-replacing-component.html )
Ensure your component’s PanelType is set to the value you added to BasePanel.PanelType
Change the Panel Description field for your new panel to something relevant.
In the main scene under SketchControls add an entry to the Panel Map (on the Panel Manager component). Choose the same PanelType as before. (note that the list item will have the wrong panel - or just a number - next to it if you used your own explicit enum value. This doesn’t seem to matter)
Opening the new Panel:
Either:
Add a button to an existing panel. The button should use the PanelButton component (or copy an existing one) or...
Tick “Begin Fixed” on the new panel component itself.
Question - what controls how close a panel is allowed to get to another panel on the wand?
Answer - BasePanel.m_WandAttachHalfHeight
Panels script components have a m_PanelPopUpMap property which connects a GlobalCommand to a popup prefab. Having to add a GlobalCommand for every popup type is a bit tedious. I need to figure out how to open a popup without needing a GlobalCommand
Create a subclass of PopUpWindow if you need one (or just use OptionsPopUpWindow)
Copy the structure of an existing popup prefab substituting your popupwindow class
Add a button to a panel to open your popup. It should be an OptionButton or a subclass thereof.
Add a command to the GlobalCommand enum to handle opening your popup
The OptionButton should have it’s command set to the new command
Tick “requires popup” on the buttonscript
Edit the m_PanelPopUpMap property on the panel prefab root that references the command and the popup prefab
CreatePopup calls SetPopupCommandParameters on the popup and passes in iCommandParam and iCommandParam2 (usually from the OptionButton used to open the popup). So override this method to handle the parameters how you want.
See the MenuPopUpWindow subclass for an example.
Create a class that inherits from BaseSlider
Go to BackdropPanel prefab and copy FogDensitySlider
Paste into the panel prefab you want to use it in
Change FogDensitySlider to use the class you created in #1(use method found at minute 18 here Found here (https://youtu.be/HjsLzyNNxuM)
Create a custom command for editing the value the slider represents. See ModifyFogCommand for an example.
Use your new command to change the underlying value that the slider represents. This is typically done in OnPositionSliderNobUpdate and EndModifyCommand.
Test and make sure your slider correctly changes the underlying value
Register for events that get triggered if some other piece of code modifies your underlying value. In this case, we need to know about it so that we can update where the slider tick is located. If the event does not already exist, you may have to create a new event. One possible appropriate place is in Switchboard.cs
These are typically known as "stencils" in code but prefab names may still use the term "guide".
Key Classes involved
StencilWidget -> GrabWidget
WidgetManager
SketchControlScript
Creating a new Stencil / Guide
Make a copy of one of the stencil prefabs and rename it for your shape. The sphere is the easiest to work with in many cases.
Add your shape name to the end of the StencilType Enum in WidgetManager.cs. You may need to follow the recommendations about Enums.
Add your prefab and shape type (Enum) to the WidgetManager Stencil Map in the inspector.
Make a duplicate of the stencil script you used in #1 and rename it myNameStencil.cs
Replace the stencil script on your prefab to use the one you just created.
Open the GuideToolsPanel in Assets/Prefabs/Panels, duplicate one of the buttons and position it appropriately in the panel.
In the StencilButton component change the Description Text and Button Texture to something appropriate for your shape and change the type to your stencil type.
Question: What determines the distance at which the pointer will snap to the guide?
Answer: WidgetManager.m_StencilAttractDist. The code does this in WidgetManager.MagnetizeToStencils.
Question: How do you enable a stencil to be scaled non-uniformly (i.e. along a particular axis)?
Answer: See SketchControlScript.UpdateGrab_ContinuesTwoHands and implement GetScaleAxis and RecordAndApplyScaleToAxis.
(Also see Open Brush: Panels, Popups and UI Classes)
ActionButton : BaseButton Triggers a UnityEvent assigned in the inspector.
ActionToggleButton : ActionButton
Triggers a UnityEvent and maintains on/off state
ConfirmationButton : BaseButton
Used in popups. Calls ResolveDelayedButtonCommand on the parent panel and sends true/false depending on the property set in the inspector
LongPressButton : OptionButton
OptionButton that opens a popup when long pressed.
LongPressToolButton : LongPressButton
(not used) Extends LongPressButton and adds tool activation
ModeButton : BaseButton
Not used directly but is the base class for Gallery PolySet and Reference buttons
MultistateButton : BaseButton
Cycle through multiple states on each click. Calls a GlobalCommand with the index of the current option
NavButton : BaseButton
Navigates between pages in paged panels and popups.
OptionButton : BaseButton
Optionally calls a GlobalCommands and passes in two parameters assigned in the inspector. Optionally opens a popup set via the PopupMap on the parent Panel script. Optionally toggles between two states.
PanelButton : BaseButton
Toggles visibility of a panel (BasePanel.PanelType)
PropertyToggleButton : BaseButton
Allows the button to be connected to a bool property on a component, and automatically reflect its value as well as toggling its value when the button in pressed.
Layers.ToggleButton : BaseButton
Performs no action but maintains on/off state
ToggleButton : OptionButton
Invokes a UnityAction and also maintains on/off state.
ToolAndPanelButton : BaseButton
Combines ToolButton and PanelButton functionality
ToolButton : BaseButton
Activates a tool (BaseTool.ToolType)
By @moat
For the input system there's this one scene Gameobject called a SketchControls:
This whole chungus of a gameobject sits in the scene and it's got like, nearly every bit of UI and management and widgety stuff.
It's like the player is already instantiated within the game to start with when you load the Main scene. There's a gameobject called the PointerManager:
This thing manages up to 10 cursors at once (although it can be set to handle more):
Brushes are attached to cursors, and when you do anything with your controllers, it drives the Main Pointer Prefab.
The reason they have multiple cursors is for things like multibrushes that make multiple brushstrokes appear simultaneously when you drag out a stroke
Pretty much every tool you switch between is sitting on a script within one of these gameobjects parented to SketchSurface:
When you switch tools, it activates one of these objects and deactivates the others
Much of the magic occurs within the FreePaintTool
It's the star of the show, being the thing that makes happy little trees appear and happy little clouds.
What most tools have in common is UpdateTool()
This is like their main interaction loop. At the start, the inputmanager states are captured into variables to be used throughout the rest of the update loop:
(rather than re-calling the same inputmanager functions again and again and again)
The Wand is your non-dominant hand, the Brush is your dominant hand controller and performing the controller-tap gesture (lightly tapping the handles together) will swap these controllers.
This BrushTrigger bit handles the actual trigger press:
m_brushTrigger is just a boolean that becomes TRUE when the trigger is pressed beyond the threshold while the BrushTriggerDown variable becomes true only during the update tic when the trigger has been pressed and brushTriggerRatio is a value mapped from 0->1 depending on how far that analog trigger has been pulled.
ReferencePanel.cs is the media library script.
LocalModelButton has got a method RequestModelPreloadInternal but it isn’t called on the local media panel - only on the Poly panel. If we want to make local media behave more like the the Poly panel then we should go through PolyPanel RefreshPage to understand what it's doing and take the relevant parts and add them to ModelPanel RefreshPage.
The code that does the actual work is in models.cs. A typical call stack goes:
This presupposes you’ve instantiated model class. An example instantiation might look something like:
Once you have a valid model you need to spawn it into the scene. Look at SpawnValidModel in ModelButton.cs
Example code to synchronously load a model:
Note - only tested on local models. The filename is appended to Media Library/models
Currently several formats are hidden behind ifdefs for various platform flags and the experimental flag. The logic is a bit tortuous so here’s a pseudocode version:
If you want to add a new export format then add your script to Scripts/Export and modify the big set of if statements in ExportScene in Exports.cs. You’ll also want to add a pair of progress.SetWork and progress.CompleteWork calls to update the progress UI.
Currently strokes are grouped by brush type when exported to other formats. People have asked in the past to also group by color AND brush type. @1pld offered the following solution:
You need to convince Open Brush to split things out by color as well as by brush. It's not that tricky a change if you can modify the code (or can get someone to modify it for you). This compiles but I haven't tested it
And also
Taken from the following comment: https://discord.com/channels/783806589991780412/806934697237938216/820958273032683520
By @andybak
I've written code to procedurally generate strokes in two places with some subtle differences that prevents me from combining them into a single utility method just yet.
The gist of it all is basically:
Create an array of control points
Create a Stroke using those points
Call stroke.Recreate and pass in App.Scene.ActiveCanvas or similar
MemoryListAdd
PerformAndRecordCommand BrushStrokeCommand
That whole shebang seems necessary to ensure that undo and saving work correctly.
I think MemoryListAdd was needed for save/loading to work and PerformAndRecordCommand was needed for Undo… The sketch memory list is what gets saved into .tilt files for brush strokes. The undo stuff handles more than just brush strokes. The undo log knows about (most) user actions and what code to call to reverse/redo them.
Stroke.Recreate seems to create the batch object and mesh - but that's not enough for "real" brush strokes.
Recreate (eventually) calls FinalizeBatchedBrush on the correct BrushScript. These overridden methods are what actually does the mesh creation.
In Open Brush, almost everything we do is done with the help of tools. A tool can be something like the Straight Line tool, which applies a modifier to any new brushes created with the Free Paint tool, or it can be something like the Teleport tool, which moves the player. At the end of the day, a tool is simply a way for us to run some code in a nice compartmentalized way.
In essence they are usually modal states that determine what actions happen when you use the controls on your main controller (the “brush” controller).
(based on Lachan's Tutorial )
Open Assets/Prefabs/Panels folder. Find “AdvancedToolsPanel” and open it
(If you want to build for Quest, you’ll also need to perform the following operations on the “AdvancedToolsPanel_Mobile” prefab)
Duplicate one of the other Tool buttons to create a new button. (Note that the mirror and straight edge buttons are not tool buttons)
Name your new button object “Button_Foo”
Make sure that it’s right underneath the “Button_Straightedge” object at the same level in the hierarchy.
Change the Description Text to read “Fly”
Make a 128x128 black and white image to use as the button texture. Place this image in the Assets/Resources/Icons folder and name it “foo.png”.
Drag it on to the “Button Texture” property of your new button object.
In Assets/Scripts/Tools/BaseTool.cs find the ToolType enum and add a new line to the bottom:
Go back to our component and select “Foo Tool” as the tool type for our button. Save the prefab.
In the main scene find the object SketchSurface which is a child of SketchControls.
Add a new empty child to this object
Give it a scale of (0.5, 0.5, 0.5) and call it FooTool placing it just above the EmptyTool object.
Place all the visual content as children of an empty ‘DirectionIndicator’ object which is a child of our tool.
Deactivate the new tool
Create a new script in Assets/Scripts/Tools and call it FooTool.cs. Use the template script [link]
Add this new component to our FlyTool object in the scene, ensure that that tool type is set to FooTool
In Assets/Scripts/InputManager.cs look for the SketchCommands enum. Add “Fly” at the bottom
Scroll down in InputManager to the GetCommand function. We need to pass the command through to the Brush
Update the function to look like this (note lines 37 and 38):
Find the Brush.GetCommand function in the file Assets/Scripts/Input/ControllerInfo.cs and update it (note lines 27 and 28)
Press play.
(this section of the docs is a work in progress)
Places to look:
Controller Material Catalog component on the App object in the main scene (contains all the materials used for adding custom buttons to the controller model)
AssignControllerMaterials method on BaseTool subclasses. This often calls methods on ControllerGeometry.cs which in turn typically does something like:
by @1pld
For stroke/control point extension data, I'd propose adding a level of indirection (the solution for everything). If a .tilt appends data to strokes or points, it should come with some extra self-describing data in the .tilt. So rather than this:
you'd have something like "the stroke sets extension bit 16; the client looks in the sketch metadata to find out what stroke extension 16 is. It has a mime type / guid / whatever. The client determines it doesn't know what to do with that data so it throws it away, which it can because that data chunk is in length+data format" or "all stroke extensions 16 and above are now defined to be length + guid + <length - sizeof(guid)> bytes. The client determines whether it understands the data based on the guid etc".
by @1pld
Re some comments I've seen elsewhere, it would be good to document the coordinate systems Tilt Brush uses and how they're reflected in the scene graph. Super quick notes on this:
"room space" = the user's physical environment. some people call this "tracking space"
"scene space" = the user's virtual environment -- the square panel on the ground, the mountains in the distance, etc.
"canvas space" = the user's artwork. Typically there's just a single Canvas whose pose is the same as the Scene pose (it's a direct child of the scene, with identity localTransform). But when you have a selection or groups, those are additional Canvas instances
the root of unity's scene graph we call "global space" (we try to avoid the term "world space" in the code because "world" is ambiguous). "global space" == "room space". The Scene is a child in global space, and canvas is a child of scene
That is backwards from what some people expect, which is for "room space" to be a child of "virtual space".
_CS, _SS, _GS, _RS suffixes all denote those spaces.
I would look at the rebrush tool (the one that's like recolor, but changes brushes). That takes an existing set of control points and regenerates the geometry.
More specifically, take a look at Stroke.cs and the various functions in there like Recreate. The general idea is you should be able to dump a bunch of control points into a Stroke, call Recreate, and you've got geometry. The API hasn't gotten as simple as I'd like, you still have to worry a bit about the various intrusive linked lists that strokes get put into when you draw "normally" (or on load), but it shouldn't be too bad
The guts of that are how I'd do it if you want something up and running quickly -- it's a good demonstration of how to generate knot information, pipe it to the right place, get a proper stroke back out. See ParametricStrokeCreator.cs
ParentBrush might also be interesting to you... but it violates some assumptions and doesn't play nicely with save/load, undo/redo etc. There's some notes about how to move forward from that in the file
The playback code might be another entry point, if you want to make more than one stroke (i.e. fill a volume with strokes). You could boot up the playback system pretend you're loading a file (but instead, you're generating the control points programmatically) The playback system has a mode that is more "real time", where stroke timestamps are allowed to overlap, multiple strokes can draw in at once and will draw in at the speed they were painted, etc. Might have bitrotted a bit, but might be a useful entry point for understanding the drawing system
One kind of annoying thing that we never fixed is that there are only 4 (or maybe 8) global pointers, and everyone just kind of hardcodes the index of the one they want to use. So the 4-way mirror will use pointers 0-3, the load code assumes it can use any of them, etc. That's as opposed to people instantiating as many pointers as they need concurrent lines, doing stuff with them, throwing them away
Ideally you wouldn't need a "pointer" at all in order to draw lines. Anyway, something to watch out for if you want procedural stuff happening at the same time the user's painting.
The guide system could use a SDF based mode so guides could interact with each other, have smooth joins, etc; rather than you getting stuck to one at a time. Man, that would be great.
(Another time Paul said “Look at basebrushscript.cs and the method Stroke.Recreate” - the latter is mentioned above.)
How to programmatically generate a mesh in such a way that it will correctly save and load back in a .tilt file?
TB files only save references to meshes (eg, Poly asset ids, paths to imported fbx or obj files, etc). Currently the only way to put geometry in a tilt file is to add brush strokes to it.
How to modify meshes from either Blocks or Poly that are embedded in a sketch?
Poly assets are immutable, so if a .tilt has a reference to a poly object, a tilt file that references it can guarantee that it will always look the same.
How to fix the undo/save behaviour of experimental brushes using “ParentBrush”?
See the giant comment at the top of ParentBrush :) Consider ParentBrush proof-of-concept that needs a week-ish of design thinking and implementation work to turn into something ready for prime time
How to add parameters to brushes. The sheer number of brushes might become too many and many brushes are simple variants of each other. A UI to allow brush parameters to define variants would help address this.
How to visualize/manipulate stroke knots?
For the most part the knots aren’t that interesting; but in a pinch you could try taking a stroke, switching its brush to a spray brush (which lays down one quad per control point) and calling stroke.Recreate(). For bonus points you could create a SprayBrush variant that drops down little coordinate axes instead of quads.
How to see the console log in a live VR session?
By @1pld
If you have a global transform we have a helper: App.ActiveCanvas.AsCanvas[your transform component] = your canvas-relative transform This works no matter where the transform component is in the hierarchy
(various nuggets extracted from drive-by comments that Paul made on the Discord)
Knot is a control point with some more data glommed on; it's a term that geometrybrush invented
Do you need to manually record strokes to memory after using DetachStroke?
You do. The intent is that Recreate doesn't interact at all with "memory" (the two linked lists of strokes, ordered by time of first and time of last control poin t). Recreate, uncreate, etc only affect the stroke geometry. They take it from the state "no geo" to "with geo", or from "with geo" to "with different geo", but shouldn't interact with any higher-level considerations like memory
There may be assumptions that you're calling it on a stroke that's in the linked lists already, so maybe that explains some of the strange behavior you're seeing.. but if you want to memorize a stroke I'm almost certain you should do it yourself; don't count on recreate to do it for you
1pld
Historically, things started with QuadStripBrush, with a couple variants based on how UVs were generated. It just generates strips, 6 unique verts per tri (3 for top, 3 for bottom, backface culled). Then there was a variant that produced isolated quads (for brushes like "leaves") instead of strips. QuadStripBrush uses a class called MasterBrush to temporarily store and work on the geometry before it's finalized into a mesh / batch. Then I wrote GeometryBrush to "reboot" geometry generation and enable other kinds of topology. The intent was that QuadStripBrush-based brushes would migrate to FlatGeometryBrush, but the way that QuadStripBrush did its smoothing was not easy to replicate (the details aren't important but the incremental algorithm QSB uses means that each knot doesn't have "local support" in the technical sense, and GeometryBrush in part was written to force people to use knots with local or at least bounded support for efficiency reasons). So FlatGeometryBrush isn't used much. Most other brushes are derived from GeometryBrush. GeometryBrush is notable for using a different storage scheme for intermediate geometry called "GeometryPool". This is used all over the place, wherever we want to process mesh data in C# (eg: geometry generation, multiplying geometry by a TrTransform, export). Some of these manipulations have native-code versions that MachWerx wrote in C++; I think we ship that DLL in the repo. The GeometryBrush variant of the old "isolated quad" brushes is SprayBrush, and I think the old version of that doesn't exist in the code any more. GeniusParticlesBrush is I think Xap's very first work on the project and replaced an older less genius way of particle brushes. TubeBrush was our first volumetric brush; it's also slightly notable for using a different method of curve framing. Instead of BaseBrushScript.ComputeSurfaceFrameNew, it uses parallel transport Dark Jeremy wrote HullBrush and that made the concept of "Knot" kind of weird.
ParentBrush was an experiment That's the major ones
I don't work for Google any more, but I don't think any kind of wholesale export of the bug db would be allowed. Happy to expand on any TODOs that I still understand though
Backwards compatibility is a very real issue in the code; we took a very hard line and very seldom swapped in completely new implementations for a brush guid. Mostly when we wanted to fix or upgrade the behavior of brushes, we'd create an entirely new guid and leave the old one around for compat.
I think monoscopic mode is a prime area for improvement! A lot of people would benefit
Anything is possible, but the main reason I wrote abstractions like Stroke.Recreate and so on is because I found it hard to keep track of all the contortions with pointers, pointer managers, input, and so on :). I know I traced through the whole path from input to geometry many many times over the course of the project; it's useful to do. From memory I can sketch it out at a very high level: input comes in from a user, makes its way to a pointer. The pointer deals with creating/finalizing BaseBrushScript instances. The pointer also deals with remembering which control points were used. This is a little gross though; see UpdateLineFromObject. The pointer assumes that the BBS will use a piece of input, and it's up to the BBS to tell it "I used new input to over-write the last quad/whatever" or "I used your input to create an all-new quad", which has implications for which control points the pointer keeps around. Lots of potential for off-by-one errors and so on. Eventually the user lets go of the trigger, the PointerScript terminates the line, deals with off-by-one issues in its control point array, arranges for the geometry in the brush to be finalized into a GameObject/batch, for the control points to be finalized into a stroke, puts the stroke into the memory, and so on
Or we could be loading from a file, in which case the work is substantially similar. We reuse PointerScript to load from files and kind of trick it into thinking that it's being driven from a user; but there are hacks to ensure that the BaseBrushScript doesn't reject any control points coming in. And there are some other hacks to allow brushes to try to process a whole batch of control point input at once instead of one-at-a-time. This was one of the main motivations for GeometryBrush; a brush should 1. not do O(n) work for each new control point, and 2. be able to process a group of control points at once instead of doing O(n) updates
Updating "stretch" UVs is obviously always going to be O(n) so there are some other hacks to defer that generation until "update visuals" gets called. Maybe some other things. Anyway, there are mechanisms to prevent O(n^2) behavior on load. Similarly, you wouldn't want your hull brush to compute a hull N times when loading. Something to think about when writing a geometry generator.
The batch manager was written because "1 gameobject per stroke" is obvs not scalable. So it's a way of taking a bunch of tiny meshes, all of the same material, and grouping them into larger meshes. The tiny meshes become a "BatchSubset" within a larger mesh "Batch", and a single material ("BatchPool") will have multiple meshes ("Batches") and the whole thing is orchestrated by BatchManager
Some thoughts on @andybak 's comment about "let a thousand brushes bloom". Tilt Brush didn't have a well-defined notion of what should happen when loading a .tilt containing an unknown brush guid. It would warn about it, and end up ignoring the strokes using that brush (see: SaveLoadScript.GetForceSupersededBy which ignores the problem when loading from disk, and StrokePlayback.BaseInit for where that warning is eventually surfaced quite late in the load process, after a stroke creation has already failed). It got away with that because by construction (and by control of the ecosystem) that error was prevented for the most part. In this new ecosystem where "unknown brush" is going to be much more likely, regardless of the strategy chosen for blooming 1000 brushes, I think it's worthwhile replacing the current behavior with something a little more friendly to both producers and consumers of .tilt files. So a sketch of a proposal: - At a minimum, guarantee that loading then saving a .tilt containing an unknown brush preserves strokes using that brush - Embed some "fallback brush" data in the .tilt's brush index, so clients can at least show something reasonable. eg, if a client knows that the missing brush is a quadstrip, tube, spray (ie, disconnected quads), volume (ie, some kind of hull), particles, or "other", that's enough info to substitute in some generic-looking placeholder brush.
There could be a similar discussion around the forward-compatible extension points built into the per-stroke and per-control-point data. Currently there can only be 32 kinds of extension data (as opposed to basically infinite brushes), which doesn't seem like enough for an ecosystem. Plus, you'd need someone to control a registry to dole out pieces of that very tiny namespace. On the other hand, it's not like people are clamoring to add new kinds of data to strokes or control points (... yet)
andybakToday at 9:03 PM
So we do need some taxonomy for brush behaviour that can be relied on universally. i guess that could be based on historic baseline of brushes released before we went brush crazy.
1pldToday at 9:04 PM
Yeah, I think we have enough data to have a rough taxonomy; and if some .tilt used an unknown taxonomy for an unknown brush, a client could then choose to ignore it, or substitute in whatever they chose
My initial taxonomy would be: ribbon, tube, hull, spray, particles, and "do not substitute"
andybakToday at 9:11 PM
why not have the entire original brushset as potential fallbacks?
we could have the smaller taxonomy to help partial implementations - but any proper client app should at least support the original set of brushes that are already out there.
1pldToday at 9:17 PM
Totally; the fallback could be specified as a guid too. I thought that a higher-level approach might be easier for brush authors -- it's the difference between an extra kind-of-inscrutable guid field in the brush descriptor, vs a dropdown saying "brush type"