OpenGL完全教程 第六章 纹理贴图

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

OpenGL完全教程 第六章 纹理贴图

作者:何咏 日期:2006-2-3 20:56:39 点击:4719

如需转载本文,请声明作者及出处。

第六章 纹理贴图

截至目前为止,我们已经能够绘制各种3D物体,并为它们增加光照效果,使它们更具有立体感。但是,在实际运用中,我们不仅仅需要简单地绘制一个物体的轮廓,我们需要绘制蓝天白云、真实的墙壁和物体、人物和树木。要达到这一目的,简单的将模型的轮廓绘制出来时远远不够的。我们需要使用纹理贴图来再现真实的细节。

在计算机硬件高速发展的今天,即使是最低端的显卡也能很快地处理大量的纹理,满足我们的需求。这些条件可以让我们毫无顾虑的使用OpenGL的纹理贴图功能,绘制出形形色色的物体。

本章将是学习OpenGL的最后一个基础章节。本章之后,我们将开始接触一些OpenGL的高级专题

学习本章内容,你将了解:

•什么是纹理贴图

•如何创建纹理图像

•OpenGL中贴图的方式

•使用纹理对象来管理的纹理

•将纹理运用到图元上

•自动生成纹理坐标

•多贴图纹理

6.0 准备工作

由于Delphi为我们所提供的OpenGL头文件是OpenGL1.0版本的,因此里面缺少一些函数的声明,这导致我们不能使用直接调用这些函数。因此我们要手动为OpenGL库添加下面的代码一进行补完:

procedure glBindTexture(target: GLEnum; texture: GLuint); stdcall; external opengl32;

procedure glDeleteTextures(n: GLsizei; textures: PGLuint); stdcall; external opengl32;

procedure glGenTextures(n: GLsizei; textures: PGLuint); stdcall; external opengl32;

function glIsTexture(texture: GLuint): GLboolean; stdcall; external opengl32;

procedure glPolygonOffset(factor, units: GLfloat); stdcall; external opengl32;

function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum;

Data: Pointer): GLint; stdcall; external GLU32;

6.1 什么是纹理贴图

纹理贴图,从本质上讲,是一个位图图像。在程序中,一个纹理图像就是一个一维或二维数组,

存储每一个像素的颜色值(包括R、G、B、A分值,分别存储一个像素的红、绿、蓝、透明度分值)。而运用一个纹理贴图,就是把纹理图像根据纹理坐标对应到图元上。

比如,现在有一个三角形,顶点坐标分别是V1、V2、V3,以及一幅纹理图像,如图6.1-1所示:

图6.1-1

现在,我们可以在绘制三角形之前,为顶点V1、V2、V3指定纹理坐标,使每一个顶点的坐标和它的纹理坐标一一对应,如图6.1-2所示:

图6.1-2 纹理映射

一旦我们建立起这种对应关系,就可以开启纹理贴图功能,让OpenGL根据顶点的贴图坐标渲染出指定的三角形,如图6.1-3那样:

图6.1-3 使用纹理渲染图元

这就是纹理贴图的原理。

6.2 创建纹理图像

正如上一节所提到的那样,纹理贴图其实是一个二维数组。而对于一般程序而言,纹理贴图可以从位图中读取。你可以定义自己的纹理图像格式,然后使用Delphi提供的TFileStream类读取文件中的像素,但在初学OpenGL的阶段,我们暂时从Bmp文件中读取纹理图像,然后使用OpenGL将这幅图像打包成纹理。OpenGL要求纹理的高度和宽度都必须是2的n次方大小,只有满足这个条件,这个纹理图片才是有效的。一旦我们完成了这一步,我们就可以在任意时刻使用这个纹理图像来渲染图形了。

首先,我们创建一个TBitmap类型的对象,用于读取Bmp文件:

var Bit:TBitmap;

begin

Bit:=TBitmap.Create;

Bit.LoadFromFile(FileName);

...

Bit.Free;

end;

接下来,我们可以使用Bitmap对象的ScanLine属性获取这个Bitmap中每一像素的颜色值。有关ScanLine属性的用法,可以参看我早期的一篇文章——《探究Delphi的图形处理 之六 -- 使用ScanLine属性进行高效的图像处理》。这里不再详细讲解。总之,你可以使用下面的代码来获取Bitmap对象中每一点的像素值:

type

TPixels = record

R,G,B:Byte;

end;

TPixelPointer = array of PByteArray;

procedure ReadPixels(Bit : TBitmap; var Pixels : TPixels;

var PixPointer:TPixelPointer);

var PixPtr: PbyteArray;

i, j ,m: Integer;

begin

SetLength(Pixels,Bit.Width,Bit.Height);

相关文档
最新文档