Journey Inspired Sand Rendering

For our group project Atl and Ollin, one of the most significant environmental elements are the sandy hills in which the game takes place. As such, it is crucial that this particular feature be artistically represented in a way that makes the player feel as though they are traversing through an actual dessert. The creators of Journey also had a similar goal in mind as pictured below, to produce a non-realistic yet believable representation of sand. I say non-realistic because when looking at sand in real life, our eyes are able to pick out much finer details than what is representable on a computer screen. This means that what looks good on screen is not necessarily the same as what we perceive through our eyes, even when viewing a photograph.




Journey developers thatgamescompany, published a set of slides available here on the rendering techniques used to achieve their depiction of believable sand. While they did include their various algorithms, which were often simple hacks that just happened to look good. I decided to take their published material as inspiration rather than attempting to implement what they had directly. This approach allowed me to simplify and be more flexible in the way that I achieved my desired outcome while also serving as an invaluable learning experience. My sand rendering is completely shader based, I'd also like to note that the textures used below are somewhat rudimentary and only depict what I currently have set as the default configuration.




The foundation of the sand shader itself is nothing more than a base color, texture and normal map using a standard Lambert lighting equation. What I wanted to reproduce was the way that sand reflects light from the sun, again not in a realistic fashion but in a manner than looks good on screen. The first trick unrelated to the matter of reflection but rather to achieve the graininess look of sand as also used in Journey, is to disable mip mapping on all textures other than the normal map. While this would normally produce undesired artifacts, it really does look quite good when the texture happens to be sand.




On to the reflection, there are three primary properties I have exposed that control the way sunlight bounces off the sand. Graininess, shininess and reflectance. After the initial Lambert equation is computed, the light direction is reflected off the normal as per the normal map, possessing the sand dunes that can be seen above. From here, a specular component is calculated by determining the absolute dot product of the reflected light direction and the view direction. This component is then raised to the power of the shininess property.

// Calculate lighting from angle between normal and light direction
half NdotL = saturate(dot(s.Normal, lightDir));

// Calculate reflected light direction from light direction and normal
lightDir = reflect(lightDir, s.Normal);

// Calculate specular lighting from absolute angle between reflected light direction and view direction
half specular = saturate(abs(dot(lightDir, viewDir)));


From here a detail component is also computed based on a grain texture, with the Z value of the view direction and X value of the normal used as UV coordinates respectively. This is nothing more than a hack that I found happened looked good after numerous instances of trial and error. The value of this component is then multiplied by the reflectance property and the result floored. By multiplying the specular and detail components together and adding these to the result of the Lambert equation, the effect as seen above can be achieved.

// New detail based on detail texture and graininess
half detail = tex2D(_Grain, half2(fmod(viewDir.z * _Graininess, 1.0), fmod(s.Normal.x * _Graininess, 1.0)));

// New specular based on shininess and detail
specular = pow(specular, _Shininess) * floor(detail * _Reflectance);

half4 c;
c.rgb = s.Albedo * _LightColor0.rgb  * (atten * 2) * (NdotL + specular);
c.a = s.Alpha;
return c;


I have uploaded the complete source code of this surface shader for Unity 4/5 here.

Comments

Popular Posts