首页 > 编程 > Delphi > 正文

NeHe的opengl教程delphi版(1)----基本框架

2019-11-18 18:33:57
字体:
来源:转载
供稿:网友
 

将CKER翻译的NeHe的VC 的OPENGL框架转成了Delphi版,
希望对用Delphi学习OPENGL的兄弟有所帮助,
不知为什么,我的Delphi环境下无法直接运行,但是在别的机器上好像没问题
我的机器只能编译后运行EXE文件。
感谢NeHe提供的这么好的框架,感谢CKER翻译的VC的资料

 

PRogram Project1;

Uses
   opengl,
   windows,
   Messages;

Const
   WND_TITLE        = 'OPenGl 基本框架'; //标题
Var
   //===========================================================================
   // 每一个OpenGL都被连接到一个着色描述表上。着色描述表将所有的OpenGL调用命令连
   // 接到Device Context(设备描述表)上,将OpenGL的着色描述表定义为hRC ,要让程序能
   // 够绘制窗口的话,还需要创建一个设备描述表,Windows的设备描述表被定义为 hDC,
   // DC将窗口连接到GDI(Graphics Device Interface图形设备接口)。而RC将OpenGL连接
   // 到DC。
   //===========================================================================
   h_RC             : HGLRC;            // Rendering Context(着色描述表)。
   h_DC             : HDC;              // Device Context(设备描述表)
   h_Wnd            : HWND;             // 窗口句柄
   h_Instance       : HINST;            // 程序Instance(实例)。
   keys             : Array[0..255] Of Boolean; // 用于键盘例程的数组
   {$R *.res}

   //==============================================================================
   //重新设置OpenGL场景的大小,而不管窗口的大小是否已经改变(假定没有使用全屏模式)。
   //甚至无法改变窗口的大小时(例如在全屏模式下),它至少仍将运行一次————————
   //在程序开始时设置透视图。OpenGL场景的尺寸将被设置成它显示时所在窗口的大小。
   //==============================================================================

Procedure glResizeWnd(Width, Height: Integer); // 重置并初始化GL窗口大小
Begin
   If (Height = 0) Then                 // 防止高度为0,产生除0异常
      Height := 1;
   glViewport(0, 0, Width, Height);     // 重置当前的视口(Viewport)

   //下面几行为透视图设置屏幕。意味着越远的东西看起来越小。这么做创建了一个现实
   //外观的场景。此处透视按照基于窗口宽度和高度的45度视角来计算。0.1f,100.0f是
   //我们在场景中所能绘制深度的起点和终点。
   //glMatrixMode(GL_PROJECTION)指明接下来的两行代码将影响projection matrix(投影矩阵)。
   //投影矩阵负责为我们的场景增加透视。
   //glLoadIdentity()近似于重置。它将所选的矩阵状态恢复成其原始状态。
   //调用 glLoadIdentity()之后我们为场景设置透视图。

   glMatrixMode(GL_PROJECTION);         // 选择投影矩阵
   glLoadIdentity();                    // 重置投影矩阵

   gluPerspective(45.0, Width / Height, 0.1, 100.0); // 计算窗口的外观比例

   //glMatrixMode(GL_MODELVIEW)指明任何新的变换将会影响 modelview matrix(模型观察矩阵)。
   //模型观察矩阵中存放了我们的物体讯息。

   glMatrixMode(GL_MODELVIEW);          // 选择模型观察矩阵
   glLoadIdentity();                    // 重置模型观察矩阵

   //如果现在还不能理解这些术语的含义,请别着急。
   //只要知道如果想获得一个精彩的透视场景的话,必须这么做。
End;

//==============================================================================
// 对OpenGL进行所有的设置。将设置清除屏幕所用的颜色,打开深度缓存,
// 启用smooth shading(阴影平滑),等等。这个例程直到OpenGL窗口创建之后才会被调用。
// 此过程将有返回值。但此处的初始化没那么复杂,现在还用不着担心这个返回值。
//==============================================================================

Procedure glInit();
Begin

   //设置清除屏幕时所用的颜色。如果对色彩的工作原理不清楚的话,快速解释一下。
   //色彩值的范围从0.0f到1.0f。0.0f代表最黑的情况,1.0f就是最亮的情况。
   //glClearColor 后的第一个参数是Red Intensity(红色分量),第二个是绿色,第三个是蓝色。
   //最大值也是1.0f,代表特定颜色分量的最亮情况。最后一个参数是Alpha值。
   //当它用来清除屏幕的时候,不用关心第四个数字。现在让它为0.0f。
   //通过混合三种原色(红、绿、蓝),可以得到不同的色彩
   //因此,使用glClearColor(0.0f,0.0f,1.0f,0.0f),您蓝色来清除屏幕。
   //如果用 glClearColor(0.5f,0.0f,0.0f,0.0f)的话,将使用中红色来清除屏幕。
   //不是最亮(1.0f),也不是最暗 (0.0f)。要得到白色背景,应该将所有的颜色设成最亮(1.0f)。
   //要黑色背景的话,该将所有的颜色设为最暗(0.0f)。

   glClearColor(0.0, 0.0, 0.0, 0.0);    // 黑色背景

   //阴影平滑通过多边形精细的混合色彩,并对外部光进行平滑。

   glShadeModel(GL_SMOOTH);             // 启用阴影平滑

   //接下来必须做的是关于depth buffer(深度缓存)的。将深度缓存设想为屏幕后面的层。
   //深度缓存不断的对物体进入屏幕内部有多深进行跟踪。本程序其实没有真正使用深度缓存,
   //但几乎所有在屏幕上显示3D场景OpenGL程序都使用深度缓存。它的排序决定那个物体先画。
   //这样您就不会将一个圆形后面的正方形画到圆形上来。深度缓存是OpenGL十分重要的部分。

   glClearDepth(1.0);                   // 设置深度缓存
   glEnable(GL_DEPTH_TEST);             // 启用深度测试
   glDepthFunc(GL_LESS);                // 所作深度测试的类型

   //接着告诉OpenGL我们希望进行最好的透视修正。
   //这会十分轻微的影响性能。但使得透视图看起来好一点。

   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 真正精细的透视修正

End;

//==============================================================================
//所有的绘图代码。任何您所想在屏幕上显示的东东都将在此段代码中出现。
//以后的每个程序会在此处增加新的代码。
//==============================================================================

Procedure glDraw();
Begin
   glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存
   glLoadIdentity();                    // 重置当前的模型观察矩阵
End;

Function WndProc(hWnd: HWND;            // 窗口的句柄
   Msg: UINT;                           // 窗口的消息
   wParam: WPARAM;                      // 附加的消息内容
   lParam: LPARAM                       // 附加的消息内容
   ): LRESULT; stdcall;
Begin
   Result := 0;
   Case (Msg) Of                        // 检查Windows消息
      WM_ACTIVATE:                      // 监视窗口激活消息
         Begin
         End;
      WM_CREATE:                        // 创建
         Begin
         End;
      WM_CLOSE:                         // 关闭
         Begin
            PostQuitMessage(0);         // 发出退出消息
            Result := 0
         End;
      WM_KEYDOWN:                       // 按键按下
         Begin
            keys[wParam] := True;       // 如果是,设为TRUE
            Result := 0;
         End;
      WM_KEYUP:                         // 按键松开
         Begin
            keys[wParam] := False;      // 如果是,设为FALSE
            Result := 0;
         End;
      WM_SIZE:                          //调整OpenGL窗口大小
         Begin
            glResizeWnd(LOWord(lParam), HIWORD(lParam));  //LoWord=Width,HiWord=Height
            Result := 0;
         End;
      WM_TIMER:                         //timers
         Begin
         End;
      Else                              //其余的让Windows自行处理。
         Result := DefWindowProc(hWnd, Msg, wParam, lParam);  //向DefWindowProc传递所有未处理的消息。
   End;
End;
//==============================================================================
// 只在程序退出之前调用。作用是依次释放着色描述表,设备描述表和窗口句柄。
// 加入了许多错误检查。如果程序无法销毁窗口的任意部分,都会弹出带相应错误消息的
// 讯息窗口,
//==============================================================================

Procedure glKillWnd(Fullscreen: Boolean);
Begin

   //在KillGLWindow()中所作的第一件事是检查是否处于全屏模式。
   //如果是,要切换回桌面。本应在禁用全屏模式前先销毁窗口,
   //但在某些显卡上这么做可能会使得桌面崩溃。所以还是先禁用全屏模式。
   //这将防止桌面出现崩溃,并在Nvidia和3dfx显卡上都工作的很好!

   If Fullscreen Then                   // 处于全屏模式吗?
      Begin
         //  使用ChangeDisplaySettings(NULL,0)回到原始桌面。
         //  将NULL作为第一个参数,
         //  0作为第二个参数传递强制Windows使用当前存放在注册表中的值
         //  (缺省的分辨率、色彩深度、刷新频率,等等)来有效的恢复我原始桌面。
         //  换回桌面后,还要使得鼠标指针重新可见。

         ChangeDisplaySettings(devmode(Nil^), 0); // 是的话,切换回桌面
         ShowCursor(True);              //显示鼠标
      End;

   //是否拥有着色描述表(hRC)。
   If h_RC > 0 Then
      //看我们能否释放它(将 hRC从hDC分开)。
      If (Not wglMakeCurrent(h_DC, 0)) Then
         MessageBox(0, 'DC和RC无法被释放!', '错误', MB_OK Or
            MB_ICONERROR);

   // 能否删除着色描述表
   If (Not wglDeleteContext(h_RC)) Then
      Begin
         MessageBox(0, '删除着色描述表失败!', '错误', MB_OK Or
            MB_ICONERROR);
         h_RC := 0;
      End;

   //是否存在设备描述表,如果有尝试释放它。
   If ((h_DC > 0) And (ReleaseDC(h_Wnd, h_DC) = 0)) Then
      Begin
         MessageBox(0, '释放设备描述表失败!', '错误', MB_OK Or
            MB_ICONERROR);
         h_DC := 0;
      End;

   //是否存在窗口句柄,调用 DestroyWindow( hWnd )来尝试销毁窗口
   If ((h_Wnd <> 0) And (Not DestroyWindow(h_Wnd))) Then
      Begin
         MessageBox(0, '无法销毁窗体!', '错误', MB_OK Or
            MB_ICONERROR);
         h_Wnd := 0;
      End;

   // 注销窗口类
   //这允许我们正常销毁窗口,接着在打开其他窗口时,
   //不会收到诸如"Windows Class already registered"(窗口类已注册)的错误消息。
   If (Not UnRegisterClass('OpenGL', hInstance)) Then
      Begin
         MessageBox(0, '无法注销窗口类!', '错误', MB_OK Or
            MB_ICONERROR);
         hInstance := 0;
      End;
End;


上一篇:NeHe的opengl教程delphi版(3)----着色

下一篇:Delphi中预想不到的代码

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
学习交流
热门图片

新闻热点

疑难解答

图片精选

网友关注