OpenGL渲染管线

一、OpenGL简介

OpenGL是OpenGL Graphics Library的缩写,是一个定义了跨编程语言、跨平台的编程接口,显卡通常有OpenGL的实现,不同显卡上的OpenGL实现也不一定相同,OpenGL标准不是平台相关的,所以同一个程序可能在不同的显卡上运行。OpenGL API只处理图形渲染,并不提供动画、定时器、文件IO、图像文件格式处理、GUI等功能。
当我们在屏幕上绘制几何体的时候,OpenGL会按照下面的顺序来处理管线:首先执行当前绑定的顶点着色器,如果有绑定,然后分别是细分和几何着色器;然后将最oh在那个集合体装配为图元进入光栅化阶段,这里将计算出窗口中哪些像素受到了几何体的影响。当OpenGL确定当前需要生成的一个独立的片元时,它将执行片元着色器的内容,然后再经过几个处理阶段,判断片元是否可以作为像素绘制到帧缓存中,以及控制绘制的方式。

二、GPU渲染管线

1.GPU渲染管线

GPU渲染包括几何阶段和光栅化阶段,其中几何阶段主要涉及各种坐标变换。

GPU渲染管线
2.几何阶段

整个过程可以这样理解:设三维空间上的坐标(0,0,0)处画一个小球,将小球移动到(1,0,0),再绕着y轴旋转90度,对小球位移和旋转处理完成后,这是模型矩阵的功能。

在空间中放置好模型后,需要架设摄像机,然后才能够观察到模型,这是视图矩阵实现的功能。把这两部分统一起来,就得到模型视图矩阵。

接着,需要把小球投影到一个虚拟屏幕上,计算小球的虚拟投影点,这是投影矩阵完成的功能。如果场景中存在多个小球,相对于摄像机的视角,有小球被前面的小球挡住了,那么被挡住的小球就不会被渲染出来,裁剪掉被阻挡的模型就是裁剪处理完成的功能。最后,根据屏幕的长宽,把虚拟屏幕映射到真实屏幕上。
几何阶段
在这里插入图片描述
如上图所示,几何变换的经历了模型变换、视图变换、投影变换、屏幕映射,中间涉及建模坐标系,世界坐标系,观察坐标系,屏幕坐标系。

(1)模型变换(建模坐标系->世界坐标系)

这个阶段的变换,主要包括glTranslate(平移)、glScale(缩放)、glRotate(旋转)。经过这样一系列变换之后,建模坐标系中的某个点 P0(x0,y0,z0),会被摆放到世界坐标系上的p1(x1,y1,z1)点。

世界坐标系是右手坐标系,以屏幕中心为原点(0,0,0),面对屏幕时,左手边是正x轴,上面是正y轴,屏幕指向你的为z轴。长度范围:窗口范围按此单位恰好是(-1,-1)到(1,1)。

世界坐标系与模型坐标系
以2D坐标系为例,其坐标图如下。图中红色坐标系是世界坐标系WC,绿色的是模型坐标系MC。现有一个顶点,在模型坐标系中的坐标为(1,1),现在要把这个模型坐标转换到世界坐标中来表示,从图中可以看出,点(1,1)在世界坐标系中的坐标为(3,4)。模型坐标系MC在世界坐标系中使用齐次坐标的矩阵表示形式为:在这里插入图片描述
其中矩阵第一列为MC中x轴在WC中的向量表示,第二列为MC中y轴在WC中的向量表示,第三列为MC中的原点在WC中的坐标表示。
有了这个模型变换矩阵后,用这个矩阵乘以在MC中表示的坐标就可以得到该坐标在世界坐标系中的坐标在这里插入图片描述
世界坐标系与模型坐标系的计算
(2)视图变换(世界坐标系->视点坐标系)

视点坐标系是为摄像机服务的坐标系,以视点为原点,视线方向为Z轴正方向,它仍然是是右手坐标系。opengl中提供了API接口gluLookAt()用于架设相机,其定义为`

void  glutLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez`,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz)

其中,(eyex, eyey, eyez)规定摄像机的位置,(centerx, centery, centerz)规定观察点,即上面提到的look坐标,(upx, upy, upz)规定摄像机的垂直朝向。
接着模型变换的结果,把相机坐标系VC加进去,计算MC坐标中的点如何在相机坐标系中表示。

在这里插入图片描述
Model view变换计算
从上面的网格坐标图中可以直接看出点(1,1)在相机坐标系中VC中的坐标为(-2,-2),相机坐标系VC在世界坐标系WC中可以表示为:在这里插入图片描述
那么世界坐标系中的点转换为相机坐标系中的点就需求VC的逆矩阵:在这里插入图片描述,最后世界坐标系WC中的点(3,4)在相机坐标系VC中的坐标为:
在这里插入图片描述
通过以上变换,可以把模型坐标变换为相机坐标。现在我们计算得到了VC逆矩阵和MC,如果把VC逆矩阵和MC相乘,就可以得到模型坐标在相机坐标中的表示。在这里插入图片描述
在opengl中模型变换和视图变换统一为模型视图变换。用函数glMatrixMode()来指定变换类型,如果是模型视图变换,则选用参数GL_MODELVIEW。如下面的代码片段所示:

glMatrixMode(GL_MODELVIEW);//规定当前处理的矩阵是模型视图矩阵
glLoadIdentity();                   //把模型视图矩阵设置为单位矩阵
drawSphere();

(3)投影变换(视点坐标系->投影坐标系)

投影变换意味着之前变换到相机坐标系的场景再次变换到投影坐标系下。

投影坐标系和相机坐标系相同,一般都是用右手坐标系,z轴正方向指向视点,投影的近裁剪面为Z=-near,远才见面为Z=-far。

在投影变换中也分为两部分,第一部分是将上个阶段得到的所有数据从观察坐标系转换到裁剪坐标系,第二个部分是将这些裁剪坐标系通过除以W分量的方式转换到归一化设备坐标(NDC)。

NDC坐标系是一个左手坐标系,其z轴方向与投影坐标系正好相反。一般地,将三维坐标系转换为平面坐标有两种投影方式:正交投影和透视投影。
在这里插入图片描述
a)正交投影

在opengl中使用glOrtho(left,right,bottom,top,near,far)来进行设置。该函数可以设置正交投影的投影空间,在该空间以外的坐标点就不会被投影到平面上。

大的投影空间是根据这六个参数设置的投影空间,OpenGL会自动将该空间归一化,也就是将该空间或立方体转化为边长为1的正六面体投影空间,并且该正六面体的中心在相机坐标系的原点。

一旦设置使用glortho函数设置投影空间,OpenGL会生成投影矩阵。这个矩阵的作用就是将坐标进行正交投影并且将投影后的坐标正规化(转换到-1到1之间)。

要注意的是,生成该矩阵的时候,OpenGL会把右手坐标系转换为左手坐标系,应为右手坐标系的z轴指向平面外,不符合我们的习惯。

b)透视投影

透视投影的核心就是近大远小,当一个物体放在视点位置,就是无穷大了,所以视点的半径一般是取非零值。
一般定义透视投影的方法有两种:

gluPerspective(theta,aspect,near,far)
glutFrustum(left,right,bottom,top,near,far)

在这里插入图片描述
上图中,摄像机摆放在视点坐标系的原点,视线指向 z 轴负方向。剪裁的近平面和原平面的深度都为正,所以实际上这些平面的Z坐标都为负(在视点坐标系下)。即有:Znear = - near, Zfar = -far。为了确定透视投影矩阵,需要用到齐次坐标,而且要牵涉到规范化的部分。

d)规范化

相当于拍照片,能放在一张照片中的东西是有限的,所以要对所见到的世界进行裁剪,取出想要的部分。
但是在算法上实现裁剪是很复杂的。为了方便这一流程,首先将需要的部分规范化,缩放到一个单位大小的格子里面,然后再用一个单元大小的相框去丈量,将相框以外的全部舍弃,这就是规范化和裁剪的一个主要出发点和思路。

对应的物理世界中的场景,就是将照相机(老式的似乎更加贴近)的所见缩放到一张标准大小的底片上,超过底片大小的部分全都不会显示出来。

这一部分内容比较多,这里就不在细讲了,可以参照搞晕我的opengl坐标系

(4)视口变换

视口变换把上阶段得到的正规化的投影坐标转化为window窗口坐标。视口变换会将投影平面上的画面映射到窗口上。在opengl中可以使用函数glViewport(x,y, width, height),其中x,y以像素为单位,指定了视口的左下角位置;width,height表示视口矩形的宽度和高度,根据窗口的实时变化重绘窗口。

3.光栅化阶段

光栅化阶段是决定哪些像素被几何图元覆盖的过程。需要对上一阶段得到的顶点数据(例如纹理坐标、顶点坐标等)进行差值,然后逐像素处理。
在这里插入图片描述
(1)三角形设置

计算光栅化一个三角形网格所需要的信息。

为了能够计算边界像素的坐标信息,我们需要得到三角形边界的表达方式。这样一个计算三角形网格表示数据的过程就叫做三角形设置。

(2)三角形遍历

检查每个像素是否被一个三角形网格所覆盖。如果被覆盖就会生成一个片元(fragment)。找到哪些像素被三角网格覆盖的过程就是三角形遍历。也称为扫描变换。

三角形遍历阶段还会使用三角网格的3个顶点信息对整个覆盖区域的像素进行差值。

输出:片元。
片元并不是真正意义上的像素。而是包含了很多状态的集合,这些状态用来计算最终颜色。这些状态包括但不限于它的屏幕坐标,深度信息,法线,纹理坐标等。

(3)片元着色器

输入:对于从顶点着色器输出的数据插值得到的。
输出:一个或者多个颜色
功能:纹理采样

(4)片元操作

主要完成以下工作;
a)决定每个片元的可见性。其中涉及很多测试工作,比如深度测试、模板测试等;
b)将通过测试的片元颜色值和已经存储在颜色缓冲区的颜色进行混合;
c)模板测试:通常用于限制渲染区域。用于轮廓渲染、阴影渲染。

以上内容参考:https://www.cnblogs.com/msc4456/p/5939807.html
https://blog.csdn.net/hjq376247328/article/details/49387011
http://www.twinklingstar.cn/2015/1532/introduce-to-opengl/
https://www.sohu.com/a/236506222_468740

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Estelle_Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值