Unified shader works. Organization / Netease Pangu Studio Technical Art Team Unit.Author / JP.LeeDirect Contact / hzlizhengbiao@corp.netease.com Overview.Milestone
TASK 任务Achievement goal 成就目标1 Month2 Month3 Month
Shader Layout 着色器布局 Ground , Building , Skin , etc… “尽可能整合各种目的的Shader。把Shader编译容量降为最低。Ground , Building , Skin , etc…” Ground , Building,Skin shaderGlobal Foliage ,Cloth with armor
本文档是关于所有角色和场景中使用的Shader的说明。
还包含对各个Shader光照模型概要和Unity PBR Shader的基本设计的解释。角色根据LOD的不同,单独设置了材质球和Shader,场景大的分为两类,分类如下: 最重要的核心就是分析完个别Shader的性能之后,该怎么定义使用到个别的场景?我们基于大O符号(大致表现出函数上限)技法,可以达成大致的性能测定。虽然,稍微有点抽象,我们把我们大致所知的运行时间定义为被填充的水,我们就需要预测水是否能充满100升的水桶。因为是以大O符号的概念来构成Shader大致的性能的,性能测定的结果无法直接定义是否超出函数上限。结论就是把函数上限设置为120,测定第一版完成的Shader,并记录。等场景制作完成,除了Shader之外,完成第一轮优化之后,把函数上限设置为100以下,对第一版应用进去的Shader再进行一次过滤(删除不需要的功能),对于剩下的Shader我们要准备优化方案。因为函数上限要定义起来很难,把能预测到的函数上限定为90,并进行最终的优化。

场景Shader
1. 地表Shader。
2. 物件Shader。
地表Shader是Ground Shader,物件Shader是Prop Shader。大的部分为两个,按照使用目的,还做了细分。
这边最重要的就是根据使用环境,一定要选用合适得Shader。(写Shader的人需要理解美术的使用需求,反之,美术需要把使用目的告诉写Shader的那位。)
基本概要参考此文档就好。
Prop Shaders.
目录区分:
Shader分为动态物件和静态物件。
理由就是Unity内置Shader的特性,MobileBlinnPhong完全不支持光照贴图效果,性能层面使用了很简单的光照公式,合适用于手游开发。
但是,完全不支持Unity的新功能。(如高光lightmap,Baked GI等等。。。)
理解构成Shader的大概念是很重要的。
1. 根据物件在游戏中的重要程度,稍微使用了不同的光照模型。
2. 原来是按照Uber Shader形态来开发的,但是要频繁确认美术是否有设置错误,选项是否有选错,所以,按照功能别,给Shader做了分类。
Dynamic Shader Group.(动态Shader组)

PropSimpleBumpedSpecular : Custom Blinn-Phong based
PropSimpleBumpedSpecular(ReflectionCube) : Custom Blinn-Phong based
1. 使用传统简单的光照计算公式。
2. 简化了Unity内置的Blinn-Phong。
3. 可以用于很小的物件,玩家获得的道具,破碎的物件等。
4. 用于陷阱等能给玩家造成伤害的物件。
5. 不支持动态批处理。(Shader运算超出了动态批处理的规则。)
6. 动态物件因为有很多效果的功能,所以分离了基本Shader。例如:自发光效果,或者未来加入动态物件的一些效果。
Static Group.
PropSimple : Lambert based
PropSimple(ReflectionCube) : Lambert based

1. 使用很传统简单的光照公式。
2. 无法表现出镜面反射。
3. NormalMap表现无法做。
4. 推荐使用 : 可以部分用于LOD 1和不重要的物件中。
– 但是,需要美术自己判断,用于即使没有NormalMap也可以充分表现出立体感的物件。
PropSimpleSpecular : Blinn Phong based
PropSimpleSpecular(ReflectionCube) : Blinn Phong based

1. 使用Unity内置Blinn-Phong光照模型。
2. 虽然,能表现出简单的镜面反射,但是无法表现NormalMap。
3. 推荐使用 : 可以部分用于LOD 1和不重要的物件中。
– 但是,需要美术自己判断,用于即使没有NormalMap也可以充分表现出立体感的物件。
5. 提示.
– 2011年前后在手机环境上使用NormalMap比现在来说要恶略得很多,提前把光照信息烘培到Albedo上是一种比较流行的方式。(一些特殊的游戏类型除外,如:无尽之剑)

PropSimpleBumped : Lambert based
PropSimpleBumped(ReflectionCube) : Lambert based

1. 使用传统简单的光照公式。
2. 无法表现镜面反射。
3. 用CubeMap来模拟镜面反射。
4. 推荐使用:几户没有镜面反射的自然物件,未经雕磨的石头,用木头做的物件等。用CubeMap可以同时表现物件铁制品部分得表现。
PropSimpleBumpedSpecular :: Phong based
PropSimpleBumpedSpecular(ReflectionCube) :: Phong based
PropSimpleBumpedSpecular :: Phong based
PropSimpleBumpedSpecular(ReflectionCube) :: Phong based

1. 使用传统简单的光照公式。
2. 比BlinnPhong效率要好。大部分的精度是half,或者以下。以GLSL精度来看就是mediump,或者以下。
– 众所周知,在opengl es中,half和fixed没有大的差异。
3. 推荐·使用:用于一般的物件。
– 其它Shader和其它特性,达成了Specular参数和CubeMap间的直接关系。
4. Shader目录:
Tianyu Shaders/Scene/Prop/Static/PropBumpedSpecular
Tianyu Shaders/Scene/Prop/Static/PropBumpedSpecular(ReflectionCube)
PropBumpedSpecular : BlinnPhong based
PropBumpedSpecular(ReflectionCube) : BlinnPhong based

PropBumpedSpecular(Reflection Probe) : BlinnPhong based


1. 使用Unity内置Blinn Phong。
2. 和PropSimpleBumpedSpecular几乎类似,美术根据视觉效果评测是否使用。
3. 因为用于静态物件,所以不受LightProbe影响。
4. 特性上,还有一个使用ReflectionProbe进行发射处理的Shader。美术判断,在无法使用CubeMap的地方可以使用它。
CubeMap的一般设置:
ttps://en.wikipedia.org/wiki/Cube_mapping
反射贴图运算,在手游环境中考虑到性能是不太推荐的。
但是,近几年,带宽使低分辨率的 CubeMap程度使用起来变容易了。
实际,根据带宽,对于测定像素Shading还是有大的差异的。 (结果当然是这样的。)
1. 性能改善对策
– 传递CubeMap因子的时候,不个别设置Shader,用SetGlobalTexture函数来实现场景manager,这样来管理的话,对性能测定会有帮助的。
https://docs.unity3d.com/ScriptReference/Shader.SetGlobalTexture.html
– Paraboloid mapping技法虽然能看到更快的运行技法,但是不是Unity内置的。
– 在View space中,使用了用旋转矩阵来实现的简单的反射mapping投影的Matcap reflection技法。
– 理论上要快3倍以上。
– 适合低配机型,关键取决于美术对物理的认可程度。
– 完全是反射模型的情况,视觉对于方向可能觉得有突兀。反之,粗糙反射模型的情况,效率还是很高的。
2. 设置

PropPBRSimple shader

1. 这个Shader稍微修改了Unity的基本PBR Shader模型。
2. 比Standard shader稍微效率好点。使用 halfview 。 (站在开发者立场上来看,能感受到高光方向差异,但是在玩家立场上很难区分出来。)
3. 强制使用brdf2 와 brdf3 。
这个用LOD来分类。
LOD 0使用brdf2,LOD 1使用brdf3 。
LOD 0为了表现出更加精巧的表现,使用paramtex(质感表现控制用),LOD1使用常量(Constant value),虽然LOD 1使用mipmap,即使已经比LOD 0处理得要快了,但是为了能更快处理,请使用0至1的常数。
美术自己判断,质感表现跟距离无关,对于那些要保留质感的重要事物,不设置LOD,或者即使设置Mesh LOD,在Mesh LOD各物件上设置同样的LOD 0 Shader就可以了。
Unity PBR BRDF的基础知识。
所谓BRDF?

05_Reflectance_Handout.pdf에 액세스하려면 클릭하세요.
双向反射率分布函数 ( Bidirection reflection distribution function )
简单的说,就是关于 ωi (光入射方向向量的逆向量),作为入射光的能量,辐射照度(irradiance)和ωr(View vector)对反射光能量的辐射率的影响的函数。
https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function
PBR定义BRDF,通过Shader实现来获取真实的基于物理的正确的光的反射。还有BRDF就是我们昨天所知道的 Lambertian reflectance model和Blinn Phong reflectance model的一般化函数。
BRDF满足两大物理法则。
1. 能量守恒 : 入射光等于反射光。
2. 相互作用 : 入射和反射可以互换。 ( Helmholtz reciprocity )
Unity提供三种BRDF计算式。
用UNITY_BRDF_PBS来定义,总共分为三个运算式。
1. BRDF1_Unity_PBS : Disney的Torrance-Sparrow反射模型。
2. BRDF2_Unity_PBS : 简化的Cook-Torrance反射模型。主要用于有代表性的游戏杀戮地带和UE4引擎中。
http://ruh.li/GraphicsCookTorrance.html
3. BRDF3_Unity_PBS : 参考正规化 Blinn-Phong 反射浓度函数(reflection density function,RDF)和预计算结果贴图(Lookup texture)。
我们使用它的时候,要按照我们游戏的性能和效果来修改定义。
参考如下:
在PanguPBSLighting.cginc中定义了。

因为是如上定义的,我们写Shader的时候,根据把Shader model定义为几,可以使用BRDF模型
但是,因为我们是手游,原则上是不使用 BRDF1_Unity_PBS的。
使用方式如下:

#pragma target 3.0 ,根据 SHADER_TARGET<31,使用BRDF3_Unity_PBS。
#pragma target 3.5 ,根据SHADER_TARGET>34,使用BRDF2_Unity_PBS。
使用如上定义,把场景中使用的PBR的运算精度分了类,进行了LOD处理和优化。

在PC画面上比较。
在手机实际画面上,LOD1的Specular要更亮点。
(根据画面大小和内部运算精度,高光一般都要比PC画面来得亮,其它Shader也是同样,特别是,不进行 MSAA等抗锯齿处理的时候,更加明显。)

导体和非导体表现测试。
Substance WorkFlow for Bumped Specular Shader.
在Substace Painter里面,大部分都是基于PBR来制作的,使用Bumped Specular Shader,要完美得再现PBR感觉是不可能的。
为啥,因为在PBR Shader中,使用了能表现出导体特性的光照模型,但是,Bumped Specular shader只是用了一般的立体表现光照公式。不管怎样,还是要尽可能找到一个能认可的程度。
首先,Substace painter的贴图导出这一过程很重要。
请看下图:

虽然,还不是很完善,先按照上面的设置来吧。
重申一遍,像黄金这样的特殊物质表现,用PBR可以达到很好的结果,用Blinn-Phong是不可能的。
所以,要适当的使用Diffuse Color和Specular Color 来增加导体特性,即最终在材质球设置中去收尾。
Specular 和 Glossiness 部分是很重要的,建议美术可以通过几种方式来树立内部基准。
存在可以原封不动使用PBR texture导出值的情况。
Fast viewspace(Camera Space) dependency
快速查看空间(相机空间)依赖着色器。
上述Shading是基于Lambert光照模型,简略构成了 Fast viewspace(Camera Space) dependency。

2005年应用于 ZBrush的光照模型。
2011年开始用于手游环境,JP加以扩展的Shader model被Netmarble和很多韩国手游公司使用。

预先生成Parabolide reflection map,(1998) View Space坐标系开始计算反射模型的方式。


1. 优点是相比快速渲染处理,能够模拟受很多灯光处理。
2. 缺点是灯光效果是重属于摄像机,即视图的,阴影是不随画面而选旋转的。即,缺点就是无法控制现实的灯光的方向。
虽然是弥补这一点的渲染技法 Dual Parabolic,但是在速度层面比Sphrer Cube Map略快。-有必要测试一下,Dual Parabolic,两张截取的图片接缝部分不能完全缝合,或者因为看起来有缝隙,所以需要在Shader里面再进行处理,美术控制起来确实有不便。
https://www.leegoonz.com/single-post/2013/10/31/HOW-TO-MAKE-PARABOLIC-AMBIENT-TEXTURE-SPHERE-MESH
虽然,PC可以实时截取做弥补处理,但是在手游环境中运算还是有负担的。
3. 如上情况,光照计算以Lambert方式处理,完全可以从光照计算中去除。
4. 完全从光照计算中去除的情况,无法应用光照探针和光照贴图。
如果要应用光照探针和光照贴图的话,可以直接移植Unity内部代码。
LightProbe可以直接用下面的代码来访问。
Inline DecordLightProbe(float3 NormalDir)
{
return ShadeSH9(float4(NormalDir,1))
}
以此为基础,可以用多种方式来扩展Shader。
Lambert光照模型已经连入光照探针,包括光照贴图。
如果希望在反射探针里面获取到环境反射部分,可以添加代码来获取。
如果需要直接连接ReflectionProbe信息的话,需要如下代码。
Inline DecodeReflectionProbe(float3 viewReflection , float mipmap)
{
float4 skydata = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, viewReflection, mipmap);
return DecodeHDR (skydata , unity_SpecCube0_HDR);
}
但是,如果这样连接所有Unity的GI功能的话, Lambert光照模型相比于BlinnPhong,高光部分计算是有优势的。
以上Shader的缺点是无法表现出Lambert光照模型高光,可以在viewspace(Camera Space) dependency Lookup texture中表现出类似效果。


如上图所示,使用提前保存的高光,在Lambert光照模型中表现出了高光和略微的反射。
为了再加强现代的感觉,可以添加 ClearCoat效果。
ClearCoat就是在陶瓷表面涂层,或者给汽车抛光,能表现出这种感觉,光泽和切线法线不会发生反应,值只需反应于Albedo上就能表现出类似的感觉。
简单增加下Fresnel效果。

制作了如上所示贴图。
白色部分是根据菲涅耳效果变亮的部分。

简单的Shader构成树。
简单的不需要在Shader里面增加复杂的计算式,就增加了菲涅耳效果。
和Light Direction并无计算,可以按照美术的意图制作菲涅耳效果。

如上所示制作Fresnel Lut。

Creation of the Advanced Light Lookup texture
Using Octane Render.

Those result from as adjusted some node graph at above image
I had wonder about comparing direction light map mode between direction specular light map mode.

Directional Specular Light map mode.

