opengl 相关概念
一个固定流水线:
1,顶点变换(VertexTransformation)
这里一个顶点是一个信息集合,包括空间中的位置、顶点的颜色、法线、纹理坐标等。
通常进行如下工作:
·顶点位置变换
·为每个顶点计算光照
·纹理坐标的生成与变换
2,图元组合和光栅化(PrimitiveAssemblyandRasterization)
输入:是变换后的顶点和连接信息(connectivityinformation)。
输出:
·帧缓存中片断的位置
·在顶点变换阶段计算出的信息对每个片断的插值
连接信息告诉流水线顶点如何组成图元(三角形、四边形等)。
此阶段还负责视景体(viewfrustum)裁剪和背面剔除。
光栅化决定了片断(fragment),以及图元的像素位置。
片断是指一块数据,用来更新帧缓存(framebuffer)中特定位置的一个像素。
一个片断包含颜色,法线和纹理坐标等属性,这些信息用来计算新的像素颜色值。
这个阶段利用在顶点变换阶段算出的数据,结合连接信息计算出片断的数据。
3,片断纹理化和色彩化(FragmentTexturingandColoring)
输入:是经过插值的片断信息。
输出:是片断的颜色值以及深度信息。
插值得到的纹理坐标和一个颜色值,本阶段用来和纹理元素进行组合。
此外,这一阶段还可以进行雾化处理。
4,光栅操作(RasterOperations)
输入:像素位置和片断深度和颜色值
在这个阶段对片断进行一系列的测试,包括:
·剪切测试(scissortest)
·Alpha测试
·模版测试
·深度测试
如果测试成功,则根据当前的混合模式(blendmode)用片断信息来更新像素值。
取代固定的功能(ReplacingFixedFunctionality)
现在的显卡允许程序员自己编程实现上述流水线中的两个阶段:
·顶点shader实现顶点变换阶段的功能
·片断shader替代片断纹理化和色彩化的功能
顶点处理器用来运行顶点shader(着色程序)。
顶点shader的输入是顶点数据,即位置、颜色、法线等。
一个顶点shader可以编写代码实现如下功能:
·使用模型视图矩阵以及投影矩阵进行顶点变换
·法线变换及归一化
·纹理坐标生成和变换
·逐顶点或逐像素光照计算
·颜色计算
一旦你使用了顶点shader,顶点处理器的所有固定功能都将被替换。
顶点shader至少需要一个变量:gl_Position,通常要用模型视图矩阵以及投影矩阵进行变换。
顶点处理器并不知道连接信息,因此这里不能执行拓扑信息有关的操作。它只是操作顶点而不是面。
片断处理器可以运行片断shader,这个单元可以进行如下操作:
·逐像素计算颜色和纹理坐标
·应用纹理
·雾化计算
片断处理器的输入是顶点坐标、颜色、法线等计算插值得到的结果。
片断处理器只对每个片断独立进行操作,并不知道相邻片断的内容。
一个片断shader有两种输出:
·抛弃片断内容,什么也不输出
·计算片断的最终颜色gl_FragColor,当要渲染到多个目标时计算gl_FragData。
片断shader不能访问帧缓存,所以混合(blend)这样的操作只能发生在这之后。
每个shader类似一个C模块,首先需要单独编译(compile),然后一组编译好的shader连接(link)成一个完整程序。
glCreateProgram()
glAttachShader()
glAttachShader()
glLinkProgram()
glUseProgram()
VBO是VertexBufferObject,用于存储顶点坐标/顶点uv/顶点法线/顶点颜色
VBO其实就是显卡中的显存,将要绘制的顶点数据缓存在显存中,这样就不需要将要绘制的顶点数据重复从CPU发送到GPU。
IBO为索引缓冲区
VAO是VertexArrayObject
VAO则是一个容器,可以包括多个VBO,它类似于以前的calllist,由于它进一步将VBO容于其中,所以绘制效率将在VBO的基础上更进一步。
取代以前的glBegin/glEnd,显示列表,顶点数组。
最后用VAO将多个VBO,IBO绑定到一起。
一个常规的网格模型就是VAO.attach(PositionVBO,TexcoordVBO,NormalVBO,IBO)
以下为VBO的创建,分配100字节的空间,未初始化:
GLuintvbo;
glGenBuffers(1,&vbo);
glBindBuffer(GL_ARRAY_BUFFER,vbo);
glBufferData(GL_ARRAY_BUFFER,100,0,GL_STATIC_DRAW);
以下为IBO的创建,分配100字节的空间,未初始化:
GLuintibo;
glGenBuffers(1,&ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,100,0,GL_STATIC_DRAW);
以下为VAO的创建:
GLuintvao;
glGenVertexArrays(1,&vao);
glBindVertexArray(vao);
向VBO提交数据,无论提交全部还是部分都用这个,ibo类似
glBindBuffer(GL_ARRAY_BUFFER,vbo);
glBufferSubData(GL_ARRAY_BUFFER,size,len,src);
MapBuffer和BufferSubData/BufferData同样是向server端“提交”数据,但是方法却是截然不同的。MapBuffer通过cilent端映射server端的数据存储,然后范围一个映射到客户端内存的指针,这时候你进行的工作是一种CPU_write/CPU-read的工作;而BufferSubData/BufferData则是一种GPU-read的过程,两者是很大的差距的。
当数据量比较小的时候,BufferSubData是远远超过MapBuffer的效率的,但是当数据足够大的时候,MapBuffer会压倒性的超越BufferSubData,据测试这个值大概是32k
参考:
http://blog.csdn.net/racehorse/article/details/6593719
http://www.cnblogs.com/eggine/archive/2012/12/07/2807245.html