为什么地球在两极严寒,而在赤道火热?这个问题,仿佛与着色器毫不相干,但却是理解光照模型怎样工作的基础。正如这个教程前面部分所解释的,表面着色器使用数学模型来预测光照在三角形上怎样反射。总的来说,Unity 引擎支持两种着色技术,一个是哑光着色器,一个是镜面材料着色器。前一种对于不透明表面的支持很完美,而后一种则用来模拟反射对象。这些光照模型背后的数学可能非常复杂,但是如果你想创造属于你自己的光照效果,你就得理解它们是如何工作的。直到 Unity 版本 4.x,默认的漫射光照模型都基于朗伯反射(Lambertian reflectance)的。 |
漫反射面:郎伯模型回到最开始的问题,两极冷的原因就在于它受照射的阳光比赤道区域少。这是由于它们受到太阳的斜射。下图显示了八角形两极区域受到的光线明显少于正面区域。 蓝线代表了正交法向量单位长度。橙线表示了光线的方向。光通量的衰减取决于光线方向与法向向量的夹角。在郎伯模型( Lambertian model )中,它的值等于垂直的入射光线。 |
其可以表述为: |
朗伯着色器(Lambertian shader)我们现在已经有必要来理解一个朗伯模型在着色器中是如何实现的。Cg/HLSL 允许用一个自定义的函数替换标准的朗伯模型。在第8行,在指令 #pragma surface 中使用 SimpleLambert,强制着色器搜索叫做 LightingSimpleLambert 的函数:
|
||
从19到25行 展示了朗伯模型如何简单地在一个表面着色器中再实现。NdotL 为光颜色的强度系数(相乘)。参数衰减器用于调制光强。其需要被两个量乘是最初 Unity3D 用于仿真某些特效的技巧。这在 Aras Pranckevičius 中有解释,在Unity4中留存了下来为了向后兼容。最终在 Unity5 进行了修复,所以如果你在 Unity5 上再实现一个朗伯模型的时候,仅仅只要乘上一个量就行啦。 理解标准发光模型的原理是改变其不可或缺的步骤。许多可选的着色技术事实上仍然使用朗伯模型作为其第一步。 |
Toon shading
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
Shader "Example/Toon Shading" { Properties { _MainTex ( "Texture" , 2D) = "white" {} _RampTex ( "Ramp" , 2D) = "white" {} } SubShader { Tags { "RenderType" = "Opaque" } CGPROGRAM #pragma surface surf Toon struct Input { float2 uv_MainTex; }; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutput o) { o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } sampler2D _RampTex; fixed4 LightingToon (SurfaceOutput s, fixed3 lightDir, fixed atten) { half NdotL = dot(s.Normal, lightDir); NdotL = tex2D(_RampTex, fixed2(NdotL, 0.5)); fixed4 c; c.rgb = s.Albedo * _LightColor0.rgb * NdotL * atten * 2; c.a = s.Alpha; return c; } ENDCG } Fallback "Diffuse" } Shader "Example/Toon Shading" {Properties {_MainTex ( "Texture" , 2D) = "white" {}_RampTex ( "Ramp" , 2D) = "white" {}}SubShader {Tags { "RenderType" = "Opaque" }CGPROGRAM#pragma surface surf Toonstruct Input {float2 uv_MainTex;};sampler2D _MainTex; void surf (Input IN, inout SurfaceOutput o) {o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;}sampler2D _RampTex;fixed4 LightingToon (SurfaceOutput s, fixed3 lightDir, fixed atten){half NdotL = dot(s.Normal, lightDir);NdotL = tex2D(_RampTex, fixed2(NdotL, 0.5));fixed4 c;c.rgb = s.Albedo * _LightColor0.rgb * NdotL * atten * 2;c.a = s.Alpha; return c;}ENDCG}Fallback "Diffuse" } |
LightingToon模型计算了光强的朗伯系数NdotL并使用ramp纹理以将其离散化。该例子中仅映射了四级光强阶。不同的ramp纹理将细化地获得不同的toon shading变形。
镜面: Blinn-Phong模型
|
在Unity5中物理渲染就像本文在前面提出的那样, Uniy4.x使用朗伯光照模型作为其默认着色器。Unity5中发生了改变, 其引入了 物理渲染(PBR). 这个名字听起来相当有趣啊, 但是与其它光照模型没有什么不同。相比于朗伯反射, PBR提供了一个更加逼真的光线物体作用模型。术语physically 来源于,PBR考虑了材料的物理属性, 比如能量守恒以及光的散射。Unity5为艺术家和开发者提供了两种不同的方法,用于创建他们的PBR 材料: 金属工作流 和 镜面工作流。在前者中,一个材料对光的反射取决于其是什么样的金属(或者说,含有多少金属的量)。 |
简单来说就是,光是电磁波啊,其行为因接触到的是导体还是绝缘体而不同(电磁波唱由电场和磁场组成,但电场属性实际上比磁场属性更重要)。在镜面工作流中, 所提供的是镜面映射。尽管被当做两个不同的东西呈现出来, 金属材料和镜面材料实际上以不同的方式初始化同一个着色器;Marmoset 上有一个很好的例程展现了同样的材料如何通过金属和镜面工作流分别创建。这也是为什么当第一次接触 Unity5 着色器时会因为源代码中出现了同一事物却有两个工作流现象时会产生误解。 Joe Wilson 创建了一个相当清晰的例程来知道我们的艺术家:如果你想学习怎么通过 PBR 创建非常逼真的材质,这将是非常好的开始哟。如果需要更详细的技术信息,在 Unity5 博客里关于 PBR 的地方猛戳a very well done primer 。 Unity5 中新光照模型名字既简单又标准。取这个名字是因为现在 PBR 是每一个 Unity3D 中新建对象的初始材料。而且,每一个新建的着色器文件会被自动配置为一个 PBR 表面着色器:
|
14行将告知 Unity3D 该表面着色器将使用 PBR 光照模型。17行 意味着该着色器将使用高级特性,因而其将不同在落后的硬件上使用。同样的, SurfaceOutput 也不能同 PBR 一起使用;而是必须使用 SurfaceOutputStandard。 PBR 表面输出在 SurfaceOutputStandard 中不光是 Albedo,Normal,Emission 和 Alpha 这些属性,还有三个新的:
你应当通过 SurfaceOutputStandardSpecular 使用镜面流,其使用 float3 镜面替换了半金属性。注意当朗伯反射存在一个半镜面场,其在 PBR 中的镜面属性就是一个 float3。这符合镜面反射光波的 RGB 颜色值属性 。 |
Unity 中使用的着色技术迄今为止已经介绍了四种不同的着色技术。为了避免混淆,可以参考下表中所示,顺序分别为:着色技术,表面着色器名,表面输出结构体名和内置着色器名称。
PBR 背后的方程非常复杂。如果你对背后的数学比较感兴趣,维基百科中的渲染方程和这篇文章 将是非常好的起点。 如果你导入 Unity3D 包 (包含了该例程中用到的着色器), 你将注意到内置 “Bumped Diffuse” 着色器是怎么产生一个与其最初实现“Simple Lambert”非常不同的结果。这是因为 Unity3D 的着色器增加了额外的特性,比如正常的映射。 |
结论本文介绍了用于表面着色的自定义光照模型。通过一个关于如何修改获得不同特性的真实例子简单解释了朗伯和 Blinn-Phong 模型。有必要注意下单纯的漫射材料实际上在生活中是不存在的:即使是你所想到的最钝的材料也会有一些镜面反射。漫射材料在过去中非常普遍,因为计算镜面反射开销太大。 本文也介绍了什么是 PBR,以及在 Unity5 中如何使用。PBR 着色器与表面着色器没有什么区别,仅仅是带有了一个非常高级的光照模型。 |
本文转自:开源中国社区 [http://www.oschina.net]
本文标题:Unity3D 的物理渲染和光照模型
本文地址:http://www.oschina.net/translate/physically-based-rendering-and-lighting-models-in-unity3d
参与翻译:Parser7SParser, SeanWangOSC, 无若, 思维特无敌
英文原文:Physically Based Rendering and lighting models in Unity3D