VC++6.0中使用OpenGL

news/2025/2/23 15:28:31

来源:计算机世界:http://www2.ccw.com.cn/99/9934/9934b16.asp

VC + + 6.0 中
使 用OpenGL

清 华 大 学 李 勇


----要 学 习OpenGL 编 程, 希 望 读 者 具 备 基 本 的 图 形 知 识。 本 文 使 用 基 于Visual C + + 消 息 驱 动 编 程, 对 于 没 学 过 VC 的 读 者 也 有 一 定 的 帮 助。 我 们 的 第 一 个 程 序 将 明 建 立 一 个 视 窗 程 序 显 示OpenGL 图 形 的 最 小 需 求。 为 成 这 一 任 务 我 们 将 分 如 下5 步 来 进 行:

----1 设 置 窗 口 像 素 的 格 式;2 建 立RC;3 使 RC 设 为 当 前;4 创 建 视 口 和 矩 阵 模 型;5 画 一 个 立 方 体 和 一 个 茶 壶。

----现 在 你 可 以 打 开 你 的Visual C + +, 建 立 一 个 单 文 档 的 项 目。 首 先 我 们 在 该 项 目 中 加 进 所 有 必 需 的OpenGL 文 件 和 库, 在 菜 单 中 选 择Build Settings, 然 后 点 击LINK 按 钮( 或 者 按 Ctrl +Tab 键 来 移 动 到 那 儿)。 在Object/Library 栏 中 键 入Opengl32.lib glu32.lib glaux.lib, 并 确 定。 打 开 文 件stdafx.h 插 入 如 下 行:

        #include < gl/gl.h >
        #include < gl/glu.h >
        #include < gl/glaux.h >

----OpenGL 仅 能 在 具 有WS_CLIPCHILDREN 和 WS_CLIPSIBLINGS 类 型 的 窗 口 显 示 图 形, 我 们 需 要 编 辑OnPreCreate 函 数, 指 定 一 下 窗 口 类 型。

BOOL COPView::PreCreateWindow(CREATESTRUCT & cs)
{cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
return CView::PreCreateWindow(cs);
}

----下 面 我 们 要 定 义 窗 口 的 像 素 格 式, 这 一 点 对 建 立RC 很 重 要。 首 先 我 们 需 要 建 立 一 个 受 保 护 的 成 员 函 数 BOOL SetWindowPixelFormat(HDC hDC)。 如 下 所 示:

BOOL COPView::SetWindowPixelFormat(HDC hDC)
{
PIXELFORMATDESCRIPTOR pixelDesc;
pixelDesc.nSize   = sizeof(PIXELFORMATDESCRIP 
 TOR);
pixelDesc.nVersion  = 1;
pixelDesc.dwFlags   = PFD_DRAW_TO_WINDOW | 
PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | 
PFD_SUPPORT_GDI |PFD_STEREO_DONTCARE;
pixelDesc.iPixelType  = PFD_TYPE_RGBA;
pixelDesc.cColorBits = 32; 
pixelDesc.cRedBits = 8;
pixelDesc.cRedShift = 16;
pixelDesc.cGreenBits = 8;
pixelDesc.cGreenShift = 8;
pixelDesc.cBlueBits = 8;
pixelDesc.cBlueShift = 0; 
pixelDesc.cAlphaBits = 0;
pixelDesc.cAlphaShift = 0;
pixelDesc.cAccumBits= 64;   
pixelDesc.cAccumRedBits = 16;
pixelDesc.cAccumGreenBits = 16;
pixelDesc.cAccumBlueBits = 16;
pixelDesc.cAccumAlphaBits= 0;
pixelDesc.cDepthBits = 32; 
pixelDesc.cStencilBits= 8;
pixelDesc.cAuxBuffers = 0; 
pixelDesc.iLayerType= PFD_MAIN_PLANE;
pixelDesc.bReserved = 0; 
pixelDesc.dwLayerMask= 0;
pixelDesc.dwVisibleMask= 0;
pixelDesc.dwDamageMask= 0;
m_GLPixelIndex = ChoosePixelFormat( hDC, &pixelDesc);
if (m_GLPixelIndex==0) // Let's choose a default index.
 {
  m_GLPixelIndex = 1;     
if (DescribePixelFormat(hDC, m_GLPixelIndex, sizeof
(PIXELFORMATDESCRIPTOR), &pixelDesc)==0)
 {
return FALSE;
}
}
if (SetPixelFormat( hDC, m_GLPixelIndex, 
                           &pixelDesc)==FALSE)
  {
  return FALSE;
  }
  return TRUE;
}

----加 入 一 个 成 员 变 量 到 视 类 中:

int m_GLPixelIndex; // protected

----最 后, 在ClassWizard 中 加 入 函 数OnCreate 来 响 应 消 息WM_CREATE, 函 数 如 下:

  int COPView::OnCreate
(LPCREATESTRUCT lpCreateStruct) 
{
  if (CView::OnCreate(lpCreateStruct) == -1)
  return -1;
  HWND hWnd = GetSafeHwnd();
  HDC hDC = ::GetDC(hWnd);
  if (SetWindowPixelFormat(hDC)==FALSE)
    return 0;
  if (CreateViewGLContext(hDC)==FALSE)
                        return 0;
    return 0;
     }

----下 面 需 要 作 的 步 骤 就 是 建 立RC, 并 置 为 当 前RC。

----在 视 类 中 加 入 保 护 函 数 CreateViewGLContext(HDC hDC) 和 变 量HGLRC m_hGLContext:

BOOL COPView::CreateViewGLContext(HDC hDC)
{
m_hGLContext = wglCreateContext(hDC);
  if (m_hGLContext == NULL)
  {
    return FALSE;
   }
  if (wglMakeCurrent(hDC, m_hGLContext)==FALSE)
  {
    return FALSE;
    }
    return TRUE;
}
    加 入 函 数OnDestroy 来 响 应WM_DESTROY:
void COPView::OnDestroy() 
{
      if(wglGetCurrentContext()!=NULL) 
                {
                wglMakeCurrent(NULL, NULL) ;
                }
                if (m_hGLContext!=NULL)
                {
                 wglDeleteContext(m_hGLContext);
                 m_hGLContext = NULL;
                }
      CView::OnDestroy();
}

----最 后, 编 辑 一 下COPView 类 构 造 函 数:

COPView::COPView()
{
                 m_hGLContext = NULL;
                m_GLPixelIndex = 0;
}

----现 在, 我 们 就 可 以 进 行OpenGL 画 图 了, 虽 然 它 看 起 来 仍 然 像 一 个 典 型 的MFC 程 序。

----现 在 我 们 进 行 下 一 步 建 立 视 点 和 矩 阵 模 型, 用ClassWizard 在 视 类 中 加 入 函 数OnSize 响 应WM_SIZE。 如 下 所 示:

void COPView::OnSize(UINT nType, int cx, int cy) 
  {
  CView::OnSize(nType, cx, cy);
  GLsizei width, height; GLdouble aspect;
  width = cx; height = cy;
  if (cy==0)
  aspect = (GLdouble)width;
  else
  aspect = (GLdouble)width/(GLdouble)height;
  glViewport(0, 0, width, height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45, aspect, 1, 10.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  }
 加 入 函 数:void COPView::OnPaint() 
   {
  CPaintDC dc(this); // device context for painting
  COPDoc * pDoc = GetDocument();
  pDoc ->RenderScene();
  }

----在 文 档 类 中 加 入 公 共 函 数RenderScene():

void COPDoc::RenderScene(void)
{ glClear(GL_COLOR_BUFFER_BIT); glFlush(); }

----现 在 程 序 运 行 后 仅 是 黑 黑 的 屏 幕, 我 们 需 要 加 进 些 东 西。

----在 文 档 类 中 加 一 个 枚 举 变 量 GLDisplayListNames:

enum GLDisplayListNames { ArmPart1,ArmPart2 };

----为 将 来 建 立 显 示 列 表 用。 编 辑 函 数 OnNewDocument(), 编 码 如 下:

BOOL COPDoc::OnNewDocument()
if (!CDocument::OnNewDocument())
        return FALSE;
        glNewList(ArmPart1, GL_COMPILE);
GLfloat RedSurface[]   = { 1.0f, 0.0f, 0.0f, 1.0f};
GLfloat GreenSurface[] = { 0.0f, 1.0f, 0.0f, 1.0f};
GLfloat BlueSurface[]  = { 0.0f, 0.0f, 1.0f, 1.0f};
GLfloat LightAmbient[]  = { 0.1f, 0.1f, 0.1f, 0.1f }; 
GLfloat LightDiffuse[]  = { 0.7f, 0.7f, 0.7f, 0.7f }; 
GLfloat LightSpecular[] = { 0.0f, 0.0f, 0.0f, 0.1f };
GLfloat LightPosition[] = { 5.0f, 5.0f, 5.0f, 0.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpecular);
glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
  glEnable(GL_LIGHT0);
  glMaterialfv(GL_FRONT_AND_BACK, 
              GL_AMBIENT, RedSurface);
  glBegin(GL_POLYGON);
  glNormal3d(  1.0,  0.0,  0.0);
  glVertex3d(  1.0,  1.0,  1.0); glVertex3d(  
1.0, -1.0,  1.0);
  glVertex3d(  1.0, -1.0, -1.0); glVertex3d
            (  1.0,  1.0, -1.0); // 画 第 一 个 面
  glEnd();
  glBegin(GL_POLYGON);
  glNormal3d( -1.0,  0.0,  0.0);
  // 此 处 同 上 画 第 二 个 面。 
     立 方 体 的 中 心 为 坐 标 原 点。
  glEnd();
  glMaterialfv(GL_FRONT_AND_BACK, 
              GL_AMBIENT, GreenSurface);
  // 此 处 同 上 画 第 三、 四 个 面, 
     注 意 平 面 法 向 和 坐 标。
  glMaterialfv(GL_FRONT_AND_BACK, 
              GL_AMBIENT, BlueSurface);
  // 此 处 同 上 画 第 五、 六 个 面。
  glEndList();
  glNewList(ArmPart2, GL_COMPILE);
  glMaterialfv(GL_FRONT_AND_BACK, 
              GL_AMBIENT, GreenSurface);
  auxSolidTeapot(1.0);// 用 辅 助 库 函 数 画 茶 壶。
  glEndList();
  return TRUE;
    }

----下 面 就 看 怎 样 显 示 它 了。 编 辑RenderScene 函 数:

void COPDoc::RenderScene(void)
        {
 double m_angle1=60.0;   double m_angle2=30.0;
 glClear
(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 glPushMatrix(); 
 glTranslated(3.0, 0.0, -8.0); glRotated( m_angle1, 0, 0, 1); 
                          glRotated( m_angle2, 0, 1, 0);
 glCallList(ArmPart1);
 glPopMatrix();
 glPushMatrix();
 glTranslated(0.0, 0.0, -8.0);
 glCallList(ArmPart2);
 glPopMatrix();
         glFlush();
}

----执 行 的 结 果 如 下 图 所 示:


http://www.niftyadmin.cn/n/4819750.html

相关文章

实验指令(3)

三层链路聚合&#xff1a; [SWB]interface Route-Aggregation 1 [SWB-Bridge-Aggregation1]exit [SWB]interface range G 1/0/21 to G 1/0/23 [SWB-if-range]port link-mode route [SWB-if-range]port link-aggregation group 1 [SWB-if-range]exit [SWB]interface route-Aggre…

vue tslint报错: Calls to 'console.log' are not allowed

使用Vue CLI 3 的 vue create 创建vuets 项目&#xff0c;使用默认配置&#xff0c; 控制台报警告Calls to console.log are not allowed&#xff0c;解决&#xff1a; 在tslint.json中的rules下 添加&#xff1a; "no-console": false。无需向在tsling.config中添加…

强制和别人QQ聊天代码

http://wpa.qq.com/msgrd?V1&Uin10001&Siteioshenmue&Menuyes http://wpa.qq.com/msgrd?V1&Uin*****&Siteioshenmue&Menuyes 收集自网络,请把*****处替换为你想要聊天的QQ号码,就像最上面的那个要和腾讯老总说话的10001一样.

如何编程动态改变IE的代理服务器设置, 并且使之马上生效!

如何编程动态改变IE的代理服务器设置, 并且使之马上生效! 选择自 sxxny 的 Blog 关键字 IE 代理服务器出处 最近有很多朋友都在讨论如何改变IE的代理服务器设置, 刚好我最近做的一个东西里面用到了这样的功能. 拿出来和大家共享一下. 用到的关键函数是wininet库里面的…

正则表达式学与练

这两天,开始学习正则表达式,并且开始练习了. 首先,我没有下载正则表达式测试器的程序,因为我使用的是一个网页测试器,它的代码来自于: 正则表达式练习器 http://www.codefans.com/ArticleView/Article_5600.html 打开上面的页面&#xff0c;把Html代码复制下来&#xff0c;保…

PHP on Windows Azure 入门教学系列(3) ——在Windows Azure中部署Wordpress

公告&#xff1a;本博客为微软云计算中文博客的镜像博客。部分文章因为博客兼容性问题&#xff0c;会影响阅读体验。如遇此情况&#xff0c;请访问原博客。 本文是PHP on Windows Azure 入门教学系列第三篇文章。请上一篇文章中&#xff0c;我们已经成功的在Windows Azure中运行…

C语言左值和右值,以及操作符属性总结

《C和指针》这本书上讲到左值和右值&#xff0c;概念有点含糊 据我自己的理解&#xff1a; 左值&#xff1a;标识的应该是个存储位置&#xff0c;内存中的位置&#xff0c;左值可以是个变量名&#xff0c;或者是个表达式&#xff0c;但表达式必须表示的是个内存位置 右值&#…

流失的日子

2005年1月13日 妈妈今天早上因癌症去世了。。。八百里奔丧回家&#xff0c;泪满矜。。。 2004年10月3日 我唯一记念在心的只是你爱的被背叛,爱情已经不存在了.放不下的只是感觉,背后很累.而所有的一切都已成为现实. 生在这个世界上,总是被他人强迫,去遵守所谓的准则. 总有人…