OpenGL入门学习——第十课,BMP文件与像素操作
现在放出第十课的内容。 首先还是以前课程的连接: 第一课,编写第一个OpenGL程序 第二课,绘制几何图形 第三课,绘制几何图形的一些细节问题 第四课,颜色的选择 第五课,三维的空间变换 第六课,动画的制作 第七课,使用光照来表现立体感 第八课,使用显示列表 第九课,使用混合来实现半透明效果 第十课,BMP文件与像素操作 –→ 本次课程的内容 今天我们先简单介绍Windows中常用的BMP文件格式,然后讲OpenGL的像素操作。虽然看起来内容可能有点多,但实际只有少量几个知识点,如果读者对诸如”显示BMP图象”等内容比较感兴趣的话,可能不知不觉就看完了。 像素操作可以很复杂,这里仅涉及了简单的部分,让大家对OpenGL像素操作有初步的印象。
学过多媒体技术的朋友可能知道,计算机保存图象的方法通常有两种:一是”矢量图”,一是”像素图”。矢量图保存了图象中每一几何物体的位置、形状、大小等信息,在显示图象时,根据这些信息计算得到完整的图象。”像素图”是将完整的图象纵横分为若干的行、列,这些行列使得图象被分割为很细小的分块,每一分块称为像素,保存每一像素的颜色也就保存了整个图象。 这两种方法各有优缺点。”矢量图”在图象进行放大、缩小时很方便,不会失真,但如果图象很复杂,那么就需要用非常多的几何体,数据量和运算量都很庞大。”像素图”无论图象多么复杂,数据量和运算量都不会增加,但在进行放大、缩小等操作时,会产生失真的情况。 前面我们曾介绍了如何使用OpenGL来绘制几何体,我们通过重复的绘制许多几何体,可以绘制出一幅矢量图。那么,应该如何绘制像素图呢?这就是我们今天要学习的内容了。 1、BMP文件格式简单介绍 BMP文件是一种像素文件,它保存了一幅图象中所有的像素。这种文件格式可以保存单色位图、16色或256色索引模式像素图、24位真彩色图象,每种模式种单一像素的大小分别为1/8字节,1/2字节,1字节和3字节。目前最常见的是256色BMP和24位色BMP。这种文件格式还定义了像素保存的几种方法,包括不压缩、RLE压缩等。常见的BMP文件大多是不压缩的。 这里为了简单起见,我们仅讨论24位色、不使用压缩的BMP。(如果你使用Windows自带的画图程序,很容易绘制出一个符合以上要求的BMP) Windows 所使用的BMP文件,在开始处有一个文件头,大小为54字节。保存了包括文件格式标识、颜色数、图象大小、压缩方式等信息,因为我们仅讨论24位色不压缩的BMP,所以文件头中的信息基本不需要注意,只有”大小”这一项对我们比较有用。图象的宽度和高度都是一个32位整数,在文件中的地址分别为 0×0012和0×0016,于是我们可以使用以下代码来读取图象的大小信息: GLint width, height; // 使用OpenGL的GLint类型,它是32位的。 // 而C语言本身的int则不一定是32位的。 FILE* pFile; // 在这里进行”打开文件”的操作 fseek(pFile, 0×0012, SEEK_SET); // 移动到0×0012位置 fread(&width, sizeof(width), 1, pFile); // 读取宽度 fseek(pFile, 0×0016, SEEK_SET); // 移动到0×0016位置 // 由于上一句执行后本就应该在0×0016位置 // 所以这一句可省略 [...]
OpenGL入门学习——第九课,使用混合来实现半透明效果
再次更新 。 首先是以前学习的课程连接列表。 第一课,编写第一个OpenGL程序 第二课,绘制几何图形 第三课,绘制几何图形的一些细节问题 第四课,颜色的选择 第五课,三维的空间变换 第六课,动画的制作 第七课,使用光照来表现立体感 第八课,使用显示列表 第九课,使用混合来实现半透明效果 –→ 本次课程的内容 今天介绍关于OpenGL混合的基本知识。混合是一种常用的技巧,通常可以用来实现半透明。但其实它也是十分灵活的,你可以通过不同的设置得到不同的混合结果,产生一些有趣或者奇怪的图象。 混合是什么呢?混合就是把两种颜色混在一起。具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果。 假设我们需要绘制这样一个场景:透过红色的玻璃去看绿色的物体,那么可以先绘制绿色的物体,再绘制红色玻璃。在绘制红色玻璃的时候,利用”混合”功能,把将要绘制上去的红色和原来的绿色进行混合,于是得到一种新的颜色,看上去就好像玻璃是半透明的。 要使用OpenGL的混合功能,只需要调用:glEnable(GL_BLEND);即可。 要关闭OpenGL的混合功能,只需要调用:glDisable(GL_BLEND);即可。 注意:只有在RGBA模式下,才可以使用混合功能,颜色索引模式下是无法使用混合功能的。
一、源因子和目标因子 前面我们已经提到,混合需要把原来的颜色和将要画上去的颜色找出来,经过某种方式处理后得到一种新的颜色。这里把将要画上去的颜色称为”源颜色”,把原来的颜色称为”目标颜色”。 OpenGL 会把源颜色和目标颜色各自取出,并乘以一个系数(源颜色乘以的系数称为”源因子”,目标颜色乘以的系数称为”目标因子”),然后相加,这样就得到了新的颜色。(也可以不是相加,新版本的OpenGL可以设置运算方式,包括加、减、取两者中较大的、取两者中较小的、逻辑运算等,但我们这里为了简单起见,不讨论这个了) 下面用数学公式来表达一下这个运算方式。假设源颜色的四个分量(指红色,绿色,蓝色,alpha值)是 (Rs, Gs, Bs, As),目标颜色的四个分量是(Rd, Gd, Bd, Ad),又设源因子为(Sr, Sg, Sb, Sa),目标因子为 (Dr, Dg, Db, Da)。则混合产生的新颜色可以表示为: (Rs*Sr+Rd*Dr, Gs*Sg+Gd*Dg, Bs*Sb+Bd*Db, As*Sa+Ad*Da) 当然了,如果颜色的某一分量超过了1.0,则它会被自动截取为1.0,不需要考虑越界的问题。 源因子和目标因子是可以通过glBlendFunc函数来进行设置的。glBlendFunc有两个参数,前者表示源因子,后者表示目标因子。这两个参数可以是多种值,下面介绍比较常用的几种。 GL_ZERO: 表示使用0.0作为因子,实际上相当于不使用这种颜色参与混合运算。 GL_ONE: 表示使用1.0作为因子,实际上相当于完全的使用了这种颜色参与混合运算。 GL_SRC_ALPHA:表示使用源颜色的alpha值来作为因子。 GL_DST_ALPHA:表示使用目标颜色的alpha值来作为因子。 GL_ONE_MINUS_SRC_ALPHA:表示用1.0减去源颜色的alpha值来作为因子。 GL_ONE_MINUS_DST_ALPHA:表示用1.0减去目标颜色的alpha值来作为因子。 除此以外,还有GL_SRC_COLOR(把源颜色的四个分量分别作为因子的四个分量)、GL_ONE_MINUS_SRC_COLOR、 GL_DST_COLOR、GL_ONE_MINUS_DST_COLOR等,前两个在OpenGL旧版本中只能用于设置目标因子,后两个在OpenGL 旧版本中只能用于设置源因子。新版本的OpenGL则没有这个限制,并且支持新的GL_CONST_COLOR(设定一种常数颜色,将其四个分量分别作为因子的四个分量)、GL_ONE_MINUS_CONST_COLOR、GL_CONST_ALPHA、 [...]
