WEB开发网
开发学院软件开发Delphi NeHe的opengl教程delphi版(6)----纹理映射(贴... 阅读

NeHe的opengl教程delphi版(6)----纹理映射(贴图)

 2006-02-04 13:40:54 来源:WEB开发网   
核心提示: {贴图可以极大的节省CPU时间,呵呵,NeHe的opengl教程delphi版(6)----纹理映射(贴图),但是这一节费了我比较多的时间 : (因为用到了opengl的辅助库,现在这个库的函数已经很少有人用了, If assigned(TextureImage[0]) Then // 纹理是否存在 If ass
 

{

贴图可以极大的节省CPU时间。呵呵,但是这一节费了我比较多的时间 : (

因为用到了opengl的辅助库,现在这个库的函数已经很少有人用了,但是我还是找到了,感谢zdcnow(磁效应),他给我提供的这个辅助库的delphi版本。在学习本节之前,请大家到网上下载glaux.dll、Glaux.pas文件,并加到项目中。

好了,让我们继续OPENGL之路.

首先我们需要加进SysUtils单元,因为我们这节要用到文件操作,我们还要将Glaux单元加进来。

然后我们在第一课的基础上加上几个变量,xrot , yrot 和 zrot 。这些变量用来使立方体绕X、Y、Z轴旋转。texture[] 为一个纹理分配存储空间。如果您需要不止一个的纹理,应该将数字1改成您所需要的数字。

}

VAR

  h_RC       : HGLRC;       // Rendering Context(着色描述表)。
  h_DC       : HDC;        // Device Context(设备描述表)
  h_Wnd       : HWND;       // 窗口句柄
  h_Instance    : HINST;       // 程序Instance(实例)。
  keys       : Array[0..255] Of Boolean; // 用于键盘例程的数组

  xrot,                 // X 旋转量 ( 新增 )
  yrot,                 // Y 旋转量 ( 新增 )
  zrot       : GLfloat;      // Z 旋转量 ( 新增 )

  Texture      : Array[0..1] Of GLuint; // 存储一个纹理 ( 新增 )

{然后引载入opengl32.dll中的两个过程,我们要用到他们}


PRocedure glGenTextures(n: GLsizei; Var textures: GLuint); stdcall; external
  opengl32;
Procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external
  opengl32;

{接下来我们需要增加一个新的函数,用来再入图像,该函数的返回类型在Glaux.pas中定义如下:

TAUX_RGBImageRec= record
    sizeX, sizeY: GLint;
     data: pointer;
      end;
 PTAUX_RGBImageRec= ^TAUX_RGBImageRec;

具体含义会在后面介绍}

Function LoadBmp(filename: pchar): PTAUX_RGBImageRec;
Var
  BitmapFile    : Thandle;      // 文件句柄
Begin
  //接下来检查文件名是否已提供
  If Filename = '' Then         // 确保文件名已提供。
    result := Nil;           // 如果没提供,返回 NULL
  //接着检查文件是否存在。
  BitmapFile := FileOpen(Filename, fmOpenWrite); //尝试打开文件
  //如果我们能打开文件的话,很显然文件是存在的。

  If BitmapFile > 0 Then        // 文件存在么?
    Begin
     //关闭文件。
     FileClose(BitmapFile);     // 关闭句柄
     //auxDIBImageLoad(Filename) 读取图象数据并将其返回。
     result := auxDIBImageLoadA(filename); //载入位图并返回指针
    End
  Else
    //如果我们不能打开文件,我们将返回NiL。
    result := Nil;           // 如果载入失败,返回NiL。
End;

//接下来在创建一个新函数,用来载入纹理贴图

Function LoadTexture: boolean;

//Status 的变量。我们使用它来跟踪是否能够载入位图以及能否创建纹理。
// Status 缺省设为 FALSE (表示没有载入或创建任何东东)。
//TextureImage变量PTAUX_RGBImageRec类型  存储位图的图像记录。
//次记录包含位图的宽度、高度和数据。

Var
  Status      : boolean;
  TextureImage   : Array[0..1] Of PTAUX_RGBImageRec;
Begin
  Status := false;
  ZeroMemory(@TextureImage, sizeof(TextureImage)); // 将指针设为 NULL
  TextureImage[0] := LoadBMP('Texture.bmp');
  If TextureImage[0] <> Nil Then
    Begin
     Status := TRUE;         // 将 Status 设为 TRUE
     //现在使用中 TextureImage[0] 的数据创建纹理。
     //glGenTextures(1, texture[0]) 告诉OpenGL我们想生成一个纹理名字
     //(如果您想载入多个纹理,加大数字)。
     //glBindTexture(GL_TEXTURE_2D, texture[0]) 告诉OpenGL将纹理名字 texture[0] 绑定到纹理目标上。
     //2D纹理只有高度(在 Y 轴上)和宽度(在 X 轴上)。
     //主函数将纹理名字指派给纹理数据。
     //本例中我们告知OpenGL, &texture[0] 处的内存已经可用。
     //我们创建的纹理将存储在 &texture[0] 的 指向的内存区域。
     glGenTextures(1, texture[0]);  // 创建纹理
     glBindTexture(GL_TEXTURE_2D, texture[0]);  // 使用来自位图数据生成 的典型纹理
     //下来我们创建真正的纹理。
     //下面一行告诉OpenGL此纹理是一个2D纹理 ( GL_TEXTURE_2D )。
     //数字零代表图像的详细程度,通常就由它为零去了。
     //数字三是数据的成分数。因为图像是由红色数据,绿色数据,蓝色数据三种组分组成。
     //TextureImage[0].sizeX 是纹理的宽度。
     //如果您知道宽度,您可以在这里填入,但计算机可以很容易的为您指出此值。
     // TextureImage[0].sizey 是纹理的高度。
     //数字零是边框的值,一般就是零。
     // GL_RGB 告诉OpenGL图像数据由红、绿、蓝三色数据组成。
     //GL_UNSIGNED_BYTE 意味着组成图像的数据是无符号字节类型的。
     //最后... TextureImage[0].data 告诉OpenGL纹理数据的来源。
     //此例中指向存放在 TextureImage[0] 记录中的数据。

   // 生成纹理
     glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
       TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
       TextureImage[0].data);

   //下面的两行告诉OpenGL在显示图像时,
     //当它比放大得原始的纹理大(GL_TEXTURE_MAG_FILTER)
     //或缩小得比原始得纹理小(GL_TEXTURE_MIN_FILTER)时OpenGL采用的滤波方式。
     //通常这两种情况下我都采用 GL_LINEAR。这使得纹理从很远处到离屏幕很近时都平滑显示。
     //使用 GL_LINEAR需要CPU和显卡做更多的运算。
     //如果您的机器很慢,您也许应该采用 GL_NEAREST 。
     //过滤的纹理在放大的时候,看起来斑驳的很(马赛克啦)。
     //您也可以结合这两种滤波方式。在近处时使用 GL_LINEAR ,远处时 GL_NEAREST 。
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  // 线形滤波
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  // 线形滤波
    End;
  //现在我们释放前面用来存放位图数据的内存。
  //我们先查看位图数据是否存放在处。
  //如果是的话,再查看数据是否已经存储。
  //如果已经存储的话,删了它。
  //接着再释放 TextureImage[0] 图像结构以保证所有的内存都能释放。
  If assigned(TextureImage[0]) Then   // 纹理是否存在
    If assigned(TextureImage[0].data) Then // 纹理图像是否存在
     TextureImage[0].data := Nil;  // 释放纹理图像占用的内存
  TextureImage[0] := Nil;        // 释放图像结构
  // 最后返回状态变量。如果一切OK,变量 Status 的值为 TRUE 。否则为 FALSE
  result := Status;           // 返回 Status
End;

Tags:NeHe opengl 教程

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接