原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78671396
《OpenGL学习笔记》系列博客目录地址:http://blog.csdn.net/qq21497936/article/category/7315532
OpenGL学习笔记(二):OpenGl语法、渲染管线以及具体实现过程详解
前话
前面介绍了OpenGL的环境搭建和基本使用,正式进入系统的学习OpenGL,本节主要介绍OpenGL技术的具体实现过程。
《OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用》
地址: http://blog.csdn.net/qq21497936/article/details/78660326
OpenGL的实现形式
OpenGL时使用客户端-服务端的形式实现的,我们编写的应用程序可以看作客户端,而计算机图形硬件厂商提供的OpengGL实现可以看服务器端。某些实现甚至可以允许服务器和客户端在一个网络内的不同计算机上运行。
OpenGL语法
以字符”gl”开头的函数,OpenGL库中所有的原生函数前缀,然后是一个或多个大写字母开头的词组,以此来命名一个完整的函数(例如glBindVertexArray())。
以“glut”开头的函数,它们来自第三方库OpenGL Utility Toolkit(GLUT),这是一个非常流行的跨平台库。
以”glew”开头的函数,只有一个glewInit(),它来自第三库OpenGL Extension Wrangler。
以“GL_”开头的常量,如GL_COLOR_BUFFER_BIT,所有常量都以GL_作为前缀,并且使用下划线来分隔。
为了跨平台兼容,其专门定义了gl数据类型。
函数名称后缀不同,代表了传入的参数,如glUniform*()的函数,它有多种变化形式,glUniform2f和glUniform3f,在函数名称核心之后的2和3代表传入2个参数或者3个参数,f字符代表参数都是Glflaot类型。对于glUnifrom2fv,后面多了一个v,它是vector的缩写,即表示我们需要用一个1维的Glfloat数组来传入2个浮点数值。
openGL专有名词
渲染(render)
光线跟踪(ray tracing)
模型(model)
顶点(vertex)
着色器(shader)
着色阶段(shader stage)
顶点着色器(vertex shader)
纹理映射(texture mapping)
像素(pixel)
帧缓存(framebuffer)
视口(viewport)
剪切(clipping)
变换矩阵(transfromation matrix)
深度测试(depth test Or z-buffering)
模版测试(stencil test)
细分着色器(tessellation shader)
片元的丢弃(discard):我们觉得不应该继续绘制某个片元,在片元着色器中终止这个片元的处理。
融合(blending)
OpenGL程序阶段划分
- 第一阶段:构建形状,从OpengGL的几何图元中设置数据,用于构建形状;
- 第二阶段:着色器(shader),使用不同的着色器对输入的图元数据执行计算操作,判断他们的位置、颜色,以及其他渲染属性;
- 第三阶段:光栅化,将输入的图片的数据描述转换为与屏幕位置对应的像素片元(fragment);
- 第四阶段:片元着色器,针对光栅化过程产生的每个片元,执行片元着色器(fragment shader),从而决定这个片元的最终颜色和位置;
- 第五阶段(可选):补充操作,若有必要可对每个片元执行一些额外操作,例如判断片元对应的对象是否可见,或者将片元的颜色与当前屏幕位置的颜色进行融合。
OpenGl管线图
着色器作用简图
OpengGL程序实现过程(对应阶管线图)
定义数据(顶点数据)
OpenGL需要将所有的数据都保存到缓存对象(buffer object)中,它相当于OpenGL服务端维护的一块内存区域,我们可以使用多种方式来创建这样的数据缓存,不过最常用的是glBufferData(),示例:
GLfloat vertices[NumVertices][2] = { { -0.90, -0.90 }, // Triangle 1 { 0.85, -0.90 }, { -0.90, 0.85 }, { 0.90, -0.85 }, // Triangle 2 { 0.90, 0.90 }, { -0.85, 0.90 } }; glGenBuffers(NumBuffers, Buffers); glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
将数据传输到OpenGL
当缓存完毕后,我们可以通过调用OpenGL的一个绘制命令来请求渲染几何图元,如glDrawArrays(),示例:
glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(VAOs[Triangles]); glDrawArrays(GL_TRIANGLES, 0, NumVertices); glFlush();
顶点着色
对于绘制命令传输的每个顶点,OpenGL都会调用一个顶点着色器(vertex shader)来处理顶点相关的数据。一个程序可以包含多个顶点着色器,但是同一时刻,只能有一个顶点作色器起作用。
细分着色(可选)
顶点着色器处理每个顶点的关联数据之后,如果同时激活了细分着色器(tessellation shader),那么它将进一步处理这些数据。细分着色器可能会使用Patch 来描述一个物体的形状,并且使用相对简单的Patch 几何体连接来完成细分的工作,其结果是几何图元的数量增加,并且模型的外观会变得更为平顺。细分着色阶段会用到两个着色器来分别管理Patch 数据并生成最终的形状。
几何着色(可选)
允许在光栅化之前对每个几何图元做更进一步的处理,例如创建新的图元。其非常强大。
图元装配
着色阶段所处理的都是顶点数据,此外这些顶点之间如何构成几何图元的所有信息也会被传递到OpenGL 当中。图元装配阶段将这些顶点与相关的几何图元之间组织起来,准备下一步的剪切和光栅化工作。
剪切
顶点可能会落在视口(viewport)之外—也就是我们可以进行绘制的窗口区域—此时与顶点相关的图元会做出改动,以保证相关的像素不会在视口外绘制。这一过程叫做剪切(clipping),它是由 OpenGL 自动完成的。
光栅化
剪切之后马上要执行的工作,就是将更新后的图元传递到光栅化单元,生成对应的片元。我们可以将一个片元视为一个“候选的像素”,也就是可以放置在帧缓存中的像素,但是它也可能被最终剔除,不再更新对应的像素位置。之后的两个阶段将会执行片元的处理,即片元着色和逐片元的操作。
片元着色
该阶段是通过编程控制屏幕上显示颜色的阶段,我们使用着色器来计算片元的最终原色。
逐片元的操作
最后的独立片元处理过程,在这个阶段里会使用深度测试(depthtest,或者通常也称作z-buffering)和模板测试(stencil test)的方式来决定一个片元是否是可见的。如果一个片元成功地通过了所有激活的测试,那么它就可以被直接绘制到帧缓存中了,它对应的像素的颜色值(也可能包括深度值)会被更新,如果开启了融合(blending)模式,那么片元的颜色会与该像素当前的颜色相叠加,形成一个新的颜色值并写入帧缓存中。
原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78671396