opengl 相关概念

一个固定流水线:
1, 顶点变换(Vertex Transformation)
    这里一个顶点是一个信息集合,包括空间中的位置、顶点的颜色、法线、纹理坐标等。
   通常进行如下工作:
   ·顶点位置变换
   ·为每个顶点计算光照
   ·纹理坐标的生成与变换

2, 图元组合和光栅化(Primitive Assembly and Rasterization)
    输入:是变换后的顶点和连接信息(connectivity information)。
     输出:
    ·帧缓存中片断的位置
    ·在顶点变换阶段计算出的信息对每个片断的插值

    连接信息告诉流水线顶点如何组成图元(三角形、四边形等)。
    此阶段还负责视景体(view frustum)裁剪和背面剔除。
   
     光栅化决定了片断(fragment),以及图元的像素位置。
   
    片断是指一块数据,用来更新帧缓存(frame buffer)中特定位置的一个像素。
     一个片断包含颜色,法线和纹理坐标等属性,这些信息用来计算新的像素颜色值。

    这个阶段利用在顶点变换阶段算出的数据,结合连接信息计算出片断的数据。

3,  片断纹理化和色彩化(Fragment Texturing and Coloring)
    输入:是经过插值的片断信息。
    输出: 是片断的颜色值以及深度信息。
    插值得到的纹理坐标和一个颜色值,本阶段用来和纹理元素进行组合。
    此外,这一阶段还可以进行雾化处理。

4,光栅操作(Raster Operations)
    输入:  像素位置 和 片断深度和颜色值
   
     在这个阶段对片断进行一系列的测试,包括:
     ·剪切测试(scissor test)
     ·Alpha测试
     ·模版测试
     ·深度测试
      如果测试成功,则根据当前的混合模式(blend mode)用片断信息来更新像素值。

取代固定的功能(Replacing Fixed Functionality)
现在的显卡允许程序员自己编程实现上述流水线中的两个阶段:
  ·顶点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是Vertex Buffer Object, 用于存储顶点坐标/顶点uv/顶点法线/顶点颜色
VBO其实就是显卡中的显存,将要绘制的顶点数据缓存在显存中,这样就不需要将要绘制的顶点数据重复从CPU发送到GPU。

IBO为索引缓冲区

VAO是Vertex Array Object
VAO则是一个容器,可以包括多个VBO,  它类似于以前的call list, 由于它进一步将VBO容于其中,所以绘制效率将在VBO的基础上更进一步。

取代以前的glBegin/glEnd,显示列表,顶点数组。

最后用VAO将多个VBO,IBO绑定到一起。
一个常规的网格模型就是VAO.attach(PositionVBO,TexcoordVBO,NormalVBO,IBO)

以下为VBO的创建,分配100字节的空间,未初始化:

GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER,100,0,GL_STATIC_DRAW);

以下为IBO的创建,分配100字节的空间,未初始化:

GLuint ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,100,0,GL_STATIC_DRAW);

以下为VAO的创建:

GLuint vao;
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

猜你喜欢

转载自catdoc.iteye.com/blog/2067373
今日推荐