渲染管线概述

一、渲染管线

清除摄像机

摄像机深度:小的先绘制,大的后绘制

打包成三个大整体

二、CPU应用程序渲染过程

1、剔除

视锥体剔除:对金字塔外的模型不进行绘制,用AABB包围盒进行检测

层级剔除:对某一物体,改变它的图层,在摄像机里的剔除网格取消勾选该图层,那么摄像机画面中不在有该物体

2、排序(渲染队列)

2.1、一般情况

在材质球中的渲染队列中,一般不透明物体为2000,半透明物体为3000.

2.2、当渲染队列相等时

对于不透明物体(<2500)
按摄像机距离从前到后排序(越近越先)

对于不透明物体,当距离摄像机近的物体挡住了距离较远的物体后,距离较远的物体的部分轮廓就不需要绘制出来了,反正也看不到,这样就起到一个优化节约资源的效果。

对于半透明物体(>2500)
按摄像机距离从后到前排序(越远越先)

对于半透明物体,只有从后往前渲染才能保证其渲染结果的正确性,因为摄像机直接看见的是距离较近的物体,如果先渲染距离较近的物体的化,当后面渲染距离较远的物体时,前面的物体绘制就会发生改变,而从后往前渲染的化就能保证最近的物体绘制是正确的。

虽然可以保证不同物体从后往前渲染,却不能保证同一物体从后往前渲染,所以半透明物体是渲染领域最难处理的物体之一。

3、打包数据Batch

3.1、模型信息:

建模软件中的模型通常都是四边面,而游戏引擎中的模型都是三角面,模型导入游戏引擎时,会自动转换为三角面。

顶点坐标

法线

模型中的法线数量可能更多,这里是合并了重复的法线

UV

UV坐标的Z坐标都为0,没有实际意义,是一个二维坐标

切线
顶点色
索引列表

第一个数字指向顶点坐标,第二个数字指向顶点法线,第三个数字指向UV坐标

一行数字代表一个面

3.2、变换矩阵

世界变换矩阵
VP矩阵:根据摄像机位置和fov等参数构建

3.3、灯光、材质参数

Shader
材质参数
灯光信息

4、绘制调用

4.1、SetPass Call

设置好渲染状态,告诉GPU我们要使用哪个Shader,哪种混合模式,帮我们设置好背面剔除等等渲染设置。

4.2、Draw Call

告诉我们的GPU对哪些模型数据进行渲染。

三、GPU渲染管线

1、渲染管线与Shader的对应关系

1.1、CPU阶段

cpu阶段将模型空间的顶点信息全部传输到顶点Shader中

1.2、顶点Shader:

将模型空间中顶点的信息变换到裁剪空间,经过视口变换后转化为2D屏幕空间坐标

1.3、图元装配及光栅化

在输出顶点数据时可以自定义一些数据,便于进行图元装配和光栅化

1.4、片元Shader

采样传输过来的UV坐标,将其赋予到我们的片元上,就得到最终赋予到片元上的颜色

2、顶点Shader

最重要的任务:将顶点坐标从模型空间变换到裁剪空间

通俗地讲:模拟“拍照”的过程,模拟投影成像的过程,将我们的3D模型进行变形

经过顶点Shader处理后,相机金字塔的视锥体被转化变形成一个比例为2x2x1的立方体(CVV)

顶点Shader并不会产生2D图像。仅使得场景中断额3D对象产生变形效果

2.1、放置物体(世界空间——模型矩阵)

不同的物体从不同建模软件中导出,必须有统一的坐标规范

2.2、摆好相机(相机空间——视图矩阵)

当我们点击一个物体的时候,它的坐标是相对于世界坐标原点的,当我们点击摄像机时,我们视角的原点就是摄像机的位置,这时其他物体的坐标都是相对于摄像机(原点)的位置。

2.3、摁下快门(裁剪空间——投影矩阵)

将三维的物体投影成一个二位的图像,形成近大远小的情况,但它并不是成为了一个二维图像,只是作了变形操作,还差一个拍扁的操作

3、图元装配及光栅化阶段

3.1、裁剪操作

对视锥体边缘的三角面进行裁剪,裁掉之外的部分,并形成新的三角面

之间讲过的视锥剔除是针对于整个的模型,而裁剪操作是针对于微小的三角面

对于裁剪操作我们并不在视锥体进行,那样的话太难了,我们从前面得到的规则的裁剪空间中进行判断,这样会简单很多

3.2、标准化设备坐标

将裁剪空间中的坐标标准化到[-1,1]之间,为后面映射到屏幕

3.3、背面剔除

对于已经标准化设备坐标的物体,先忽略其Z轴,得到一个xy平面,如果在xy平面上的三角面的索引顺序呈现顺时针的话,那么这个三角面就是背面,就应该被剔除

3.4、视口转换(屏幕坐标)

将背面剔除后的标准化物体转换到屏幕分辨率大小的屏幕上,如(0,0)对应分辨率为1920下x1080像素的(960,540)

这里我们仅仅转换顶点的x,y坐标,对于z坐标我们暂时不做处理,因为z坐标要用来判断物体的前后关系

3.5、图元装配

其实之前转换的都是一堆顶点,现在我们要将它们连接成线,形成一些封闭的三角面

3.6、光栅化

对生成的图元三角形,采用特定的插值算法,得到片元,再将3D顶点转换为2D像素,将视口转换后的额3D模型压扁,得到屏幕上的2D图像,对其进行插值计算得到像素

顶点的Z值并没有丢弃掉,而是同样进行插值后存储在对应的片元上。当有重叠的片元时,我们就可以根据Z值去处理前后遮挡关系

顶点存储有颜色信息的,进行插值后就变成了片元上的颜色,下面是线性插值颜色的视频:

此处为语雀视频卡片,点击链接查看:tmpwppvideo_20230608_1_20230608_01095641.mp4

对应坐标和颜色值:

线性插值公式:

逐行扫描插值:

光栅化会产生锯齿:

4、片元Shader

在经过了顶点Shader后,除了输出了必要的深度值Z,还会输出一系列自定义的数据,如法线、顶点颜色、切线、位置……

4.1、最重要任务:上色

纹理技术
光照计算

4.2、 纹理技术

纹理图像在计算机中就是一个二维的数组,是用纹素地址储存的一组颜色值

1、纹理采样
给定一个纹理坐标,根据纹素地址找到对应的像素的颜色值

纹理坐标:一个二维的数值,可以在建模软件中生成,也可以在Shader中自由的设置。

一般在建模软件中设置,展UV的操作就是给我们的UV赋值

2、纹理过滤机制
当纹理映射到屏幕坐标上不为整数的时候,我们就粗暴的把他四舍五入为整数,常用于把较小的图片映射到较大的区域时产生的纹理失真现象

但是这样做,当一个较小的图片映射到较大的尺寸时,就会产生失真的现象

我们可以采样其中心点周围的四个点的像素值,对其进行双线性线性插值计算,就会得到较柔和的图片

对应着unity中的功能

3、Mipmap
当较大的图像要映射到较小的区域的时候,部分背景会变成纯色,引起失真

我们会根据原图生成一系列不同大小的图像,形成一条纹理链,然后根据映射区域的大小选择不同的图像

unity中的功能展示:

我们对导入图片可以选择生成mipmap图像,可以调整迭代的次数得到不同大小的图片,同时也会占用一定的内存

4、纹理寻址模式

一般情况下的UV坐标都在【0,1】之间,当出现UV坐标超出的情况,我们就要使用纹理寻址模式

对应unity中的功能:

就是限制边界(Clamp),它有四种模式,GL_CLAMP_TO_BORDER是用纯色填充超出的uv坐标,GL_CLAMP_TO_EDGE会复制边界边缘的像素,GL_REPEAT会重复平铺对象,GL_MIRRORED_REPEAT会重复镜像平铺。

5、纹理压缩格式
像PNG、JPG、TGA这些常用的图片压缩格式,我们在游戏中是不会直接使用的,图片导入到游戏引擎后我们会对它进行一个转换,转换到对对应平台支持的压缩格式

4.3、光照计算

1、光照组成
直接光源:光线到达物体表面后,只经过一次反射就进入人眼
间接光源:光线到达物体表面后经过多次反射,最终进入人眼的效果

2、光照模型:

要了解光照的计算,就要知道入射光线是怎样经过物体表面然后被反射出去的,我们把这种关系用BRDF双向反射分布函数来表示,但是这种函数过于复杂,难以直接放进Shader中进行计算,于是用简单的光照模型来简化BRDF函数的计算

Phong光照模型:

物体表面的颜色由三个光决定=漫反射光(Diffuse)+镜面反射光(Specular)+环境光(Ambient)

Diffuse漫反射:

遵循Lambert反射定律,认为物体表面是一个理想的漫反射表面,光到达物体表面一点后反射出去的光线在各个方向上的强度都是相等的

其反射强度与光线入射方向与物体表面一点法线的夹角大小有关,夹角越小,强度越大

我们通过点乘来计算判断夹角的大小

注意:我们约定俗成,光线方向为由顶点指向物体

镜面反射:

光线镜面反射,入射光线和反射光线呈现等角分布

其光照强度与摄像机观察方向和光线反射方向的夹角大小决定的,然后我们还会添加光滑度,就是决定了这个高光衰减的范围,假设这光滑度越大呢,就表明高光衰减的范围就越小,我们的摄像机要很靠近反射光线,才能看到物体表面点的颜色和亮度。

环境光:

环境光,顾名思义就是从周围环境反射过来的光。

我们可以把环境光等同于间接光照,间接光照有可模拟的技术,像light map光照贴图,Refletion probe反射球,它其实是基于图像的照明。还有一种就是light probe,实现的原理就是球谐SH,它能帮我们实现一些低频的漫反射光。

基本框架

5、输出合并

5.1、最重要的任务处理:处理前后遮挡关系,半透明混合。

屏幕位置有限,同一个像素点(x,y)可能存在多个片元的竞争,我们会根据一系列的测试和规则决定哪个片元会被渲染到屏幕的像素点上,或者两者需不需要做一些混合输出到我们的像素点

5.2、通俗的讲:片元通过重重考验到达像素点位置的过程。

1、片元数据:首先我们会得到一个由片元shader输出得到的片元数据,它包含了Color(Alpha通道)值和Depth值
2、Alpha测试:Alpha测试就是检测片源数据传过来的Alpha值。如果他低于某一个数的话,我们就可以直接把它丢弃掉。一般我们用它来做一些树叶镂空的效果。
3、模版测试Stencil Test:
4、深度测试Depth test:深度测试就是指对于屏幕上的同一个位置(x,y)有两个重叠的片元,这时候我们就检测他们片元数据中的深度值其中深度值较小的那一个,我们就认为更靠近摄像机就应该被渲染。
5、混合Blending:对于屏幕上同一个位置不同片源重叠的颜色计算,有时需要用到混合,我们可以根据不同程度的公式来进行混合计算得到该点的颜色。
6、帧缓冲区Color,Depth,Stencil:帧缓冲区就是一个临时的画布。当我们把场景中的物体都绘制完成的时候,我们的屏幕就会把他们拿到帧缓冲区进行显示。除此之外,是因为有帧缓冲区机制,我们的模板测试,深度测试,混合才得以实现,因为他们分别是在帧缓冲区区中的模版缓冲区,深度缓冲区和颜色缓冲区实现的一些操作。

5.3、帧缓冲区Framebuffer

1、颜色缓冲区

下面是颜色缓冲区

2、深度缓冲区

上面是深度缓冲区,他的深度默认为1.0

5.4深度测试Depth Test

假设我们要渲染一个蓝色和红色的三角形形,他们有部分片元重叠在一起

1、先渲染红色三角形
因为先渲染红色三角形,将红色三角形的深度值和默认的1.0深度值进行,可以看到红色三角形胜出,那么将红色三角形区域的像素点的深度和颜色都写为0.8和红色;
然后再渲染蓝色三角形,将蓝色三角形的深度值和现存的深度值(有1.0和0.8部分)进行比较,可以看到蓝色三角形胜出,那么蓝色三角形对应区域像素深度值和颜色更改为0.5和蓝色。

可以看到对于重叠区域,因为蓝色三角形深度值更小,所以蓝色三角形胜出,应该被优先渲染

2、先渲染蓝色三角形
类比于先渲染红色三角形

一个完整的深度测试,有两个选项是可以在Shader中控制的,分别是ZWrite深度写入和ZTest深度测试

ZWrite深度写入:

如果关闭掉ZWrite深度写入的话,即使蓝色三角形完成了深度测试,但是它的深度值也无法写入深度缓冲区中,显示的依然是默认的深度值1.0,但是它不影响颜色缓冲区的写入,只要通过了深度测试,那么颜色还是会正常的写入到我们的颜色缓冲区

ZTest深度测试:

我们还可以再Shader中写入一些深度测试的规则,比如片元的深度值要比默认的1.0大才能写入深度值、片元总是能通过深度测试、片元总是不能通过深度测试等等……

提前深度测试Early-Z:

提前深度测试发生在顶点Shader之后和片元Shader之前,它的作用是更好地优化,在顶点Shader和光栅化之后其实我们就已经获得了片元的深度值,这时我们通过比较就可以剔除或者不用深度较大的片元,这样就不需要经过片元Shader过程,达到优化的目的。

5.5、混合Blending

机制:当我们渲染一个片元的时候,它会拿到片元的Color值,去和当前颜色缓冲区现有的Color值进行混合,最后重新输出到颜色缓冲区上。

至于混合的模式是可以控制的。常见的有半透明混合(AlphaBlend)

其中白色部分是不可以改变的,Source Color是当前渲染片元的颜色值, Dest Color是对应位置颜色缓冲区里的已存的颜色值

其中绿色的部分是可以改变和控制的,在Shader中写上Blend SrcAlpha OneMinusSrcAlpha就可以改变我们的公式,其中的Source Alpha就是当前渲染片元的Alpha值,OneMinusSrcAlpha就是(1.0-SourceAlpha)

其他模式:柔和的叠加模式

排序问题
从后到前
对于片元从后往前渲染是非常困难的,过程中可能会发生一些错误
关闭Zwrite
打开混合模式通常情况下都会关闭ZWrite深度写入功能,因为我们要的不是单一的颜色值

四、渲染管线回顾

1、应用程序阶段:

对场景里的物体进行视椎体剔除(也有其他形式的剔除),然后对剩下的物体做一个渲染的排序,然后我们按照拍好的顺序提交Drawcall,提交一些模型的数据和SetPass call

2、GPU渲染管线:

2.1、顶点处理阶段:

顶点的MVP空间变换(Model、View、Projection),从模型空间转换到裁剪空间,并且输出一些自定义的数据

2.2、光栅化操作:

视椎体裁剪;把顶点转换到NDC(标准化设备坐标);背面剔除;映射到屏幕坐标;图元装配(链接各地顶点形成图元);对三角形内的图元进行光栅化操作,插值生成片元(会继承来自顶点的数据)

2.3、片元处理:

片元通过片元Shader调用片元数据进行光照计算和纹理着色,对片元进行着色

2.4、输出合并:

输出之前会进行Alpha测试、模版测试、深度测试、颜色混合

3、帧缓冲器:

将图像整合输出到帧缓冲区,屏幕就从帧缓冲区显示图像

文章参考:

渲染管线概述 (yuque.com)

  • 34
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值