认识一下基础配置:
ClearFlags:
在摄像机进行渲染前,对颜色缓冲及深度缓冲,进行不同控制操作,每个相机在渲染时会存储颜色和深度信息。屏幕的未绘制部分是空的,默认情况下会显示天空盒。当你使用多个相机时,每一个都将自己的颜色和深度信息存储在缓冲区中,还将积累大量的每个相机的渲染数据。当场景中的任何特定相机进行渲染时,你可以设定清除标记以清除缓冲区信息的不同集合。可以通过下面四个选项之一来完成:
Skybox :清除颜色缓冲和深度缓冲,没有物体遮挡的背景,用天空盒子填充。
Solid Color :清除颜色缓冲和深度缓冲,没有物体遮挡的背景,用 Camera 的另一个属性Background的颜色填充。
Depth Only:只清除深度缓存。
Don’t Clear:颜色缓冲和深度缓冲都不清除。
CullingMask:
这个相机可以绘制的Layer图层,这个每一个节点都会有这个属性,如下图所示
projection
投影的方式:可以为透视投影或者正交投影
field of view
相机张开的角度,相当于眼睛张开的角度
clipping planes
near:0.3,近裁切面深度值
far:1000,远裁切面深度值
这两个值将会决定视锥体的长度
viewRect
x:0.0
y:0.0;
W:1.0;
H:1.0;
这四个参数会决定相机投影到屏幕坐标系的具体位置和大小,按照现在这个设置,则完全覆盖屏幕,因为屏幕的大小就是(1.0,1.0),屏幕的坐标系原点就是(0.0,0.0);
Depth
这个值越大,说明这个相机所包含的内容越先被渲染
RenderTexture
渲染纹理
Unity中使用RenderTexture来接收FBO(可视化FBO),Game窗口是一个特殊的RenderTexture,它允许多个FBO叠加渲染,当Camera的RenderTarget都设置为null时表示输出到game窗口(没有摄像机的RenderTaget为null会显示没有摄像机进行渲染),设置不为null表示输出到某个RT
cpu------>上传纹理----->gpu renderbuffer–>当要渲染某个纹理时,会生成framebuffer–>
如果此时将framebuffer绑定到framebufferobject(fbo),则这个纹理就会被写入到渲染纹理中,摄像机如果渲染纹理设置为null,那么摄像机的渲染纹理默认指的是屏幕,如果是自己创建的渲染纹理,则会将结果输出到其中,类似于截图或者小地图的效果,
//截图代码
RenderTexture renderTexture = m_Camera.targetTexture;//拿到目标渲染纹理
RenderTexture.active = renderTexture;
Texture2D tex = new Texture2D(renderTexture.width, renderTexture.height);//新建纹理存储渲染纹理
tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);//把渲染纹理的像素 给Texture2D,才能在项目里面使用
tex.Apply();//记得应用一下,不然很蛋疼
byte[] bytes = tex.EncodeToPNG();//拿到图片的byte
File.WriteAllBytes(Application.dataPath + "/Resources/ScreenShort/" + _index.ToString() + ".png", bytes);//写入本地
RenderPath
渲染路径决定了光照在 shader 中是如何应用的,所以在计算光源时,需要在每个 Pass 块内指定它的渲染路径,Unity 才会为我们提供正确的光照信息
渲染路径:一般有以下四种
Legacy Vertex Lit:遗留的顶点照明渲染.光照效果最一般的,不支持阴影,一般用于配置较差的移动设备
Forward:前向渲染,能够很好的支持光照效果,不支持点光源和聚光灯的阴影,一般采用烘焙的方式来处理更多的阴影,前向渲染路径是我们最常用的一种渲染路径。在进行一次完整的前向渲染时,我们需要渲染该对象的渲染图元,并计算两个缓冲区的信息:颜色缓冲区和深度缓冲区。
利用深度缓冲来决定一个片元是否可见,如果可见就更新颜色缓冲区中的颜色值
Pass {
for(each primitive in this model){
if(failed in depth test){
//如果没有通过深度测试,说明该片元是不可见的
discard;
}else{
//如果该片元可见
//就进行光照计算
float4 color = Shadering(materialInfo, pos, normal, lightDir, viewDir);
//更新帧缓冲
writeFrameBuffer(fragment,color);
}
}
}
对于每个逐像素光源,都需要进行上面一次完整的渲染流程。如果一个物体在多个逐像素光源的影响区域内,那么该物体就需要执行多个Pass,每个Pass计算一个逐像素光源的光照结果,然后在帧缓冲中把这些光照结果混合起来得到最终的颜色值。假设,场景中有N个物体,每个物体受到M个光源的影响,那么就需要 N * M 个 Pass。可以看出,如果有大量逐像素光照,需要执行的Pass数目也会很大。所以 Unity 会限制每个物体的逐像素光照的数目
Deferred Lighting:延迟渲染,支持最佳的光照效果以及所有类型的光照投影,但是需要硬件支持, pro模式才有.
延迟渲染主要包含两个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 {
// 如果该片元可见
// 就把需要的信息存储到G缓冲中
writeGBuffer(materialInfo, pos, normal, lightDir, viewDir);
}
}
}
}
Pass 2 {
// 利用G缓冲中的信息进行真正的光照计算
for (each pixel in the screen) {
if (the pixel is valid) {
// 如果该像素是有效的
// 读取它对应的G缓冲中的信息
readGBuffer(pixel, materialInfo, pos, normal, lightDir, viewDir);
// 根据读取到的信息进行光照计算
float4 color = Shading(materialInfo, pos, normal, lightDir, viewDir);
// 更新帧缓冲
writeFrameBuffer(pixel, color);
}
}
}
可以看出,延迟渲染使用的Pass数目通常就是两个,这跟场景中包含的光源数目是没有关系的。换句话说,延迟渲染的效率不依 赖于场景的复杂度,而是和我们使用的屏幕空间的大小有关。这是因为,我们需要的信息都存储在缓冲区中,而这些缓冲区可以理解 成是一张张2D图像,我们的计算实际上就是在这些图像空间中进行的。
Unity中的延迟渲染
Unity有两种延迟渲染路径,一种是遗留的延迟渲染路径,即Unity 5之前使用的延迟渲染路径,而另一种是Unity5.x中使用的延迟渲 染路径。如果游戏中使用了大量的实时光照,那么我们可能希望选择延迟渲染路径,但这种路径需要一定的硬件支持。
对于延迟渲染路径来说,它最适合在场景中光源数目很多、如果使用前向渲染会造成性能瓶颈的情况下使用。而且,延迟渲染路 径中的每个光源都可以按逐像素的方式处理。但是,延迟渲染也有一些缺点。
不支持真正的抗锯齿(anti-aliasing)功能。
不能处理半透明物体
对显卡有一定要求。如果要使用延迟渲染的话,显卡必须支持MRT(Multiple Render Targets)、Shader Mode 3.0及以上、深度渲 染纹理以及双面的模板缓冲。
当使用延迟渲染时,Unity要求我们提供两个Pass。
(1)第一个Pass用于渲染G缓冲。在这个Pass中,我们会把物体的漫反射颜色、高光反射颜色、平滑度、法线、自发光和深度等 信息渲染到屏幕空间的G缓冲区中。对于每个物体来说,这个Pass仅会执行一次。
(2)第二个Pass用于计算真正的光照模型。这个Pass会使用上一个Pass中渲染的数据来计算最终的光照颜色,再存储到帧缓冲中。
默认的G缓冲区(注意,不同Unity版本的渲染纹理存储内容会有所不同)包含了以下几个渲染纹理(Render Texture,RT)。
RT0:格式是ARGB32,RGB通道用于存储漫反射颜色,A通道没有被使用。
RT1:格式是ARGB32,RGB通道用于存储高光反射颜色,A通道用于存储高光反射的指数部分。
RT2:格式是ARGB2101010,RGB通道用于存储法线,A通道没有被使用。
RT3:格式是ARGB32(非HDR)或ARGBHalf(HDR),用于存储自发光+lightmap+反射探针(reflection probes)。
深度缓冲和模板缓冲。
当在第二个Pass中计算光照时,默认情况下仅可以使用Unity内置的Standard光照模型。如果我们想要使用其他的光照模型,就需要 替换掉原有的Internal-DeferredShading.shader文件。
Legacy Deferred :(遗留的延迟渲染)