以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 C/C++编程思想 』  (http://bbs.xml.org.cn/list.asp?boardid=61)
----  OpenGL学习  (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=87760)


--  作者:葛靖青001
--  发布时间:11/16/2010 11:57:00 AM

--  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();
    }
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
62.500ms