51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 2548|回复: 0
打印 上一主题 下一主题

Delphi游戏编程导学——OpenGL入门

[复制链接]
  • TA的每日心情
    慵懒
    2015-1-8 08:46
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]测试小兵

    跳转到指定楼层
    1#
    发表于 2007-11-30 15:48:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    这次我结合以前的教学,把入门知识给大家讲解完整,让摸不到门路的朋友尽快找到感觉。
    我使用的OpenGL接口文件还是那个DOT,因为我很喜欢在VCL环境里编程,这样才能体现Delphi的高效。
    关于DOT的安装,以及绘制简单的图形等等,请参考我以前的教学:
    http://bbs.gameres.com/showthread.asp?threadid=66287

    好了,开始我们这次的主题吧。
    按照OpenGL官方的说法,纹理和贴图是两个概念。
    纹理被称为material, 贴图被称为texture.
    (其实中文是我自己翻译的,我完全是为了方便自己的理解)。
    我们这次主要讲的是贴图,因为纹理的使用只要参照NeHe的教学或者红宝书/Super Bible 就能掌握了。
    而贴图要实现,就不是很容易了。因为涉及到如何将硬盘(也可以是其它媒介)上的图形文件读取,并
    转换成OpenGL的贴图格式这样的问题。
    Delphi里想读取一个图形文件是很简单的,比如 bmp 图形的读取

    var
      bp : TBitmap;
    ...
      bp := TBitmap.Create;
      bp.LoadFromFile('name.bmp');
    ...
      bp.Free

    要转换成OpenGL的贴图格式,其实很简单,只要读取bmp图形的RGB值,
    然后按照RGB的顺序保存到一个Byte数组里就行了。
    var
       bb : array[0..bp.Width,0..bp.Height,0..2] of Byte;
    ...
       for x := 0 to bp.Width -1 do
         for y := 0 to bp.Height - 1 do
         begin
           bb[x,y,0] := GetRvalue( bp.Canvas.Pixels[x,y] )
           bb[x,y,1] := GetGvalue( bp.Canvas.Pixels[x,y] );
           bb[x,y,2] := GetBvalue( bp.Canvas.Pixels[x,y] );
         end;
    ...

    但是这次我可不想费劲来使用bmp图形,因为DOT里为我们准备好了更加方便的贴图生成方式。
    好了,让我们来看看实际的代码吧。

    //和上次教学里的代码一样的地方,我就不说了,重点看看新加的东西
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, DotWindow, GL, GLu, GLext, TGA2;

    //uses这里我只加了一个对 TGA2 单元的引用
    type
      TForm1 = class(TDotForm)
        procedure FormPaint(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        bFullScreen : Bool;
        rX, rY      : GLuint;

        procedure BuildTexture;
        procedure DrawScene;
      public
        { Public declarations }
      end;

    //这里我加了一个新函数 BuildTexture,是用于生成贴图的
    var
      Form1: TForm1;

    implementation
    {$R *.dfm}
    //看看这个新函数的内容吧
    procedure TForm1.BuildTexture;
    var
      bp      : TTGAImage;
    //增加对 TGA2 单元的引用就是为了读取 tga 图形
    //这里先声名一个tga图形类的变量
    begin

    //定义贴图的方式
      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    //下面两句先申请内存,然后读取程序所在目录里的tga文件
      bp := TTGAImage.Create;
      bp.LoadFromFile('tex02.tga');

    //如果你的显卡不支持BGR格式,就需要下面的语句
    //  bp.BGRtoRGB;

    //分配贴图对象的号码
    glBindTexture(GL_TEXTURE_2D, 100);
              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
                  GL_LINEAR);
              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                  GL_LINEAR);
    //这里是实际分配数据的地方,最后的参数直接读取bp的Data值就行了
              glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                           64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, bp.Data);

    //创建第二个贴图,直接读取新的文件就可以了
      bp.LoadFromFile('tex01.tga');
    //  bp.BGRtoRGB;
    glBindTexture(GL_TEXTURE_2D, 200);
              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
              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_RGBA,
                           64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, bp.Data);

    //这是第三个贴图
      bp.LoadFromFile('tex00.tga');
    //  bp.BGRtoRGB;
    glBindTexture(GL_TEXTURE_2D, 300);
              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
              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_RGBA,
                           64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, bp.Data);
      bp.Free;
    end;

    procedure TForm1.DrawScene;
    begin
      glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

      glLoadIdentity;
      glTranslatef(0, 0, -3);
      glRotatef(rX, 1, 0, 0);
      glRotatef(rY, 0, 1, 0);

    //绘制物体前调用分配的贴图
    //前
    glBindTexture(GL_TEXTURE_2D, 100);
      glBegin(GL_QUADS);
        glColor3f(1, 0, 0);
    //每个顶点前都要设置贴图坐标
        glTexCoord2F(0, 0);
        glVertex3f(-0.5,-0.5, 0.5);

        glTexCoord2F(1, 0);
        glVertex3f(0.5,-0.5, 0.5);

        glTexCoord2F(1, 1);
        glVertex3f(0.5, 0.5, 0.5);

        glTexCoord2F(0, 1);
        glVertex3f(-0.5, 0.5, 0.5);
      glEnd;
    //后
    glBindTexture(GL_TEXTURE_2D, 300);
      glBegin(GL_QUADS);
        glColor3f(0, 1, 0);
        glTexCoord2F(0, 0);
        glVertex3f(-0.5,-0.5,-0.5);
    //    glVertex3f(0.5, -0.5,-0.5);

        glTexCoord2F(1, 0);
        glVertex3f(-0.5, 0.5,-0.5);
    //    glVertex3f(-0.5, -0.5,-0.5);

        glTexCoord2F(1, 1);
        glVertex3f(0.5, 0.5,-0.5);
    //    glVertex3f(-0.5, 0.5,-0.5);

        glTexCoord2F(0, 1);
        glVertex3f(0.5,-0.5,-0.5);
    //    glVertex3f(0.5, 0.5,-0.5);
      glEnd;
    //左
    glBindTexture(GL_TEXTURE_2D, 200);
      glBegin(GL_QUADS);
        glColor3f(0, 0, 1);
        glTexCoord2F(0, 0);
        glVertex3f(-0.5,-0.5,-0.5);

        glTexCoord2F(1, 0);
        glVertex3f(-0.5,-0.5, 0.5);

        glTexCoord2F(1, 1);
        glVertex3f(-0.5, 0.5, 0.5);

        glTexCoord2F(0, 1);
        glVertex3f(-0.5, 0.5,-0.5);
      glEnd;
    //右
      glBegin(GL_QUADS);
        glColor3f(1, 1, 0);
        glVertex3f(0.5,-0.5,-0.5);

        glVertex3f(0.5, 0.5,-0.5);
        glVertex3f(0.5, 0.5, 0.5);
        glVertex3f(0.5,-0.5, 0.5);
    //顶
        glColor3f(1, 0, 1);
        glVertex3f(-0.5, 0.5,-0.5);

        glVertex3f(-0.5, 0.5, 0.5);
        glVertex3f(0.5, 0.5, 0.5);
        glVertex3f(0.5, 0.5,-0.5);
    //底
        glColor3f(1, 1, 1);
        glVertex3f(-0.5,-0.5,-0.5);

        glVertex3f(0.5,-0.5,-0.5);
        glVertex3f(0.5,-0.5, 0.5);
        glVertex3f(-0.5,-0.5, 0.5);
      glEnd;

      Self.Context.PageFlip;
    end;

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      dotSetDisplayMode(0, 0, 0, 0);
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      bFullScreen := False;
      rX := 360;
      rY := 360;

      if bFullScreen then
      begin
        dotSetDisplayMode(800, 600, 32, 60);
        Self.BorderStyle := bsNone;
        Self.Height := 600;
        Self.Width  := 800;
        Self.WindowState := wsMaximized;
        Self.Context.DC  := GetDC(Self.Handle);
        ShowCursor(False);
      end
      else
      begin
        Self.Height := 600;
        Self.Width  := 800;
      end;

      Self.Context.QuickPF(32, 0, 24, 0, 0);
      Self.Context.InitGL;

    glShadeModel(GL_SMOOTH);
    glEnable(GL_DEPTH_TEST);
    //打开贴图模式
      glEnable(GL_TEXTURE_2D);

    glClearColor(0, 0, 0, 0);
      glMatrixMode(GL_PROJECTION);
        gluPerspective(60.0, Self.ClientWidth / Self.ClientHeight, 1.0, 100.0);
      glMatrixMode(GL_MODELVIEW);

    //调用新函数
      BuildTexture;
    end;

    procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      case Key of
        VK_UP:
        begin
          if rX = 0 then
            rX := 360;
          Dec(rX);
          DrawScene;
        end;
        VK_DOWN:
        begin
          if rX = 720 then
            rX := 360;
          Inc(rX);
          DrawScene;
        end;
        VK_LEFT:
        begin
          if rY = 0 then
            rY := 360;
          Dec(rY);
          DrawScene;
        end;
        VK_RIGHT:
        begin
          if rY = 720 then
            rY := 360;
          Inc(rY);
          DrawScene;
        end;
        VK_ESCAPE:
          Close;
      end;
    end;

    procedure TForm1.FormPaint(Sender: TObject);
    begin
      DrawScene;
    end;


    end.

    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-25 19:40 , Processed in 0.065912 second(s), 27 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表