glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, MinFilter); //设置缩小滤镜
上述调用中,第一个参数表明是针对何种纹理进行设置,第二个参数表示要设置放大滤镜还是缩小滤镜。第三个参数表示使用的滤镜。可以为下面的值之一:
表6.3-1 可使用的纹理滤镜 滤镜 GL_NEAREST GL_LINEAR 描述 取最邻近像素 线性内部插值 最近多贴图等级的最GL_NEAREST_MIPMAP_NEAREST 邻近像素 GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_NEAREST GL_LINEAR_MIPMAP_LINEAR 在最近多贴图等级的内部线性插值 在最近多贴图等级的外部线性插值 在最近多贴图等级的外部和内部线性插值 3 纹理映射 3.1 纹理坐标
要使用当前的纹理绘制图元,我们必须在绘制每个顶点之前为该顶点指定纹理坐标。只需调用
glTexCoord2d(s:Double;t:Double);
函数即可。其中,s、t是对于2D纹理而言的s、t坐标。对于任何纹理,它的纹理坐标都如同图6.4-1所示的那样:
图6.4-1 纹理坐标
对于任何纹理,无论纹理的真正大小如何,其顶端(左上角)的纹理坐标恒为(0,0),右下角的纹理坐标恒为(1,1)。也就是说,纹理坐标应是一个介于0到1之间的一个小数。
例如,下面的代码将使用当前纹理绘制一个三角形: glBindTexture(Tex);
glBegin(GL_TRIANGLES); glTexCoord2d(0,0);
glVertex3f(-10,-10,0); glTexCoord2d(0,1); glVertex3f(-10,10,0);
glTexCoord2d(1,1); glVertex3f(10,10,0); glEnd(); 纹理映射
2009-05-04 19:23
1.纹理贴图,首先要载入位图
A:直接读取BMP格式来获得图像数据,从而生成纹理的,要求需要了解BMP的格式
B:用windows的API函数LoadImage()来实现这个功能
C:在NeHe的教程中,用了OpenGL中的AUX函数auxDIBImageLoad来从文件中读取位图,载入到AUX_RGBImageRec结构体中(实际上这是一个typedef)
2.用位图生成纹理,先用glGenTextures创建纹理,再用glBindTexture绑定纹理,然后用glTexImage2D把刚才从文件中读入的位图转换成纹理,非常重要的,最后要用glTexParameteri函数对GL_TEXTURE_MIN_FILTER和
GL_TEXTURE_MAG_FILTER两种贴图(近距离贴图和远距离贴图)设置类型(有
GL_LINEAR和GL_NEAREST两种模式)。在google上看到这最后一步如果不做,会发生纹理贴不上但又不报错的情况。
3.这时从文件读入的位图(AUX_RGBImageRec结构)可以释放,在库中可能是用malloc之类的函数生成的,因此在教程中用free来进行释放,应当注意的是,先应该释放AUX_RGBImageRec中的data指针,然后再释放整个结构。
4.这一步也就是我照教程做所漏做的一步!!!似乎在默认状态下,纹理贴图是被禁用的,所以先要启用纹理贴图。glEnable(GL_TEXTURE_2D);语句可以打开二维的纹理贴图功能,只有打开之后才可以正确地将纹理贴到形状表面。
5.绘制图形,同时将纹理上的一些点和图形的顶点绑定。以下是详细的绘制三角形和将纹理贴到三角形表面的代码,程序比较容易理解。 glBegin(GL_TRIANGLES);
glColor3f(1.0f,1.0f,1.0f);
glTexCoord2f(0.0f,1.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glTexCoord2f(1.0f,0.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glEnd();
6.其他的,用glTranslatef可以做图形平移,用glRotatef可以做图形旋转,从而可以做出一些最简单的动画。 转:3D游戏场景数据的组织 2009-05-10 22:34
3D游戏最重要的部分就是场景数据的组织,他决定了这个3D游戏的速度,同时也决定一个3D游戏的质量(因为速度越快我们就能加入更多的特效)。场景数据的组织形式决定了内存的动态平衡,可视剪裁,LOD计算,碰撞检测,通信等一序列对于游戏来说最重要和最根本的东西,所以我们需要开发一个有效的数据结构来保存我们的3D场景,下面我们来简单的看看这些技术。
3D场景分为室内场景和室外场景,两者在数据组织和优化上是完全不同的,这是由他们的特性决定的,下面来比较一下他们的异同:
1、室内场景小,物体离观察者非常近,所以基本上没有必要使用LOD技术,
但是可以使用替代物技术;
室外场景大,远处的物体对观察者的贡献非常小,甚至可以忽略,所以可以使用LOD技术和替代物技术。
2、室内场景存在大量的大型的遮挡物,即使是小的遮挡物,由于他们离观察者很近,也能遮住大的物体,而且室内场景之间的联系往往是受限的,也就是说只能通过一些洞互相观察到,那么就可以使用Portal技术和PVS技术; 室外场景物体相对来说比较分散和稀少,而且远处的地形和物体经过LOD处理,多边形不多,但是还是需要进行剪裁,因为还有很多建筑和树等分布在野外,这个时候我们需要使用地平线技术或者HOM技术,特别在城市里的室外场景更是需要使用2.5D的地平线剪裁技术,虽然如此,我们还可以使用硬件本身提供的背面消隐和fog来达到很高性能。
3、室内场景一般需要比较精确的碰撞检测,这个需要使用BSP来进行,这样可以获得很高的效率;
室外场景碰撞检测则比较简单,和地面,桥,城堡,树等的碰撞都可以简化为和三角形或包围体的碰撞。
4、室内场景一般都是静态的,因为他们不需要LOD,所以可以组织为静态的数据结构,如BSP;
室外场景一般都是动态的,因为他们使用LOD,所以我们要么动态生成场景,如ROAM,VDMP,要么使用块LOD拼接技术。由于这些原因,我们只能把室外场景组织为四叉树或者八叉树,而里面可能不含数据,他们只是用来剪裁用。 5、室内场景特效比较少,一般就是开灯,关灯,火,爆炸等,所以大部分情况都可以使用简单数据结构;
室外场景特效多,太阳光源的移动,天气,自然现象,白天黑夜,这些都需要大量的纹理和复杂的数据结构做后盾。
6、最后一点,你很难想象一个室内的小房间里挤满了100个人,而在室外,100人在一个场景里是很平常的,这在数据通信和遮挡方面是一个严重考验,这也决定了室内引擎和室外引擎的不同。 在游戏里,室内引擎和室外引擎同时存在,并且在同一时间他们都会被用到,如站在房间里透过窗户看远处的山。那么如何把他们联系起来呢?可以是手动或者由你写的编辑器自动完成,自动完成是很难的,所以一般都是手动完成的。 下面我们来介绍一个有效场景的组织结构,他可能不是最好的,但是却完全是实用的。 室外引擎:
室外地图一般用高度场表示,也就是一张位图。虽然有山脉,湖泊,但是由于地图一般很大,相对来说他们是非常平坦的,而我们关心的也只是大面积剪裁,所以我们使用四叉树来表地图而不是八叉树,这个四叉树不仅仅覆盖着地图,他还在节点里保存着地图上的建筑物,树,水等物体,但是不包含动态的物体(会自由移动的)
这个四叉树还可以用来实现LOD用 室内引擎:
我们使用Portal来连接每个房间,这样可以使用Portal引擎来表示场景,还可以使用PVS,对于小的房间,我们直接用BSP表示,对于很大而且有很多物体的房间,我们使用八叉树表示,每个八叉树的节点里有一个小的BSP树,这样可以使碰撞检测比较高效。
室内引擎和室外引擎的连接:
由于室内引擎用的是Portal引擎,从室外看室内也是通过Portal看到的,所以我们可以把这些Portal放到室外引擎的四叉树的节点中,并且在Portal里标志这个Portal是连接着室内和室外,在渲染的时候需要切换引擎即可。 Portal的生成:
室内引擎一个大的问题就是如何生成Portal,这是一个大问题。究竟由人工来指定,还是由程序来指定呢?这是一个权衡问题,人工指定很浪费人力,而且容易出错,但是却能得到很好的效果,由程序来指定则很轻松,但是遇到有大量三角形的物体,那么这将是一场灾难,会产生出很多Portal,在计算剪裁的时候效率反而下降。经过研究,我们发现人工的优点在于能很好的找到适合的Portal,而程序在于生成,我们把这两个优点结合起来,就产生了下面的半人工半程序的做法:在生成场景的时候,由人工指定哪些物体是房间,然后程序将这些物体之外的物体全部隐藏,接着用传统的Portal生成方法计算Portal。 动态物体的管理:
动态物体包括:人,怪物,交通工具,各种人或怪物放出的魔法和扔出的武器,死了以后留在地上的尸体等。
上面的室内引擎还是室外引擎都没有谈到可以移动的物体该如何处理,这有很多方法,一种是把这些物体放到引擎的数据结构的节点中,然后使用局部更新技术动态的在节点间移动他们,这可以很好的使用这些结构本身带来的好处,如遮挡,而且还能直接找到碰撞源,这个技术的缺点是太复杂。还有一种做法是为这些物体建立一个包围体层次树,如球形树,用这个树来剪裁他们,但是却用不上任何遮挡信息和需要计算碰撞的可能区域,这个技术的缺点在于速度慢。
【转】 opengl基本概念
2010-10-10 19:16
转载自 cherry_shining 最终编辑 cherry_shining
像素格式
当读者进行openGL的绘图操作时,实际上是在进行设备像素的操作。OpenGL将数据转化为像素操作写入帧缓存中,OpenGL需要知道Windows的像素格式,或则说需要与其一致起来。
在创建一个图形操作描述表之前,首先必须设置像素格式。像素格式含有设备绘图界面的属性,这些属性包括绘图界面是用RGBA模式还是颜色表模式,像系缓存是用单缓存还是双缓存,以及颜色位数、深度缓存和模板缓存所用的位数,还有其他一些属性信息。 (1)像素格式结构
每个OpenGL显示设备都支持一种指定的像素格式号。一般用一个名为
PIXELFORMATDESCRIPTOR的结构来表示某个特殊的像素格式,这个结构包含26个属性信息。Win32定义的PIXELFORMATDESCRIPTOR如下所示:
typedef struct tagPIXELFORMATDESCRIPTOR {
WORD nSize; WORD nVersion; DWORD dwFlags; BYTE iPixelType; BYTE cColorBits; BYTE cRedBits; BYTE cRedShift; BYTE cGreenBits; BYTE cGreenShift; BYTE cBlueBits; BYTE cBlueShift; BYTE cAlphaBits; BYTE cAlphaShift; BYTE cAccumBits; BYTE cAccumRedBits; BYTE cAccumGreenBits; BYTE cAccumBlueBits; BYTE cAccumAlphaBits; BYTE cDepthBits; BYTE cStencilBits; BYTE cAuxBuffers; BYTE ilayerType; BYTE bReserved; DWORD dwLayerMask; DWORD dwVisibleMask; DWORD dwDamageMask; }
PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR,
FAR *LPPIXELFORMATDESCRIPTOR;
(2)初始化PIXELFORMATDESCRIPTOR结构
PIXELFORMATDESCRIPTOR中每个变量值的具体含义和设置可以参
考有关资料,下面举出一个PIXELFORMATDESCRIPTOR初始化例子来简要 说明相关变量的意义。定义PIXELFORMATDESCRIPTOR结构的pfd如下: PIXELFORMATDESCRIPTOR pfd= {
sizeof(PIXELFORMATDESCRIPTOR),//结构尺寸 l, //结构版本
PFD-DRAW-TO-WINDOWS|PFD-SUPPORT-OPENGL,//特性标志 PFD-TYPE-RGBA,//RGBA模式 24,//24位颜色
0,0,0,0,0,0,//不涉及这些属性