|
; 这里我们使用的颜色设置函数是glColor4ub,而不是以前的glColor4f。 ub意味着参数是Unsigned Byte型的。 一个byte的取值范围是0~255。 这里使用byte值取随机整数似乎要比取一个浮点的随机数更容易一些。 } star[loop].dist := (Trunc(loop) / 50) * 5.0; // 计算星星离中心的距离 star[loop].r := random(256); // 为star[loop]设置随机红色分量 star[loop].g := random(256); // 为star[loop]设置随机红色分量 star[loop].b := random(256); // 为star[loop]设置随机红色分量 End;
End;
{ 现在我们转入glDraw()绘图代码。 如果您使用第一课的代码,删除旧的DrawGLScene代码,只需将下面的代码复制过去就行了。 实际上,第一课的代码只有两行,所以没太多东西要删掉的。 }
Procedure glDraw(); Begin glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存
glBindTexture(GL_TEXTURE_2D, texture[0]); // 选择纹理 For loop := 0 To 49 Do // 循环设置所有的星星 Begin glLoadIdentity(); // 绘制每颗星星之前,重置模型观察矩阵 glTranslatef(0.0, 0.0, zoom); // 深入屏幕里面 (使用 ''''zoom''''的值) glRotatef(tilt, 1.0, 0.0, 0.0); // 倾斜视角(使用 ''''tilt''''的值) { 现在我们来移动星星。 星星开始时位于屏幕的中心。 我们要做的第一件事是把场景沿Y轴旋转。 如果我们旋转90度的话,X轴不再是自左至右的了,他将由里向外穿出屏幕。 为了让大家更清楚些,举个例子。假想您站在房子中间。 再设想您左侧的墙上写着-x,前面的墙上写着-z, 右面墙上就是+x咯,您身后的墙上则是+z。 加入整个房子向右转90度,但您没有动,那么前面的墙上将是-x而不再是-z了。 所有其他的墙也都跟着移动。-z出现在右侧,+z出现在左侧,+x出现在您背后。 神经错乱了吧?通过旋转场景,我们改变了x和z平面的方向。 第二行代码沿x轴移动一个正值。 通常x轴上的正值代表移向了屏幕的右侧(也就是通常的x轴的正向), 但这里由于我们绕y轴旋转了坐标系,x轴的正向可以是任意方向。 如果我们转180度的话,屏幕的左右侧就镜像反向了。 因此,当我们沿 x轴正向移动时,可能向左,向右,向前或向后。 } glRotatef(star[loop].angle, 0.0, 1.0, 0.0); //旋转至当前所画星星的角度 glTranslatef(star[loop].dist, 0.0, 0.0); // 沿X轴正向移动 { 接着的代码带点小技巧。 星星实际上是一个平面的纹理。 现在您在屏幕中心画了个平面的四边形然后贴上纹理,这看起来很不错。 一切都如您所想的那样。但是当您当您沿着y轴转上个90度的话, 纹理在屏幕上就只剩右侧和左侧的两条边朝着您。 看起来就是一条细线。 这不是我们所想要的。我们希望星星永远正面朝着我们,而不管屏幕如何旋转或倾斜。 我们通过在绘制星星之前,抵消对星星所作的任何旋转来实现这个愿望。 您可以采用逆序来抵消旋转。当我们倾斜屏幕时,我们实际上以当前角度旋转了星星。 通过逆序,我们又以当前角度"反旋转"星星。也就是以当前角度的负值来旋转星星。 就是说, 如果我们将星星旋转了10度的话,又将其旋转-10度来使星星在那个轴上重新面对屏幕。 下面的第一行抵消了沿y轴的旋转。然后,我们还需要抵消掉沿x轴的屏幕倾斜。 要做到这一点,我们只需要将屏幕再旋转-tilt倾角。 在抵消掉x和y轴的旋转后,星星又完全面对着我们了。 } glRotatef(-star[loop].angle, 0.0, 1.0, 0.0); // 取消当前星星的角度 glRotatef(-tilt, 1.0, 0.0, 0.0); // 取消屏幕倾斜 {如果 twinkle 为 TRUE,我们在屏幕上先画一次不旋转的星星: 将星星总数(num) 减去当前的星星数(loop)再减去1, 来提取每颗星星的不同颜色(这么做是因为循环范围从0到num-1)。 举例来说,结果为10的时候,我们就使用10号星星的颜色。 这样相邻星星的颜色总是不同的。这不是个好法子,但很有效。 最后一个值是alpha通道分量。这个值越小,这颗星星就越暗。 由于启用了twinkle,每颗星星最后会被绘制两遍。 程序运行起来会慢一些,这要看您的机器性能如何了。 但两遍绘制的星星颜色相互融合,会产生很棒的效果。 同时由于第一遍的星星没有旋转,启用twinkle后的星星看起来有一种动画效果。 (如果您这里看不懂得话,就自己去看程序的运行效果吧。) 值得注意的是给纹理上色是件很容易的事。 尽管纹理本身是黑白的,纹理将变成我们在绘制它之前选定的任意颜色。 此外,同样值得注意的是我们在这里使用的颜色值是byte型的, 而不是通常的浮点数。甚至alpha通道分量也是如此。}
If (twinkle) Then // 启用闪烁效果 Begin // 使用byte型数值指定一个颜色 glColor4ub(star[(50 - loop) - 1].r, star[(50 - loop) - 1].g, star[(50 - loop) - 1].b, 255); glBegin(GL_QUADS); // 开始绘制纹理映射过的四边形 glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 0.0); glEnd(); // 四边形绘制结束 End;
{ 现在绘制第二遍的星星。 唯一和前面的代码不同的是这一遍的星星肯定会被绘制,并且这次的星星绕着z轴旋转。 } glRotatef(spin, 0.0, 0.0, 1.0); // 绕z轴旋转星星 // 使用byte型数值指定一个颜色 glColor4ub(star[loop].r, star[loop].g, star[loop].b, 255); glBegin(GL_QUADS); // 开始绘制纹理映射过的四边形 glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 0.0); glEnd(); // 四边形绘制结束
{以下的代码代表星星的运动。 我们增加spin的值来旋转所有的星星(公转)。 然后,将每颗星星的自转角度增加loop/num。 这使离中心更远的星星转的更快。最后减少每颗星星离屏幕中心的距离。 这样看起来,星星们好像被不断地吸入屏幕的中心。} spin := spin + 0.01; // 星星的公转 &n 上一页 [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 问题的解决之道
|