shader入门基础-更复杂光照
渲染路径
- 前向渲染路径(Forward Rendering Path)
- 延迟渲染路径(Defferred Rendering Path)
- 顶点照明渲染路径(Vertex Lit Rendering Path)
通过设置 Pass 的 LightMode 标签实现
1
2
3
Pass{
Tags {"LightMode"="ForwardBase"}
}
LightMode 标签支持的渲染路径设置选项
标签名 | 描述 |
---|---|
Always | 不管使用哪种渲染路径,该 Pass 总是会被渲染,但不会计算任何光照 |
ForwardBase | 用于前向渲染,该 pass 会计算环境光,最重要的平行光,逐顶点/SH 光源和 Lightmaps |
ForwardAdd | 用于前向渲染,该 pass 会计算额外的逐像素光源,每个 pass 对应一个光源 |
Deferred | 用于延迟渲染,该 pass 会渲染 G 缓冲 G-buffer |
ShadowCaster | 把物体的深度信息渲染到阴影映射纹理(shadowmap)或一张深度纹理中 |
PrepassBase | 用于遗留的延迟渲染,该 pass 会渲染法线和高光反射的指数部分 |
PrepassFinal | 用于遗留的延迟渲染,该 pass 通过合并纹理、光照和自发光来渲染得到最后的颜色 |
Vertex、VertexLMRGBM 和 VertexLM | 用于遗留的顶点照明渲染 |
前向渲染路径的原理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Pass{
for (each primitive in this model){
for (each fragment covered by this primitive)
{
if (failed in depth test)
{
//如果没有通过深度测试,则该片元时不可见
discard;
}
else{
//如果片元可见就记性光照机选
float4 color = Shading(materialinfo,pos,normal,lightDir,viewDir);
//更新帧缓冲
writeFrameBuffer(fragment,color);
}
}
}
}
对于每个逐像素光源,我们都需要进行上面一次完整的渲染流程。如果一个物体在多个逐像素光源的影响区域内,那么该物体就需要执行多个 Pass, 每个 Pass 计算一个逐像素光源的光照结果,然后在帧缓冲中把这些光照结果混合起来得到最终的颜色值。假设场景中有个 N 个物体,每个物体受 M 个光源的 影响,那么要渲染整个场景一共需要 N*M 个 pass。
Unity 中的前向渲染
前向渲染路径有 3 种光照处理方式:
- 逐顶点处理
- 逐像素处理
- 球谐函数(Spherical Harmonics,SH)
unity 会根据场景中各个光源的设置以及这些光源对物体影响程度,对这些光源进行一个重要度排序。 其中,一定数目光源按逐像素方式处理,最多 4 个光源会按逐顶点方式处理,剩下按 SH 方式处理。 Unity 排序规则
- 场景中最亮的平行光总是按逐像素处理
- 渲染模式被设置成 Not Important 的光源,会按逐顶点或者 SH 处理。
- 渲染模式被设置成 Important 的光源,会按照逐像素处理。
- 如果根据以上规则得到的逐像素官员数量小于 Quality Setting 中的逐像素光源数量,会有更多的光源以逐像素的方式进项渲染。
延迟渲染原理
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
Pass 1 {
//第一个pass不进行真正的光照计算
//仅仅把光照计算需要的信心存储到G缓冲中
for(each primitive in this model)
{
for(each fragment covered by this privitive)
{
if(failed in depth test)
{
//如果没有通过深度测试,说明该片元是不可见
discard;
}else{
//如果该片元可见
//就把需要的信息存储到G缓冲中
writeGBuffer(materialInfo,pos,normal);
}
}
}
}
Pass 2{
//利用G缓冲中的信息进行真正的光照计算
for(each pixel in the screen)
{
if(the pixel is valid)
{
//如果该像素是有效地
//读取它对应的G缓冲中的信息
readGBuffer(pixel,materialInfo,pos,normal);
//根据读取到的信息进行光照计算
float4 color = Shading(materialInfo,pos,normal,lightDir,viewDir);
//更新帧缓冲
writeFrameBuffer(pixel,color);
}
}
}
延迟渲染使用的 Pass 数目通常就是两个,延迟渲染的效率不依赖于场景的复杂度,而是和我们使用的屏幕空间的大小有关。
Unity 中的延迟渲染
延迟渲染路径适合场景中光源数量较多、使用前向渲染路径会造成性能瓶颈的情况下使用,延迟渲染中的每个光源都可以按逐像素的方式进行处理。 延迟渲染缺点:
- 不支持真正的抗锯齿(anti-aliasing)功能
- 不能处理半透明物体(延迟渲染需要深度写入)
对显卡有一定要求 Unity 中使用延迟渲染路径,需要提供两个 Pass。 第一个 Pass 用于渲染 G 缓冲,在该 Pass 中将物体漫反射、高光反射、颜色、平滑度、法线、自发光和深度等信息渲染到屏幕空间的 G 缓冲区,因此,延迟渲染路径的效率不依赖与场景是否复杂,而是屏幕的分辨率高低。对于每个物体来说,这个 Pass 仅会执行一次。 第二个 Pass 用于计算真正的光照模型。这个 Pass 使用上一个 Pass 中渲染的数据来计算最终的光照颜色,再存储到帧缓冲中。 默认的 G 缓冲区包括以下渲染纹理(Render Texture):
- RT0:ARGB,RGB 通道存储漫反射颜色,A 通道未使用
- RT1:ARGB,RGB 通道存储高光反射颜色,A 通道存储高光反射的指数部分(Gloss)
- RT2:ARGB,RGB 通道存储法线,A 通道未使用
- RT3:ARGB,存储自发光+lightmap+反射探针
- 深度缓冲和模板缓冲
光源类型
常用的光源属性有光源的位置,方向,颜色,强度,衰减。
- 平行光 没有位置,只有方向,不会衰减。
- 点光源 球形,球心处光照强度最强,球体边界处最弱,衰减值可以由一个函数定义。
- 聚光灯 锥形
- 面光源