Epidermis

I got a tip that skins are a very important thing to render properly. THE method to solve rendering through semi-solid objects such as skin, leaves etc. is called subsurface scattering, which can be seen here http://en.wikipedia.org/wiki/Subsurface_scattering.

The only problem with the general and near-perfect method of rendering skins using subsurface scattering is that one needs to perform light-operations per each light source. This means deferred rendering is out the window, which is bad! So, there is method, called SSSS or Screen-Space Subsurface Scattering, which has seen use in engines such as in the Unreal 3 engine.

Our graphics artist, Samuel, thought it would be a very nice addition to Nebula if I were to add this algorithm in order to render skins properly. Here is the result:

facenosss

No Screen-Space Subsurface Scattering

facesss

With Screen-Space Subsurface Scattering

I accomplished this by adding a new MRT, which renders Absorption color, Scatter color and binary mask which masks out the area where the SSS should take place. We need to mask out the rest because we are working with this in screen-space, and must therefore be very careful exactly what we apply our algorithm too, so that ordinary static objects don’t get this effect.

The algorithm itself is simply a horizontal and vertical bloom, where the light is blurred instead of the color depending on the depth of nearby pixels. This, combined with a Gaussian distribution which ‘favors’ reddish hues gives the effect that skin appear more life-like since it simulates light being spread under the surface of the skin.

The exact implementation in Nebula uses two passes. One pass is the standard boring old skinning pass, which calculates lighting, albedo, emissive and specularity. Then, we render all geometry which uses the SSS process, and while doing so we render out the absorption map and scatter map. Also, we render a small data buffer, which holds our variables, such as SSS width, SSS strength, and the SSS correction factor, as well as a bit which tells us if a certain pixel should be SSS:ed or not. Then we apply our screen-space post effect which runs the actual algorithm, performing the above seen image. This means that we can perform per-object settings for the SSS, while still rendering the result in screen-space. I also fixed a minor glitch with the original implementation, which gave artifacts when the edges of the screen cut a subsurfaced area by using the mirror address mode for the sampler, which means that pixels along the border of the screen wont suffer from wrapping samples, which in turn removes the artifact.

The red rectangle shows an artifact which occurs when using a wrap address mode

The red rectangle shows an artifact which occurs when using a wrap address mode

I also applied the same technique to the HBAO shader, seeing as it previously suffered from the same problem with artifacts along the screen borders.

// Gustav

2 Comments

Leave Comment