Monday, September 21, 2015

Day 29: Skyboxes and When Regular Lighting Doesn't Cut It

Today was another thrilling day with learning Cg shaders in Unity. Going back from working with attaching cookie textures to lights and creating materials with shaders, I was pleased to see another type of projection with actual Unity projector objects, where the shader is specific to the projector, rather than the object on which it is projecting. The way this works is that the texture is still converted to a separate coordinate space (the projector coordinate space), but the projector uses additive blending to add the color of the texture to an object. On a regular square surface this produces what needs to be projected, but on something like a sphere this can lead to a very interesting look:

After working on projectors, I moved onto environmental mapping. By way of a cube map (a map of six textures shaped in a cube), one could use the reflection of the view vector and trace it to a value on the skybox. The skybox itself does not have to be rendered in the scene, but can be applied to the surface of that reflected object to make it look like a mirror. This has been applied to the ellipsoid below by reflecting a charming winter scene:

Very similar calculations can also be utilized with a built in refraction function, similarly to reflection but involves a refractive index as a parameter:

 However, the quality of the skybox is unfortunately not as good as expected, and the same sampling function used to sample the skybox texture can be applied as an actual environmental background. This is thankfully much simpler than my previous work with a skybox in DirectX, as the settings are much more automatic. Culling is still kept to culling front-facing triangles so that one can view the inside of the box as shown below:

 One of the large problems with using an actual box shape is the corners of the border, which can be averaged or employed in a different shape, such as the skysphere I created in DirectX. This can also be used as a lighting map, where the skybox can actually add and apply light with similar reflective mapping to the reflected texture above.

I also looked into more complex lighting calculations, including anisotropic specular reflection. When specular lighting is calculated, one must take into account that light does not reflect in a very specific direction, but splits into many directions. The function that determines such a reflection is the bidirectional reflectance distribution function, or the BRDF. The BRDF can come in handy for brushed surfaces like brushed aluminum, when the reflection relies on something less isotropic.

It's quite the complex equation, relying on the halfway vector (average of view and light direction), the tangent vector (referred to as a brush direction), its binormal, and roughness of those vectors. The result is not completely noticeable but improves the quality of lighting and allows for brushed surfaces to be more properly represented. This also allows further control of specular reflection as is done below:

The roughness of the tangent vector has been modified for a much broader specular reflection. The specular reflection can also be modified with a Fresnel factor for a much brighter and opaque effect, such as light silhouettes under a large backlight. This can result in incredibly bright and glaring surfaces at the edges of objects like this sphere below:

And last but not least, hemisphere lighting is another special type of lighting that varies the normal with an up vector on the sphere, where one can specify a main sky light color that fully illuminates the top of the sphere but can vary with lighting below the sphere, like the reflection of a pool of water or a dark effect like below:


There are a couple other special things we can do with lighting in shaders, and I will probably dive into those before the next prototype project comes about.

No comments:

Post a Comment