logo80lv
Articlesclick_arrow
Talentsclick_arrow
Events
Workshops
Aboutclick_arrow
profile_login
Log in
0
Save
Copy Link
Share

Building a Stylized Mountain Cabin with Modular Assets and Custom Shaders

Arjun Perayil explains why blockout is the most important part of production, shows how he created a complex master shader for the cabin in Unreal Engine 5, and talks about the process of hand-sculpting stylized vegetation.

Introduction

My name is Arjun Perayil, and I'm a 3D Environment Artist from India. I currently work at Art Bully Productions LLC.

I've always played a lot of video games, and the environments were always the most fascinating aspect of those for me. My journey into 3D art started around 2014 when I began modding GTA games. Tinkering with those mods sparked a deep curiosity about how 3D assets were actually made. It bridged my artistic passions with my technical interests perfectly, which is what really drew me into the mechanics of game creation and led me to open Blender for the very first time.

My formal 3D career began in 2018 when I enrolled in art college. During my time there, I read a lot of books and heavily followed the theoretical sides of both art and technology. I loved digging into the more technical workflows, while also nurturing a deep interest in traditional arts. I found myself especially drawn to paintings from the European Renaissance era and traditional Indian art – particularly the landscapes and how those worlds visually connect to stories and myths. Alongside my studies, I collaborated with a small group of game enthusiasts, helping them build 3D environments for their projects.

After honing my skills and working as a freelancer for a few years, I decided I wanted to experience studio life and transition into a more collaborative team environment, which ultimately led me to join Art Bully Productions in 2023. During my time here, I've had the amazing opportunity to contribute to major titles like Call of Duty and EA's Skate.

Getting Started with the Hearth and Hillside Project

I wanted to create a stylized environment in Unreal Engine that steered clear of the generic look often associated with the genre. In the beginning, I didn't have a solid concept; I just had a strong sense of the feeling I wanted it to evoke – a cozy, warm, and calm landscape. 

My primary inspiration came from traditional paintings rather than other games. I was deeply drawn to artworks with highly saturated, bright color values that capture a tranquil, painterly atmosphere. I wanted to see if I could translate that specific traditional, illustrative feeling into a real-time 3D space. Alongside the artistic vision, I had specific technical goals. One of the key objectives of this project was to improve my skills, pipelines, and workflows for creating foliage. I also wanted to use this scene to explore lighting and final post-processing much more deeply. 

To keep myself focused and avoid overcomplicating the process, I made a conscious effort to keep my references as simple as possible, using a curated mix of classical paintings and real-world photography. I started by concentrating entirely on finding just enough reference to lock in a strong composition.

Once that foundational layout was set, the rest of the reference gathering for mood, lighting, architectural assets, vegetation, and materials happened gradually as I progressed through the environment creation. 

Composition & Blockout

The blockout stage is arguably the most important phase in production, as it fundamentally defines the overall look and feel of the project. I usually break my blockout stage down into three distinct phases:

  1. Proxy Pass: using basic, primitive shapes to define the scale and base forms of the scene;
  2. Value Pass: adding more definition to the shapes, introducing basic lighting, and applying greyscale textures to ensure the contrast and readability are working;
  3. Color Pass: introducing the basic colors to establish the overall palette of the scene.

During this process, after a few iterations and ideation phases, I locked in a composition that relied heavily on classic framing techniques to guide the viewer's eye:

  1. Focal Point and Contrast: The house acts as the primary point of interest (POI). I deliberately placed it so its silhouette contrasts heavily against the bright sky, making it immediately readable.
  2. Leading Lines: The river acts as a dynamic, winding path that draws the viewer's gaze from the bottom foreground deep into the scene. Additionally, the slopes of the distant mountains form a subtle 'V' shape, which funnels the visual momentum right down into the central valley where the primary POI and the bridge sit.
  3. Depth and Framing: I broke the scene into distinct layers. Rocks anchor the immediate foreground corners, framing the entry into the world. The midground houses the primary action (the structures and figures), while the distant mountains push the background back to create an immense sense of depth.
  4. Asymmetrical Balance: The heavy structural weight of the house, the towering trees, and the scattered assets on the right are counterbalanced by the expansive open space, the lake, and the distant mountain peak on the left. The fence on the left side also plays a crucial role in pulling the visual weight back across the scene to keep it balanced.

Creating the Landscape & Mountains

While I used Unreal Engine's default Landscape tools to hand-sculpt the immediate foreground and the main grounds, for the distant mountains that frame the background, I relied on Gaea to procedurally generate the terrain. I exported both the meshes and the base textures directly from the software.

To ensure these realistic procedural textures matched the painterly art direction of the scene, I brought them into Substance 3D Painter. By utilizing Painter's new Stylization filter and tweaking the parameters, I was able to quickly convert the realistic terrain textures into a cohesive, stylized look before importing everything into Unreal Engine. 

For the main ground, I built a landscape material utilizing four different layers: Grass, Dirt, DirtPath, and RiverBed. I used the Landscape Layer Blend node with height blending enabled to ensure natural, organic transitions between these surfaces, allowing the dirt to break through the grass naturally based on height data.

Additionally, I set up the landscape material to output Runtime Virtual Texturing (RVT) for both color and normals. This was a crucial technical step; it allowed me to blend my scattered assets, like rocks and foliage meshes, seamlessly into the terrain. It grounds the props in the world and prevents harsh intersection lines, which is essential for maintaining that soft, cohesive painterly look.

One of the core features of this material is how it handles color variation to give the grass a painted brushstroke feel on a macro scale. On top of the base grass layer, I blended different colors using a custom variation map across large and medium tiling scales.

This variation map is a simple packed texture where the R, G, and B channels each hold different grunge patterns. Layering these scales and grunge patterns completely breaks up the tiling and gives the landscape its distinct, hand-painted look from a distance. 

Building the Cabin

Since the cabin acts as the main focal point and is primarily constructed of wood, I took a material-first approach to save time. I started by creating a foundational stylized wood material in Substance 3D Designer. From there, I developed two specific variations: a standard tileable wood texture and a dedicated trim sheet based on that same wood style.

Instead of uniquely modeling and unwrapping the entire house, I modeled a small set of foundational wooden planks and mapped their UVs directly to the wood trim sheet. Using just these few optimized planks, I constructed a library of modular wall pieces and structural elements.

I then assembled these modular prefabs to build the entire cabin. This modular trim-sheet workflow was a massive time-saver, allowing me to iterate quickly on the architecture without having to constantly jump back and forth to rebake or retexture unique assets.

For the roof, I applied a trim texture onto a simple plane and then extruded the mesh to give the shingles more depth and structural definition. The chimney and the metal sheets were built using basic geometries paired with tileable textures.

To break up the uniformity and make the roof more visually interesting, I brought the metal sheet meshes into Substance 3D Painter. I applied the base tileable metal texture I had originally created in Substance 3D Designer, and then hand-painted custom rust and water leaks over it to add specific character and weathering to the top of the cabin.

Because I didn't have a final look in mind for the cabin initially, I needed the material to be highly iterative. I built a complex master wall shader in Unreal Engine that served as a base, providing options for color tinting, macro color variations, and RVT color blending to ground the structure into the terrain. 

The shader relies heavily on vertex painting for custom blending. The base texture uses UV0. On top of this, I set up two triplanar grunge layers using the same variation map from the landscape material, with parameters to switch between the texture's channels. I used the Blue vertex color channel as a mask for these grunge layers.

Over that, I added a dirt layer utilizing the same grunge map at a different tiling scale, masked via the Red vertex channel. Finally, I added a top layer masked by the Green vertex channel to blend custom colors. I used this specific green channel mask to paint in and darken the ambient occlusion (AO) areas with a deep, stylized shade of blue, which really pushed the painterly feel of the shadows. 

To further enhance the cabin's main wood, especially since I was duplicating the same modular trim planks repeatedly, I needed a way to add uniqueness and break up the repetition. For this, I incorporated a packed utility map.

The Green channel contains an edge mask used to emphasize and highlight the edges of the wood, and the Blue channel holds the inverted ambient occlusion for a pillion effect. Applying this utility map gave the duplicated trim pieces a lot more individual character. 

Setting Up the Vegetation

A major focus of this scene was developing a cohesive, stylized look for the organic assets. I broke the vegetation workflow down into three main categories: Trees, Plants and Ivy, and Grass.

Trees

There are three distinct types of trees in the scene: the main yellow hero tree, a pine tree, and an oak tree. I started by creating the initial leaf shapes in Affinity Designer. From there, I hand-drew the leaf clusters and branches to construct a cohesive foliage texture atlas. For the trunks, I used Substance 3D Designer to create a stylized, tileable bark texture.  

Once these base textures were prepped, I brought them into SpeedTree and started generating the trees. During this phase, I focused primarily on the general silhouette of the tree rather than getting bogged down in the smaller details. Because stylized art relies so heavily on readable shapes, the overall volume is what matters most.

For the main yellow tree in particular, I spent a bit more time manually adjusting the leaf orientations and individual branch positions to ensure it had a very specific, appealing silhouette that stood out in the composition. 

I kept the overall poly count on these trees relatively low, especially on the pine trees, since I knew they would be heavily instanced across the background. For an artistic touch, I edited the normals of the tree canopies to point upwards. This is a common but crucial trick in stylized foliage to ensure the canopy catches light uniformly and looks like a soft, cohesive volume rather than individual, noisy leaves.

I also applied vertex colors to all the trees in this stage, which drives some specific shader features I'll explain a bit later. 

The leaf shader itself is relatively simple but highly effective, relying heavily on those vertex colors to drive the final look. First, I blended two different colors using the Red vertex channel, which acts as a vertical gradient from the bottom to the top of the tree.

Then, I utilized the Green vertex channel, which provides a gradient from the inner branches extending out to the tip of the canopy (excluding the trunk). To control these blends precisely, I created a custom material function called 'Gradient Adjustment,' which essentially acts like the Levels adjustment layer in Photoshop.

By blending these vertex-driven gradients together, I could introduce beautiful, localized color variations throughout the canopy, making the foliage look much more like a hand-painted illustration rather than a flat 3D mesh.

Additionally, the leaves don't use a standard normal map; instead, I used a flat normal multiplied by the Two-Sided Sign node to soften the lighting and push the stylized, illustrative feel even further. 

For the movement, the wind system is driven entirely by World Position Offset (WPO) in the material. I broke the wind down into two distinct behaviors: a 'normal wind' that flutters the individual leaves, and a 'tree sway' that moves the tree as a whole from the bottom of the trunk all the way to the top.

By utilizing the vertex colors, I was able to mask the intensity of the wind effect on the leaves, ensuring the movement feels natural and the trunk stays rooted. I actually found a fantastic YouTube tutorial by Mohammad Solei that explains this exact wind system setup perfectly. I highly recommend checking it out if you want to implement something similar.

Plants & Ivy

For the plants and ivy, I started by sculpting a foliage atlas – including the leaves, stems, and flowers – in ZBrush. During this high-poly stage, I focused purely on the basic shapes and the overall silhouette rather than micro-details.

Once sculpted, I brought the high-poly meshes into Substance 3D Designer to bake the Normal, ID, Ambient Occlusion, and Alpha maps.

I used these baked maps to establish a quick base color setup in Substance 3D Designer, and then moved over to Substance 3D Painter for further hand-detailing. To finish it off and ensure it perfectly matched the environment, I applied the same Stylization filter I used on the mountains to get that distinct, painterly feel.

After texturing, I brought the atlases into Maya to hand-assemble the individual plant models and modular ivy clusters. Once I brought them into Unreal Engine, I integrated the same World Position Offset (WPO) wind system that I used for the trees. To control it, I used the Blue vertex color channel to paint the wind intensity directly onto the meshes, painting the roots with zero movement so they stay firmly grounded, while allowing the tops to sway naturally in the breeze. 

For the ivy, however, I took an additional optimization step. I brought the individual ivy leaves into Maya and assembled them into larger ivy clusters. I then took these assembled clusters back into Substance 3D Designer to bake out a new, consolidated set of maps for the clusters themselves – Base Color, Normal, AO, and ID – and made a few final color adjustments. 

Grass

Similarly to how I approached the plants and ivy, I started by sculpting a high-poly grass blade. From this, I baked out a Color ID map (which I later converted to a grayscale map to randomize the color of individual blades inside the shader), an Alpha mask, and a root-to-tip gradient map. To keep the project optimized, I packed all of these into a single RGB texture. 

I then took these into Maya and assembled them into a few distinct grass clusters. Just like I did with the trees, I edited the normals of these grass clusters to point straight up. This is essential for grass, as it ensures the clusters catch the lighting uniformly and look like a soft, cohesive bed rather than a bunch of intersecting flat planes. I also painted the meshes with a blue vertex color to serve as a wind mask later. 

The real magic of the grass comes together in the Unreal shader. As I mentioned earlier, the grass shader pulls color data directly from the landscape's Runtime Virtual Texture (RVT), allowing the base of the clusters to blend seamlessly into the terrain below.

I combined this RVT blending with the packed greyscale map to add random color variation across the blades. Finally, I hooked that blue vertex color up to my WPO wind logic, ensuring the grass sways naturally in unison with the trees and ties the whole environment together with a consistent breeze. 

Koi Fish Animation

To bring life and subtle movement to the river, I decided to include koi fish. I started by poly-modeling a basic fish mesh in Maya and then brought it into Substance 3D Painter to texture it, ensuring the colors and patterns matched the overarching stylized aesthetic of the environment.

For the animation, I transitioned to Blender. By utilizing Blender's Damped Track constraint, I was able to quickly rig and create a smooth, natural-looking looping swimming animation, which I then baked down. Here's the tutorial I followed to set it up. 

I didn't want the fish to just swim in one place, so I built a custom Blueprint in Unreal Engine to guide their movement. Inside the Blueprint, I used the Spline component to define the exact path the fish should take and drove the mesh along that path using the Timeline node.

This setup was incredibly flexible: it allowed me to draw custom spline paths winding through the river rocks and have the animated fish naturally follow the curves, bringing a wonderful sense of life and tranquility to the water. 

Ambient FX: Butterflies, Crows, & Falling Leaves

To further push the feeling of a living, breathing world, I added several ambient effects – butterflies, a flock of crows, and falling leaves – all powered by Unreal Engine's Niagara system.

Keeping performance and optimization in mind, I avoided complex skeletal rigs for these background elements. For the butterflies, I used a simple plane mesh. The wing flapping animation is driven entirely by World Position Offset (WPO) in the shader, while the Niagara system handles their erratic flight paths and spawning logic.

The distant crows utilize a slightly more advanced setup but follow the exact same core philosophy: relying on a WPO shader for the wing movement to keep the overhead low, while Niagara drives their movement across the sky.

Crafting the Props

For the majority of the scattered props in the scene, I stuck to a generic, traditional pipeline. The main exceptions to this traditional unique-texturing pipeline were the rocks and the wooden bridge. Because the bridge is a larger structural element, I approached it differently.

I started by sculpting a dedicated, modular 'Bridge Kit' in ZBrush to get all the stylized wood grain and edge wear looking just right.

I then brought those high-poly sculpts into Maya to retopologize the kit into game-ready low-poly meshes and lay out the UVs. However, instead of taking these meshes into Substance 3D Painter to uniquely texture them, I went for a more optimized, shader-driven approach in Unreal Engine.

From the high-poly sculpts, I baked down the Normal maps and created a custom packed utility mask (an RGB map packing the Ambient Occlusion, Curvature, and a Position gradient). In Unreal Engine, I set up a material that combined these baked normals and the utility mask with a tiling stylized wood texture.

By using the Curvature and AO channels from the mask, I could highlight the sculpted edges and darken the crevices dynamically in the engine, while the tileable wood texture ensured the bridge maintained a crisp, high texel density up close. 

For the rocks, I utilized a similar shader-driven pipeline as the bridge. I sculpted them in ZBrush, retopologized and unwrapped them in Maya, and brought them into Unreal Engine. However, instead of using a standard tileable rock texture, I used the macro variation map (T_Variation_Map) that I had previously created for the landscape.

I blended this variation map directly with the baked normals and the custom utility mask. I also made one key adjustment to the mask for the rocks: while exporting it, I swapped out the position gradient channel and replaced it with a processed inverted AO map. This acted as a custom grunge mask within the shader, allowing me to dynamically blend stylized details across the rock surfaces without losing resolution and keeping them perfectly tied to the surrounding environment.

For the rest of the props, I modeled the base meshes in Maya and then brought them into ZBrush to sculpt the high-poly details. From there, I baked the necessary maps using Marmoset Toolbag.

After baking, I took the props to Substance 3D Painter for texturing. Just like with the foliage and mountains, I utilized the Stylization filter in Painter to give all these smaller assets a more painterly, stylized character that matches the rest of the environment.

Lighting & Rendering 

The scene is entirely illuminated using dynamic lighting. To establish the baseline mood and ensure the sky matched the overall aesthetic of the environment, I utilized the free StylizedWeather asset by Notokeke. The skybox from this package provided a fantastic, painterly backdrop that tied the upper third of the composition together.

While the main directional light and skylight do the heavy lifting for the global illumination, I didn't rely on them exclusively. I strategically placed several fake lights throughout the environment. These act as custom fill and bounce lights to highlight specific focal points, shape the models, and guide the viewer's eye, adding more depth and readability to the overall composition.

For the atmosphere, I started with Unreal Engine's standard Exponential Height Fog to establish the atmospheric perspective. However, to push the sense of depth further and give the air a more tangible, illustrative feel, I also created a custom fog material.

This material utilizes a panning grunge texture to simulate rolling mist. Placing this custom fog throughout the scene, especially in the background forest and mountains, adds a tremendous amount of liveliness to the environment.

Finally, for the river, I implemented the Planar Reflection Capture. Stylized water can sometimes look a bit detached from the environment, so getting crisp, accurate reflections of the cabin, bridge, and surrounding foliage was crucial for making the river feel integrated and grounded in the scene.

Cameras & Post-Processing

For the cinematic presentation, I adjusted the camera Filmback settings rather than just relying on standard focal lengths. I used a custom sensor height of 9mm and a width of 21mm across all my cameras. This created a very wide, cinematic aspect ratio that perfectly captured the sweeping vistas and the scale of the environment.

Regarding post-processing, I didn't need to do any heavy color grading. Because I had already established saturated color values in the textures and carefully placed my custom bounce lights, the scene was naturally vibrant right out of the box.

Inside the Post Process Volume, I just applied a light polish. I added a bit of sharpening to crisp up the stylized details. For the color grading, I slightly pushed the overall saturation towards green to enhance the lushness of the foliage, shifted the shadows to a cooler, bluish tint to complement the warm highlights, and gently desaturated the global values to balance the image and prevent the vibrant colors from becoming overwhelming.

To get the absolute highest quality for the final output, I rendered all the cinematic shots using Unreal Engine's Movie Render Queue (MRQ). Alongside the standard Game Overrides, I added specific console variables to maximize fidelity.

I set r.ScreenPercentage to 200.0 to heavily supersample the image. Because MRQ handles its own high-quality temporal and spatial sampling, real-time denoisers can introduce unwanted smudging. To prevent this, I explicitly disabled them by adding r.AmbientOcclusion.Denoiser, r.DiffuseIndirect.Denoiser, r.Reflections.Denoiser, and r.Shadow.Denoiser, setting all of their values to 0.

I exported everything as EXR image sequences to retain maximum color data and brought those sequences into DaVinci Resolve for a final, subtle color retouch to unify the shots and polish the project.

Since we are on the topic of rendering, I highly recommend watching tutorials from a couple of YouTube creators who have excellent learning materials on rendering and lighting in UE5: William Faucher and Karim Yasser.

Conclusion

I set a strict time limit for completing this project. The longer a personal project drags on, the higher the chance of dropping it entirely, so it was crucial to save as much time as possible. I focused on utilizing quickly iterable materials, modular meshes, and keeping the level design simple yet effective.

I completed this project over the span of around 30 days, mostly spending my weekends working on it. It was occasionally difficult to deal with the technical aspects after taking breaks between production days, but it forced me to be efficient.

Developing this efficient time management system and project organization was one of the key improvements I had while doing this project, along with elevating my overall stylization skills. Ultimately, one of the biggest challenges during the production of Hearth and Hillside was finding the right balance between high visual fidelity and smart optimization. 

For artists just starting their environment art journey, my first piece of advice is to learn to gather references for absolutely everything, not just your individual assets. You may not always find a single reference that exactly matches the picture in your mind, but find images that help you visualize your goal. Having dedicated references for your composition, rendering style, colors, and even your blockout will act as a roadmap to guide you through the entire process.

Always be mindful of the scale of your project and set firm deadlines for yourself. Using Kanban boards like Trello to monitor asset production deadlines or running time trackers like TimeCamp to log your hours can be invaluable for keeping your scope in check and ensuring you actually finish what you start.     

Once you have your references and your timeline, I recommend you spend a lot of time in the blockout phase. One of my main mottos is: "Make it exist first; you can always make it better later." This mindset really helps prevent you from getting stuck endlessly adding details too early on.

Focus on the fundamentals before getting lost in complex software tricks. A strong composition, clear value grouping, and a solid graybox blockout will do more for your scene than any high-resolution texture or post-process effect ever could. Nailing your lighting and contrast early on is half the battle.

Also, give importance to storytelling in your environments. Don't be afraid to make mistakes, and don't be afraid to make changes and experiment with things as your scene evolves. And finally, embrace reusability.

Thank you for reading, and I hope this breakdown provided some helpful insights into my workflow!

Arjun Perayil, 3D Environment Artist

Interview conducted by Kseniya Serebrennikova

Built for the Game & Digital Art Industry
Get Our Media Kit

Comments

0

arrow
Type your comment here
Leave Comment
Built for the Game & Digital Art Industry
Get Our Media Kit