OpenGL超级宝典笔记----渲染管线

  在OpenGL中任何事物都在3D空间中,但是屏幕和窗口是一个2D像素阵列,所以OpenGL的大部分工作都是关于如何把3D坐标转变为适应你屏幕的2D像素。3D坐标转为2D坐标的处理过程是由OpenGL的图形渲染管线完成的。图像渲染管线可以被划分为两个主要部分:第一个部分把你的3D坐标转换为2D坐标,第二部分是把2D坐标转变为实际的有颜色的像素。

  渲染管线接收一组3D坐标,然后把它们转变为你屏幕上的有色2D像素。渲染管线可以被划分为几个阶段,每个阶段需要把前一阶段的输出作为输入。所有这些阶段都是高度专门化的,它们能简单地并行执行。由于它们的并行执行的特征,当今大多数显卡都有成千上万的小处理核心GPU,在GPU上为每一个阶段运行各自的小程序,从而在图形输送管道中快速处理你的数据。这些小程序叫做着色器。有些着色器允许开发者自己配置,用我们自己写的着色器替换默认存在的。这样我们就可以更细致地控制渲染管线的特定部分,因为它们运行在GPU上,所以它们也会节约宝贵的CPU时间。着色器是用OpenGL着色器语言(OpenGL Shading Language)GLSL写成的。

  下图显示了渲染管线中各个阶段主要完成的工作,蓝色部分代表的是我们可以定义自己的着色器。

  在上图中,我们以数组的形式传递3个3D坐标作为渲染管线的输入,用它来表示一个三角形,这个数组叫做顶点数据(Vertex Data);这里顶点数据是几个顶点的集合。每个顶点是用顶点属性(vertex attributes)表示的,它可以包含任何我们希望用的数据,下面我们来看看渲染管线中各个阶段主要完成的工作:

  • 渲染管线的第一个部分是顶点着色器(vertex shader),它把一个单独的顶点作为输入。顶点着色器主要的目的是把3D坐标转为另一种3D坐标(投影坐标),同时顶点着色器允许我们对顶点属性进行一些基本处理。
  • 图元组装(primitive assembly)阶段把顶点着色器的表示为基本图形的所有顶点作为输入,把所有点组装为特定的基本图形的形状;上图中是一个三角形。
  • 图元组装阶段的输出会传递给几何着色器(geometry shader)。几何着色器把基本图形形成的一系列顶点的集合作为输入,它可以通过产生新顶点构造出新的(或是其他的)基本图形来生成其他形状。
  • 细分着色器(tessellation shaders)拥有把给定基本图形细分为更多小基本图形的能力。这样我们就能在物体更接近玩家的时候通过创建更多的三角形的方式创建出更加平滑的视觉效果。
  • 细分着色器的输出会进入光栅化(rasterization)阶段,这里它会把基本图形映射为屏幕上相应的像素,生成供像素着色器(fragment shader)使用的fragment(OpenGL中的一个fragment是OpenGL渲染一个独立像素所需的所有数据。)。在像素着色器运行之前,会执行裁切(clipping)。裁切会丢弃超出你的视图以外的那些像素,来提升执行效率。
  • 像素着色器的主要目的是计算一个像素的最终颜色,这也是OpenGL高级效果产生的地方。通常,像素着色器包含用来计算像素最终颜色的3D场景的一些数据(比如光照、阴影、光的颜色等等)。
  • 在所有相应颜色值确定以后,最终它会传到另一个阶段,我们叫做alpha测试和混合(blending)阶段。这个阶段检测像素的相应的深度(和stencil)值,使用这些来检查这个像素是否在另一个物体的前面或后面,如此做到相应取舍。这个阶段也会查看alpha值(alpha值是一个物体的透明度值)和物体之间的混合(blend)。所以即使在像素着色器中计算出来了一个像素所输出的颜色,最后的像素颜色在渲染多个三角形的时候也可能完全不同。

  虽然渲染管线有多个阶段,每个阶段都需要对应的着色器,但其实对于大多数场合,我们必须做的只是顶点和像素着色器,几何着色器和细分着色器是可选的,通常使用默认的着色器就行了。现在的OpenGL中,我们必须定义至少一个顶点着色器和一个像素着色器(因为GPU中没有默认的顶点/像素着色器)。

时间: 2024-12-11 06:33:26

OpenGL超级宝典笔记----渲染管线的相关文章

OpenGL超级宝典笔记——深度纹理和阴影 【转】

目录[-] 光源视角 新型的纹理 深度纹理的大小 首先绘制阴影 然后是光照 投影阴影贴图 阴影比较 之前我们介绍过简单的把物体压平到投影平面来制造阴影.但这种阴影方式有其局限性(如投影平面须是平面).在OpenGL1.4引入了一种新的方法阴影贴图来产生阴影. 阴影贴图背后的原理是简单的.我们先把光源的位置当作照相机的位置,我们从这个位置观察物体,我们就知道哪些物体的表面是被照射到(被光源看到) 的,哪些是没有被照射到(被遮挡住)的(在某个方向上离光源最近的表面是被照射的,后面的表面则没有被照射到

OpenGL超级宝典笔记——遮挡查询 [转]

目录[-] 遮挡查询之前 包围体 遮挡查询 在一个场景中,如果有有些物体被其他物体遮住了不可见.那么我们就不需要绘制它.在复杂的场景中,这可以减少大量的顶点和像素的处理,大幅度的提高帧率.遮挡查询就是允许我们判断一组图形在进行了深度测试之后是否可见. 遮挡查询之前 为了显示遮挡查询对性能的提升,我们需要一个对照组(不使用遮挡查询来渲染场景). 首先我们先绘制“主遮挡物”.这个主遮挡物不需要太多的细节,一般是墙,天花板,地板之类的物体.在下面的例子中我们,使用6面墙来组成这个主遮挡物. void 

【转载】OpenGL超级宝典笔记——GLSL语言基础

变量 GLSL的变量命名方式与C语言类似.变量的名称可以使用字母,数字以及下划线,但变量名不能以数字开头,还有变量名不能以gl_作为前缀,这个是GLSL保留的前缀,用于GLSL的内部变量.当然还有一些GLSL保留的名称是不能够作为变量的名称的. 基本类型 除了布尔型,整型,浮点型基本类型外,GLSL还引入了一些在着色器中经常用到的类型作为基本类型.这些基本类型都可以作为结构体内部的类型.如下表: 类型 描述 void 跟C语言的void类似,表示空类型.作为函数的返回类型,表示这个函数不返回值.

OpenGL超级宝典笔记二 - 基础变换

1.向量: 点乘:float m3dDotProduce3(u,v):返回两个单位向量的余弦值 叉乘:float m3dCrossProduct3(result,u,v):返回垂直于两个向量定义的平面的向量 2.矩阵: OpenGL使用的是列优先排序的矩阵 单位矩阵(对角线为1,其他为0):任何向量乘以一个单位矩阵都不会发生任何改变 3.变换:最终获得的变换矩阵会应用到每个顶点 视图矩阵x模型矩阵x投影矩阵->投影摄像机的位置变换,物体对象的位置变换,投影裁剪变换 若顶点向量为Vert,则变换公

OpenGL超级宝典笔记——贝塞尔曲线和曲面(转)

http://my.oschina.net/sweetdark/blog/183721 参数方程表现形式 在中学的时候,我们都学习过直线的参数方程:y = kx + b;其中k表示斜率,b表示截距(即与y轴的交点坐标).类似地,我们也可以用一个参数方程来表示一条曲线.1962年,法国工程师贝塞尔发明了贝塞尔曲线方程.关于贝塞尔曲线的详细介绍可以参考(维基贝塞尔).这里只介绍OpenGL实现贝塞尔的函数. OpenGl定义一条曲线时,也把它定义为一个曲线方程.我们把这条曲线的参数成为u,它的值域就

OpenGL超级宝典笔记三 - 基础纹理1

纹理对象的使用:纹理图像数据的类型,图像数据的导入导出方式,纹理的使用过程:图像数据的加载,纹理参数的设置,纹理的绑定. 一.图像数据的分类:位图图像和像素图像 二.像素图像数据的包装: 在OpenGL中:使用4字节的行对齐方式,每一行补全到4的倍数,使用glPixelStorei(pname,param)可以改变或者恢复像素的存储方式 介绍常用的两组:内存<->缓冲区的压缩和解包 glPixcelStorei(GL_UNPACK_ALIGNMENT) ----图像数据从内存到缓冲区的解包设置

OpenGL超级宝典笔记——画三角形(转)

http://my.oschina.net/sweetdark/blog/161002 学习了画线的知识,我们可以使用GL_LINE_LOOP来画闭合的多边形.但是使用这种方式画出来的只有线框,多边形没有填充颜色.OpenGL支持绘制实心的多边形,并使用当前的颜色进行填充. 三角形 简单的三角形,需要指定三个顶点. 1: glBegin(GL_TRIANGLES); 2: glVertex2f(0.0f, 0.0f); // V0 3: glVertex2f(25.0f, 25.0f); //

OpenGL超级宝典笔记四 - 基础纹理2

一.使用MipMap贴图(主要是应用在纹理缩小过滤中) 优点: 防止当纹理缩小太大的时候,出现闪烁的问题 提高性能,需要缩小的时候就不加载大内存的纹理 缺点: 需要额外的内存作为代价 组成:由一系列缩小的纹理图像组成,子层是父层的1/4 过滤类型:NEAREST快速,LINEAR效果好 GL_NEAREST_MINMAP_NEAREST选择最邻近Mip层并执行邻近过滤 GL_NEAREST_MINMAP_LINEAR选择最Mip层线性插补并执行邻近过滤 GL_LINEAR_MINMAP_NEAR

OpenGL超级宝典笔记一 - 基础渲染

1.渲染中的双缓冲: 使用但缓冲的时候,在渲染每一帧的绘图时,会对画板进行擦除然后在慢慢填充绘制,如果绘制时间过长的时候,就会出现闪烁的现象.为解决这个问题,所以引入双缓冲 双缓冲相当于,在显示的画板中重新创建另外一个画板,绘制的过程在另外的画板进行,绘制完成之后,将显示的画板的内容直接替换成另外一个画板的内容.这样呈现的过程中就不会出现闪烁的问题,即使是绘制的过程比较慢,最多就是出现顿的现象 在例子中渲染的RenderScene()函数中,每次渲染结束之后都会调用glutSwapBuffers