Photobooth Plugin

Photobooth is a plugin that allows you to capture images of the workspace or UI elements entirely in Roblox Studio.

It features the ability to remove skyboxes / backgrounds from images, tools to automate the capture of many targets in sequence, post-processing effects, and bindings that let developers write their own capture workflows.

Results are output as editable images stored on a mesh part’s texture.

Get it on Roblox Get it on Itch.io

Looking for support outside the devforum? Join the photobooth plugin community!

Examples





Limitations

Photobooth has a couple of limitations that are worth noting. For most users these will likely not be of significant impact, but they’re listed here so people can see them before getting the plugin.

  • Photobooth can only be used during edit mode in Studio. It cannot capture anything during a Studio play session.
  • The viewport must be visible when capturing. You cannot tab out of Studio or switch to the script editor while a capture is in progress.
  • “Studio Settings > Rendering > Graphics Mode = OpenGL” is unsupported (this is a Roblox bug). The plugin will warn you if you attempt to capture in this mode.
  • “Studio Settings > Rendering > Graphics Mode = Vulkan” is supported, but some users experience a bug where emulators that match their display resolution force them into fullscreen and won’t allow them to take captures.
  • Atmosphere is supported. Fog is not - if you attempt to capture with fog it will hide itself.
  • Anything that cannot be frozen in place on screen is not supported. For example:
    • Terrain grass.
    • Force-field material with a moving texture.
  • Retro color grading is highly recommended for best results, but not mandatory.

Warning: This plugin will cause the screen to flash when removing skyboxes. Those with photosensitive epilepsy are advised caution when using this plugin.

OS Scaling

With the advent of high resolution monitors many computers use scaling options built into their operating system to ensure that applications rendered on screen are not too small. Roblox, however, always captures in full resolution, leading to a number of UX problems.

Photobooth will attempt to function with your device’s os scale in mind, but for the highest quality image it is strongly recommended to use your monitor’s true resolution - i.e. scale 100% and the display resolution that matches your monitor.

Or on Mac

Capturing

Cropped Viewport Captures

In cropped capture mode you can draw a rectangle over the viewport to capture a specific region. This mode has a 2048 x 2048 limit. For anything larger, use full viewport captures.

While in cropped capture mode you can hold the shift key to drag your capture rectangle around the viewport and resize non-symmetrically. You can also hold the control / command key to maintain aspect ratio when sizing from the corners.

Full Viewport Captures

It is possible to circumvent the cropped-mode limit of 2048 x 2048 by capturing the entire viewport window. You can toggle to full viewport capture mode from the action bar or in the settings menu.

To set an arbitrary resolution you can either resize your viewport (not recommended) or take advantage of custom device resolutions in the emulator.

When photobooth captures in the emulator it requires you use the “actual resolution” mode in the emulator. If you attempt a capture while not in this mode photobooth will briefly switch to it and back for the duration of the capture.

Note: Full viewport captures will result in images with their dimensions as viewportSize * osScale. It is highly recommended to adjust your display settings such that OS scale is (1, 1) when using full viewport captures.

UI Captures

In addition to the workspace, Photobooth can capture UI elements. This is useful for flattening complex GUIs into a single image. Select a GuiObject in the explorer and then select the UI button on the plugin toolbar and the capture will commence.

Auto Capture

Auto Capture lets you batch capture many targets in sequence rather than framing each one by hand.

On capture the workspace will be hidden so it is strongly recommended to do auto-captures in an empty baseplate or something similar to avoid any impacts on your main placefile in the event of an error.

Most of the options here are self explanatory or easy to figure out, but there are a few worth calling out.

Synchronized

By default the tool is set to synchronize options, the camera angle, etc. across all your capture targets. However, sometimes you may want to individually adjust each target. Toggle off the value and change any desired properties. Now you can switch targets and the configurations for each item will behave independently.

Fit Type

This option determines how the camera should behave when focusing on a capture target.

  • Orbital - Calculates the minimum fixed distance required such that any possible camera angle will contain the target. This does not account for animation transforms.
  • Point Cloud - Uses the point cloud of the target and the camera angle to determine the exact fit CFrame. This does account for animation transforms.
  • Free - Let’s you freely move the camera around the workspace to achieve any camera angle.

Animation

Any capture targets with animators in them can have an animation applied by pasting an animation id to the animation instance in the camera. This will bring up a playback bar that can be used to set the exact frame as desired.

Ignore Tag

By default all BaseParts inside an auto capture target are taken into account when calculating the bounds of the orbital and point cloud fit types. This can be problematic if the user does not want certain elements of the capture target to be included in the bound calculation. Adding the photobooth:ignore tag to an instance in the capture target will filter that instance and all its descendants from the bounds calculation.

For example this tree has a baseplate attached to it. By default the baseplate is included in the bounds calculation. The baseplate could be deleted and tree alone would be properly bounded, but say you wanted it to be visible in the capture.

By adding the photobooth:ignore tag to the baseplate it now gets ignored in the bounds calculation which solves the issue.

Post-Processing Effects

The post processing tool lets you add effects like drop shadows and strokes quickly and easily to your captures.

Layers are a copy of your image that you can apply effects to. Using a combination of layers and effects you can create an assortment of composition types. A number of examples can be found under the presets tab and you can even add your own!

Saving Captures as PNGs

If you want to save any of the plugin captures to your computer, right-click the exported mesh part and select “Export as Obj”. This will prompt you to export the mesh in .obj format, which includes the texture as a .png. Both the .obj and .mtl files can be discarded.

To export many images at the same time first select all the mesh parts at you want, and then export that selection.

glTF Exports

Alternatively, you can export your Photobooth selection in the glTF format. This may be preferable, as many users have reported that exporting as an .obj can sometimes not work in studio due to Roblox bugs.

To extract the pngs from a glTF file you’ll need an additional tool. For convenience I’ve created a website where you can drag and drop the export and get the resulting pngs.

Uploading

Photobooth also offers the ability to upload your captures directly to roblox to either your account or a group you have permission to upload images to.

Currently this feature is disabled by default because it requires that the CreateAssetAsync beta is enabled and the plugin is locally installed. You can read more about that from Roblox here.

If you really find yourself needing the uploader feature I’ve created a standalone uploader plugin that you can install locally.

Download Uploader

Install instructions
  1. Take the rbxm and put it in “Plugins > Plugins Folder”.
  2. Open “File > Beta Features” and enable the “CreateAssetAsync Lua API” beta.
  3. Restart studio.

You can also write your own code to upload editable images if you don’t want to install the local plugin:

Sample code
local ATTRIBUTE_NAME = "UploadResult"

local AssetService = game:GetService("AssetService")
local SelectionService = game:GetService("Selection")

for _, selected in SelectionService:Get() do
	if selected:IsA("MeshPart") and not selected:GetAttribute(ATTRIBUTE_NAME) then
		local content = selected.TextureContent
		local object = content and content.Object

		if object and object:IsA("EditableImage") then
			local result, value = AssetService:CreateAssetAsync(object, Enum.AssetType.Image, {
				Name = selected.Name,
				Description = "",
				IsPackage = false,
			})

			if result == Enum.CreateAssetResult.Success then
				selected:SetAttribute(ATTRIBUTE_NAME, `rbxassetid://{value}`)
			end
		end
	end
end

Some other options would be to export as pngs and then use the asset manager, the importer, or a third party tool like asphalt.

Advanced

Experimental Mode

As of v1.2.0, Photobooth supports a setting called experimental mode. Enabling it requires restarting Studio and is not available during team create sessions.

Experimental mode is a way to provide speculative features to the public without any guarantee that the behavior will remain supported in the future. If you enable this mode, be aware that any behavior it exposes may be removed and should not be relied on.

Blackout Mode

This setting can be toggled on / off to set a pure black background quickly and easily without changing the skybox (which can impact the scene lighting). This makes it easier to see how things that get influenced heavily by their background will actually capture with photobooth.

Bindings

Photobooth also exposes some of its capture API in the form of bindings. This allows script capable developers to write their own code that takes advantage of photobooth’s capture capabilities.

To use this feature, open the viewer and in the settings menu toggle “Bindings” to true.

Roblox may prompt you for script injection permissions.

This creates a ModuleScript underneath ServerStorage which provides a typed interface for building automated capture workflows. A couple of common template workflows are included to get you started.

local Photobooth = require(game.ServerStorage.Photobooth.Bindings)
local capture = Photobooth.captureViewport({
	rect = Rect.new(0, 0, 300, 300),
	type = "NoSkybox",
})

capture.Name = "Example"
capture.Parent = game.StarterGui

Fullscreen captures can be made with bindings by passing a rect that represents the viewport:

local viewportSize = workspace.CurrentCamera.ViewportSize
local capture = Photobooth.captureViewport({
	rect = Rect.new(Vector2.zero, viewportSize),
	type = "NoSkybox",
})

Captures should be parented as a descendant of StarterGui. This ensures they can be properly exported as pngs.

Note: For the highest quality image when using bindings, it is strongly recommended to use your monitor’s true resolution (i.e. OS scale 100%)

Reviews

If you’ve been using the plugin for awhile I appreciate leaving a review + thumbs up on the creator store. It helps others discover this plugin as well!


Change Log

406 Likes

Glad to see this is finally out! But it seems to be bugged for me currently making it unusable

image

11 Likes

Thank you for this report. I’m jumping right on it!

What is the context you’re capturing under? - Are you perhaps in team create?

7 Likes

Im just in studio not running a play test. Yes it is a team create enabled place

4 Likes

Okay, that’s likely the issue. I believe I can pretty easily fix that. Hold tight an update will come very soon.

9 Likes

Should be fixed now. Please update the plugin!

6 Likes

Alright i appreciate the speedy response. I just tried it out on a new baseplate without team create enabled and it works great, already one of my favorite plugins!

2 Likes

The fix worked great for me too!
image

21 Likes

Awesome!

Just a reminder that as with regular editable images in a team create sessions your co-devs won’t be able to see the capture results since Roblox explicitly doesn’t allow the replication of editable images. You’d have to first upload the results and then use the asset id for them to see.

I myself have not yet tested this behavior so I could be completely wrong in this statement, but something to consider / be aware of.

3 Likes

Yeah that makes sense. We mainly just have a separate shared place with a bunch of assets for the main game, so replication is not really important in my case

2 Likes

This is actually amazing! Thank you EgoMoose!

4 Likes

Game changer for sure! Definitely getting it!

2 Likes

The lebron james of roblox. :sunny:

13 Likes

Was looking for something like this a few days ago!! thanks for making this, extremely useful

1 Like

Can you also release this on itch.io or somewhere else? I can’t really buy it from the Creator Store and would even consider donating more. This is so very well worth the price; it’s a great plugin.

3 Likes

2025 Best Plugin winner, no doubt

3 Likes

I don’t inherently have an issue with selling on another store front, but I have to read into Roblox’s ToS to make sure that’s okay. Beyond that I’ll prob also take some time to speak to other devs who have released on different marketplaces to field their thoughts.

I’m curious why the creator store isn’t an option for you? Is it unavailable in certain countries? Lack of payment options? etc…?

2 Likes

Lack of payment options basically, and I don’t really like purchasing from Creator Store itself.

Boatbomber released their Benchmark plugin on itch.io, you can go ahead and ask him for details if you wish. You can sell Plugins on other sources.

1 Like

That error seems to be unrelated to the plugin. However, try first viewing the capture in the viewer then exporting. I believe this is a fincky thing on Roblox’s end that causes the texture of the mesh to register as empty until it’s actually needed by the engine/renderer.

Let me know if that fixes it which will give you a short-term fix and I’ll look towards a long-term solution.

5 Likes

The short-term fix does indeed work, the EditableImage just needs to stay rendered. Thank you.

3 Likes