Unity3d Human skin Real time rendering realistic mock man rugged rendering

Source: Internet
Author: User

First release the result picture ... Because the online model is spelled, so eyelids, cheeks, lips look like there is a rift, the solution is to add the surface subdivision and displacement map for a certain uplift, but the blogger tried the fragment shader of the surface subdivision, although the subdivision succeeded but the coloring effect becomes very strange, There is no need to subdivide the surface, if you have a fragment shader on the surface subdivision of a good way, can you please tell me

Parameter Settings 1

Parameter Settings 2

Delicate to the pores of the high light

Sub-surface scattering of the ears

Human skin rendering is a more than 10-year project, people want to do everything possible to make it believable, large 3 A-era game recently done more real, such as the son of Rome, their skin claims to have surpassed the Nvidia example


This was a multi-layered skin rendering in the 2005 SIGGRAPH, their parameters were measured in a precise medical measure, and the rendering took 5 minutes ...

Study this to find a lot of information, in the combination of prior knowledge to make a look of human skin
This example achieves the following points
1. Sub-surface scattering

2. Physics-based rendering

including specular and BRDF and so on, BRDF I used a map to adjust the curvature instead, specular in this article has a detailed explanation of the link in this

3. Normal Blur

Wait a minute.

Why is skin rendering so hard?
1. Most diffuse light comes from sub-surface scattering
2. Skin color mainly from upper epidermis
3. Pink or red is mainly the blood in the dermis
This figure is a human skin composition simulation, people have a lot of layers of epidermis, which means that in the real situation to do several refraction and reflection, it is more difficult to achieve real

Refraction and reflection of light



It's a visual indication of how the light "is going."
When light comes into contact with the skin, about 96% is scattered by the layers of the skin, and only about 4% is reflected.

Moreover specular, the human skin will produce the oil, therefore will have the reflection, but the human skin cannot reflect like the mirror, because the human skin is coarse, in this case uses the physics-based (physically based) method is best, has not understood physically Based's crossing can first understand this article and the same as above

Using the method before the best test results, that is, call of Duty 2 used in the method, while trying the next Beckmann method, but the effect is not good, Phong and other methods have not tried
Here, here's how we do it:

<span style= "FONT-SIZE:14PX;" >           /*            *this part is compute physically-based Rendering             *the method is in the PPT about "ops2"             */     & nbsp      float _sp = Pow (8192, _GL);            float D = (_ SP + 2)/(8 * PIE) * POW (dot (n2, H), _sp);            float f = _sc + (1-_ SC) *pow (2, -10 * DOT (H, lightdir));            float k = min (1, _GL + 0.545);             float v = 1/(k* dot (viewdir, h) *dot (Viewdir, h) + (1-k)); &nbs p;           float all = d*f*v;            &NBSP;FLOAT3 Refdir = Reflect (-viewdir, n2);           &NBSP;FLOAT3 ref = Texcubelod (_cubemap, Float4 (Refdir, _nmips-_gl*_nmips)) .rgb;</span>

and found that although the gloss to the maximum did not achieve the kind of effect we expected,
"Smart Fill Light"
That is, the normal way to get high light, we add a highlight map here, do not let the high light of the place (such as eyebrows) to produce high light

float specbase = max (0, Dot (n2, H)), Float spec = POW (specbase, N) * (_GL + 0.2); spec = LERP (0, 1.2, spec); FLOAT3 SPEC3 = s PEC * (tex2d (_speculartex, I.uv_maintex)-0.1); Spec3 *= luminance (diff); spec3 = saturate (SPEC3); spec3 *= _specularpower;

where the light passes, it takes a part of the color , the light from the incident to the ejection, the position and direction have changed

The number of paths of Light Walk is infinite, the light reflected back is diffuse reflection, the oil surface transparency is also different,
This creates a subsurface scattering


In GDC2007 's speech, Nvidia mentioned that the image was blur six times to achieve a softer sub-surface scattering effect.
Each time the blur is in different color channels with different range and degree of blur

Because our stickers are such "high-match"

Use in this example will be lost a little bit of the details on the map, but there is a certain degree of sub-surface scattering effect, you crossing self-choice, and do not only do Gaussian blur, so that the details will be lost more, and there is no second surface scattering feeling

In order to save money, omit the PPT in the rendering when the blur, directly on PS made 6 Gaussian blur map into material, and linear mixing


FLOAT3 C = tex2d (_maintex, I.uv_maintex) * 128;c + = tex2d (_blurtex1, I.uv_maintex) * 64;c + = tex2d (_blurtex2, I.uv_maintex * 32;c + = tex2d (_blurtex3, I.uv_maintex) * 16;c + = tex2d (_blurtex4, I.uv_maintex) * 8;c + = tex2d (_blurtex5, I.uv_MainTex ) * 4;c + = tex2d (_blurtex6, I.uv_maintex) * 2;c/= 256;




We also play an important role in the marginal light rim and BRDF,
The most obvious advantage of using the BRDF is that the BRDF map indirectly controls the color of the shading line, which simulates the reflection and refraction of light to the skin at the junction of Light and shadow by curvature control, if all black means that light is just ordinary diffuse reflection.

and gives the skin a second surface scattering texture.

/**this part was to add the sss*used front rim,back rim and brdf*/float3 rim = (1-dot (Viewdir, n2)) *_rimpower * _rimcolor *tex2d (_rimtex, I.uv_maintex); FLOAT3 Frontrim = (dot (viewdir, n2)) *_frontrimpower * _frontrimcolor *tex2d (_FrontRimTex , I.uv_maintex); FLOAT3 sss = (1-dot (Viewdir, N2))/* _ssspower;sss = Lerp (tex2d (_sssfronttex, I.uv_maintex), tex2d (_ Sssbacktex, I.uv_maintex), SSS *) *sss;fixed atten = Light_attenuation (i); float curvature = Length (Fwidth (Mul (_ Object2world, Float4 (Normalize (I.normal), 0)))/length (Fwidth (i.worldpos)) * _curvescale;  FLOAT3 BRDF = tex2d (_brdftex, Float2 ((Dot (normalize (i.normal), Lightdir) * 0.5 + 0.5) * atten, curvature)). RGB;



For rim, the addition of the forward rim and the back rim was essentially rim, and the latter used a white picture to create a feeling of jade (well, more like Yokan), with the front rim using a red picture, equivalent to adding light scattering from the blood layer, giving the person's face a real color.



This is the result of the subsurface scattering:

Light in the mouth.


like the effect of putting a finger or ear in front of a flashlight? That's the second surface scattering.
A intense strips map is required to blend the original color by finding the distance between the current point and the point light source in the case of a point light, the closer the brighter

About Normals,
With a new blend, so that more normal detail can be maintained,
Here is a brief explanation of the normal mix,

FLOAT3 N1 = tex2d (texbase,   UV). XYZ*2-1;FLOAT3 N2 = tex2d (Texdetail, UV). xyz*2-1;float3 R  = Normalize (n1 + N2); return r*0.5 + 0.5;


You may have used this way to mix two normal maps, this linear way to compromise the two map, get the details of the weight is average, the effect is not good, get the result


Improved a bit and turned into a blanket mix

FLOAT3 N1 = tex2d (texbase,   UV). XYZ;FLOAT3 N2 = tex2d (Texdetail, UV). XYZ;FLOAT3 R  = N1 < 0.5? 2*n1*n2:1-( 1-N1) * (1-N2); r = Normalize (r*2-1); return r*0.5 + 0.5;

is normal 1 of the normal relatively deep place, more weight, relatively shallow place is properly covered by the normal 2, but this effect is not enough real


In GDC2012 's mastering DX11 with Unity, an official approach is described as follows:

float3x3 nbasis = float3x3 (    float3 (n1.z, N1.y,-n1.x),//rotate float3 around the y-axis +90 degrees (n1.x, N1.z,-N1.Y),//rotate float3 around X-axis-90 degrees (n1 . x, N1.y, n1.z)); n = Normalize (N2.x*nbasis[0] + n2.y*nbasis[1] + n2.z*nbasis[2]);

Get the result is this, is not much better?


The level of detail of both sides has been improved a lot,

They used a basis to transform the second normal. See this article specifically-links


Using a function defined in the Autolight.cginc light_attenuation to find the attenuation of the light atten,atten is fixed in the directional lights is 1, in the point light source has the attenuation effect, because directional Light does not have a positional difference in unity and is the same everywhere.

Fixed atten = light_attenuation (i);



For details, such as pores, in this case the map and the normal map are very detailed, has included pores and skin texture, if the texture is low precision and want high details, you can paste the details





All variables can be set:




All code is shared to GitHub link
----by wolf96

Unity3d Human skin Real time rendering realistic mock man rugged rendering

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.