# Home

**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 ](https://discord.gg/W7NCEYnEfy)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.


# How to get Open Brush

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 ](/alternate-and-experimental-builds)that are available

## PC

[Steam](https://store.steampowered.com/app/1634870/Open_Brush/)\
[Oculus Store](https://www.oculus.com/experiences/rift/5227489953989768/)\
[Viveport](https://www.viveport.com/f1f3d00b-cf8a-443f-825e-4fea2dd3b005)\
[Itch.io](https://openbrush.itch.io/openbrush)

## Oculus Quest

[Oculus Applab](https://www.oculus.com/experiences/quest/3600360710032222/)\
[SideQuest](https://sidequestvr.com/app/2852/open-brush)\
[Itch.io](https://openbrush.itch.io/openbrush)

## Linux

[Itch.io](https://openbrush.itch.io/openbrush)

## Mac

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](/user-guide/monoscopic-mode).


# Differences between Open Brush and Tilt Brush

## Features Added to Open Brush

This section only lists features currently in the main release. There is also a [beta version ](/alternate-and-experimental-builds/open-brush-beta-docs)with new features. There's also plenty more stuff in [experimental and alternate builds](/alternate-and-experimental-builds).

### Scripting & Extensibility

* [Plugin Scripting](/user-guide/using-plugins) - Create custom tools and modify painting behavior with Lua scripts
* [Scripting API](/user-guide/open-brush-api) - WebSocket and HTTP API support

### Import & Export

* [VOX File Import](/release-history/v2.29#vox-file-import) - Import Magicavoxel .vox format files
* [Open Blocks Model Import](/release-history/v2.29#import-open-blocks-models) - Import models from the sibling app Open Blocks
* [New GLTF Importer](/user-guide/importing-images-videos-3d-models) - Based on GLTFast with support for animated 3D models
* [SVG Import](/user-guide/importing-images-videos-3d-models) - Import SVG files as images or 3D meshes
* [Point Cloud Import](/user-guide/importing-images-videos-3d-models#point-cloud-import)
* [360 Panorama Backgrounds](/release-history/v2.4-prismatic#360-panorama-background-import) - Import jpeg, png, and HDR panoramas (including stereoscopic)
* [WebM Video Import](/user-guide/importing-images-videos-3d-models#webm-video-import)
* [LATK export](https://lightningartist.org)
* [Folder Navigation UI](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/folder-navigation.md) - Better organization of imported media
* [Splitting 3D Models](/release-history/v2.29#splitting-3d-models) - Break apart imported models into separate components

### Painting & Drawing Tools

* [Lazy Input](/user-guide/lazy-input)
* [Jitter](/user-guide/repaint-tool#jitter)
* [Repaint Tool](/user-guide/repaint-tool) - Change brush type, color, or size of existing strokes
* [Repaint Selection](/user-guide/repaint-tool#repaint-selection) - Apply repaint tools to all selected strokes
* [Multi-Mirror](/user-guide/multimirror) - Dozens of symmetry types with color variance control
* [Bimanual Input](/user-guide/bimanual-input-and-revolver#bimanual-input)
* [The Revolver](/user-guide/bimanual-input-and-revolver#revolver)
* [Passthrough Hull Brush](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/platform-and-device-support.md#passthrough-hull-brush) - Paint with passthrough effects
* [Experimental Brushes](/user-guide/experimental-mode)
* [Logitech MX Ink Integration](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/logitech-mx-ink.md) - Support for Logitech MX Ink stylus

### Guides & Snapping

* [Grid and Angle Snapping](/user-guide/grid-and-angle-snapping)
* [Enhanced Snap Settings](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/snap-settings-panel#enhanced-snap-settings) - Snap axis toggles, snap to guides, snap selected objects
* [Guide Settings & Snapping to Guides](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/snap-settings-panel#snap-to-guides)
* [Plane Guide](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/guides-panel#plane-guide)
* [View Axis Unlocking](/user-guide/world-axis-unlock)

### Selection & Transformation

* [Transform Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/transform-panel) - Axis locks, alignment tools, and precise positioning
* [Selection/Erase Filter](/user-guide/selection-erase-filter)
* [Full Selection Tools on Quest/Standalone VR](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/tools-panel/selection-options#selection-tools-on-queststandalone-vr) - "Select All" and "Invert Selection" now available
* [Erase Media Widgets](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/tools-panel/selection-options#erase-media-widgets) - Use the erase tool on images, videos, and 3D models
* [Snip/Join Strokes](/alternate-and-experimental-builds/old-or-completed-feature-builds/snip-tool)

### Organization & File Management

* [Layers](/alternate-and-experimental-builds/old-or-completed-feature-builds/layers)
* [Saved Stroke Gallery](/user-guide/importing-images-videos-3d-models) - Save and reuse selections of brush strokes
* [Merging Sketches](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/merging-sketches.md)
* [Hiding Brushes with Brush Tags](/user-guide/brushes/hiding-brushes-with-brush-tags)
* [Move selection to current layer](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/tools-panel/selection-options#move-selection-to-layer)

### Video & Camera

* [Advanced Camera Tool](/user-guide/exporting-videos/camera-tool-gifs-snapshots-video)
* [Camera Paths on All Headsets](/user-guide/exporting-videos/camera-paths-tool) - Create and edit camera paths on standalone devices
* [Camera Path Rendering on All Devices](/release-history/v2.29#camera-path-rendering-on-all-devices) - Render video frames on standalone headsets
* [Render Video on Any Computer](/release-history/v2.4-prismatic#render-video-on-any-computer) - Use ffmpeg on Mac and PC to render videos
* [Webcam Viewer](/release-history/v2.4-prismatic#webcam-viewer) - View webcam feed while working (PC VR only)

### Sharing & Publishing

* [Publish to Viverse](/release-history/v2.29#publish-worlds-to-viverse) - Share sketches directly to Viverse 3D worlds
* [Icosa Gallery uploads](https://icosa.gallery)
* [Icosa Gallery Integration](/user-guide/saving-and-sharing-your-open-brush-sketches#icosa-gallery-integration) - Browse and load sample sketches directly from Icosa Gallery

### User Interface

* [XR Keyboard](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/xr-keyboard.md) - Built-in virtual keyboard for naming sketches and layers
* [Multiple Language Support](/release-history/v2.4-prismatic#multiple-language-support) - French, Spanish, German, Chinese, Japanese, Korean
* [Switching hands](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/switching-hands.md)
* [Reset to "First Time"](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/the-admin-panel/settings#reset-to-first-time)

### Platform & Device Support

* [Support for More Headsets](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/platform-and-device-support.md#supported-headsets) - Pico, Zapbox, and other OpenXR devices
* [Quest 1 Support](/release-history/v2.4-prismatic#quest-1-support-is-back) - Full selection tool support restored
* [Audio Reactive Mode for Quest](/release-history/v2.4-prismatic#audio-reactive-mode-for-quest) - Brushes animate to imported audio
* [Monoscopic Mode](/user-guide/monoscopic-mode) - Run on non-VR devices
* [Flatscreen View Mode](/release-history/v2.4-prismatic#flatscreen-view-mode) - Navigate sketches with keyboard, touch, or gamepad
* [Enhanced View-only Mode](/release-history/v2.29#view-only-mode-improvements) - Improved navigation on non-VR devices with gamepad and touch support
* [Passthrough Mode with Room Scale](/release-history/v2.4-prismatic#passthrough-room-scale) - Stable scene orientation relative to real space

### Multiplayer & Collaboration

* [Multiplayer Support](/alternate-and-experimental-builds/old-or-completed-feature-builds/multiplayer) - Collaborative sketching with multiple users

### Other Features & Improvements

* [LIV Support](https://www.liv.tv)
* [Oculus MRC fixes](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/platform-and-device-support.md#oculus-mrc-fixes)
* [Fly Tool](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/tools-panel#fly-tool)
* [JSON exports include sketch metadata](/user-guide/exporting-open-brush-sketches-to-other-apps/configuring-export#json-exports-include-sketch-metadata)
* [Precise slider control using thumb stick](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/platform-and-device-support.md#precise-slider-control)

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 [@mikeage](https://github.com/mikeage) for the amazing automated build system.


# User Guide


# Get started with Open Brush

Paint in 3D with Open Brush, an app that runs on the [HTC Vive](http://www.htcvive.com/) , [Valve Index](https://store.steampowered.com/valveindex) , [Oculus Rift](https://www.oculus.com/rift/) , [Oculus Quest](https://www.oculus.com/quest/), and [Windows Mixed Reality](https://www.microsoft.com/en-us/windows/windows-mixed-reality) virtual reality systems. You can use different brushes, effects, and tools to paint your virtual creations.

### **Requirements and Installation**

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**

1. Set up your [HTC Vive](http://www.htc.com/managed-assets/shared/desktop/vive/Vive_PRE_User_Guide.pdf) or [Valve Index](https://support.steampowered.com/kb_article.php?ref=9140-EYIL-0086).
2. If you haven't already, [install Steam](http://store.steampowered.com/).
3. Download the [Open Brush](https://store.steampowered.com/app/1634870/Open_Brush/) app.
4. 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](https://www.vive.com/us/support/vive/category_howto/system-requirements.html) and [Valve Index](https://store.steampowered.com/app/1070910/Are_you_ready_for_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:

1. Set up your [Oculus Rift](https://www3.oculus.com/en-us/setup/).
2. Download the [Open Brush](https://www.oculus.com/experiences/rift/5227489953989768/) app.
3. 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](https://www3.oculus.com/en-us/oculus-ready-pcs/).

**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:

1. Set up your [Oculus Quest](https://www.oculus.com/setup/#quest-setup).
2. Download the [Open Brush](https://www.oculus.com/experiences/quest/3600360710032222/) app, currently on App Lab.
3. To open Open Brush, open the **Oculus Home Library** > **Open Brush.**

**Windows Mixed Reality**

1. Set up your [Windows Mixed Reality headset](https://support.microsoft.com/en-us/help/4043101/windows-10-set-up-windows-mixed-reality).
2. If you haven't already, [install Steam](http://store.steampowered.com/).
3. Download the [Open Brush](https://store.steampowered.com/app/1634870/Open_Brush/) app.
4. 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](https://docs.microsoft.com/en-us/windows/mixed-reality/enthusiast-guide/windows-mixed-reality-minimum-pc-hardware-compatibility-guidelines).

### **For a quick tutorial**

1. Make sure you are in [Advanced Mode](https://support.google.com/tiltbrush/answer/6389712?hl=en\&ref_topic=7074683).
2. On your palette, go to **Tools >** **More** > **Tips ‘N Tricks.**
3. 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](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/the-admin-panel/settings)

### **View sketches**

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.


# Painting with Open Brush

## **Paint with Open Brush**

1. On your painting controller, use your index finger to pull the trigger.
2. 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.

### **Alternative Input Devices**

For enhanced precision and pressure-sensitive painting, you can use the [Logitech MX Ink](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/logitech-mx-ink.md) stylus, which provides a pen-like experience with natural pressure control.

### **Using the palette**

![](/files/PuKGOaUayeVy8e7ToGRq)

1. 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).
2. This will allow you to rotate between the three faces of the palette.
3. Using your painting controller, angle your controller towards the palette in order to select items on the palette.
4. Focus the pointer and press trigger to make selections.
5. You can also use the grips on your painting controller to grab panels spawned into the world, and place them onto your palette.

### **Change the width of your brush strokes**

To change the width of your brush strokes:

1. 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).
2. Sliding or toggling left will make the brush stroke finer. Sliding or toggling right will make the brush stroke larger.

### **Undo & Redo shortcuts**

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.

### **Rotate & Resize your sketch**

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.


# The Open Brush UI

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.**

### **The Quick Tools Panel**

Additionally, you can find the **Brush, Dropper, re-color, Selection, Model Pin, and Eraser** on the Quick Tools panel.

<figure><img src="/files/qXWko9zSxcH76DF1SXc3" alt="" width="375"><figcaption></figcaption></figure>

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


# Admin Panel

### How to Find the Admin Panel

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](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/the-admin-panel/settings))

### Using the Admin Panel

The large central button opens the Sketchbook Panel.

Around the outside are buttons for:

1. Save Sketch\\
2. Upload Panel\
   ![](/files/oWlBaroWwvQomoXIXaiv)\\
3. The 3 dots "more" button opens this:\
   ![](/files/r6smR2LgtHxoIEFOTTHI)\
   \
   A popup with:
   1. Tutorial
   2. [Labs Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/the-admin-panel/labs-panel)
   3. [Settings Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/the-admin-panel/settings)
   4. (small button underneath) Reset Panels: resets all panels to their default position/visibility\\
4. Beginner/Advanced mode toggle\\
5. New Sketch\\


# Settings Panel

![](/files/geidEJF3L1hRYnVLPCRb)

The Settings Panel can be opened from a button on the [Admin Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/the-admin-panel).

1. 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
2. Second row of buttons (Left to right):\
   i. Autosimplify\
   ii. Experimental Mode: Toggles [Experimental Mode](/user-guide/experimental-mode) on or off next time you open the app\
   iii. Swap Hands: Swaps the brush between the left and right hands. See [Switching Hands](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/switching-hands.md) for more information.\
   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 [Experimental Mode](/user-guide/experimental-mode) and switches back to Beginners Mode where most of the tools are hidden.
3. Pointer Angle: This changes the angle the brush pointer is at. Find a settings you feel comfortable with.
4. Quality
5. Simplification
6. Current Sketch Cost
7. Super Secret Hidden Buttons: Absolutely nothing happens if you click here.

## Reset to "First Time"

The "Reset First Use" button returns Open Brush to its initial state as if you're running it for the first time:

* Restarts the introductory tutorial on next launch
* Resets to Beginner Mode (hides advanced tools)
* Turns off Experimental Mode
* Resets all preferences to defaults

This is useful for:

* Showing Open Brush to new users
* Teaching others how to use Open Brush
* Troubleshooting by returning to a known state
* Resetting after experimenting with settings


# Labs Panel

<figure><img src="/files/8lBc1M35TDXSJyzWBfN9" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
[More info on Labs features](/user-guide/check-out-labs-or-experimental-features)
{% endhint %}


# Tools Panel

1. **Eraser Tool**. You can use the eraser tool to erase entire brush strokes. To select the tool:

   1. Point your painting controller towards the palette and select the eraser .
   2. Position the tool anywhere on the brush stroke and press the trigger to erase.
   3. 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.
2. **Dropper Tool**. To select the brush and color used for a stroke or the color in a reference image:
   1. Position your controller on the brush stroke or the color in an image you want.
   2. Press the trigger to confirm. Your brush type, color and size will be copied.
   3. To disable the dropper, click the icon again
3. [Repaint Tool](/user-guide/repaint-tool)
4. **Camera Tool**. Use Cameras to save your creation in various formats.

   1. Point your painting controller towards the palette and select Cameras.
   2. 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.
   3. After selecting your option, your image file will save to the "Open Brush" folder inside "Documents" on your computer.
   4. You can then share photos, videos, and GIFs or your artwork online.
   5. 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](/user-guide/exporting-videos).\
   \
   Long-press the camera tool to access the camera settings:

   \
   ![](/files/TzhR4VFicaUIZc1Uz7KU)\\
5. **Teleport Tool**. To virtually hop to a different spot in your environment, use Teleport.

   1. Point your painting controller towards the palette and select Teleport.
   2. On your painting hand, press the thumbpad or trigger to move around the x and y axis.
   3. You will see footprints on the ground, which represent your landing spot.
   4. To disable Teleport, select the icon again.

   Note: The distance which you can teleport varies in each environment.
6. **Selection Tool**. Use Selection to select and duplicate strokes and models in your scene.

   1. 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).
   2. 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.
   3. 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.

   **Selection Tray Buttons:**\
   \
   **Select All** ![](/files/-MjYoz4KkSz49zljeghI)

   To select everything in a scene, long press on the Select button on the Tools panel and the Select All button will appear.

   **Invert Selection** ![](/files/-MjYoz4LqjVw-XVg38Aj)

   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.

   **Toggle Grouping for Selection** ![](/files/ikMBiqJC3xxuLWEnnJSI)

   Combines the currently selected strokes into a single group. They will move and scale as one. You can ungroup them easily by clicking again.\\
7. **Mirror Tool**. Use the mirror mode tool to paint symmetrically. To use the tool:

   1. Point your painting controller towards the palette and select Mirror Mode.
   2. To grab and move the mirror, use the Grip button on the sides of your controllers.
   3. To adjust the mirror back to default, grab and move the mirror onto the snapback widget.
   4. 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:

   \
   ![](/files/px3gxhXV52m28uELWT47)\
   \
   The second button is the Mirror Recall button. This will recall a Mirror that is out of reach.\ <mark style="color:blue;">(If you like the mirror - you might want to check out the multi-mirror )</mark>
8. **Straight Edge Tool**. Use the straight edge tool to paint in straight lines between two points.
9. **Fly Tool**. The Fly tool allows you to navigate through your sketch smoothly, similar to flying in a video game. This is particularly useful for:

   * Navigating large, complex sketches
   * Moving through tight spaces
   * Exploring your creation from different angles
   * Getting to hard-to-reach areas

   To use the Fly tool:

   1. Select the Fly tool from the Tools panel (Advanced Mode only)
   2. Point your controller in the direction you want to move
   3. Hold the trigger to fly in that direction
   4. Release to stop
10. **Snip Tool** (currently [beta only](/alternate-and-experimental-builds/open-brush-beta-docs))
11. **Join Tool** (currently [beta only](/alternate-and-experimental-builds/open-brush-beta-docs))

#### Differences in Beginners vs Advanced modes

The following tools only appear in [Advanced Mode](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/the-admin-panel/settings)

1. Dropper
2. Repaint
3. Selection
4. Fly
5. Snip
6. Join

Additionally in Advanced Mode the Environment Panel button moves to the [Extras Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel)


# Selection Options

The Selection tool has various options for selecting strokes and objects in your sketch.

## Selection Tools on Quest/Standalone VR

Quest and other standalone VR devices now have access to the full range of selection tools that were previously only available on PC VR:

### Select All

Selects every stroke, image, video, and 3D model in your current sketch. This is useful for:

* Applying transformations to your entire sketch
* Moving or scaling everything at once
* Changing colors or brushes across all strokes

### Invert Selection

Inverts your current selection - everything that was selected becomes unselected, and everything unselected becomes selected. This is useful for:

* Selecting everything except specific elements
* Quick operations like "select everything but this"

**Performance Note:** On complex sketches with many strokes, these operations may cause temporary stuttering or lag on standalone devices. Use them carefully in very large sketches.

## Move Selection to Layer

You can move selected strokes to a specific layer using the layer controls. This helps organize your sketch by grouping related elements together.

## Erase Media Widgets

The erase tool can now delete imported media (images, videos, and 3D models) in addition to brush strokes. Simply activate the eraser and touch any media widget to remove it from your sketch. This provides a faster alternative to using the grip button flick gesture to delete widgets.


# Repaint Options

<figure><img src="/files/gAAeGhmB332aYEqPg9Fi" alt=""><figcaption></figcaption></figure>


# Brushes Panel


# Extras Panel

![](/files/RzaMBydMPEFmVIp6j7pG)

1. [Environment Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/environment-panel): 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.
2. [Lights Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/lights-panel)
3. [Backdrop Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/backdrop-panel)
4. [Guides Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/guides-panel)
5. [Media Library Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/media-library)
6. [Camera Paths Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/camera-paths-panel)
7. [Snap Settings Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/snap-settings-panel)
8. [Transform Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/transform-panel)
9. [Layers Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/layers-panel)


# Environment Panel

![](/files/QU3j9bExV226wj2yuulw)


# Lights Panel

<figure><img src="/files/k79XGYQEa0nDddQP3Uph" alt="" width="338"><figcaption></figcaption></figure>

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.


# Backdrop Panel

<figure><img src="/files/woyNB5EN7gQDEcPCjU9I" alt=""><figcaption></figcaption></figure>

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.


# Guides Panel

<figure><img src="/files/cR3VaZ6oMPcYaAq4BMQK" alt=""><figcaption></figcaption></figure>

* Use the sphere, cube, and pill guides to create perfect shapes.
* Guides are moved and scaled similar to other widgets, using the Grip buttons.

## Guide Types

Open Brush includes several types of guides:

### Plane Guide

The plane guide creates a flat surface that you can paint on or use as a reference. This is useful for:

* Creating flat surfaces like floors, walls, or tables
* Drawing 2D elements in 3D space
* Aligning objects to a common plane
* Building architectural elements

### Other Guides

* **Sphere guide** - Paint on a spherical surface
* **Cube guide** - Paint along box edges and faces
* **Capsule (pill) guide** - Paint on cylindrical surfaces with rounded ends

### Guide Settings

<figure><img src="/files/8k67uzUJkzbeu7SzTOtf" alt=""><figcaption></figcaption></figure>

The Guide Settings allow you to customize how guides behave, including snapping options and visibility settings.


# Media Library

<figure><img src="/files/Xf8jMkxP2RacSPNBtSp2" alt=""><figcaption></figcaption></figure>


# Camera Paths Panel

<figure><img src="/files/WpZ1jvrUYgmoI8zyffNH" alt=""><figcaption></figcaption></figure>


# Snap Settings Panel

<figure><img src="/files/0pjgnpIR60oriK0jSgsP" alt=""><figcaption></figcaption></figure>

The Snap Settings Panel provides controls for grid and angle snapping. For basic usage, see [Grid and Angle Snapping](/user-guide/grid-and-angle-snapping).

## Enhanced Snap Settings

The snap settings include several advanced features:

### Snap Axis Toggles

You can choose which axes snapping applies to. For example:

* Enable only Y-axis snapping to keep strokes at consistent heights while allowing free movement in X and Z
* Enable only X and Z to create a flat plane of snapped objects
* Enable all three axes for full 3D grid snapping

This is useful for creating rows, columns, or planes of duplicated objects while maintaining precise control over which dimensions are constrained.

### Snap to Guides

When you have guides active in your scene, you can enable snapping to align selections and brush strokes to guide surfaces. This works with:

* Plane guides
* Sphere guides
* Line guides
* Mirror planes

This makes it easier to paint directly on guide surfaces or position imported models precisely on guides.


# Transform Panel

<figure><img src="/files/D7h4XTLBmbAVDTWgsAe3" alt=""><figcaption></figcaption></figure>


# Layers Panel

<figure><img src="/files/lpzHHILjkt0Amos6vff0" alt="" width="338"><figcaption></figcaption></figure>

The Layers Panel allows you to organize your sketch into separate layers, making it easier to manage complex scenes.

## Naming Layers

You can rename layers by clicking on the layer name. This will open the [XR Keyboard](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/xr-keyboard.md), which allows you to enter text while in VR.


# UI Differences Between Basic Mode and Advanced Mode

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) .

| Basic Mode Tools | Advanced Mode Tools | More Tools   |
| ---------------- | ------------------- | ------------ |
| 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 |


# Grid and Angle Snapping

### What does it do?

![TODO](https://cdn.discordapp.com/attachments/804251582715265034/846812293177933894/2021-05-25_19-06-31.gif)

1. Snap selections to a grid. Duplicate selections at precise positions
2. Draw brush strokes that align with the grid (especially useful with the hull brush)
3. Snap the rotation of selections to a chosen angle (i.e. 15, 45 or 90 degrees)

### What's it good for?

Drawing along straight x, y or z lines. Building regular structures up by making multiple copies of brush strokes

### How do I use it?

Click the button shown above on the [Extras Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/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 ](/user-guide/repaint-tool#jitter-positions)can be useful with snapped brush strokes.

### Can I see it in action?

{% embed url="<https://www.youtube.com/watch?v=as_ty_89Bfk>" %}


# Repaint Tool and Jitter

### What does it do?

It expands on the previous Recolor tool which is now renamed to "Repaint". The following features can be used individually or in any combination:

#### Recolor

Same as before (but see the "jitter" feature below which adds new functionality to Recolo)

#### Rebrush

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)

#### Resize

Change the brush size of existing strokes.

#### Jitter

When this option is turned on, recolor and resize will add random variations based on your current Jitter settings.

### Jitter Improvements

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)

#### Jitter Brush Size

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.

#### Jitter Positions

![](/files/n5OVTosdDpAa9J413zzu)

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.

### Things to try

1. 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.
2. 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
3. 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)

### What's it good for?

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)

### How do I use it?

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

## Repaint Selection

Instead of repainting strokes one at a time, you can select multiple strokes and apply repaint operations to all of them at once:

1. Use the selection tool to select the strokes you want to modify
2. Activate the Repaint tool with your desired settings (Recolor, Resize, Rebrush, or Jitter)
3. The selected strokes will all be repainted with the current settings

This is particularly useful for:

* Changing the color scheme of multiple strokes at once
* Applying consistent size changes to a group of strokes
* Converting multiple strokes to a different brush type
* Adding jitter variation to duplicated elements

### Can I see it in action?

{% embed url="<https://youtu.be/mScGKQke4QA>" %}

![Hull brush drawn with the Polyhedra tool with color and position jitter added](/files/vm99QCBjRd8FSnl6lM9Q)


# Selection/Erase Filter

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.


# Lazy Input

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.

{% embed url="<https://www.youtube.com/watch?v=2CEyUrv3IZk>" %}


# Bimanual Input and Revolver

### Bimanual Input

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.

{% embed url="<https://www.youtube.com/watch?v=ufGpqmul4Rc>" %}

### Revolver

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.

{% embed url="<https://www.youtube.com/watch?v=Wtx5uAF0GXs>" %}


# World Axis Unlock

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!

This feature unlocks the view axis, allowing you to rotate your entire sketch independently of the VR world's orientation. This is particularly useful for:

* Working on different sides of a sketch without moving yourself
* Creating artwork at unusual angles
* Comfortable painting positions regardless of the sketch's orientation

{% embed url="<https://www.youtube.com/watch?v=_d34eBiTtGA>" %}


# Saving and sharing your Open Brush sketches

When you are finished with your 3D creation, you can save your Open Brush sketch to your computer, or share it to [Icosa](https://beta.icosa.gallery/) or [Sketchfab](https://sketchfab.com). You can also take snapshot, GIFs or videos of your art to send to friends or post online.

### **Saving a sketch**

While painting, you can save your sketch to avoid losing changes.

1. Navigate to the Tools panel in the palette, and select the **Save** icon: ![](/files/-MjYoz4RZztjBnCTfyTT)
2. Take a snapshot of your sketch to use as a thumbnail image.
3. Your sketch is now added to your Sketchbook.
4. Your sketch file is saved to your computer at **Documents/Open Brush/Sketches**.

You can rename your sketches using the [XR Keyboard](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/xr-keyboard.md) when browsing them in the Sketchbook.

You can also combine multiple sketches into one. See [Merging Sketches](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/merging-sketches.md) for more information.

### Organizing your sketches

If you are using Open Brush on a PC or have copied your sketch files to a PC from a headset then you will find it useful to install the Windows Explorer Thumbnail Extension so you can see the thumbnails for each sketch in Windows Explorer. You can install this from Itch.io (it's the last download in the list)\
\
<https://openbrush.itch.io/openbrush>

### **Trouble saving 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.

### **Sharing your Open Brush sketches**

To share your creations outside of Open Brush, click **Upload** ![](/files/-MjYoz4SoEdlEc_tK-4c) to publish your sketch to [Icosa](https://beta.icosa.gallery/). Once you have published your sketch, you can share the link to your sketch on social networks like Facebook, Twitter, and Google+.

## Icosa Gallery Integration

Open Brush has built-in integration with [Icosa Gallery](https://icosa.gallery), allowing you to:

### Browse and Load Sketches

From within Open Brush, you can browse the Icosa Gallery and load sample sketches directly into VR:

1. Open the sketch browser
2. Navigate to the Icosa Gallery tab
3. Browse featured and popular sketches
4. Select a sketch to download and open it

This is a great way to:

* Explore what other artists have created
* Learn new techniques by examining others' work
* Find inspiration for your own creations
* Use sketches as starting points for remixes

### Upload Your Sketches

You can upload your sketches directly to Icosa Gallery from within Open Brush to share with the community and preserve your work online.

### **Save in various file formats using Cameras**

1. While in your sketch, go to **Tools** > **Cameras**.
2. With your painting controller, swipe the thumbpad to toggle between Auto GIF, 5-second GiF, video, and snapshot.
3. After selecting your option, your image file will save to the Documents folder on your computer.
4. You can then share photos, videos, and GIFs or your artwork online.

Note: Using Cameras will not save the sketch file to gallery.

### **Take a 5-second GIF**

1. Select **5-second GIF** from the Cameras menu.
2. 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.
3. When the recording hits 5-seconds, the GIF will be saved to your desktop under **Documents/Open Brush/Snapshots**.

### **Take a video**

1. Select **Video** from the Cameras menu.
2. On your painting controller, tap the trigger to start recording. Tap the trigger again to stop.
3. 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.](https://docs.google.com/document/d/11ZsHozYn9FnWG7y3s3WAyKIACfbfwb4PbaS8cZ_xjvo/preview)

### **Upload a video to YouTube**

1. Select **Video** from the Cameras menu.
2. On your painting controller, tap the trigger to start recording. Tap the trigger again to stop.
3. Hold down the thumbpad after a video has finished recording to go into Preview mode.
4. If you like the video you’ve captured, hold down the checkmark to upload.
5. If you haven't already, you will need to sign-into your YouTube account in your default desktop browser.

### **Export your sketch file to .fbx, .obj, .gltf and other formats**

.fbx is a popular format for 3D modeling, and can be used in applications like Blender and Maya.

1. From the Tools panel, select "**More Options..."** > **Labs** > **Export**.
2. 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](/user-guide/exporting-open-brush-sketches-to-other-apps)

### **Create a 360 video**

To create a 360 video, follow the [instructions here](/user-guide/exporting-videos#exporting-360-videos-offline-video-rendering). Note: this is an advanced feature, and requires some working knowledge of the command line.


# Troubleshooting issues with Open Brush

If you are having issues using Open Brush, check out your options below.

### Asking Questions and getting help

You can join our [Discord ](https://discord.gg/NQv6QPus)or post to our [Github Discussions](https://github.com/icosa-foundation/open-brush/discussions) or the [Tilt Brush subreddit](https://www.reddit.com/r/TiltBrush/). At the time of writing Google still hosts the old Tilt Brush [Product Forum](https://productforums.google.com/forum/#!forum/tilt-brush).

### **Common issues**

#### **Looking for saved files**

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.

#### **Lost artwork**

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.

#### **After I launch Open Brush, a sad Tiltasaurus appears**

This means your Head Mounted Display is not detected, and you'll need troubleshoot your HMD. [Learn to troubleshoot your HTC Vive](http://www.htc.com/managed-assets/shared/desktop/vive/Vive_PRE_User_Guide.pdf) or your [Oculus Rift.](https://product-guides.oculus.com/en-us/documentation/rift/latest/concepts/rgsg-3-ts-setup-troubleshooting/)

#### **Pink screen when starting Open Brush**

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.

#### **Open Brush crashing or freezing**

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.

### **Finding your log files**

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


# Check out Labs features

<figure><img src="/files/8lBc1M35TDXSJyzWBfN9" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This page isn't up to date at the moment
{% endhint %}

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](/alternate-and-experimental-builds).)

### **Accessing the Labs panel**

1. Make sure you are in Advanced Mode.
2. Below your palette, go to the Menu panel and select "**More Options...**".
3. On your paint palette, swipe to the Tools panel and select More.
4. Select **Labs**.

## Labs Features:

### [**Multi Mirror**](/user-guide/multimirror)

<div align="left"><figure><img src="/files/HHm4XA6MTBOO9tAktPv7" alt=""><figcaption></figcaption></figure></div>

### [Export your sketch as a 3d file](/user-guide/exporting-open-brush-sketches-to-other-apps)

<div align="left"><figure><img src="/files/Sj1AbKTWDcWzHK0GYKyb" alt=""><figcaption></figcaption></figure></div>

### Save Selected Strokes to your Media Library

<div align="left"><figure><img src="/files/0dh3XugZMqpzkmn7RDXn" alt=""><figcaption></figcaption></figure></div>

### Hide or show Draft Brush strokes

<div align="left"><figure><img src="/files/pbUJu4Rz2c8coHPRjgfz" alt=""><figcaption></figcaption></figure></div>

### View a live webcam or other video feed while drawing

<div align="left"><figure><img src="/files/IW06aqQmloICO5ypEzEa" alt=""><figcaption></figcaption></figure></div>

### Use the "Pin" tool

<div align="left"><figure><img src="/files/J44RWw0wgY45AsSonwXg" alt=""><figcaption></figcaption></figure></div>

### [Browse and Import 3d models from the Icosa Gallery](/alternate-and-experimental-builds/old-or-completed-feature-builds/icosa-gallery-support)

<div align="left"><figure><img src="/files/NJ1uXFY34XScv4g2kXjA" alt=""><figcaption></figcaption></figure></div>

### Switch the desktop view to a spectator camera

<div align="left"><figure><img src="/files/9ZyP6p96lf1i2dQKFeOF" alt=""><figcaption></figcaption></figure></div>

### Use [plugins ](/user-guide/using-plugins)or run [API scripts](/user-guide/open-brush-api)

<div align="left"><figure><img src="/files/GgOjrAMnP7nWswoW6ANY" alt=""><figcaption></figcaption></figure></div>

***


# Multi Mirror

{% embed url="<https://www.youtube.com/watch?v=WIAsbqW_j8U>" %}

### What does it do?

Big expansion to the mirror to support many different types of symmetry:

**Point symmetry:** Symmetry around a point. 7 families of axial symmetry plus 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

### What's it good for?

Creating symmetrical patterns. Drawing multiple strokes at the same time. Arranging models or images into grids or other regular patterns.

### How do I use it?

Click the button on the [Labs Panel](/user-guide/check-out-labs-or-experimental-features) to activate Multi Mirror mode:

<div align="center"><figure><img src="/files/DGeOmomz5M8mjjjovksR" alt="" width="563"><figcaption></figcaption></figure></div>

When it is active you can access multi mirror settings by clicking and holding the button down for a second or so. This will bring up a panel which contains three tabs:

#### 1. Point Symmetry

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)

#### 2. Wallpaper Symmetry

![](/files/a5UEWIfIb8hUddgJ1vXF)

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.

#### 3. Options

![](/files/fmHk0ibdAMFaX9LyVbmX)

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.

### Creating Patterns From Existing Brush Strokes

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)

{% hint style="info" %}
This is buggy in the release version but fixed on the [current beta](/alternate-and-experimental-builds/open-brush-beta-docs)
{% endhint %}

### Creating Symmetrical Patterns from Imported Objects

As well as duplicating brush strokes, if you have [imported some media](/user-guide/using-reference-images-on-oculus-quest) such as images, video or 3D objects then you can select those and create copies that follow the current symmetry settings.

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.

### Known Issues

1. 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.
2. 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.

### Can I see more?

{% embed url="<https://www.youtube.com/watch?v=khsI-7rl2yg>" %}
Some early experiments with spinning mirrors
{% endembed %}

{% embed url="<https://youtu.be/VxVjkV_CkFs>" %}
Another early test of the feature
{% endembed %}


# Importing Images, Videos and 3D Models

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.

1. Make sure you are in Advanced Mode.
2. Below your palette, go to the Menu panel and select "**More Options...**".
3. On your paint palette, swipe to the Tools panel and select More.
4. Select **Labs** to open the [Labs Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/the-admin-panel/labs-panel)

![](/files/ENXFhIwXBEoC3Qsl5yLp)

Click this icon to open the Media Library:

###

#### **Add an image or video clip**

1. Copy a PNG or JPG file to Documents/Open Brush/Media Library/Images or a video file to Documents/Open Brush/Media Library/Videos
2. In Open Brush, make sure you are in [Advanced Mode](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/tool-panels).
3. Go to the Menu panel (below your palette) and select **"More Options..."** **>** **Labs > Local Media Library > Local Images**.
4. Switch between selecting images and models using the icons in the top left.

You can organize your media files into folders. See [Folder Navigation](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/folder-navigation.md) for more information.

#### **Add a 3D model**

1. Copy any [supported](#supported-file-formats) 3d file to Documents/Open Brush/Media Library/Models.
2. In Open Brush, make sure you are in Advanced Mode. On the Quest you also need to switch Experimental Mode on in the settings.
3. Go to the Menu panel (below your palette) and select **"More Options..."** **> Labs > Local Media Library > Local Models**.
4. Switch between selecting images and models using the icons in the top left.
5. See "Supported Formats" below to see which file types you can use.

You can organize your media files into folders. See [Folder Navigation](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/folder-navigation.md) for more information.

### Supported File Formats

<table><thead><tr><th width="140">Type</th><th>Format</th><th>Notes</th></tr></thead><tbody><tr><td>Images</td><td>PNG</td><td></td></tr><tr><td></td><td>JPEG</td><td></td></tr><tr><td></td><td>SVG</td><td>(SVGs can be imported either as images or as a mesh)</td></tr><tr><td></td><td>HDR</td><td></td></tr><tr><td>Video</td><td>MP4</td><td>See notes below.</td></tr><tr><td></td><td>MKV</td><td>See notes below.</td></tr><tr><td></td><td>MOV</td><td>See notes below.</td></tr><tr><td></td><td>WEBM</td><td>See notes below. Must use VP8 codec. Supports transparency on Windows only.</td></tr><tr><td>3d Models</td><td>GLTF/GLB</td><td></td></tr><tr><td></td><td>OBJ</td><td></td></tr><tr><td></td><td>FBX</td><td>PC/Mac only.</td></tr><tr><td></td><td>USD</td><td>PC/Mac only. Support is rather outdated and experimental</td></tr><tr><td></td><td>PLY</td><td>Point clouds only. Binary little-endian format.</td></tr><tr><td></td><td>SVG</td><td>(SVGs can be imported either as images or as a mesh)</td></tr><tr><td></td><td>VOX</td><td>Magicavoxel format for voxel models</td></tr></tbody></table>

## WebM Video Import

WebM is a video format that supports transparency (alpha channel), allowing you to import videos with transparent backgrounds. This is particularly useful for effects, animated sprites, or reference footage.

**Requirements:**

* Must use VP8 codec
* Transparency is currently only supported on Windows
* Place .webm files in Documents/Open Brush/Media Library/Videos

## Point Cloud Import

You can import point cloud data in PLY format (binary little-endian). Point clouds are useful for:

* Importing 3D scanned data
* Working with photogrammetry outputs
* Creating particle-like effects
* Reference data from LiDAR scans

Place .ply files in Documents/Open Brush/Media Library/Models and they will appear in the model browser.

{% hint style="info" %}
Video support varies across OS and hardware versions. See:\
\
<https://learn.microsoft.com/en-us/windows/win32/medfound/supported-media-formats-in-media-foundation#video-codecs>\
\
<https://learn.microsoft.com/en-us/windows/win32/medfound/supported-media-formats-in-media-foundation#video-codecs>\
\
for more detailed information.
{% endhint %}

### **Interacting with Imported Objects**

**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 or model, 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. You can also use the [eraser tool](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/tools-panel).


# Experimental Brushes

## Turning on Experimental Brushes

![](/files/3Ty6J6NmRguZPgF2Ktmf)

Simply open up the Settings Panel and click the button.

There are [50 new brushes](#experimental-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.

### Compatibility Issues

Any sketch you save that contains these new brushes may not look correct when you export it to other Unity projects using the [Open Brush SDK](/user-guide/open-brush-unity-sdk)

We are currently working on a new Unity Toolkit that has support for all the experimental brushes in conjunction with the [new glb export format](/user-guide/exporting-open-brush-sketches-to-other-apps/configuring-export#choosing-between-the-new-and-old-gltf-formats)

## What was Experimental Mode?

{% hint style="info" %}
Some features that used to require experimental mode have been made part of normal mode. The only remaining difference in experimental mode is the brushes. There is also no longer a separate build for experimental mode but we do have some [experimental feature builds](/alternate-and-experimental-builds) you can download.
{% endhint %}

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 ](/user-guide/check-out-labs-or-experimental-features)in the official release. And finally it would be released as an officially supported feature.

We have merged all those features into the main version now - so there's no need for a separate experimental mode aside from activating the extra set of brushes.


# Make moving creations using audio reactive brushes

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.

![](/files/pFA0KnaOGcFkm6c7GMRK)

### **To use audio reactive brushes**

1. Begin playing audio from your computer desktop.
2. Point your painting controller on Brushes page and click the wavy audio reactive icon.
3. You will see a message that Open Brush is listening for audio.
4. Once audio is detected, press the trigger on your painting controller and begin to lay down your brush strokes.
5. 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.


# Using Reference Images on Oculus Quest

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.

### **How to access the Reference Images Panel**

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.

1. 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.
2. 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.
3. A popup will appear with a few choices. Click 'Labs'.
4. The Labs Panel will spin out. Point at it and find the 'Reference Images' button. Click this.
5. The Reference Images Panel will spin out.

### **Adding images to your sketch**

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.

### **Adding more images**

To add more images to the Reference Images Panel, you need to connect your Oculus Quest to a PC. Use [these steps](https://support.oculus.com/855551644803876/#faq_2255729571307786) to learn how to do that.

1. Once connected to a PC, look for, 'Quest' in Windows Explorer. Click this.
2. Navigate to '..Quest\Internal shared storage\Open Brush\Media Library\Images\\'
3. Copy image files (.jpg or .png) into this folder.

### **Supported image files**

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.

1. Only .jpg and .png file types.
2. Max image file size is 10Mb.
3. Max image dimension (height and width) is 1024.


# Remixing and Creative Commons

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.

### **Creative Commons**

[Creative Commons](https://creativecommons.org/) 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 [CC BY](https://creativecommons.org/licenses/by/3.0/legalcode) license. These sketches are then accessible to other Open Brush Sketches users for use, even commercially, in their own sketches.

### **Turning off remixing for your content**

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.

If you don't allow remixing, your content will be published under the standard Google [Terms of Service](https://www.google.com/policies/terms/).

### **Attribution**

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.

### **Deleting remixable content or changing remix settings**

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.

### **What's eligible for remixing**

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


# Accessing Autosave Files

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.


# The Open Brush config file

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.

{% hint style="info" %}
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](https://jsonformatter.org/) can help if you're stuck.
{% endhint %}

Example of an empty *Open Brush.cfg:*

```
{
   "User":{
      
   },
   "Brushes":{
   
   },
   "Video":{
      
   },
   "Flags":{
      
   },
   "Export":{
      
   }
}
```

Sample contents of a *Open Brush.cfg* with various fields filled in:

```
{
   "User":{
      "Author":"Tiltasaurus"
   },
   "Brushes": {
      "IncludeTags": ["classroom"]
   },
   "Video":{
      "Resolution":1280,
      "OfflineResolution":1920,
      "FPS":30,
      "OfflineFPS":60,
      "ContainerType":"mp4",
      "CameraSmoothing":0.98,
      "Encoder":"h.264",
      "SaveCameraPath":true,
      "FOV":80
   },
   "Flags":{
      "PostEffectsOnCapture":true,
      "ShowWatermark":true,
      "ShowHeadset":true,
      "ShowControllers":true,
      "SnapshotWidth":1920,
      "SnapshotHeight":1080,
      "FOV":80,
      "DisableAudio":false,
      "UnlockScale":false,
      "AdvancedKeyboardShortcuts":false,
      "SkipIntro":true,
      "EnableMonoscopicMode":false,
      "DisableXrMode":false
   },
   "Export":{
      "ExportBinaryFbx":true,
      "ExportFbxVersion":"FBX201400",
      "ExportStrokeTimestamp":true
   }
}
```

### Valid Config file Settings

#### "User" Section

* **Author:** The name you use here will be stored in files uploaded to Icosa, Sketchfab etc.

#### "Brushes" Section

* **AddTagsToBrushes**: See [Brush Tags](/user-guide/brushes/hiding-brushes-with-brush-tags)
* **RemoveTagsFromBrushes**: See [Brush Tags](/user-guide/brushes/hiding-brushes-with-brush-tags)
* **IncludeTags**: See [Brush Tags](/user-guide/brushes/hiding-brushes-with-brush-tags)
* **ExcludeTags**: See [Brush Tags](/user-guide/brushes/hiding-brushes-with-brush-tags)

#### "Video" Section

* **Encoder**: (h.264) This setting specifies the video codec used for encoding exported videos. Currently, the only supported codec is h.264.

#### "Flags" Section

1. **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.
2. **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.
3. **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.
4. **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.
5. **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.
6. **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.
7. **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.
8. **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.
9. **AdvancedKeyboardShortcuts**: (true | false) Enables some extra keyboard shortcuts that were previously available in [Experimental Mode](/user-guide/experimental-mode)
10. **SkipIntro**: (true | false) Skips the intro scene that appears when Open Brush finishes loading
11. **EnableMonoscopicMode**: (true | false) See [Using Open Brush without a VR headset](/user-guide/monoscopic-mode)
12. **DisableXrMode**: (true | false) See [Using Open Brush without a VR headset](/user-guide/monoscopic-mode)

#### "Import" Section

See [Configuring Import](/user-guide/importing-images-videos-3d-models#enabling-the-new-gltf-importer)

#### "Export" Section

See [Configuring Export](/user-guide/exporting-open-brush-sketches-to-other-apps/configuring-export#choosing-between-the-new-and-old-gltf-formats)

1. **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.
2. **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.
3. **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.

### Setting config values from the command line

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:

```
--Flags.ShowWatermark true

--Video.CameraSmoothing 0.99

--User.Author "Captain Open Brush"
```


# Exporting Open Brush sketches to other apps

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:

<table><thead><tr><th>Format</th><th data-type="checkbox">PC Only?</th><th data-type="checkbox">Experimental Mode Only?</th></tr></thead><tbody><tr><td>GLTF/GLB</td><td>false</td><td>false</td></tr><tr><td>FBX</td><td>true</td><td>false</td></tr><tr><td>OBJ</td><td>true</td><td>true</td></tr><tr><td>USD</td><td>true</td><td>false</td></tr><tr><td>JSON</td><td>true</td><td>false</td></tr><tr><td>LATK</td><td>false</td><td>false</td></tr><tr><td>WRL</td><td>true</td><td>true</td></tr><tr><td>STL</td><td>true</td><td>true</td></tr></tbody></table>

(.glb is closely related to .gltf and most software will support both. We output binary glTF version 2)

.latk is an interchange format for 3d brush strokes: <https://lightningartist.org/>

The .json is a “raw” format which you can use if you need a different file format. See the [Open Brush Toolkit](https://github.com/icosa-foundation/open-brush-toolkit) for sample [Python 2.7](https://www.python.org/download/releases/2.7/) scripts that convert the raw .json to .obj.

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.

The USD contains both geometry and curve information. If your DCC tool doesn’t support USD, the [Open Brush Toolkit](https://github.com/icosa-foundation/open-brush-toolkit) contains a Python 2.7 script that can convert the .tilt file to a Collada .dae containing the curves.

## Flipside XR

1. Follow the instructions for installing and configuring [Flipside Creator Tools](https://www.flipsidexr.com/docs/2023.1/creator-tools/getting-started)
2. Download the .unitypackage for the latest release of the [Open Brush Unity SDK](/user-guide/open-brush-unity-sdk#_iqjwk94xwdgd)
3. You'll also need the [Json.Net.for.open.brush.toolkit.unitypackage](https://github.com/icosa-foundation/open-brush-toolkit/releases/download/v24.0.0/Json.Net.for.open.brush.toolkit.unitypackage) from the same page
4. Add both to your Flipside Unity project
5. Export your Open Brush sketch and import the .glb file into the Flipside project
6. Follow the Flipside instructions for uploading a Unity scene as a Flipside Set

## Maya <a href="#maya" id="maya"></a>

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 Hubs

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.

## Sketchfab <a href="#sketchfab" id="sketchfab"></a>

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.

## Snapchat Lens Studio🔗

[See this page](#snapchat-lens-studio)

## Styly

To upload your work to Styly, you'll need to remove all traces of the audio-reactivity scripts in the Open Brush toolkit.

1. Follow the instructions for setting up Styly in Unity here: <https://styly.cc/manual/unity-asset-uploader/> but stop when you get to the section about half-way through headed "Upload from Unity to STYLY"
2. Download the Open Brush Unity SDK unitypackage as described here: [Open Brush Unity SDK](/user-guide/open-brush-unity-sdk)
3. Delete the following folders from your Unity project window:
   1. ThirdParty/CSCore
   2. ThirdParty/Reaktion
4. Delete the following files from you Unity project window:
   1. TiltBrush/Scripts\:/VisualizerAudioInput
   2. TiltBrush/Scripts\:/VisualizerManager
   3. TiltBrush/Scripts/Editor/VisualizerManagerEditor
5. Also in the project window, drag the entire TiltBrush/Scripts/Gltf folder so it's inside TiltBrush/Scripts/Editor
6. Carry on where you left off with the Styly docs.

## Unity <a href="#unity" id="unity"></a>

We recommend using the [Open Brush Toolkit](/user-guide/open-brush-unity-sdk) and the .glb format. Open Brush Toolkit also understands the .fbx format. More info

## Unity WebGL

You'll need to delete the following 2 scripts if you want to build for Unity WebGL targets: `GenericAudioInputEditor.cs` and `GenericAudioInput.cs`

## Unreal Engine🔗

[See this page](#unreal-engine)

## Command-line Exporting <a href="#command-line-exporting" id="command-line-exporting"></a>

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.

```
OpenBrush.exe --export Untitled_15.tilt Untitled_2*.tilt C:\Downloads\downloaded.tilt --exportPath C:\Temp -batchmode
```


# Exporting to Unreal Engine 5

How to Import OpenBrush FBX files & edit Materials to appear correctly

![](/files/AEZ9TjhtsPmuaxu9DUXs)

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:\\

  ![](/files/HsjMnSZ0KfkWPsaOVTnm)

  Make sure to select: **Advanced > Vertex Color Import Option \[REPLACE]**

### **Organize Materials, Textures, Mesh Files** <a href="#organize-materials-textures-mesh-files" id="organize-materials-textures-mesh-files"></a>

* 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*\\

  ![](/files/FzHh44UnliSzSmymKxta)
* The materials are pretty terribly named. I highly recommend renaming them. The brush material names are at the end of the filename:\\

  ![](/files/Kcf521kxvNI60u1Tj2cH)
* From Windows Explorer, drag optimized PNG brush textures into the UE5 *TEXTURES* folder:\\

  ![](/files/UkbX3Y3uGnjTFqnUgdIs)
* 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:\\

  ![](/files/qA8U0G61GZmMewfim48F)

  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.)\\

  ![](/files/uaIRSgfxS5DqJpAjvM0a)

### Associate Vertex Colors, Textures, Opacity to Materials <a href="#associate-vertex-colors-textures-opacity-to-materials" id="associate-vertex-colors-textures-opacity-to-materials"></a>

**Edit Vertex Colors to Materials that&#x20;*****only*****&#x20;need Vertex Colors:**

| 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 |

* 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

![](/files/yzcRXl5qnYVIISWNx1W9)

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]​

![](/files/fih2ByHlldhwdMPa6B5j)

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:**

| 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 |

* 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

  ![](/files/i6Ol16DqXmWiG51DbzrI)

  * 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:**

| 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 |

* 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

![](/files/RXmSJhqMfjk0vUYbHn3Q)

* 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!

![](/files/J3mAQIFoyUihW7VlLP1c)

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.

*Docs contributed by* [*Estella Tse*](https://www.estellatse.com/)*. Additional thanks to* [*Steve Bowler*](https://www.linkedin.com/in/stevebowler/)


# Exporting to Snapchat Lens Studio

### Tilt Brush → Blender → Snap Lens Studio <a href="#up0jqawz2jcs" id="up0jqawz2jcs"></a>

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.

### Tilt Brush to Blender: <a href="#a6ehfejuvpu1" id="a6ehfejuvpu1"></a>

* **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:

```
"Export": {
   "ExportBinaryFbx": true,
   "ExportFbxVersion": "FBX201400"
}
```

* 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\\
* 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>)\
  ![](/files/xkrdh9dgHz6DvASrxj9H)\\
* Export the FBX

### Blender to Snap Lens Studio: <a href="#v7x9a6ox1lqj" id="v7x9a6ox1lqj"></a>

* 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

    ![](/files/rug5ejOvG2mz7bYVuBGj)

    *Docs contributed by* [*Estella Tse*](https://www.estellatse.com/)*. Additional thanks to* [*Jose Andres Rosero*](https://twitter.com/never_render)


# Configuring Export

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:

```json
  "Export": {
    "ExportBinaryFbx": true,
    "ExportFbxVersion": "FBX201400",
    "ExportStrokeMetadata": true,
    "KeepStrokes": true,
    "KeepGroups": false,
    "Formats": {
      "fbx": true,
      "glb": true,
      "newglb": true,
      "json": true,
      "latk": true,
      "obj": true,
      "stl": false,
      "usd": true,
      "wrl": false
    }
```

* **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

## JSON Exports Include Sketch Metadata

When you export to JSON format, Open Brush now includes additional metadata about your sketch:

* Sketch creation date and modification time
* Author information (if configured)
* Sketch title and description
* Stroke count and complexity metrics
* Brush types used
* Camera information

This metadata is useful for:

* Cataloging and organizing exported sketches
* Analyzing sketch complexity and composition
* Building tools that process Open Brush exports
* Archiving and documentation purposes

The JSON export provides a complete data representation of your sketch that can be parsed by external tools and scripts.

* **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.

### Supported GLTF Extensions with New GLB exports

**Extensions supported**

* 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
* 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.

### Choosing between the new and old GLTF formats

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](/user-guide/open-brush-unity-sdk) then use the older GLB format
* If you're manually uploading to [Icosa Gallery](https://icosa.gallery/) then use the older GLB format
* If you're use the [Icosa three.js loader](https://github.com/icosa-foundation/three-icosa) 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](/alternate-and-experimental-builds/open-brush-beta-docs) or from other [experimental branches](/alternate-and-experimental-builds) will work better using the new exporter.

### Platform Support

<table><thead><tr><th width="151">Format</th><th align="center">Android/iOS (Standalone VR)</th><th align="center">PC (Tethered VR)</th></tr></thead><tbody><tr><td>FBX</td><td align="center"><mark style="color:red;">✘</mark></td><td align="center"><mark style="color:green;">✔</mark></td></tr><tr><td>GLB</td><td align="center"><mark style="color:green;">✔</mark></td><td align="center"><mark style="color:green;">✔</mark></td></tr><tr><td>NEWGLB</td><td align="center"><mark style="color:green;">✔</mark></td><td align="center"><mark style="color:green;">✔</mark></td></tr><tr><td>JSON</td><td align="center"><mark style="color:green;">✔</mark></td><td align="center"><mark style="color:green;">✔</mark></td></tr><tr><td>LATK</td><td align="center"><mark style="color:green;">✔</mark></td><td align="center"><mark style="color:green;">✔</mark></td></tr><tr><td>OBJ</td><td align="center"><mark style="color:red;">✘</mark></td><td align="center"><mark style="color:green;">✔</mark></td></tr><tr><td>STL</td><td align="center"><mark style="color:green;">✔</mark></td><td align="center"><mark style="color:green;">✔</mark></td></tr><tr><td>USD</td><td align="center"><mark style="color:red;">✘</mark></td><td align="center"><mark style="color:green;">✔</mark></td></tr><tr><td>WRL</td><td align="center"><mark style="color:green;">✔</mark></td><td align="center"><mark style="color:green;">✔</mark></td></tr><tr><td></td><td align="center"></td><td align="center"></td></tr></tbody></table>

### Breaking Apart Imported Models

This build supports a new feature - The existing "group/ungroup" button on the pop-out tray that appears when you activate the [Selection Tool](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/tools-panel/selection-options) 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.

### Importing Lights

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](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/lights-panel). Furthermore imported lights support point lights and spot lights - whereas the existing environment lights only support directional lights.

These additional lights will only affect imported 3d models - they will not affect brush strokes which ignore lights other than the ones configured in your [environment settings](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/extras-panel/lights-panel)

{% embed url="<https://www.youtube.com/watch?v=98drHT5DD7Y>" %}


# Plugins

{% embed url="<https://www.youtube.com/playlist?list=PL94EgLgEIJyIou6-PzO2vBTvcZQav2Ibq>" %}

You can open the Scripts Panel from a button on the [Labs Panel](/user-guide/using-the-open-brush-tools-quick-tools-and-menu-panels/the-admin-panel/labs-panel)

![](/files/EX9RxERi9my4PooB3tzw)

We won't be using the buttons on the bottom row at the moment. These are related to the older [HTTP API Scripts](/user-guide/open-brush-api) 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 [Tool Plugins](#tool-plugins), [Symmetry Plugins](#symmetry-plugins), [Pointer Plugins](#pointer-plugin) and [Background Plugins](#background-plugins).

## Understanding the different plugin types

### Pointer Plugin

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 [example Pointer Plugins](/user-guide/using-plugins/example-plugins/example-pointer-plugins).

### Symmetry Plugins

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 [example Symmetry Plugins](/user-guide/using-plugins/example-plugins/example-symmetry-plugins).

### Tool Plugins

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 [example Tool Plugins](/user-guide/using-plugins/example-plugins/example-tool-plugins).

### Background Plugins

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 [example Background Plugins](/user-guide/using-plugins/example-plugins/example-background-plugins).

## Selecting and Activating a Plugin

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.

## Plugin Parameters

![](/files/sEqyD0LVt5irBifhcFeu)

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.

## Discovering New Plugins

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 [Plugins Discord channel](https://discord.com/channels/783806589991780412/1054686775504797816) for info on any plugins.

## Installing Plugins

Place plugins inside your Open Brush/Plugins folder. Some plugins might use extra libraries. These should be placed in Plugins/LuaModules


# Example Plugins

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.

## General Tips

* 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.
* [Lazy Input](/user-guide/lazy-input) (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.
* 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.


# Example Pointer Plugins

### Ballistic Missile

<div align="left"><figure><img src="/files/qWa8v45gp0i85iBKT0Oe" alt="" width="375"><figcaption></figcaption></figure></div>

Launches a line from your brush which you can steer. Similar to [LaserBeam](#laserbeam) except that you can steer the brush stroke as it moves.

#### Parameters

* **Speed:** The speed of the missile

### Dashes

<div align="left"><img src="/files/RYNX2ypfJtN6DzXQcFby" alt="" width="375"></div>

Stops and restarts the stroke at regular intervals as you draw resulting in a dashed line.

#### Parameters

* **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

#### Tips

If you use this in conjunction with [Lazy Input Mode](/user-guide/lazy-input) then you'll need to draw very slowly on the default settings Dashes.

#### How it works

The script calls`Brush:ForcePaintingOn` and `Brush:ForcePaintingOn` based on the value of `Brush:DistanceDrawn`

### GridFollow

<div align="left"><figure><img src="/files/7aiBnYqS4ilU4MwMg53c" alt="" width="375"><figcaption></figcaption></figure></div>

Locks movement of the pointer to either the x, y or z axis depending on which direction your hand is mostly moving.

#### Parameters

* **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.

#### Tips

Draw slowly and deliberately. It can be tricky to get the hang of initially.

### LaserBeam

<div align="left"><figure><img src="/files/c1yW8PSh0IMztLtxwy1n" alt="" width="375"><figcaption></figcaption></figure></div>

The pointer continues moving in the direction you were pointing when you initially pressed the trigger. Pew pew\...

#### Parameters

* **Speed:** The speed of the beam

#### Tips

You definitely want to try this in conjunction with Symmetry Plugins - especially if you also spin the mirror widget.

### Loops

<div align="left"><figure><img src="/files/pQiP8xgr5Vw65jQyWG93" alt="" width="375"><figcaption></figcaption></figure></div>

The pointer moves around a circlular path with your current hand position as it's center.

#### Parameters

* **Speed:** The speed of the pointer
* **Radius:** The size of the circle it moves around

### Oscilloscope

Control your pointer with multiple waveforms to create patterns

#### Parameters

* **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

### PolygonBrush

<div align="left"><figure><img src="/files/DLqkzFNRxzD7LYMz5Ydy" alt="" width="375"><figcaption></figcaption></figure></div>

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.

#### Parameters

* **Points:** How many sides the polygon has
* **Size:** The outer radius of the polygon

### RainbowStrokes

<div align="left"><figure><img src="/files/zdM0ZPzWm4f755Hv5x3t" alt="" width="375"><figcaption></figcaption></figure></div>

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.

#### Parameters

* **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

### SineWave

<div align="left"><figure><img src="/files/q4VsVSNWFTsLebK0plgH" alt="" width="375"><figcaption></figcaption></figure></div>

Moves the pointer in a simple wave pattern as you draw.

#### Parameters

* **Frequency:** How close together the peaks of the waveform are
* **Amplitude:** The height of the waveform

### Spherograph

<div align="left"><figure><img src="/files/aAgc4Nrh2QEnRyYUn6Tm" alt="" width="375"><figcaption></figcaption></figure></div>

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.

#### Parameters

* **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

### Spirals

<div align="left"><figure><img src="/files/vYJc18F8OiaJLlpQJ6Pz" alt="" width="375"><figcaption></figcaption></figure></div>

The brush stroke moves in a circle but the radius increases the longer you keep the trigger pressed.

#### Parameters

* **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

### Spirograph

Draw a spirograph pattern as you move your brush. Ignores your hand position and simply uses the distance you've moved.

### StringArt

<div align="left"><figure><img src="/files/VeZLz2NpdtCI26Ee535k" alt="" width="375"><figcaption></figcaption></figure></div>

Additional lines are drawn from the initial point you started drawing to your current brush position.

#### Parameters

* **Rate:** How many frames to wait before drawing another connecting line

### Terrain

<div align="left"><figure><img src="/files/0DvrMnoRTeBGZ3NybLzs" alt="" width="375"><figcaption></figcaption></figure></div>

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.

#### Parameters

* **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

#### Tips

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 [low poly landscape Tool Plugin](/user-guide/using-plugins/example-plugins/example-tool-plugins#lowpolylandscape)

### Twist

<div align="left"><figure><img src="/files/er90AuYWXgzVIeJ3vgt2" alt="" width="375"><figcaption></figcaption></figure></div>

As you draw the position is controlled by your hand as normal. However the orientation of the stroke spins around by itself

#### Parameters

* **Speed:** How fast to spin around the axis

#### Tips

* 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.

### WandLerp

<div align="left"><figure><img src="/files/bC3pVqvnPmXw8PIJhp3e" alt="" width="375"><figcaption></figcaption></figure></div>

The brush position cycles back and forth between your brush hand and your other hand. Paint with both hands for a change...

#### Parameters

* **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

#### Tips

Move your hands close together or further apart to see different effects

### Wander

<div align="left"><figure><img src="/files/uOjdnpLiNB0bkIUZCzqg" alt="" width="375"><figcaption></figcaption></figure></div>

The brush stroke wanders off in random directions while you hold the trigger

#### Parameters

* **Speed:** How fast the pointer should move
* **Frames Per Path:** After this many frames, the stroke is restarted from the current brush position

### Wiggle

<div align="left"><figure><img src="/files/9nfY121oTyiNibK09WON" alt="" width="375"><figcaption></figcaption></figure></div>

Randomizes the brush position

#### Parameters

* **Wiggle Amount:** The amount of randomness to add to the brush position

### Wobble

<div align="left"><figure><img src="/files/Bgf7XqkQuxWEarq9fsJV" alt="" width="375"><figcaption></figcaption></figure></div>

Like Wiggle but uses a smooth noise function

#### Parameters

* **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)


# Example Symmetry Plugins

### AutoLathe

<div align="left"><figure><img src="/files/TVssDMSsZDy4KtH3g3sm" alt="" width="375"><figcaption></figcaption></figure></div>

Like spinning the mirror by hand but with precise control

#### Parameters

* **Speed:** How fast to spin
* **Angle X:** The axis tilt in the X direction
* **Angle Y:** The axis tilt in the Y direction

### Boids

A flock of pointers follows your hand using simple rules to control how they fly

<div align="left"><figure><img src="/files/0lYa5XnZxbezMS6Ws2tQ" alt="" width="375"><figcaption></figcaption></figure></div>

#### Parameters

* **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

### Ducklings

{% embed url="<https://www.youtube.com/watch?v=WkGY_nXPehc>" %}

The pointers follow your brush position but each one moves towards a point where your hand was further back in time

#### Parameters

* **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

### EllipseAround

{% embed url="<https://www.youtube.com/watch?v=e3JXcvarGkI>" %}

Copies of your stroke forming an ellipse - with optional color shifts

#### Parameters

* **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

### Frame

<div align="left"><figure><img src="/files/34bF5A0j5M3k3U9xuNOX" alt="" width="375"><figcaption></figcaption></figure></div>

A simple frame of points following your brush position

### HoldFirstClick

{% embed url="<https://www.youtube.com/watch?v=JS06ssbbCi0>" %}

Like [Many Around](#manyaround) except the widget always moves to where you start drawing

#### Parameters

* **Copies:** The number of strokes to draw at once

### ManyAlong

<div align="left"><figure><img src="/files/fd6eMR4hXMmkvrWyf5fz" alt="" width="375"><figcaption></figcaption></figure></div>

Linear copies of your stroke with optional color shifts

#### Parameters

* **Copies:** The number of strokes to draw at once
* **Distance:** How far each copy is from the next

### ManyAround

<div align="left"><figure><img src="/files/rduJ1T0EmCMsSQxL9POV" alt="" width="375"><figcaption></figcaption></figure></div>

Radial copies of your stroke with optional color shifts

#### Parameters

* **Copies:** The number of strokes to draw at once

### PointSymSpin

Works like activating Multimirror but the extra pointers spin around your brush position

#### Parameters

(todo)

### Pole

{% embed url="<https://www.youtube.com/watch?v=7YxjNvCY8ak>" %}

Multiple copies of your brush spaced between your left and right hand positions

#### Parameters

* **Copies:** The number of strokes to draw at once

### PolygonAround

<div align="left"><figure><img src="/files/3jUaPmEh9XhRMOudHENH" alt="" width="375"><figcaption></figcaption></figure></div>

Copies of your stroke forming an polygon

#### Parameters

* **Copies:** The number of strokes to draw at once
* **Sides:** The number of sides of the polygon

### RectangleAround

<div align="left"><figure><img src="/files/6OQrll4RrrIbrkQbERP9" alt="" width="375"><figcaption></figcaption></figure></div>

Copies of your stroke forming an rectangle

#### Parameters

* **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

### Spin

<div align="left"><figure><img src="/files/2Gu1tglXsWLPVYQua3UZ" alt="" width="375"><figcaption></figcaption></figure></div>

Multiple copies of your brush spinning around your actual brush position

#### Parameters

* **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

### StrokePoints

<div align="left"><figure><img src="/files/W1QueqDSUIqgWBIow0A7" alt="" width="375"><figcaption></figcaption></figure></div>

The previous stroke you drew is used as a template and multiple copies of the pointer are spread along it as you draw

#### Parameters

* **Point Spacing:** The distance to space out the copies along the stroke

### SuperEllipseAround

<div align="left"><figure><img src="/files/JGLEv1DmTXK5iQAkcInd" alt="" width="375"><figcaption></figcaption></figure></div>

Copies of your stroke forming a [superellipse](https://en.wikipedia.org/wiki/Superellipse)

#### Parameters

* **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

### Svg

<div align="left"><figure><img src="/files/vUsaON4pLSSWGrlxhN3i" alt="" width="375"><figcaption></figcaption></figure></div>

An example of using an SVG file as a template for symmetry patterns

### SvgAround

<div align="left"><figure><img src="/files/JApQKS7l0N9e6ZAHivU5" alt="" width="375"><figcaption></figcaption></figure></div>

Similar to [SVG](#svg) but centered around the Symmetry Widget

#### Parameters

* **Point Spacing:** The distance between each pointer around the shape

###


# Example Tool Plugins

### Circle

<div align="left"><figure><img src="/files/5yHeZn9ny6rKf90kjrDV" alt="" width="375"><figcaption></figcaption></figure></div>

Draws a circle centered on the position you first press the trigger with the radius and orientation controlled by where you release the trigger.

### Cube

<div align="left"><figure><img src="/files/owiZtLxMjjYORRyTLxMa" alt="" width="375"><figcaption></figcaption></figure></div>

Draws a cube centered on the position you first press the trigger with the size and orientation controlled by where you release the trigger.

#### Parameters

* **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

### LowPolyLandscape

{% embed url="<https://www.youtube.com/watch?v=uRlrzk91QN4>" %}

Draws tiles that follow a hilly landscape as you hold the trigger.

#### Parameters

* **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"

### Platonic

Creates wireframe brushstrokes for any of the 5 Platonic solids (Tetrahedron, Cube, Octahedron, Dodecahedron, Icosahedron)

#### Parameters

(todo)

### RandomAvatar

{% embed url="<https://www.youtube.com/watch?v=S9TzdMAbAbU>" %}

Calls an API to generate a random SVG icon using the [MultiAvatar ](https://multiavatar.com/)library

### Rays

<div align="left"><figure><img src="/files/vaBuCfQe8srE1EYBmRMK" alt="" width="375"><figcaption></figcaption></figure></div>

Draws lines from the position you start drawing to your current position.

#### Parameters

* **Spacing:** How often to draw a new stroke

### ScatterCubes

<div align="left"><figure><img src="/files/2JaelrBFy11PZmYl73Bh" alt="" width="375"><figcaption></figcaption></figure></div>

Switches to the Hull Brush and draws cubes of random size and color as you move your brush",

#### Parameters

* **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.

### Spiral

<div align="left"><figure><img src="/files/4R9HWPsDNix1cPTV0Jed" alt="" width="375"><figcaption></figcaption></figure></div>

Draws a conical spiral.

#### Parameters

* **Number of turns:**
* **Number of steps per turn:**

### SpiralSphere

<div align="left"><figure><img src="/files/RDI1TD8fcIJ2tcD4b1UA" alt="" width="375"><figcaption></figcaption></figure></div>

Draws a spherical spiral.

#### Parameters

* **Steps:**
* **Turns:**

### SuperFormula

<div align="left"><figure><img src="/files/9LXAQ7wd2KTsSNs8NfDK" alt="" width="375"><figcaption></figcaption></figure></div>

Draws a supershape using the [Super Formula](http://paulbourke.net/geometry/supershape/)

#### Parameters

* **Symmetry:**
* **n1:**
* **n2:**
* **n3:**

### SvgHeart

<div align="left"><figure><img src="/files/PVQfVWtgQ9eUwIOq4R0f" alt="" width="375"><figcaption></figcaption></figure></div>

Draws a heart shape using an [SVG Path](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths)

#### Parameters

* **Point Spacing:**

### TorusKnot

Draws a brush stroke forming a variety of interlocking knot shapes known as [Torus Knots](https://en.wikipedia.org/wiki/Torus_knot)

#### Parameters

(todo)

### VoxelLandscape

<div align="left"><figure><img src="/files/NrSm4kSB1vDbwicKUJNP" alt="" width="375"><figcaption></figcaption></figure></div>

Draws a blocky landscape (best used with a hull brush).

#### Parameters

* **Horizontal Spacing:**
* **Verticle Spacing:**

### Voxels

Draws regular blocks in space as you draw (best used with the hull brush)

<div align="left"><figure><img src="/files/6Dx7GknYfr1GJv7NOe3T" alt="" width="375"><figcaption></figcaption></figure></div>

#### Parameters

* **Grid Size:**

### Words

{% embed url="<https://www.youtube.com/watch?v=x-3K_0jT3Pg>" %}

Draws words that follows your brush. Tries to access the clipboard so try copying in some text.

#### Parameters

* **Size:**
* **Spacing:**


# Example Background Plugins

### AutoSpinSymmetry

Allows you to precisely control the spin speed of the symmetry widget

### CrossfadeLayers

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

### DrawAndAnimateStrokes

An example of drawing procedurally on startup and then using shader parameters to animate the strokes it has created

### Lines

An example of drawing continuously. It draws random straight lines for as long as the script is active.

### RandomPanorama

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!


# Writing Plugins

Plugins are written in the scripting language [Lua](https://www.lua.org) 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](https://wiki.factorio.com/Tutorial:Scripting), [Garry's Mod](https://wiki.facepunch.com/gmod/Beginner_Tutorial_Intro)*,* [Roblox](https://create.roblox.com/docs/tutorials/scripting/basic-scripting/intro-to-scripting), [LÖVR](https://lovr.org/) 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.

## Libraries

In addition to the [API commands](https://icosa.gitbook.io/open-brush-plugin-scripting-docs) you can use most of the [Lua Standard Library](https://www.moonsharp.org/MoonSharpStdLib.pdf). Another included library is [Lume](https://github.com/rxi/lume) which you can use via `require "lume"`

### Built-in functions and properties

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.](https://icosa.gitbook.io/open-brush-plugin-scripting-docs)

* **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

### Script Parameters

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:

```lua
Parameters = {
    speed={label="Speed", type="float", min=0.01, max=32, default=16},
    radius={label="Radius", type="float", min=0.01, max=5, default=1},
}

function Main()
    angle = App.time * speed
    r = Brush.pressure * radius;
    pos = Vector3:New(Math.Sin(angle) * r, Math:Cos(angle) * r, 0)
    return Transform:New(pos)
end
```

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 text label 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.

#### Available Parameter Types

The following parameter types are available for use in your plugins:

**Float and Integer Sliders**

```lua
Parameters = {
    floatValue={label="Choose Value", type="float", min=0, max=1, default=0.5},
    intValue={label="Pick a Number", type="int", min=1, max=8, default=4},
}
```

**Color Picker**

```lua
Parameters = {
    color={label="Choose Color", type="color", default=Color.red},
}
```

**Toggle/Checkbox**

```lua
Parameters = {
    toggle={label="Toggle Something", type="toggle", default=false},
}
```

**Text Input**

```lua
Parameters = {
    text={label="Enter Some Text", type="text", default="hello"},
}
```

**List/Dropdown**

```lua
Parameters = {
    list={label="Choose Option", type="list", items={"Cats", "Dogs", "Bird", "Fishes"}, default="Fishes"},
}
```

### Coordinate Spaces

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:

```lua
Settings = {space="canvas"}

function Main()
    return Transform:New(
        Vector3:New(Brush.position.x, 0, Brush.position.z)
    )
end
```

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".


# Getting Started

## Choosing an Editor

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:

{% embed url="<https://code.visualstudio.com/download>" %}

## Autocomplete and Intellisense for Lua scripts

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.

2. Launch Visual Studio Code.
3. Click on the button on the left that shows the Extensions sidebar:\
   ![](/files/iV6d5QRbwjozTdvQZqsm)
4. Search for "Lua" and look for the sumneko extension:
5. Click to install it and wait for it to finish installing
6. Click the small cog icon and then open the Extension Settings:\
   ![](/files/SBwqCX6F14eFPrZ4UdTe)
7. Optionally you can hide a lot of spurious warnings by disabling "lowercase-global" warnings under **Lua> Diagnostics: Disable:**\
   ![](/files/Jph6DsWhi4pa4MKvG3bu)\
   (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\...)
8. Scroll down to **Lua> Workspace: Library** and add the path to your LuaModules folder:\ <br>
9. 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:

```lua
function Start()
    print (App.
```

As soon as you type the period you should see a list of suggestions that match the "App" part:

![](/files/LKrhG8iwD0WMLR8XbuVU)

If not - check you've followed all the steps above.

{% hint style="info" %}
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.
{% endhint %}

{% hint style="info" %}
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
{% endhint %}

## Next Steps

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.


# Tweaking existing plugins

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.

Any of the example plugins can be copied to your Open Brush plugins folder simply by clicking the copy button for that plugin type: <img src="/files/kpKSQh5niv6HsM4f6Sy8" alt="" data-size="line">

(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.


# Writing a Pointer Plugin

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](https://icosa.gitbook.io/open-brush-plugin-scripting-docs/readme/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:

```lua
function Main()
    return Transform.identity
end
```

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:

```lua
-- Explicitly returns zero for position, rotation and scale.
return Transform:New(Vector3.zero, Rotation.zero, 0)

-- If you miss out rotation and/or scale they are assumed to be zero
return Transform:New(Vector3.zero)

-- Vector3.zero is itself shorthand for this:
return Transform:New(Vector3:New(0,0,0))

-- You can create a transform with only a position in a slightly shorter way:
return Transform:Position(0,0,0)
```

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.*

```lua
function Main()
    return Transform:New(0,1,0)
end

-- or

function Main()
    return Transform:Vector3.up
end
```

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.

```lua
function Main()
    return Transform:Position(0, App.time, 0)
end
```

App.time is a property of the [App](https://icosa.gitbook.io/open-brush-plugin-scripting-docs/readme/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.

```lua
function Main()
    return Transform:Position(0, Waveform:Triangle(App.time, 1), 0)
end
```

That single return line is getting a bit complicated. Let's split things over two lines to make it easier to read:

```lua
function Main()
    y = Waveform:Triangle(App.time, 1)
    return Transform:Position(0, y, 0)
end
```

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](https://en.wikipedia.org/wiki/Triangle_wave)

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](/user-guide/using-plugins/writing-plugins/getting-started) then you should have seen a hint pop up when you typed the first open bracket:

<figure><img src="/files/Vvumuro4XulMrBb5XJQF" alt=""><figcaption></figcaption></figure>

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:

```lua
Parameters = {
    frequency={label="Frequency", type="float", min=0.01, max=10, default=2}
}

function Main()
    y = Waveform:Triangle(App.time, Parameters.frequency)
    return Transform:Position(0, y, 0)
end
```

We've now told Open Brush that this plugin should show a slider in it's [Parameters popup](/user-guide/using-plugins#plugin-parameters) which changes the frequency that the pointer moves.


# Writing a Symmetry Plugin

Symmetry Plugins are similar to Pointer plugins with a few differences:

1. They can return a list of transforms that represent multiple pointers.
2. They can modify the color, size and brush type for each of the strokes separately.
3. 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](/alternate-and-experimental-builds/old-or-completed-feature-builds/multi-mirror) 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:

```lua
function Main()
    return {Transform.identity}
end
```

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](/user-guide/using-plugins/writing-plugins#coordinate-spaces). 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:

```lua
Settings = {space="pointer"}

function Main()
    return {Transform.identity}
end
```

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:

```lua
function Main()
    origin = Transform.identity
    brushOffset = Transform:New(Symmetry.brushOffset)
    return {
        Transform:Lerp(origin, brushOffset, 0.2),
        Transform:Lerp(origin, brushOffset, 0.4),
        Transform:Lerp(origin, brushOffset, 0.6),
        Transform:Lerp(origin, brushOffset, 0.8)
    }
end
```

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](https://icosa.gitbook.io/open-brush-plugin-scripting-docs/readme/transform) with it's position set to the value of`Symmetry.brushOffset`. This is a [Vector3](https://icosa.gitbook.io/open-brush-plugin-scripting-docs/readme/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 by`Brush.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.

```lua
function Main()
    copies = 10
    pointers = Path:New()
    angleStep = 360 / copies 
    for i = 1, copies do
        angle = i * angleStep
        pointer = Transform:New(Symmetry.brushOffset, Rotation:New(0, angle, 0))
        pointers:Insert(pointer)
    end
    return pointers
end
```

Some things to note here:

1. 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.
2. 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.
3. `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.
4. 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.


# Writing a Tool Plugin

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.*

```lua
function Main()
    if Brush.triggerPressedThisFrame then
        return {}
    end
end
```

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:

```lua
function Main()
    if Brush.triggerPressedThisFrame then
        return {
            Transform:Position(-1, -1, 0),
            Transform:Position(1, -1, 0),
            Transform:Position(1, 1, 0),
            Transform:Position(-1, 1, 0),
            Transform:Position(-1, -1, 0)
        }
    end
end
```

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:

```lua
function Main()
    if Brush.triggerPressedThisFrame then
        myPath = Path:New({
            Transform:Position(-1, -1, 0),
            Transform:Position(1, -1, 0),
            Transform:Position(1, 1, 0),
            Transform:Position(-1, 1, 0),
            Transform:Position(-1, -1, 0)
        })
        return myPath:SubdivideSegments(5)
    end
end
```

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`](https://icosa.gitbook.io/open-brush-plugin-scripting-docs/readme/path#path-subdividesegments-parts) 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:

```lua
function Main()
    if Brush.triggerReleasedThisFrame then
        points = Path:New()
        for angle = 0, 360, 10 do
            position2d = Vector2:PointOnCircle(angle)
            points:Insert(Transform:Position(position2d:OnZ()))
        end
        return points
    end
end
```

There's a few new things here:

1. a loop that begins `for...do`, this is a standard lua construct and works similarly to loops in other languages.
2. 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.
3. 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)
4. 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.


# Writing a Background Plugin

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:

1. Pointer Plugins use the returned value to change the pointer position, rotation or scale.
2. Symmetry Plugins use the returned values to create multiple new pointers.
3. 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:

```lua
function Main()
    if Brush.triggerPressedThisFrame then
        myPath = Path:New()
        position = getRandomPosition()
        myPath:Insert(Transform:New(position))
        myPath:Insert(Transform:New(position))
        myPath:Draw()
    end
end

function getRandomPosition()
    return Brush.position + Random.insideUnitSphere
end
```

There are some potentially new details to be aware of here:

1. We are defining our own function to generate a random position around the current brush position
2. 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
3. We are manually drawing the path with `myPath:Draw()`


# Defining and Drawing Brush Strokes

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:

1. 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
2. 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:

```lua
origin = Transform:New(Vector3:New(0, 0, 0), Rotation.forwards)
return {origin, origin:TranslateBy(2, 2, 0)}
```

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`](https://icosa.gitbook.io/open-brush-plugin-scripting-docs/readme/path). The advantage of using this class is that also has many useful methods for modifying paths.

```lua
origin = Transform:New(Vector3:New(0, 0, 0), Rotation.forwards)
path = Path:New({origin, origin:TranslateBy(2, 2, 0)})
path:RotateBy(0, 45, 0)
return path
```

(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.


# Open Brush Unity SDK

Using Open Brush with Unity

## About <a href="#j7bdhxvyulyl" id="j7bdhxvyulyl"></a>

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

## Requirements <a href="#q9lph11ngm09" id="q9lph11ngm09"></a>

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](#_nvutjzw2fj1u) to fix errors related to "CSCore".

## Getting the code <a href="#iqjwk94xwdgd" id="iqjwk94xwdgd"></a>

Download the latest version of the toolkit from:[<br>](https://github.com/icosa-foundation/open-brush-toolkit)<https://github.com/icosa-foundation/open-brush-toolkit/releases>

The SDK comes in the form of a Unity Package. To import:

1. Open Unity
2. Create a project or open an existing one
3. Double click the downloaded .unitypackage file, or go to Assets > Import Package > Custom Package.
4. Import the package

## Importing a sketch <a href="#id-6wwms1xya8em" id="id-6wwms1xya8em"></a>

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:

1. Open Tilt Brush, load your sketch
2. Click the **\[...]** icon in the settings area of your hand menu
3. Click the \*\*Labs \*\*icon
4. Hit **Export** in the floating window that pops up

To import a sketch into your scene:

1. Find the exported files:
   1. On a PC or Mac look in **Documents/Open Brush/Exports**
   2. If you created the sketch on a standalone Quest thenconnect it to your PC/Mac by following [these instructions](https://www.meta.com/en-gb/help/quest/articles/headsets-and-accessories/using-your-headset/transfer-files-from-computer-to-headset/) and then browse to the Quest in Explorer/Finder and look in **Internal Shared Storage/Open Brush/Exports**
2. Copy the .glb file into your Unity project
3. 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*

## Tips <a href="#ibglt4zbyabz" id="ibglt4zbyabz"></a>

### Fixing CSCore errors (or other errors related to Audio Reactivity) <a href="#nvutjzw2fj1u" id="nvutjzw2fj1u"></a>

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:

1. The folder ThirdParty\CSCore
2. The folder ThirdParty\Reaktion
3. These files:
   1. TiltBrush\Scripts\VisualizerManager
   2. TiltBrush\Scripts\VisualizerAudioInput
   3. TiltBrush\Scripts\Editor\VisualizerManagerEditor

### "My brushes look different to Open Brush" (Linear vs Gamma) <a href="#nvutjzw2fj1u" id="nvutjzw2fj1u"></a>

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](https://docs.unity3d.com/Manual/LinearRendering-LinearOrGammaWorkflow.html). The shaders are set to Gamma mode by default. **If you wish to use Linear, add this call somewhere in your program**.

```
Shader.EnableKeyword("TBT_LINEAR_TARGET");
```

Note: while this improves the colour accuracy, due to [fundamental differences](https://docs.unity3d.com/Manual/LinearRendering-LinearOrGammaWorkflow.html) between linear and gamma rendering, brushes may still not exactly replicate the look of their gamma counterparts.

### Audio Reactivity <a href="#st8oph1ghsgx" id="st8oph1ghsgx"></a>

You can make the brushes wiggle to the audio in your scene:

1. Drag the\*\* \[Tilt Brush Audio Reactivity] prefab\*\* into your scene
2. 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:

![](/files/-MjYvTa7FC4tN1CVvHMG)

### Bloom <a href="#id-7ljsa6ylg4rb" id="id-7ljsa6ylg4rb"></a>

![](/files/75ErALR2GKe0os8gsx0o)\
You can achieve\_ an Open Brush look\_ by adding **Bloom**, using Unity’s built-in shaders:

1. Import the Standard Assets “Effects” package (Assets menu / Import Package / Effects)
2. \*\*Important: \*\*Enable your camera’s HDR checkbox\
   ![](/files/75ErALR2GKe0os8gsx0o)
3. Add the Bloom post-processing effect, these are recommended settings:\
   ![](/files/75ErALR2GKe0os8gsx0o)

Internally, Open Brush uses a modified version of Sonic Ether bloom, which has been released as [open source](https://github.com/sonicether/SE-Natural-Bloom-Dirty-Lens).


# Open Brush API

### What does it do?

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:

![](/files/XNYWPlodRJhrr297xiHl)

Example output from the form shown above:

![](/files/-MikxGjITHhzOjjW2XAX)

Some output from other example scripts that are included:

![](/files/-MikxGjKAh92kdzsw2f_)

![](/files/-MikxGjJ9FAc6I-7aOZX)

### What's it good for?

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.

### Can I run scripts automatically at startup?

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:

```
load.named=startup.tilt
tool.fly
viewonly.toggle
```

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:

```
import.model=mysketch.glb
tool.fly
viewonly.toggle
```

Voila - a way to let people fly around your sketches without being able to modify them.

### How do I configure it

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:

```
"Flags": {
  "EnableApiRemoteCalls": false,
  "EnableApiCorsHeaders": false
},
```

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.

### How do I use Open Brush without a headset?

See [Monoscopic mode](/user-guide/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.

### What's the simplest way to use the API?

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>

### What commands are available?

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](/user-guide/open-brush-api/api-commands) (not neccesarily as up to date as the list you get directly from the app)

### How do I use the API from javascript

The [help](http://localhost:40074/help) has got some example scripts to look at.

Here's a simple piece of code to send a single command:

```
var xmlHttp = new XMLHttpRequest();
xmlHttp.open('GET',  '/api/v1?brush.type=ink', false);
xmlHttp.send(null);
```

### How about other languages?

Any language that can send http requests should work.

### Known Issues with the API

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.

### How to get help

With a custom build running you can visit:

```
http://localhost:40074/help
```

and follow links to useful info such as a full list of commands, examples scripts etc


# Retrieving a preview image

<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:

```
function refreshCameraPreview() {
    var image = document.getElementById("cameraPreview");
    image.src = "http://localhost:40074/cameraview?t=" + new Date().getTime();
}
setInterval(refreshCameraPreview, 1000);
```

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: [Configuring the Open Brush API](/user-guide/open-brush-api#how-do-i-configure-it)


# API Commands List

[API Docs](/user-guide/open-brush-api)

{% hint style="info" %}
*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*](http://localhost:40074/help/commands) *as that will always be current.*
{% endhint %}

{% hint style="info" %}
*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* ](/developer-notes/github-wiki/monoscopicmode)*version if you don't have a VR headset attached.*
{% endhint %}

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](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.

### Command List

{% hint style="info" %}
Correct for beta version as of Oct 21 2025)
{% endhint %}

**listenfor.strokes** (string url) [Try it](http://localhost:40074/api/v1?/api/v1?listenfor.strokes=http://localhost:8000/)

Adds the url of an app that wants to receive the data for a stroke as each one is finished

**showfolder.scripts** [Try it](http://localhost:40074/api/v1?/api/v1?showfolder.scripts)

Opens the user's Scripts folder on the desktop

**showfolder.exports** [Try it](http://localhost:40074/api/v1?/api/v1?showfolder.exports)

Opens the user's Exports folder on the desktop

**spectator.move.to** (Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?spectator.move.to=1,1,1)

Moves the spectator camera to the given position

**spectator.move.by** (Vector3 amount) [Try it](http://localhost:40074/api/v1?/api/v1?spectator.move.by=1,1,1)

Moves the spectator camera by the given amount

**user.move.to** (Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?user.move.to=1,1,1)

Moves the user to the given position

**user.move.by** (Vector3 amount) [Try it](http://localhost:40074/api/v1?/api/v1?user.move.by=1,1,1)

Moves the user by the given amount

**spectator.turn.y** (float angle) [Try it](http://localhost:40074/api/v1?/api/v1?spectator.turn.y=45)

Rotates the spectator camera left or right.

**spectator.turn.x** (float angle) [Try it](http://localhost:40074/api/v1?/api/v1?spectator.turn.x=45)

Rotates the spectator camera up or down.

**spectator.turn.z** (float angle) [Try it](http://localhost:40074/api/v1?/api/v1?spectator.turn.z=45)

Tilts the angle of the spectator camera clockwise or anticlockwise.

**user.turn.y** (float angle) [Try it](http://localhost:40074/api/v1?/api/v1?user.turn.y=45)

Rotates the user camera left or right.

**user.turn.x** (float angle) [Try it](http://localhost:40074/api/v1?/api/v1?user.turn.x=45)

Rotates the user camera up or down. (monoscopic mode only)

**user.turn.z** (float angle) [Try it](http://localhost:40074/api/v1?/api/v1?user.turn.z=45)

Tilts the angle of the user camera clockwise or anticlockwise. (monoscopic mode only)

**scene.scale.to** (float scale) [Try it](http://localhost:40074/api/v1?/api/v1?scene.scale.to=0.5)

Sets the scene scale to the given value

**scene.scale.by** (float amount) [Try it](http://localhost:40074/api/v1?/api/v1?scene.scale.by=1.5)

Scales the scene by the given amount

**spectator.direction** (Vector3 direction) [Try it](http://localhost:40074/api/v1?/api/v1?spectator.direction=45,45,0)

Points the spectator camera to look in the specified direction. Angles are given in x,y,z degrees

**user.direction** (Vector3 direction) [Try it](http://localhost:40074/api/v1?/api/v1?user.direction=45,45,0)

Points the user camera to look in the specified direction. Angles are given in x,y,z degrees. (Monoscopic mode only)

**spectator.look.at** (Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?spectator.look.at=1,2,3)

Points the spectator camera towards a specific point

**user.look.at** (Vector3 direction) [Try it](http://localhost:40074/api/v1?/api/v1?user.look.at=1,2,3)

Points the user camera towards a specific point (In VR this only changes the y axis. In monoscopic mode it changes all 3 axes)

**spectator.mode** (string mode) [Try it](http://localhost:40074/api/v1?/api/v1?spectator.mode=stationary)

Sets the spectator camera mode to one of stationary, slowFollow, wobble, circular

**spectator.hide** (string thing) [Try it](http://localhost:40074/api/v1?/api/v1?spectator.hide=panels)

Hides the chosen type of elements from the spectator camera (widgets, strokes, selection, headset, panels, ui

**brush.move.to** (Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?brush.move.to=widgets)

Moves the brush to the given coordinates

**brush.move.to.hand** (string hand, Boolean alsoRotate) [Try it](http://localhost:40074/api/v1?/api/v1?brush.move.to.hand=r)

Moves the brush to the given hand (l or r

**brush.move.by** (Vector3 offset) [Try it](http://localhost:40074/api/v1?/api/v1?brush.move.by=1,1,1)

Moves the brush by the given amount

**brush.move** (float distance) [Try it](http://localhost:40074/api/v1?/api/v1?brush.move=1)

Moves the brush forward by 'distance' without drawing a line

**brush.draw** (float distance) [Try it](http://localhost:40074/api/v1?/api/v1?brush.draw=2)

Moves the brush forward by 'distance' and draws a line

**brush.turn.y** (float angle) [Try it](http://localhost:40074/api/v1?/api/v1?brush.turn.y=45)

Changes the brush direction to the left or right. Angle is measured in degrees

**brush.turn.x** (float angle) [Try it](http://localhost:40074/api/v1?/api/v1?brush.turn.x=45)

Changes the brush direction up or down. Angle is measured in degrees

**brush.turn.z** (float angle) [Try it](http://localhost:40074/api/v1?/api/v1?brush.turn.z=45)

Rotates the brush clockwise or anticlockwise. Angle is measured in degrees

**brush.look.at** (Vector3 direction) [Try it](http://localhost:40074/api/v1?/api/v1?brush.look.at=1,2,3)

Changes the brush direction to look at the specified point

**brush.look.forwards** [Try it](http://localhost:40074/api/v1?/api/v1?brush.look.forwards)

Changes the brush direction to look forwards

**brush.look.up** [Try it](http://localhost:40074/api/v1?/api/v1?brush.look.up)

Changes the brush direction to look upwards

**brush.look.down** [Try it](http://localhost:40074/api/v1?/api/v1?brush.look.down)

Changes the brush direction to look downwards

**brush.look.left** [Try it](http://localhost:40074/api/v1?/api/v1?brush.look.left)

Changes the brush direction to look to the left

**brush.look.right** [Try it](http://localhost:40074/api/v1?/api/v1?brush.look.right)

Changes the brush direction to look to the right

**brush.look.backwards** [Try it](http://localhost:40074/api/v1?/api/v1?brush.look.backwards)

Changes the brush direction to look backwards

**brush.home.reset** [Try it](http://localhost:40074/api/v1?/api/v1?brush.home.reset)

Resets the brush position and direction

**brush.home.set** [Try it](http://localhost:40074/api/v1?/api/v1?brush.home.set)

Sets the current brush position and direction as the new home. This persists in new sketches

**brush.transform.push** [Try it](http://localhost:40074/api/v1?/api/v1?brush.transform.push)

Stores the current brush position and direction on to a stack

**brush.transform.pop** [Try it](http://localhost:40074/api/v1?/api/v1?brush.transform.pop)

Pops the most recent current brush position and direction from the stack

**debug.brush** [Try it](http://localhost:40074/api/v1?/api/v1?debug.brush)

Logs some info about the brush

**text.add** (string text) [Try it](http://localhost:40074/api/v1?/api/v1?text.add=Hello%20world!)

Adds a text widget to the sketch

**video.import** (string location) [Try it](http://localhost:40074/api/v1?/api/v1?video.import=animated-logo.mp4)

Imports a video given a url or a filename in Media Library\Videos

**skybox.import** (string location) [Try it](http://localhost:40074/api/v1?/api/v1?skybox.import=panorama.jpg)

Sets the skybox from either a url or a filename in Media Library\BackgroundImages (Images loaded from a url are saved locally first)

**image.import** (string location) [Try it](http://localhost:40074/api/v1?/api/v1?image.import=OpenBrushLogo.png)

Imports an image given a url or a filename in Media Library\Images (Images loaded from a url are saved locally first)

**environment.type** (string name) [Try it](http://localhost:40074/api/v1?/api/v1?environment.type=pistachio)

Sets the current environment

**panel.open** (string name, float x, float y, float z) [Try it](http://localhost:40074/api/v1?/api/v1?panel.open=scripts,4,12,4)

Opens a given panel at the given position

**panel.close** (string name) [Try it](http://localhost:40074/api/v1?/api/v1?panel.close=scripts)

Closes a given panel

**panel.position** (string name, Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?panel.position=4,12,4)

Sets position of a given panel

**panel.rotation** (string name, Vector3 rotation) [Try it](http://localhost:40074/api/v1?/api/v1?panel.rotation=4,12,4)

Sets rotation of a given panel

**strokes.debug** [Try it](http://localhost:40074/api/v1?/api/v1?strokes.debug)

Logs some debug info about the strokes

**panel.attach** (string name) [Try it](http://localhost:40074/api/v1?/api/v1?panel.attach=scripts)

Attaches the given panel to the user's wand

**panel.detach** (string name, Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?panel.detach=scripts)

Detaches the given panel from the user's wand

**layer.add** [Try it](http://localhost:40074/api/v1?/api/v1?layer.add)

Adds a new layer

**layer.clear** (int layer) [Try it](http://localhost:40074/api/v1?/api/v1?layer.clear=2)

Clears the contents of a layer

**debug.ram** (Boolean active) [Try it](http://localhost:40074/api/v1?/api/v1?debug.ram)

Enable/Disable logging of RAM usage to the in-app console (Android only)

**layer.delete** (int layer) [Try it](http://localhost:40074/api/v1?/api/v1?layer.delete=1)

Deletes a layer

**layer.squash** (int squashedLayer, int destinationLayer) [Try it](http://localhost:40074/api/v1?/api/v1?layer.squash=1,0)

Move everything from one layer to another then removes the empty layer

**layer.activate** (int layer) [Try it](http://localhost:40074/api/v1?/api/v1?layer.activate=2)

Make a layer the active layer

**layer.show** (int layer) [Try it](http://localhost:40074/api/v1?/api/v1?layer.show=2)

Make a layer visible

**layer.hide** (int layer) [Try it](http://localhost:40074/api/v1?/api/v1?layer.hide=2)

Hide a layer

**layer.toggle** (int layer) [Try it](http://localhost:40074/api/v1?/api/v1?layer.toggle=2)

Toggles a layer between visible and hidden

**model.select** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?model.select=2)

Selects a 3d model by index.

**model.position** (int index, Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?model.position=2,6,8)

Move a 3d model to the given coordinates

**model.rotation** (int index, Vector3 rotation) [Try it](http://localhost:40074/api/v1?/api/v1?model.rotation)

Set a model's rotation to the given angles

**model.scale** (int index, float scale) [Try it](http://localhost:40074/api/v1?/api/v1?model.scale)

Set a model's scale to the amount

**symmetry.position** (Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.position=2,6,8)

Move the symmetry widget to the given coordinates

**symmetry.set.rotation** (Vector3 rotation) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.set.rotation=45,30,0)

Sets the symmetry widget rotation

**symmetry.set.transform** (Vector3 position, Vector3 rotation) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.set.transform=2,6,8,45,30,0)

Sets the position and rotation of the symmetry widget

**brush.force.painting.on** (Boolean active) [Try it](http://localhost:40074/api/v1?/api/v1?brush.force.painting.on=true)

Turns on or off an override that paints even if the trigger is not pressed.

**brush.force.painting.off** (Boolean active) [Try it](http://localhost:40074/api/v1?/api/v1?brush.force.painting.off=false)

Turns on or off an override that stops the user painting even if the trigger is pressed.

**brush.new\.stroke** [Try it](http://localhost:40074/api/v1?/api/v1?brush.new.stroke)

Ends the current stroke and starts a new one next frame

**image.select** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?image.select=2)

Selects an image by index.

**image.delete** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?image.delete=2)

Deletes an image by index.

**video.delete** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?video.delete=2)

Deletes a video by index.

**model.delete** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?model.delete=2,6,8)

Deletes a 3d model by index.

**guide.delete** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?guide.delete=2)

Deletes a guide by index.

**image.position** (int index, Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?image.position=2,1,6,8)

Move an image to the given coordinates

**image.rotation** (int index, Vector3 rotation) [Try it](http://localhost:40074/api/v1?/api/v1?image.rotation)

Set a images rotation to the given angles

**image.scale** (int index, float scale) [Try it](http://localhost:40074/api/v1?/api/v1?image.scale)

Set a images scale to the amount

**light.position** (int index, Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?light.position)

Move a light to the given coordinates

**light.rotation** (int index, Vector3 rotation) [Try it](http://localhost:40074/api/v1?/api/v1?light.rotation)

Set a light's rotation to the given angles

**image.formEncode** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?image.formEncode=2)

Converts an image to a string suitable for use in a form

**image.base64Decode** (string base64, string filename) [Try it](http://localhost:40074/api/v1?/api/v1?image.base64Decode)

Saves an image based on a base64 encoded string

**scripts.initPluginScripting** [Try it](http://localhost:40074/api/v1?/api/v1?scripts.initPluginScripting=)

Call this before using any HTTP endpoint that accesses plugins (including html pages that list plugins)

**scripts.toolscript.activate** (string scriptName) [Try it](http://localhost:40074/api/v1?/api/v1?scripts.toolscript.activate=Spiral)

Activate the given tool script

**scripts.toolscript.deactivate** [Try it](http://localhost:40074/api/v1?/api/v1?scripts.toolscript.deactivate=Spiral)

Dectivate the tool script

**scripts.symmetryscript.activate** (string scriptName) [Try it](http://localhost:40074/api/v1?/api/v1?scripts.symmetryscript.activate=Boids)

Activate the given symmetry script

**scripts.symmetryscript.deactivate** [Try it](http://localhost:40074/api/v1?/api/v1?scripts.symmetryscript.deactivate=Boids)

Dectivate the symmetry script

**scripts.pointerscript.activate** (string scriptName) [Try it](http://localhost:40074/api/v1?/api/v1?scripts.pointerscript.activate=Loops)

Activate the given pointer script

**scripts.pointerscript.deactivate** [Try it](http://localhost:40074/api/v1?/api/v1?scripts.pointerscript.deactivate=Loops)

Dectivate the pointer script

**scripts.backgroundscript.activate** (string scriptName) [Try it](http://localhost:40074/api/v1?/api/v1?scripts.backgroundscript.activate=Lines)

Activate the given background script

**scripts.backgroundscript.deactivate** (string scriptName) [Try it](http://localhost:40074/api/v1?/api/v1?scripts.backgroundscript.deactivate=Lines)

Dectivate the given background script

**scripts.backgroundscript.activateall** [Try it](http://localhost:40074/api/v1?/api/v1?scripts.backgroundscript.activateall)

Dectivate all background scripts

**scripts.backgroundscript.deactivateall** [Try it](http://localhost:40074/api/v1?/api/v1?scripts.backgroundscript.deactivateall)

Dectivate all background scripts

**guide.add** (string type) [Try it](http://localhost:40074/api/v1?/api/v1?guide.add=cube)

Adds a guide to the scene (cube, sphere, capsule, cone, ellipsoid)

**guide.select** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?guide.select=2)

Selects a guide by index.

**guide.position** (int index, Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?guide.position=2,4,10,-4)

Move a guide to the given coordinates

**guide.scale** (int index, Vector3 scale) [Try it](http://localhost:40074/api/v1?/api/v1?guide.scale=2,1.5,1,1.5)

Sets the (non-uniform) scale of a guide

**draw\.paths** (string jsonString) [Try it](http://localhost:40074/api/v1?/api/v1?draw.paths=\[\[0,0,0],\[1,0,0],\[1,1,0]],\[\[0,0,-1],\[-1,0,-1],\[-1,1,-1]])

Draws a series of paths at the current brush position \[\[\[x1,y1,z1],\[x2,y2,z2], etc...]]. Does not move the brush position

**brush.pathsmoothing** (float amount) [Try it](http://localhost:40074/api/v1?/api/v1?brush.pathsmoothing=0.1)

Sets the amount of smoothing applied to brush paths at corners. Default is 0.10 turns off smoothing and you'll have to ensure you create enough points or else the path may end up smoothed to nothing.

**draw\.path** (string jsonString) [Try it](http://localhost:40074/api/v1?/api/v1?draw.path=\[0,0,0],\[1,0,0],\[1,1,0],\[0,1,0])

Draws a path at the current brush position \[x1,y1,z1],\[x2,y2,z2], etc.... Does not move the brush position

**draw\.stroke** (string jsonString) [Try it](http://localhost:40074/api/v1?/api/v1?draw.stroke=\[0,0,0,0,180,90,.75],\[1,0,0,0,180,90,.75],\[1,1,0,0,180,90,.75],\[0,1,0,0,180,90,.75])

Draws an exact brush stroke including orientation and pressure

**draw\.polygon** (int sides, float radius, float angle) [Try it](http://localhost:40074/api/v1?/api/v1?draw.polygon=5,2.5,45)

Draws a polygon at the current brush position. Does not move the brush position

**draw\.text** (string text) [Try it](http://localhost:40074/api/v1?/api/v1?draw.text=hello%20world)

Draws the characters supplied at the current brush position

**draw\.opentypetext** (string text, string fontPath) [Try it](http://localhost:40074/api/v1?/api/v1?draw.opentypetext=hello%20world,hello%20world,calibri.ttf)

Same as draw text but uses an opentype font (the font should be in a Fonts folder in your Open Brush folder)

**draw\.svg** (string svg) [Try it](http://localhost:40074/api/v1?/api/v1?draw.svg)

Draws an entire SVG document

**draw\.svg.path** (string svgPath) [Try it](http://localhost:40074/api/v1?/api/v1?draw.svg.path=M%20184,199%20116,170%2053,209.6%2060,136.2%204.3,88)

Draws the path supplied as an SVG Path string at the current brush position

**brush.type** (string brushType) [Try it](http://localhost:40074/api/v1?/api/v1?brush.type=ink)

Changes the brush. brushType can either be the brush name or it's guid. brushes are listed in the /help screen

**color.add.hsv** (Vector3 hsv) [Try it](http://localhost:40074/api/v1?/api/v1?color.add.hsv=0.1,0.2,0.3)

Adds the supplied values to the current color. Values are hue, saturation and value

**color.add.rgb** (Vector3 rgb) [Try it](http://localhost:40074/api/v1?/api/v1?color.add.rgb=0.1,0.2,0.3)

Adds the supplied values to the current color. Values are red green and blue

**color.set.rgb** (Vector3 rgb) [Try it](http://localhost:40074/api/v1?/api/v1?color.set.rgb=0.1,0.2,0.3)

Sets the current color. Values are red, green and blue

**color.set.hsv** (Vector3 hsv) [Try it](http://localhost:40074/api/v1?/api/v1?color.set.hsv=0.1,0.2,0.3)

Sets the current color. Values are hue, saturation and value

**color.set.html** (string color) [Try it](http://localhost:40074/api/v1?/api/v1?color.set.html=darkblue)

Sets the current color. colorString can either be a hex value or a css color name.

**brush.size.set** (float size) [Try it](http://localhost:40074/api/v1?/api/v1?brush.size.set=0.5)

Sets the current brush size

**brush.size.add** (float amount) [Try it](http://localhost:40074/api/v1?/api/v1?brush.size.add=0.1)

Changes the current brush size by the given amount

**draw\.camerapath** (int index, float step) [Try it](http://localhost:40074/api/v1?/api/v1?draw.camerapath=0)

Draws along a camera path with the current brush settings

**model.webimport** (string url) [Try it](http://localhost:40074/api/v1?/api/v1?model.webimport=Andy\Andy.obj)

Imports a model given a url or a filename in Media Library\Models (Models loaded from a url are saved locally first)

**import.webmodel** (string url) [Try it](http://localhost:40074/api/v1?/api/v1?import.webmodel=Andy\Andy.obj)

Same as model.webimport (backwards compatibility for poly.pizza)

**model.icosaimport** (string modelId) [Try it](http://localhost:40074/api/v1?/api/v1?model.icosaimport=9L2Lt-sxzdp)

Imports a model from the Icosa Gallery given a model id

**model.import** (string location) [Try it](http://localhost:40074/api/v1?/api/v1?model.import=Andy.glb)

Imports a model given a filename in Media Library\Models (Models loaded from a url are saved locally first)

**model.breakapart** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?model.breakapart=0)

Breaks apart a model

**save.overwrite** [Try it](http://localhost:40074/api/v1?/api/v1?save.overwrite)

Save the current scene overwriting the last save if it exists

**save.as** (string filename) [Try it](http://localhost:40074/api/v1?/api/v1?save.as=newSketch)

Saves the current scene under a new name. (No need to include the .tilt suffix)

**save.new** [Try it](http://localhost:40074/api/v1?/api/v1?save.new)

Saves the current scene in a new slot

**save.selected** [Try it](http://localhost:40074/api/v1?/api/v1?save.selected)

Saves the current selected strokes in a new slot

**icosa.devicelogin** (string code) [Try it](http://localhost:40074/api/v1?/api/v1?icosa.devicelogin)

Login to the Icosa Gallery using a device code

**icosa.logout** [Try it](http://localhost:40074/api/v1?/api/v1?icosa.logout)

Logout of the Icosa Gallery

**icosa.upload** [Try it](http://localhost:40074/api/v1?/api/v1?icosa.upload)

Uploads it to the Icosa Gallery

**export.all** [Try it](http://localhost:40074/api/v1?/api/v1?export.all)

Exports all the scenes in the users's sketch folder

**drafting.visible** [Try it](http://localhost:40074/api/v1?/api/v1?drafting.visible)

Shows all strokes made with the drafting brush fully opaque

**drafting.transparent** [Try it](http://localhost:40074/api/v1?/api/v1?drafting.transparent)

Shows all strokes made with the drafting brush semi-transparent

**drafting.hidden** [Try it](http://localhost:40074/api/v1?/api/v1?drafting.hidden)

Hides all strokes made with the drafting brush

**load.user** (int slot) [Try it](http://localhost:40074/api/v1?/api/v1?load.user=2)

Loads the sketch from the user's sketch folder given an index (0 being most recent)

**load.featured** (int slot) [Try it](http://localhost:40074/api/v1?/api/v1?load.featured=2)

Loads the sketch in the given slot number from the featured sketch list

**load.liked** (int slot) [Try it](http://localhost:40074/api/v1?/api/v1?load.liked=2)

Loads the sketch in the given slot number from the user's liked sketches

**load.drive** (int slot) [Try it](http://localhost:40074/api/v1?/api/v1?load.drive=2)

Loads the sketch in the given slot number from the user's Google Drive

**load.named** (string filename) [Try it](http://localhost:40074/api/v1?/api/v1?load.named=Untitled_1)

Loads the sketch with the given name from the user's sketch folder

**merge.named** (string filename) [Try it](http://localhost:40074/api/v1?/api/v1?merge.named=Untitled_1)

Loads the sketch with the given name from the user's sketch folder

**new** [Try it](http://localhost:40074/api/v1?/api/v1?new)

Clears the current sketch

**symmetry.mirror** [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.mirror)

Sets the symmetry mode to 'mirror'

**symmetry.multimirror** [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.multimirror)

Sets the symmetry mode to 'multimirror'

**twohandeded.toggle** [Try it](http://localhost:40074/api/v1?/api/v1?twohandeded.toggle)

Toggles painting with both hands at once

**straightedge.toggle** [Try it](http://localhost:40074/api/v1?/api/v1?straightedge.toggle)

Toggles the straight edge tool on or off

**autoorient.toggle** [Try it](http://localhost:40074/api/v1?/api/v1?autoorient.toggle)

Toggles autoorientate on or off

**undo** [Try it](http://localhost:40074/api/v1?/api/v1?undo)

Undoes the last action

**redo** [Try it](http://localhost:40074/api/v1?/api/v1?redo)

Redo the last action

**panels.reset** [Try it](http://localhost:40074/api/v1?/api/v1?panels.reset)

Reset the position of all panels

**sketch.origin** [Try it](http://localhost:40074/api/v1?/api/v1?sketch.origin)

Enables the sketch origin tool

**viewonly.toggle** [Try it](http://localhost:40074/api/v1?/api/v1?viewonly.toggle)

Toggles 'view only' mode on or off

**spectator.toggle** [Try it](http://localhost:40074/api/v1?/api/v1?spectator.toggle)

Toggles the spectator camera

**spectator.on** [Try it](http://localhost:40074/api/v1?/api/v1?spectator.on)

Turns the spectator camera on

**spectator.off** [Try it](http://localhost:40074/api/v1?/api/v1?spectator.off)

Turns the spectator camera off

**autosimplify.toggle** [Try it](http://localhost:40074/api/v1?/api/v1?autosimplify.toggle)

Toggles 'auto-simplify' mode on or off

**export.current** [Try it](http://localhost:40074/api/v1?/api/v1?export.current)

Exports the current sketch to the user's Exports folder

**showfolder.sketch** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?showfolder.sketch)

Opens the user's Sketches folder on the desktop

**guides.disable** [Try it](http://localhost:40074/api/v1?/api/v1?guides.disable)

Toggles guides on and off

**disco** [Try it](http://localhost:40074/api/v1?/api/v1?disco)

Starts a party

**selection.duplicate** [Try it](http://localhost:40074/api/v1?/api/v1?selection.duplicate)

Create a duplicate of the current selection (uses symmetry mirrors if active

**selection.delete** [Try it](http://localhost:40074/api/v1?/api/v1?selection.delete)

Deletes the current selection

**selection.group** [Try it](http://localhost:40074/api/v1?/api/v1?selection.group)

Groups (or ungroups) the current selection

**export.selected** [Try it](http://localhost:40074/api/v1?/api/v1?export.selected)

Exports the selected strokes to the user's Media Library

**camerapath.render** [Try it](http://localhost:40074/api/v1?/api/v1?camerapath.render)

Renders the current camera path to a video

**profiling.toggle** [Try it](http://localhost:40074/api/v1?/api/v1?profiling.toggle)

Toggles profiling mode on or off

**settings.toggle** [Try it](http://localhost:40074/api/v1?/api/v1?settings.toggle)

Toggles the settings panel on or off

**mirror.summon** [Try it](http://localhost:40074/api/v1?/api/v1?mirror.summon)

Summons the mirror origin to the user's position

**selection.invert** [Try it](http://localhost:40074/api/v1?/api/v1?selection.invert)

Inverts the current selection

**select.all** [Try it](http://localhost:40074/api/v1?/api/v1?select.all)

Selects all strokes and widgets on the current layer

**select.none** [Try it](http://localhost:40074/api/v1?/api/v1?select.none)

Deselects all strokes and widgets on the current layer

**selection.flip** [Try it](http://localhost:40074/api/v1?/api/v1?selection.flip)

Mirrors the current selection

**postprocessing.toggle** [Try it](http://localhost:40074/api/v1?/api/v1?postprocessing.toggle)

Toggles post-processing effects on or off

**watermark.toggle** [Try it](http://localhost:40074/api/v1?/api/v1?watermark.toggle)

Toggles the watermark on or off

**camerapath.togglevisuals** [Try it](http://localhost:40074/api/v1?/api/v1?camerapath.togglevisuals)

Toggles the camera path visuals on or off

**camerapath.togglepreview** [Try it](http://localhost:40074/api/v1?/api/v1?camerapath.togglepreview)

Toggles the camera path preview on or off

**camerapath.delete** [Try it](http://localhost:40074/api/v1?/api/v1?camerapath.delete)

Deletes the current camera path

**camerapath.record** [Try it](http://localhost:40074/api/v1?/api/v1?camerapath.record)

Starts recording a camera path

**camerapath.setactive** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?camerapath.setactive)

Sets the active camera path

**stroke.delete** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?stroke.delete=2)

Delete a stroke by index

**stroke.select** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?stroke.select=2)

Select a stroke by index.

**strokes.select** (int from, int to) [Try it](http://localhost:40074/api/v1?/api/v1?strokes.select=1,4)

Select multiple strokes by index.

**selection.recolor** (Boolean jitter) [Try it](http://localhost:40074/api/v1?/api/v1?selection.recolor)

Recolors the currently selected strokes

**strokes.move.to** (int start, int end, Vector3 position) [Try it](http://localhost:40074/api/v1?/api/v1?strokes.move.to=1,2,5,12,-4)

Moves several strokes to the given position

**strokes.move.by** (int start, int end, Vector3 translation) [Try it](http://localhost:40074/api/v1?/api/v1?strokes.move.by=1,2,5,12,-4)

Moves several strokes to the given coordinates

**strokes.rotate.by** (int start, int end, float angle) [Try it](http://localhost:40074/api/v1?/api/v1?strokes.rotate.by=1,2,5,12,-4)

Rotates multiple brushstrokes around the current brush position

**strokes.scale.by** (int start, int end, float scale) [Try it](http://localhost:40074/api/v1?/api/v1?strokes.scale.by=1,2,0.5)

Scales multiple brushstrokes around the current brush position

**selection.rebrush** (Boolean jitter) [Try it](http://localhost:40074/api/v1?/api/v1?selection.rebrush=true)

Rebrushes the currently selected strokes

**selection.resize** (Boolean jitter) [Try it](http://localhost:40074/api/v1?/api/v1?selection.resize)

Changes the brush size the currently selected strokes

**selection.trim** (int count) [Try it](http://localhost:40074/api/v1?/api/v1?selection.trim=4)

Removes a number of points from the currently selected strokes

**selection.points.perlin** (string axis, Vector3 scale) [Try it](http://localhost:40074/api/v1?/api/v1?selection.points.perlin=y,0.5,2,0.5)

Moves the position of all control points in the selection using a noise function

**stroke.points.quantize** (Vector3 grid) [Try it](http://localhost:40074/api/v1?/api/v1?stroke.points.quantize=2,2,2)

Snaps all the points in selected strokes to a grid (buggy)

**stroke.join** [Try it](http://localhost:40074/api/v1?/api/v1?stroke.join)

Joins a stroke with the previous one

**strokes.join** (int from, int to) [Try it](http://localhost:40074/api/v1?/api/v1?strokes.join=1,4)

Joins all strokes between the two indices (inclusive)

**stroke.add** (int index) [Try it](http://localhost:40074/api/v1?/api/v1?stroke.add=2)

Adds a point at the current brush position to the specified stroke

**symmetry.type** (string type) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.type=wallpaper)

Sets the custom symmetry type (Currently either 'point' or 'wallpaper'

**symmetry.pointfamily** (string family) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.pointfamily=C4v)

Sets the custom point symmetry family (Any of Cn, Cnv, Cnh, Sn, Dn, Dnh, Dnd, T, Th, Td, O, Oh, I, Ih) Replace n with a number to also set the order.

**symmetry.wallpapergroup** (string group) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.wallpapergroup=p6m)

Sets the custom wallpaper symmetry group (Any of p1, pg, cm, pm, p6, p6m, p3, p3m1, p31m, p4, p4m, p4g, p2, pgg, pmg, pmm, cmm)

**symmetry.pointorder** (int order) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.pointorder=5)

Sets the custom point symmetry order

**symmetry.wallpaperrepeats** (int x, int y) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.wallpaperrepeats=4,4)

Sets the custom wallpaper symmetry repeats

**symmetry.wallpaperscale** (float x, float y) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.wallpaperscale=0.5,1)

Sets the custom wallpaper symmetry scale

**symmetry.wallpaperskew** (float x, float y) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.wallpaperskew=1,0.5)

Sets the custom wallpaper symmetry skew

**symmetry.colorshift.hue** (string mode, float amplitude, float frequency) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.colorshift.hue=Noise,1,2)

Sets the custom wallpaper color shift hue (mode is one of SineWave, SquareWave, SawtoothWave, TriangleWave, Noise)

**symmetry.colorshift.saturation** (string mode, float amplitude, float frequency) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.colorshift.saturation=SineWave,0.1,1)

Sets the custom wallpaper color shift saturation (mode is one of SineWave, SquareWave, SawtoothWave, TriangleWave, Noise)

**symmetry.colorshift.brightness** (string mode, float amplitude, float frequency) [Try it](http://localhost:40074/api/v1?/api/v1?symmetry.colorshift.brightness=SquareWave,0.5,6)

Sets the custom wallpaper color shift brightness (mode is one of SineWave, SquareWave, SawtoothWave, TriangleWave, Noise)

**multiplayer.join** (string nickname, string roomName, Boolean isPrivate, int maxPlayers, Boolean silentRoom, Boolean viewOnlyRoom) [Try it](http://localhost:40074/api/v1?/api/v1?multiplayer.join)

Joins a multiplayer room

**multiplayer.leave** [Try it](http://localhost:40074/api/v1?/api/v1?multiplayer.leave)

Leaves a multiplayer room

**tool.sketchsurface** [Try it](http://localhost:40074/api/v1?/api/v1?tool.sketchsurface)

Activates the SketchSurface

**tool.selection** [Try it](http://localhost:40074/api/v1?/api/v1?tool.selection)

Activates the Selection Tool

**tool.colorpicker** [Try it](http://localhost:40074/api/v1?/api/v1?tool.colorpicker)

Activates the Color Picker

**tool.brushpicker** [Try it](http://localhost:40074/api/v1?/api/v1?tool.brushpicker)

Activates the Brush Picker

**tool.brushandcolorpicker** [Try it](http://localhost:40074/api/v1?/api/v1?tool.brushandcolorpicker)

Activates the Brush And Color Picker

**tool.sketchorigin** [Try it](http://localhost:40074/api/v1?/api/v1?tool.sketchorigin)

Activates the SketchOrigin Tool

**tool.autogif** [Try it](http://localhost:40074/api/v1?/api/v1?tool.autogif)

Activates the AutoGif Tool

**tool.canvas** [Try it](http://localhost:40074/api/v1?/api/v1?tool.canvas)

Activates the Canvas Tool

**tool.transform** [Try it](http://localhost:40074/api/v1?/api/v1?tool.transform)

Activates the Transform Tool

**tool.stamp** [Try it](http://localhost:40074/api/v1?/api/v1?tool.stamp)

Activates the Stamp Tool

**tool.freepaint** [Try it](http://localhost:40074/api/v1?/api/v1?tool.freepaint)

Activates the FreePaint Tool

**tool.eraser** [Try it](http://localhost:40074/api/v1?/api/v1?tool.eraser)

Activates the Eraser Tool

**tool.screenshot** [Try it](http://localhost:40074/api/v1?/api/v1?tool.screenshot)

Activates the Screenshot Tool

**tool.dropper** [Try it](http://localhost:40074/api/v1?/api/v1?tool.dropper)

Activates the Dropper Tool

**tool.saveicon** [Try it](http://localhost:40074/api/v1?/api/v1?tool.saveicon)

Activates the SaveIcon Tool

**tool.threedofviewing** [Try it](http://localhost:40074/api/v1?/api/v1?tool.threedofviewing)

Activates the ThreeDofViewing Tool

**tool.multicam** [Try it](http://localhost:40074/api/v1?/api/v1?tool.multicam)

Activates the MultiCam Tool

**tool.teleport** [Try it](http://localhost:40074/api/v1?/api/v1?tool.teleport)

Activates the Teleport Tool

**tool.repaint** [Try it](http://localhost:40074/api/v1?/api/v1?tool.repaint)

Activates the Repaint Tool

**tool.recolor** [Try it](http://localhost:40074/api/v1?/api/v1?tool.recolor)

Activates the Recolor Tool

**tool.rebrush** [Try it](http://localhost:40074/api/v1?/api/v1?tool.rebrush)

Activates the Rebrush Tool

**tool.pin** [Try it](http://localhost:40074/api/v1?/api/v1?tool.pin)

Activates the Pin Tool

**tool.camerapath** [Try it](http://localhost:40074/api/v1?/api/v1?tool.camerapath)

Activates the CameraPath Tool

**tool.fly** [Try it](http://localhost:40074/api/v1?/api/v1?tool.fly)

Activates the Fly Tool

**snap.angle** (string angle) [Try it](http://localhost:40074/api/v1?/api/v1?snap.angle=15)

Sets the current snapping angle. Angle must be a supported value (15, 30, 45, 60, 75 or 90)

**snap.grid** (string size) [Try it](http://localhost:40074/api/v1?/api/v1?snap.grid=5)

Sets the current snapping grid. Size must be a supported value (0.1, 0.25, 0.5 ,1, 2, 3, 5

**selection.snap.angles** [Try it](http://localhost:40074/api/v1?/api/v1?selection.snap.angles)

Applies the current snap angle to all selected objects

**selection.snap.positions** [Try it](http://localhost:40074/api/v1?/api/v1?selection.snap.positions)

Applies the current snap grid to all selected objects

**selection.align** (string axis, string alignBy) [Try it](http://localhost:40074/api/v1?/api/v1?selection.align=x,center)

Aligns all selected objects to the given axis using their minimum, center or maximum points


# Cameras and Video Export

{% hint style="info" %}
Quest and other standalone headset users: exporting video *from inside Open Brush* has some limitations compared to PC. See [Quest and other standalone headsets](/user-guide/exporting-videos/quest-and-other-standalone-headsets).
{% endhint %}

### Quick navigation

* [Camera tool (GIFs, snapshots, video)](/user-guide/exporting-videos/camera-tool-gifs-snapshots-video)
* [Spectator Camera](/user-guide/exporting-videos/spectator-camera-desktop-view)
* [Camera Paths tools](/user-guide/exporting-videos/camera-paths-tool)
* [Video settings (Open Brush.cfg)](/user-guide/exporting-videos/video-settings-open-brush.cfg)
* [Offline rendering (HQ renders)](/user-guide/exporting-videos/offline-rendering-hq-renders)
* [360° / ODS video workflow](/user-guide/exporting-videos/360-ods-video-workflow)
* [Quest and other standalone headsets](/user-guide/exporting-videos/quest-and-other-standalone-headsets)


# Camera tool (GIFs, snapshots, video)

Auto-GIF, 5-second GIF, snapshots, and handheld video capture.

Open Brush has a handheld camera tool for quick captures. You use it for GIFs, snapshots, and (on PC VR) video.

### Where captures are saved

Videos and GIFs created with the Camera tool are saved to:

* `Documents/Open Brush/Videos`

### Beginner mode

In Beginner mode, the camera icon is a single-function tool. It opens camera controls on your brush controller.

The options are:

1. Auto-Gif
2. 5 Second Gif
3. Snapshot
4. Video (not present in some versions of Open Brush)

You control the camera like a handheld device.

* Swipe left/right on the thumbpad to switch modes.
* Pull the trigger to capture.

#### 5 Second Gif

Hold the trigger for five seconds. You can release and pull again to stop/start on the same 5-second timeline.

#### Video

Pull the trigger to start. Pull again to stop.

This is true handheld capture. You control camera direction, speed, and orientation.

### Advanced mode (Camera Options)

In Advanced mode, the camera icon has a sub-menu. You’ll see a small triangle in the corner.

Click and hold to open the sub-menu. Then choose **Camera Options**.

<figure><img src="/files/OOhDRfj8nJosueFYnkMe" alt=""><figcaption><p>The Cameras icon in Advanced mode has a sub-menu.</p></figcaption></figure>

<figure><img src="/files/UMEv6os5aez7ZPIZMO7g" alt=""><figcaption><p>Camera Options is inside the Cameras sub-menu.</p></figcaption></figure>

In **Camera Options**, you can:

* Toggle the Open Brush watermark.
* Adjust field of view (FOV) and smoothing.
* Toggle post effects.

<figure><img src="/files/pnbEy1WE2tq6q6m0bRaE" alt=""><figcaption></figcaption></figure>

#### FOV examples

These examples show FOV set to 140, 70, and 10. The first image has the watermark enabled.

<figure><img src="/files/8VzYF6uuO6uDcB0fndUJ" alt=""><figcaption><p>FOV 140 (wide angle), watermark on</p></figcaption></figure>

<figure><img src="/files/UrGtrjBIDfxmExGTmyla" alt=""><figcaption><p>FOV 140, watermark off</p></figcaption></figure>

<figure><img src="/files/TpRcZ5D8T5vLUpbivWrN" alt=""><figcaption><p>FOV 70</p></figcaption></figure>

<figure><img src="/files/acQxmNcz6LXa6zIWL8iV" alt=""><figcaption><p>FOV 10</p></figcaption></figure>

### Demo video

This demo was recorded via the Spectator Camera.

{% embed url="<https://youtu.be/C1mUcv5fl9k?si=0mbO3RxIDmGgfzD8>" %}


# Spectator Camera (Desktop View)

Output a clean view to a monitor for screen capture.

The Spectator Camera does **not** record images or video. It outputs a view to your monitor.

To record it, use screen capture software. That software is outside Open Brush.

### Why you’d use it

It’s the only camera that can show:

* The full environment
* UI tools
* Camera paths

It’s also good for “stroke-by-stroke” creation footage.

### Modes

The Spectator Camera has four modes.

* **Headset**: The headset view. It moves with your head.
* **Stationary**: Place a camera in the scene. Or hold it like a handheld.
* **Figure 8**: A continuous figure-8 around a fixed point.
* **Circle**: A continuous horizontal orbit around a fixed point.

### Audio notes

Some audio sources can’t be captured due to DRM/DMCA restrictions. Spotify is a common example.

Your microphone recording is not affected.

### Strengths and limitations

Strengths:

* Easy, repeatable motion (Stationary/Figure 8/Circle).
* Shows controllers, headset, and tools.

Limitations:

* Requires external screen capture software.
* Field of view in **Camera Options** does **not** affect the Spectator Camera.


# Camera Paths Tool

Draw a path, control direction/speed/FOV, then record a guided move.

Camera Paths lets you record video by moving a camera along a path. It’s the core “virtual cinematography” tool in Open Brush.

Once you start recording a path, other tools are locked. If you cancel mid-recording, the partial video is discarded.

<figure><img src="/files/53a9lfb2LUiuqFHxNUQF" alt=""><figcaption><p>The Camera Paths tool opens a dedicated panel.</p></figcaption></figure>

### Create your first path

If you have no paths yet, you’ll only see **Add New Path**.

<figure><img src="/files/UWbw61dhPirKTQrbiuDl" alt=""><figcaption><p>Create a path first. Other tools unlock after that.</p></figcaption></figure>

Create a path with 2+ anchor points.

After that, you’ll see the full set of tools:

<figure><img src="/files/KCUFFoLpRhvBwrjiUr6R" alt=""><figcaption><p>The panel after a path is created.</p></figcaption></figure>

### Tools

#### Select Path

Choose which existing path you want to edit.

<figure><img src="/files/MnUBBPR3OnATo83fTbOx" alt=""><figcaption><p>Select Path</p></figcaption></figure>

#### Show Paths

Shows paths in the sketch so you can manipulate them.

<figure><img src="/files/KQZgSFsLc7i2rsBtpxSS" alt=""><figcaption><p>Show Paths</p></figcaption></figure>

#### Delete Path

Deletes the entire selected path.

<figure><img src="/files/r5eJLk9TIwPYLmVhhdSr" alt=""><figcaption><p>Delete Path</p></figcaption></figure>

#### Record Path

Renders a video by moving the camera through the full path. The output video appears in `Documents/Open Brush/Videos`.

Recording cannot be paused. Cancel by clicking the **X** on the brush controller while recording.

<figure><img src="/files/IPYHOGsJOnITXdKAgnbW" alt=""><figcaption><p>Record Path</p></figcaption></figure>

#### New Anchor Point

Adds an anchor point to the path. If you add to either end, it stays active for adding more points.

<figure><img src="/files/x1dPEEw6AfiNlPAst1VR" alt=""><figcaption><p>New Anchor Point</p></figcaption></figure>

#### Delete Anchor Point

Deletes any control point on the timeline. That includes anchor, direction, speed, and zoom points.

<figure><img src="/files/ULnnZP7qTHQeS6HfD2RE" alt=""><figcaption><p>Delete Point</p></figcaption></figure>

#### Camera Direction Point

Controls where the camera points. Direction points blend with nearby direction points for smooth motion.

<figure><img src="/files/uT9p6D0REcOTVLvoIYzp" alt=""><figcaption><p>Camera Direction Point</p></figcaption></figure>

#### Camera Speed Point

Controls how fast the camera moves. Values range from `0.1` to `100`. Speed blends between points.

<figure><img src="/files/WhImaYPB0qPUDwYi8DGt" alt=""><figcaption><p>Camera Speed Point</p></figcaption></figure>

#### Camera Zoom (FOV) Point

Controls field of view over time. Values range from `10` to `140`. FOV blends between points.

<figure><img src="/files/HWMm30hE9NFSWpJGiP32" alt=""><figcaption><p>Camera Zoom Point</p></figcaption></figure>

### Practical notes

Camera Paths can be time consuming. Each control point affects the timeline before and after it.

The tool is only accessible after the sketch is fully rendered. So it can’t capture the rendering process itself.


# Video settings (Open Brush.cfg)

FPS, resolution, encoder, watermark, and capture flags.

Several capture and render settings live in the config file. See [The Open Brush config file](/user-guide/the-open-brush-config-file) for location and format rules.

### Video-related fields

This is an example snippet showing the fields that affect capture and rendering:

```json
{
  "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
  }
}
```

### FPS and performance

FPS affects memory use. Each frame must be rendered and encoded.

Live recording is heavier than it looks. VR already renders twice (one per eye). Recording adds another render/encode pass.

If you run out of memory, VR can stutter. Stutter can quickly cause VR sickness.

### When to use offline rendering

Offline rendering is best for:

* Higher resolution output
* Higher FPS output
* More stable output on complex sketches

See [Offline rendering (HQ renders)](/user-guide/exporting-videos/offline-rendering-hq-renders) for the workflow.


# Offline rendering (HQ renders)

Re-render recorded videos via .bat files or the command line.

Offline rendering lets you re-render a recorded camera move. You can output higher resolution and/or higher FPS.

It works by saving the camera motion to a USD file. Then Open Brush can replay that motion later.

### Enable camera path saving

Set `"SaveCameraPath": true` in your config. See [The Open Brush config file](/user-guide/the-open-brush-config-file).

### What files you get

When you record a video with `SaveCameraPath` enabled, Open Brush writes extra files. On Windows, you’ll see a batch file next to the video in `Documents\Open Brush\Videos`.

Example:

```
Untitled_13_00.mp4
Untitled_13_00.HQ_Render.bat
```

### Re-render using the Windows .bat

Double-click the `.bat`. Pick an option from the menu.

![](/files/s7cI21RTtcVlBsR2s5sr)

Open Brush will:

1. Launch
2. Load your sketch
3. Render the video
4. Exit

Higher quality settings can make the framerate choppy. Don’t wear the headset during the render.

#### “No Quick Load” option

The “No Quick Load” option forces a full load. Use it when your render finishes before the sketch fully loads.

### Render a saved camera path from the command line

The camera path is saved in ASCII USD (`.usda`). If you have other USD tools, you may be able to edit it.

To render directly:

```
Openbrush.exe --renderCameraPath <path/to/camerapath.usda> <path/to/sketchfile.tilt>
```

### Video camera paths vs Camera Paths tools

These are different concepts:

* **Camera Paths tools** create a path that Open Brush records.
* **Video camera paths** are the saved motion data used for offline re-rendering.

The saved `.usda` path can be combined with USD exports. That can recreate camera motion in other pipelines.


# 360° / ODS video workflow

Render stereoscopic 360 videos and inject metadata for YouTube.

Open Brush can render ODS (stereoscopic 360) videos via offline rendering. This is a PC workflow.

You’ll typically:

1. Record a camera move with `SaveCameraPath` enabled.
2. Re-render offline at high quality.
3. Inject 360 metadata for YouTube.

### Fix clipping by changing eyeScale

On ODS renders, you may see:

* Missing floor
* Geometry clipping

This often happens when the scene is scaled down. Objects end up too close to the camera for ODS.

Open the saved `.usda` camera path in a text editor. Look for:

```
uniform float eyeScale = 1
```

Try:

```
uniform float eyeScale = 0.1
```

{% hint style="info" %}
Reducing `eyeScale` also reduces stereo strength. Scaling your scene is often better for stereo.
{% endhint %}

### Inject 360 metadata

YouTube needs metadata to recognize 360 and stereo layout.

1. Download the 360° Video Metadata tool:
   * [Mac](https://github.com/google/spatial-media/releases/download/v2.0/360.Video.Metadata.Tool.mac.zip)
   * [Windows](https://github.com/google/spatial-media/releases/tag/v2.0)
2. Unzip it.
3. Launch the app.
   * On macOS you may need right-click → **Open**.
4. Select your rendered video.
5. Check **My Video is stereoscopic 3D (top/bottom layout)**.
6. Click **Inject Metadata**.
7. Save the new file.

### Upload to YouTube

Upload the “injected” file. YouTube takes extra time to process 360 video.

Until processing finishes, you may see the raw over/under output. After processing, YouTube will show the 360 viewer.


# Quest and other standalone headsets

Current limitations and the best workarounds.

{% hint style="info" %}
Standalone headsets (Quest, etc.) can’t currently export video directly inside Open Brush. The workaround depends on what you’re trying to record.
{% endhint %}

### Option 1: Render frames on Quest, then compile

This option shipped near the end of 2025.

You can render camera paths directly on Quest. The output is a folder of frames.

You then compile frames into a video. We generate a helper script for [ffmpeg](https://ffmpeg.org/).

### Option 2: Draw the camera path on Quest, render on a computer

Quest builds have the Camera Paths tool. The **record** button is disabled.

But paths are saved with the sketch. Copy the sketch to a PC or Mac and render there.

The computer does **not** need VR hardware. You can run Open Brush without a headset.

#### Example script workflow

1. Launch Open Brush once on the computer.
2. Copy your sketch from the headset to `Open Brush/Sketches`.
3. Copy any referenced media (images/videos/models) to the matching Media Library folders.
4. With Open Brush running, open: <http://localhost:40074/help/>
5. Go to **Example Scripts**.
6. Open **/examplescripts/record\_camera\_path.html**.
7. Select your sketch.
8. Click **Go**.

### Option 3: Use the Quest system recorder

Record the headset view using Quest’s built-in recording.

Quality will be lower. You may want to hide UI elements. The [Open Brush API](/user-guide/open-brush-api) can help with scripted UI control.


# Brushes

Open Brush comes with a wide selection of brushes and there are even more if you switch on [Experimental Mode](/user-guide/experimental-mode). But be warned that the experimental brushes can be more problemmatic if you need to export to other apps. See the docs on the [Unity Toolkit/SDK](/user-guide/open-brush-unity-sdk) and on [Exporting ](/user-guide/exporting-open-brush-sketches-to-other-apps)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.

## Customizing Brushes

There are currently three ways to add and modify brushes:

1. This requires you to learn your way around Unity a little bit: [https://lachlansleight.medium.com/customizing-tilt-brush-6e9a63bd5425](https://steamcommunity.com/linkfilter/?url=https://lachlansleight.medium.com/customizing-tilt-brush-6e9a63bd5425) Brushes created this way won't export to other apps correctly without manual shader editing. Using them in other Unity projects via the [Unity SDK](/user-guide/open-brush-unity-sdk) is possible but requires manual editing of the Unity shaders and materials.
2. Tim Aidley has created a feature that allows editing of brushes via config files: [https://github.com/TimAidley/open-brush/blob/features/simple-brushes/Docs/UserBrushes.md](https://steamcommunity.com/linkfilter/?url=https://github.com/TimAidley/open-brush/blob/features/simple-brushes/Docs/UserBrushes.md)
3. 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: [Brush Editing](/alternate-and-experimental-builds/brush-editing)

This last method will eventually be the recommended method moving forwards and we hope to fully support these custom brushes in the Unity SDK and for exporting..

{% content-ref url="/pages/-MipjouWPtDnuOCoLedf" %}
[Brush List](/user-guide/brushes/brush-list)
{% endcontent-ref %}


# Brush List

* **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](/user-guide/make-moving-creations-using-audio-reactive-brushes#to-use-audio-reactive-brushes)

## Standard Brushes

| Brush Name          | Type     | Animated? | Self-lit? | Audio Reactive? |
| ------------------- | -------- | --------- | --------- | --------------- |
| 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             |

## Experimental Brushes

| Brush Name                  | Type     | Animated? | Self-lit? | Audio Reactive? |
| --------------------------- | -------- | --------- | --------- | --------------- |
| 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              |


# Memory limits and brush costs

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:

![](/files/RIUvezFAQu3RV6IXNbcB)

![](/files/IzpmRAXmmKYfdZmeQX2R)

![](/files/rg4f4V7koFBu5sOkm4Np)


# Experimental Brushes

This is a list of the brushes that are only available in any "Experimental Mode" Builds:

| Brush Name             | Notes                                                                                                             |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------- |
| 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](/alternate-and-experimental-builds/main-experimental-build#drafting)" 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                   |                                                                                                                   |


# Hiding Brushes with Brush Tags

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:

1. IncludeTags - specifies all of the brushes that may be included included in the panel
2. 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:

```
{
	"User": {
	},
	"Brushes": {
		"AddTagsToBrushes": {
			"Rainbow": ["classroom", "bedazzling"],
			"Plasma": ["classroom", "bedazzling"],
			"testBrushNotFound": ["classroom"]
		},
		"RemoveTagsFromBrushes": {
			"Rainbow": ["default", "test"],
			"Plasma": ["default", "test"],
			"testBrushNotFound": ["classroom"]
		},
		"IncludeTags": ["classroom"],
		"ExcludeTags": ["test"] 
	},
	"Video": {
	},
	"Flags": {
	},
	"Export": {
	},
}
```


# Using Open Brush without a VR headset

{% hint style="info" %}
This page has been update to reflect changes in the current [beta version](/alternate-and-experimental-builds/open-brush-beta-docs). Sketch Viewer mode is a new feature and Monoscopic Mode was previously only available as a separate download.
{% endhint %}

## Desktop Mode

<figure><img src="/files/iLSVWu5u7blUdF8IA27I" alt=""><figcaption></figcaption></figure>

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](/user-guide/the-open-brush-config-file) in the "Flags" section and setting it to true. For example:

```json
{
  "Flags": {
    "DisableXrMode": true
  }
}
```

You can return to normal either by removing the entry or by setting it to false.

### Plugins and Scripting in Desktop Mode

Another great use case for Desktop Mode is in conjunction with either or both the [HTTP API](/user-guide/open-brush-api) and [Plugins](/user-guide/using-plugins)

In fact - we've included a script designed to show how you can control and configure Open Brush and trigger plugins from your browser. Just open <http://localhost:40074/examplescripts/remotecontrol.html> while Open Brush is running. (this also works in VR but is especially useful in desktop mode)

<figure><img src="/files/vMD3wx3KXyCBUqBSqQnV" alt=""><figcaption></figcaption></figure>

## Monoscopic Mode

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](/user-guide/open-brush-api) allowing you to control Open Brush from a web browser.

## Activating Monoscopic mode

You can access Monoscopic mode by adding a "EnableMonoscopicMode" entry to your [Open Brush config file](/user-guide/the-open-brush-config-file) in the "Flags" section and setting it to true. For example:

```json
{
  "Flags": {
    "EnableMonoscopicMode": true
  }
}
```

You can return to normal either by removing the entry or by setting it to false.

## Controlling Monoscopic mode

1. Alt+mousing will rotate your viewpoint.
2. 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.
3. Dragging with the right button down will bring the drawing plane nearer or further.
4. Ctrl+mouse drag will rotate the drawing plane
5. Clicking in the game window will capture your mouse cursor. Escape will return full control (so you can interact with Unity etc)
6. In most cases you can alt+mouse to left or right to view the tool panels and choose tools/brushes with the mouse.
7. Rotating with “Alt” whilst pressing shift will allow you to move the panel you were currently focused on.
8. Sometimes panels appear in weird places. Try looking behind you or down at your feet.

## Other Keyboard Shortcuts

{% hint style="info" %}
The file Scripts/InputManager.cs lists all the keyboard controls. Also see [Open Brush: Keyboard Controls and VR Input](https://docs.google.com/spreadsheets/d/1D7vIerfSz1vtyDS_dPdvHiANluEr60VFrxhzE7ZbfAU) However many aren’t relevant, aren’t implemented or only apply in particular modes. The more useful ones are listed below.
{% endhint %}

| **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          |                                                                                             |


# Command Line Arguments

(If you're not sure how to launch an app with command line arguments I found this tutorial via Google: <https://www.digitalcitizen.life/shortcut-arguments-parameters-windows/> - suggestions for a better link gratefully received)

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)


# Tilt Brush Version 23 Release Notes

These were the last release notes that were put out by Google and contain some useful information not found elsewhere.

## Version 23

* 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.

## Accessing Autosave Files

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.

## ~~Tilt Brush Config File~~

Outdated See [Open Brush Config File](/user-guide/the-open-brush-config-file)

## Exporting Tilt Brush Sketches

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](https://github.com/googlevr/tilt-brush-toolkit) for sample [Python 2.7](https://www.python.org/download/releases/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](https://github.com/googlevr/tilt-brush-toolkit) contains a Python 2.7 script that can convert the .tilt file to a Collada .dae containing the curves.

#### Maya

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.

#### Sketchfab

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.

#### Unity

We recommend using the Tilt Brush Toolkit and the .glb format. Tilt Brush Toolkit also understands the .fbx format.

#### Command-line Exporting

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.

```
TiltBrush.exe --export Untitled_15.tilt Untitled_2*.tilt C:\Downloads\downloaded.tilt --exportPath C:\Temp -batchmode
```

## Exporting Video

### Rendering ‘Offline’ videos

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:

![](/files/s7cI21RTtcVlBsR2s5sr)

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.

### Video Camera Paths

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](https://graphics.pixar.com/usd/docs/index.html)) 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:

```
Tiltbrush.exe --renderCameraPath <path/to/camerpath.usda> <path/to/sketchfile.tilt>
```

### Changing Eye Scale on ODS 360 videos

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:

```
uniform float eyeScale = 1
```

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:

```
uniform float eyeScale = 0.1
```

Then you can just try re-rendering with the batch file.

### Exporting 360 videos / Offline Video Rendering

Videos can be rendered ‘offline’ faster and at a much higher resolution and framerate than using the internal Multicam tool

1. **Editing Tilt Brush cfg file**
2. Go to C:\Documents\Tilt Brush\Tilt Brush cfg
3. Under "Video" add the flag "SaveCameraPath": true,
4. Save Tilt Brush cfg
5. **Camera Setup**
6. Load the sketch you would like to render
7. Find a good spot from which you would like to capture your 360 video
8. Be sure to look around in all directions to make sure no objects are too close to the point of capture
9. Save your sketch
10. Record your video by moving camera or keeping camera stationary
11. After saving, exit Tilt Brush
12. **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
13. Go to C:\Documents\Tilt Brush\Videos . There should be .usda, .bat and video file which corresponds to the .tilt file
14. Double click on .bat file
15. If you run that batch file a command window will appear giving you several options for re-rendering your video:\
    \
    ![](/files/IFFPruY9bpdMYajtNR0Z)\
    \
    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.
16. Once the render is complete, it will pop open the “VRVideos” folder which should contain an video file with your stereo render.
17. **Converting into 360 video**\
    \
    1\. [Download the 360° Video Metadata app](https://support.google.com/youtube/answer/6178631?hl=en) for [Mac](https://github.com/google/spatial-media/releases/download/v2.0/360.Video.Metadata.Tool.mac.zip) or [Windows](https://github.com/google/spatial-media/releases/tag/v2.0). The dialog should look like this:\
    \
    ![](/files/8UfRwY1iZLr6iMpDXtNU)\
    \
    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.
18. **Uploading to Youtube**
    1. Upload the new “injected” video file to YouTube
    2. 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.
    3. 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:

![](/files/TAedNNM0DW6yg5C34D83)

### Tilt Brush Unity Shader Examples

Use these with geometry you export from Tilt Brush and import into Unity. However, you should prefer to use the [Tilt Brush Toolkit](http://github.com/googlevr/tilt-brush-toolkit), which comes with Tilt Brush shaders.

#### Opaque shader

```
Shader "Brush/Standard"
{
    Properties
    {
        _Color ("Main Color", Color) = (1,1,1,1)
        _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
        _MainTex ("Base (RGBA)", 2D) = "white" {}
        _BumpMap ("Normalmap", 2D) = "bump" {}
        _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    }
    SubShader
    {
        Tags
        {
            "Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"
        }
        LOD 400
        CGPROGRAM
        #pragma target 3.0
        #pragma surface surf StandardSpecular vertex:vert alphatest:_Cutoff addshadow
        struct Input
        {
            float2 uv_MainTex;
            float2 uv_BumpMap;
            float4 color : Color;
        };

        sampler2D _MainTex;
        sampler2D _BumpMap;
        fixed4 _Color;
        half _Shininess;

        void vert(inout appdata_full i)
        {
        }

        void surf(Input IN, inout SurfaceOutputStandardSpecular o)
        {
            fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
            o.Albedo = tex.rgb * _Color.rgb * IN.color.rgb;
            o.Smoothness = _Shininess;
            o.Specular = _SpecColor;
            o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
            o.Alpha = tex.a * IN.color.a;
        }
        ENDCG
    }
    FallBack "Transparent/Cutout/VertexLit"
}
```

#### Additive shader

```
Shader "Brush/Additive"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    Category
    {
        Tags
        {
            "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"
        }
        Blend SrcAlpha One
        AlphaTest Greater .01
        ColorMask RGB
        Cull Off Lighting Off ZWrite Off Fog
        {
            Color (0,0,0,0)
        }
        SubShader
        {
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                sampler2D _MainTex;

                struct appdata_t
                {
                    float4 vertex : POSITION;
                    fixed4 color : COLOR;
                    float3 normal : NORMAL;
                    float2 texcoord : TEXCOORD0;
                };

                struct v2f
                {
                    float4 vertex : POSITION;
                    fixed4 color : COLOR;
                    float2 texcoord : TEXCOORD0;
                };

                float4 _MainTex_ST;

                v2f vert(appdata_t v)
                {
                    v2f o;
                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                    o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                    o.color = v.color;
                    return o;
                }

                fixed4 frag(v2f i) : COLOR
                {
                    half4 c = tex2D(_MainTex, i.texcoord);
                    return i.color * c;
                }
                ENDCG
            }
        }
    }
}
```

### Tilt Brush File Format

The .tilt file format can also be parsed by the [Tilt Brush Toolkit](http://github.com/googlevr/tilt-brush-toolkit).

A .tilt is a zip-format file with a prepended header:

```
uint32 sentinel ('tilT')
uint16 header_size (currently 16)
uint16 header_version (currently 1)
uint32 reserved
uint32 reserved
```

Inside the zip, the strokes are stored in a custom binary format in a file, "data.sketch":

```
uint32 sentinel
uint32 version
uint32 reserved (must be 0)
[ uint32 size + <size> bytes of additional header data ]
int32 num_strokes
num_strokes * {
    int32 brush_index
    float32x4 brush_color
    float32 brush_size
    uint32 stroke_extension_mask
    uint32 controlpoint_extension_mask
    [ int32/float32 for each set bit in stroke_extension_mask & ffff ]
    [ uint32 size + <size> bytes for each set bit in stroke_extension_mask & ~ffff ]
    int32 num_control_points
    num_control_points * {
        float32x3 position
        float32x4 orientation (quat)
        [ int32/float32 for each set bit in controlpoint_extension_mask ]
    }
}
```

The orientation is that of the controller. Curve and surface frames must be reconstructed.

Stroke extensions:

| 0 | <p>uint32 bitfield.<br>Bit 0: IsGroupContinue</p> |
| - | ------------------------------------------------- |

Control point extensions:

| 0 | float pressure, in \[0,1]         |
| - | --------------------------------- |
| 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.

## Previous Releases

### Version 22

* 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](https://github.com/googlevr/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
    * [How to use the Tilt Brush config file.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
  * **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.

### Version 21

* 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](https://support.google.com/tiltbrush/answer/9427219?hl=en\&ref_topic=7074683) 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.

#### Version 20

* 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.

### Version 19

* 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.

### Version 18

* 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:

```json
{
  "Video": {
    "FOV": 90
  },
  "Flags": {
    "FOV": 100
  }
}
```

* * [How to use the Tilt Brush config file.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
* Added a button in the Settings to link to the [Help Center](https://support.google.com/tiltbrush/).
* 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!”.

### Version 17

* Added controller support for Windows Mixed Reality headsets on SteamVR

### Version 16

* 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](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md) 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.

### Version 15

* 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](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md).

### Version 14

* Blocks Library:
  * Accessible on the “Tools” panel, the Blocks Library allows you to add remixable featured and liked [Blocks](https://vr.google.com/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.

### Version 13

* Internal version that was either too good to release, or the dev team suffered from triskaidekaphobia.

### Version 12

* 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

### Version 11

* 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](https://www.youtube.com/watch?v=EUYJSxjUmYg))
  * 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](https://developers.google.com/vr/concepts/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](https://github.com/googlevr/tilt-brush-toolkit) (including all particles)
* Linear lighting support in The [Tilt Brush Toolkit](https://github.com/googlevr/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.

### Version 10

* Sharing
  * Share sketches to the [online gallery](https://vr.google.com/sketches)!
  * 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](https://vr.google.com/sketches)!
  * 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](https://docs.google.com/document/d/1UnXLNrIV5z-bfHilWh1--vdN_-MY9BdLg5fcs9xlpDU/edit#heading=h.fti7q68lns72).
* 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.

### Version 9

* 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.

### Version 8

* 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](https://support.google.com/youtube/topic/2676339).
  * 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.
  * [How to use the Tilt Brush config file.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
* 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.

### Version 7.5

* 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.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
* 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.
    * [How to use the Tilt Brush config file.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
  * Support scripts have moved to the [Tilt Brush Toolkit](https://github.com/googlevr/tilt-brush-toolkit).

### Version 7

* 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](https://support.google.com/tiltbrush#topic=7074683) for instructions how to play.
  * Adding *Tiltasaurus.json* to the **Documents/Tilt Brush** folder will let you add your own list of words.
  * Format:

```
{
   "Categories":[
      {
         "Name":"Action",
         "Words":[
            "Applause",
            "Arguing",
            "Ballet"
         ]
      },
      {
         "Name":"Animal",
         "Words":[
            "Butterfly ",
            "Cat",
            "Chicken"
         ]
      }
   ]
}
```

* 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.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
  * 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.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
* 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.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
  * 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.

### Version 6

* 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](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md) 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.

### Version 5

* 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.

### Version 1.4

* 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:

```
{
 "YouTube": {
 "ChannelID": "UCabcdefghijklmnopqrstuv",
 },
}
```

* * Note: [How to find your YouTube Channel ID.](https://support.google.com/youtube/answer/3250431)
  * [How to use the Tilt Brush config file.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
  * 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:

```
{
 "Twitch": {
 "Username": "TiltBrushStreamer",
 "OAuth": "oauth:abcdefghijklmnopqrstuvwxyz0123",
 "Channel": "#tiltbrushchannel",
 },
}
```

* * Note: [How to get an OAuth key for Twitch.](https://twitchapps.com/tokengen/)
  * [How to use the Tilt Brush config file.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
  * Use Grip button to move chat widget.
  * Use both Grip buttons to scale chat widget.
  * Toss the widget to dismiss it.

#### Version 1.3

* 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](https://www.python.org/download/releases/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](http://images.autodesk.com/adsk/files/fbx20151_fbxpythonsdk_win.exe). 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](mailto:tiltbrush@google.com?Subject=I%20used%20export) how you use this functionality!
* IRC
  * Requires “Tilt Brush.cfg”, stored in: **Documents/Tilt Brush**
  * Format:

```
{
   "IRC":{
      "ServerName":"irc.twitch.tv",
      "ServerPort":6667,
      "Username":"TiltBrushStreamer",
      "OAuth":"oauth:abcdefghijklmnopqrstuvwxyz0123",
      "Channel":"#tiltbrushchannel"
   }
}
```

}

Note: [How to get an OAuth key for Twitch.](http://help.twitch.tv/customer/portal/articles/1302780-twitch-irc)

* * [How to use the Tilt Brush config file.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)
  * 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

```
{
 "Flags": {
 "ShowWatermark": false,
 },
}
```

* * [How to use the Tilt Brush config file.](https://github.com/icosa-gallery/open-brush-docs/blob/master/user-guide/broken-reference/README.md)


# Get Involved!

### Artists, Bloggers, Content Creators and anyone

* Post your work on social media and make sure to name check us to spread awareness.
* Join the [Discord](https://discord.openbrush.app) 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.
* Contribute to the docs - send in corrections or improvements or fill in any gaps you find. (We have a [TODO list](/docs-todo) just for the docs)
* 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](/alternate-and-experimental-builds/open-brush-beta-docs) or one of the [experimental builds](/alternate-and-experimental-builds) and share bugs you find or any other feedback.

### Unity/C# Developers

* Download the [repo](https://github.com/icosa-foundation/open-brush) and read the [developer notes](/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

### Other Devs: Javascript/Processing/Python/anything

* Check out the [API](/user-guide/open-brush-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.

### UX/UI Designers

* 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](/user-guide/open-brush-api). Or partner with a dev to make an innovative add-on tool.

### Teachers, Academics, Researchers in any field

* 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.

### Media, PR or Marketing people

* 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](https://opencollective.com/icosa/updates/2021-retrospective-and-open-brush-1-0). Help us get the word out.

### Billionaires

Enough funding for a couple of full-time staff would make a vast difference. That's small change to you, right? :-)


# How to help with Testing

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").

## Testing the Beta version

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](https://discord.com/channels/783806589991780412/1019733473797341225) on Discord (or if you need to chat before you're confident enough to report a bug, just post in the [General channel](https://discord.com/channels/783806589991780412/783806589991780415))

To help you focus on testing the right things you can see a list of [changes and new features in the beta version here.](/release-history/automatic-changelog)

## Testing Pull Requests

"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](https://github.com/icosa-foundation/open-brush/pulls?q=is%3Apr+is%3Aopen+-is%3Adraft+). You can click on any one and then scroll down to the bottom:

![](/files/JesAIS4hCWs4vNCO10Jo)

Click on any of the blue "details" links and then click "Summary" on the left followed by the number underneath "Artifacts" on the right:

![](/files/6p43HvyuB4eVuF4SyNym)

You'll then be taken to the bottom of the page where there is a list of all the builds:

![](/files/2aPr6fSLgJqD62EctO6I)

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)

## Testing Experimental Builds

[Experimental builds](/alternate-and-experimental-builds#beta-release) 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.


# Pre-release and Experimental Builds

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.

## Beta Release

[List of changes in the current beta version](/release-history/automatic-changelog)

{% content-ref url="/pages/yQUzxfPS6zd8k7lS3Vsr" %}
[Current Beta Release Notes](/release-history/automatic-changelog)
{% endcontent-ref %}

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](https://github.com/icosa-foundation/open-brush/releases). 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).

{% content-ref url="/pages/sj4biA5dL2TYHxiZoSz1" %}
[Installing the Beta Release](/alternate-and-experimental-builds/open-brush-beta-docs)
{% endcontent-ref %}

## "Experimental Mode" Build

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.

{% content-ref url="/pages/-MjYuWAAZYQBY2A-D\_SH" %}
["Experimental Mode" Builds](/alternate-and-experimental-builds/main-experimental-build)
{% endcontent-ref %}

## Feature Builds

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.

{% content-ref url="/pages/FT9EZYpfSI5ptcj1ixSS" %}
[Feature: 3D Shapes Tool](/alternate-and-experimental-builds/3d-shapes)
{% endcontent-ref %}

{% content-ref url="/pages/I9XL9ntK51TALklDjl2D" %}
[Feature: Brush Editing](/alternate-and-experimental-builds/brush-editing)
{% endcontent-ref %}

{% content-ref url="/pages/-MlAOYCs4Pvq7a5jQYom" %}
[Feature: New Monoscopic Mode](/alternate-and-experimental-builds/old-or-completed-feature-builds/new-monoscopic-mode)
{% endcontent-ref %}

{% content-ref url="/pages/Z6WSemLQ6x5E8IAg79Br" %}
[Old or Completed Feature Builds](/alternate-and-experimental-builds/old-or-completed-feature-builds)
{% endcontent-ref %}

## Multibrush (Tilt Brush fork)

Multibrush is mostly an [experimental mode build](/alternate-and-experimental-builds/main-experimental-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.

{% embed url="<https://blog.rendever.com/2021/02/04/news-multibrush-by-rendever-now-available-on-sidequest-providing-artists-with-a-collaborative-tool-in-virtual-reality>" %}

## Silk Brush (Tilt Brush Fork)

{% embed url="<https://msub2.github.io/silk-brush/>" %}

Tilt Brush. Running in a browser!

### TutoriVR

{% embed url="<https://www.tkbala.com/tutorivr>" %}

A VR-embedded tutorial system that supplements video tutorials with 3D and contextual aids directly in the user's VR environment.

## Full list of known Work in Progress

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!)

{% embed url="<https://docs.google.com/spreadsheets/d/1j_eIGT0PeOeviy1tz47qUdho_EG51tcFgHIS-4Fe9mU/edit#gid=0>" %}


# Installing the Beta Release

This build is the pre-release version of Open Brush and may contain untested new features.

{% content-ref url="/pages/yQUzxfPS6zd8k7lS3Vsr" %}
[Current Beta Release Notes](/release-history/automatic-changelog)
{% endcontent-ref %}

{% hint style="warning" %}
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!
{% endhint %}

## Opting in to the Steam beta <a href="#lnka1z4mzei7" id="lnka1z4mzei7"></a>

1. Right Click on Open Brush in your Steam Library and choose "Properties"

![](/files/2p44VjOV3Tr10UR1ynKw)

2\. Choose "Betas" on the left, and in the dropdown, select whether you want to opt into the beta or [experimental mode](/alternate-and-experimental-builds/main-experimental-build) version. You can also return to the normal release version by choosing "None"

3. Wait for Open Brush to update.

## Opting in to the Meta beta (Quest or PC) <a href="#lnka1z4mzei7" id="lnka1z4mzei7"></a>

### In the headset (Quest)

1. Find Open Brush in your Library, click the 3 dots menu and choose "Settings"
2. Click "Release Channels"
3. Choose "Beta"
4. Wait for Open Brush to appear in your list of updates and choose "Update"

### Using the desktop app or website (Quest or PC)

![](/files/sqOxhIboaUOn9LWoCkwU)

2. Or find Open Brush in the mobile app:

![](/files/Xu0c0t2TQ36jWfHfilIK)

3. 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.)
4. Wait for Open Brush to update.

## Download from Itch.io

We also host some beta versions on our Itch.io page.

{% embed url="<https://openbrush.itch.io/openbrush>" %}

## Download Directly from Github

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.

{% embed url="<https://github.com/icosa-foundation/open-brush/releases/>" %}


# "Experimental Mode" Builds

{% hint style="info" %}
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](/user-guide/experimental-mode)

However - there are still plenty of interesting [Experimental Builds](/alternate-and-experimental-builds) to try!
{% endhint %}


# Feature: 3D Shapes Tool

#### Status: Mostly working. Some improvements to the UI are needed. Ready for beta testing

{% embed url="<https://www.youtube.com/watch?v=Lnf6mS8xNIg>" %}

## Downloads

* [Oculus Quest 1](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2F3d-shapes/Oculus%20Quest%20%281%29.zip)
* [Oculus Quest 2 or 3](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2F3d-shapes/Oculus%20Quest%20%281%29.zip)
* [Oculus PC VR](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2F3d-shapes/Windows%20Rift.zip) (Rift, Quest via Link cable...)
* [SteamVR and other PC VR](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2F3d-shapes/Windows%20OpenXR.zip) (Vive, Index, Reverb...)
* [Other Builds](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2F3d-shapes) (Pico, Pimax etc)
* [Code](https://github.com/icosa-foundation/open-brush/tree/feature/3d-shapes)

### What does it do?

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.

### What's it good for?

Creating symmetrical patterns, geometric forms and complex 3d shapes.

### How do I install it?

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/>

### How do I use the 3D Shapes tool?

![](/files/p5lzb2XJCHx3r9ZfKo64)

1. (Make sure you've switch off beginner mode) Find the "Experimental Tools" panel which is usually attached to your wand.
2. There will be a new icon at the bottom that looks like a wireframe cube. Click that to activate the 3D shape tool.
3. 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".
4. Draw your chosen shape using the trigger on your drawing hand. Click once to start and release when you're happy with the size.

<mark style="color:red;">**WARNING!**</mark> 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.

### The main "3D Shape Tool" buttons

There are four buttons on the tray that appears when the Polyhedra tool is active:

#### 1. Shape Gallery

This opens a popup with a selection of built-in shapes to get you started.

#### 2. "Create" action

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.

#### 3. "Modify" action

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:

1. **Apply settings**: picks up the Shape Designer settings from the model and loads those settings into the Shape Designer panel.
2. **Grab settings**: Applies the current Shape Designer Settings to the model.
3. **Apply color**: Changes all faces on the model to the current selected brush color.
4. **Draw brush strokes on faces**: Create brush strokes on the model. One brush stroke for every face.
5. **Draw brush strokes on edges**: Create brush strokes on the model. One brush stroke for every edge.

#### 4. Shape Designer

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

### Known Issues

1. There's nothing to stop you creating extremely complex shapes that can slow everything down and even cause Open Brush to crash.
2. 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")
3. Duplicating models using the selection tool sometimes produces changes in scale.
4. You can't scale the custom mirror. Instead scale your scene.
5. Custom mirror stroke colours are sometimes unpredictable.

### The Custom Guide

(docs coming soon)

### The Custom Mirror

1. The symmetry mode only affects normal paint strokes. You can't currently use symmetry to create multiple copies of the polyhedra tool.
2. You can grab the symmetry widget and change it's position and orientation.

### Using the Shape Designer

![The "Generate" panel showing the main shape categories](/files/SCBrt3pDO60WIV58q3xH)

![The "Modify" panel showing 3 modifiers applied to the shape.](/files/AaNO9i69Nr2DgejN47r1)

![The "Appearance" panel showing color and material options.](/files/CPILdVMBbcmdb5kRcUQ1)

![The "Presets" popup where you can save the shapes you've created.](/files/JR1JYkgAaPvaDqUIeTh0)

(docs coming soon)

## How do I get help

Come over to the Open Brush Discord: <https://discord.openbrush.app> and chat to me ( andybak#5425 ).

I'm on UK time but I check in fairly regularly.

### Can I see it in action?

<figure><img src="/files/-MikxGjNlPb8UIebeXu0" alt=""><figcaption></figcaption></figure>

(docs coming soon)


# Feature: Animation Timeline

Developed by [Benji Costin](mailto:b3nsup@gmail.com) with support from [The Icosa Foundation](https://opencollective.com/icosa) and Open Brush community

#### Status: <mark style="color:red;">Experimental and incomplete</mark>

<figure><img src="/files/6KI6W4X4WvmotSQGX4LG" alt=""><figcaption><p>An early version of the UI</p></figcaption></figure>

## Download

* [Oculus Quest 1](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fanimation/Oculus%20Quest%20\(2%2B\).zip)
* [Oculus Quest 2 or 3](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fanimation/Oculus%20Quest%20\(2%2B\).zip)
* [Oculus PC VR](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fanimation/Windows%20Rift.zip)(Rift, Quest via Link cable...)
* [SteamVR and other PC VR](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fanimation/Windows%20OpenXR.zip)(Vive, Index, Reverb...)
* [Other Builds](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fanimation) (Pico, Pimax etc)
* [Code](https://github.com/icosa-foundation/open-brush/tree/feature/animation)

### What does it do?

Both hand-drawn ("flipbook style") animation and tweening. Inspired by the classic Flash timeline - add motion to your Open Brush sketches.

### How do I install it?

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/>

### How do I use it?

TODO

### Known Issues

TODO

## How do I get help

Come over to the Open Brush Discord: <https://discord.openbrush.app> and chat to @seethrough ).

We're mostly on UK time but we check in fairly regularly.

### Can I see it in action?

{% embed url="<https://www.youtube.com/watch?v=JZWjgx1LuCU&feature=youtu.be>" %}


# Feature: Brush Editing

#### Status: Buggy (especially the Quest version) but powerful and worth trying

## Download

* [Oculus Quest 1](https://nightly.link/icosa-foundation/open-brush/workflows/build/features%2Fbrush-editing/Oculus%20Quest%20%282%2B%29.zip)
* [Oculus Quest 2 or 3](https://nightly.link/icosa-foundation/open-brush/workflows/build/features%2Fbrush-editing/Oculus%20Quest%20%282%2B%29.zip)
* [Oculus PC VR](https://nightly.link/icosa-foundation/open-brush/workflows/build/features%2Fbrush-editing/Windows%20Rift.zip)(Rift, Quest via Link cable...)
* [SteamVR and other PC VR](https://nightly.link/icosa-foundation/open-brush/workflows/build/features%2Fbrush-editing/Windows%20OpenXR.zip)(Vive, Index, Reverb...)
* [Other Builds](https://nightly.link/icosa-foundation/open-brush/workflows/build/features%2Fbrush-editing) (Pico, Pimax etc)
* [Code](https://github.com/icosa-foundation/open-brush/tree/features/brush-editing)

### What does it do?

It's an attempt to provide a runtime UI for Tim Aidley's "User Brushes" feature:

See:

* <https://docs.google.com/document/d/1tEGN6OjAI7DSIeqWwfdPOAH_APv-33cOEwz_gDdVVe8/edit>
* <https://github.com/TimAidley/open-brush/blob/features/simple-brushes/Docs/UserBrushes.md>

Currently it:

1. Allows you to create a new user brush by duplicating an built-in brush
2. It exposes shader parameters as sliders and shows a preview stroke changing in realtime as you adjust the sliders

### What's it good for?

Making your own crazy brushes!

### How do I install it?

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/>

### How do I use it?

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)

### Known Issues

Lots. It's an early proof of concept

## How do I get help

Come over to the [Open Brush Discord](https://discord.openbrush.app) and chat to me ( @andybak#5425 ). I'm on UK time (currently UTC+1) but I check in fairly regularly.

### Can I see it in action?

I made a quick video showing an early stage example:

{% embed url="<https://www.youtube.com/watch?v=BWCpKSLiWKE>" %}

{% embed url="<https://www.youtube.com/watch?time_continue=7&v=G3LN3OEPqKQ&feature=emb_logo>" %}


# Feature: Sculpting

Made by [Chingiz Dadashov-Khandan](<mailto:chingizdkhandan@gmail.com >) as a project for [The University of Groningen](https://www.rug.nl/?lang=en)

Status: <mark style="color:red;">Experimental. Saved sketches are incompatible with official builds</mark>

{% embed url="<https://www.youtube.com/watch?v=UAvjtiK-Bek>" %}

## Download

* [Oculus Quest 1](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fsculpting/Oculus%20Quest%20%282%2B%29.zip)
* [Oculus Quest 2 or 3](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fsculpting/Oculus%20Quest%20%282%2B%29.zip)
* [Oculus PC VR](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fsculpting/Windows%20Rift.zip)(Rift, Quest via Link cable...)
* [SteamVR and other PC VR](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fsculpting/Windows%20OpenXR.zip)(Vive, Index, Reverb...)
* [Other Builds](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fsculpting) (Pico, Pimax etc)
* [Code](https://github.com/icosa-foundation/open-brush/tree/feature/sculpting)

### What does it do?

Allows you to modify brush stroke meshes like digital clay

### How do I install it?

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/>

### How do I use it?

Switch to advanced mode and use the new sculpting tool on any brush strokes. Works best on hull brushes.

### Known Issues

{% hint style="info" %}
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.
{% endhint %}

## How do I get help

Come over to the Open Brush Discord: <https://discord.openbrush.app> and chat to me @andybak).

I'm on UK time but I check in fairly regularly.

### Can I see it in action?

TODO


# Combined Testing Build

To make trying out multiple features easier I used to maintain a "Kitchen Sink" build that combined multiple feature builds in one.\
\
I don't have a current combined build. Instead try our [current beta release](/alternate-and-experimental-builds/open-brush-beta-docs)


# Old or Completed Feature Builds

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.\\


# Feature: Polyhedra

#### Status: <mark style="color:red;">OUTDATED</mark>

<mark style="color:red;background-color:red;">**THIS BRANCH HAS BEEN SUPERCEDED BY A NEW COMPLETELY WRITTEN VERSION WITH MANY MORE FEATURES**</mark>

See the new [3D Shapes](/alternate-and-experimental-builds/3d-shapes) feature instead!

### What does it do?

![Polyhedra Tool](/files/-MikxGjNlPb8UIebeXu0)

![Custom Symmetry](/files/pHyImkQtvzxgd64QCbA9)

Mainly two related things:

1. Adds a polyhedra tool that can create a wide variety of polyhedra and grid patterns using brush strokes
2. Adds a custom symmetry tool similar to the existing mirror except it creates multiple strokes for each face of your selected polyhedra or grid

### What's it good for?

Creating regular patterns and geometry forms.

### How do I install it?

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/>

### How do I use the Polyhedra tool?

1. Switch out of beginner mode and you'll see the "Experimental Tools" panel on your wand.
2. There is a new icon at the bottom that looks like a wireframe cube. Click that to activate the polyhedra tool.
3. Draw a cube with your brush hand. Click once to start and release when you're happy with the size and rotation.
4. 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
5. The panel that opens when you first clicked the button let's you select various shape.
6. If you want to change the default colours simply add some custom colours at the bottom of the standard colour picker panel.

### Known Issues with the polyhedra tool

1. There's nothing to stop you creating extremely complex shapes that might slow everything down
2. There's currently no colour controls but you can use the standard recolor tool on your shapes.
3. Snapping is a bit unpredictable sometimesree paint mode. You need to select the polyhedra tool every time you change brushes.
4. Scene scale and brush size interact in a slightly confusing way.

### How do I use the new symmetry mode?

1. 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.
2. The symmetry mode only affects normal paint strokes. You can't currently use symmetry to create multiple copies of the polyhedra tool.
3. You can grab the symmetry widget and change it's position and orientation.

### Known Issues with the custom symmetry mode

1. It's possible to create very complex sketches very quickly.
2. There's no control over the color variation of the symmetry strokes.
3. You can't scale the grids. Instead scale your scene
4. I haven't added any way to control the colours of the additional strokes yet.

## How do I get help

Come over to the Open Brush Discord: <https://discord.openbrush.app> and chat to me ( andybak#5425 ).

I'm on UK time (currently UTC+1) but I check in fairly regularly.

### Can I see it in action?

Here's an earlier version of the polyhedra tool:

{% embed url="<https://www.youtube.com/watch?v=HRrJWFB11IU>" %}

Here's a video with terrible audio showing the symmetry tool:

{% embed url="<https://www.youtube.com/watch?v=Lnf6mS8xNIg>" %}

and another without any audio:

{% embed url="<https://www.youtube.com/watch?v=xrsxaVxNMvY>" %}

Yeah. I really need to do better videos. Please share anything you make that I can use to show off the features.


# Feature: Snip Tool

#### <mark style="color:red;background-color:red;">**THIS BRANCH HAS BEEN RELEASED AND IS PART OF THE REGULAR VERSION OF OPEN BRUSH**</mark>

#### Status: Released in [v2.0](/release-history/v2.0-xr-update)

### What does it do?

![](/files/61ukQQslXaBLS69u1kVZ)

{% embed url="<https://twitter.com/andybak/status/1488929073288163332?s=20&t=T74T-QeYnZna7cKASXBGgg>" %}

It allows you to cut strokes so they behave as if they were separate strokes.


# Feature: Layers

#### <mark style="color:red;background-color:red;">**THIS BRANCH HAS BEEN RELEASED AND IS PART OF THE REGULAR VERSION OF OPEN BRUSH**</mark>

#### Status: Released in [v2.0](/release-history/v2.0-xr-update)

### What does it do?

{% embed url="<https://youtu.be/uWAuh80yLPE>" %}

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.

### How do I install it?

This is now part of the regular release of Open Brush

## How do I get help

Come over to the Open Brush Discord: <https://discord.openbrush.app> and chat to me ( andybak#5425 ).

I'm on UK time (currently UTC+1) but I check in fairly regularly.


# Insominx's (michael-g) Experimental Build

#### <mark style="color:red;background-color:red;">**THIS BRANCH HAS BEEN RELEASED AND IS PART OF THE REGULAR VERSION OF OPEN BRUSH**</mark>

**Note: Released in** [**v1.0**](/release-history/v1.0-happy-birthday-to-us)

This build was intended to streamline the UI with a subset of features to:

1. Not overwhelm the user with complexity. This essentially meant that it should look as similar to basic mode as possible.
2. 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".

This build was successfully utilized to teach aspects of raytracing as show in the video below and its git repository can be found [here](https://github.com/insominx/open-brush).

{% embed url="<https://www.youtube.com/watch?v=wFo035DyciI>" %}


# XR Framework Beta

The future of Open Brush begins here!

#### <mark style="color:red;background-color:red;">**THIS BRANCH HAS BEEN RELEASED AND IS PART OF THE REGULAR VERSION OF OPEN BRUSH**</mark>

**Status: Released in** [**v2.0**](/release-history/v2.0-xr-update)

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.

### I want to help test! Where do I get the new build?

Thank you very much! Please join our [Discord ](https://discord.gg/W7NCEYnEfy)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!\\

:warning: Remember that this is a beta release, so if you do any important work with Open Brush, please back up your files! :warning:

\
This section is very detailed per platform, so here's some quick links to your preferred version:\
\
[Windows via SteamVR (OpenXR)](#windows-via-steamvr-openxr)\
[Oculus Quest](#oculus-quest)\
[Oculus Desktop](#oculus-desktop)\
\
Already set up? Jump to:\
[What should I be testing?](#what-should-i-be-testing)\
[How do I report bugs?](#how-do-i-report-bugs)

### Windows via SteamVR (OpenXR)

Our desktop build is now powered by OpenXR! To make it easy to access, we have added a new beta channel on Steam.

![Accessing Open Brush properties via Steam.](/files/nOxELvXhFUjiAo7w4BGY)

First, grab Open Brush from the Steam store. Once you have added it to your library, right click on the listing and choose 'Properties...'

![The beta unlocks!](/files/u1MvE0akURA1fPsS9kwt)

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!

![Selecting the beta branch after opting in.](/files/46Zkv4AZFhirdXQ4rTMk)

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].

![Selecting the OpenXR Mode when launching Open Brush.](/files/yjrJa9gN0ZFbPJd3dOEK)

When you click Launch from within Steam, make sure to select 'Launch Open Brush in OpenXR Mode'!

### Oculus Quest

We have created a special [SideQuest](https://side.quest) 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 [excellent guide](https://side.quest/setup-howto) on setting up your Quest for development builds.

{% embed url="<https://sidequestvr.com/app/9538/beta-open-brush>" %}
SideQuest page link for those that know what to do!
{% endembed %}

#### Easy Installer (Beta)

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!

![Open Brush (feature-xr-v2) in the Unknown sources section of the Quest app drawer.](/files/zFng93rzNUaYGFPaZfu1)

#### Advanced Installer

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!

![Searching for Open Brush Beta in SideQuest](/files/IvV2pWhyABYABawQgNCY)

![Open Brush Beta page, highlighting the download app button.](/files/u3XPwojv2mhmHQGIsWFB)

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!

### Oculus Desktop

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 [Nightly Link](https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fxr_v2).

{% embed url="<https://nightly.link/icosa-foundation/open-brush/workflows/build/feature%2Fxr_v2>" %}

![nightly.link showing the various builds for xr\_v2](/files/obiejwCs7MUFXlF1rlFK)

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!

#### Rift (Oculus Desktop)

![Setting Oculus as active XR Runtime](/files/EM5qkNAhrjYlSU46i6K9)

**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.

### What should I be testing?

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 [prepared a list](https://github.com/icosa-foundation/open-brush/issues/249) over on our GitHub with suggestions of things to test (anything already ticked is assumed to be working).

### How do I report bugs?

If you are a GitHub user, please feel free to add a comment to our [Issue #249](https://github.com/icosa-foundation/open-brush/issues/249) where we are keeping track of validation.\
\
Otherwise, please join our [Discord ](https://discord.gg/W7NCEYnEfy)if you haven't already and post a message in the `#unity-xr` channel, we'll log it on your behalf!


# Feature: Transform Panel and Snap Enhancements

#### <mark style="color:red;background-color:red;">**THIS BRANCH HAS BEEN RELEASED AND IS PART OF THE REGULAR VERSION OF OPEN BRUSH**</mark>

#### Status: Released in [v2.4](/release-history/v2.4-prismatic)

<div><figure><img src="/files/D7h4XTLBmbAVDTWgsAe3" alt="" width="397"><figcaption></figcaption></figure> <figure><img src="/files/0pjgnpIR60oriK0jSgsP" alt="" width="410"><figcaption></figcaption></figure></div>

### What does it do?

A new panel allows for precise position/rotation/scale changes to brush strokes and imported objects.

1. Enter an exact value to change the position, rotation or scale of the current selection
2. Lock any axis so you can only move the selection along a line or in a plane
3. Lock rotation axes in a similar fashion.
4. Control which axes respond to the snap grid
5. Align all the objects or brush strokes you've selected in various ways
6. Distribute all the objects or brush strokes you've selected so they are spaced evenly.

We've improved the Snap Settings panel:

1. You can turn position and rotation snapping on or off for each axis independently
2. You can also snap all the currently selected objects
3. You can turn on or off the ability to snap the selected objects to guides

### What's it good for?

Creating regular arrangements of strokes or precisely positioning/orientating parts of your sketch.

### How do I install it?

This is now part of the regular release of Open Brush

### Where do I find the new Transform Panel?

It should appear automatically.

## How do I get help

Come over to the Open Brush Discord: <https://discord.openbrush.app> and chat to me ( andybak#5425 ).

I'm on UK time but I check in fairly regularly.


# Feature: Improved GLTF Importer

#### <mark style="color:red;background-color:red;">**THIS BRANCH HAS BEEN RELEASED AND IS PART OF THE REGULAR VERSION OF OPEN BRUSH**</mark>

#### Status: Released

## Download

This feature has now been merged into the main release

### What does it do?

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](https://github.com/atteneder/glTFast)

### What's it good for?

Importing a wide range of GLTF files into Open Brush including animated models.

### How do I install it?

This is now part of the regular release of Open Brush

### How do I use it?

Just import gltf models as you normally would.

### Known Issues

* There's no way to control the animation for animated models and selecting them can sometimes be tricky.

## How do I get help

Come over to the [Open Brush Discord](https://discord.openbrush.app) and chat to me ( @andybak#5425 ). I'm on UK time (currently UTC+1) but I check in fairly regularly.

### Can I see it in action?

Not yet.


# Feature: Multi-Mirror

#### <mark style="color:red;background-color:red;">**THIS BRANCH HAS BEEN RELEASED AND IS PART OF THE REGULAR VERSION OF OPEN BRUSH**</mark>

#### Status: Released in [v2.4](/release-history/v2.4-prismatic)

![](/files/y0DYMP7fn8CDhf4ddIJe) ![](/files/zIXuD7MKrZoNqpcQ7z1j)

![](/files/0hL3zKXz7xVkxFn6W6Dw) ![](/files/MHO96jIvL1zqv7MFLq64)

### What does it do?

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

### What's it good for?

Creating symmetrical patterns. Drawing multiple strokes at the same time. Arranging models or images into grids or other regular patterns.

### How do I install it?

This is now part of the regular release of Open Brush

### How do I use it?

Hold down the mirror button on the Experimental Panel for a second or two:

![](/files/KL6jpgjnMu81rk2xEDdg)

This will bring up the Symmetry settings panel which contains three tabs:

#### Point Symmetry

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

![](/files/a5UEWIfIb8hUddgJ1vXF)

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.

#### Options

![](/files/fmHk0ibdAMFaX9LyVbmX)

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

### Known Issues

1. 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.
2. 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.

## How do I get help

Come over to the Open Brush Discord: <https://discord.openbrush.app> and chat to me ( andybak#5425 ).

I'm on UK time but I check in fairly regularly.

### Can I see it in action?

{% embed url="<https://www.youtube.com/watch?v=khsI-7rl2yg>" %}
Some early experiments with spinning mirrors
{% endembed %}

{% embed url="<https://youtu.be/VxVjkV_CkFs>" %}
Another early test of the feature
{% endembed %}


# Feature: New Monoscopic Mode

{% hint style="info" %}
At the time of writing - the current [beta version](/alternate-and-experimental-builds/open-brush-beta-docs) has added a new [View Sketches mode and has made ](/user-guide/monoscopic-mode)[Monoscopic Mode available](/user-guide/monoscopic-mode) 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.
{% endhint %}

User @rapka on Github (@collige on the Discord) is working on a new, revamped version of the existing [Monoscopic Mode](/developer-notes/github-wiki/monoscopicmode) - 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>




---

[Next Page](/llms-full.txt/1)

