How to Photoscan Props with Substance 3D Sampler to Unreal Engine 5

Tutorial / 23 June 2023

Hello there and welcome to my short breakdown on how I used Substance 3D Sampler to photoscan my Gameboys into Unreal Engine 5. Theres a lot of different ways to photoscan, however I found this workflow to work best for me especially in making game ready photoscans. I’d always recommend doing more research before trying any hard-set pipeline, but I hope this guide can help you understand the general process of photoscanning, cleaning up scans and optimizing.

What I used:

  • A camera, you can use your phone but preferably a DSLR or mirrorless photo camera with adjustable aperture/focal lengths.
  • Strong computer with Substance 3D Sampler, 3DSMax, Blender, ZBrush, Substance Painter and Unreal Engine 5 installed.
  • A mug of coffee (optional)

Contents:

  1. Taking Pictures + Processing Scans in Sampler
  2. Cleanup and Assembly of Photoscans in 3DSMax (Optional Zbrush Import)
  3. Retopoligising High to Low Poly Mesh with UV Unwrapping In 3DSMax
  4. Reprojecting Diffuse Maps in Blender
  5. Baking the Rest of the PBR maps in Substance Painter + Cleanup in Photoshop
  6. Presenting Assets in Unreal Engine 5
  7. Tips and Troubleshooting
  8. Final Thanks and Thoughts

1) Taking Pictures + Processing Scans in Sampler

The first step to photo scanning is taking photos, and a lot of them at that. Sampler will end up cutting some out if they are blurry or difficult to match to one another so having more is better being safe than sorry later on. For taking my photos I ended up buying a cheap DLSR camera (Sony A230) so I would be able to lower the aperture and focus the shots more clearly than my phone camera. Lower aperture lets you blur the background when taking shots automatically and lock other settings like focal length keeping shots consistent + helps Sampler identifying what to cut out when generating masks.

Posing and setting up the props is crucial too, as any shadows cast, or hidden sides will not scan properly. I’ve been advised by professionals to try hang the props using fishing wire or use a tall pedestal to rotate the assets around a stationary setup in future. However, for my first try and with limited resources on hand I ended up taking a small board to prop the Gameboys up in the garden and took hundreds of photos of each side (rotating and resetting the Gameboy on the stand) to capture all angles. Do not move the props unless you know you are unable to capture certain angles!

The lighting the day I was taking photos of was quite cloudy which is ideal to ensure no harsh shadows ended up showing up on my scans. However, as I did miss some edges when photo scanning, I had to retake shots the day after to make up for it, which had slightly different lighting. This ended up affecting the colors of the photoscans even if the geometry matched so be warned there is more cleanup and patching to do later if you don’t take all the photos in the same day. Having access to a photography studio or a few high-power lamps would resolve this too as you have full control over the lighting.

Now comes the fun part – processing the scans in Substance 3D Sampler. Simply open up a new project and select new 3D capture. As I moved the object around to capture all the sides on my stand, I will have to scan these lots of images separately to generate separate meshes as Sampler will struggle to combine them on its own. After dragging in a group of photos, say the front side you can add extra info such as the sensor size or generate a mask. Since taking a lot of photos can make masking manually a bit of a chore, you can get sampler to generate masks itself. Depending on the color differences, blur, and other magical settings the quality of these masks can vary. But overall, I haven’t had too many issues generating them and much prefer the option since it saves a ton of time.

Next you submit the scans to begin processing and can select low or high precision alongside how to order the photos. I generally left this on low precision and default order as the mesh came out great and my dataset wasn’t too complex to process. However, if you miss any detail its worth going back and reprocessing using other settings to see if you can salvage it. Generally, through all my scans the Gameboy screens always processed poorly due to their shiny nature so to tackle this in the future I’d recommend placing paper or some sort of covering over the top to help keep the shape intact.

Youd then have to lightly touchup the color maps later to regain whatever’s covered by texturing it manually. With the mesh/meshes reconstructed, it’s time to set the post process settings before exporting this mesh to 3DSMax. I tend to up the 2048 map to 4096 to get the highest quality my computer can handle working on alongside upping the target face count. Theres more settings for how Sampler handles baking the normal, AO and even decimation/texture reprojection of the mesh that can help polish the scan here too. However, the scan is not game ready by any means yet, the UV unwrap for one is highly inefficient resembling a banana peel at best with the model having a high tricount that could be optimized better. So, time to fix this in 3DSMax.

2) Cleanup and Assembly of Photoscans in 3DSMax

With how Sampler scans models it’s not guaranteed they will be orientated the same so after importing all the scans into 3DSMax it’s time to carefully repositioning, resize and refit all the meshes together. Unless you have only a singular scanned mesh in which case it’s good to go. If there are any holes you can use the edge selection to bridge or cap these areas. It will unfortunately not bring back any missing textures but will make the model easier to work on with less holes in Zbrush later. I also used the vertices tool to cut and delete faces of my pink stand that was also captured below the Gameboy. However, if the model is too low poly to delete these faces without removing data from the mesh you can later do this more cleanly in Zbrush.

It is up to you if you want to combine this high poly photo scanned asset into one mesh. However, be careful as this may lose your automatically assigned textures unless the material is set up as a multi sub object material with correct ID channels for each mesh texture set beforehand. I ended up keeping the high poly in a group in the hierarchy, not merging it. Due to how some edges scanned I ended up using symmetry to bring back higher res detail due to the symmetrical nature of the Gameboys. The next step is optional, as bringing the combined assembled mesh into Zbrush is only something I do to push the details further and smooth out any broken edges.

You can also get Zbrush to retopologies a low poly base with better geometry to work on top of for the low poly mesh later rather than starting from scratch. Plus, a handful of more polishing with the ease of handling higher geometry counts that 3DSMax can. But if you feel the scans are sufficient enough you can begin making a low poly retop with good UV unwraps and skip out of this program entirely.

2) Optional Zbrush Import + Cleanup

Jumping into Zbrush, when importing the highpoly, ensure you check keep UVS and textures on. Each separate mesh will appear as its own subtool in the hierarchy which will make working on them nondestructive and easy to jump between. I recommend starting off by subdividing the scans quite a bit to make it smoother to delete any unnecessary geometry, such as stands, through the hide and delete hidden functions. Caution you can only do this on the lowest subdivision so you may have to delete the lower counts. With varying move brushes, smooth and carving tools you can add extra surface detail to the high poly here. The geometry is not perfect, and you shouldn’t remesh the photoscan as it will lose the UV detail + the photo scanned textures since it changes the mesh entirely.

After the model is polished to the best of its ability and aligned well, I recommend 2 different exports. The first being the high poly model, after some decimation (don’t forget to keep UVS when calculating and decimating!) You can get a way better higher poly model to use in baking rather than the original export from 3DSMax through this. It’s important to decimate the subtools as 3DSMax does not handle high poly geometry as well as Zbrush so bringing it down will give you the best chance of avoiding crashing. The second model being a low poly model, which you can make by combining all subtools and then remeshing them. This will lose the UVS, and detail however allows you to work from a similarly shaped mesh to your high poly back in 3DSMax. This method also works best with scans that are entirely one mesh to begin with (for example the Pokémon plushies). Now it’s time to head back into 3DSMax to make a low poly to bake to.

3) Retopoligising High to Low Poly Mesh with UV Unwrapping In 3DSMax

Whether or not you are starting from no mesh or the low poly remeshed geometry from Zbrush it’s important to align everything once more. Have the high poly on the same coordinates as the low poly or whatever base geometry you might use to retop. A great tool in 3DSMax is the Freeform < Object Pick Tool that lets you use a mesh as base to conform/draw new verts over. As the high poly is made up of parts/separate meshes (to help preserve the UV texture) I save a different copy of the scene in which I merge down the highpoly so it can be “picked” by the tool. For re-topping I tend to either draw a lot of verts and conform down or use a base square to work with dragging edges upwards to conform to the shape if starting from scratch. Either way its important to try and capture as much as possible in the silhouette of the asset and if there are any additional functionality, like buttons or switches, to model them in too. It’s important not to go too low poly as to lose any rounded edges or important mesh details if you are also working from a remeshed copy. After being satisfied with a good low poly mesh its important to UV unwrap it and try to smooth out the UVS as best as possible. Since the reprojection results will be affected if the UVS are not straight/warped. Since the Gameboys are all separate, I ended up giving them a sheet each. However, with having to reproject the textures later you can merge multiple props to one sheet to help save on space if you are making a modular kit of photo scanned assets.

4) Reprojecting Diffuse Maps in Blender

Blender is really the bread and butter of making the photoscan game ready as now we can take the high poly with textures model and reproject the maps onto the better unwrapped final low poly model. From 3DSMax, export the low poly model separate from the high poly photo scanned mesh (or meshes if multiple is needed) as a. FBX (don’t forget to embed textures on export). Align them both to the same point as to cause overlap and then head into the Shading tab. If the low poly does not have a material be sure to set one up (red ball with UV icon on the bottom right) and add a new image texture node that is blank (this will be where the baked map will go) on the bottom material node screen. I tend to keep these maps at 4096 resolutions since it is much easier to down scale and keep detail than it is too upscale later. Now double check the high poly meshes have the textures attached as well to their own material outputs (by clicking on the meshes in the hierarchy). Ensure metal is set to 0 as a value, sometimes blender can set exported random materials values to 1 which will cause problems when baking such as making the texture turn black.

Now onto the fun part; baking the textures down. First, it’s important to setup the bake settings correctly. Head over to the Render Properties panel, and make sure the renderer is set to Cycles. For devices I also recommend setting GPU as the rendering will go much smoother and faster than CPU (depending on your PC rig). Then heading down, under sampling set the renderer and viewports max samples to 1 (this will help save performance and has no effect on baking to my experience). Furthermore, you can set the light path to have max bounces of 1 and no reflective or refractive caustics. Under performance, make sure the tiling is set to be used, with the tile size matching whatever the image texture node is set to be baked to on the low poly prior. This will ensure the bake is the correct size. Further down under Bake, set the bake setting to be Diffuse (for color maps) or Normal (for normal data). I recommend mainly baking the diffuse color detail as the normal and AO maps can be made in Painter with better baking there. For baking diffuse ensure that under the bake settings both Direct and Indirect lighting is also turned off. We only want color data to transfer and not any lighting data from the scene. Enable selective to active, this ensures baking from only the selected meshes. I recommend playing around with the extrusion settings as depending on the low poly you may have to increase it around the range of 0.05-2 to avoid any clipping.

Now is the final and most important step, select all of the high poly meshes and then your low poly last (hold down ctrl when clicking in the hierarchy). With the low poly selected go to the image texture node you made and ensure it also is selected (it will have a white border) and hit bake back on the render properties panel. If using multiple meshes it generally takes longer for progress to show but don’t be worried if the texture bake progress sticks on 0%. After a bit of time the maps will be projected and baked onto the image texture node you made (it should show on the bottom left, if not make sure it is viewing the image). And all it takes is saving the image (click the lines icon above the image preview on the bottom left and then Image < Save as) to export it out. If you encounter any clipping simply go back and adjust settings, hitting bake to write over the image texture. If you want to bake other maps or adjust the image type/size, then be sure to hit the multiple paper icon on the image texture node to make a new image. If you adjust texture size don’t forget to adjust the tiling size! Now with textures baked across onto crisp UVS it’s time to do a bit of polishing and fixing the maps alongside generating new ones in Substance Painter.

5) Baking the Rest of the PBR maps in Substance Painter + Cleanup in Photoshop

As the previous export is already aligned, open up a new Substance Painter Project with PBR setting and texture size matching the diffuse bake. Set the project to open your low poly mesh exported previously and head over to the Texture Set Settings panel. Here is where the magic happens, however I tend to do a bit of housekeeping first which is optional. Add a new channel for ambient collusion and set both the normal and ambient occlusion mixing modes to replace. This allows us later to insert the textures and mask out any issues + work on top to add extra details. Now hit bake mesh maps and setup the bake settings to match the quality and resolution of your maps. Plus add the same high poly mesh export to bake from we have used in Blender to bake any missing details. Now with normal, ambient occlusion and other helpful maps for masking/generators baked you can head back into the layers panel. Add a new fill layer with your baked normal map and ambient occlusion (be sure to swap to AO/normal map viewing mode in the top left corner of layers to set the fill layer as normal instead of multiply/Nmdt). This puts the maps into working order as previously we have set the mixing mode to replace. If this hasn’t been changed then you do not need to worry about adding the maps back in. However, you cannot add a white mask to the layer and color out any baking issues.

Don’t forget to also import your exported diffuse map into Substance Painter and set it up as a fill color. If you have any baking color errors, I recommend going into Photoshop to use content aware fill or general painting to get rid of issues, and then reimporting the map back into painter. As Painter does not nearly have tools capable of easily adjusting/getting rid of blemishes as Photoshop does. One cool trick I learnt in regard to getting more surface detail/extra painted height information to show up in curvature, AO, and other helpful maps in baking (without putting it on the high poly model itself) is to export the final normal map out. Then import the normal back in (I recommend saving a backup copy of the project as this will affect any existing masks in effect), place the final normal in the Texture Set Settings panel for normal, go into Bake Mesh Maps, untick the normal baking and hit bake as to generate the other maps using the imported map. Now you can use the new curvature, AO, and other maps to further paint in roughness detail and other cool effects to make the photoscan matchup closer with PBR. Depending on the complexity of the photoscan alongside the quality of the scan you may be polishing and fixing a lot of issues. I ended up having a lot of seams, harsh lighting cracks on my diffuse maps from baking multiple meshes and misaligned text/wonky normal that led me to have to spend a few days on this step alone. However, be sure all and any time spent polishing is worth it as the photoscans can only go so far.

With a final result export as .TGA with your base color, normal and a packed channel map containing extra data of Ambient Occlusion, Roughness and Metalness. Targas is a fantastic file that lets you also keep an alpha channel per image that is useful for adding opacity/height maps without accosting another sheet. Now for the final step of setting up the photoscans in Unreal Engine 5!

6) Presenting Assets in Unreal Engine 5

With Unreal Engines 5 fantastic Lumen renderer I opted to ensure all raytracing and shadow map options were enabled whilst disabling static lighting. Considering I wanted to showcase the assets in a diorama you may or may not suffer performance hits with complex scenes by removing static lighting altogether as these forces all the lights to be real-time all the time. However, with Lumens capabilities I’d say it’s worthwhile and makes for easier adjustments. I used a mega scanned shelf to setup my Gameboys on (from Quixel Megascans), and began framing as soon as I imported my meshes in. Setting up a cine camera with a 2.5 sensor aspect ratio, 3 by 3 grid for framing the props dynamically in a three-point lighting setup. I find that having the grid helps you think about composition and eye direction from the get-go as you then begin to light the scene. Considering I wanted to showcase the variety of Gameboys in different angles I carefully added clutter to one corner to drive the focal point. Varying the sizes of the Gameboys and general height differences can also make for a more interesting composition. For post processing I also recommend setting the following values: Slope to 0,6, Toe to 0.5 and Shoulder to 0.25. I’ve found these settings to wash out Unreal Engines highly saturated color tone mapper to make for a bit more realistic result, be sure to adjust accordingly and with more fine tuning in the highlights, shadows, and global settings here too. Additionally, if you want crisper edges I recommend opening up the console with ¬ (in the top left of the keyboard) and typing in the following; r.Tonemapper.Sharpen 2. This command forces the tone mapper to sharpen the scene and gives you more crisper edges on render. Values between 1-3 are best but don’t go overboard as it can be easy to spot. However, the tone mapper will reset on startup of the scene so be sure to paste the command and number you want in the projects Default.Engine.ini found in the Config Folder. Paste the command under Renderer Settings so it looks like this:

[/Script/Engine.RendererSettings]

r.Tonemapper.Sharpen=2

This will now add the command to startup, and you can add any extra tone mapper or renderer commands here too. As for material setup, I tend to make one master material that connects texture sample parameters for my base color, normal and channel packed maps. Extra adjustment nodes such as desaturation, flatten normal or general multiplies for parameters are also plugged in here to make it easier to adjust instances on the fly. And since a lot of my Gameboys share the same textures minus the base color, I can adjust per instance much easier using a similar master material.

However, one final node I highly recommend adding is Parallax Occlusion, if you have any sort of LCD or depth effect that occurs when going to the sides of an asset. With a simple height map of white for the affected areas packed onto an alpha channel, you can setup a bit of stepping to occur when going around asset faking that detail. Similar to how an eye refracts light darker into the central iris. Parallaxing is taxing on performance so having multiple master materials is what I found working for me, with simpler adjustment ones being used for the majority of assets, with parallax/animated variants being used on single assets. This cuts down on the instructions the materials have which can save considerable performance if you have multiple draw calls. Generally, I gather a lot of lighting references and inspiration when composing and lighting the scene. Don’t forget the point of the render; in my case being to showcase the Gameboy Advance specifically and take following shots that add to uncovering new details rather than fill/waffle the renders. Video renders are also great fun to showcase the scene in motion if you have any simulation/effects but level sequencer is its own beast so I might do another post on that entirely. Generally, this is what I have stuck to and came out pretty well.

Tips and Troubleshooting)

  • Take photos with your best camera and in cloudy/shadowless conditions.
  • Try to capture all angles but move slightly between photos to keep most of the frame consistent, helping the program know where you are.
  • Do not move the object at all unless it’s a new angle for a new mesh or you are using a turntable with constant interior lighting e.g., a photography studio.
  • Use low aperture and blur the background of props to help masking when taking shots.
  • Cleanup the scan mesh always, mask and look for oddities in the generation as Sampler isn’t perfect.
  • Fill in holes in 3DSMax prior to export to Zbrush and keep things quaded (n-gons are the worst)
  • It’s easier to clean up the mesh in Zbrush as adding more geometry lets you cut away easier at higher tri counts than 3DSMax.
  • Depending on complexity you might be able to remesh the photoscan high poly into a low poly and use it as base to start conforming in 3DSMax than starting fresh. (Using Zbrush)
  • Straighten your UVS for the low poly to make for best baking/reprojecting results.
  • In Blender if the image texture being projected looks black, check all the high poly photoscan meshes for metalness/rogue PBR values in materials. Ensure they’re set to 0, you don’t want PBR to interfere with the color renderer. Also ensure only the lighting available is color and no indirect/direct lighting is projected. The final check is to ensure the order of selection is correct, select all high polys first then the low poly last and the image texture node last too before hitting bake. If it’s still black, I’ll pray for you.
  • Photoshop content aware fill is a godsend for patching up and fixing any issues in the diffuse maps of photo scanning. Be wary of seams and keep the general mesh without any shadows. You can use layers to isolate any different lighting spots and then match/replace the color to the rest of the map below if need be. Painting and overlaying text/graphics can also help get a better result if deformed/warped in the scanning process. Use the texture as a base reference where to place stuff. Do keep the original blender reprojection however in case you need to pull elements back.
  • Use the normal baking trick as mentioned in Painter if you add substantial height definition/detail + want to generate maps/masks that match it. Be warned it will affect all existing masks/generators that use curvature, world normal and more so save a copy of the project first.
  • Setup a good cine camera as you begin to light and tone down the slope, toe, and shoulder settings for more realistic results. Don’t forget to keep composition clear and use console commands to adjust sharpness/other effects on the tone mapper.
  • If you have preview lighting showing up or Lumen misbehaving it might be because static lighting is still enabled. Disable it in settings and ensure the project has Direct x 12 running with shadow maps and Lumen enabled for both lighting and reflections. You can also play around with indirect lighting, resolution, light bounces and more in Post Processing for Lumen to finetune the renders.

Final Thanks and Thoughts:

I would not have been able to have done the project if not for the following amazing people down below. Having never used Sampler nor Blender the advice and tutorials/content out by these amazing people made learning all the easier to go through. Overall taking about 2 weeks I’m quite happy with the results. But I know that I can definitely continue to improve the assets and further scan having obtained some good advice from an industry professional in regard to 2 key issues.

Inconsistent Lighting – use fishing wire to suspend the props and take shots from all angles without moving the mesh.

Loss Of Detail – use the photoscans as base mesh and make a new high poly with more defined details/exploded components that assemble for a more realistic result.

Theres still a lot I want to learn about photogrammetry but being able to successfully pull of a scan and make game ready assets has motivated me to continue to pursue learning more. And I will definitely get my hands on some fishing wire and other elements to make my scans better quality whilst waiting for more cloudy days. Keeping an eye out for industry, a new program I want to tackle next is Houdini. Simulations and scattering tools to help make environments easier to randomize/generate with populating assets are all elements Houdini is known for and would be great to pick up skill wise. Additionally, the LCD animated shader for my Pokémon game overlays using flipbook nodes  in UE5 is something I will save for another post as it’s quite a comprehensive process.

Bibliography:

3D Sampler Scanning Advice – https://www.artstation.com/gapur

Substance 3D Capture Documentation - https://substance3d.adobe.com/documentation/sadoc/3d-capture-247825363.html 

Parallax Eye Shader - https://youtu.be/GVNKpHOD5n0

Flipbook Animation - https://youtu.be/L0dT_dPPVPI

Reprojecting Textures - https://www.youtube.com/watch?v=Yx9TvvnxCAM