Ali Mshasha talked to us about the recent Boat Diorama project, discussed the modeling process in Maya, and explained how the water shader was set up.
Hey there! Thank you for taking the time out of your day to read this article. I'm honored to share with you my work on the Boat Diorama project that I recently finished and I hope some of you from the amazing 80 Level community will find what I say helpful.
My name is Ali Mshasha and I'm a 3D Environment Artist. I live in Vancouver, BC and I’m nearing the end of my studies at the Think Tank Training Centre.
The Boat Diorama Project
I started working on this project with a set goal in mind: to improve my stylized skills as well as to develop my Unreal Engine shaders knowledge.
One of the inspirations for the project was the work of my instructor Johnny Malcolm whose art is very intricate and detailed but remains well-defined as an overall image. Another inspiration, and the artist of my chosen concept, was Mike Azevedo. His emotive characters and environments blow my mind every time I look at them. His boat illustration, nested in a collection of environment concepts, caught my eye instantly.
I began my project by blocking out the boat and everything around it in Maya. To stay true to the concept I used a free program called fSpy to figure out the focal length that I would need for the main camera in my scene by lining up perspective to the concept art.
Once I knew the focal length, it was easy to line up my Maya camera to the concept art's perspective. Once that was done, all I had to do was box model the scene to a point where all my assets had a shape that I could build on. From the start, I knew that the biggest challenge during the modeling phase was going to be the rope as well as the fishnet, while the rest of the model had fairly simple shapes. So, during the block-out phase, I created a sphere and nudged it around with Maya's sculpting tools to form the general shape of the net and created a rough shape of the rope.
After the blockout, I thought it would be best to sculpt the fish and knife in ZBrush since it's far easier to get organic shapes than doing them in Maya. I sculpted the shapes of the fish and knife using DynaMesh to get a high poly version with all the shapes and then I used the ZRemesher to clean up the high poly and create a low poly version of the sculpt. I saved the 2 versions of these assets, the low poly version to UV unwrap and use in my scene, and the high poly version to bake in Substance Painter so I can transfer the details to the low poly mesh's Normal Maps.
Once I had the assets imported back into Maya, I began creating the game mesh and the process mostly involved beveling many of the edges and refining some of the detail that wasn't present in the blockout. The net was made by turning the blob (that I previously had from the blockout) into a Live Surface which means that objects and tools will snap to it. I then used the camera that was lined up to the concept art to draw curves along the concept's net.
Once I had curves, it was only a matter of extruding tubes along them. In Maya, there are several ways of approaching this. My preferred option was to create a NURBS circle, sizing it to the desired diameter and then going to Surfaces -> Extrude Options and generating a polygonal tube along the selected curve. This method is better than for example creating a circular plane and extruding the face along the curve because the workflow would otherwise be somewhat destructive. Using a NURBS circle keeps the extruded tube live and lets you change the size of the tube by changing the size of the circle.
This method was also applied to the rest of the ropes in the scene.
The remainder of the modeling process was fairly straightforward, with the exception perhaps of the drape, which required some playing around with cloth simulation. In the end, this is how my model looked:
When it came to UV unwrapping my model, I used Maya's built-in features, which over the past few years have gotten amazing. If you don't have Maya, you can use software such as RizomUV or UVLayout and I'm sure Blender also has a great unwrapping tool.
During the process, I was faced with two options that would determine the texturing process. The first option was to treat the boat as a Hero prop asset and the second was to set it up for a more tileable texturing approach. I decided to go for the Hero approach since I knew that the final result of the project was going to be a video from the original concept's perspective and no one was going to walk through it, so the texel density didn't have to be very large. It just needed to be high enough to look good while being watched in a 4k video. I split my boat into 4 UV groups for all the different parts and assets, except for the net, rope, and eyes of the fish so that I can apply tileable textures. Below is an example of a UV group. Repeating UVs were placed in the same location on a different UV Tile to make it easier to create the mesh that I was going to use for texturing and map baking.
The rope and net were Unwrapped in this manner to accommodate a 64x64 tiling rope texture.
In the end, you need to make sure that the texel density is the same across the mesh, or else textures won't appear to have the same resolution.
If anyone is confused about texel density, I highly recommend the video by malcom341 who explains it very well.
The texturing phase was relatively straightforward. It was done using Substance Painter and Substance Designer. I began by creating a color palette of the concept, I recommend using Adobe Color to extract the colors for reference and sampling. This allowed me to have a direct comparison of values when something seemed off.
I brought my game mesh into Unreal and applied some base materials that later held the exported files from Substance, just so that I could see how my textures looked in the engine. I also changed the color LUT (Lookup Table) inside Substance Painter to ACES, which is the same LUT that Unreal uses, so that my textures look indistinguishable between the two softwares. I highly recommend this tutorial by William Faucher to understand LUT and also to learn how to change it in Painter.
To make the rope tiling texture, I created a very simple graph in Designer that uses the Tile Generator and a couple of bevels blended together to create a simple twirling shape. The eyes were also made in Designer, but it was essentially just two colors with a Gradient Radial mask blending them together.
Within Substance Painter, I baked the mesh to generate maps like Ambient Occlusion and Curvature to later use as masks while texturing.
I noticed that Unreal wasn't capturing much of the detail of my wooden textures, so I exaggerated the height, color contrast, and roughness of the grain to better capture the look. In fact, I did this to most, if not all, of my textures so that I could make everything stand out a lot more within Unreal.
For the wood, I made multiple Base materials that I created within Painter so that I could throw them into my layers and adjust accordingly. For example, I would have a wood material and then another bark material that I overlayed on top with a higher height value to push it out. This allowed me to quickly create varying types of wood that can be adjusted and edited individually.
Grain and break-up were usually made using noise or grunge as a mask over a "Fill Layer". When I needed to add specific details, I added a paint adjustment to the mask so that I could hand paint my own detail. I also made extensive use of "Anchor Points" on significant adjustments of height so that I could later apply them as "Micro Height" details, like for example, when creating the curvature highlights of my mesh. If you don't completely understand how to use Anchor Points, I highly recommend this video from FlippedNormals:
When creating stylized work, a very common practice is to highlight your edges to make them stand out and make the overall shape of your assets defined. This is done very easily in Painter by creating a "Fill Layer" and masking it with the curvature generator so that the "Fill Layer" only appears on the edges. Getting it right in terms of exactly what you want, requires playing around with the balance and contrast sliders within the generator. Once you have that layer masked, you can adjust the color to your intended style. I usually duplicate the base layer of my material and raise the value and saturation by a small amount and occasionally, if necessary, apply a slight hue shift to my curvature highlights.
To get a "brushstroke" effect on the blue roof of my boat, I created a brighter layer masked by a couple of "Crystal 2" noises on max contrast with different randomness seeds to introduce variation. I then added a paint adjustment to the mask to add some of my own strokes wherever I wanted them. Then, I multiplied them by the "Directional Noise" noise pattern to break them up.
Another texturing challenge that I came across was achieving a stylized look for metals. I began working by adjusting the values on the metallic map but it appeared too realistic for a stylized work. So, instead, I played with the light generator to create a mask that simulates directional light and allows for baking lighting into the textures. This is especially great for objects that don't move, because you can "art direct" exactly how you want the object to capture and bounce light.
Unreal Engine and Shaders
Once my textures were done and looked good in Unreal, I began working on the Water Shader. Unreal has a built-in water plugin that gives you a set of relatively easy tools to use to create unified water systems. So, if you’re looking to make bodies of water like lakes, oceans, and rivers then I highly recommend using this plugin.
Unfortunately, these water systems aren't compatible with what I was trying to achieve because they create planes of water while my diorama's water was essentially a cube with sides. That meant that I had to create a water shader more or less from scratch.
I began by creating a base material and applying an instance of that to a cube in the shape of the water
Then, I set the Material blend mode to "Translucent", turned "Two-Sided" on, and changed the translucency lighting mode to "Surface ForwardShading". It's the computationally heaviest mode for translucency but looks the best for water and glass. I then began by creating the network that displaces the mesh. Since this displacement isn't being tessellated, you will need to have enough vertices on the cube to push them out. For the Displacement, I generated a simple Perlin noise in Designer and also generated a normal for it by using the Normal Sobel node and imported them into Unreal. A good trick for making water move in place without going in a specific direction is to multiply two of the same noises that pan in opposite directions to one another. In the node graph below you can see how I approached this. The easiest way, I found, is to use the "Panner" node and have the speed set by two vector parameters so that you can control them in your material instance settings. While the noise can be multiplied (since it only has linear values of 0 to 1), the Normal Maps need to be blended a little differently. This is why I used the "BlendAngleCorrectedNormals" node, which corrects the overlaid Normal Map's directions with the map below it.
Once I had this graph put together, I plugged in the normals straight into the output node, multiplied the black and white noise by a "VertexNormalWS" and plugged it into the "WorldPositionOffset" output.
This displaced the vertices on the entire geometry, which in my case is not what I wanted because the sides of my diorama were more or less flat. So, I needed to create a mask that only allows the top part of my mesh to displace. The easiest way for me to do that was to use World Position and control the height as well as the transition of the masking so that there isn’t an abrupt and harsh mask that cuts off the small waves but instead, with a soft transition, fades them out. Below is the graph showing my approach, which I recycled from another project in which I was trying to give the appearance of liquid in a bottle without creating any extra geometry. Once the mask was created, I just used a Lerp node to mask out the sides.
This is how the displacement looked in the end.
Another challenge in the water was the opacity and refraction. One relatively complicated aspect was being able to get the "caustic" effect on the water. This was achieved by applying a custom "Histogram Select" material function (for more information, check this video). This function serves the same purpose as the "Histogram Select" node in Substance Designer which allowed me to select and contrast a specific range of a Linear value/texture. I plugged in the panning Perlin noise that I used to offset the vertices in the "HistogramSelect" node and made it so that the selected range would increase the opacity.
Lighting and Post-Processing
The lighting for my scene was relatively simple. I had a directional light with a warm color hitting the front of the boat and a Skylight to fill in the dark areas with some cooler tones. To get the caustics to reflect onto the boat. I created a spotlight with a light function material applied to it that panned a caustic texture the same way I panned the Perlin for my vertex offsetting.
In terms of post-processing, I added some very light contrast and gamma correction as well as a tiny amount of chromatic aberration – giving the scene the effect of being filmed by a camera since all cameras in real life can cause this type of light distortion.
I had several challenges throughout this project. Although none of them left me lost or stuck for too long! I believe that was due to thoroughly planning out the project beforehand. I highly recommend when starting a project, setting up a deadline and a stretch goal-type system. In my case, my main goal was to model and texture the boat and get it into Unreal within a set amount of time. After that, I wanted to finish the water shader before adding any additional features such as the smoke and animations.
While repetition can be good for refining skills, you can sometimes find yourself stuck in a loop of doing the same thing to the point where you aren't really learning anything new. I believe that every project is a good way to learn something new and an opportunity to get out of your comfort zone. But most importantly, it’s an opportunity to have fun and do what you love!
Thank you so much for featuring me on this website, and I hope you found this useful. If you have any questions whatsoever, you can message me on my ArtStation and I would be more than happy to provide more details!
You may find these articles interesting