Creating Realistic Vintage Cassette Recorder with Substance 3D & UE5
Louise Wyke talked to us about the CTR-85 Recorder project, discussing modeling and texturing a realistic vintage cassette recorder with three skins using Maya, Substance 3D Painter, Marmoset Toolbag, and Unreal Engine.
Introduction
Hello, I'm Louise Wyke, a Character Artist based in Sweden. In 2020, I enrolled at The Game Assembly, a school in Malmö, Sweden, to learn game development. After graduating, I worked at Massive Entertainment, a Ubisoft studio, on titles such as Star Wars: Outlaws and The Division 2.
I started this project to keep improving my craft, and I knew I wanted to expand my portfolio with a detailed and realistic prop while improving my hard surface and texturing skills.
The CTR-85 recorder seemed like an interesting project since it had several intricate parts that fit and worked together as well as with other objects, like cassettes and batteries, which I decided to model as well.
I mainly found reference pictures of the recorder and cassette tapes on auction and second-hand sites, Reddit community pages, and collector forums for vintage devices. I also used blueprints, user manuals, and restoration videos on YouTube showing spare parts that came in handy when figuring out how to connect the pieces and if I could simplify them.
My goal with finding references was to see the recorder from all kinds of angles to understand what parts to include from the inside out, along with close-up shots of materials that showed details that could help take the final asset to the next level of realism. I also made sure to look for inspiration on how to present it at this stage.
Modeling
Workflow-wise, I decided to do all the modeling in Maya, highpoly and lowpoly, and use the Marmoset Toolbag 5's Bevel Shader so I could have floating geometry in the highpoly and still get good-looking bakes.
The video shows the high-poly mesh in Marmoset Toolbag, how to turn the bevel function on in the material and see it, as well as how you can adjust bevel size in the material:
Change the high-poly mesh's Material Surface setting to Bevel, changing rendering to Ray Tracing, and you can decide on the bevel size between two objects intersecting with a slider.
I start big and then go small. With the dimensions of the recorder in mind, I set a simple cube up and aligned the reference pictures to the image planes. I block out by cutting into the cube, carving out the sizes of things from the main block. It’s about making sure all parts are where they need to be at this stage, getting the shapes right, and fixing the topology later.
I marked out the polys representing a future extrusion or separate piece with different coloured materials early on. It showed me where the battery compartment would go, where the speaker grid fit, and what other parts needed to be carved out from the base blockout while staying flexible.
To make sure the lids fit perfectly into their sockets, I could now use the marked areas and simply extract the faces to get perfectly aligned surfaces on different parts.
The video shows how extracting selected faces separates them from a mesh and makes it easier to work on smaller pieces that have to fit together perfectly with another piece:
As the big block is separated into smaller parts, I assign them a shiny Blinn material to be able to spot bumps and any uneven surfaces more easily as I keep on refining.
When moving on to blocking out the mechanics on the inside of the device, I started by cutting out the shapes from planes, extruding the whole piece to give it thickness, only when I was sure the placements of the parts worked together.
The evolution from big to small shapes while refining the recorder and all the pieces:
The evolution from big to small shapes, focusing on the buttons of the recorder:
I worked on the recorder and the cassette simultaneously to make sure both objects fit together every step of the way. By duplicating the special and using an instance to see how the cassette looked when placed in the recorder, I could keep the mesh in the middle of the world for easier modeling and altering throughout the process.
The video shows how working with an instance makes it possible to make changes to an object that is positioned in a slot (like the cassette) while still keeping the mesh in origo and making changes easier:
For as long as I could, I worked on only half of the cassette and later mirrored it to save some time. To further accelerate the whole process, I reuse the blockout mesh from the mid-poly stage, from which both the high-poly and, later on, the low-poly are built.
The modeling of the battery was done the same way. I knew I wanted the final look to have lots of batteries spread out and decided the quickest way would be with a gravity simulation. I let a bunch of batteries drop in a smaller, contained area, shortened the simulation time, and the result was a pile of batteries looking naturally spread out.
With different materials assigned to random batteries in the heap, I exported everything together as one big mesh to get the look I wanted in the final Image.
I did the retopologizing in Maya, and instead of starting from scratch, I started from the same blockout I used for the high poly to start the low poly, focusing on where bevels were needed to catch highlights.
For the UVs, I mainly used planar UV mapping to get the pieces from each angle straight and aligned, either by selecting faces first and then using planar, or using planar first and then cutting the pieces at the corners of the mesh. I then unfolded the islands in the direction that worked best, straightening further if needed and laying them out.
The video shows how I used the planar and cylindrical functions to get the UV pieces from different angles and saved time by getting each island quite straight before cutting them into smaller pieces:
Texturing
In Marmoset Toolbag, I bake Normals, Material ID, Curvature, Ambient Occlusion, Position maps, and Thickness.
For texturing, I used Substance 3D Painter and started off by changing the tone mapping to ACES to give me a better idea of what it would look like in Unreal Engine 5. To further help with getting that idea of the final look early on, I changed the Environment Map in Substance 3D Painter to be the same HDRI map I used in Unreal Engine for the look dev scene. Neutral, natural light with an outdoor source helps a lot when making materials look right, and I recommend Poly Haven for finding a suitable map for a project.
To lay the groundwork for the texturing, I added a channel for opacity to the texture maps and started out by using the material IDs I baked in Marmoset to put down a base colour and roughness. It makes it easier to differentiate between various types of plastic and metal, sorting each type into folders to keep it tidy. After that, I kept refining and adding layers and progressing wear, dust, and scratches as I've observed on the reference pictures.
A thing I keep in mind when starting the texturing process and adding height variety to an object, like the small bumps in the plastic outer shell of the recorder, is to make sure they indicate the size of the object properly. Too small and the object will read as huge, and too big will make it read like a miniature. This can set off the entire look and needs to be addressed early on and adjusted to the texel density.
Whenever adding any stronger height through texturing, like for the text next to the audio jacks, by anchoring them, I use the decals for micro height or micro normal on generators. The anchor point is also used to add or subtract from certain layers and help control the look of dirt, dust, or grease around things with faked height in the material.
Most text and logos I made myself with Affinity Photo and placed in Substance Painter through alphas. With the help of WhatTheFont Font I could use the reference pictures to find really similar-looking fonts and type whatever texts I needed for the batteries, the cassettes, and the recorder, respectively.
After a first pass of texturing, I set up materials in Unreal Engine following a PBR workflow and set up a LookDev scene early to get an idea of how the material presents. Making plastic look like plastic can be tricky, so having a LookDev set up where the light is calibrated early helps a ton. If the asset looks good in the LookDev scene, you know that there is something wrong with the light, not the texture.
Once the recorder looks like it's placed in the real world and both shadows and light are working well, even with a basic grey material in the LookDev, you can focus on the texturing and building on that realistic look exclusively in Substance 3D Painter for quite some time.
For the battery and cassette, I followed the same idea and chose to make three skins each. To showcase them, I set up the material with a switch parameter. I then drive that switch through the recorder's blueprint construction script. That allows me to change between the recorder’s skins directly in the details outliner.
The tricky part initially was that all the parts of the cassette had different shading models with different textures, and I needed to switch between different materials depending on the selected skin. In the end, instead of switching materials and textures for each object, I separated each affected group into separate arrays so I could change the skin with far fewer function calls.
Lighting, Rendering, & Post-Production
When setting up the lighting of the CTR-85 recorder, I was quite inspired by the opening scene of Mindhunter. A simple backdrop with a similar colour to the asset helped to bring in that minimal feeling that would let the asset take center stage. To show the front and back of the recorder at the same time, I set up more of a product shoot.
I use the Atlux plug-in to get a basic scene set up with a three-point lighting for both the close-up and the wider shots. For more control of each shot, I duplicated the main scene to be able to do some adjustments to the lighting, and tailored each shot to capture cool highlights.
Due to the different presentation and shiny nature of the batteries, I went with lower-angled three-point soft box lights and an overhead lightbank.
The Atlux cameras save me a lot of time when it comes to adjusting and refining my render settings. They also come with easy-to-manage post-process settings.
I kept the settings very simple, a bit of trial and error managing the denoiser in Path Tracing and setting up a LUT for a minor Fincher-inspired look directly in Unreal Engine before I moved them to Da Vinci Resolve for further processing.
In Davinci Resolve:
I added a bit of chromatic aberration for the lens and some film grain to get a more organic and analogue look, overall, more of a movie feel to it. In general, I increased the contrast a bit more. Since the renders were mostly in a monochrome palette, I boosted some colours to make them pop, added a vignette to draw the eye a bit more on the asset, and an overall sharpening filter.
Conclusion
The whole project took me around two months and really taught me the importance of starting big and going small, especially with all the parts that had to fit together.
The challenging part was learning the technical fundamentals. There was a lot of testing, going back and forth, and getting to a place where I could understand and troubleshoot issues without relying on tutorials to explain or fix an issue.
The most enjoyable part was by far texturing and seeing the details come together, making a common object look special through the personality and history of its materials, and then showcasing it. Staying consistent with color profile management across the whole project was the biggest lesson learned for me.
Thankfully, I had an amazing mentor to guide me – Richard Trouve, Technical Consultant for Blizzard Entertainment.