前言
5.0版本更新后unity的渲染路径实际上共有两种:前向渲染路径和延迟渲染路径。
在unity里,默认采用的渲染路径是前向渲染路径,新版的unity在Edit->Player->Other Setting->Rendering Path中不能进行选择,但在相机的Inspector窗口中依然可以设置,默认为Use Graphics Settings.也可以在shader内部设置渲染路径,如: Tags { "LightMode"="ForwardBase" }
前向渲染路径
每进行一次完整的前向渲染,我们都需要渲染该对象的渲染图元,并计算颜色缓冲区和深度缓冲区的信息,其中深度缓冲区的信息决定了一个片元是否可见,若可见则颜色缓冲区中的值会被更新。
实例代码如下
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);//更新帧缓冲
}
}
}
}
在Unity中,前向渲染路径有3种处理光照(即,照亮物体)的方式:逐像素处理,逐顶点处理,球谐函数(Spherical Harmonics, SH)处理。
延迟渲染路径
延迟渲染主要包含了两个Pass,在第一个Pass中,我们不进行任何光照计算,而是仅仅计算哪些片元是可见的,这主要是通过深度缓冲技术来实现,当法线一个片元是可见的,我们就把它的相关信息存储到G缓冲区中。然后,在第二个Pass中,我们利用G缓冲区的各个片元信息,例如表面法线、视角方向、漫反射系数等,进行真正的光照计算。
Pass 1{
//第一个Pass不进行真正的光照计算
//仅仅把光照计算需要的信息存储到G缓冲中
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 2{
//利用G缓冲中的信息进行真正的光照计算
for (each pixel in this screen){
for(the pixel is valid){
//如果该像素有效
//读取它对应的G缓冲中的信息
readGBuffer(pixel,materialInfo,pos,normal);
//根据读取到的信息进行光照计算
float4 color = Shading(materialInfo, pos, normal, lightDir, viewDir);
writeFrameBuffer(fragment, color);//更新帧缓冲
}
}
}
}
优点:效率与光源数目无关,适合处理大量光源的实时光照,延迟渲染的效率不依赖于场景的复杂度,而是和我们使用的屏幕空间大小有关
缺点:1.不支持真正的抗锯齿
2.不能处理半透明物体
3.对显卡有一定要求