概述
引言
图形渲染管线到底干了什么?这是任何一个学习图形学的人都无法逃避的问题。
现代的API(如OpenGL,DirectX等)都将其具体过程封装好了,使用的时候只需传入相应参数,调用函数即可达到渲染的目的。尽管不了解它的原理并不影响使用,但为了编程可持续发展(雾),最好还是自己手动实现一下光栅化渲染器。
以下我简单地阐述图形渲染管线的流程(以OpenGL辅以理解),我会用整体->细节的结构去阐述这个流程
正文
整体
首先是一张流传甚广的图片:
这是OpenGL的图形渲染管线(蓝色底代表可编程)示意图,从上我们可以知道图形渲染管线的功能是什么:输入顶点数据,输出屏幕上我们看到的东西。
更加具体一点:输入顶点数据至顶点着色器,接着进行图元装配,(几何着色器可选),然后光栅化(将连续的顶点映射至屏幕,由于屏幕是一个一个的像素(离散的),所以称之为光栅化),接着进行着色,最后进行各种测试和混合(深度测试、模板测试,颜色混合之类的)。
由此,我们知道了图形渲染管线的大致流程,下面开始深入讲解细节。
细节
同样是以一张图开局
我们先抛开OpenGL中的那些人为划定的Shader,直接来看渲染管线干了些什么。
Application 这是完全由开发者控制的阶段,通常在CPU上运行,一般是执行一些碰撞之类的计算。此阶段不可再分。
Geometry 这个阶段分为四个小流程,分别是:vertex shading , optional vertex processing , clipping, screen mapping。
Rasterization 这个阶段有两个部分,primitive setup和primitive traversal。
Pixel Processing 分为Pixel Shading和Merging。
Geometry
vertex shading
此阶段有两个任务:计算顶点位置,计算其他属性的值(如法线、纹理坐标,颜色等)。
- 计算顶点的位置。我们所熟知的model->view->projection在这里计算。
具体地说。model变换由三个变换组成:缩放(scale),旋转(rotate),平移(translate),通过矩阵乘法来执行这些操作。(注:rotate用的是四元数而非欧拉角的方式实现,因为欧拉角会导致Gimbal Lock的问题:具体参照 Bonus,四元数和欧拉角之间的转化可以参照图书《3D数学基础:图形与游戏开发》或者quaternion。
接着是view矩阵(即摄像机)。
最后是projection投影矩阵,这个矩阵的推导较为冗长,这里我给出两个推导的链接:深入探索透视投影变换,OpenGL projection matrix,写的都很好。
- 计算顶点其他属性的值。在计算的过程中要注意透视纹理映射的问题,具体参考:深入探索透视纹理映射(上), 深入探索透视纹理映射(下)。
optional vertex processing
这个阶段是可选的,有曲面细分,几何着色和流输出(图元装配在曲面细分里面),这不是我们阐述的重点。
clipping
裁剪过程发生在裁剪空间里面(在执行了model->view->projection变换之后,顶点的坐标所处的空间称为裁剪空间)。我们不妨将投影后的点设为
的点将会被裁去(裁去之后依据裁剪情况重新组合图元)。
为什么是这个范围?:很简单,在裁剪之后会进行透视除法,将原本perspective构建的视锥体变换到CVV空间(CVV空间中的坐标系称之NDC)中。经过透视除法之后的点(x, y, z,w)变成(x/w, y/w, z/w, 1),我们知道他们应当处于CVV内,即取值范围为[-1, 1](z在DirectX中是[0, 1],在OpenGL中是[-1, 1]),我们将这个取值范围逆着推回来即可。此外透视除法会产生近大远小的效果。
裁剪之后便会进行透视除法,将视锥体变成长方体(OpenGL中是特殊一点的长方体,即正方体),同时产生近大远小的效果。我们也可以说透视除法是要把齐次坐标转回欧式坐标。
screen mapping
将处于CVV空间的
这里我们可以知道,如果Perspective的视锥体的Aspect不为1,透视除法之后会失真,而映射到屏幕(视口)上之后会复原(因此我们要把视口的长宽比设置为Perspective 的Aspect一致,这样子映射之后才不会失真)。
Rasterization
光栅化有三角形建立和三角形遍历两个阶段。
- primitive setup(三角形(图元)建立):三角形通过传入三个点得以建立。
- primitive traversal(三角形(遍历)):遍历三角形内的片元(fragment),送至下一个阶段。
Pixel Processing
- pixel shading:所有逐像素的计算都在这里完成,光照,纹理,颜色值都是在这里计算。
- merging:执行深度测试,模板测试,混合测试等过程。
总结
写完了光栅化渲染器,对OpenGL中的图形渲染管线(pipeline)有了初步的理解和认知,尽管实现的只是一个最简单的光栅化渲染器,但以后面对封装好的图形库、游戏引擎的时候总不至于两眼一抹黑。
路还长着呢。
拓展知识
- Directx在坐标运算中全程采用的是左手坐标系,OpenGL的NDC是左手坐标系,其他时候都是右手坐标系。
- 为什么坐标的运算要用到齐次坐标?可以参考这个回答:关于齐次坐标的理解(经典),此外也有另外一种角度,参考:深入探索透视投影变换的开头部分。
参考资料
- Bonus
- quaternion
- 3D图形固定短线(这个专栏讲的是真的好)
- OpenGL projection matrix
- RTR 4th阅读笔记 Chapter2
- GPU在进行vertex shading之后,rasterization之前,是怎么剪裁的?——徐行的回答
- 在透视投影中要进行透视除法。对于这一步 有没有更具体的解释或更形象的类比 让人容易理解?——milo yip的回答
最后
以上就是虚拟犀牛为你收集整理的matlab z变换离散化_光栅化渲染器的实现的全部内容,希望文章能够帮你解决matlab z变换离散化_光栅化渲染器的实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复