Setting Up a Detailed Snow Shader in Unreal Engine 5
Daniil Spivak talked about the snow shader project, explained how he made the snow look soft and more translucent around the edges using the Fresnel node, and showed how he achieved the sparkling effect.
Introduction
Hi, my name is Daniil Spivak, and I've been working in the game industry for about 15 years. I currently focus on technical art, though throughout my career I've also worked as a character artist and outsourcing manager, contributing to both mobile and AAA titles such as DOOM, Quake, and Borderlands.
I started my journey in 2012 at Sperasoft, where I worked on Star Wars: The Old Republic, Dragon Age: Inquisition, and Mass Effect: Andromeda. Back then, learning relied heavily on forums like Polycount and YouTube tutorials, since structured education in game art was rare. And CGhub (it was alive back then). Working on real production assets became the best way to grow.
Over time, my curiosity led me beyond modeling into animation, rigging, and eventually Unreal Engine, where I began experimenting with visual scripting and building small prototypes. That path naturally evolved into technical art, which I now study in depth, exploring Python and Houdini.
Right now, I'm working on a portfolio piece that highlights my skills as a Technical Artist. One of the key areas I'm focusing on is material creation. To showcase different techniques, I decided to build a few materials with distinct properties, each demonstrating a specific approach or technology.
Today, I'd like to talk about the creation of a snow material. It's based on the same technique I used for my glitter shader, which I'll cover in more detail later. Snow in games is a complex and multifaceted topic. Different projects handle it in very different ways. Sometimes, it's just a procedural layer within a material, where you can define where snow appears.
In other cases, teams use hero assets that are pre-modeled and textured with snow. Some advanced systems even rely on local render targets, Displacement Maps, and tessellation to create real-time deformations, like footprints that sink into the snow as a character walks.
Snow Project
First, I collected visual references to define the look I wanted to achieve. There are plenty of tutorials online on how to create snow for offline rendering, but my goal was to make it look convincing in real time to push the visual quality within the limits of a game engine.
The work on the snow material can be roughly divided into two stages: creating the base textures in Substance 3D Designer and building the shader itself in Unreal Engine.
Let's quickly go through the Substance 3D Designer stage. I wouldn't call myself an expert in creating highly complex materials there, but in this case, the setup is quite straightforward. For our snow material, we need to generate the following maps:
- Base Color
- Normal Map
- RMAO (Roughness, Metalness, AO, Opacity)
- Height Map
For the Base Color, I used subtle gradients ranging from white to a slightly bluish tint, with just a hint of surface detail. It's important not to overdo the contrast, snow color should never be pure white, otherwise it causes harsh overexposure in lighting.
A good starting point is around RGB(200, 214, 230), which can always be adjusted later in the shader. The Roughness Map contains fine black-and-white noise made up of tiny dots and patches. This variation helps break up the surface and gives the impression of sparkling micro-reflections under light. The Normal Map and Height Map are relatively simple, just blended cloud textures that add a bit of surface variation and breakup.
As for Metalness and Opacity, I left them completely black. They're not used in this case and can be replaced with scalar values directly in Unreal Engine. I just kept them in the export because it's part of my standard preset.
I also used a couple of cloud noise textures to generate a base for global displacement, which adds a sense of unevenness and depth to the snow surface.
Unreal Engine
If you switch to a low-poly cylinder, the result immediately loses its "fluffy" look. The same goes for many displacement-heavy materials made in Substance 3D Designer, they often look great in previews, but don't always hold up in production.
In real projects, no one subdivides entire meshes just to make snow look soft. Instead, developers often use local tessellation, for example, to create footprints or deformations where characters walk through the snow. This approach allows for realistic detail only where it's needed, keeping the rest of the geometry lightweight.
If you switch to a low-poly cylinder, the result immediately loses its "fluffy" appearance. The same applies to many impressive displacement-heavy materials created in Substance 3D Designer. They often look great in previews but don't necessarily translate well into production.
In real projects, no one will subdivide regular meshes that heavily just for a snow layer. It's still snow, but it looks far less appealing and much flatter in practice.
We'll start with a standard Opaque material. For the Shading Model, I chose subsurface profile. You could also use plain subsurface, or even skip subsurface entirely and fake the soft scattering with a touch of emissive for a simpler setup. For this project, I went with a subsurface profile. It gives snow that gentle, light-through-grains look without overcomplicating the graph.
Let's set up the Base Maps for the material.
Now we can adjust the texture scale and offset.
Refining the Material
Next, we need to go through each channel in the material and start refining it. Let's begin with the Base Color. So, what can we say about the base color of snow? Well, it's white, but that's not the whole story. It's a good idea to introduce color variation through the Ambient Occlusion Map.
This way, we can make the small cavities slightly bluer, adding more depth and realism. It's also useful to include a color control block for the base color, allowing us to tint the snow toward different hues or desaturate it if needed. Using a lerp node with a scalar in the alpha input lets us control the AO intensity directly.
Next, snow viewed at a grazing angle has a noticeable Fresnel effect. We can achieve this with another lerp node driven by the Fresnel node. At this stage, we already have some visual variation from the Substance 3D Designer textures, plus several adjustable parameters that can be fine-tuned directly inside the shader.
Next is the Roughness texture. What can we say about it? Well, we already have a solid base. One interesting property of snow is that when viewed at a grazing angle, it reflects more light due to the Fresnel effect. To emphasize this, I added a Fresnel node from the diffuse setup into the roughness network.
This way, we're blending two Roughness values, which not only introduces the Fresnel behavior but also allows for finer overall Roughness control directly within the shader.
Next is opacity. In our shader, opacity controls the intensity of subsurface scattering. Here, the Fresnel effect also comes in handy, objects appear thinner along the edges, allowing more light to pass through.
By using a Fresnel node to modulate the opacity, we can make the snow look softer and more translucent around the edges, enhancing the overall sense of light diffusion. We're getting somewhere, but the snow still looks too flat and lacks those sparkling highlights. Let's fix that next.
Alright, we've added our displacement: a cloud texture as the main displacement layer and a finer noise from Substance 3D for additional detail. Let's take a look at the result:
It's already starting to look like something, but we can push it further. We can make our Normal Map more interesting by blending the main Normal Map with a Detail Normal Map.
Great, now our snow finally has volume. But we still don't have any sparkling snowflakes. Let's add a few bright points to the Emissive channel. These come from the green channel of our RMAO texture. On top of that, we can layer some noise with animated UV panning, so that the sparkles subtly shimmer over time instead of just glowing statically.
Now we've got some sparkling points, but we can make this effect much more interesting. This is where we introduce special glitter flakes that light up depending on both the viewing angle and the position of the light source in the scene.
I used the same principle for my glitter shader. I was curious how to make polarized glitter flakes that only flare up at certain angles relative to the camera. To achieve this, I created a custom glitter texture in Substance 3D, specifically designed for that effect.
Let's take a look at the glitter shader example. When I was building it, the key goal was to make the sparkle behavior controllable. You can't just add some variation to the Normal Map and shine a stronger light on the object to get proper glitter that will only give you a bumpy surface, not real, directional sparkles.
We need to manually control the glitter parameters and somehow tell the shader that each flake has its own orientation and reaches maximum brightness at a specific viewing angle. How do we do that? With the help of the additional texture I mentioned earlier.
You can think of each glitter flake as having its own tilt, encoded in the red and green channels, which is how much the flake is rotated along the X and Y axes, essentially like a Normal Map. The blue channel stores the angle at which the flake reaches its peak intensity relative to the camera.
One flake might flare up at 90 degrees to the camera, while another peaks at 10 degrees. This gives us rich variation in sparkle behavior. The alpha channel simply contains the mask of the glitter points themselves. This setup works perfectly for our snow material as well.
Conclusion
I won't go through every single node in the glitter block, but here's a quick overview. We start by sampling our glitter texture and adding a parameter to control its scale. Then we calculate the intensity mask for the flakes. All of this is multiplied by an animated panning noise to give the sparkles subtle motion.
On top of that, each flake should reach its peak brightness in the area where the most light from the sun hits the surface. For shadowed areas, we can mask them out using the Atmosphere Sun Light Vector node.
Done! I also like to add a rim-light function for presentation. I found this setup online a long time ago, and I still use it frequently in my projects.
Here we are! That's everything for now. Thank you for taking the time to read my article. I hope you found it useful.