OpenGL/3D图形渲染管线
来源:互联网 发布:淘宝秒杀抢拍器手机版 编辑:程序博客网 时间:2024/06/08 06:41
http://blog.csdn.NET/shenzi/article/details/5417488
一.顶点变换(Vertex Transformation):
顶点变换是图形硬件渲染管线种的第一个处理阶段。顶点变换在每个顶点上执行一系列的数学操作。这些操作包括把顶点位置变换到屏幕位置以便光栅器使用,为贴图产生纹理坐标,以及照亮顶点以决定它的颜色。
坐标系统:
应用程序在一个被称为物体空间(也叫模型空间)的坐标系统里指定顶点位置。当一个美工人员创建了一个物体的三维模型的时候,他选择了一个方便的方向、比例和位置来放置模型的组成顶点。一个物体的物体空间可以与其它物体的物体空间没有任何关系。
世界空间:
一个物体的物体空间和其它对象没有空间上的关系。世界空间的目的是为在你的场景中的所有物体提供一个绝对的参考。一个世界空间坐标系如何建立可以任意选择。例如:你可以决定世界空间的原点是你房间的中心。然户,房间里的物体就可以相对房间的中心和某个比例和某个方向放置了。
建模变换:
在物体空间中指定的物体被放置到世界空间的方法要依靠建模变换。例如:你也许需要旋转、平移和缩放一个椅子的三维模型,以使椅子可以正确地放置在你的房间的世界坐标系统里。在同一个房间中的两把椅子可以使用同样的三维椅子模型,但使用不同的建模变换,以使每把椅子放在房间中不同的位置。
眼空间:
最后,你要从一个特殊的视点(“眼睛”)观看你的场景。在称为眼空间(或视觉空间)的坐标系统里,眼睛位于坐标系统的原点。朝“上”的方向通常是轴正方向。遵循标准惯例,你可以确定场景的方向使眼睛是从z轴向下看。
视变换:
从世界空间位置到眼空间位置的变换时视变换。典型的视变换结合了一个平移把眼睛在世界空间的位置移到眼空间的原点,然后适当地旋转眼睛。通过这样做,视变换定义了视点的位置和方向。
我们通常把分别代表建模和视变换的两个矩阵结合在一起,组成一个单独的被称为modelview的矩阵。你可以通过简单地用建模矩阵乘以视矩阵把它们结合在一起。
剪裁空间:
当位置在眼空间以后,下一步是决定什么位置是在你最终要渲染的图像中可见的。在眼空间之后的坐标系统被称为剪裁空间,在这个空间中的坐标系统称为剪裁坐标。
投影变换:
从眼空间坐标到剪裁空间的变换被称为投影变换。投影变换定义了一个事先平截体(view frustum),代表了眼空间中物体的可见区域。只有在视线平截体中的多边形、线段和点背光栅化到一幅图形中时,才潜在的有可能被看得见。
标准化的设备坐标:
剪裁坐标是齐次形式<x,y,z,w>的,但我们需要计算一个二维位置(一对x和y)和一个深度值(深度值是为了进行深度缓冲,一种硬件加速的渲染可见表面的方法)。
透视除法:
用w除x,y和z能完成这项工作。生成的结果坐标被称为标准化的设备坐标。现在所有的几何数据都标准化为[-1,1]之间。
窗口坐标:
最后一步是取每个顶点的标准化的设备坐标,然后把它们转换为使用像素度量x和x的最后的坐标系统。这一步骤命名为视图变换,它为图形处理器的光栅器提供数据。然后光栅器从顶点组成点、线段或多边形,并生成决定最后图像的片段。另一个被称为深度范围变换的变换,缩放顶点的z值到在深度缓冲中使用的深度缓存的范围内。
当一个图元被光栅化为一堆零个或多个片段的时候,插值、贴图和着色阶段就在片段属性需要的时候插值,执行一系列的贴图和数学操作,然后为每个片段确定一个最终的颜色。除了确定片段的最终颜色,这个阶段还确定一个新的深度,或者甚至丢弃这个片段以避免更新帧缓存对应的像素。允许这个阶段可能丢弃片段,这个阶段为它接收到的每个输入片段产生一个或不产生着过色的片段。
图形渲染管线(Pipeline)
图形渲染管线指的是对一些原始数据经过一系列的处理变换并最终把这些数据输出到屏幕上的整个过程。
图形渲染管线的整个处理流程可以被划分为几个阶段,上一个阶段的输出数据作为下一个阶段的输入数据,是一个串行的,面向过程的执行过程。每一个阶段分别在GPU上运行各自的数据处理程序,这个程序就是着色器。
部分着色器允许我们使用着色语言(OpenGL Shading Language)编写自定义的着色器,这样就可以更为细致的控制图像渲染流程中的特定处理过程了,下图是一个图形渲染管线每一个阶段的抽象表示,蓝色部分代表允许自定义着色器。
顶点数据是一些顶点的集合,顶点一般是3维的点坐标组成。
基本图元(Primitives)包括点,线段,三角形等,是构成实体模型的基本单位,需要在传入顶点数据的同时通知OpenGL这些顶点数据要组成的基本图元类型。
顶点着色器(Vertex Shader)包含对一些顶点属性(数据)的基本处理。
基本图元装配(Primitive Assembly)把所有输入的顶点数据作为输入,输出制定的基本图元。
几何着色器(Geometry Shader)把基本图元形式的顶点的集合作为输入,可以通过产生新顶点构造出新的(或是其他的)基本图元来生成其他形状。
细分着色器(Tessellation Shaders)可以把基本图元细分为更多的基本图形,创建出更加平滑的视觉效果。
光栅化(Rasterization)即像素化,把细分着色器输出的基本图形映射为屏幕上网格的像素点,生成供片段着色器处理的片段(Fragment),光栅化包含一个剪裁操作,会舍弃超出定义的视窗之外的像素。
片段着色器(Fragment Shader)的主要作用是计算出每一个像素点最终的颜色,通常片段着色器会包含3D场景的一些额外的数据,如光线,阴影等。
测试与混合是对每个像素点进行深度测试,Alpha测试等测试并进行颜色混合的操作,这些测试与混合操作决定了屏幕视窗上每个像素点最终的颜色以及透明度。
在整个渲染管线中需要自定义处理的主要是顶点着色器和片段着色器。
顶点缓冲对象(Vertex Buffer Objects,VBO)
顶点缓冲对象VBO是在显卡存储空间中开辟出的一块内存缓存区,用于存储顶点的各类属性信息,如顶点坐标,顶点法向量,顶点颜色数据等。在渲染时,可以直接从VBO中取出顶点的各类属性数据,由于VBO在显存而不是在内存中,不需要从CPU传输数据,处理效率更高。
所以可以理解为VBO就是显存中的一个存储区域,可以保持大量的顶点属性信息。并且可以开辟很多个VBO,每个VBO在OpenGL中有它的唯一标识ID,这个ID对应着具体的VBO的显存地址,通过这个ID可以对特定的VBO内的数据进行存取操作。
VBO的创建以及配置
创建VBO的第一步需要开辟(声明/获得)显存空间并分配VBO的ID:
创建的VBO可用来保存不同类型的顶点数据,创建之后需要通过分配的ID绑定(bind)一下制定的VBO,对于同一类型的顶点数据一次只能绑定一个VBO。绑定操作通过glBindBuffer来实现,第一个参数指定绑定的数据类型,可以是GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, GL_PIXEL_PACK_BUFFER或者GL_PIXEL_UNPACK_BUFFER中的一个。
接下来调用glBufferData把用户定义的数据传输到当前绑定的显存缓冲区中。
顶点数据传入GPU之后,还需要通知OpenGL如何解释这些顶点数据,这个工作由函数glVertexAttribPointer完成:
- 第一个参数指定顶点属性位置,与顶点着色器中layout(location=0)对应。
- 第二个参数指定顶点属性大小。
- 第三个参数指定数据类型。
- 第四个参数定义是否希望数据被标准化。
- 第五个参数是步长(Stride),指定在连续的顶点属性之间的间隔。
- 第六个参数表示我们的位置数据在缓冲区起始位置的偏移量。
顶点属性glVertexAttribPointer默认是关闭的,使用时要以顶点属性位置值为参数调用glEnableVertexAttribArray开启。如glEnableVertexAttribArray(0);
顶点数组对象(Vertex Arrary Object,VAO)
VBO保存了一个模型的顶点属性信息,每次绘制模型之前需要绑定顶点的所有信息,当数据量很大时,重复这样的动作变得非常麻烦。VAO可以把这些所有的配置都存储在一个对象中,每次绘制模型时,只需要绑定这个VAO对象就可以了。
VAO是一个保存了所有顶点数据属性的状态结合,它存储了顶点数据的格式以及顶点数据所需的VBO对象的引用。
VAO本身并没有存储顶点的相关属性数据,这些信息是存储在VBO中的,VAO相当于是对很多个VBO的引用,把一些VBO组合在一起作为一个对象统一管理。
VAO的创建和配置
生成一个VAO对象并绑定:
执行VAO绑定之后其后的所有VBO配置都是这个VAO对象的一部分,可以说VBO是对顶点属性信息的绑定,VAO是对很多个VBO的绑定。
OpenGL中所有的图形都是通过分解成三角形的方式进行绘制,glDrawArrays函数负责把模型绘制出来,它使用当前激活的着色器,当前VAO对象中的VBO顶点数据和属性配置来绘制出来基本图形。
第一个参数表示绘制的类型,有三种取值:
- 1.GL_TRIANGLES:每三个顶之间绘制三角形,之间不连接;
- 2.GL_TRIANGLE_FAN:以V0V1V2,V0V2V3,V0V3V4,……的形式绘制三角形;
- 3.GL_TRIANGLE_STRIP:顺序在每三个顶点之间均绘制三角形。这个方法可以保证从相同的方向上所有三角形均被绘制。以V0V1V2,V1V2V3,V2V3V4……的形式绘制三角形;
第二个参数定义从缓存中的哪一位开始绘制,一般定义为0;
第三个参数定义绘制的顶点数量;
索引缓冲对象(Element Buffer Object,EBO)
索引缓冲对象EBO相当于OpenGL中的顶点数组的概念,是为了解决同一个顶点多洗重复调用的问题,可以减少内存空间浪费,提高执行效率。当需要使用重复的顶点时,通过顶点的位置索引来调用顶点,而不是对重复的顶点信息重复记录,重复调用。
EBO中存储的内容就是顶点位置的索引indices,EBO跟VBO类似,也是在显存中的一块内存缓冲器,只不过EBO保存的是顶点的索引。
创建EBO并绑定,用glBufferData(以GL_ELEMENT_ARRAY_BUFFER为参数)把索引存储到EBO中:
当用EBO绑定顶点索引的方式绘制模型时,需要使用glDrawElements而不是glDrawArrays:
- 第一个参数指定了要绘制的模式;
- 第二个参数指定要绘制的顶点个数;
- 第三个参数是索引的数据类型;
- 第四个参数是可选的EBO中偏移量设定。
Talk is cheap,第一个例子是使用VBO,VAO绘制一个矩形图形:
编译并执行:
第二个例子使用EBO绘制两个三角形,组成同样的矩形图形:
效果一样:
- OpenGL/3D图形渲染管线
- OpenGL/3D图形渲染管线
- 3D图形渲染管线
- 3D图形渲染管线
- 3D图形渲染管线
- 3D图形渲染管线
- 3D图形渲染管线
- 3D图形渲染管线
- 3D图形渲染管线
- 3D图形渲染管线
- 3D图形渲染管线 (转)
- (一) 3D图形渲染管线
- OPENGL固定图形渲染管线
- OpenGL图形渲染管线图解
- 3D渲染管线
- 3D渲染管线
- 3D渲染管线
- 3D图形技术概念和渲染管线的处理
- 像数组一样使用NodeList:一个对象组合的有效用法
- 51nod 1003 阶乘后面0的数量
- BZOJ 1618: [Usaco2008 Nov]Buying Hay 购买干草
- 摘要: Druid连接池一个设置引发的血案 -- 链接池出现问题
- 搜狐笔试:Kolakoski sequence
- OpenGL/3D图形渲染管线
- idea 配置Tomcat(非Maven项目)
- Android事件分发机制(一)
- Web项目的 UI 自动化测试方案
- Java安全学习笔记(七)-攻击消息摘要保存的口令
- 面试总结
- java根据当前时间获取前一个月的日期组成List
- Linux下的基本网络配置
- Android 的约定命名