名词介绍
设备上下文
Windows图形设备接口(GDI)能够绘制到屏幕、内存、打印机或任何提供一个接口层,可以处理GDI调用其他设备。GDI通过渲染处理当前选择的设备,这就是所谓的设备上下文,或DC。
绘制上下文
渲染上下文是GDI的OpenGL的等效直流。所有的OpenGL调用渲染到装置通过一个RC。OpenGL渲染环境保持状态变量,如当前背景色,当前颜色等直流保持GDI状态变量如当前笔,当前刷等。
像素格式
像素格式调用OpenGL和渲染操作,Windows执行之间的转换层 举个例子,若像素格式只支持很少一部分颜色值,则OpenGL在用RGB值(128,120,135)绘制一个像素时,就可能使用转换后的值(128,128,128)来绘制.
第一个基于MFC的OpenGL应用程序
环境:VC6.0
首先下载需要的GLUT头文件,DLL和Lib文件, 下载链接: glutdlls37beta.zip ,解压缩后把gltu.h放到”VC98/Include/GL”下,把glut.lib和glut32.lib放到”VC9/Lib” 下,glut32.dll和glut.dll放到你创建的应用程序的运行目录下创建一个当文档应用程序 在项目的工具–>设置–>连接中配置好库文件 在stdafx.h中加入下列语句,这几个是OpenGL函数调用需要使用的,添加在这个头文件中是因为其他的几个头文件中已经引入了这个头文件
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <gl/glaux.h>
需要为项目添加消息处理函数 1.右键view类添加消息函数 WM_CREATE (for OnCreate), WM_DESTROY (for OnDestroy), WM_SIZE (for OnSize), WM_ERASEBACKGROUND (for OnEraseBkground) 在窗口创建之前我们必须设置窗口风格包含 WS_CLIPCHILDREN和 WS_CLIPSIBLINGS 从而避免OpenGL绘制到其他窗口中去。
BOOL CDemoView
::PreCreateWindow(CREATESTRUCT
& cs)
{
cs
.style
|= WS_CLIPSIBLINGS
| WS_CLIPCHILDREN;
return CView
::PreCreateWindow(cs);
}
右键view类,添加以下几个变量,就是前面所指的DC和RC
HGLRC m_hRC;
CDC* m_pDC;
之后添加以下几个函数
void RenderScene ();
BOOL SetupPixelFormat();
BOOL InitializeOpenGL();
在OnCreate中我们将通过建立像素格式和绘制上下文来初始化OpenGL. 在InitializeOpenGL()中会创建一个设备上下文(DC),为这个DC选择一个像素格式,创建和这个DC相关的绘制上下文(RC),然后选择这个RC.这个函数会调用SetupPixelFormat()来建立像素格式
int CDemoView
::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView
::OnCreate(lpCreateStruct)
== -1)
return -1;
InitializeOpenGL();
return 0;
}
BOOL CDemoView
::InitializeOpenGL()
{
m_pDC
= new CClientDC(this);
if(m_pDC
== NULL)
{
MessageBox(
"Error Obtaining DC");
return FALSE;
}
if(
!SetupPixelFormat())
{
return FALSE;
}
m_hRC
= ::wglCreateContext (m_pDC
->GetSafeHdc ());
if(m_hRC
== 0)
{
MessageBox(
"Error Creating RC");
return FALSE;
}
if(
::wglMakeCurrent (m_pDC
->GetSafeHdc (), m_hRC)
==FALSE)
{
MessageBox(
"Error making RC Current");
return FALSE;
}
::glClearColor(
0.0f,
0.0f,
0.0f,
0.0f);
::glClearDepth(
1.0f);
::glEnable(GL_DEPTH_TEST);
return TRUE;
}
BOOL CDemoView
::SetupPixelFormat()
{
static PIXELFORMATDESCRIPTOR pfd
=
{
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,
0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0,
0,
0
};
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;
}
在OnSize()中一般用来设置视口和视锥,因为这些是和窗口大小相关的。基本操作包括设置视口,选择投影矩阵,设置模型视图矩阵
void CDemoView
::OnSize(UINT nType, int cx, int cy)
{
CView
::OnSize(nType, cx, cy);
GLdouble aspect_ratio;
if (
0 >= cx
|| 0 >= cy )
{
return;
}
::glViewport(
0,
0, cx, cy);
aspect_ratio
= (GLdouble)cx
/(GLdouble)cy;
::glMatrixMode(GL_PROJECTION);
::glLoadIdentity();
::gluPerspective(
45.0f, aspect_ratio,
.01f,
200.0f);
::glMatrixMode(GL_MODELVIEW);
::glLoadIdentity();
}
在绘制场景时,一般包括如下步骤:
清空缓存。绘制场景。Flush掉渲染流水线。若设置了双缓冲,则交换前后台缓冲区
void CDemoView
::OnDraw(CDC* pDC)
{
CDemoDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
RenderScene();
::glFinish();
::SwapBuffers( m_pDC->GetSafeHdc() );
}
void CDemoView
::RenderScene()
{
}
为了防止窗口大小改变时不闪烁,在关闭程序的时候不出现内存泄漏
BOOL CDemoView::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CDemoView
::OnDestroy()
{
CView
::OnDestroy();
if(
::wglMakeCurrent (
0,
0)
== FALSE)
{
MessageBox(
"Could not make RC non-current");
}
if(
::wglDeleteContext (m_hRC)
==FALSE)
{
MessageBox(
"Could not delete RC");
}
if(m_pDC)
{
delete m_pDC;
}
m_pDC
= NULL;
}
到此一个基本的框架就算是搭建完毕了
转载请注明原文地址: https://ju.6miu.com/read-1202818.html