Opengl的初始化

来源:互联网 发布:期货平台软件开发 编辑:程序博客网 时间:2024/05/08 04:37

MFC中需要添加的基本函数

1) Init()

完成对Opengl的初始化,如视图模式,变换模式等的设置。这些初始设置是通过

glMatrixMode(), glLoadIdentity(), gluPerspective(), glMatrixMode()等函数来实现的。特别需要注意的是,在初始化阶段,必须调用Windows专用Opengl库函数来建立windows视图与Opengl窗口的联系。这些函数一wgl为前最。即wglCreateContext, wglMakeCurrent()

2)CreateRGBPallette(void)

用于设置绘图调色板

3bSetupPixelFormat()

为制定的设备内容设置像素格式,关键调用函数SetPixelFormat()

4)ComponentFromIndex()

该函数用于从颜色索引获取该索引对应的RGB颜色分两

5)DrawScene()

图形应用程序住模块。

Init()OnCreate()调用,DrawScene()OnDraw()调用。

一、stdafx.h的修改及连接库的修改

//加入OpenGl所需的头文件,并通过Project/Setting/Link/object/LibraryModules

//中添加glaux.lib opengl32.lib glu32.lib

#include<GL/gl.h>

#include<GL/glu.h>

#include<GL/glaux.h>

二、窗体大小的改变

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

      if( !CFrameWnd::PreCreateWindow(cs) )

           return FALSE;

      // TODO: Modify the Window class or styles here by modifying

      // the CREATESTRUCT cs

      //自定义窗口的大小

      cs.cx=500;

      cs.cy=500;

      return TRUE;

}

三、MyOpenGlView.h中添加相应的成员变量和成员函数

class CMyOpenGlView : public CView

{

……

public:

      //自定义相关成员变量

      CClientDC      *m_pDC;

      CRect m_oldRect;

      int m_CurrentTool;

……

public:

      //自定义相关函数

      void DrawScene();

      BOOL bSetupPixelFormat();

      void Init();

……

}

To be continued................

 

 

1:新建一个MFC的工程,单文档的工程。


2
:工程建好之后,可以先编译运行一下。下面就是要把View的窗口初始化为OpenGL的编程环境。当然以下所有的操作都是在View类中进行的。
先在Project->Settings->Link中,加上opengl32.lib glu32.lib glut.lib glaux.lib,然后在View.h的类定义中加上如下引用。这个大家都知道。

#include <gl/gl.h>

#include <gl/glu.h>   

#include <gl/glaux.h>

3:在PreCreateWindow(CREATESTRUCT& cs)这个函数中可以修改一下窗口的风格,比如说窗口的名称背景什么的,当然也可以不修改,如果想修改的话,需要对WNDCLASSEXCREATESTRUCT这两个结构比较熟悉。在这里,我不进行修改。采用默认的风格。


4
:下面开始正题,首先要让窗口支持OpenGL,那就必须要对PIXELFORMATDESCRIPTOR这个结构有所了解,先在View类中新建一个函数SetupPixFormat(CDC *pDC),公有私有无所谓,如下:
BOOL CTestGLInitialView::SetupPixFormat(CDC *pDC) //
我建立的工程名叫TestGLInitial
{
static PIXELFORMATDESCRIPTOR pfd = //
定义像素格式

{
   sizeof(PIXELFORMATDESCRIPTOR), //
上述格式描述符的大小
   1,         //
版本号
   PFD_DRAW_TO_WINDOW |    //
格式支持窗口
   PFD_SUPPORT_OPENGL |    //
格式必须支持OpenGL
   PFD_DOUBLEBUFFER,     //
必须支持双缓冲

   PFD_TYPE_RGBA,      //
申请 RGBA 格式
   24,         // 24
位色彩深度,即1.67千万的真彩色
   0, 0, 0, 0, 0, 0,     //
忽略的色彩位
   0,         //
Alpha缓存
   0,         //
忽略Shift Bit
   0,         //
无累加缓存

   0, 0, 0, 0,       //
忽略聚集位
   32,         // 32
Z-缓存 (深度缓存)
   0,         //
无蒙板缓存

   0,         //
无辅助缓存
   PFD_MAIN_PLANE,      //
主绘图层
   0,         // Reserved
   0, 0, 0        //
忽略层遮罩
};

int nIndex = ChoosePixelFormat(pDC->GetSafeHdc(), &pfd); //选择刚刚定义的像素格式
if( nIndex == 0 ) return FALSE;

return SetPixelFormat(pDC->GetSafeHdc(), nIndex, &pfd);   //
设置像素格式
}
这个函数的主要目的就是设置窗口的像素格式,使之支持OpenGL,明白这点就行了。在创建窗口的时候,调用这个函数。


5
:刚刚那个函数是用来在创建窗口是调用的,在创建窗口时,还需要对OpenGL的环境做一些初始化,再定义一个函数InitialGL(),公有私有也无所谓,反正是自己调用的,如下:
BOOL CTestGLInitialView::InitialGL()
{
glShadeModel(GL_SMOOTH);           //
启用阴影平滑
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);       //
黑色背景
glClearDepth(1.0f);                            //
设置深度缓存
glEnable(GL_DEPTH_TEST);             //
启用深度测试
glDepthFunc(GL_LEQUAL);              //
所作深度测试的类型
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    //
告诉系统对透视进行修正
return TRUE;                                      //
初始化 OK
}
这里的代码我都是抄的NeHe教程上面的代码。


6
:现在可以捕获WM_CREATE消息了。 但是,还要先定义一个CClientDC*的成员,这个成员指向View窗口自己,是用来传递给SetupPixFormat(CDC *pDC)函数的,没别的意思。
现在,来捕获WM_CREATE消息,写上如下代码:
int CTestGLInitialView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
   return -1;

// TODO: Add your specialized creation code here
m_pDC = new CClientDC(this);
SetupPixFormat(m_pDC);

HGLRC hrc = wglCreateContext(m_pDC->GetSafeHdc());
wglMakeCurrent(m_pDC->GetSafeHdc(), hrc);

InitialGL();
return 0;
}
当然,当窗口关闭的时候,还应该要释放一些资源。捕获WM_DESTROY消息,写下如下代码:
void CTestGLInitialView::OnDestroy()
{
CView::OnDestroy();

// TODO: Add your message handler code here
HGLRC hrc = wglGetCurrentContext();
wglMakeCurrent(NULL, 0);
wglDeleteContext(hrc);
delete m_pDC;
}
现在可以编译一下了,没有错误。


7
:现在,OpenGL的环境已经初始化差不多了。可以开始做图了,先定义一个作图的函数DrawScene(),写上如下的代码:
BOOL CTestGLInitialView::DrawScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    //
清除屏幕和深度缓存
glLoadIdentity();            //
重置当前的模型观察矩阵
SwapBuffers(m_pDC->GetSafeHdc());        //
交换缓冲区
return TRUE;
}
然后,要在OnDraw中,调用这个函数:
void CTestGLInitialView::OnDraw(CDC* pDC)
{
CTestGLInitialDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
DrawScene();
}


8
:运行一下,黑色的背景出来了。


9
:这时,可以修改DrawScene()这个作图函数,作图。画出NeHe3课的那个三角形和正方形来。写代码如下:
BOOL CTestGLInitialView::DrawScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    //
清除屏幕和深度缓存
glLoadIdentity();            //
重置当前的模型观察矩阵

glTranslatef(-1.5f,0.0f,-6.0f);       // 左移 1.5 单位,并移入屏幕 6.0
glBegin(GL_TRIANGLES);         //
绘制三角形

glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);       //
上顶点
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);       //
左下
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 0.0f);       //
右下
glEnd();            //
三角形绘制结束

glTranslatef(3.0f,0.0f,0.0f);       //
右移3单位
glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_QUADS);          //
绘制正方形
glVertex3f(-1.0f, 1.0f, 0.0f);       //
左上
glVertex3f( 1.0f, 1.0f, 0.0f);       //
右上
glVertex3f( 1.0f,-1.0f, 0.0f);       //
左下
glVertex3f(-1.0f,-1.0f, 0.0f);       //
右下
   glEnd();

SwapBuffers(m_pDC->GetSafeHdc());        //
交换缓冲区
return TRUE;
}
   
运行一下,发现图形没有出现,这个怎么回事呢。原来是因为还没有定义投影方式和视口。即用正交投影还是透视投影。定义投影,还要捕获WM_SIZE消息。写如下代码:
void CTestGLInitialView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);

// TODO: Add your message handler code here
if (0 == cy)         //
防止被零除
{
   cy = 1;          //
Height设为1
}

glViewport(0, 0, cx, cy);      //
重置当前的视口

glMatrixMode(GL_PROJECTION);     //
选择投影矩阵
glLoadIdentity();        //
重置投影矩阵

//
设置视口的大小
gluPerspective(45.0f,(GLfloat)cx/(GLfloat)cy,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);      //
选择模型观察矩阵
   glLoadIdentity();        //
重置模型观察矩阵
}
   
再运行一下,图形已经出来了。以后,就可以在DrawScene()写任何画图的代码了,当窗口重绘的时候,都可以自动适应。如果要做一段可以运动的3D图画,可以再捕获WM_TIMER消息,通过在OnCreate的时候定义一个时钟,再配合一些变量,就可以做简单的动画了。

原创粉丝点击