Photobooth Plugin

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

Notably, it features the ability to remove skyboxes/backgrounds from images and bindings to allow developers to write their own capture workflows.

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

roblox-marketplace-badge itch


Examples





Limitations

Photobooth has a couple of limitations specific to the skybox removal preset. For most users these will likely not be of significant impact, but I’m listing them here so people can see them before purchase.

General:

  • No capture can be larger than 1024 x 1024 since that’s the limit of editable images.
    • As of v0.3.0 there are no longer size limits, but there are some stipulations. Please read the “Full Viewport Captures” section for more details.
  • Photobooth can only be used during edit mode in studio. It cannot be used to capture anything during a studio play session.
  • The built-in upload feature is currently disabled. You can still upload, but you have to write code to do it yourself. Read more about this further down the post.
  • Using the emulator + photobooth only works correctly when on “actual resolution”

Skybox removal:

  • No atmosphere / fog support.
  • Anything that cannot be frozen in place on screen is not supported. For example:
    • Terrain grass.
    • Force-field material.
  • Retro color grading is highly recommended for best results, but not mandatory.

Bindings:

  • See the OS scaling section below

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

Bindings

This plugin can be used for automation purposes. An example use case might be capturing icons for all the inventory items in your game thereby allowing you to avoid using viewport frames which are more expensive than traditional images.

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

RobloxStudioBeta_p95RW4mQpS

Roblox may prompt you for script injection permissions.

RobloxStudioBeta_bbMp0Ictpr

This will create a ModuleScript underneath ServerStorage which provides a typed interface that can be used to create automated capture workflows. Included are a couple of common template workflows to get you started.

For example:

local Photobooth = require(game.ServerStorage.PhotoboothBindings)

local capture = Photobooth.captureViewport(Rect.new(0, 0, 300, 300), "NoSkybox")
capture.Name = "Example"
capture.Parent = game.ServerStorage

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 resolve this issue automatically, but for the highest quality image when using bindings it is strongly recommended to use your monitor’s true resolution.

i.e. use scale 100% and the display resolution that matches your monitor.

Or on Mac

Full Viewport Captures

Normally editable images have a 1024x1024 limit. However, it is possible to circumvent this by capturing the entire viewport window. You can toggle to full viewport capture mode by using the the “Photobooth Viewport Fullscreen” action.

Using this action while the Photobooth viewport is open will switch to a fullscreen capture mode. To set an arbitary size you can either resize your viewport (not recommended) or take advantage of custom device resolutions on the emulator.

It’s very important that you use the “Actual Resolution” option when capturing in the emulator. For very large dimensions that don’t fit on screen I recommend temporarily switching to “Fit to Window”, setting up the scene, and then switching back to “Actual resolution” once you’re ready to capture.

Saving Captures as PNGs

If you want to save any of the plugin captures to your computer, you can do so by right clicking the exported mesh part and selecting “Export Selection”.

This will prompt you to export the mesh in .obj format which will include the texture of the mesh in .png format. Both the .obj and .mtl files can be discarded.

If you want to export many images at the same time. First group all the mesh parts together as a model and then export that model.

Uploading

This feature is currently disabled!

Uploading will be enabled in the future once Roblox provides the proper security tooling to allow creator store plugins to upload assets on your behalf. More detail from Roblox here.

For now, developers will have to write their own code to upload editable images.

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

When this feature is enabled this is what the upload process will look like:

Reviews

This is a brand new plugin and I think it offers a tool that has otherwise traditionally been locked behind 3rd party applications.

I have spent a lot of time ironing out bugs and issues, but if you find any I’d very much appreciate reaching out to me before jumping to leaving a negative review. If you’ve done that and I haven’t reasonably responded or given a good solution then go nuts!

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

[0.1.1]

  • Add full color correction support!
  • Fix maintain aspect ratio when holding ctrl and dragging viewport corners
  • Unify plugin names:
    • “Photo Booth” → “Photobooth”
    • “Viewer” → “Gallery”
  • Gallery button properly toggles off when player closes the dock minimized
  • Add version number in the settings

[0.2.0]

  • Add new plugin action (Photobooth Focus) which allows user to focus their camera on a selection and fit the capture frame in the viewport
  • Alpha bleed fixes
    • Algorithm now only bleeds one pixel which saves a lot of time on images with a lot of transparency
    • Fix algorithm mistake where pixels could sample their neighbors before they should be allowed to

[0.2.1]

  • Check for CreateAssetAsync API to show / hide upload button

[0.2.2]

  • Add support for transparent glass

[0.3.0]

  • Add full viewport capture support (say goodbye to the 1024x1024 limit)
  • Alpha bleeding changes:
    • Fix incorrect assumption about bleeding one pixel
    • Add option to disable alpha bleeding
  • Add ability to change background of an image being viewed in the gallery by right clicking
  • Icons no longer use local assets and instead all have asset ids
  • Uploading an editable image no longer makes a copy before opening the upload wizard
  • Attempting to capture with a mismatched OS scale now warns
170 Likes

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

image

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

2 Likes

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

3 Likes

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

4 Likes

Should be fixed now. Please update the plugin!

4 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

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

1 Like

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

1 Like

This is actually amazing! Thank you EgoMoose!

4 Likes

Game changer for sure! Definitely getting it!

2 Likes

The lebron james of roblox. :sunny:

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

2 Likes

2025 Best Plugin winner, no doubt

1 Like

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

1 Like

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

I’m not sure if I’m doing something wrong, but I get some error when I take a photo. Exporting the result mesh doesn’t appear to save a .png texture file either.


image

  20:15:40.365  Error: attempt to index nil with 'Parent'  -  Edit
  20:15:40.365  builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.Scheduler.Scheduler.forks.SchedulerHostConfig.default:117: 
------ Error caught by React ------
attempt to index nil with 'Parent'
------ Error caught by React ------
builtin_TextureGenerator.rbxm.TextureGenerator.Src.Components.ViewSelector:51
sabuiltin_VisualizationModes.rbxm.VisualizationModes.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberHooks.new:1539 function mountMemo
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.React.React.ReactHooks:178 function useMemo
builtin_TextureGenerator.rbxm.TextureGenerator.Src.Components.ViewSelector:37 function ViewSelector
sabuiltin_VisualizationModes.rbxm.VisualizationModes.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberHooks.new:3134 function renderWithHooks
sabuiltin_VisualizationModes.rbxm.VisualizationModes.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberBeginWork.new:207 function renderWithHooks
sabuiltin_VisualizationModes.rbxm.VisualizationModes.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberBeginWork.new:1575 function mountIndeterminateComponent
sabuiltin_VisualizationModes.rbxm.VisualizationModes.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberBeginWork.new:3483 function beginWork
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:245
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:1946
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:1834
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:1783
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:919
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:837
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.Scheduler.Scheduler.Scheduler:304
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.Scheduler.Scheduler.Scheduler:260
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.Scheduler.Scheduler.forks.SchedulerHostConfig.default:81 function doWork
builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.Scheduler.Scheduler.forks.SchedulerHostConfig.default:104 function performWorkUntilDeadline
  -  Edit
  20:15:40.365  Stack Begin  -  Studio
  20:15:40.366  Script 'builtin_MaterialPicker.rbxm.MaterialPicker.Packages._Index.Scheduler.Scheduler.forks.SchedulerHostConfig.default', Line 117 - function performWorkUntilDeadline  -  Studio
  20:15:40.366  Stack End  -  Studio
2 Likes

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.

3 Likes