漂亮的星星动画:Jeff Molofee(NeHe) 的 OPENGL 教程-第九课

Jeff Molofee 中文教程 OPenGL NeHe的教程一共有30多课,内容翔实,并且不断更新 。国内的网站实在应该向他们学习。令人惊讶的是,NeHe提供的例程源码几乎都有跨平台的不同编译版本,涉及从Visual C++、Borland C++、Visual Basic、MacOS X/GLUT、Linux/GLX、Code Warrior、Delphi、C++ Builder、MASM、ASM、MingW32&Allegro以及Python等等的不同平台下的多种编译器。这在国内市场上的百元大书中似乎也未曾见到。关于OpenGL,是最早由SGI开发的跨平台的工业标准的3D图形硬件的软件接口,与微软的DirectX所鼎立,不必我来多吹。    由于CKER只是业余水准,关于OpenGL的专用术语的翻译难免有错误和不妥之处,请多加指正。另外,要想流畅的运行例程,您的爱机应该够劲,内存应该够大,还要支持3D硬件加速的显卡。第一课的内容有些简单,但这是NeHe几乎所有的OpenGl例程的框架。他有太废话,但看看不会错的。 立即下载

Jeff Molofee(NeHe) 的 OPENGL 教程

第九课

Translated by
CKER

Lesson 9 第九课

欢迎进入第九课。到现在为止,您应该很好的理解OpenGL了。『CKER:如果没有的话,一定是我翻译的罪过......』。您已经学会了设置一个OpenGL窗口的每个细节。学会在旋转的物体上贴图并打上光线以及混色(透明)处理。这一课应该算是第一课中级教程。您将学到如下的知识:在3D场景中移动位图,并去除位图上的黑色象素(使用混色)。接着为黑白纹理上色,最后您将学会创建丰富的色彩,并把上过不同色彩的纹理相互混合,得到简单的动画效果。
我们在第一课的代码基础上进行修改。先在程序源码的开始处增加几个变量。出于清晰起见,我重写了整段代码。
#include <windows.h>     // Windows的头文件
#include <stdio.h>      // 标准输入输出库头文件
#include <gl/gl.h>      // OpenGL32库的头文件
#include <gl/glu.h>     // GLu32库的头文件
#include <gl/glaux.h>     // GLaux库的头文件
HDC  hDC=NULL;    // 私有GDI设备描述表
HGLRC  hRC=NULL;    // 永久着色描述表
HWND  hWnd=NULL;    // 保存我们的窗口句柄
HINSTANCE hInstance;    // 保存程序的实例
bool keys[256];     // 用于键盘例程的数组
bool active=TRUE;     // 窗口的活动标志,缺省为TRUE
bool fullscreen=TRUE;     // 全屏标志缺省设定成全屏模式
下列这几行新加的。twinkle和 tp是布尔变量, 表示它们只能设为 TRUE 或 FALSE。 twinkle用来跟踪 闪烁 效果是否启用。 tp用来检查 'T'键有没有被按下或松开. (按下时 tp=TRUE, 松开时 tp=FALSE).
BOOL twinkle;      // 闪烁的星星
BOOL tp;      // 'T' 按下了么?
num 跟踪屏幕上所绘制的星星数。这个数字被定义为一个常量。这意味着无法在以后的代码中对其进行修改。这么做的原因是因为您无法重新定义一个数组。因此,如果我们定义一个50颗星星的数组,然后又将num增加到51的话,就会出错『CKER:数组越界』。不过您还是可以(也只可以)在这一行上随意修改这个数字。但是以后请您别再改动 num 的值了,除非您想看见灾难发生。
const num=50;      //绘制的星星数

现在我们来创建一个结构。 结构这词听起来有点可怕,但实际上并非如此。 一个结构使用一组简单类型的数据 (以及变量等)来表达较大的具有相似性的数据组合。 我们知道我们在保持对星星的跟踪。 您可以看到下面的第七行就是 stars;并且每个星星有三个整型的色彩值。第三行 int r,g,b设置了三个整数. 一个红色 (r), 一个绿色 (g), 以及一个蓝色 (b). 此外,每个星星离屏幕中心的距离不同, 而且可以是以屏幕中心为原点的任意360度中的一个角度。如果你看下面第四行的话, 会发现我们使用了一个叫做 dist的浮点数来保持对距离 的跟踪. 第五行则用一个叫做 angle的浮点数保持对星星角度值的跟踪。
因此我们使用了一组数据来描述屏幕上星星的色彩, 距离, 和角度。 不幸的是我们不止对一个星星进行跟踪。但是无需创建 50 个红色值、 50 个绿色值、 50 个蓝色值、 50 个距离值 以及 50 个角度值,而只需创建一个数组star。 star数组的每个元素都是
stars类型的,里面存放 了描述星星的所有数据。star数组在下面的第八行创建。 第八行的样子是这样的: stars star[num]。数组类型是 stars结构. 所数组 能存放所有stars结构的信息。 数组名字是 star. 数组大小是 [num]。 数组中存放着 stars结构的元素. 跟踪结构元素会比跟踪各自分开的变量容易的多. 不过这样也很笨, 因为我们竟然不能改变常量 num来增减星星 数量。

typedef struct      // 为星星创建一个结构
{
 int r, g, b;      // 星星的颜色
 GLfloat dist;     // 星星距离中心的距离
 GLfloat angle;     // 当前星星所处的角度
}
stars;       // 结构命名为stars
stars star[num];      // 使用 'stars' 结构生成一个包含 'num'个元素的 'star'数组
width=28>  width="100%">  vAlign=top width="100%"> 
接下来我们设置几个跟踪变量:星星离观察者的距离变量(zoom),我们所见到的星星所处的角度(tilt),以及使闪烁的星星绕Z轴自转的变量spin。
loop变量用来绘制50颗星星。texture[1]用来存放一个黑白纹理。如果您需要更多的纹理的话,您应该增加texture数组的大小至您决定采用的纹理个数。
GLfloat zoom=-15.0f;     // 星星离观察者的距离
GLfloat tilt=90.0f;      // 星星的倾角
GLfloat spin;      // 闪烁星星的自转
GLuint loop;      // 全局l Loop 变量
GLuint texture[1];     // 存放一个纹理
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  // WndProc的声明
width=28>  width="100%">  width=28>  vAlign=top width="100%"> 
紧接着上面的代码就是我们用来载入纹理的代码。我不打算再详细的解释这段代码。这跟我们在第六、七、八课中所用的代码是一模一样的。这一次载入的位图叫做star.bmp。这里我们使用glGenTextures(1, &texture[0]),来生成一个纹理。纹理采用线性滤波方式。
AUX_RGBImageRec *LoadBMP(char *Filename)  // 载入位图文件
{
 FILE *File=NULL;     // 文件句柄
 if (!Filename)     // 确认已给出文件名
 {
  return NULL;    // 若无返回 NULL
 }
 File=fopen(Filename,"r");    // 检查文件是否存在
 if (File)      // 文件存在么?
 {
  fclose(File);    // 关闭文件句柄
  return auxDIBImageLoad(Filename);  // 载入位图并返回指针
 }
 return NULL;     // 如果载入失败返回 NULL
}
width=28>  width="100%">  width=28>  vAlign=top width="100%"> 
下面的代码(调用上面的代码)载入位图,并转换成纹理。变量用来跟踪纹理是否已载入并创建好了。
int LoadGLTextures()     // 载入位图并转换成纹理
{
 int Status=FALSE;    // Status 状态指示器
 AUX_RGBImageRec *TextureImage[1];  // 为纹理分配存储空间
 memset(TextureImage,0,sizeof(void *)*1);  // 将指针设为 NULL
 // 载入位图,查错,如果未找到位图文件则退出
 if (TextureImage[0]=LoadBMP("Data/Star.bmp"))
 {
  Status=TRUE;    // 将 Status 设为TRUE
  glGenTextures(1, &texture[0]);  // 创建一个纹理
  // 创建一个线性滤波纹理
  glBindTexture(GL_TEXTURE_2D, texture[0]);
  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, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 
  0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
 }
 if (TextureImage[0])    // 如果纹理存在
 {
  if (TextureImage[0]->data)   // 如果纹理图像存在
  {
   free(TextureImage[0]->data); // 释放纹理图像所占的内存
  }
  free(TextureImage[0]);   // 释放图像结构
 }
 return Status;     // 返回 Status的值
}
width=28>  width="100%">  width=28>  vAlign=top width="100%"> 
现在设置OpenGL的渲染方式。这里不打算使用深度测试,如果您使用第一课的代码的话,请确认是否已经去掉了 glDepthFunc(GL_LEQUAL); 和 glEnable(GL_DEPTH_TEST);两行。否则,您所见到的效果将会一团糟。这里我们使用了纹理映射,因此请您确认您已经加上了这些第一课中所没有的代码。您会注意到我们通过混色来启用了纹理映射。
int InitGL(GLvoid)      // 此处开始对OpenGL进行所有设置
{
 if (!LoadGLTextures())    // 调用纹理载入子例程
 {
  return FALSE;    // 如果未能载入,返回FALSE
 }
 glEnable(GL_TEXTURE_2D);   // 启用纹理映射
 glShadeModel(GL_SMOOTH);   // 启用阴影平滑 
 glClearColor(0.0f, 0.0f, 0.0f, 0.5f);   // 黑色背景
 glClearDepth(1.0f);    // 设置深度缓存
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 真正精细的透视修正
 glBlendFunc(GL_SRC_ALPHA,GL_ONE);  // 设置混色函数取得半透明效果
 glEnable(GL_BLEND);    // 启用混色
width=28>  width="100%">  width=28>  vAlign=top width="100%"> 
以下是新增的代码。设置了每颗星星的起始角度、距离、和颜色。您会注意到修改结构的属性有多容易。全部50颗星星都会被循环设置。要改变star[1]的角度我们所要做的只是star[1].angle={某个数值};就这么简单!
 for (loop=0; loop<num; loop++)   // 创建循环设置全部星星
 {
  star[loop].angle=0.0f;   // 所有星星都从零角度开始
width=28>  width="100%">  width=28>  vAlign=top width="100%"> 
第loop颗星星离中心的距离是将loop的值除以星星的总颗数,然后乘上5.0f。基本上这样使得后一颗星星比前一颗星星离中心更远一点。这样当loop为50时(最后一颗星星),loop 除以 num正好是1.0f。之所以要乘以5.0f是因为1.0f*5.0f 就是 5.0f。『CKER:废话,废话!这老外怎么跟孔乙己似的!:)』5.0f已经很接近屏幕边缘。我不想星星飞出屏幕,5.0f是最好的选择了。当然如果如果您将场景设置的更深入屏幕里面的话,也许可以使用大于5.0f的数值,但星星看起来就更小一些(都是透视的缘故)。
您还会注意到每颗星星的颜色都是从0~255之间的一个随机数。也许您会奇怪为何这里的颜色得取值范围不是OpenGL通常的0.0f~1.0f之间。这里我们使用的颜色设置函数是glColor4ub,而不是以前的glColor4f。ub意味着参数是Unsigned Byte型的。一个byte的取值范围是0~255。这里使用byte值取随机整数似乎要比取一个浮点的随机数更容易一些。
  star[loop].dist=(float(loop)/num)*5.0f;  // 计算星星离中心的距离
  star[loop].r=rand()%256;   // 为star[loop]设置随机红色分量
  star[loop].g=rand()%256;   // 为star[loop]设置随机红色分量
  star[loop].b=rand()%256;   // 为star[loop]设置随机红色分量
 }
 return TRUE;     // 初始化一切OK
}
width=28>  width="100%">  width=28>  vAlign=top width="100%"> 
Resize的代码也是一样的,现在我们转入绘图代码。如果您使用第一课的代码,删除旧的DrawGLScene代码,只需将下面的代码复制过去就行了。实际上,第一课的代码只有两行,所以没太多东西要删掉的。
int DrawGLScene(GLvoid)     // 此过程中包括所有的绘制代码
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕及深度缓存
 glBindTexture(GL_TEXTURE_2D, texture[0]);  // 选择纹理
 for (loop=0; loop<num; loop++)   // 循环设置所有的星星
 {
  glLoadIdentity();    // 绘制每颗星星之前,重置模型观察矩阵
  glTranslatef(0.0f,0.0f,zoom);  // 深入屏幕里面 (使用 'zoom'的值)
  glRotatef(tilt,1.0f,0.0f,0.0f);   // 倾斜视角(使用 'tilt'的值)
width=28>  width="100%">  width=28>  vAlign=top width="100%"> 
现在我们来移动星星。星星开始时位于屏幕的中心。我们要做的第一件事是把场景沿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.0f,1.0f,0.0f); //旋转至当前所画星星的角度
  glTranslatef(star[loop].dist,0.0f,0.0f);  // 沿X轴正向移动
width=28>  width="100%">  width=28>  vAlign=top width="100%"> 
接着的代码带点小技巧。星星实际上是一个平面的纹理。现在您在屏幕中心画了个平面的四边形然后贴上纹理,这看起来很不错。一切都如您所想的那样。但是当您当您沿着y轴转上个90度的话,纹理在屏幕上就只剩右侧和左侧的两条边朝着您。看起来就是一条细线。这不是我们所想要的。我们希望星星永远正面朝着我们,而不管屏幕如何旋转或倾斜。
我们通过在绘制星星之前,抵消对星星所作的任何旋转来实现这个愿望。您可以采用逆序来抵消旋转。当我们倾斜屏幕时,我们实际上以当前角度旋转了星星。通过逆序,我们又以当前角度"反旋转"星星。也就是以当前角度的负值来旋转星星。就是说,如果我们将星星旋转了10度的话,又将其旋转-10度来使星星在那个轴上重新面对屏幕。下面的第一行抵消了沿y轴的旋转。然后,我们还需要抵消掉沿x轴的屏幕倾斜。要做到这一点,我们只需要将屏幕再旋转-tilt倾角。在抵消掉x和y轴的旋转后,星星又完全面对着我们了。
  glRotatef(-star[loop].angle,0.0f,1.0f,0.0f); // 取消当前星星的角度
  glRotatef(-tilt,1.0f,0.0f,0.0f);   // 取消屏幕倾斜
width=28>  width="100%">  width=28>  vAlign=top width="100%"> 
如果 twinkle 为  TRUE,我们在屏幕上先画一次不旋转的星星:将星星总数(num) 减去当前的星星数(loop)再减去1,来提取每颗星星的不同颜色(这么做是因为循环范围从0到num-1)。举例来说,结果为10的时候,我们就使用10号星星的颜色。这样相邻星星的颜色总是不同的。这不是个好法子,但很有效。最后一个值是alpha通道分量。这个值越小,这颗星星就越暗。
由于启用了twinkle,每颗星星最后会被绘制两遍。程序运行起来会慢一些,这要看您的机器性能如何了。但两遍绘制的星星颜色相互融合,会产生很棒的效果。同时由于第一遍的星星没有旋转,启用twinkle后的星星看起来有一种动画效果。(如果您这里看不懂得话,就自己去看程序的运行效果吧。)
值得注意的是给纹理上色是件很容易的事。尽管纹理本身是黑白的,纹理将变成我们在绘制它之前选定的任意颜色。此外,同样值得注意的是我们在这里使用的颜色值是byte型的,而不是通常的浮点数。甚至alpha通道分量也是如此。
  if (twinkle)     // 启用闪烁效果
  {
   // 使用byte型数值指定一个颜色
   glColor4ub(star[(num-loop)-1].r,star[(num-loop)-1].g,star[(num-loop)-1].b,255);
   glBegin(GL_QUADS);   // 开始绘制纹理映射过的四边形
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
   glEnd();     // 四边形绘制结束
  }
width=28>  width="100%">  width=28>  width=28>  noWrap width=28>  noWrap width=28>  vAlign=top width="100%">  noWrap width=28> 
现在绘制第二遍的星星。唯一和前面的代码不同的是这一遍的星星肯定会被绘制,并且这次的星星绕着z轴旋转。
  glRotatef(spin,0.0f,0.0f,1.0f);   // 绕z轴旋转星星
  //  使用byte型数值指定一个颜色
  glColor4ub(star[loop].r,star[loop].g,star[loop].b,255);
  glBegin(GL_QUADS);    // 开始绘制纹理映射过的四边形
   glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
   glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
   glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
   glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
  glEnd();      // 四边形绘制结束
width=28>  width="100%">  width=28>  width=28>  noWrap width=28>  noWrap width=28>  vAlign=top width="100%">  noWrap width=28> 
以下的代码代表星星的运动。我们增加spin的值来旋转所有的星星(公转)。然后,将每颗星星的自转角度增加loop/num。这使离中心更远的星星转的更快。最后减少每颗星星离屏幕中心的距离。这样看起来,星星们好像被不断地吸入屏幕的中心。
  spin+=0.01f;     // 星星的公转
  star[loop].angle+=float(loop)/num;   // 改变星星的自转角度
  star[loop].dist-=0.01f;    // 改变星星离中心的距离
width=28>  width="100%">  width=28>  width=28>  noWrap width=28>  noWrap width=28>  vAlign=top width="100%">  noWrap width=28> 
接着几行检查星星是否已经碰到了屏幕中心。当星星碰到屏幕中心时,我们为它赋一个新颜色,然后往外移5个单位,这颗星星将踏上它回归屏幕中心的旅程。
  if (star[loop].dist<0.0f)   // 星星到达中心了么
  {
   star[loop].dist+=5.0f;  // 往外移5个单位
   star[loop].r=rand()%256;  // 赋一个新红色分量
   star[loop].g=rand()%256;  // 赋一个新绿色分量
   star[loop].b=rand()%256;  // 赋一个新蓝色分量
  }
 }
 return TRUE;     // 一切正常
}
width=28>  width="100%">  width=28>  width=28> 
现在我们添加监视键盘的代码。下移到WinMain()。找到SwapBuffers(hDC)一行。我们就在这一行后面增加键盘监视代码。
代码将检查T键是否已按下。如果T键按下过,并且又放开了,if块内的代码将被执行。如果twinkle为FALSE,他将变为TRUE。反之亦然。只要T键按下, tp就变为TRUE。这样处理可以防止如果您一直按着T键的话,块内的代码被反复执行。
  SwapBuffers(hDC);   // 切换缓冲 (双缓冲)
  if (keys['T'] && !tp)    // 是否T 键已按下并且 tp值为 FALSE
  {
   tp=TRUE;   // 若是,将tp设为TRUE
   twinkle=!twinkle;   // 翻转 twinkle的值
  }
width=28>  width="100%"> 
下面的代码检查是否松开了T键。若是,使 tp=FALSE。除非tp的值为FALSE,否则按着T键时什么也不会发生。所以这行代码很重要。
  if (!keys['T'])    //  T 键已松开了么?
  {
   tp=FALSE;   // 若是 ,tp为 FALSE
  }
width=28>  width="100%"> 
余下的代码检查上、下方向键,向上翻页键或向下翻页键是否按下。
  if (keys[VK_UP])    // 上方向键按下了么?
  {
   tilt-=0.5f;    // 屏幕向上倾斜
  }
  if (keys[VK_DOWN])   // 下方向键按下了么?
  {
   tilt+=0.5f;    // 屏幕向下倾斜
  }
  if (keys[VK_PRIOR])   // 向上翻页键按下了么
  {
   zoom-=0.2f;   // 缩小
  }
  if (keys[VK_NEXT])   // 向下翻页键按下了么?
  {
   zoom+=0.2f;   // 放大
  }
width=28>  width="100%"> 
像以前一样,确认窗口的标题是否正确。
  if (keys[VK_F1])    // F1键按下了么?
  {
   keys[VK_F1]=FALSE;  // 若是,使对应的Key数组中的值为 FALSE
   KillGLWindow();   // 销毁当前的窗口
   fullscreen=!fullscreen;  // 切换 全屏 / 窗口 模式
   // 重建 OpenGL 窗口
   if (!CreateGLWindow("NeHe's Textures, Lighting & Keyboard Tutorial",640,480,16,fullscreen))
   {
    return 0;   // 如果窗口未能创建,程序退出
   }
  }
 }
}
width=28>  width="100%"> 
这一课我尽我所能来解释如何加载一个灰阶位图纹理,(使用混色)去掉它的背景色后,再给它上色,最后让它在3D场景中移动。我已经向您展示了如何创建漂亮的颜色与动画效果。实现原理是在原始位图上再重叠一份位图拷贝。到现在为止,只要您很好的理解了我所教您的一切,您应该已经能够毫无问题的制作您自己的3D Demo了。所有的基础知识都已包括在内!
Jeff Molofee (NeHe)
* DOWNLOAD Visual C++ Code For This Lesson.
* DOWNLOAD Visual C++ / OpenIL Code For This Lesson. ( Conversion by Denton Woods )
* DOWNLOAD Visual Basic Code For This Lesson. ( Conversion by Peter De Tagyos )
* DOWNLOAD Visual Fortran Code For This Lesson. ( Conversion by Jean-Philippe Perois )
* DOWNLOAD Cygwin (FREE Language) Code For This Lesson. ( Conversion by Stephan Ferraro )
* DOWNLOAD Delphi Code For This Lesson. ( Conversion by Marc Aarts )
* DOWNLOAD MacOS X/GLUT Code For This Lesson. ( Conversion by Raal Goff )
* DOWNLOAD Linux/GLX Code For This Lesson. ( Conversion by Mihael Vrbanec )
* DOWNLOAD MASM Code For This Lesson. ( Conversion by Nico (Scalp) )
* DOWNLOAD Linux Code For This Lesson. ( Conversion by Richard Campbell )
* DOWNLOAD Irix Code For This Lesson. ( Conversion by Lakmal Gunasekara )
* DOWNLOAD Solaris Code For This Lesson. ( Conversion by Lakmal Gunasekara )
* DOWNLOAD Mac OS Code For This Lesson. ( Conversion by Anthony Parker )
* DOWNLOAD Power Basic Code For This Lesson. ( Conversion by Angus Law )
* DOWNLOAD BeOS Code For This Lesson. ( Conversion by Chris Herborth )
* DOWNLOAD Java Code For This Lesson. ( Conversion by Darren Hodges )
* DOWNLOAD MingW32 & Allegro Code For This Lesson. ( Conversion by Peter Puck )
* DOWNLOAD Borland C++ Builder 4.0 Code For This Lesson. ( Conversion by Patrick Salmons )
Visual C++ OpenGL 星星动画 用VC++ 6.0写的OpenGL三维动画程序 立即下载

相关推荐

OpenGL星星公转自转实例

本例使用了opengl的基础知识,实现了星星公转,自转,闪烁的效果。

Jeff Molofee(NeHe)的OpenGL教程 - 碰撞检测与模型运动

原 文 : Lesson 31: Collision Detection and Physically Based Modeling Tutorial 译 者 : Wguzgg   下面我们要讨论的是如何快速有效的检测物体的碰撞和合乎物理法则的物体运动,先看一下我们要学的:   1 )碰撞检测 ...

Windows SDK 296

opengl_qt实现闪烁的星星

这一小节我们要完成的任务是:将一张背景是黑色,中间是白亮色的星星图片和五颜六色的颜色进行色彩融合,变成一颗彩色的星星。并且让这些星星自转和公转,可以控制自转和公转的速度,另外也能控制所有的星星是否能够闪烁。 按键T是用来控制是否开启星星闪烁功能;按键B是用来控制是否开启色彩融合功能;PageUp键用来控制物体走向远处的距离,相反PageDown用来控制物体走向观察者的距离;向上的方向键和向下的方向键用来控制星星公转屏幕和屏幕的夹角(默认值2者是重合的);当然了F1键用来控制全屏切换,Ese键是退出程序键。

OpenGL 漂亮的星星

原 文:Lesson 9: Moving Bitmaps In 3D Space作 者:CKER  欢迎进入第九课。到现在为止,您应该很好的理解OpenGL了。您已经学会了设置一个OpenGL窗口的每个细节。学会在旋转的物体上贴图并打上光线以及混色(透明)处理。这一课应该算是第一课中级教程。您将学到如下的知识:在3D场景中移动位图,并去除位图上的黑色象素(使用混色)。接着为黑白纹理上色,最后您

痞子龙3D编程 2373

Jeff Molofee(NeHe) 的 OPENGL 教程源代码(1)

Jeff Molofee(NeHe) 的 OPENGL 教程源代码 48课全部源代码

opengl中的星星特效代码

opengl中实现星星状旋转闪耀特效,虽然很简单,但也可以参考!

OpenGL_Qt学习笔记之_07(闪烁的星星)

       这一小节我们要完成的任务是:将一张背景是黑色,中间是白亮色的星星图片和五颜六色的颜色进行色彩融合,变成一颗彩色的星星。并且让这些星星自转和公转,可以控制自转和公转的速度,另外也能控制所有的星星是否能够闪烁。        实验基础   色彩融合知识:       刚开始提到由黑白的星星变成彩色的星星用到的是色彩融合的知识,关于色彩融合,在上篇文章OpenGL_Qt学习笔记之...

weixin_33905756的博客 321

python——体育收入排行2012-2019

请分析文件并读取数据,完成以下功能: 1. 某年的收入排名前若干名选手 如果输入n是2012-19之间的年份,则可以输入整数k,输出n年的前k名排名信息。如果k大于当年排名运动员人数,则输出当年所有的信息。每行一名运动员信息,以' | '间隔该行各项信息。 2. 某年属于某个运动项目的所有运动员信息,和收入总和 如果输入的是'sport'(不区分大小写),则可以继续输入一个年份201*,输出一个当年排行中的运动项目菜单,按照字符串升序排列,格式见示例,再输入运动项目对应的数字来输出该项运动当

m0_62488776的博客 2257

漂亮的星星动画:Jeff Molofee(NeHe) 的 OPENGL 教程-第九课 (转)

漂亮的星星动画:Jeff Molofee(NeHe) 的 OPENGL 教程-第九课 (转)[@more@] ...

csd3176的博客 108

从OFED到rdma-core:手把手带你搞定Linux下RDMA开发环境的选型与搭建

本文详细介绍了在Linux系统下搭建RDMA开发环境的完整流程,涵盖OFED与rdma-core的选型对比及分步安装指南。针对高性能计算和分布式存储需求,解析RDMA技术栈的核心组件,提供环境验证与性能测试方法,帮助开发者快速构建稳定高效的开发环境。特别适合需要优化网络性能的工程师参考。

weixin_26905487的博客 225

线性代数——(期末突击)行列式(上)-行列式计算、行列式的性质

简单解释一下:4213原本的顺序应为1234,对于‘4’而言,‘2’、‘1’、‘3’都应该排在它的前面,所以此处记逆序数为3;对于‘2’而言,‘1’应该排在它的前面,而‘3’排在它之后 是合理的,所以此处只有一个逆序数;最后看‘1’,其后面的‘3’排在后面显然也是合理的,故而4213的逆序数为4.一般我们使用这个性质来计算四阶行列式,也就是将其变换成三角行列式,再计算对角线的值;以主对角线为分界线的就为正三角,反之则为反三角行列式。若行列式某一行(列)为0,则该行列式=0.将和的那一行分开,其余行。

li13437542099的博客 1万+

Jeff Molofee(NeHe)的OpenGL教程--漫游3D世界

原 文:Lesson 10: Loading And Moving Through A 3D World译 者:CKER  这一课是由Lionel Brits(βtelgeuse)所写的。在本课中我们只对增加的代码做解释。当然只添加课程中所写的代码,程序是不会运行的。如果您有兴趣知道下面的每一行代码是如何运行的话,请下载完整的源码,并在浏览这一课的同时,对源码进行跟踪。  好了,现在欢迎来到名不见

llldddrrr的专栏 988

【点云语义分割】Ubuntu20.04下RangeNet++环境配置与实战指南

本文详细介绍了在Ubuntu20.04系统下配置和运行RangeNet++点云语义分割模型的完整实战指南。内容涵盖从Cuda、cudnn到TensorRT的深度学习环境搭建,RangeNet++源码编译的详细步骤与常见问题解决,以及如何运行首个分割Demo并可视化结果。最后,还探讨了处理自定义点云数据格式和进行性能调优的进阶技巧,旨在帮助开发者和研究者快速部署并应用这一先进的点云语义分割技术。

rnn9storyteller的博客 516

粗糙的世界:Jeff Molofee(NeHe) 的 OPENGL 教程-第十课

Jeff Molofee(NeHe) 的 OPENGL 教程 第十课 Translated by CKER   这一课是由Lionel Brits (βtelgeuse)所写的。在本课中我们只对增加的代码做解释。当然只添加课程中所写的代码,程序是不会运行的。如果您有兴趣知道下面的每一行代码是如何运行的话,请下载完整的源码,并在浏览这一课的同时

没吃过猪肉,光看见猪跑啦.................... 2964

基于MATLAB/Simulink与WSL2的ROS2实时联合仿真实践

本文详细介绍了基于MATLAB/Simulink与WSL2的ROS2实时联合仿真实践。通过环境配置、PX4仿真环境搭建、自定义消息生成、Simulink通信实现及实时优化等步骤,提供了完整的无人机位置控制案例,帮助开发者实现高精度的实时联合仿真。

red88的博客 202

HFSS入门学习笔记——微带一分四功分器的设计与仿真

功率分配器是将输入信号功率分成相等或不相等的几路功率输出的一种多端口无源微波网络,用于功率分配和功率合成。工程上常用的微带功分器有T型功分器和威尔金森功分器。经典的威尔金森功分器有几个缺点:①、多应用于低频段,高频段时,波长会与隔离电阻的尺寸相比拟,此时需要考虑电阻的分布参数效应;②、大功率应用时,隔离电阻的耗散功率要很大,因此隔离电阻的体积也会比较大。

weixin_42126696的博客 2万+

粗糙的世界:Jeff Molofee(NeHe) 的 OPENGL 教程-第十课 (转)

粗糙的世界:Jeff Molofee(NeHe) 的 OPENGL 教程-第十课 (转)[@more@] Jeff Molofee(NeHe) 的 OPENGL 教程 第十课 Translated by CKER .N...

ciya3282的博客 313

使用epiDisplay包中的logistic

其中的logistic.display函数可以用于获取逻辑回归模型的汇总统计信息,包括自变量的优势比和置信区间,以及回归系数的Wald检验的p值。最后,我们使用print函数打印出汇总统计信息。使用epiDisplay包中的logistic.display函数获取逻辑回归模型的汇总统计信息(包括自变量的初始和调整后的优势比及置信区间,回归系数的Wald检验的p值)- R语言。通过使用logistic.display函数,我们可以方便地获取逻辑回归模型的重要统计信息,并对自变量的影响进行解释和推断。

CyberJolt的博客 608

OpenGL实验(一)彩色五角星绘制

Open Graphics Library (OpenGL)

Birdcage 7223

第七节:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入门 - 用户管理(上)

本节的内容是用户管理,后端Python代码的实现。

cuiwin的专栏 778

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

OpenGL教程之漫游3D世界

Jeff Molofee(NeHe)的OpenGL教程- 漫游3D世界原 文:Lesson 10: Loading And Moving Through A 3D World译 者:CKER  这一课是由Lionel Brits(βtelgeuse)所写的。在本课中我们只对增加的代码做解释。当然只添加课程中所写的代码,程序是不会运行的。如果您有兴趣知道下面的每一行代码是如何运行的话,请下载完整

3486

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

android opengl es 飘落的星星

用的是别人七彩星星的框架, 自己亲手去调试,虽然还有很多不懂的地方,但算是对android opengl es的框架有了一定的认识 两个类 StarsActivity.class package wjw.stars; import android.app.Activity; import android.content.res.Resources; impor

jw72jw的专栏 1493

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

C++下用OpenGL制作星月绕行动画

C++下用OpenGL来制作星月绕行动画,特点是绿色无动态链接库,可编程管线,图片纹理功能。 绿色C++ OPENGL 可编程管线 视频显示运行效果 代码片段: mvStack.push(mvStack.top()); mvsize=mvStack.size(); //将向量(0, 0, 0)与单位矩阵相乘,然后与视图矩阵相乘,使相机移 mvStack.top()*=glm::translate(glm::mat4(1.0f),glm::vec3...

garyaofq的博客 950
上一篇: 玩转BCB的IDE,体验ToolsAPI
下一篇: 粗糙的世界:Jeff Molofee(NeHe) 的 OPENGL 教程-第十课
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值