opengl纹理映射总结
Posted 狡啮之仰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opengl纹理映射总结相关的知识,希望对你有一定的参考价值。
大概步骤:
1.创建纹理对象,并为他指定一个纹理.
2.确定纹理如何应用到每个像素上.
3.启用纹理贴图
4.绘制场景,提供纹理和几何坐标
过滤:由于我们提供的纹理图像很少能和最终的屏幕坐标形成对应,大小不同,所以需要设置过滤项目.允许我们进行插值或者匀和,指定放大缩小的函数.glTexParameter*(),使用过滤模式GL_NEAREST那么纹理单位最邻*的将被使用,GL_LINEAR那么就用2*2的包含纹理数据的数组加权组作为纹理;
命名纹理对象:glGenTexures(GLSize n,Gluint *textureNames); n为产生n个未使用的对象值,textureNames为纹理名字数组,你可能有几个纹理需要使用,这个数组来区分.
1.你需要载入图片时候的纹理定义
void glTexImage2D( GLenum target, GLint level, GLint components,GLsizei width, GLsizei height, GLint border,GLenum format, GLenum type, const GLvoid *pixels );
定义一个二维纹理映射。target是常数 GL_TEXTURE_2D, level表示多级分辨率的纹理图象的级数。若只有一种分辨率,level为0。components是从1到4的整数,1:选择R;2:选择R A;3:选择R G B;
源文档 <http://www.pinxue.net/OpenGL/credbook/chapter9_textuer.htm>
绑定纹理对象:glBindTexture(Glenum target,Gluint,glTexImage*),将把数据存储到这个纹理对象中,如果需要纹理图像的颜色和物体表面的颜色进行组合,不是直接贴图,那么就需要glTexEvn*()函数.
确定纹理坐标:glTexCoord2f(1.of,1.Of);glVertex3f(1.Of,1.Of,0.Of);比如这一句话.对于设置纹理贴图的坐标和绘图坐标的确定问题.一般的情况假设纹理和图片都是正方形的,那么我们希望纹理映射到整个物体上面,这个时候纹理坐标按照逆时针放心依次(0,0),(1,0),(1,1),(0,1),其中的四个坐标只是代表的向量,并不是真实的坐标,如果是要一半贴到物体上就应该是0.5的值了,假如你给的纹理坐标大于1,那么将会贴多个纹理,比如值为2的时候,会有4个纹理贴图.
1 概述
概括的说, 纹理映射机制允许你将一个图像关联到一个多边形上,从而呈现出真实视觉效果。例如, 你可以将书的封面图像应用到一个方形上, 这样这个方形看起来就像是一本书了。你可以将地球的地图通过纹理映射应用到一个球体上, 那么这个球体就是一个3D的具真实感的地球了。纹理映射在当今的3D图形应用上处处皆是。游戏都是通过纹理映射来作为虚拟真实的第一个步骤。
纹理映射是一个二维的数组。数组中的每一项称之为纹理点( texel )。 虽然这个数组是二维的, 但是可以映射到非二维的对象上, 如球体或者其他的 3D 对象模型上。
比较常见的是, 开发者在他们的图形应用中运用二维纹理, 当然一维或者三维的纹理也并非未闻。二维纹理有宽度和高度决定二维。一维纹理也有宽度和高度, 只是高度被设为值 1(单位:像素 pixel). 而三维纹理不仅具有宽度和高度, 还有深度, 所以三维为纹理又称为立体纹理。我们讨论的主要是二维纹理。
2 预备知识: 纹理坐标
在 OpenGl 中是通过指定纹理坐标来将纹理映射到多边形上去的. 在纹理坐标系中, 左下角是 (0,0), 右上角是 (1,1). 2D 纹理的坐标中通过指定 (s,t) (s为x轴上,t为y轴上, 取值0~1). 1D, 3D, 4D纹理坐标系中对应的需要指定 (s), (s,t,r), (s,t, r,q).
纹理坐标需要通过函数 glTexCoord() 来设置, 此函数:
void glTexCoord{1234}{sifd}(TYPE coords); |
void glTexCoord{1234}{sifd}v(TYPE coords); |
如将 2D 纹理坐标设为 (0.2, 0.4):
1 |
glTexCoord2f(0.2f,0.4f); |
每次通过 glVertex() 指定一个顶点时, 当前的纹理坐标会被应用到这个点上. 所以每指定一个新的顶点, 需要同时修改纹理坐标:
1 2 3 4 5 6 |
glBegin(GL_POLYGON); glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f, 0.5f, 0.5f);//左下角 glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5f, 0.5f, 0.5f); // 右下角 glTexCoord2f(1.0f, 1.0f); glVertex3f(0.5f, 0.5f, -0.5f);// 右上角 glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, 0.5f, -0.5f);// 左上角 glEnd(); |
至此, 我们知道了纹理坐标如何赋值.且看如何创建纹理:
3 使用纹理映射
纹理就是应用到多边形上的图像. 这些图像可以从文件中加载, 或是在内存中生成. 一旦你将图像数据加载到了内存中, 你需要指定其为纹理映射来使用它. 指定其为纹理映射, 首先需要生成一个纹理对象, 其中存储着纹理的诸如图像数据, 如何应用等信息.
纹理是一个OpenGL状态, 因而通过 glEnable() 和 glDisable() 来开闭, 参数是 GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP.
3.1 纹理对象
纹理对象是内部数据类型, 存储着纹理数据和选项等. 你不能直接访问它, 但是可以通过一个整数的 ID 来作为其句柄 (handler) 来跟踪之. 为了分配到一个唯一的 ID, OpenGL 提供了glGenTextures() 函数来获取一个有效的 ID 标识值:
void glGenTexture(Glsizei n, GLuint *texture);
texture 是一个数组, 用于存储分配到的n个ID值. 在调用一次 glGenTextures() 后, 会将分配到的 ID 标识为\'已用\', 虽然直到绑定后才真正为\'已用\'.
分配3个纹理对象 ID:
1 2 |
unsigned inttextureObjects[3]; glGenTexture(3, textureObjects); |
3.2 纹理绑定
在第一次绑定一个纹理对象时, 会将一系列初始值来适应你的应用. 函数 glBindTexture() 用于绑定操作:
void glBindTexture(GLenum target, GLuint texture);
target 指定了纹理类型: GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP. texure 是你希望绑定的纹理对象的 ID.
一个被绑定的纹理对象直到被删除,或被另外的纹理对象绑定到 target 上才被解除绑定. 当一个纹理对象绑定到 target 上后, OpenGL 的后续的纹理操作都是基于这个纹理对象的。
1 2 3 4 5 6 7 8 9 10 |
glBindTexture (GL_TEXTURE_2D, textureObject[0]); // 后面的对 GL_TEXTURE_2D 的纹理操作影响textureObject[0]
glBindTexture (GL_TEXTURE_3D, textureObject[1]); // 后面的对 GL_TEXTURE_3D 的纹理操作影响textureObject[1] // 对 GL_TEXTURE_2D 的纹理操作依然影响textureObject[0]
glBindTexture (GL_TEXTURE_2D, textureObject[2]); // 后面的对 GL_TEXTURE_2D 的纹理操作影响textureObject[2] // 对 GL_TEXTURE_3D 的纹理操作依然影响textureObject[1] |
3.3 删除纹理对象
创建一个纹理对象后, OpenGL为其分配内存, 所以当不再使用一个纹理对象时, 为防止内存泄露, 必须删除. 删除纹理对象的函数: glDeleteTexture() :
void glDeleteTexure(Glsizei n, Gluint *texture);
texture 指定了要删除的纹理对象的 ID (n个). 在删除后, texture 中的各个对象 ID 会置为0.
3.4 驻留纹理
显卡有一块固定大小的内存区域专门用于存储纹理数据。当数据超量时,会将一部分纹理数据移除到系统内存中(通常是最*最少使用的纹理数据). 当这些移除的纹理被再次使用时,会影响击中率, 因为它们会被再次移入显卡的内存中。你可以查看一个纹理对象是否驻留在显卡内存中未被移出, 通过函数 glAreTexturesResident() :
GLboolean glAreTexturesResident (GLsizei n, GLuint *textures, GLboolean *residents);
texture 中每一项纹理对象的驻留情况会存储在 resident 参数中返回。 若 textures 中有一项纹理对象不在内存驻留内存, 函数会返回 GL_FALSE.
3.5 纹理优先级
纹理的优先级是针对驻留显卡内存而言。优先级设置函数 glPrioritizeTextures() :
void glPrioritizeTextures (GLsizei n, GLuint *textures, GLclampf *priorities)
前两个参数 textures 和 n 指定了要设置优先级的纹理对象数组。 priorities 是 textures 中每一项纹理对象对应的优先级, priorities 中每一项的优先级取值区间是 [0,1], 0为优先级最低, 1 为最高。 glPrioritizeTextures() 函数会忽略掉那些未使用的和优先级要设为 0 的纹理对象。
4 指定纹理
OpenGL 提供了三个函数来指定纹理: glTexImage1D(), glTexImage2D(), glTexImage3D(). 这三个版本用于相应维数的纹理, 例如如果纹理是3D纹理,则需要有 glTexImage3D() 来指定。
4.1 2D 纹理
void glTexImage2D (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* texels);
参数 target 是 GL_TEXTURE_2D (二维纹理) 或 GL_PROXY_TEXTURE_2D (二维代理纹理), 代理纹理暂且不提。
参数 level 指定了纹理映射细节的级别,用在mipmap中。 基本的纹理图像级别为0, 在后面的mipmap部分讲解。
参数 internalFormat 指定了纹理存储在显存中的内部格式, 取值在下表, 为兼容 OpenGL1.0 internalFormat 可以取值 1,2,3,4 分别对应常量 LUMINANCE, LUMINANCE_ALPHA, RGB, RGBA.
格式 |
注解 |
GL_ALPHA |
Alpha 值 |
GL_DEPTH_COMPONENT |
深度值 |
GL_LUMINCE |
灰度值 |
GL_LUMINANCE_ALPHA |
灰度值和 Alpha 值 |
GL_INTENSITY |
亮度值 |
GL_RGB |
Red, Green, Blue三原色值 |
GL_RGBA |
Red, Green, Blue 和Alpha 值 |
纹理内部格式
参数 width 和 height 定义了纹理映射的大小,前面已经说过纹理映射就是一个二维数组。 和 glDrawPixels() 一样, 纹理映射的宽度和高度必须是 2 的整数次幂。
参数 border 注明了纹理是否有边框。无边框取值为 0, 有边框取值为 1, 边框的颜色由 GL_TEXTURE_BORDER_COLOR 选项设置。
接下来的三个参数主要定义了图像数据的格式。
参数 format 定义了图像数据数组 texels 中的格式。可以取值如下:
格式 |
注解 |
GL_COLOR_INDEX |
颜色索引值 |
GL_DEPTH_COMPONENT |
深度值 |
GL_RED |
红色像素值 |
GL_GREEN |
绿色像素值 |
GL_BLUE |
蓝色像素值 |
GL_ALPHA |
Alpha 值 |
GL_RGB |
Red, Green, Blue 三原色值 |
GL_RGBA |
Red, Green, Blue 和Alpha 值 |
GL_BGR |
Blue, Green, Red 值 |
GL_BGRA |
Blue, Green, Red 和Alpha 值 |
GL_LUMINANCE |
灰度值 |
GL_LUMINANCE_ALPHA |
灰度值和 Alpha 值 |
图像数据数组 texels 格式
参数 type 定义了图像数据数组 texels 中的数据类型。可取值如下
数据类型 |
注解 |
GL_BITMAP |
一位(0或1) |
GL_BYTE |
带符号8位整形值(一个字节) |
GL_UNSIGNED_BYTE |
不带符号8位整形值(一个字节) |
GL_SHORT |
带符号16位整形值(2个字节) |
GL_UNSIGNED_SHORT |
不带符号16未整形值(2个字节) |
GL_INT |
带符号32位整形值(4个字节) |
GL_UNSIGNED_INT |
不带符号32位整形值(4个字节) |
GL_FLOAT |
单精度浮点型(4个字节) |
GL_UNSIGNED_BYTE_3_3_2 |
压缩到不带符号8位整形:R3,G3,B2 |
GL_UNSIGNED_BYTE_2__3_REV |
压缩到不带符号8位整形:B2,G3,R3 |
GL_UNSIGNED_SHORT_5_6_5 |
压缩到不带符号16位整形:R5,G6,B5 |
GL_UNSIGNED_SHORT_5_6_5_REV |
压缩到不带符号16位整形:B5,G6,R5 |
GL_UNSIGNED_SHORT_4_4_4_4 |
压缩到不带符号16位整形:R4,G4,B4,A4 |
GL_UNSIGNED_SHORT_4_4_4_4_REV |
压缩到不带符号16位整形:A4,B4,G4,R4 |
GL_UNSIGNED_SHORT_5_5_5_1 |
压缩到不带符号16位整形:R5,G5,B5,A1 |
GL_UNSIGNED_SHORT_1_5_5_5_REV |
压缩到不带符号16位整形:A1,B5,G5,R5 |
GL_UNSIGNED_INT_8_8_8_8 |
压缩到不带符号32位整形:R8,G8,B8,A8 |
GL_UNSIGNED_INT_8_8_8_8_REV |
压缩到不带符号32位整形:A8,B8,G8,R8 |
GL_UNSIGNED_INT_10_10_10_2 |
压缩到32位整形:R10,G10,B10,A2 |
GL_UNSIGNED_INT_2_10_10_10_REV |
压缩到32位整形:A2,B10,G10,R10 |
图像数据数组 texels 中数据类型
你可能会注意到有压缩类型, 先看看 GL_UNSIGNED_BYTE_3_3_2, 所有的 red, green 和 blue 被组合成一个不带符号的8位整形中,在 GL_UNSIGNED_SHORT_4_4_4_4 中是把 red, green , blue 和 alpha 值打包成一个不带符号的 short 类型。
最后一个参数是 texels, 这个指针指向实际的图像数据(你自己生成的或是从文件中加载的)。OpenGL 会按照 type 参数指定的格式来读取这些数据,
例如, 假设你加载了一个 RGBA 图像到 textureData 中( 宽高为 textureWidth, textureHeight).你想要用它来指定一个纹理, 可以这样做:
1 2 |
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData); |
执行完这个函数后, 纹理会加载,等待被使用。
4.2 1D 纹理
1D 纹理其实就是 2D 纹理的特殊形式(高度等于1)。这类纹理常常用来描绘颜色边界从而创造出阴影效果。创建 1D 纹理的函数如下:
void glTExImage1D (GLenum target, GLint level, GLint internalFormat, GLsizei width, |
GLint border, GLenum format, GLenum type, const GLvoid *texels); |
函数中的参数同 glTexImage2D(), 不同的是 height 参数没有被给出(因为定值1), 参数 target 也需要指定为 *GL_TEXTURE_1D*。
下面是简单的代码, 用于创建32个纹理点宽度的 RGBA 纹理:
1 2 3 |
unsigned char imageData[128]; ... glTexImage1D (GL_TEXTURE_1D, 0, GL_RGBA, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); |
4.3 3D 纹理
创建 3D 纹理的函数:
glTexImage3D(GLenum target, GLint level, GLint internalFormat, GLsizei width GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *texels);
函数参数同 glTexImage1D() 和 glTexImage2D() 大部分相同,不同的是多了一个深度参数 depth, 指定了纹理的第三维。
下面的代码片段, 用于创建一个 16*16*16 个纹理点的 RGB 纹理:
1 2 3 |
... glTexImage3D (GL_TEXTURE_3D, 0, GL_RGB, 16, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData); |
4.4 Cube Map 纹理
一个 Cube Map 纹理是由6个2D纹理组成。对应的, 需要通过 glTexImage2D() 来指定6个 target 参数: GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z.
5 纹理过滤
将纹理映射到多边形上, 实际上是将纹理的图像数据空间映射到帧缓冲图像空间上。所以, 你必须保证纹理图像加载完成。 纹理图像被映射到多边形上可能会造成失真。纹理图像映射到多边形上去,屏幕上的一个点可能是纹理点的一个部分(如果视口设置的离纹理很*), 也有可能屏幕上的一个像素点是多个纹理的集合(如果视口设置的足够远). 纹理过滤就是告诉 OpenGL 在纹理到屏幕像素点的映射中如何计算最终显示的图像数据。
在纹理过滤中, 放大器处理一个屏幕像素点代表一个纹理点的一部分的情况;缩小器处理一个像素点代表多个纹理点的情况. 你可以通过下面函数来告诉 OpenGL 怎样处理这两种情况:
void glTexParameter{if}(GLenum target, GLenum pname, T param); |
void glTexParameter{if}v(GLenum target, GLenum pname, T params); |
glTexParameter 不仅仅设置放大器和缩小器, 在本章中,由于只涉及纹理,所以只讨论纹理相关的参数取值.
参数 target 指的是纹理目标, 可以是 GL_TEXTURE_1D, GL_TEXTURE_2D*, GL_TEXTURE_3D 或 GL_TEXTURE_CUBE_MAP 。 指定纹理放大过滤器需要指定参数 pname为 GL_TEXTURE_MAG_FILTER, 指定纹理缩小过滤器需要指定参数 pname 为 GL_TEXTURE_MIN_FILTER.
当指定为 GL_TEXTURE_MAG_FILTER, 参数 param 取值 GL_NEAREST 或 GL_LINEAR. 对放大过滤器而言, 使用 GL_NEAREST 将告诉 OpenGL 使用离像素点中心最*的纹理来渲染, 这被称作 点样( point sampling); 使用 GL_LINEAR 告诉 OpenGL 会使用离像素点中心最*的四个纹理的*均值来渲染. 这被称作 双线性过滤( bilinear filtering)。
缩小过滤器比放大过滤器的取值更广, 下表是指定缩小过滤器时, 参数 param 的取值, 下面表中的值是为了增强渲染质量。
过滤参数 |
注解 |
GL_NEAREST |
使用像素点中心最*的点渲染 |
GL_LINEAR |
使用双线性过滤 |
GL_NEAREST_MIPMAP_NEAREST |
|
GL_NEAREST_MIPMAP_LINEAR |
|
GL_LINEAR_MIPMAP_NEAREST |
|
GL_LINEAR_MIPMAP_LINEAR |
|
缩小过滤器的参数
在缩小过滤器中, 有4个参数处理mipmap, 这将会在后面的mipmap部分讲解。
默认情况下, 放大过滤器的参数为 GL_LINEAR, 缩小过滤器为 GL_NEAREST_MIPMAP_LINEAR.
在渲染纹理时, OpenGL 会先检查当前的纹理是否加载完成,同时也会处理其他事情,如在选用缩小过滤器的mipmap处理时会验证mipmap的所有级别是否被定义。 如果纹理未完成, 纹理会被禁用。因为缩小过滤器的缺省值使用mipmap,所以你必须指定所有的mipmap级别或是将缩小过滤器的参数设为 *GL\\_LINEAR* 或*GL\\_NEAREST*.
6 简单例程
在初始化函数 init() 中创建了纹理对象, 设定了过滤模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
bool CGfxOpenGL::init () { glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
// 启用 2D 纹理 glEnable (GL_TEXTURE_2D);
m_textureOne = new CTargaImage;
// 加载纹理图像 if (!m_textureOne->Load ("rock.tga")) return false;
// 创建纹理对象, glGenTextures (1, &m_textureObjectOne);
// 绑定纹理对象 glBindTexture (GL_TEXTURE_2D, m_textureObjectOne);
// 设定缩放器的过滤参数 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// 为纹理对象指定纹理图像数据 glTExImage2D (GL_TEXTURE_2D, 0, GL_RGB, m_textureOne->GetWidth(), m_textureOne->GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, m_textureOne->GetImage());
// 创建第二个纹理对象 glGenTexture (1, &m_textureObjectTown); glBindTexture (GL_TEXTURE_2D, m_textureObjectTwo);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, m_textureOne->GetWidth(), m_textureOne->GetHeight(), 0, GL_TGB, GL_UNSIGNED_BYTE, m_textureOne->GetImage());
// 初始化运动变量 m_zPos = -0.5f; m_zMoveNegative = true;
return true; } |
在 init() 函数中, 我们先启用 2D 纹理( glEnable() ), 然后加载图像到 CTargaImage 类中(详见第6章), 然后通过 glGenTextures() 获得一个未被使用的纹理对象, 继而绑定, 指定缩放器的过滤模式, 最后为纹理指定图像数据(通过 glTexImage2D() ). 然后同样的流程创建了第二个纹理对象, 使用了同样的纹理图像数据。只是缩放器的过滤参数做了下更改。
主要的渲染函数有两个 DrawPlane(), Render() :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
void CGfxOpenGL::DrawPlane () { glBegin (GL_TRIANGLE_STRIP); glTexCoord2f (1.0, 0.0); glVertex3f (2.0, -2.0, -2.0); glTexCoord2f (0.0, 0.0); glVertex3f (-2.0, -2.0, -2.0); glTexCoord2f (1.0, 1.0); glVertex3f (2.0, -2.0, 2.0); glTexCoord2f (0.0, 1.0); glVertex3f (-2.0, -2.0, 2.0); glEnd(); }
void CGfxOpenGL::Render () { // 清除屏幕和深度缓存 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 重置当前矩阵 glLoadIdentity ();
// 绘制左边的多边形 glPushMatrix (); // glTranslatef (-3.0, 0.0, m_zPos); glRotatef (90.0, 1.0, 0.0, 0.0);
// 绑定纹理 glBindTexture (GL_TEXTURE_2D, m_textureObjectOne);
// 绘制 Plane DrawPlane (); glPopMatrix();
// 同样地, 绘制右边多边形 glPushMatrix (); glTranslatef (3.0, 0.0, m_zPos); glRotatef (90.0, 1.0, 0.0, 0.0); glBindTexture (GL_TEXTURE_2D, m_textureObjectTwo); DrawPlane (); glPopMatrix();
} |
在 DrawPlane() 中, 我们指定了纹理坐标然后绘制多边形的顶点。在 Render() 中,我们先绑定好纹理对象, 然后绘制多边形。
源文档 <http://caobeixingqiu.is-programmer.com/posts/18999.html>
/////////////////////////////////////////////////////////////////////////////
// 函数名: T3DDEMTextureLoad(HDC hDC, char *bmpfile)
// 参数列表:hDC -- HDC句柄
// bmpfile -- 纹理图象文件名
// 函数功能:装入纹理图象
/////////////////////////////////////////////////////////////////////////////
int T3D::T3DDEMTextureLoad(HDC hDC, char *bmpfile)
{
//设置纹理参数必须在当前HDC中进行,m_hRC为PUBLIC变量
wglMakeCurrent(hDC,m_hRC);
//利用辅助库直接装入BMP图象
image=auxDIBImageLoad(bmpfile);
//处理图象错误的情况,注意作为纹理的图象尺寸必须是2的n次幂
if(image == NULL) return 0;
if((image->sizeX % 64) == 0 && (image->sizeY % 64) == 0)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D,0,3,image->sizeX,image->sizeY,0,GL_RGB,
GL_UNSIGNED_BYTE,image->data);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);// GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);// GL_NEAREST);
//设置纹理环境,确定纹理贴图方式,见有关帮助
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_DECAL);
}
else return 0;
//打开纹理贴图方式
glEnable(GL_TEXTURE_2D);
wglMakeCurrent(hDC,NULL);
//为应用程序设置纹理标志
m_TextureFlag = TRUE;
return 1;
}
物体表面通常并不是具有简单颜色的*滑面,而是有着花纹图案等丰富细节的。
计算机三维图形通过给面贴纹理来表现表面细节。OpenGL默认设置是关闭贴纹理的,所以必须先用命令打开纹理计算。
前面提到过,可以给面指定材质来影响面上各点最终的颜色。能不能同时使用材质和纹理呢?当然是可以的,OpenGL允许你用glTexEnv(GL_TEXTUREN_ENV,GL_TEXTURE_ENV_MODE,mode);命令来设置两者如何结合以决定最终的颜色。有三种模式GL_DECAL,GL_MODULATE,GL_BLEND。
OpenGL纹理的使用分三步:将纹理装入内存,将纹理发送给OpenGL管道,给顶点指定纹理坐标。
OpenGL中纹理图像尺寸必须是2n+2m个像素,m为图片包含的拼接边界的像素数。实际使用中很少使用超过512像素的纹理图,制作纹理文件时要注意适当缩放。通常我们使用Photoshop之类的工具制作纹理图片,并保存成文件,然后在程序中对图片文件进行解码以读入内存。常用的图片格式有.bmp/.jpg/.tif/.gif/.rgb等。在BCB中TPicture直接支持.bmp/.jpg,所以可以用一个LoadFromFile调用完成图片解码读入的工作。
OpenGL体系内有一块纹理内存,在有硬件加速的情况下,可能是位于显卡的VRAM里,否则会是OpenGL库管理的一块内存。在这个纹理内存里图片是以特定的内部格式保存的,有的显卡还支持压缩纹理技术,所以将纹理像素从应用程序内存传到纹理内存需要进行格式转换。这在OpenGL中是通过分别描述像素在应用程序内存和纹理内存的格式来完成的,真正转换工作OpenGL会在内部完成。
定义纹理的命令是glTexImage2/1D(GL_TEX_IMAGE_2/1D,level,components,width,height, border,format,type,*pixels );
OpenGL术语称应用程序内存读出像素的过程为解码(UNPACK),而向纹理内存写像素的过程为编码(PACK)。用glPixelStore*(GL_[UN]PACK_*,参数值);命令设定编码[解码]格式 。对于贴纹理过程我们只需关心解码过程。
如今的显卡通常都有比较大的显存,其中有一部份是专门的纹理存储区,有的卡还可以将最多64M系统内存映射为纹理内存,所以我们有可能把经常要用的纹理就保留在纹理内存里以提高程序性能。OpenGL从1.2开始提供了纹理对象技术,可以把在管道内放多个纹理,每个纹理对应一个数字(名字),需要用到是把这个名字的纹理Bind为当前纹理就可以了。用glGenTextures (n,*textures);命令取得可用的纹理名字的。
当前纹理已经存在之后,就可以给顶点指定纹理坐标,以说明这一顶点的纹理像素在图上的位置。OpenGL会对根据顶点坐标对*面内部进行分割,以确定每一点对应纹理图上的哪个像素。
指定当前纹理坐标的命令是glTexCoord*(s,t,r,q); 此后定义的所有顶点的纹理坐标都会是(s,t,r,q)。目前我们只需知道(s,t)是顶点纹理相对图片左下角原点的位置,坐标值应在0~1.0之间。也可以给顶点指定比1大比0小的纹理坐标,对于这种超出纹理图范围的情况,使你可以用glTexParameter*(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S/T,GL_REPEAT/GL_CLAMP);选择:
- GL_REPEAT:当纹理比表面小时重复使用纹理以填满每个点。
-
GL_CLAMP:比1大的当作1,比0小的当作0。
纹理坐标之所以设为0~1之间的实数,是因为物体表面投影得到的二维*面可能比纹理图大(像素多)或小(像素少),纹理长宽乘上纹理坐标就可以得到对应像素,并且必定在纹理图内。但计算出的像素坐标可能介于像素之间,OpenGL提供了滤波机制来决定最终使用哪个像素,命令是glTexParameter*(GL_TEXTURE_2D,GL_TEXTURE_MAG/MIN_FILTER,GL_NEAREST/GL_LINEAR);。放大和缩小的处理方法可以不同,用参数MAG/MIN分别设定。
- GL_NEAREST:取比较接*的那个像素。
- GL_LINEAR:以周围四个像素的*均值做为纹理。
-
bilinear:二次插值,精度更高,但需要自己动手计算。
对于复杂的物体表面来说逐一指定其纹理坐标是相当烦琐的事,所以OpenGL支持纹理坐标自动生成。可用glTexGen命令开关。详情见手册或联机帮助。
注意:OpenGL1.2还支持GL_TEXTURE_3D,在低版本OpenGL中三维纹理则是一个展扩。
以下代码是展示了完整的贴纹理过程:
//----纹理尺寸----------#define TEXW 64#define TEXH 64byte tex[TEXW][TEXH][3];//----生成纹理数据------int i,j;//----定义纹理--------- glPixelStorei(GL_UNPACK_ALIGNMENT,1); glTexImage2D(GL_TEXTURE_2D,0,3,TEXW,TEXH,0,GL_RGB,GL_UNSIGNED_BYTE,tex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);//----打开纹理计算----- glEnable(GL_TEXTURE_2D);//----使用纹理---------- glBegin(GL_QUADS); glTexCoord2f(-1,-1); glVertex3f(-1,-1,0); glTexCoord2f(-1,1); glVertex3f(-1,1,0); glTexCoord2f(1,1); glVertex3f(1,1,0); glTexCoord2f(1,-1); glVertex3f(1,-1,0); glEnd();
源文档 <http://www.cnblogs.com/yxnchinahlj/archive/2010/11/23/1885233.html>
OpenGL纹理贴图
纹理映射是将指定图像的一部分映射到允许进行纹理映射的每个图段上。这种映射伴随着使用一幅图像的颜色到某一图段的(s,t,r)坐标所指示的位置上并修改该图段的RGBA颜色。但要特别注意的是,在OpenGL中,纹理映射仅在RGBA模式下说明,在颜色索引模式下,它的使用未作定义。概括地说,使用纹理绘制的一般步骤为:定义纹理贴图、控制纹理、说明纹理贴图方式,定义纹理坐标等。
2.1 定义纹理
纹理的定义有两种:连续法和离散法。连续法把纹理定义为一个二元函数,函数的定义域就是纹理空间。而离散法则是把纹理定义在一个二维数组中,该数组表示纹理空间中行间隔和列间隔固定的一组网格点上的纹理值。网格点之间的其它点的纹理值可以通过对相邻网格点上纹理值进行插值来获得。通过纹理空间与物体空间之间的坐标变换,可以把纹理映射到物体表面。一般来说,离散法是较为常用的纹理定义方法。其实现函数为
glTexlmage2D()。该函数的原型如下:void glTexImage2D(Gl_enum target,GLint level,Gl_enum compo—nents, GLsizei width, GLsizei height, Glint border,Gl_enumformat。Gl_enumtype,const GLvoid pixels);其中:target指定纹理映射,此处必须是GL—TEXT—URE 2D;level指定纹理图像分辨率的级数,当只
有一种分辨率时,level=0;Components是选择用于调整和混合的成分;width和height分别指定纹理图像的宽和高,必须是2 ,凡为正数;Border为边界的宽度,必须是0和1;format和type分别指定纹理映射的格式和数据类型;Pixels指定一个指针,指向纹理数据在内存中的位置。
2.2 控制纹理
纹理图像在映射到物体时会产生许多问题。这些问题主要有纹理图像的纹理怎样对应到屏幕上的像素、怎样通过纹理贴图实现纹理缩放和纹理重复等。其实现函数为glTexParmneter(),该函数的原型(以glTexParmneterf形式为例)为:void glTexPa—rmneterf(GLeRuin target,GLeRuin pname,GLfloat pa—ram),其中target参数为目标纹理,pname参数的取值有以下几个:GL TEXTURE MIN FILTER、GL,ⅡⅨ TURE—MAG一兀I肛R、GL—TEXrrI yRE— WRAP一GL— TEXTU RE —WRAP— T,而parmn参数的取值要根据pname而定。
2.3 说明纹理贴图方式
OpenGL用于纹理贴图方式的函数为glTex~v(),该函数的原型(以glTexEnvf形式为例)为:voidglTexEnv(Gl_enum target,Gl_enum pname,GLfloat pa—ram)其中target参数必须为GL—TEXTURE —ENV,pname参数必须为GL—TEXTURE —ENV—MODE,而参数parmn为GL—MODULATE 、GL—DECAL或GL—BLEND。
2.4 定义纹理坐标
纹理坐标控制纹理图像中的像素怎样映射到物体。纹理坐标可以是1、2、3、4维的,通常用齐次坐标来表示,即(5,t,r,q)。OpenGL定义纹理坐标的函数为 xCoord()。该函数共有32种不同的形式。例如:glTexCoord4f(O.Of,0.Of,0.Of,0.Of)。
3 基于MFC的OpenGL中的纹理贴图利用VC++的MFC AppWizard(exe)建立一个新项目OpenglTexture,选择基于单文档界面的应用,其它选项都使用缺省值。在OpenglTextureView.h头文件中,添加各成员变量和成员函数。
for(i=0;i<128;i++)
{
for(j=0;j<64;j++)
{
c=(((i&Ox08)==0) ((j ))==0)*255;
g=(4*i)%255;
b:(j*i)%255;
imag~Ei儿j][0]=(GIaxbyte)b;
image[i儿J儿1]=(GIaxbyte)g;
image~i][j][2]=(GIaibyte)c;
}
}
glPixelStorei(GL—UNPACK— ALIGNMENT,2);
glTexImage2D(GL—TEXTURE一2D,0,3,64,64 ,0,GL— RGB,GL—UNSIGNED— BYTE,image);
//定义纹理
glTexParameteri(GL— TEXTURE一2D,GL— TEXTURE — W RAP— S,
GL— CLAMP);
//控制纹理
glTexParameteri(GL—
TEXTURE一2D,GL— TE XTURE — WRAP—T,GL— CLAMP);
glTexParameteri(GL—TEXTURE一2D,GL—TEXTURE—MAG—FIL—E R,GL— NEAREST);
glTexParameteri(GL— TEXTURE 一2D,GL— TEXTURE — MIN— FIL—TE R,GL— NE AREST);
rSTexEnvf(GL—TEXTURE —ENV,GL—TEXTURE —ENV—MODE,GL— DECAL);//说明纹理贴图方式
glEnable(GL— TEXTURE 一2D);//启动纹理贴图
glShadeModel(GL—SMOOTH);
glBegin(GL— QUADS);//定义纹理坐标和物体几何坐标
glTexCoord2f(1.of,1.Of);glVertex3f(1.Of,1.Of,0.Of);
glTexCoord2f(1.of,0.Of);glVertex3f(1.Of,一1.Of,0.Of);
glTexCoord2f(0.of,0.Of);glVertex3f(一1.Of,一1.Of,0.Of);
glTexCoord2f(0.Of.I.Of);glVertex3f(一I.Of,I.Of,0.Of);
glEnd();
glDisabh(GL—TEXTURE 一2D);//关闭纹理贴图
结束语
利用OpenGL强大的图形功能,可以轻松地实现逼真的贴图模型。在此基础上,运用VC++的MFC应用程序模式,可对OpenGL产生的模型进行更进一步的控制和变化。同时提供给用户一个友好的操作环境,这在当今的时尚编程中是不可或缺的。
源文档 <http://hi.baidu.com/imfei/blog/item/c55aa0c4cff5dec239db4909.html>
int CMubanView::LoadGLTextures()
{
int Status=FALSE; //状态参数跟踪是否能够载入位图以及能否创建纹理
AUX_RGBImageRec* TextureImage[1]; //设置纹理数组
memset(TextureImage,0,sizeof(void*)*1); //清除图像记录,将指针设置为NULL
if (TextureImage[0]=LoadBMP("it.bmp")) //载入位图
{
Status=TRUE;
glGenTextures(1,&m_texture[0]); //创建纹理
glBindTexture(GL_TEXTURE_2D,m_texture[0]); //根据来自位图的数据创建NEAREST纹理
glTexImage2D(GL_TEXTURE_2D, //产生的是2D纹理
0, //图像的详细程度,一般为0
3, //图像的成分,为RGB
TextureImage[0]->sizeX/2, //图像宽
TextureImage[0]->sizeY/2, //图像高
0, //图像边框
GL_RGB, //图像是RGB三色组成
GL_UNSIGNED_BYTE, //图像数据是无符号字节类型
TextureImage[0]->data); //图像数据来源
//采用GL_LINEAR使得纹理从很远处到离屏幕很*时都*滑显示
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // 线形滤波
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // 线形滤波
return Status;
}
AUX_RGBImageRec* CMubanView::LoadBMP(char *Filename)
{
FILE *File=NULL;
if (!Filename) //文件名是否存在(判断结果---文件名是存在的)
{
return NULL;
}
File=fopen(Filename,"r"); //读取文件
if (File) //文件读取成功
{
fclose(File); //关闭文件流
return auxDIBImageLoad(Filename); //载入位图并返回指针
}
return NULL;
}
源文档 <http://bbs.gameres.com/showthread.asp?threadid=100160>
品寒绝顶雪舞人间
OPENGL的纹理
在3D图形中,纹理映射是广泛使用的。纹理映射也是相当复杂的过程:
一 定义纹理
二 控制滤波
三 说明映射方式
四 绘制场景给出顶点的纹理坐标和几何坐标
注意!!纹理映射只能在RGBA模式下使用,不适用于颜色索引模式
1.纹理定义
void glTexImage2D( GLenum target, GLint level, GLint components,
GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const GLvoid *pixels );
定义一个二维纹理映射。
target是常数 GL_TEXTURE_2D
level表示多级分辨率的纹理图象的级数。若只有一种分辨率,level为0。
components是从1到4的整数,1:选择R;2:选择R A;3:选择R G B;
4:选择R G B A;
width height是纹理的尺寸。
format和type描述映射格式和数据类型。它们与前面讲的glDrawPixels()中
OPENGL的纹理
在3D图形中,纹理映射是广泛使用的。纹理映射也是相当复杂的过程:
一 定义纹理
二 控制滤波
三 说明映射方式
四 绘制场景给出顶点的纹理坐标和几何坐标
注意!!纹理映射只能在RGBA模式下使用,不适用于颜色索引模式
1.纹理定义
void glTexImage2D( GLenum target, GLint level, GLint components,
GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const GLvoid *pixels );
定义一个二维纹理映射。
target是常数 GL_TEXTURE_2D
level表示多级分辨率的纹理图象的级数。若只有一种分辨率,level为0。
components是从1到4的整数,1:选择R;2:选择R A;3:选择R G B;
4:选择R G B A;
width height是纹理的尺寸。
format和type描述映射格式和数据类型。它们与前面讲的glDrawPixels()中
GL_NEAREST_MIPMAP_NEAREST
GL_NEAREST_MIPMAP_LINEAR
GL_LINEAR_MIPMAP_NEAREST
GL_LINEAR_MIPMAP_LINEAR
2.1 滤波
原始纹理图象是个方形图象,把它映射到奇形怪状的物体上,一般不可能图象
上的一个象素对应屏幕的一个象素。因此局部放大缩小时,就要定义合适的滤
波方式(以2D为例):
void glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
void glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
前者是放大滤波(GL_TEXTURE_MAG_FILTER),
后者是缩小滤波(GL_TEXTURE_MIN_FILTER);
另外,GL_NEAREST是利用最坐标最靠*象素中心的纹理元素,这有可能使图样
走型,但计算速度快;GL_LINEAR利用线形插值,效果好但计算量大。
2.2重复与缩限
纹理映射可以重复映射或者缩限映射,重复映射时纹理可以在自己的坐标S T方
向重复。
对于重复映射:
void glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
void glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
参数GL_REPEAT改为GL_CLAMP,则缩限,所有大于1的纹理元素值置为1。所有小于
0的纹理元素值置为0。
0的纹理元素值置为0。
3. 映射方式
处理纹理本身图案颜色和物体本身颜色的关系:
void glTexEnv{if}[v](GLenum target,GLenum pname,TYPE param);
target必须是GL_TEXTURE_ENV;
pname是GL_TEXTURE_ENV_MODE,则param可以是 GL_DECAL GL_MODULATE或
GL_BLEND,说明纹理值与原来颜色不同的处理方式。
pname是GL_TEXTURE_ENV_COLOR,则参数param是包含4个浮点数(R、G、B、A)
的数组。这些值只在采用GL_BLEND纹理函数时才采用。
4. 纹理坐标
坐标的定义:纹理图象是方形的,纹理坐标可定义成s,t,r,q坐标,仿照齐次
坐标系的x,y,z,w坐标。
void glTexCoord{1234}{sifd}[v](TYPE coords);
设置当前纹理坐标,此后调用glVertex*()所产生的顶点都赋予当前的纹理坐标。
5. 坐标自动产生
有时不需要为每个物体顶点赋予纹理坐标,可以使用
void glTexGen{if}(GLenum coord,GLenum pname,TYPE param);
coord为:GL_S GL_T GL_R或GL_Q,指明哪个坐标自动产生
pname为GL_TEXTURE_GEN_MODE时
param为常数:GL_OBJECT_LINEAR GL_EYE_LINEAR或GL_SPHERE_MAP,它们决定用
哪个函数来产生纹理坐标
pname为GL_OBJECT_PLANE或GL_EYE_PLANE,param时一个指向参数数组的指针。
先请看一个简单的例子:
////////////////////////////////////////////
//sample.cpp
#include "glos.h"
#include <GL/gl.h>
#include <GL/glaux.h>
#include "windows.h"
void myinit(void);
void CALLBACK display(void);
void CALLBACK reshape(GLsizei w,GLsizei h);
//创建纹理图象的子程序
#define TEXTUREWIDTH 64
#define TEXTUREHEIGHT 64
GLubyte Texture[TEXTUREWIDTH][TEXTUREHEIGHT][3];
void makeTexture(void)
void makeTexture(void)
{
int i,j,r,g,b;
for(i=0;i<TEXTUREWIDTH;i++)
{
for(j=0;j<TEXTUREHEIGHT;j++)
{
r=(i*j)%255;
g=(4*i)%255;
b=(4*j)%255;
Texture[i][j][0 =(GLubyte)r;
Texture[i][j][1 =(GLubyte)g;
Texture[i][j][2 =(GLubyte)b;
}
}
}
void myinit(void)
{
auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow("sample1");
auxInitWindow("sample1");
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
//创建纹理图象的原始数据保存在Texture[][][]中
makeTexture();
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
//定义二维纹理
glTexImage2D(GL_TEXTURE_2D,0,3,TEXTUREWIDTH,
TEXTUREHEIGHT,0,GL_RGB,GL_UNSIGNED_BYTE,
&Texture[0][0][0]);
//控制滤波
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//说明映射方式
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
//这个应该很熟了,启用纹理模式
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
// glShadeModel(GL_FLAT);
}
void CALLBACK reshape(GLsizei w,GLsizei h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//定义立体视景体
gluPerspective(60.0,1.0*(GLfloat)w/(GLfloat)h,1.0,30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-3.6);
}
void CALLBACK display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);//绘制四边形
//先绘制正方形,用来显示实际未变形的纹理图样
//先绘制正方形,用来显示实际未变形的纹理图样
glTexCoord2f(0.0,0.0);glVertex3f(-2.0,-1.0,0.0);
glTexCoord2f(0.0,1.0);glVertex3f(-2.0,1.0,0.0);
glTexCoord2f(1.0,1.0);glVertex3f(0.0,1.0,0.0);
glTexCoord2f(1.0,0.0);glVertex3f(0.0,-1.0,0.0);
//绘制一个不规则四边形,用来显示纹理是如何随物体形状而变形的。
glTexCoord2f(0.0,0.0);glVertex3f(0.0,-1.0,0.0);
glTexCoord2f(0.0,1.0);glVertex3f(0.0,1.0,0.0);
glTexCoord2f(1.0,1.0);glVertex3f(1.41421,1.0,-1.41421);
glTexCoord2f(1.0,0.0);glVertex3f(1.41421,-1.0,-1.41421);
glEnd();
glFlush();
}
void main(void)
{
myinit();
auxReshapeFunc(reshape);
auxMainLoop(display);
}
//end of sample
从例子来看,除了纹理的定义和控制比较麻烦和不容易理解外,其应用是十分
方便的。只须从纹理的坐标系选出合适点附在实际物体顶点上即可。对于复杂
的纹理定义和控制,你也可以自行改变一些参数,看看效果如何。例如把
GL_LINEAR改成GL_NEAREST,则纹理的明显变的粗糙,但计算结果却快的多。
你也可以改动glTexCoord2f()的参数,看看如何选定纹理的一部分(例子中是
选定全部纹理)来贴图。例如1.0改成0.5则选择实际纹理的左上1/4部分来贴图。
下次将给出一个更复杂的纹理应用的例子和说明。18:03 98-1-21
---------------------------------------------
这次将结束纹理的内容。紧接上次,在上次*面纹理贴图中,我们先
定义了一个数组(一维或二维...)来定义纹理的数据,所以纹理本身
是一个N维空间
以上是关于opengl纹理映射总结的主要内容,如果未能解决你的问题,请参考以下文章