Articles . Rendering Ice in Liquidiced
When I started writing the snow / ice shaders for liquidiced, I was a bit surprised about how few articles I could find that dealt with the convincing rendering of glistening (sparkling) ice and snow. There are quite a few articles that cover the rendering of refracting and reflecting ice blocks, apparently yielding great results, however, these typically require rendering the scene into environment maps and such, which is in no way feasible for snow that covers complexly deformed landscapes.
So I started out trying to fake some of the important characteristics of ice and snow that I came across in the articles mentioned, without the need to render the scene and/or parts of it from additional perspectives. I ended up implementing more or less three major features being direct lighting, translucent lighting and glistening, which led to satisfactory results.
Direct lighting was done by simply applying standard phong lighting with a very broad and soft specular reflection, both distorted by a subtle wavy bump map. In addition to direct lighting, rim lighting was added using
1 - |dot(n, -l)|, attenuated by a fresnel term
pow(1 - dot(n, v), 8) as well as the light/view angle
Glistening clearly makes for the most important visual feature when it comes to rendering snow, yet, I have been unable to find useful articles on how to achieve cheap glistening so far. Many sources simply suggest that you apply noise to your specularity, which may work in close-up shots, but suffers from two big problems: Firstly, glistening will only ever appear in the very tiny spots where you would usually see your un-masked specularity (about nowhere), secondly, noise tends to work extremely badly as soon as your geometry stretches from the camera up to the horizon, in a way that terrain or ground in general not uncommonly does. Close-up, the noise will form big interpolated smudges. At about 2 meters, it might look convincing, but beyond, the noise will simply dissolve due to mip-mapping, leaving un-masked specularity behind (you could disable mip-mapping, but this is likely to turn your snow into a fairly noisy nightmare).
I.3: Snow glistening in the distance
I.4: Snow / Ice glistening nearby
One important fact that I stumbled upon while looking for articles on the rendering of ice is that the visual appearance of ice is greatly affected by specular reflections resulting from cracks inside the ice. This led me to the idea of emulating such cracks by sampling normals from a random normal texture, to be used as the normals of crack surfaces. Via alteration of the texture coordinates, normals are sampled in a way similar to that of nearest-neighbor sampling, giving the cracks a certain extent. Texture coordinates are also distorted by sampling from the same random texture to make sure that the cracks are not all square.
Both of the two layers displayed in I.5 and I.6 are used to compute separate layers of specularity, which are added to the surface specularity afterwards. The first layer (I.5) gives similar results to the masked specularity described erlier, however, glistening is spread more widely, as also normals outside the range of the actual surface specularity might be bent in such a way that results in specular highlights. Besides, no specularity is removed, but instead, the reflections add up.
The second layer of specularity spreads glistening even further by making any pixel anywhere on the screen a potential candidate for specular reflection, which in a way simulates light interaction with arbitrarily oriented crystals of ice.
The second, entirely random layer thus makes sure that some glistening is always present, even when the direction of the viewer aligns with the direction of the corresponding light. There is a slight hack involved when looking into the same direction as the light, as specular highlights proved to be way too low in this case, with two layers of specularity entirely missing. Therefore, glistening brightness is doubled when the view direction aligns with the light direction, making the glistening visible again.
Due to the quite extensive crack normal cells, this method of rendering ice scales incredibly well with distance, yielding authentic glistening even about a hundred meters away.
In liquidiced, we have only one shader for both snow and ice, it is the ratio of blending between rock and ice / snow layers that slightly changes the appearance from more icy to more snowy.
Note: Images taken from our Evoke 2010 demo collaboration.