1.值得记住的约定
一般情况下,VC++下进行OpenGL应用程序开发步骤如下:
1.通过PIXELFORMATDESCRIPTOR结构设置备注描述表DC的像素格式属性。
2.创建渲染描述表RC,并与设备描述表DC建立联系。
3.使用OpenGL作图
4.释放所占用的资源,包括解除DC和RC的联系、删除RC及其关联的DC。
在这里,应该先为应用程序添加所需的变量和函数,对相关变量进行初始化,然后在相应函数中实现DC像素格式设置、RC的创建及其和DC的关联、图形绘制以及资源释放等功能。
2.一个典型实例
2.1 添加成员变量和成员函数
CClientDC* pDrawDC; // 用于指向当前DC的指针
BOOL PixelformatSetting(void); // 用于设置像素格式
void GLSetting(void); // 用于创建渲染描述表RC 并关联RC/DC
void DrawGraphics(void); //OpenGL作图
2.2 添加消息响应函数
WM_CREATE --- OnCreate(); //该消息响应函数在建立一个窗体前被调用。
WM_DESTROY --- OnDestroy(); //窗口撤销时响应此函数,因此在该函数中释放所有被占用的资源。
WM_SIZE --- OnSize(); //改变窗口大小时响应此函数,可以调整视场。
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
afx_msg void OnSize(UINT nType, int cx, int cy);
2.3 成员函数和消息响应函数添加代码
设置像素格式
BOOL CtestGLView::PixelformatSetting(void)
{
static PIXELFORMATDESCRIPTOR pdf =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW|
PFD_SUPPORT_OPENGL|
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24,
0,0,0,0,0,0,0,0,0,0,0,0,
32,
0,0,
PFD_MAIN_PLANE,
0,0,0,0
}; //填充PIXELFORMATDISCRIPTOR
int ipixelformat;
//获得最佳匹配的像素格式索引
if((ipixelformat = ChoosePixelFormat(pDrawDC->GetSafeHdc(), &pdf))==0)
{
MessageBox(_T("Choose pixel format failed!"));
return FALSE;
}
//把DC的像素格式设置成由索引值ipixelformat指向的像素格式
if(SetPixelFormat(pDrawDC->GetSafeHdc(),ipixelformat, &pdf) == FALSE)
{
MessageBox(_T("Set pixel format failed"));
return FALSE;
}
return TRUE;
}
创建渲染描述表,调用PixelFormatSetting()设置像素格式,创建和DC关联的RC
void CtestGLView::GLSetting(void)
{
HGLRC hRC; //渲染描述表句柄
pDrawDC = new CClientDC (this); //使用pDrawDC指向当前DC
ASSERT(pDrawDC != NULL);
if( !PixelformatSetting()) //设置像素格式
return;
//创建和当前DC兼容的RC,并和当前DC关联
hRC = wglCreateContext(pDrawDC->GetSafeHdc());
wglMakeCurrent(pDrawDC->GetSafeHdc(),hRC);
}
在消息响应函数OnCreate()中调用函数GLSetting(),使得GL环境生效
int CtestGLView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
GLSetting();
return 0;
}
绘制几何拓扑
void CtestGLView::DrawGraphics(void)
{
//移动物体到显示区
glTranslatef(0.0,0.0,-6.0); //相当于在调整照相机 避免像太大
glRotated(RotateAngle,1,1,1);
//以边线的方式绘制三角形
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
//绘制三角形,顺序给出3个三角形的顶点
glBegin(GL_TRIANGLES);
glVertex3f(-0.6,0,0);
glVertex3f(0.6,0,0);
glVertex3f(0.0,0.15,0.6);
glVertex3f(-0.6,0,0);
glVertex3f(0,0.15,0.6);
glVertex3f(0,0.9,0.6);
glVertex3f(0,0.9,0.6);
glVertex3f(0,0.15,0.6);
glVertex3f(0.6,0,0);
glEnd();
}
OnDraw函数中,图像显示
void CtestGLView::OnDraw(CDC* /*pDC*/)
{
CtestGLDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
static BOOL bBusy = FALSE; //定义开关变量
if(bBusy) //开关 绘制完成后才可以更新缓存
{
return;
}
bBusy = TRUE;
glClearColor(0,0,0.5,0.5);//设置背景颜色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除深度缓存和颜色缓存
glMatrixMode(GL_MODELVIEW); //启动模型视图矩阵
glLoadIdentity();
DrawGraphics();
SwapBuffers(wglGetCurrentDC()); //更新缓存
bBusy = FALSE;
}
删除渲染描述表RC及其绑定的设备描述表DC
void CtestGLView::OnDestroy()
{
CView::OnDestroy();
//删除渲染描述表及其绑定的设备描述表
HGLRC hRC; //OpenGL的渲染描述表
hRC = ::wglGetCurrentContext();
::wglMakeCurrent(NULL,NULL); //解除当前RC和DC的关联,并把当前RC非当前化
if(hRC)
{
::wglDeleteContext(hRC);
}
if(pDrawDC)
{
delete pDrawDC;
}
}
2.4 添加人机交互(旋转功能)
采用鼠标左键控制开关,定时旋转方案。
WM_BUTTONDOWN --- OnLButtonDown();
WM_TIMER --- OnTimer();
添加变量:
BOOL bRotate;
float RotateAngle;
void CtestGLView::OnLButtonDown(UINT nFlags, CPoint point)
{
if (bRotate)
{
SetTimer(1,100,NULL);
}
else
{
KillTimer(1);
}
bRotate = !bRotate;
CView::OnLButtonDown(nFlags, point);
}
void CtestGLView::OnTimer(UINT_PTR nIDEvent)
{
//定时器计时达到预定时刻 则旋转角度增加10
if( nIDEvent == 1)
{
RotateAngle += 10;
Invalidate(FALSE); //重新绘制
}
CView::OnTimer(nIDEvent);
}
3.输出结果
转载请注明原文地址: https://ju.6miu.com/read-670643.html