TA的每日心情 | 慵懒 2015-1-8 08:46 |
---|
签到天数: 2 天 连续签到: 1 天 [LV.1]测试小兵
|
这次我结合以前的教学,把入门知识给大家讲解完整,让摸不到门路的朋友尽快找到感觉。
我使用的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.
|
|