将CKER翻译的NeHe的VC 的OPENGL框架转成了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;

解决方案 »

  1.   

    //==============================================================================
    // 只在程序退出之前调用。作用是依次释放着色描述表,设备描述表和窗口句柄。
    // 加入了许多错误检查。如果程序无法销毁窗口的任意部分,都会弹出带相应错误消息的
    // 讯息窗口,
    //==============================================================================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;
    //==============================================================================
    // 创建OpenGL窗口,
    // 带有5个参数:窗口的标题栏,窗口的宽度,窗口的高度,色彩位数(16/24/32),
    // 全屏标志(TRUE --全屏模式, FALSE--窗口模式 )。
    // 返回的布尔值 窗口是否成功创建。
    //==============================================================================Function glCreateWnd(Width, Height: Integer; Fullscreen: Boolean; PixelDepth:
       Integer): Boolean;
    Var
       wndClass         : TWndClass;        // 窗口类
       dwStyle          : DWORD;            // 窗口风格
       dwExStyle        : DWORD;            // 扩展窗口风格
       PixelFormat      : GLuint;           // 象素格式
       h_Instance       : HINST;            // 当前实例
       dmScreenSettings : DEVMODE;          // 设备模式
       pfd              : TPIXELFORMATDESCRIPTOR; //格式描述符Begin
       h_Instance := GetModuleHandle(Nil);  // 取得窗口的实例
       ZeroMemory(@wndClass, SizeOf(wndClass)); // 初始化内存
       With wndClass Do                     // 设置窗口类
          Begin
             style := CS_HREDRAW Or         // 如果长度变化,
             CS_VREDRAW Or                  // 如果高度变化,就是只要变化就强制重画
             CS_OWNDC; //CS_OWNDC为窗口创建一个私有的DC。这意味着DC不能在程序间共享。
             lpfnWndProc := @WndProc;       // WndProc处理消息
             // cbClsExtra := 0;               // 无额外窗口数据
             // cbWndExtra := 0;               // 无额外窗口数据
             hInstance := h_Instance;       // 设置实例
             //hIcon := LoadIcon(0, IDI_WINLOGO); // 装入缺省图标
             hCursor := LoadCursor(0, IDC_ARROW); //载入鼠标指针
             //hbrBackground := 0;            // GL不需要背景
             //lpszMenuName := '';            // 不需要菜单
             lpszClassName := 'OpenGL';     //设定类名
          End;
       If (RegisterClass(wndClass) = 0) Then // 注册窗体类
          Begin
             MessageBox(0, '注册窗体类失败!', '错误', MB_OK Or
                MB_ICONERROR);
             Result := False;
             Exit
          End;   // 如果需要全屏的话
       If Fullscreen Then
          Begin
             ZeroMemory(@dmScreenSettings, SizeOf(dmScreenSettings)); // 确保内存分配
             With dmScreenSettings Do
                Begin                       // 设置屏幕设置的参数
                   dmSize := SizeOf(dmScreenSettings); // Devmode 结构的大小
                   dmPelsWidth := Width;    // 所选屏幕宽度
                   dmPelsHeight := Height;  // 所选屏幕高度
                   dmBitsPerPel := PixelDepth; // 每象素所选的色彩深度
                   dmFields := DM_PELSWIDTH // 设置初始标志为dmPelsWidth
                   Or DM_PELSHEIGHT         // dmPelsHeight 和
                   Or DM_BITSPERPEL;        // dmBitsPerPel
                End;         // 转换为全屏模式 ,
             //切换成与dmScreenSettings所匹配模式。
             //CDS_FULLSCREEN 移去了状态条。
             //并保证在来回切换时,没有移动或改变您在桌面上的窗口。
             // 转换为全屏模式
             If (ChangeDisplaySettings(dmScreenSettings, CDS_FULLSCREEN) =
                DISP_CHANGE_FAILED) Then    //转换失败
                Begin
                   MessageBox(0, '不能转换为全屏模式!', '错误', MB_OK
                      Or MB_ICONERROR);
                   Fullscreen := False;
                End;
          End;   If (Fullscreen) Then                 // 仍在全屏模式下
          Begin
             dwStyle := WS_POPUP Or         // 没有边框
             WS_CLIPCHILDREN // 要让OpenGL正常运行,这两个属性是必须的。
             Or WS_CLIPSIBLINGS;            //他们阻止别的窗体在我们的窗体内/上绘图。
             dwExStyle := WS_EX_APPWINDOW;  // 窗体可见时处于最前面
             ShowCursor(False);             // 不显示鼠标
          End
       Else                                 //否则
          Begin
             dwStyle := WS_OVERLAPPEDWINDOW Or  //带标题栏、可变大小的边框、菜单和最大/小化按钮
             WS_CLIPCHILDREN Or // 要让OpenGL正常运行,这两个属性是必须的。
             WS_CLIPSIBLINGS;               //他们阻止别的窗体在我们的窗体内/上绘图。
             dwExStyle := WS_EX_APPWINDOW Or // 增强窗体的3D感观
             WS_EX_WINDOWEDGE;              // 边框为凸起
             ShowCursor(false);             // 不显示鼠标
          End;
      

  2.   

    //创建一个窗体
       h_Wnd := CreateWindowEx(dwExStyle,   // 扩展窗体风格
          'OpenGL',                         // 类名
          WND_TITLE,                        // 标题
          dwStyle,                          // 窗体属性
          0, 0,                             // 窗体位置
          Width, Height,                    // 窗体大小
          0,                                // 没有父窗体
          0,                                // 没有菜单
          h_Instance,                       // 实例句柄
          Nil);                             // 不向WM_CREATE传递任何东东   If h_Wnd = 0 Then                    // 创建失败,销毁窗体
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, '不能创建窗体!', '错误', MB_OK Or
                MB_ICONERROR);
             Result := False;
             Exit;
          End;   // 描述象素格式
       //选择了通过RGBA(红、绿、蓝、alpha通道)支持OpenGL和双缓存的格式。
       //试图找到匹配选定的色彩深度(16位、24位、32位)的象素格式。
       //最后设置16位Z-缓存。
       //其余的参数要么未使用要么不重要
       //(stencil buffer模板缓存和accumulation buffer聚集缓存除外)。
       With pfd Do
          Begin
             nSize := SizeOf(TPIXELFORMATDESCRIPTOR); // 格式描述符大小
             nVersion := 1;                 // 版本号
             dwFlags := PFD_DRAW_TO_WINDOW  // 格式必须支持窗口
             Or PFD_SUPPORT_OPENGL          // 格式必须支持OpenGL
             Or PFD_DOUBLEBUFFER;           // 必须支持双缓冲
             iPixelType := PFD_TYPE_RGBA;   // 申请 RGBA 格式
             cColorBits := PixelDepth;      // 选定色彩深度
             cRedBits := 0;                 // 忽略的色彩位
             cRedShift := 0;                // 忽略的色彩位
             cGreenBits := 0;               // 忽略的色彩位
             cGreenShift := 0;              // 忽略的色彩位
             cBlueBits := 0;                // 忽略的色彩位
             cBlueShift := 0;               // 忽略的色彩位
             cAlphaBits := 0;               // 无Alpha缓存
             cAlphaShift := 0;              // 忽略Shift Bit
             cAccumBits := 0;               // 无聚集缓存
             cAccumRedBits := 0;            // 忽略聚集位
             cAccumGreenBits := 0;          // 忽略聚集位
             cAccumBlueBits := 0;           // 忽略聚集位
             cAccumAlphaBits := 0;          // 忽略聚集位
             cDepthBits := 16;              // 16位 Z-缓存 (深度缓存)
             cStencilBits := 0;             // 无模板缓存
             cAuxBuffers := 0;              // 无辅助缓存
             iLayerType := PFD_MAIN_PLANE;  // 主绘图层
             bReserved := 0;                // 保留
             dwLayerMask := 0;              // 忽略层遮罩
             dwVisibleMask := 0;            // 忽略层遮罩
             dwDamageMask := 0;             // 忽略层遮罩
          End;
       //得到设备场景描述
       h_DC := GetDC(h_Wnd);
       If (h_DC = 0) Then
          Begin
             glKillWnd(Fullscreen);         // 创建失败,销毁窗体
             MessageBox(0, '不能得到设备场景!', '错误', MB_OK Or
                MB_ICONERROR);
             Result := False;
             Exit;
          End;   //找到相应的象素格式
       PixelFormat := ChoosePixelFormat(h_DC, @pfd);
       If (PixelFormat = 0) Then
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, '找不到合适的格式', '错误', MB_OK
                Or MB_ICONERROR);
             Result := False;
             Exit;
          End;   //设置像素格式.
       If (Not SetPixelFormat(h_DC, PixelFormat, @pfd)) Then
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, '无法创建渲染格式', '错误', MB_OK Or
                MB_ICONERROR);
             Result := False;
             Exit;
          End;   //取得着色描述表
       h_RC := wglCreateContext(h_DC);
       If (h_RC = 0) Then
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, '无法创建OpenGL 绘制描述表', '错误',
                MB_OK Or MB_ICONERROR);
             Result := False;
             Exit;
          End;   //已经取得了设备描述表和着色描述表。
       //激活着色描述表
       If (Not wglMakeCurrent(h_DC, h_RC)) Then
          Begin
             glKillWnd(Fullscreen);
             MessageBox(0, 'Unable to activate OpenGL rendering context', 'Error',
                MB_OK Or MB_ICONERROR);
             Result := False;
             Exit;
          End;
       //OpenGL窗口已经创建完成   // 显示窗体,置于最前
       ShowWindow(h_Wnd, SW_SHOW);          // 显示窗口
       SetForegroundWindow(h_Wnd);          // 略略提高优先级
       SetFocus(h_Wnd);                     // 设置键盘的焦点至此窗口   glResizeWnd(Width, Height);          // 设置透视 GL 屏幕
       glInit();                            // 初始化新建的GL窗口   Result := True;
    End;Function WinMain(hInstance: HINST;      //实例
       hPrevInstance: HINST;                // 前一个实例
       lpCmdLine: PChar;                    // 命令行参数
       nCmdShow: Integer                    // 窗口显示状态
       ): Integer; stdcall;
    Var
       msg              : TMsg;             // Windowsx消息结构
       finished         : Boolean;          // 用来退出循环的Bool 变量
    Begin
       finished := False;   //应用程序初始化
       //glCreateWnd,创建窗体为800*600
       If Not glCreateWnd(800, 600, false, 32) Then
          Begin
             Result := 0;
             Exit;
          End;   While Not finished Do
          Begin
             //检查一个线程消息队列,将所选的范围保存到消息纪录中
             //BOOL PeekMessage(
             //             LPMSG lpMsg,          // 消息记录的指针
             //             HWND hWnd,          // 窗口句柄
             //             UINT wMsgFilterMin,  // 第一个消息
             //             UINT wMsgFilterMax,  // 最后一个消息
             //             UINT wRemoveMsg      // 标志    Value        Meaning
             //            );                                  PM_NOREMOVE 处理后保留在消息队列中
             //                                                PM_REMOVE 处理后从消息队列中清除
             //要做的第一件事是检查是否有消息在等待。
             //使用PeekMessage()可以在不锁住我们的程序的前提下对消息进行检查。
             //许多程序使用GetMessage(),也可以很好的工作。
             //但使用GetMessage(),程序在收到paint消息或其他别的什么窗口消息之前不会做任何事。
             If (PeekMessage(msg, 0, 0, 0, PM_REMOVE)) Then //检查是否有消息
                // wMsgFilterMin,wMsgFilterMax 这两个参数都为0,返回所有可用的消息
                Begin
                   If (msg.message = WM_QUIT) Then // 如果是退出消息
                      finished := True      //改变循环条件,退出
                   Else
                      Begin                 // 否则处理消息
                         // 翻译消息,然后发送消息,使得WndProc() 或 Windows能够处理他们。
                         TranslateMessage(msg); //翻译消息
                         DispatchMessage(msg); //发送消息
                      End;
                End
             Else                           //如果没有消息,绘制我们的OpenGL场景。
                Begin
                   glDraw();                // 重画屏幕
                   SwapBuffers(h_DC);       // 交换缓存 (双缓存)               If (keys[VK_ESCAPE]) Then // 如果按下了ESC键
                      finished := True
                End;
          End;
       glKillWnd(FALSE);                    // 释放窗体
       Result := msg.wParam;                // 退出程序
    End;Begin
       WinMain(hInstance, hPrevInst, CmdLine, CmdShow);
    End.
     这段代码的功能是设置一个 OpenGL窗口。它可以只是一个窗口或是全屏幕的、可以任意 大小、任意色彩深度。此处的代码很稳定且很强大,您可以在您所有的OpenGL项目中使用。我会尽量在学习NeHe教程的同时将他翻译成Delphi版的。
      

  3.   

    AD,你小子研究OPENGL这个东西是准备做什么啊 ?
      

  4.   

    玩呀 :)一天到晚数据库有什么意思?FS,这个全考过去就可以直接运行的什么都不用,只要Project文件就行了你试试,看在你机器上能不能运行?
      

  5.   

    怎么没人顶?平时不是好多兄弟都嫌没有资料吗?继续  利用上面的框架,我们可以很方便的进行我们的OPENGL编程(NeHe的教程也是围绕这个框架展开的,而且我看老外的源码,很多使用这个框架的)下面我们在窗体上画一个三角和一个正方形只要在Procedure glDraw();中添加以下代码即可//==============================================================================
    //所有的绘图代码。任何您所想在屏幕上显示的东东都将在此段代码中出现。
    //以后的每个程序会在此处增加新的代码。
    //==============================================================================Procedure glDraw();
    Begin
       glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存   //当您调用glLoadIdentity()之后,您实际上讲当前点移到了屏幕中心,X坐标轴从左至右,
       //Y坐标轴从下至上,Z坐标轴从里至外。OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。
       // 中心左面的坐标值是负值,右面是正值。移向屏幕顶端是正值,移向屏幕底端是负值。
       // 移入屏幕深处是负值,移出屏幕则是正值。
       glLoadIdentity();                    // 重置当前的模型观察矩阵   //glTranslatef(x, y, z)沿着 X, Y 和 Z 轴移动。
       //根据前面的次序,下面的代码沿着X轴左移1.5个单位,Y轴不动(0.0f),最后移入屏幕6.0f个单位。
       //注意在glTranslatef(x, y, z)中当您移动的时候,您并不是相对屏幕中心移动,
       //而是相对与当前所在的屏幕位置。
       glTranslatef(-1.5, 0.0, -6.0);       // 左移 1.5 单位,并移入屏幕 6.0   //现在我们已经移到了屏幕的左半部分,
       //并且将视图推入屏幕背后足够的距离以便我们可以看见全部的场景-创建三角形。
       //glBegin(GL_TRIANGLES)的意思是开始绘制三角形,glEnd() 告诉OpenGL三角形已经创建好了。
       //通常您会需要画3个顶点,可以使用GL_TRIANGLES。
       //在绝大多数的显卡上,绘制三角形是相当快速的。
       //如果要画四个顶点,使用GL_QUADS的话会更方便。
       //但据我所知,绝大多数的显卡都使用三角形来为对象着色。
       //最后,如果您想要画更多的顶点时,可以使用GL_POLYGON。   //本节的简单示例中,我们只画一个三角形。
       //如果要画第二个三角形的话,可以在这三点之后,再加三行代码(3点)。
       //所有六点代码都应包含在glBegin(GL_TRIANGLES) 和 glEnd()之间。
       //在他们之间再不会有多余的点出现,
       //也就是说,(GL_TRIANGLES) 和 glEnd()之间的点都是以三点为一个集合的。
       //这同样适用于四边形。如果您知道实在绘制四边形的话,
       //您必须在第一个四点之后,再加上四点为一个集合的点组。
       //另一方面,多边形可以由任意个顶点,
       //(GL_POLYGON)不在乎glBegin(GL_TRIANGLES) 和 glEnd()之间有多少行代码。    //   几何图元类型和说明
        //   类型                    说明
        //   GL_POINTS              单个顶点集
        //   GL_LINES               多组双顶点线段
        //   GL_POLYGON             单个简单填充凸多边形
        //   GL_TRAINGLES           多组独立填充三角形
        //   GL_QUADS               多组独立填充四边形
        //   GL_LINE_STRIP          不闭合折线
        //   GL_LINE_LOOP           闭合折线
        //   GL_TRAINGLE_STRIP      线型连续填充三角形串
        //   GL_TRAINGLE_FAN        扇形连续填充三角形串
        //   GL_QUAD_STRIP          连续填充四边形串  //glBegin之后的第一行设置了多边形的第一个顶点,
      //glVertex 的第一个参数是X坐标,然后依次是Y坐标和Z坐标。
      //第一个点是上顶点,然后是左下顶点和右下顶点。
      //glEnd()告诉OpenGL没有其他点了。
      //这样将显示一个填充的三角形。  //译者:这里要注意的是存在两种不同的坐标变换方式,
      //glTranslatef(x, y, z)中的x, y, z是相对与您当前所在点的位移,
      //但glVertex(x,y,z)是相对于glTranslatef(x, y, z)移动后的新原点的位移。
      //因而这里可以认为glTranslate移动的是坐标原点,glVertex中的点是相对最新的坐标原点的坐标值。   glBegin(GL_TRIANGLES);               // 绘制三角形
       glVertex3f(0.0, 1.0, 0.0);           // 上顶点
       glVertex3f(-1.0, -1.0, 0.0);         // 左下
       glVertex3f(1.0, -1.0, 0.0);          // 右下
       glEnd();                             // 三角形绘制结束   //在屏幕的左半部分画完三角形后,我们要移到右半部分来画正方形。
       //为此要再次使用glTranslate。
       //这次右移,所以X坐标值为正值。
       //因为前面左移了1.5个单位,
       //这次要先向右移回屏幕中心(1.5个单位),再向右移动1.5个单位。
       //总共要向右移3.0个单位。   glTranslatef(3.0, 0.0, 0.0);         // 右移3单位   //现在使用GL_QUADS绘制正方形。
       //与绘制三角形的代码相类似,画四边形也很简单。
       //唯一的区别是用GL_QUADS来替换了GL_TRIANGLES。
       //并增加了一个点。
       //我们使用顺时针次序来画正方形-左上-右上-右下-左下。
       //采用顺时针绘制的是对象的后表面。这就是说我们所看见的是正方形的背面。
       //逆时针画出来的正方形才是正面朝着我们的。
       //现在来说并不重要,但以后您必须知道。
       glBegin(GL_QUADS);                   // 绘制正方形
       glVertex3f(-1.0, 1.0, 0.0);          // 左上
       glVertex3f(1.0, 1.0, 0.0);           // 右上
       glVertex3f(1.0, -1.0, 0.0);          // 左下
       glVertex3f(-1.0, -1.0, 0.0);         // 右下
       glEnd();                             // 正方形绘制结束   // Markus Knauer 注:
       //在 ("OpenGL Programming Guide: The Official Guide to Learning OpenGL, Release 1",
       //J. Neider, T. Davis, M. Woo, Addison-Wesley, 1993)
       //《OpenGL编程指南:OpenGL学习的官方指南,第一版》
       //一书中清楚的解释了NeHe所指的在OpenGL中移动的单位概念:
       //"在OpenGL中真的有英寸和英里的区别吗?
       //答案是一句话:没有。透视和其他的变换都是无单位的。
       //如果您想要裁剪在1.0到20.0米,英寸、公里等等之间的平面,
       //在OpenGL中您无法做到。唯一的法则是您必须使用一致的度量单位。"
    End;
    你可以运行一下看看效果
      

  6.   

    继续上一节中我教给您三角形和四边形的绘制方法。这一节将教您给三角形和四边形添加2种不同类型的着色方法。使用Flat coloring(单调着色)给四边形涂上固定的一种颜色。使用Smooth coloring(平滑着色)将三角形的三个顶点的不同颜色混合在一起,创建漂亮的色彩混合。继续在上节的glDraw上修改。Procedure glDraw();
    Begin
       glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存
       glLoadIdentity();                    // 重置当前的模型观察矩阵   glTranslatef(-1.5, 0.0, -6.0);       // 左移 1.5 单位,并移入屏幕 6.0   glBegin(GL_TRIANGLES);               // 绘制三角形   //glColor3f(r,g,b)。括号中的三个参数依次是红、绿、蓝三色分量。
       //取值范围可以从0,0到1.0。类似于以前所讲的清除屏幕背景命令。   //我们将颜色设为红色(纯红色,无绿色,无蓝色)。
       //接下来的一行代码设置三角形的第一个顶点(三角形的上顶点),
       //并使用当前颜色(红色)来绘制。从现在开始所有的绘制的对象的颜色都是红色,
       //直到我们将红色改变成别的什么颜色。   glColor3f(1.0, 0.0, 0.0);            //设置当前色为红色
       glVertex3f(0.0, 1.0, 0.0);           // 上顶点   //第一个红色顶点已经设置完毕。
       //接下来我们设置第二个绿色顶点。三角形的左下顶点被设为绿色。
       glColor3f(0.0, 1.0, 0.0);            //设置当前色为绿色
       glVertex3f(-1.0, -1.0, 0.0);         // 左下
       //三角形的右下顶点。将颜色设为蓝色
       //glEnd()出现后,三角形将被填充。
       //但是因为每个顶点有不同的颜色,因此看起来颜色从每个角喷出,
       //并刚好在三角形的中心汇合,三种颜色相互混合。这就是平滑着色。
       glColor3f(0.0, 0.0, 1.0);            //设置当前色为蓝色
       glVertex3f(1.0, -1.0, 0.0);          // 右下   glEnd();                             // 三角形绘制结束
       glTranslatef(3.0, 0.0, 0.0);         // 右移3单位   //现在我们绘制一个单调着色-紫色的正方形。
       //最重要的是要记住,设置当前色之后绘制的所有东东都是当前色的。
       //以后您所创建的每个工程都要使用颜色。
       //即便是在完全采用纹理贴图的时候,
       //glColor3f仍旧可以用来调节纹理的色调。
       //等等....,以后再说吧。
       //(呵呵,原书是蓝色,但是我喜欢紫色)   glBegin(GL_QUADS);                   // 绘制正方形
       glColor3f(0.6, 0.2, 2.0);            //设置当前色为紫色
       glVertex3f(-1.0, 1.0, 0.0);          // 左上
       glVertex3f(1.0, 1.0, 0.0);           // 右上
       glVertex3f(1.0, -1.0, 0.0);          // 左下
       glVertex3f(-1.0, -1.0, 0.0);         // 右下
       glEnd();                             // 正方形绘制结束
    End;运行一下看看效果
      

  7.   

    OpenGL,什么东西呀?
    不要拿鸡蛋砸我呀,我真的不懂!--------------------------------------
    靠,还不结帖!
      

  8.   

    (2003-07-26 14:48:34)   阿德
    帮我up一下,我好回贴http://expert.csdn.net/Expert/topic/2072/2072933.xml?temp=.1717646------------------------------------------------------------------------什么叫虚伪?这就叫虚伪!哈哈..........
      

  9.   

    实在搞不懂
    平时那么些问游戏编程需要什么的,opengl怎么入门的,现在都哪去了?
    俺对opengl以前也是一窍不通的,现在俺给他们整理好了贴出来,咋就没人理呢?要是到了周一还没人的话,俺就结贴,何苦呢?
      

  10.   

    哪里是我搞明白了是我参考CKER翻译的NeHe的VC 的OPENGL的教程来的在这里再次对CKER表示感谢,对NeHe表示敬仰!
    其实仔细看看代码会发现,撇开OPENGL不说,我们也能学到很多东西的
      

  11.   

    myling(阿德) :
    我喜欢~
    :)偶正在玩OpenGL,遇到问题多多~
    还请指教!
      

  12.   


    我按部就班的做了一遍,挺不错~
    可是遇到一个大~~~~~问题!
    就是我想在一个Form中做多个OpenGL的显示——搞不定!
    我下载了一个控件TGLPanel——好像是从“品雪”那儿下的——它能做,可是“视角”又不很理想,向改称我自己的方法,可惜功力太浅没搞定!求教
      

  13.   

    求教?
    呵呵,我现在连门都没入,何来求教?在form中显示OPENGL我还没做过
    不知道是不是简单的连接在form的DC上,而不是象例子中的自己创建DC如果是的话,在窗体中创建多个DC不知行不行?呵呵,OPENGL这个玩艺我才搞了几天,很外行的,共同学习吧
      

  14.   

    靠,好像不行呀,我试了半天,还是搞不定呵呵,不能越级,我要一步步来,急不得的从现在开始老兄,你这个问题,到大富翁上问问吧,让cdyxl他们回答你吧,呵呵
      

  15.   

    哈,搞定了!
    有点意思,果然是我想的那样!!
    不过现在只是连接到form的DC上,代码如下:Unit Unit1;
    Interface
    Uses
       Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
       Dialogs, StdCtrls, opengl, ExtCtrls;
    Type
       TForm1 = Class(TForm)
          Timer1: TTimer;
          Procedure FormCreate(Sender: TObject);
          Procedure Timer1Timer(Sender: TObject);
       private
          { Private declarations }
       public
          { Public declarations }
       End;
    Var
       Form1            : TForm1;
       h_RC             : HGLRC;            // Rendering Context(着色描述表)。
       h_DC             : HDC;              // Device Context(设备描述表)
       pfd              : TPIXELFORMATDESCRIPTOR; //格式描述符
       PixelFormat      : GLuint;           // 象素格式
       keys             : Array[0..255] Of Boolean; // 用于键盘例程的数组
       rtri             : GLfloat;          // 用于三角形的角度
       rquad            : GLfloat;          // 用于四边形的角度
    Implementation
    {$R *.dfm}
    Procedure glDraw();
    Begin
       glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存
       glLoadIdentity();                    // 重置当前的模型观察矩阵
       glTranslatef(-1.5, 0.0, -6.0);       // 左移 1.5 单位,并移入屏幕 6.0
       glRotatef(rtri, 0.0, 1.0, 0.0);      // 绕Y轴旋转三角形 ( 新增 )
       glBegin(GL_TRIANGLES);               // 绘制三角
       glColor3f(1.0, 0.0, 0.0);            //设置当前色为红色
       glVertex3f(0.0, 1.0, 0.0);           // 上顶点
       glColor3f(0.0, 1.0, 0.0);            //设置当前色为绿色
       glVertex3f(-1.0, -1.0, 0.0);         // 左下
       glColor3f(0.0, 0.0, 1.0);            //设置当前色为蓝色
       glVertex3f(1.0, -1.0, 0.0);          // 右下
       glEnd();                             // 三角形绘制结束
       glLoadIdentity();                    // 重置模型观察矩阵
       glTranslatef(1.5, 0.0, -6.0);        // 右移1.5单位,并移入屏幕 6.0
       glRotatef(rquad, 1.0, 0.0, 0.0);     // 绕X轴旋转四边形 ( 新增 )
       glBegin(GL_QUADS);                   // 绘制正方形
       glColor3f(0.6, 0.2, 2.0);            //设置当前色为紫色
       glVertex3f(-1.0, 1.0, 0.0);          // 左上
       glVertex3f(1.0, 1.0, 0.0);           // 右上
       glVertex3f(1.0, -1.0, 0.0);          // 左下
       glVertex3f(-1.0, -1.0, 0.0);         // 右下
       glEnd();                             // 正方形绘制结束
       rtri := rtri + 0.2;                  // 增加三角形的旋转变量(新增)
       rquad := rquad - 0.15;               // 减少四边形的旋转变量(新增)
    End;
    Procedure glResizeWnd(Width, Height: Integer); // 重置并初始化GL窗口大小
    Begin
       If (Height = 0) Then                 // 防止高度为0,产生除0异常
          Height := 1;
       glViewport(0, 0, Width, Height);     // 重置当前的视口(Viewport)
       glMatrixMode(GL_PROJECTION);         // 选择投影矩阵
       glLoadIdentity();                    // 重置投影矩阵
       gluPerspective(45.0, Width / Height, 0.1, 100.0); // 计算窗口的外观比例
       glMatrixMode(GL_MODELVIEW);          // 选择模型观察矩阵
       glLoadIdentity();                    // 重置模型观察矩阵
    End;
    Procedure glInit();
    Begin
       glClearColor(0.0, 0.0, 0.0, 0.0);    // 黑色背景
       glShadeModel(GL_SMOOTH);             // 启用阴影平滑
       glClearDepth(1.0);                   // 设置深度缓存
       glEnable(GL_DEPTH_TEST);             // 启用深度测试
       glDepthFunc(GL_LESS);                // 所作深度测试的类型
       glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 真正精细的透视修正
    End;
    Procedure TForm1.FormCreate(Sender: TObject);
    Begin
       With pfd Do
          Begin
             nSize := SizeOf(TPIXELFORMATDESCRIPTOR); // 格式描述符大小
             nVersion := 1;                 // 版本号
             dwFlags := PFD_DRAW_TO_WINDOW  // 格式必须支持窗口
             Or PFD_SUPPORT_OPENGL          // 格式必须支持OpenGL
             Or PFD_DOUBLEBUFFER;           // 必须支持双缓冲
             iPixelType := PFD_TYPE_RGBA;   // 申请 RGBA 格式
             //cColorBits := PixelDepth;      // 选定色彩深度
             cRedBits := 0;                 // 忽略的色彩位
             cRedShift := 0;                // 忽略的色彩位
             cGreenBits := 0;               // 忽略的色彩位
             cGreenShift := 0;              // 忽略的色彩位
             cBlueBits := 0;                // 忽略的色彩位
             cBlueShift := 0;               // 忽略的色彩位
             cAlphaBits := 0;               // 无Alpha缓存
             cAlphaShift := 0;              // 忽略Shift Bit
             cAccumBits := 0;               // 无聚集缓存
             cAccumRedBits := 0;            // 忽略聚集位
             cAccumGreenBits := 0;          // 忽略聚集位
             cAccumBlueBits := 0;           // 忽略聚集位
             cAccumAlphaBits := 0;          // 忽略聚集位
             cDepthBits := 16;              // 16位 Z-缓存 (深度缓存)
             cStencilBits := 0;             // 无模板缓存
             cAuxBuffers := 0;              // 无辅助缓存
             iLayerType := PFD_MAIN_PLANE;  // 主绘图层
             bReserved := 0;                // 保留
             dwLayerMask := 0;              // 忽略层遮罩
             dwVisibleMask := 0;            // 忽略层遮罩
             dwDamageMask := 0;             // 忽略层遮罩
          End;
       h_DC := GetDC(self.Handle);
       PixelFormat := ChoosePixelFormat(h_DC, @pfd);
       SetPixelFormat(h_DC, PixelFormat, @pfd);
       h_RC := wglCreateContext(h_DC);
       wglMakeCurrent(h_DC, h_RC);
       glResizeWnd(Width, Height);          // 设置透视 GL 屏幕
       glInit();                            // 初始化新建的GL窗口
    End;Procedure startdraw;
    Var
       msg              : TMsg;             // Windowsx消息结构
       finished         : Boolean;          // 用来退出循环的Bool 变量
    Begin
       finished := False;
       While Not finished Do
          If (PeekMessage(msg, 0, 0, 0, PM_REMOVE)) Then //检查是否有消息
             Begin
                If (msg.message = WM_QUIT) Then // 如果是退出消息
                   finished := True         //改变循环条件,退出
                Else
                   Begin                    // 否则处理消息
                      TranslateMessage(msg); //翻译消息
                      DispatchMessage(msg); //发送消息
                   End;
             End
          Else                              //如果没有消息,绘制我们的OpenGL场景。
             Begin
                glDraw();                   // 重画屏幕
                SwapBuffers(h_DC);          // 交换缓存 (双缓存)
                If (keys[VK_ESCAPE]) Then   // 如果按下了ESC键
                   finished := True
             End;
       Application.Terminate;
    End;
    Procedure TForm1.Timer1Timer(Sender: TObject);
    Begin
       startdraw;
       Timer1.Enabled := false;
    End;
    End.
    运行一下看看效果 :)这样就不用麻烦他们了,呵呵,下班了
      

  16.   

    :)
    谢谢~不过,我要的不是着效果的“多个”OpenGL显示
    我要的是在一个窗口中,有两个或多个Panel做为显示“窗口”
      

  17.   

    哈,那样更简单了!把这句
    h_DC := GetDC(self.Handle);
    换成
    h_DC := GetDC(Panel1.Handle);就搞定了!
      

  18.   

    楼主!还是搞错了!
    ——————————————————————
    把这句
    h_DC := GetDC(self.Handle);
    换成
    h_DC := GetDC(Panel1.Handle);
    ——————————————————————
    不还是都在一个地方显示嘛~
    我要的是在多个“Panel”里现实!
      

  19.   

    呵呵,是我搞错了sorry不知道用线程能不能搞定先吃饭去,等晚上试试
      

  20.   

    呵呵,是我搞错了sorry不知道用线程能不能搞定先吃饭去,等晚上试试
      

  21.   

    http://www.freecoder.org/~pinxue/OpenGL/tglp_src.zip
    这是我找的一个控件,是“品雪”的看上去挺简单的,可是我拿咱们的方法往上套就是不行!
    :(
      

  22.   

    搞定了~
      gluPerspective(45.0, ClientWidth/ClientHeight,1,500);//能够定义一个以Z轴为中线的四棱台视景体.
      glOrtho(-1, 1, -1, 1, -1, 50);                       //用投影矩阵操纵当前矩阵;虽然没有深入了解,可是看了些文档改了几个方法,搞定了!
    可以使了!可是怎么做Zoom涅?!怎么做可以选择Zoom区域的?!
    :)
      

  23.   

    ZOOM怎么做?
    就是用鼠标圈选区域放大!?
      

  24.   

    从现在开始:       呵呵,你说的这些我都没做过,我想应该是吧?
       向正方向移动z轴就行了吧?
           根据鼠标up和down的坐标,和当前屏幕斜角的顶点坐标,
       比上现在z轴的距离,能求出移动的距离吧?
           这个玩艺应该是立体几何的东东吧?
           没做过,瞎说的磁效应:
       
          呵呵。我的业余生活还比较闲,有东西写当然好了!
       但是俺现在这个水平……      哈,够呛呀,还是先好好学学吧,有什么想法QQ联系    
      

  25.   

    继续……
    {贴图可以极大的节省CPU时间。呵呵,但是这一节费了我比较多的时间 : (因为用到了opengl的辅助库,现在这个库的函数已经很少有人用了,但是我还是找到了,感谢zdcnow(磁效应),他给我提供的这个辅助库的delphi版本。在学习本节之前,请大家到网上下载glaux.dll、Glaux.pas文件,并加到项目中。好了,让我们继续OPENGL之路.首先我们需要加进SysUtils单元,因为我们这节要用到文件操作,我们还要将Glaux单元加进来。然后我们在第一课的基础上加上几个变量,xrot , yrot 和 zrot 。这些变量用来使立方体绕X、Y、Z轴旋转。texture[] 为一个纹理分配存储空间。如果您需要不止一个的纹理,应该将数字1改成您所需要的数字。}VAR   h_RC             : HGLRC;            // Rendering Context(着色描述表)。
       h_DC             : HDC;              // Device Context(设备描述表)
       h_Wnd            : HWND;             // 窗口句柄
       h_Instance       : HINST;            // 程序Instance(实例)。
       keys             : Array[0..255] Of Boolean; // 用于键盘例程的数组   xrot,                                // X 旋转量 ( 新增 )
       yrot,                                // Y 旋转量 ( 新增 )
       zrot             : GLfloat;          // Z 旋转量 ( 新增 )  Texture          : Array[0..1] Of GLuint; // 存储一个纹理 ( 新增 ){然后引载入opengl32.dll中的两个过程,我们要用到他们}
    Procedure glGenTextures(n: GLsizei; Var textures: GLuint); stdcall; external
       opengl32;
    Procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external
       opengl32;{接下来我们需要增加一个新的函数,用来再入图像,该函数的返回类型在Glaux.pas中定义如下:TAUX_RGBImageRec= record
           sizeX, sizeY: GLint;
            data: pointer;
              end;
     PTAUX_RGBImageRec= ^TAUX_RGBImageRec;具体含义会在后面介绍}Function LoadBmp(filename: pchar): PTAUX_RGBImageRec;
    Var
       BitmapFile       : Thandle;          // 文件句柄
    Begin
       //接下来检查文件名是否已提供
       If Filename = '' Then                // 确保文件名已提供。
          result := Nil;                    // 如果没提供,返回 NULL
       //接着检查文件是否存在。
       BitmapFile := FileOpen(Filename, fmOpenWrite); //尝试打开文件
       //如果我们能打开文件的话,很显然文件是存在的。   If BitmapFile > 0 Then               // 文件存在么?
          Begin
             //关闭文件。
             FileClose(BitmapFile);         // 关闭句柄
             //auxDIBImageLoad(Filename) 读取图象数据并将其返回。
             result := auxDIBImageLoadA(filename); //载入位图并返回指针
          End
       Else
          //如果我们不能打开文件,我们将返回NiL。
          result := Nil;                    // 如果载入失败,返回NiL。
    End;
      

  26.   

    //接下来在创建一个新函数,用来载入纹理贴图Function LoadTexture: boolean;//Status 的变量。我们使用它来跟踪是否能够载入位图以及能否创建纹理。
    // Status 缺省设为 FALSE (表示没有载入或创建任何东东)。
    //TextureImage变量PTAUX_RGBImageRec类型  存储位图的图像记录。
    //次记录包含位图的宽度、高度和数据。Var
       Status           : boolean;
       TextureImage     : Array[0..1] Of PTAUX_RGBImageRec;
    Begin
       Status := false;
       ZeroMemory(@TextureImage, sizeof(TextureImage)); // 将指针设为 NULL
       TextureImage[0] := LoadBMP('Texture.bmp');
       If TextureImage[0] <> Nil Then
          Begin
             Status := TRUE;                // 将 Status 设为 TRUE
             //现在使用中 TextureImage[0] 的数据创建纹理。
             //glGenTextures(1, texture[0]) 告诉OpenGL我们想生成一个纹理名字
             //(如果您想载入多个纹理,加大数字)。
             //glBindTexture(GL_TEXTURE_2D, texture[0]) 告诉OpenGL将纹理名字 texture[0] 绑定到纹理目标上。
             //2D纹理只有高度(在 Y 轴上)和宽度(在 X 轴上)。
             //主函数将纹理名字指派给纹理数据。
             //本例中我们告知OpenGL, &texture[0] 处的内存已经可用。
             //我们创建的纹理将存储在 &texture[0] 的 指向的内存区域。
             glGenTextures(1, texture[0]);  // 创建纹理
             glBindTexture(GL_TEXTURE_2D, texture[0]);  // 使用来自位图数据生成 的典型纹理
             //下来我们创建真正的纹理。
             //下面一行告诉OpenGL此纹理是一个2D纹理 ( GL_TEXTURE_2D )。
             //数字零代表图像的详细程度,通常就由它为零去了。
             //数字三是数据的成分数。因为图像是由红色数据,绿色数据,蓝色数据三种组分组成。
             //TextureImage[0].sizeX 是纹理的宽度。
             //如果您知道宽度,您可以在这里填入,但计算机可以很容易的为您指出此值。
             // TextureImage[0].sizey 是纹理的高度。
             //数字零是边框的值,一般就是零。
             // GL_RGB 告诉OpenGL图像数据由红、绿、蓝三色数据组成。
             //GL_UNSIGNED_BYTE 意味着组成图像的数据是无符号字节类型的。
             //最后... TextureImage[0].data 告诉OpenGL纹理数据的来源。
             //此例中指向存放在 TextureImage[0] 记录中的数据。         // 生成纹理
             glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
                TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
                TextureImage[0].data);         //下面的两行告诉OpenGL在显示图像时,
             //当它比放大得原始的纹理大(GL_TEXTURE_MAG_FILTER)
             //或缩小得比原始得纹理小(GL_TEXTURE_MIN_FILTER)时OpenGL采用的滤波方式。
             //通常这两种情况下我都采用 GL_LINEAR。这使得纹理从很远处到离屏幕很近时都平滑显示。
             //使用 GL_LINEAR需要CPU和显卡做更多的运算。
             //如果您的机器很慢,您也许应该采用 GL_NEAREST 。
             //过滤的纹理在放大的时候,看起来斑驳的很(马赛克啦)。
             //您也可以结合这两种滤波方式。在近处时使用 GL_LINEAR ,远处时 GL_NEAREST 。
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  // 线形滤波
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  // 线形滤波
          End;
       //现在我们释放前面用来存放位图数据的内存。
       //我们先查看位图数据是否存放在处。
       //如果是的话,再查看数据是否已经存储。
       //如果已经存储的话,删了它。
       //接着再释放 TextureImage[0] 图像结构以保证所有的内存都能释放。
       If assigned(TextureImage[0]) Then    // 纹理是否存在
          If assigned(TextureImage[0].data) Then // 纹理图像是否存在
             TextureImage[0].data := Nil;   // 释放纹理图像占用的内存
       TextureImage[0] := Nil;              // 释放图像结构
       // 最后返回状态变量。如果一切OK,变量 Status 的值为 TRUE 。否则为 FALSE
       result := Status;                    // 返回 Status
    End;
    //然后在 glInit 中增加很少的几行代码Procedure glInit();
    Begin
       If (Not LoadTexture) Then            // 调用纹理载入子例程( 新增 )
          exit;                             // 如果未能载入,退出( 新增 )
       glEnable(GL_TEXTURE_2D);             // 启用纹理映射( 新增 )
       glClearColor(0.0, 0.0, 0.0, 0.0);    // 黑色背景
       glShadeModel(GL_SMOOTH);             // 启用阴影平滑
       glClearDepth(1.0);                   // 设置深度缓存
       glEnable(GL_DEPTH_TEST);             // 启用深度测试
       glDepthFunc(GL_LESS);                // 所作深度测试的类型
       glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 真正精细的透视修正End;
      

  27.   

    {现在我们绘制贴图过的立方体。这段代码被狂注释了一把,应该很好懂。开始两行代码 glClear() 和 glLoadIdentity() 是第一课中就有的代码。 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 清除屏幕并设为我们在 InitGL() 中选定的颜色,本例中是黑色。深度缓存也被清除。模型观察矩阵也使用glLoadIdentity()重置。}Procedure glDraw();
    Begin
       glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存
       glLoadIdentity();                    // 重置当前的模型观察矩阵
       glTranslatef(0.0, 0.0, -6.0);        // 移入屏幕6个单位   //下面三行使立方体绕X、Y、Z轴旋转。
       //旋转多少依赖于变量 xrot , yrot 和 zrot 的值。
       glRotatef(xrot, 1.0, 0.0, 0.0);      // 绕X轴旋转
       glRotatef(yrot, 0.0, 1.0, 0.0);      // 绕Y轴旋转
       glRotatef(zrot, 0.0, 0.0, 1.0);      // 绕Z轴旋转   //下一行代码选择我们使用的纹理。
       //如果在场景中使用多个纹理,应该使用
       //glBindTexture(GL_TEXTURE_2D, texture[ 所使用纹理对应的数字 ]) 来选择要绑定的纹理。
       //当想改变纹理时,应该绑定新的纹理。
       //有一点值得指出的是,
       //不能在 glBegin() 和 glEnd() 之间绑定纹理,
       //必须在 glBegin() 之前或 glEnd() 之后绑定。
       //注意我们在后面是如何使用 glBindTexture 来指定和绑定纹理的。   glBindTexture(GL_TEXTURE_2D, texture[0]); // 选择纹理   //为了将纹理正确的映射到四边形上,
       //必须将纹理的右上角映射到四边形的右上角,
       //纹理的左上角映射到四边形的左上角,
       //纹理的右下角映射到四边形的右下角,
       //纹理的左下角映射到四边形的左下角。
       //如果映射错误的话,图像显示时可能上下颠倒,侧向一边或者什么都不是。   //glTexCoord2f 的第一个参数是X坐标。
       // 0.0是纹理的左侧。 0.5是纹理的中点, 1.0是纹理的右侧。
       //glTexCoord2f 的第二个参数是Y坐标。
       //0.0是纹理的底部。 0.5是纹理的中点, 1.0是纹理的顶部。
       //所以纹理的左上坐标是 X:0.0f,Y:1.0f ,
       //四边形的左上顶点是 X: -1.0f,Y:1.0f 。
       //其余三点依此类推。   //试着玩玩 glTexCoord2f 的X,Y坐标参数。
       //把1.0改为0.5将只显示纹理的左半部分,
       //把0.0改为0.5将只显示纹理的右半部分。
       glBegin(GL_QUADS);
       // 前面
       glTexCoord2f(0.0, 0.0);
       glVertex3f(-1.0, -1.0, 1.0);         // 纹理和四边形的左下
       glTexCoord2f(1.0, 0.0);
       glVertex3f(1.0, -1.0, 1.0);          // 纹理和四边形的右下
       glTexCoord2f(1.0, 1.0);
       glVertex3f(1.0, 1.0, 1.0);           // 纹理和四边形的右上
       glTexCoord2f(0.0, 1.0);
       glVertex3f(-1.0, 1.0, 1.0);          // 纹理和四边形的左上
       // 后面
       glTexCoord2f(1.0, 0.0);
       glVertex3f(-1.0, -1.0, -1.0);        // 纹理和四边形的右下
       glTexCoord2f(1.0, 1.0);
       glVertex3f(-1.0, 1.0, -1.0);         // 纹理和四边形的右上
       glTexCoord2f(0.0, 1.0);
       glVertex3f(1.0, 1.0, -1.0);          // 纹理和四边形的左上
       glTexCoord2f(0.0, 0.0);
       glVertex3f(1.0, -1.0, -1.0);         // 纹理和四边形的左下
       // 顶面
       glTexCoord2f(0.0, 1.0);
       glVertex3f(-1.0, 1.0, -1.0);         // 纹理和四边形的左上
       glTexCoord2f(0.0, 0.0);
       glVertex3f(-1.0, 1.0, 1.0);          // 纹理和四边形的左下
       glTexCoord2f(1.0, 0.0);
       glVertex3f(1.0, 1.0, 1.0);           // 纹理和四边形的右下
       glTexCoord2f(1.0, 1.0);
       glVertex3f(1.0, 1.0, -1.0);          // 纹理和四边形的右上
       // 底面
       glTexCoord2f(1.0, 1.0);
       glVertex3f(-1.0, -1.0, -1.0);        // 纹理和四边形的右上
       glTexCoord2f(0.0, 1.0);
       glVertex3f(1.0, -1.0, -1.0);         // 纹理和四边形的左上
       glTexCoord2f(0.0, 0.0);
       glVertex3f(1.0, -1.0, 1.0);          // 纹理和四边形的左下
       glTexCoord2f(1.0, 0.0);
       glVertex3f(-1.0, -1.0, 1.0);         // 纹理和四边形的右下
       // 右面
       glTexCoord2f(1.0, 0.0);
       glVertex3f(1.0, -1.0, -1.0);         // 纹理和四边形的右下
       glTexCoord2f(1.0, 1.0);
       glVertex3f(1.0, 1.0, -1.0);          // 纹理和四边形的右上
       glTexCoord2f(0.0, 1.0);
       glVertex3f(1.0, 1.0, 1.0);           // 纹理和四边形的左上
       glTexCoord2f(0.0, 0.0);
       glVertex3f(1.0, -1.0, 1.0);          // 纹理和四边形的左下
       // 左面
       glTexCoord2f(0.0, 0.0);
       glVertex3f(-1.0, -1.0, -1.0);        // 纹理和四边形的左下
       glTexCoord2f(1.0, 0.0);
       glVertex3f(-1.0, -1.0, 1.0);         // 纹理和四边形的右下
       glTexCoord2f(1.0, 1.0);
       glVertex3f(-1.0, 1.0, 1.0);          // 纹理和四边形的右上
       glTexCoord2f(0.0, 1.0);
       glVertex3f(-1.0, 1.0, -1.0);         // 纹理和四边形的左上
       glEnd();   xrot := xrot + 0.3;                  // X 轴旋转
       yrot := yrot + 0.2;                  // Y 轴旋转
       zrot := zrot + 0.4;                  // Z 轴旋转
    End;{最后,关于用作纹理的图像我想有几点十分重要,并且您必须明白。此图像的宽和高必须是2的n次方;宽度和高度最小必须是64象素;并且出于兼容性的原因,图像的宽度和高度不应超过256象素。如果您的原始素材的宽度和高度不是64,128,256象素的话,使用图像处理软件重新改变图像的大小。可以肯定有办法能绕过这些限制,但现在我们只需要用标准的纹理尺寸。}//OK!运行一下看看效果
      

  28.   

    http://www.csdn.net/Develop/read_article.asp?id=20023
    http://www.csdn.net/Develop/read_article.asp?id=20029
    http://www.csdn.net/Develop/read_article.asp?id=20031
    http://www.csdn.net/Develop/read_article.asp?id=20039
    http://www.csdn.net/Develop/read_article.asp?id=20109
    http://www.csdn.net/Develop/read_article.asp?id=20165一共六课,还会继续贴的
      

  29.   

    呵呵,最近比较忙,第7课早写翻译了,但是一直没时间整理现在贴出来了http://www.csdn.net/Develop/read_article.asp?id=20554
      

  30.   

    myling(阿德) 
    可不可以把你上边发的好长的代码的程序给我一个啊`
    我运行了~
    可是什么效果没有啊~
    555555555555~~~~~~~~~~~
    我很想学习OPENGL啊~
    [email protected]
      

  31.   

    OpenGL 和 Direct3D 有什么区别?
      

  32.   

    唉,越来越懒,时间拖的越来越长这次贴两课第8课:透明http://www.csdn.net/Develop/read_article.asp?id=21062第9课:星星动画http://www.csdn.net/Develop/read_article.asp?id=21064
      

  33.   

    procedure TPForm.FormCreate(Sender: TObject);
    var
      pDC: HDC;
    begin  // It's simple, really:
      pDC := GetDC(GLPanel1.Handle);
      CgDC1 := TCGDeviceContext.Create(pDC);
      CgDC1.InitGL;
      glEnable(GL_DEPTH_TEST);  // Note that each DC you create has its own OpenGL state variables!
      pDC := GetDC(GLPanel2.Handle);
      CgDC2 := TCGDeviceContext.Create(pDC);
      CgDC2.InitGL;
      glEnable(GL_DEPTH_TEST);end;procedure TPForm.FormClose(Sender: TObject; var Action: TCloseAction);
    begin  CgDC1.Free;
      CgDC2.Free;end;procedure TPForm.FormPaint(Sender: TObject);
    begin  // Just draw something...
      CgDC1.MakeCurrent;
      glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
      glLoadIdentity;
      glRotatef(a, 1, 2, 3);
      glutWireTorus(0.2, 0.4, 16, 32);
      CgDC1.PageFlip;  // And to the second panel as well...
      CgDC2.MakeCurrent;
      glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
      glLoadIdentity;
      glRotatef(-a, 1, 2, 3);
      glBegin(GL_TRIANGLES);
        glColor3f(1, 0, 0);   glVertex2f(-0.5, -0.5);
        glColor3f(0, 1, 0);   glVertex2f(0.5, -0.5);
        glColor3f(0, 0, 1);   glVertex2f(0, 0.5);
      glEnd;
      CgDC2.PageFlip;end;procedure TPForm.TimerTimer(Sender: TObject);
    begin  a := (a+1) mod 360;
      Paint;end;procedure TPForm.SplitterMoved(Sender: TObject);
    begin  // Resize the viewports. Also called when the form resizes.
      { The splitter is set to rsUpdate, so it repaints whenever you drag it. This
        causes a lot of flicker, so set it to rsPattern if you get a migraine. }
      CgDC1.MakeCurrent;
      glViewport(0, 0, GLPanel1.Width, GLPanel1.Height);
      CgDC2.MakeCurrent;
      glViewport(0, 0, GLPanel2.Width, GLPanel2.Height);end;procedure TPForm.SplitterCanResize(Sender: TObject; var NewSize: Integer;
      var Accept: Boolean);
    begin  // Keep the splitter from snapping to the left edge of the form.
      Accept := not (NewSize <= 31);end;