{ 欢迎进入第九课。到现在为止,您应该很好的理解OpenGL了。 『CKER:如果没有的话,一定是我翻译的罪过......』。 ( myling补充道:我的罪过更大,呵呵) 您已经学会了设置一个OpenGL窗口的每个细节。 学会在旋转的物体上贴图并打上光线以及混色(透明)处理。 这一课应该算是一课中级教程。 您将学到如下的知识:在3D场景中移动位图,并去除位图上的黑色象素(使用混色)。 接着为黑白纹理上色,最后您将学会创建丰富的色彩, 并把上过不同色彩的纹理相互混合,得到简单的动画效果。 我们在第一课的代码基础上进行修改。先在程序源码的开始处增加几个变量。 出于清晰起见,我重写了整段代码。 }
Var h_RC : HGLRC; // Rendering Context(着色描述表)。 h_DC : HDC; // Device Context(设备描述表) h_Wnd : HWND; // 窗口句柄 h_Instance : HINST; // 程序Instance(实例)。 keys : Array[0..255] Of Boolean; // 用于键盘例程的数组
{下列这几行新加的。 twinkle和 tp是布尔变量, 表示它们只能设为 TRUE 或 FALSE。 twinkle用来跟踪 闪烁 效果是否启用。 tp用来检查 ''''T''''键有没有被按下或松开. (按下时 tp=TRUE, 松开时 tp=FALSE).} twinkle : Boolean; // 闪烁的星星 (新增) tp : Boolean; // ''''T'''' 按下了么? (新增) {现在我们来创建一个结构。 结构这词听起来有点可怕,但实际上并非如此。(就是delphi的纪录类型) 一个结构使用一组简单类型的数据 (以及变量等)来表达较大的具有相似性的数据组合。 我们知道我们在保持对星星的跟踪。 您可以看到下面的就是 stars; 每个星星有三个整型的色彩值。一个红色 (r), 一个绿色 (g), 以及一个蓝色 (b). 此外,每个星星离屏幕中心的距离不同, 而且可以是以屏幕中心为原点的任意360度中的一个角度。 dist的浮点数来保持对距离 的跟踪. angle的浮点数保持对星星角度值的跟踪。 因此我们使用了一组数据来描述屏幕上星星的色彩, 距离, 和角度。 不幸的是我们不止对一个星星进行跟踪。 但是无需创建 50 个红色值、 50 个绿色值、 50 个蓝色值、 50 个距离值 以及 50 个角度值,而只需创建一个数组star。} Type stars = Record // 为星星创建一个结构,结构命名为stars r, g, b: integer; // 星星的颜色 dist: GLfloat; // 星星距离中心的距离 angle: GLfloat; // 当前星星所处的角度 End; Var star : Array[0..49] Of stars; // 使用 ''''stars'''' 结构生成一个包含 50个元素的 ''''star''''数组
{接下来我们设置几个跟踪变量: 星星离观察者的距离变量(zoom), 我们所见到的星星所处的角度(tilt), 以及使闪烁的星星绕Z轴自转的变量spin。 loop变量用来绘制50颗星星。 texture[1]用来存放一个黑白纹理。 如果您需要更多的纹理的话, 您应该增加texture数组的大小至您决定采用的纹理个数。 }
zoom : GLfloat = -15.0; // 星星离观察者的距离 tilt : GLfloat = 90.0; // 星星的倾角 spin : GLfloat; // 闪烁星星的自转 loop : GLuint; // 全局l Loop 变量 texture : Array[0..1] Of GLuint; // 存放一个纹理
Procedure glGenTextures(n: GLsizei; Var textures: GLuint); stdcall; external opengl32;
Procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external opengl32;
{ 紧接着上面的代码就是我们用来载入纹理的代码。 我不打算再详细的解释这段代码。 这跟我们在第六、七、八课中所用的代码是一模一样的。 这一次载入的位图叫做star.bmp。 这里我们使用glGenTextures(1, &texture[0]), 来生成一个纹理。纹理采用线性滤波方式。 }
Function LoadTexture: boolean; // 载入位图并转换成纹理 Var Status : boolean; // Status 指示器 TextureImage : Array[0..1] Of PTAUX_RGBImageRec; // 创建纹理的存储空间 Begin Status := false; ZeroMemory(@TextureImage, sizeof(TextureImage)); // 将指针设为 NULL TextureImage[0] := LoadBMP(''''Star.bmp''''); If TextureImage[0] <> Nil Then Begin Status := TRUE; // 将 Status 设为 TRUE glGenTextures(1, texture[0]); // 创建纹理 // 创建 Nearest 滤波贴图 glBindTexture(GL_TEXTURE_2D, texture[0]); // 生成纹理 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // ( 新增 ) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // ( 新增 )
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX, TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0].data); End; If assigned(TextureImage[0]) Then // 纹理是否存在 If assigned(TextureImage[0].data) Then // 纹理图像是否存在 TextureImage[0].data := Nil; // 释放纹理图像占用的内存 TextureImage[0] := Nil; // 释放图像结构 result := Status; // 返回 Status End; { 在glInit()中设置OpenGL的渲染方式。这里不打算使用深度测试, 如果您使用第一课的代码的话, 请确认是否已经去掉了 glDepthFunc(GL_LEQUAL)和 glEnable(GL_DEPTH_TEST)。 否则,您所见到的效果将会一团糟。 这里我们使用了纹理映射, 因此请您确认您已经加上了这些第一课中所没有的代码。 您会注意到我们通过混色来启用了纹理映射。 }
Procedure glInit(); Begin If (Not LoadTexture) Then // 调用纹理载入子例程( 新增 ) exit; // 如果未能载入,退出( 新增 )
glEnable(GL_TEXTURE_2D); // 启用纹理映射 glShadeModel(GL_SMOOTH); // 启用阴影平滑 glClearColor(0.0, 0.0, 0.0, 0.5); // 黑色背景 glClearDepth(1.0); // 设置深度缓存 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 真正精细的透视修正 glBlendFunc(GL_SRC_ALPHA, GL_ONE); // 设置混色函数取得半透明效果 glEnable(GL_BLEND); // 启用混色
{以下是新增的代码。 设置了每颗星星的起始角度、距离、和颜色。 您会注意到修改结构的属性有多容易。 全部50颗星星都会被循环设置。 要改变star[1]的角度我们所要做的只是star[1].angle=某个数值; 就这么简单!} For loop := 0 To 49 Do // 创建循环设置全部星星 Begin star[loop].angle := 0.0; // 所有星星都从零角度开始 {第loop颗星星离中心的距离是将loop的值除以星星的总颗数,然后乘上5.0。 基本上这样使得后一颗星星比前一颗星星离中心更远一点。 这样当loop为50时(最后一颗星星),loop 除以 num正好是1.0。 之所以要乘以5.0是因为1.0*5.0 就是 5.0。 『CKER:废话,废话!这老外怎么跟孔乙己似的!:)』 5.0已经很接近屏幕边缘。我不想星星飞出屏幕,5.0是最好的选择了。 当然如果如果您将场景设置的更深入屏幕里面的话, 也许可以使用大于5.0的数值,但星星看起来就更小一些(都是透视的缘故)。 您还会注意到每颗星星的颜色都是从0~255之间的一个随机数。 也许您会奇怪为何这里的颜色得取值范围不是OpenGL通常的0.0~1.0之间。   [1] [2] [3] 下一页 [系统软件]InstallShield Express for delphi制作安装程序定… [常用软件]InstallShield Express制作Delphi数据库安装程序 [Delphi程序]为什么选择Delphi.Net ? [Delphi程序]《关于VisiBroker For Delphi的使用》(4) [Delphi程序]Delphi 程序员代码编写标准指南 [Delphi程序]转贴:Conversion to Delphi 6: Missing unit Pro… [Delphi程序]Borland Delphi 9 的新特性 [Delphi程序]Delphi 键盘码表 [Delphi程序]Chuck Jazdzewski的离开意味着Delphi的终结吗? [Delphi程序]Delphi Access violations 问题的解决之道
|