【转】《基于MFC的OpenGL编程》Part 2 Setting up OpenGL on Windows(2)

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

int CCY457OpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    
if (CView::OnCreate(lpCreateStruct) == -1
)
        
return -1
;
    
//Initialize OpenGL Here

     InitializeOpenGL();
    
return 0
;
}

BOOL CCY457OpenGLView::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;
}
//Setup Pixel Format

/////////////////////////////////////////////////////////////////////////////
BOOL CCY457OpenGLView::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;
}

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

void CCY457OpenGLView::OnSize(UINT nType, int cx, int cy)
{
     CView::OnSize(nType, cx, cy);
     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);
    
    
// switch back to the modelview matrix and clear it

     ::glMatrixMode(GL_MODELVIEW);
     ::glLoadIdentity();
}

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

void CCY457OpenGLView::OnDraw(CDC* pDC)
{
     CCY457OpenGLDoc
* pDoc =
GetDocument();
     ASSERT_VALID(pDoc);
    
// Clear out the color & depth buffers

     ::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
     RenderScene();
    
// Tell OpenGL to flush its pipeline

     ::glFlush();
    
// Now Swap the buffers

     ::SwapBuffers( m_pDC->GetSafeHdc() );
}
void
CCY457OpenGLView::RenderScene ()
{
//第一个玩具嘛,先空着,后面慢慢填

}

8,试试改变窗口的大小,你会看到很严重的闪烁,并且关闭程序后会报告内存泄露,因此我们这就来解决这两个问题吧。

发生闪烁的原因是Windows先绘制背景,然后再是OpenGL绘制,因为我们已经让OpenGL负责清空背景色,因此我们不需要Windows去清空背景了

BOOL CCY457OpenGLView::OnEraseBkgnd(CDC* pDC)
{
    
//Tell Windows not to erase the background

    return TRUE;
}

      内存泄露的原因是我们在SetupPixelFormat()使用了new运算符来为CClientDC对象分配内存,因此需要显式delete掉。

void CCY457OpenGLView::OnDestroy()
{
     CView::OnDestroy();
    
//Make the RC non-current

    if(::wglMakeCurrent (NULL, NULL) == FALSE)
     {
         MessageBox(
"Could not make RC non-current"
);
     }
    
    
//Delete the rendering context

    if(::wglDeleteContext (m_hRC)==FALSE)
     {
         MessageBox(
"Could not delete RC"
);
     }
    
//Delete the DC

    if(m_pDC)
     {
         delete m_pDC;
     }
    
//Set it to NULL

     m_pDC = NULL;
}

原文地址:https://www.cnblogs.com/lcxu2/p/2004066.html