OpenGL 纹理贴图

贴图步骤: 1创建纹理对象,并指定纹理, 2确定纹理如何应用在每个像素上3启用纹理4绘制

 

纹理通常是2D , 但是他也可以是1D,3D的。 每个纹理单元中,描述纹理的数据可以是1、2、3、4个元素组成。

确定纹理如何应用到每个像素上,一种简单的方法是将纹理颜色作为最终的颜色,此为replace模式,另一种是用纹理来调整或缩放片断的颜色。这个技巧在组合纹理和光照效果是非常有用。

启用纹理贴图, glEnable(GL_TEXTURE_1D/2D/3D/GL_TEXTURE_CUBE_MAP)

绘制场景,提供纹理坐标。

生成纹理 glGenTexture(1,&texName) ;

绑定纹理: glBindTexture(GL_TEXTURE_2D,texName);

设定纹理参数: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WARP_S/T, GL_REPEAT) ; 其中第二个参数可以传如各种纹理参数。

glTexImage2D() 用于制定纹理的大小,数据。此外还有相关的glTexImage1D/3D() 两个函数。 这里中点介绍下glTexImage2D函数

glTexImage2D(GLEnum target , GLuint level , GLint internalFormat , GLsizei width ,  GLsizei height ,  GLint border ,  GLenum format ,  GLenum type , GLvoid * texels) ;

这个函数定义一个2D纹理或者一个1D纹理的数组。target可以为 GL_TEXTURE_2D / GL_PROXY_TEXTURE_2D / GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z , GL_PROXY_TEXTURE_CUBE_MAP . 如果提供了多种分辨率的纹理图像,可以指定level参数,如果只有一种分辨率,level应设为0.

接下来的internalFormat 指定了哪些成分(RGBA,深度亮度或者强度)被选定为图像的纹理单元,这里有很多很多的参数,使用时需要查询手册。接下来的宽度和高度表示纹理图像的宽和高,border表示边框的宽度,可以是0 或者1.  format和type参数描述了纹理图像的数据格式和数据类型。他们和glDrawPixels()函数中对应的参数有一样的含义。texels描述了纹理图像本身及他的边框。

如果需要纹理宽度和高度为2的幂,可以利用工具函数gluScaleImage来缩放纹理图像。

另外帧缓冲区本身可以作为纹理数据使用,glCopyTexImage2D()可以从帧缓冲区读取一块矩形像素,并把它作为一个新纹理的纹理单元。

glCopyTexImage2D(GLenum target , GLint level , GLint interna,Format , GLint x, GLint y, GLsizei width , GLsizei height , GLint border)

该函数创建一个2d纹理,像素从当前的GL_READ_BUFFER中读取。

 

2.纹理代理,纹理代理是一种特殊的纹理,可以用于判断的昂前的OPENGL实现在某种特定纹理大小下能否支持某种特定的纹理格式。

3。替换纹理图像的全部或一部分 glTexSubImage2D

glCopyTexSubImage2D可以冲帧缓冲区考出一部分数据作为某纹理的一部分。

 

4.纹理矩形  若想要在绘制的时候直接把纹理单元映射为像素,GL_TEXTURE_RECTANGLE 是比较有用的。

 

5.1D纹理

glTexImage1D() ;

glTexSubImage1D()  更新1D纹理的部分数据。
glCopyTexSubImage1D()

6. 3D纹理:

类似的有3D纹理的定义和更新拷贝函数。

7.纹理数组:假设要显示基本模型一样多个角色,只是每个角色的装束不一样,那么就可以通过纹理数组来实现。2d纹理数组和3d纹理之间的区别,3D纹理的第三分量被规范化到[0,1],这是的访问第二片纹理时不那么方便,而纹理数组则比较容易做到。这里没有API,待日后再看。

8.纹理压缩,openGL可以直接加载和更新压缩后的纹理。相关的函数为

glCompressedTexImage1/2/3D()

glCompressedTexSubImage1/2/3D()

9. 纹理边框 , openGL 3.1以后不支持纹理边框,在哪些实现中,纹理边框的值必须为0.

10. mipmap

mipmap是一种对于不同大小的表面使用不同大小的纹理图像的技术。在具体使用的时候,需要事先提供各个level的图像,也就是多次调用glTexImage2D函数,每次调用使用的level和大小是不同的。然后设定GL_TEXTURE_MIN/MAG_FILTER ,  => GL_NEAREAST_MIPMAP_NEAREST , 然后启用glEnable(GL_TEXTURE_2D) 就可以了, openGL会自动根据大小来选择响应的图进行纹理映射。

在实际应用中构建mipmap, 因为mipmap的重要性,OpenGL中提供了一些函数了方便mipmap的处理:
(>openGL3.0) glGenerateMipMap(GLenum target) , 为target相关联的纹理生成一组完整的mipmap。其中的target可以是GL_TEXTURE_1/2/3D/[1d/2d_ARRAY] 以及 GL_TEXTURE_CUBE_MAP . 所构建的层有GL_TEXTURE_BASE_LEVEL和GL_TEXTURE_MAX_LEVEL控制.

假设已经建立了第0层mipmap, 可以使用gluBuild1/2/3DMipmaps() 函数来创建和定义一系列大小递减的mipmap。如果源纹理的大小不是2的幂,可以利用gluBuild*DMipmaps()函数把纹理图像缩放为最邻近的2的幂。

另外函数glBuild*DMipmapLevels() 可以对mipmap的生成进行更精细的控制,可以控制生成的mipmap的level,从第几层开始第几层结束。详细请查手册。

 

计算mipmap的层,假设纹理图像的大小为64×64, 多边形大小为32×32,那么取lod层为第1层。因为第0层为64×64,第1层为32×32 .

有时候,我们不希望使用太高级别的mipmap,因为这个分辨率太低。这可以利用glTexParameter*() 设置GL_TEXTURE_BASE_LEVEL , GL_TEXTURE_MAX_LEVEL , GL_TEXTURE_MIN_LOD , GL_TEXTURE_MAX_LOD.

 

过滤:纹理图像是方形的,但是映射到屏幕上以后,基本不会出现与pixel的1:1对应,经常多个texel对应一个pixel或者1个texel对应多个pixel。因此需要进行过滤,不然会出现失真的情况。

设置纹理过滤可以通过glTexParameteri, 参数GL_TEXTURE_MAG_FILTER/GL_TEXTURE_MIN_FILTER 来指定,前者是放大过滤方法,后者是缩小过滤方法,可以使用的值有GL_NEAREST , GL_LINEAR / GL_NEAREST , GL_LINEAR , GL_NEAREST_MIPMAP_NEAREST , GL_NEAREST_MIPMAP_LINEAR,  GL_LINEAR_MIPMAP_NEAREST , GL_LINEAR_MIPMAP_LINEAR .等

 

纹理对象:与glTexImage*D相比 ,纹理对象可以实现更高效的纹理切换。
首先要命名纹理对象: glGenTexture(n,*names) ;

glIsTexture( ) 判断一个对象是否为纹理对象。
glBindTexture可以创建和使用纹理对象。 当调用glBindTexture函数以后,后续所有的glTexImage*D, glTexSubIMage*() 等函数都将作用域这个纹理上。当以个纹理对象以后再被绑定时,他的数据就称为当前状态。

清除纹理对象: glDeleteTexture(n,*names) ;

11. 常驻纹理工作集.

查询函数,glAreTextureResident()  可以查询n个纹理是否为常驻内存纹理

glPrioritizeTextures()可以用来制定把哪些纹理常驻内存。

12. 纹理函数:现在,纹理的颜色都用来直接替换多边形表面的颜色,除了直接替换以外,还可以控制纹理颜色与表面颜色进行组合。可以通过函数glTexEnv()函数来指定。

13. 分配纹理坐标:
利用glTexCoord函数来指定某定点的纹理坐标。纹理映射是一个需要相当精细的工作。

14.重复和截取
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WARP_S/T , GL_REPEAT).

15. 纹理坐标自动生成:
glTexGen(GLenum coord, GLenum pname , TYPE para) , 指定纹理坐标的生成方式。可以利用glTexGenf(GL_S , GL_TEXTURE_GEN_MODE , GL_OBJECT_PLANE) ;  glTexGenv(GL_S , GLTEXTURE_GEN_MODE , param) ; 其中的params用来制定参数,指定以后,opengl会自动根据当前点的坐标来计算出纹理坐标。这个是相当有用,并且具有实际的应用价值。这应该是个很有趣的东西,可以试着用他来做一些有趣的应用。

16.球体纹理
也就是环境纹理,通过指定一个纹理图像以后,利用glTexGeni(GL_S,GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP) ;  glTexGeni(GL_T,GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP) ; glEnable(GL_TEXTURE_GEN_S) ; glEnable(GL_TEXTURE_GEN_T) ;

如此openGL就会自动为每个点生成环境纹理坐标。计算方法是人眼看到的点反射到环境中对应的那个点。

17.立方体纹理(cube map)

可以使用glTexImage2D 6次,分别使用target为立方体的各面+-x, +-y , +-z 。 同时也可以设置其他的比如WARP , FILTER之类的属性。纹理坐标可以手工计算,当然最好的是自动生成纹理坐标。
这里有两种自动生成模式GL_REFLECTION_MAP 和 GL_NORMAL_MAP.  前者的计算方式和球体坐标一样。 后者稍有不同。可日后再看。

18 多重纹理:
对于每个文理单元,建立相关的文理状态。可以使用glActiveTexture函数更改当前的纹理单位。可以用glGetIntegerv(GL_MAX_TEXTURE_UNITS,…)来获取当前GL所支持的纹理单位的数量。任何GL必须支持至少2个纹理单元。
在指定定点是,可以使用glMultiTexCoord()函数为每个定点指定多个纹理坐标。
建立文理单元:每个纹理单元的状态包括纹理图像,过滤参数,纹理环境应用,纹理坐标自动生成,定点数组指定。
每个文理单元根据他的纹理状态,把原先的片段颜色与纹理图像进行组合,然后把上述操作的结果传给下一个纹理单元。
为了向每个纹理单元分配纹理信息,可以使用glActiveTexture来选择需要修改的当前纹理单元。之后的glTexImage(), glTexParameter() , glTexEnv, glTexGen,glBindTexture等函数就只修改当前纹理单元。

glActiveTexture(GL_TEXTUREi) ;

 

注意:texture 对象和texture单元是不一样的, glGenTexture是纹理对象, 以下是两个tex对象和两个tex单元的代码:
glGenTexture(2,texName);
glBindTexture(GL_TEXTURE_2D,texName[0]) ; glTexImage2D() ; glTexParameteri()  ;
glBindTexture(GL_TEXTURE_2D,texName[1]) ; glTexImage2D() ; glTexParameteri()  ;
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D); glBindTexure(GL_TEXTURE_2D,texName[0]);
glMatrixMode(GL_TEXTURE) ?? ;  glLoadIdentity() ; glRotatef() ;
glMatrixMode(GL_MODEVIEW) ; glActiveTexture(GL_TEXTURE1) ; …

指定多重纹理坐标的方法,glMultiTexCoord2f(GL_TEXTURE0/1 , x, y) ;
指定多重纹理坐标的其他方法: glTexGen*()  和 glTexCoordPointer() 函数。

19.纹理组合函数  glTexEnv{if}(GLenum target , GLenum pname , TYPE param)  可以指定纹理组合的方法。具体使用参数可以参考手册。

20. 纹理之后使用辅助颜色, 把一个纹理应用一个典型的片段时,只有主颜色与纹理单元的颜色进行组合,。在纹理处理以后,执行雾计算之前,可以对片段应用一种辅助颜色,应用辅助颜色可以使经过纹理贴图的物体具有更真是的镜面亮点效果。

21.点块纹理:可以用GL_POINT_SPRITE调用glEnable函数,这将导致GL忽略当前的点抗锯齿设置,大点中的每个片段将分配相关的纹理坐标数据,这些值将会在着色中使用。

22. 纹理矩阵堆栈:
和顶点在渲染之前可以旋转平移一样,纹理坐标也可以在使用到像素之前进行平移旋转变换。默认情况下,纹理矩阵是单位矩阵。

23.深度纹理
深度纹理是绘制阴影的一种方法,首先将视点移动到光源处,渲染场景,将深度图保存下来,(shadow map), 并将他存储在一个纹理图像中。第二步生成纹理坐标,其中(s,t)坐标引用阴影图中的位置,第三个坐标r表示于光源的距离。然后再次绘制场景。把每个片段的r值与对应深度纹理值进行比较,以确定这个片段是被光所照射还是阴影区。

本文地址: http://www.bagualu.net/wordpress/archives/2405 转载请注明

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值