OpenGL系列2:渲染管线

来源:互联网 发布:暖宫贴自发热原理 知乎 编辑:程序博客网 时间:2024/06/15 23:36

一、渲染:计算机根据模型创建图象。模型(或物体)是由几何图元构成的,而几何图元是通过顶点来指定的。最终渲染的图象由屏幕像素组成。像素(pixel)是显示硬件能够放置到屏幕上的最小的可视元素。有关像素的信息(如颜色)在系统内存中被组织为位面(bitplane)。位面构成了帧缓存(包含图形显示设备为控制屏幕上所有像素的颜色和亮度所需的信息)。 
1、使用几何图元建立模型,从而得到物体的数学描述。(OpenGL将点、直线、多边形、图形和位图视为图元); 
2、在三维空间排列物体,选择观察场景的有利位置; 
3、计算所有物体的颜色。颜色可能是由应用程序指定的、根据光照条件确定的、将问题粘贴到物体上得到的,也可能是上述多种操作的结果; 
4、将物体的数学描述和相关的颜色信息转换为屏幕像素,这被称为光栅化。 
当我们把绘制的图形传递给OpenGL后,OpenGL还要做许多才能完成3D空间到屏幕的投影。这一系列的过程称为OpenGL渲染流水线。一般的渲染流水线过程有如下几步: 显示列表 求值程序 顶点操作 图元装配 像素操作 纹理装配 光栅化 片断操作

OpenGL工作流程图:

也可以简单的记为:

这是固定管线流程,但是其中顶点处理模块和片元处理模块对于应用程序来说都是可编程的

OpenGL建立三维模型的基本步骤 
从三维空间到二维平面,就如同用相机拍照一样,通常都要经历以下几个步骤(括号内表示的是相应的图形学概念) 
1 将相机置于三角架上,让它对准三维景物(视点变换,Viewing Transformation); 
2 将三维物体放在适当的位置(模型变换,Modeling Transformation ); 
3 选择相机镜头并调焦,使三维物体投影在二维胶片上(投影变换,Projection Transformation ); 
4 决定二维像片的大小(视口变换,Viewport Transformation )。 
这样,一个三维空间里的物体就可以用相应的二维平面物体表示了,也就能在二维的计算机屏幕上正确显示了。

二、 计算机图形学中,存在一种管线结构,在概念上可以分为3个阶段:应用程序、几何以及光栅。应用程序包括:图元数据遍历,摄像机的移动,物体模型的动画移动,物体可见检查,选择细节等级(LOD);几何主要包括:模型和视点变换,光照与着色,投影,裁减,屏幕映射;光栅为像素(Pixel)正确配色,以便绘制完整图像,该阶段进行的都是单个像素的操作,每个像素的信息存储在颜色缓冲器(color buffer或者frame buffer)中。值得注意的是:光照计算属于几何阶段,因为光照计算涉及视点、光源和物体的世界坐标,所以通常放在世界坐标系中进行计算;而雾化以及涉及物体透明度的计算属于光栅化阶段,因为上述两种计算都需要深度值信息(Z值),而深度值是在几何阶段中计算,并传递到光栅阶段的。
      3D世界的大多数高层次方面操作右管线中应用阶段的应用软件负责管理,余下的两个阶段由OpenGL负责管理,顶颜色,光照,材质三个输入在光栅化前控制绘制管线的操作。光照和材质不能单独使用。顶点颜色,光源颜色,材质颜色都有alpha值,它们的alpha经过运算最后会保存在光栅化后的图元 中,也就是说它们的影响也就在上图中红色虚线上方。输入是点(几何坐标、顶点颜色),矩阵,光照(光源,参数),材质,输出是片元。纹理映射的过程的本质是根据纹理信息对片元的再处理,这个过程可能改变片元的alpha值。输入是片元,纹理(纹理坐标、各种参数),输出还是片元。 Alpha值最终通过Alpha混合阶段影响绘制效果,输入时片元,输出是帧缓存颜色值。其管线流程如下图:

 

 

 





【顶装景投光 栅片 纹测混】

 

 

意思为:

:先在顶点处理器上计算每个顶点的属性(包括坐标,颜色,法向量,纹坐标,以及其他属性如反射方向,折射方向等属性)

:根据图元的装配方式(虚线,实线,线宽,多边形着色模式等参数)将顶点装配连接成各种图元

:根据设置好的透视视椎体,裁剪掉那些没有在视椎体中的顶点,他们不纳入计算)

:将视椎体中的景物投影到近裁面上,根据投影变换矩阵计算每个顶点的齐次投影坐标

:根据经典光照模型公式,光源的位置,顶点的位置,顶点的法向量,眼睛的位置综合计算每个点的光照颜色,光照公式自己去查)

 

至此:上面的这些阶段就是"顶点处理程序"的流程


然后是中间的
"栅片"阶段,意为让图形硬件根据扫描线"栅出"(即线性插值计算)每个片元的颜色和法向量,纹坐标,这个过程是不可编程的.我们无法控制.

 

下面是"片元处理程序阶段"

纹:指将纹理按照指定贴图方式(GL_MODULATE,GL_DECAL,GL_REPLACE)贴到每个片元上,计算出每个片元贴上纹理后的颜色

测:指对每个片元按顺序进行剪裁测试、alpha测试、模板测试、深度测试),所有测试通过的片元的颜色将写入帧缓冲区中到屏幕显示。

混:指在最后将片元颜色写入帧缓冲区中的时候根据指定的混色方案如glBlendFuncGL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)将片元颜色与帧缓冲区颜色混合,OK,整个渲染流程就此结束了。

 

总结:

1,在每对glBegin()与glEnd()之间即每个图元都要经过一个完整的渲染流程后才会执行到下一条语句去。因此,在此期间可以屏蔽各种硬件缓冲以实现特殊的效果。

2,光栅化阶段前面是顶点处理程序,后面是片元处理程序。但光栅栏化这个过程本身不可以自由控制。

opengl_api兼容模式

1.glDepthFunc();

The test function puts the incoming fragment's depth on the left of the equation and on the right is the depth from the depth buffer

物体的depth op  z buffer

 
2.

glPushAttrib(GL_ALL_ATTRIB_BITS);

    我们可以将多组属性或者全部属性(GL_ALL_ATTRIBUTE_BITS)通过函数glPushAttrib压入属性堆栈中,恢复则用glPopAttrib。

    glPushAttrib()保存由mask指定的所有属性,把它们压入到属性堆栈中。glPopAttrib()恢复上一次调用glPushAttrib()时所保存的状态变量的值。当glPopAttrib()函数被调用时,所有这些变量的值都被恢复。特殊掩码GL_ALL_ATTRIB_BITS用于保存和恢复所有属性组中的所有状态变量。

    我遇到的问题是添加某种物体时,物体的颜色会叠加到天空等物体上,使得天空颜色不正常显示。通过

glPushAttrib(GL_ALL_ATTRIB_BITS)和 glPopAttrib();一组代码,问题解决。



---------------------------------------  我不是分割线     ------------------------------------------------------------


OpenGL渲染管线包含一系列有序地处理数据的阶段。两种图形数据即基于顶点的数据和基于像素的数据,在渲染管线中处理并统一输出到帧缓冲区。注意,OpenGL可以将处理后的数据重新发送到你的程序中(注意下图中的灰色线条)。


OpenGL渲染管线




显示列表(Display List)

显示列表是一组已经被存储或编译过的的命令。所有的数据,几何数据和像素数据都可以被存储在显示列表中。它可以提升性能是由于所有的命令和数据都缓存在显示列表中。当OpenGL程序需要通过网络执行时,通过显示列表你可以减少数据在网络之间传输的次数。由于显示列表是服务器端的状态并且驻留在服务器端,客户端只需要将命令和数据发送一次到服务器端的显示列表中(更多详细的细节参考显示列表这章)。




顶点操作(Vertex Operation)

每个顶点和法向量坐标需要经过GL_MODELVIEW(模型视图矩阵,从物体坐标系到人眼坐标系)矩阵变换。同样地,如果光照状态开启,作用在每个顶点上的光照计算是使用变换后的顶点和法向量数据。光照计算会更新每个顶点的颜色(更多详细的细节参考变换这章)。




图元装配(Primitive Assembly)

顶点操作之后,图元(点,线,三角形)再次经过投影变换,然后经过裁剪平面裁剪,从人眼坐标系变换到裁剪坐标系。经过上述操作之后,再次经过透视除法和视口变换从而将三维的场景映射到窗口的区域坐标中。图元装配中最后要做的一件事就是如果裁剪状态开启则进行裁剪测试。




像素转换操作(Pixel Transfer Operation)

将像素数据从客户端内存中读取进来以后,数据会经过缩放,映射等一系列操作。这些操作叫做像素转换操作。转换后的数据被存储在纹理中或直接光栅化到片元中。




纹理内存(Texture Memory)

纹理图片被加载到纹理内存中以便应用到几何对象上。




光栅化(Raterization)

光栅化将几何数据和像素数据转换到片元中。片元是一种可以包含颜色,深度值,线宽,点大小和抗锯齿计算(GL_POINT_SMOOTH, GL_LINE_SMOOTH, GL_POLYGON_SMOOTH)的矩形数组。如果明暗模式是GL_FILL,那么多边形内部的像素将会在这个阶段被填充。每一个片元对于帧缓冲区中的一个像素。




片元操作(Fragment Operation)

这是将片元转换成要传输到帧缓冲区中的像素的最后一步。首先进行纹素生成;纹理元素通过纹理内存生成并且被应用到每一个片元。然后进行雾计算。接下来是一系列有序的片元测试操作:裁剪测试->alpha测试->模板测试->深度测试。

最后,经过混合,抖动,逻辑操作,遮挡这些操作实际的纹理数据被存储到帧缓冲区中。




反馈(Feedback)

OpenGL能通过glGet*()和glIsEnabled()命令返回大多数当前的状态和信息。除此之外,可以使用glReadPixels()函数从帧缓冲区中读取一个长方形区域的像素数据,使用glRenderMode(GL_FEEDBACK)函数得到变换后的顶点数据。glCopyPixels不会返回像素数据到指定的系统内存中,而是将他们复制到另一个缓冲区中,如将前台缓冲区中的像素数据复制到后台的缓冲区中。

0 0
原创粉丝点击