• MFC下OpenGL绘图框架


     

    MFCOpenGL入门

    源文件

    1, 建一工程文件,我这里命名为first,现在first工程里面我们没有添加任何东西,所有的东西都是MFC自动帮我们创建的。

    2, 添加链接库。这一步很关键。打开菜单栏下的项目->属性->配置属性->链接器->输入->附加依赖项里加入OpenGL32.lib GLu32.lib GLaux.lib,如图

     

    3, 加头文件,在stdafx里面添加opengl的头文件。如下代码所示:

     

    代码
     //-----------------------Tramp---添加OpenGL库头文件----------------------------->

    #include 
    "stdio.h"

    #include 
    "math.h"

    #include 
    "gl\gl.h"

    #include 
    "gl\glu.h"

    #include 
    "gl\glaux.h"

    //---------------------------------------------------------------------------<

     

    4, CCY457OpenGLView类的属性栏,为下述消息加入消息处理函数:WM_CREATE (for OnCreate), WM_DESTROY (for OnDestroy), WM_SIZE (for OnSize), WM_ERASEBACKGROUND (for OnEraseBkground).如下图:

       

    5, 设置窗口显示风格。窗口创建之前我们必须设置窗口风格包含WS_CLIPCHILDREN WS_CLIPSIBLINGS,从而避免OpenGL绘制到其他窗口中去。这些应该放在PreCreateWindow()中。

     

    代码
    BOOL CfirstView::PreCreateWindow(CREATESTRUCT& cs)

    {

     
    // TODO: 在此处通过修改

     
    // CREATESTRUCT cs 来修改窗口类或样式

     cs.style 
    |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;//Tramp

     
    return CView::PreCreateWindow(cs);

    }

     

    6, CfirstView.h中加入如下语句:

        /************************************************************************/

        /* 设置的变量是Rendering Context(着色描述表)。每一个OpenGL都被连接到一个着

        色描述表上。着色描述表将所有的OpenGL调用命令连接到Device Context(设备描述表)上。

        我将OpenGL的着色描述表定义为hRC 。要让您的程序能够绘制窗口的话,还需要创建一个

        设备描述表,也就是第二行的内容。Windows的设备描述表被定义为hDC 。DC将窗口连接到

        GDI(Graphics Device Interface图形设备接口)。而RC将OpenGL连接到DC                                                                     */

        /************************************************************************/

        HGLRC m_hRC;    //Rendering Context着色描述表

        CDC* m_pDC;        //Device Context设备描述表

        BOOL InitializeOpenGL();    //Initialize OpenGL

        BOOL SetupPixelFormat();    //Set up the Pixel Format

        void RenderScene();            //Render the Scene

    7, OnCreate中我们将通过建立像素格式和绘制上下文来初始化OpenGL. InitializeOpenGL()中会创建一个设备上下文(DC),为这个DC选择一个像素格式,创建和这个DC相关的绘制上下文(RC,然后选择这个RC.这个函数会调用SetupPixelFormat()来建立像素格式。

    int Clesson1View::OnCreate(LPCREATESTRUCT lpCreateStruct)

    {

     if (CView::OnCreate(lpCreateStruct) == -1)

          return -1;

     

     // TODO: 在此添加您专用的创建代码

     InitializeOpenGL();//初始化openGL绘图

     

     return 0;

    }

         //初始化opengl绘制

    BOOL CfirstView::InitializeOpenGL()

    {

        //Get a DC for the Client Area

        m_pDC = new CClientDC(this);

        //Failure to Get DC

        if(m_pDC == NULL)

        {

            //::MessageBox("Error Obtaining DC");

            return FALSE;

        }

        //Failure to set the pixel format

        if(!SetupPixelFormat())

        {

            return FALSE;

        }

     //Create Rendering Context

     m_hRC = ::wglCreateContext (m_pDC->GetSafeHdc ());

     //Failure to Create Rendering Context

     if(m_hRC == 0)

     {

          // MessageBox("Error Creating RC");

          return FALSE;

     }

     //Make the RC Current

     if(::wglMakeCurrent (m_pDC->GetSafeHdc (), m_hRC)==FALSE)

     {

          // MessageBox("Error making RC Current");

          return FALSE;

     }

     //Specify Black as the clear color

     ::glClearColor(0.0f,0.0f,0.0f,0.0f);

     //Specify the back of the buffer as clear depth

     ::glClearDepth(1.0f);

     //Enable Depth Testing

     ::glEnable(GL_DEPTH_TEST);

     return TRUE;

     

    }

    //设置像素格式

    BOOL CfirstView::SetupPixelFormat()

    {

     static PIXELFORMATDESCRIPTOR pfd =

     {

          sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd

          1,                              // version number

          PFD_DRAW_TO_WINDOW |            // support window

          PFD_SUPPORT_OPENGL |            // support OpenGL

          PFD_DOUBLEBUFFER,                // double buffered

          PFD_TYPE_RGBA,                  // RGBA type

          24,                             // 24-bit color depth

          0, 0, 0, 0, 0, 0,               // color bits ignored

          0,                              // no alpha buffer

          0,                              // shift bit ignored

          0,                              // no accumulation buffer

          0, 0, 0, 0,                     // accum bits ignored

          16,                             // 16-bit z-buffer

          0,                              // no stencil buffer

          0,                              // no auxiliary buffer

          PFD_MAIN_PLANE,                 // main layer

          0,                              // reserved

          0, 0, 0                         // layer masks ignored

     };

     int m_nPixelFormat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);

     if ( m_nPixelFormat == 0 )

     {

          return FALSE;

     }

     if ( ::SetPixelFormat(m_pDC->GetSafeHdc(), m_nPixelFormat, &pfd) == FALSE)

     {

          return FALSE;

     }

     return TRUE;

    }

    8, OnSize()中一般用来设置视口和视锥,因为这些是和窗口大小相关的。基本操作包括设置视口,选择投影矩阵,设置模型视图矩阵。

    void CfirstView::OnSize(UINT nType, int cx, int cy)

    {

     CView::OnSize(nType, cx, cy);

     

     // TODO: 在此处添加消息处理程序代码

     GLdouble aspect_ratio; // width/height ratio

     

     if ( 0 >= cx || 0 >= cy )

     {

          return;

     }

     // select the full client area

     ::glViewport(0, 0, cx, cy);

     // compute the aspect ratio

     // this will keep all dimension scales equal

     aspect_ratio = (GLdouble)cx/(GLdouble)cy;

     // select the projection matrix and clear it

     ::glMatrixMode(GL_PROJECTION);

     ::glLoadIdentity();

     // select the viewing volume

     ::gluPerspective(45.0f, aspect_ratio, .01f, 200.0f);//画三维

     //::gluOrtho2D(-10.0f, 10.0f, -10.0f, 10.0f);    //二维

     

     

     // switch back to the modelview matrix and clear it

     ::glMatrixMode(GL_MODELVIEW);

     ::glLoadIdentity();

    }

     

    9, 在绘制场景时,一般包括如下步骤:1)清空缓存。2)绘制场景。3Flush掉渲染流水线。4)若设置了双缓冲,则交换前后台缓冲区。

    void CfirstView::OnDraw(CDC* /*pDC*/)

    {

     CfirstDoc* pDoc = GetDocument();

     ASSERT_VALID(pDoc);

     if (!pDoc)

          return;

     

     // TODO: 在此处为本机数据添加绘制代码

     // Clear out the color & depth buffers

     ::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

     RenderScene();//绘图都放在这

     // Tell OpenGL to flush its pipeline

     ::glFinish();

     // Now Swap the buffers

     ::SwapBuffers( m_pDC->GetSafeHdc() );

    }

    10,              为了使改变窗口大小时严重的闪烁,在OnEraseBkgnd里做一些操作,避免windows自己的窗口刷新闪烁。

    BOOL CfirstView::OnEraseBkgnd(CDC* pDC)

    {

    // TODO: 在此添加消息处理程序代码和/或调用默认值

     

    return TRUE;

    }

    11,              为了避免内存泄露,我们要将在SetupPixelFormat()中使用了new运算符来为CClientDC对象分配的内存在程序关闭时delete掉。

     void CfirstView::OnDestroy()

    {

        CView::OnDestroy();

     

        // TODO: 在此处添加消息处理程序代码

        //Make the RC non-current

        if(::wglMakeCurrent (0,0) == FALSE)

        {

            MessageBox(_T("Could not make RC non-current"));

        }

     

        //Delete the rendering context

        if(::wglDeleteContext (m_hRC)==FALSE)

        {

            MessageBox(_T("Could not delete RC"));

        }

        //Delete the DC

        if(m_pDC)

        {

            delete m_pDC;

        }

        //Set it to NULL

        m_pDC = NULL;

    }

    12,      下面写主绘图函数,RenderScene(),在窗口画了一个正方体、一个四面体。

     void CfirstView::RenderScene()

    {

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer

        glLoadIdentity();                                   // Reset The Current Modelview Matrix

        glTranslatef(-1.5f,0.0f,-6.0f);                     // Move Left 1.5 Units And Into The Screen 6.0

        glRotatef(30,0.0f,1.0f,0.0f);                       // Rotate The Triangle On The Y axis ( NEW )

        glBegin(GL_TRIANGLES);                              // Start Drawing A Triangle

        glColor3f(1.0f,0.0f,0.0f);                      // Red

        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Front)

        glColor3f(0.0f,1.0f,0.0f);                      // Green

        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Front)

        glColor3f(0.0f,0.0f,1.0f);                      // Blue

        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Front)

        glColor3f(1.0f,0.0f,0.0f);                      // Red

        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Right)

        glColor3f(0.0f,0.0f,1.0f);                      // Blue

        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Right)

        glColor3f(0.0f,1.0f,0.0f);                      // Green

        glVertex3f( 1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Right)

        glColor3f(1.0f,0.0f,0.0f);                      // Red

        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Back)

        glColor3f(0.0f,1.0f,0.0f);                      // Green

        glVertex3f( 1.0f,-1.0f, -1.0f);                 // Left Of Triangle (Back)

        glColor3f(0.0f,0.0f,1.0f);                      // Blue

        glVertex3f(-1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Back)

        glColor3f(1.0f,0.0f,0.0f);                      // Red

        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Left)

        glColor3f(0.0f,0.0f,1.0f);                      // Blue

        glVertex3f(-1.0f,-1.0f,-1.0f);                  // Left Of Triangle (Left)

        glColor3f(0.0f,1.0f,0.0f);                      // Green

        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Left)

        glEnd();                                            // Done Drawing The Pyramid

     

        glLoadIdentity();                                   // Reset The Current Modelview Matrix

        glTranslatef(1.5f,0.0f,-7.0f);                      // Move Right 1.5 Units And Into The Screen 7.0

        glRotatef(25,1.0f,1.0f,1.0f);                   // Rotate The Quad On The X axis ( NEW )

        glBegin(GL_QUADS);                                  // Draw A Quad

        glColor3f(0.0f,1.0f,0.0f);                      // Set The Color To Green

        glVertex3f( 1.0f, 1.0f,-1.0f);                  // Top Right Of The Quad (Top)

        glVertex3f(-1.0f, 1.0f,-1.0f);                  // Top Left Of The Quad (Top)

        glVertex3f(-1.0f, 1.0f, 1.0f);                  // Bottom Left Of The Quad (Top)

        glVertex3f( 1.0f, 1.0f, 1.0f);                  // Bottom Right Of The Quad (Top)

        glColor3f(1.0f,0.5f,0.0f);                      // Set The Color To Orange

        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Top Right Of The Quad (Bottom)

        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Top Left Of The Quad (Bottom)

        glVertex3f(-1.0f,-1.0f,-1.0f);                  // Bottom Left Of The Quad (Bottom)

        glVertex3f( 1.0f,-1.0f,-1.0f);                  // Bottom Right Of The Quad (Bottom)

        glColor3f(1.0f,0.0f,0.0f);                      // Set The Color To Red

        glVertex3f( 1.0f, 1.0f, 1.0f);                  // Top Right Of The Quad (Front)

        glVertex3f(-1.0f, 1.0f, 1.0f);                  // Top Left Of The Quad (Front)

        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Bottom Left Of The Quad (Front)

        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Bottom Right Of The Quad (Front)

        glColor3f(1.0f,1.0f,0.0f);                      // Set The Color To Yellow

        glVertex3f( 1.0f,-1.0f,-1.0f);                  // Top Right Of The Quad (Back)

        glVertex3f(-1.0f,-1.0f,-1.0f);                  // Top Left Of The Quad (Back)

        glVertex3f(-1.0f, 1.0f,-1.0f);                  // Bottom Left Of The Quad (Back)

        glVertex3f( 1.0f, 1.0f,-1.0f);                  // Bottom Right Of The Quad (Back)

        glColor3f(0.0f,0.0f,1.0f);                      // Set The Color To Blue

        glVertex3f(-1.0f, 1.0f, 1.0f);                  // Top Right Of The Quad (Left)

        glVertex3f(-1.0f, 1.0f,-1.0f);                  // Top Left Of The Quad (Left)

        glVertex3f(-1.0f,-1.0f,-1.0f);                  // Bottom Left Of The Quad (Left)

        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Bottom Right Of The Quad (Left)

        glColor3f(1.0f,0.0f,1.0f);                      // Set The Color To Violet

        glVertex3f( 1.0f, 1.0f,-1.0f);                  // Top Right Of The Quad (Right)

        glVertex3f( 1.0f, 1.0f, 1.0f);                  // Top Left Of The Quad (Right)

        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Bottom Left Of The Quad (Right)

        glVertex3f( 1.0f,-1.0f,-1.0f);                  // Bottom Right Of The Quad (Right)

        glEnd();                                            // Done Drawing The Quad

    }

      

     

    附,坐标交互操作的实现:

        //控制旋转和位置的变量

        GLfloat m_xAngle;//

        GLfloat m_yAngle;

        GLfloat m_xPos;

        GLfloat m_yPos;

        CPoint m_MouseDownPoint;

    旋转的关键操作:

            m_xAngle+=(point.y-m_MouseDownPoint.y)/3.6;

            m_yAngle+=(point.x-m_MouseDownPoint.x)/3.6;

            //Set the mouse point

            m_MouseDownPoint=point;

            InvalidateRect(NULL,FALSE); 

    绘图:

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer

        glLoadIdentity();

        glTranslatef(m_xPos, m_yPos, -5.0f);

        glRotatef(m_xAngle, 1.0f,0.0f,0.0f);

        glRotatef(m_yAngle, 0.0f,1.0f,0.0f);

    绘图操作......

  • 相关阅读:
    iOS开发——高级篇——iOS抽屉效果实现原理
    iOS开发——高级篇——FMDB 数据库简单使用
    iOS开发——高级篇——多线程dispatch_apply
    iOS开发——基础篇——get和post请求的区别
    iOS开发——高级篇——线程同步、线程依赖、线程组
    谈谈程序员最讨厌做的事
    iOS开发——高级篇——iOS 项目的目录结构
    iOS开发——高级篇——Runtime实际应用
    程序猿如何“智斗”产品经理
    iOS开发——基础篇——iOS开发 Xcode8中遇到的问题及改动
  • 原文地址:https://www.cnblogs.com/yanhuiw/p/1794462.html
Copyright © 2020-2023  润新知