开发皮肤着色器的注意事项。 2019版本。

Abstract

object
Various considerations for the development of skin shaders for OpenGL 3.2 or higher devices released in the generation after 2019.

Subject
Using Dual Lobe Skin Shader and Blurry Normal.
Hardware Test phase by context.

What is the dual lobe specular?双镜叶高光(dual lobe specular)为最终结果提供两个个别specular lobe的粗糙度值。他们结合在一起为实现优秀的皮肤表现提供高质量的子像素的微弱频率,从而表现自然的视觉效果。<— epic games认为。

其实这部分已经从2013年开始使用并被大家所知,只是在Epik Games 2018年发表的时候更强调了而已。

Softer Lobe

Tighter Lobe

Combined Lobes

简单来说,丰富自然的皮肤表面的specular只用一个specular去控制的话有点勉强。虽然跟Clear Coat 是不同的层面,皮肤凹凸和皮脂分布、油份分布之间的差异性非常多样化,因此为了表现更写实更自然的皮肤光泽,最近几年开始使用两个specular是大趋势。根据个人喜好,Softer Lobe 可以使用一般的GGX或者与之类似的Trowbridge-Reitz;Tighter Lobe 可以使用 BackMann。如果要多考虑到优化的话,可以全部使用BackMann,同时specular模型只计算一次,在Softer Lobe 里下一个分支之前针对Branching和Narrow 的值进行mapping之后,最终合并一下即可。

让我们来修改下现有PBR shader的机制。大的有三种需要添加修改。Geometry Shadow Model 需要修改。Curvature 和Blurry Scatter需要添加,Back Scatter 也需要添加。全部都以Forward rendering 为标准进行体现。

以上示例无法获取,可以先简单看一下Mike示例。和Dual Lobe 的基本概念相似,如下:这部分是使用了两个粗糙值…

整体表面的平均粗糙度值0.95第二个粗糙度值为1.05,使用贴图采样器进行插值。这个值与另一个更精细的微粗糙度相乘,与下面外表面的Fresnel结果相加

我们来debug看下每一个表现部分。

整体来看我们分析示例,修改一个master material需要对shader编译一并处理,很烦。难道在家也得建一个完美的版本系统么;

角色上半身使用的shading模型分类好之后给大家看。
头发 皮肤 衣服

Albedo

Combined Roughness Buffer

Specular Occlusion buffer

Metallic Buffer

SS AO buffer(Can not used Mobile devices)

Opacity area buffer

Pre HDR Tone Mapping result.

Post HDR Tone Mapping result.

Return Final Image Buffer.

All combined final result with Color grading and etc…最终渲染的Bloom处理是一种不可在手机游戏中使用的[convolution]类型。

Report on full shading analysis using netease game 楚留香 modeling.

特别事项:游戏本身在帧调试的时候没有关于“Tone Mapping”的信息,我想对这部分做一个预测。实际上,在后期处理部分,是否使用“Tone Mapping”虽然无法准确把握,但在GPU调试中并未出现。网易楚留香的TA在完成这个项目后加入了腾讯王者荣耀组,现在腾讯王者荣耀(成都工作室)组也没有在后期处理中使用Tone Mapping。取而代之的是Tone Mapping公式是在角色shader内部计算和使用的方式来处理的。因为最近,王者荣耀中国国内版也正在变更为PBR,这时Tone Mapping成为了重要的一部分。由于Tone Mapping影响整体渲染并影响FX,因此推测只有角色的渲染部分和特定部分在Shader中是对ACES公式(实际上并不复杂)修改后使用的。因为如果不使用Tone Mapping的话,得到上述的肤色结果或者Specular结果会很辛苦或者不可能。

应用ARTISTIC IBL Lighting并进行修改。修改IBL环境光照值并观察变化趋势。这个阶段很重要。渲染的花是照明,因此在采用基本shader的情况下也可以凭美术的努力提高至类似品质。

楚留香选角窗口和实际游戏内角色品质偏差很严重。分析结果显示:以选角窗口可扩大显示的五官标准进行制作,睫毛的浓度(清晰度,分布密度等..)以及眉毛都是以选角窗口标准进行制作的。所以实际游戏里面脸部五官的分辨力降低,外貌的特征表现不明显。分析标准是根据2019年10月楚留香版本标准。
从网易同事那边获得的楚留香原件。

使用楚留香模型进行的阴影分析报告。-楚留香游戏引擎(弥赛亚)和Unity引擎功能的实现不同,以个人见解为基础进行分析。重点观察过的东西。为了实现柔和的阴影效果而要看的东西。

通过白模确认造型。只更改ambient浓度和阴影的浓度和人物的Portrait Lighrting角度进行测试。

Change test using white ambient lighting.

使用人为制作的白色环境光,确认曲面弯曲的变化会如何变化.

应用Roughness并继续确认整体形状。因为Highlight和Ambient效果决定了面部的立体感本身看起来如何,所以这是一个非常重要的测试阶段。

IBL 创建自己的灯光.Create your own IBL lights used by Substance Designer.

reference of SD file

HDR_Custo

m.sbs8.85KB

ARTISTIC IBL Lighting 申请.边修改IBL环境光照值,边观察变化。这个阶段很重要。渲染之花是照明,因此最好是在采用基本shader的情况下凭美术家的努力提高质量到一定程度。

该屏幕是使用Unity的PBR基本功能的结果。使用了IBL照明和一个定向照明。结果是没有应用皮肤效果。

Adding AO(AO Value : 0.75) + Skin detailed Normal ( Normal Value : 0.14 , Tile Count : X7 Y7 )

Adding Fake SSS(Temporaly test used by Thickness data with Emissive Color of SSS)

校正摄像机角度和视点,同时将钳口线校正为更细的角度。

添加了使用AO信息控制着色器中瞳孔EyeLashes中假阴影区域的功能。

Default.

Remapped color use to Channel mixer.Blue Channel mix use to increase Red 0 to 10

Shader Test result.

Reference of Specular BRDF Candidates lists below.BackMann NDF function

float BeckmannNormalDistribution(float roughness, float NdotH)
{
    float roughnessSqr = roughness * roughness;
    float NdotHSqr = NdotH*NdotH;
    return max(0.000001,(1.0 / (3.1415926535*roughnessSqr*NdotHSqr*NdotHSqr)) 
    * exp((NdotHSqr-1)/(roughnessSqr*NdotHSqr)));
}

Blend Normals ( Now Just blending with Vertex Normal )

float3 BlendNormals(float lightDiffusion, float vertexNdotL, float bumpNdotL )
{
   
   float redIntensity  = lerp(0.0f, 0.6f, lightDiffusion);
   float greenBlueIntensity = 1;
   float red = lerp(vertexNdotL, bumpNdotL, redIntensity);
   float greenBlue = lerp(vertexNdotL, bumpNdotL, greenBlueIntensity);
   greenBlue = min(red, greenBlue);
   return saturate(float3(red, greenBlue, greenBlue));
}

Simple Back Lighting

inline float3 BackLighting(float3 lightColor , float NdotL, float shadowMap, float AO, float transTex, float SssScale, float3 backScatterColor)
{   
   float backLight = lerp(NdotL , 1, transTex) - lerp(NdotL, 1.0, 0.4);
   float3 result = saturate(backLight) * lightColor * (shadowMap + AO)  * (backScatterColor * SssScale);
   return result;
   
}

Categories: tutorials

Tagged as: ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s