• GL 纹理 格式 资料备份



    分别转载至:http://www.tuicool.com/articles/qAbYfq    和 http://www.verydemo.com/demo_c161_i114362.html



    在手机游戏开发中怎样选择图像素材格式?

    How to choose the picture texture format in the game develop?

    这是我在知乎上的一个回答, 这里是原文 。

    回答的前提是:使用OpenGL来渲染。

    分几个点来回答。

    1. RGBA4444真的比RGBA8888占用的RAM要少

    事实上这里说的RAM,是指的显存而非内存。OpenGL支持以这几种形式来使用纹理资源(viahttp://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml ):

    • GL_UNSIGNED_BYTE(RGBA8888或RGBA888)
    • GL_UNSIGNED_SHORT_5_6_5
    • GL_UNSIGNED_SHORT_4_4_4_4
    • GL_UNSIGNED_SHORT_5_5_5_1

    在程序将图片加载系统内存后,会依据你选择的形式(RGBA8888/RGB565 etc.)对其做一些处理(怎么处理后面说)。然后就将这些纹理上传到显卡的显存,之后会把这些图片占用的内存删除掉。

    也就是说。加载的图片在变成了显卡能处理的纹理之后。就根本不会保存在内存中。所以你看不到内存占用的变化。

    当然。这个操作是由程序猿自行控制(或者由你选择的框架来决定)的,你假设决定不删除它们而让它们留在内存中。那当然会占用系统内存。

    2. TexturePackger导出的图片是个什么情况?

    你能够拿一张图片尝试,在导出为RGBA8888和RGBA4444的时候。它们的文件大小确实是不同的。请看以下的图片。并注意我加亮的部分:

    RGBA8888

    RGBA4444

    对于同一张图片,在RGBA8888格式下。唯一颜色数是5864;而RGBA4444格式下,唯一颜色数是1454。文件大小降低了80KB左右。

    至于图片信息中显示的 Original Colors依旧是32Bit。这是由于在图像处理软件显示图像的时候。内部使用的色彩是8888的。

    3. 保存的文件是个什么情况?

    上面的RGBA4444是否就真的使用的16bit(4×4)来保存每一个像素呢?

    不是。

    我们知道,PNG格式能够保存成 8bit 和 24bit 以及 24bit(with alpha channel)=32bit 三种格式。而JPEG格式是24bit的。RGBA4444有16bit,所以不管怎样是不能使用8bit格式来保存的。

    因此,这个RGBA4444是使用24bit(或者32bit)格式来保存的。

    那么,为什么RGBA4444的文件体积会比RGBA8888小呢?

    注意上面的两个 Number of unique colors。在这里,压缩算法起了作用,将同样的颜色压缩了,导致文件体积变小。

    只是。即使是採用相同的色深保存,我仍然要说的是。 RGBA4444比RGBA8888的图像质量会差一些 。

    4. 怎么做到的?

    要回答上面的下划线部分结论。我们须要提出一个新的问题:RGBA8888转换成RGBA4444,发生了什么变化?

    先来看看它们分别代表什么:

    • RGBA8888 : R 8bit + G 8bit + B 8bit + A 8bit
    • RGBA4444 : R 4bit + G 4bit + B 8bit + A 8bit

    8bit 能代表的最大数字是256。也就是说每种颜色能够表达256个级别,那么8×3=24bit(不算A)就能表现 2^{24} = 167772165 种颜色。

    相同的,RGBA4444能表现的颜色是 2^{12} = 4096 种颜色。

    也就是说。进行这样的转换。是一定会丢失颜色信息的。

    以 0xFFFFFFFF 这个RGBA8888 颜色为例。转换成 RGBA4444 能够这样做:

    unsigned int pixel32 = 0xFFFFFFFF;
    unsigned short pixel16 = 
                ((((pixel32 >> 0) & 0xFF) >> 4) << 12) | // R
                ((((pixel32 >> 8) & 0xFF) >> 4) <<  8) | // G
                ((((pixel32 >> 16) & 0xFF) >> 4) << 4) | // B
                ((((pixel32 >> 24) & 0xFF) >> 4) << 0);  // A

    unsigned int pixel32 = 0xFFFFFFFF ;

    unsigned short pixel16 =

                 ( ( ( ( pixel32 >> 0 ) & 0xFF ) >> 4 ) << 12 ) | // R

                 ( ( ( ( pixel32 >> 8 ) & 0xFF ) >> 4 ) <<    8 ) | // G

                 ( ( ( ( pixel32 >> 16 ) & 0xFF ) >> 4 ) << 4 ) | // B

                 ( ( ( ( pixel32 >> 24 ) & 0xFF ) >> 4 ) << 0 ) ;    // A

    终于的结果是 0xFFFF。

    5. iOS用什么?

    当然是用pvr格式。

    pvr是iOS设备的图形芯片 PowerVR 图形 支持的专用压缩纹理格式。

    它在PowerVR图形芯片中效率极高,占用显存也小。 
    性能对照能够看这里: In Depth iOS & Cocos2D Performance Analysis with Test Project 。

    6. Android用什么?

    Android设备就没有那么好的运气了。因为硬件平台不统一。每一个厂商的GPU可能使用不同的纹理压缩格式。所以还是老老实有用PNG比較好。

    =============================================

    =======================================



    本章你将学到

    • 纹理映射基础知识
    • 纹理坐标
    • 纹理对象及绑定
    • 纹理过滤
    • mipmap和自己主动生成mipmap
    • 纹理參数, 外包模式, 细节级别
    • 纹理环境和纹理函数

    Table of Contents

    • 1 概述
    • 2 预备知识: 纹理坐标
    • 3 使用纹理映射
      • 3.1 纹理对象
      • 3.2 纹理绑定
      • 3.3 删除纹理对象
      • 3.4 驻留纹理
      • 3.5 纹理优先级
    • 4 指定纹理
      • 4.1 2D 纹理
      • 4.2 1D 纹理
      • 4.3 3D 纹理
      • 4.4 Cube Map 纹理
    • 纹理过滤
    • 6 简单例程

    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_1DGL_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 int textureObjects[3];
    glGenTexture(3, textureObjects);

    3.2 纹理绑定

    在第一次绑定一个纹理对象时, 会将一系列初始值来适应你的应用. 函数 glBindTexture() 用于绑定操作:


    void glBindTexture(GLenum target, GLuint texture);

    target 指定了纹理类型: GL_TEXTURE_1D GL_TEXTURE_2D GL_TEXTURE_3DGL_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 分别相应常量 LUMINANCELUMINANCE_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 中的格式。能够取值例如以下:

    图像数据数组 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 值

    參数 type 定义了图像数据数组 texels 中的数据类型。可取值例如以下

    图像数据数组 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

    你可能会注意到有压缩类型, 先看看 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_XGL_TEXTURE_CUBE_MAP_NEGATIVE_XGL_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() 中,我们先绑定好纹理对象, 然后绘制多边形。



  • 相关阅读:
    ::作用域运算符
    c++多继承
    关于C++命名空间namespace的理解与使用介绍
    __stdcall、__cdcel和__fastcall三者的区别
    JAVA自定义异常
    JS仿淘宝星星评价
    JAVA代码实现下载单个文件,和下载打包文件
    Oracle求部门员工工资占总工资的比率
    java代码实现打包多个文件下载功能
    Jfinal验证码功能
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7273261.html
Copyright © 2020-2023  润新知