GLSL
http://blog.csdn.net/racehorse/article/details/6634830
https://learnopengl-cn.readthedocs.org/zh/latest/04%20Advanced%20OpenGL/08%20Advanced%20GLSL/
http://blog.csdn.net/xiajun07061225/article/details/7628146
http://blog.csdn.net/silangquan/article/details/9674371
http://www.cnblogs.com/eggine/archive/2012/12/07/2807245.html
https://www.zhihu.com/question/30095978
http://www.xuebuyuan.com/2073294.html
http://www.jianshu.com/p/1c3d15cb2ea7
https://zh.wikipedia.org/wiki/GLSL
0 VBO
“客户端状态”和“服务端状态”
从VBO的作用说起吧。VBO出现的背景是人们发现VA还有不让人满足的地方。一般,在OpenGL里,提高顶点绘制速度的手法,一是把常规的glBegin() - glEnd()类代码段放入一个显示列表中(通常在初始化阶段完成),然后每遍渲染都调用这个显示列表;二是使用顶点数组,把顶点以及顶点属性数据作为数组,渲染的时候直接用一个或几个函数调动这些数组里的数据进行绘制,形式上是减少函数调用的次数(glVertex再见),提高绘制效率。但是这两种方法都有缺点。在说这个之前,应该对“客户端状态”和“服务端状态”两个名词有点了解。
OpenGL是个状态机,我们通常见到的glEnable - glDisable函数就是通知OpenGL开启/关闭某种状态的,譬如光照、深度检测等等。但是也有glEnableClientState - glDisableClientState这对。它们的区别是通知的具体对象在概念上不一样——分别是服务端和客户端。事实上我也无法很清楚地告诉你区别之处,反正你把你电脑上的具体程序,包括它用到的内存等等看作客户端,把你电脑里面的——显卡里的OpenGL“模块”,乃至整张拥有OpenGL流水线、硬件实现OpenGL功能的显卡,作为服务端。它们各自维护一些“状态”,glEnable 等是直接维护流水线处理相关的状态的,glEnableClientState 维护的则是进入流水线前的状态。流水线早期的T&L阶段,程序的顶点数据就被获知而接受处理了。至于顶点是怎么来的——是glVertex来的,还是glDrawArray来的,流水线没必要知道——这就是客户端的任务,所以是否使用顶点数组(作为一种状态是否需要被启动)都是由客户端决定。显示列表的glCallList比较特殊,它绕过客户端,直接通知服务端把之前初始化时设定的代码段所映射的硬件设置“启亮”,这是相当于直接把显存的某一段占有而随时呼唤了,硬件对此命令没有丝毫犹豫地接受,对该呼唤的答应变成一种“神经反射”行为——这是最理想最高级的“绘制”。
VBO存在的理由
VBO出现的背景是人们发现VA还有不让人满足的地方,同样,显示列表也是。VA(顶点数组)是在客户端设置的,所以执行这类函数(glDrawArray,glDrawElement等等)后,客户端还得把得到的顶点数据向服务端传输一次(所谓的“二次处理”),这样一来就有了不必要的动作了,降低了效率——如果我们写的函数能直接把顶点数据发给服务端就好了——这正是VBO的特性之一。你可能会说,既然上面说到显示列表这么强大,用显示列表不就好了?显示列表的缺点正在于它的古板——一旦设定,就不容许更改,所以它只适合对一些“固定”的东西的绘制进行包装。(我们无办法直接在硬件层改顶点数据,因为这是脱离了流水线的事物。)而VBO直接把顶点数据交到流水线的第一步,与显示列表的效率还是有差距,但它这样就得到了操作数据的弹性——渲染阶段,我们的VBO绘制函数持续把顶点数据交给流水线,在某一刻我们可以把该帧到达了流水线的顶点数据捏回客户端修改(Vertex mapping),再提交回流水线(Vertex unmapping),(或者用glBufferData或glBufferSubData重新全部/部分提交更改了的顶点数据,)这是VBO的另一特性。
或者说,VBO结合了VA和显示列表的这个说法不太妥当,应该说它结合了两者的一些的特性,绘制效率在两者之间,且拥有良好的数据更改弹性。这种折衷造就了它一直为目前“最高”的地位。
http://www.zwqxin.com/archives/opengl/learn-vbo.html
1.名称:
stbi_load 加载jpg,png,gif等格式图片
函数原型:
unsigned char *stbi_load(
char const *filename,
int *x,
int *y,
int *comp,
int req_comp
);
函数参数:
描述:
http://www.cnblogs.com/likebeta/archive/2012/09/25/2701332.html
2.名称:
glTexImage2D—— 指定一个二维的纹理图片
函数原型:
void glTexImage2D(
GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const GLvoid * pixels
);
函数参数:
target 指定目标纹理,这个值必须是GL_TEXTURE_2D。
level 执行细节级别。0是最基本的图像级别,你表示第N级贴图细化级别。
internalformat 指定纹理中的颜色组件,这个取值和后面的format取值必须相同。可选的值有
GL_ALPHA,
GL_RGB,
GL_RGBA,
GL_LUMINANCE,
GL_LUMINANCE_ALPHA 等几种。
width 指定纹理图像的宽度,必须是2的n次方。纹理图片至少要支持64个材质元素的宽度
height 指定纹理图像的高度,必须是2的m次方。纹理图片至少要支持64个材质元素的高度
border 指定边框的宽度。必须为0。
format 像素数据的颜色格式,必须和internalformatt取值必须相同。可选的值有
GL_ALPHA,
GL_RGB,
GL_RGBA,
GL_LUMINANCE,
GL_LUMINANCE_ALPHA 等几种。
type 指定像素数据的数据类型。可以使用的值有
GL_UNSIGNED_BYTE,
GL_UNSIGNED_SHORT_5_6_5,
GL_UNSIGNED_SHORT_4_4_4_4,
GL_UNSIGNED_SHORT_5_5_5_1
pixels 指定内存中指向图像数据的指针
描述:
纹理映射一个指定的纹理图像的每一部分到相应的图元中。调用带GL_TEXTURE_2D参数的glEnable和glDisable函数来启用和禁止二维材质贴图。默认,二维材质贴图是禁用的。
调用glTexImage2D来定义材质图片。
http://blog.csdn.net/wangyuchun_799/article/details/7804859
3.glBlendFunc颜色混合
混合是什么呢?混合就是把两种颜色混在一起。具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果。
假设我们需要绘制这样一个场景:透过红色的玻璃去看绿色的物体,那么可以先绘制绿色的物体,再绘制红色玻璃。在绘制红色玻璃的时候,利用“混合”功能,把将要绘制上去的红色和原来的绿色进行混合,于是得到一种新的颜色,看上去就好像玻璃是半透明的。
要使用OpenGL的混合功能,只需要调用:glEnable(GL_BLEND);即可。
要关闭OpenGL的混合功能,只需要调用:glDisable(GL_BLEND);即可。
注意:只有在RGBA模式下,才可以使用混合功能,颜色索引模式下是无法使用混合功能的。
混合就是在绘制时,不是直接把新的颜色覆盖在原来旧的颜色上,而是将新的颜色与旧的颜色经过一定的运算,从而产生新的颜色。新的颜色称为源颜色,原来旧的颜色称为目标颜色。传统意义上的混合,是将源颜色乘以源因子,目标颜色乘以目标因子,然后相加。
源 因子和目标因子是可以设置的。源因子和目标因子设置的不同直接导致混合结果的不同。将源颜色的alpha值作为源因子,用1.0减去源颜色alpha值作 为目标因子,是一种常用的方式。这时候,源颜色的alpha值相当于“不透明度”的作用。利用这一特点可以绘制出一些半透明的物体。
在进行混合时,绘制的顺序十分重要。因为在绘制时,正要绘制上去的是源颜色,原来存在的是目标颜色,因此先绘制的物体就成为目标颜色,后来绘制的则成为源颜色。绘制的顺序要考虑清楚,将目标颜色和设置的目标因子相对应,源颜色和设置的源因子相对应。
在进行三维混合时,不仅要考虑源因子和目标因子,还应该考虑深度缓冲区。必须先绘制所有不透明的物体,再绘制半透明的物体。在绘制半透明物体时前,还需要将深度缓冲区设置为只读形式,否则可能出现画面错误
http://www.cppblog.com/wc250en007/archive/2012/07/18/184088.html