Recreating snow with a shader

4. The looks

To make snow look better, we divided it into a couple of layers. We have the top snow layer, The edges and the bottom ground layer.

4.1 Snow

To make the snow look better, a combination of normal maps where used. We use one main normal map to give the snow a feeling like its not fresh snow but snow that has interacted objects before. Then we added another detailed normal map to give snow the roughness it normally has.

Since snow is normally just white, a texture will not be needed. Since we are not using a texture, we can just a single color.

To combine the 2 normal maps we first unpack both normals with the UnpackNormal function and then we blend the 2 together with the BlendNormals function. This results in a surface using both normals.

A layer of small tessellation with a noise texture was added to improve the roughness of the snow. I made a bit that applies the displacement according to the plane normals and the normals of the snow.

// This is only applied when the ground is not raised and the surface is above a centain limit
float displacementIntensity = (1 - depthCoordinate.r); // less intense when the surface is lower
float3 normals = UnpackNormal( tex2D(_SnowNormalMap, v.texcoord.xy, 0, 0) );
v.vertex.xyz += displacementIntensity
    * (v.normal * normals * tex2Dlod(_snowDisp, float4(v.texcoord.xy,0,0)).r * _snowDispStrength);

4.2 Ground

The ground uses an ice texture combined with an ice normal. This is the only part that uses an albedo texture instead of a plain color. To make sure the snow blends well into the ground, a larp is applied to the albedo and the normal. The snow normal is the same as in 4.1 Snow. And the dirt normal and albedo can be seen above.

A value called _textureDepthOffset was made to set a certain threshold at which the snow needs to start blending.

The result

4.3 The edges

For the middle part we had to blend the snow values from 4.1 Snow with a new normal map for the edges. We also blend the normal map of the edges with the detailed snow map to make sure that the edges also have the rough snow feeling.

The edges use the same normal map as the snow itself but with a lower level of tilling to make it look rougher

// When the blue value is higher dan 0
float3 snowNormal = BlendNormals(normals, detailedNormals); // blend the normal snow normals

float3 edgeNormals = UnpackNormal( tex2D(_edgesNormalMap, IN.uv_edgesNormalMap) );
edgeNormals = BlendNormals(detailedNormals, edgeNormals); // blend the rough snow with a normal for the edge

// lerp and make the edge appear at a certain point
o.Normal = normalize(lerp(snowNormal, edgeNormals, textureCoor.b + _edgeThreshold)); 

Related Posts