快捷搜索:

VC++6.0中使用OpenGL

----要进修OpenGL 编程,盼望读者具备基础的图形常识。本文应用基于Visual C ++消息驱动编程,对付没学过VC 的读者也有必然的赞助。我们的第一个法度榜样将明建立一个视窗法度榜样显示OpenGL 图形的最小需求。为成这一义务我们将分如下5 步来进行:

----要进修OpenGL 编程,盼望读者具备基础的图形常识。本文应用基于Visual C ++消息驱动编程,对付没学过VC 的读者也有必然的赞助。我们的第一个法度榜样将明建立一个视窗法度榜样显示OpenGL 图形的最小需求。为成这一义务我们将分如下5 步来进行:

----1 设置窗口像素的款式;2 建立RC;3 使RC 设为当前;4 创建视口和矩阵模型;5 画一个立方体和一个茶壶。

----现在你可以打开你的Visual C ++,建立一个单文档的项目。首先我们在该项目中加进所有必需的OpenGL 文件和库,在菜单中选择Build Settings,然后点击LINK 按钮( 或者按Ctrl +Tab 键来移动到那儿)。在Object/Library 栏中键入Opengl32.lib glu32.lib glaux.lib, 并确定。打开文件stdafx.h 插入如下行:

#include

#include

#include

----OpenGL 仅能在具有WS_CLIPCHILDREN 和WS_CLIPSIBLINGS 类型的窗口显示图形,我们必要编辑OnPreCreate 函数,指定一下窗口类型。

BOOL COPView::PreCreateWindow(CREATESTRUCT &cs)

{cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS);

return CView::PreCreateWindow(cs);

}

----下面我们要定义窗口的像素款式,这一点对建立RC 很紧张。首先我们必要建立一个受保护的成员函数BOOL SetWindowPixelFormat(HDC hDC)。如下所示:

BOOL COPView::SetWindowPixelFormat(HDC hDC)

{

PIXELFORMATDESCRIPTOR pixelDesc;

pixelDesc.nSize= sizeof(PIXELFORMATDESCRIP ?

TOR);

pixelDesc.nVersion= 1;

pixelDesc.dwFlags= PFD_DRAW_TO_WINDOW |

PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL |

PFD_SUPPORT_GDI |PFD_STEREO_DONTCARE;

pixelDesc.iPixelType= PFD_TYPE_RGBA;

pixelDesc.cColorBits = 32;

pixelDesc.cRedBits = 8;

pixelDesc.cRedShift = 16;

pixelDesc.cGreenBits = 8;

pixelDesc.cGreenShift = 8;

pixelDesc.cBlueBits = 8;

pixelDesc.cBlueShift = 0;

pixelDesc.cAlphaBits = 0;

pixelDesc.cAlphaShift = 0;

pixelDesc.cAccumBits= 64;

pixelDesc.cAccumRedBits = 16;

pixelDesc.cAccumGreenBits = 16;

pixelDesc.cAccumBlueBits = 16;

pixelDesc.cAccumAlphaBits= 0;

pixelDesc.cDepthBits = 32;

pixelDesc.cStencilBits= 8;

pixelDesc.cAuxBuffers = 0;

pixelDesc.iLayerType= PFD_MAIN_PLANE;

pixelDesc.bReserved = 0;

pixelDesc.dwLayerMask= 0;

pixelDesc.dwVisibleMask= 0;

pixelDesc.dwDamageMask= 0;

m_GLPixelIndex = ChoosePixelFormat( hDC, &pixelDesc);

if (m_GLPixelIndex==0) // Let's choose a default index.

{

m_GLPixelIndex = 1;

if (DescribePixelFormat(hDC, m_GLPixelIndex, sizeof

(PIXELFORMATDESCRIPTOR), &pixelDesc)==0)

{

return FALSE;

}

}

if (SetPixelFormat( hDC, m_GLPixelIndex,

&pixelDesc)==FALSE)

{

return FALSE;

}

return TRUE;

}

----加入一个成员变量到视类中:

int m_GLPixelIndex; // protected

----着末,在ClassWizard 中加入函数OnCreate 来相应消息WM_CREATE,函数如下:

int COPView::OnCreate

(LPCREATESTRUCT lpCreateStruct)

{

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

return -1;

HWND hWnd = GetSafeHwnd();

HDC hDC = ::GetDC(hWnd);

if (SetWindowPixelFormat(hDC)==FALSE)

return 0;

if (CreateViewGLContext(hDC)==FALSE)

return 0;

return 0;

}

----下面必要作的步骤便是建立RC,并置为当前RC。

----在视类中加入保护函数CreateViewGLContext(HDC hDC) 和变量HGLRC m_hGLContext:

BOOL COPView::CreateViewGLContext(HDC hDC)

{

m_hGLContext = wglCreateContext(hDC);

if (m_hGLContext == NULL)

{

return FALSE;

}

if (wglMakeCurrent(hDC, m_hGLContext)==FALSE)

{

return FALSE;

}

return TRUE;

}

加入函数OnDestroy 来相应WM_DESTROY:

void COPView::OnDestroy()

{

if(wglGetCurrentContext()!=NULL)

{

wglMakeCurrent(NULL, NULL) ;

}

if (m_hGLContext!=NULL)

{

wglDeleteContext(m_hGLContext);

m_hGLContext = NULL;

}

CView::OnDestroy();

}

----着末,编辑一下COPView 类构造函数:

COPView::COPView()

{

m_hGLContext = NULL;

m_GLPixelIndex = 0;

}

----现在,我们就可以进行OpenGL 画图了,虽然它看起来仍旧像一个范例的MFC 法度榜样。

----现在我们进行下一步建立视点和矩阵模型,用ClassWizard 在视类中加入函数OnSize 相应WM_SIZE。如下所示:

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

{

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

GLsizei width, height; GLdouble aspect;

width = cx; height = cy;

if (cy==0)

aspect = (GLdouble)width;

else

aspect = (GLdouble)width/(GLdouble)height;

glViewport(0, 0, width, height);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluPerspective(45, aspect, 1, 10.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

加入函数:void COPView::OnPaint()

{

CPaintDC dc(this); // device context for painting

COPDoc *pDoc = GetDocument();

pDoc ->RenderScene();

}

----在文档类中加入公共函数RenderScene():

void COPDoc::RenderScene(void)

{ glClear(GL_COLOR_BUFFER_BIT); glFlush(); }

----现在法度榜样运行后仅是黑黑的屏幕, 我们必要加进些器械。

----在文档类中加一个罗列变量GLDisplayListNames:

enum GLDisplayListNames { ArmPart1,armPart2 };

----为将来建立显示列表用。编辑函数OnNewDocument(),编码如下:

BOOL COPDoc::OnNewDocument()

if (!CDocument::OnNewDocument())

return FALSE;

glNewList(armPart1, GL_COMPILE);

GLfloat RedSurface[]= { 1.0f, 0.0f, 0.0f, 1.0f};

GLfloat GreenSurface[] = { 0.0f, 1.0f, 0.0f, 1.0f};

GLfloat BlueSurface[]= { 0.0f, 0.0f, 1.0f, 1.0f};

GLfloat LightAmbient[]= { 0.1f, 0.1f, 0.1f, 0.1f };

GLfloat LightDiffuse[]= { 0.7f, 0.7f, 0.7f, 0.7f };

GLfloat LightSpecular[] = { 0.0f, 0.0f, 0.0f, 0.1f };

GLfloat LightPosition[] = { 5.0f, 5.0f, 5.0f, 0.0f };

glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);

glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);

glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpecular);

glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);

glEnable(GL_LIGHT0);

glMaterialfv(GL_FRONT_AND_BACK,

GL_AMBIENT, RedSurface);

glBegin(GL_POLYGON);

glNormal3d(1.0,0.0,0.0);

glVertex3d(1.0,1.0,1.0); glVertex3d(

1.0, -1.0,1.0);

glVertex3d(1.0, -1.0, -1.0); glVertex3d

(1.0,1.0, -1.0); // 画第一个面

glEnd();

glBegin(GL_POLYGON);

glNormal3d( -1.0,0.0,0.0);

// 此处同上画第二个面。

立方体的中间为坐标原点。

glEnd();

glMaterialfv(GL_FRONT_AND_BACK,

GL_AMBIENT, GreenSurface);

// 此处同上画第三、四个面,

留意平面法向和坐标。

glMaterialfv(GL_FRONT_AND_BACK,

GL_AMBIENT, BlueSurface);

// 此处同上画第五、六个面。

glEndList();

glNewList(armPart2, GL_COMPILE);

glMaterialfv(GL_FRONT_AND_BACK,

GL_AMBIENT, GreenSurface);

auxSolidTeapot(1.0);// 用帮助库函数画茶壶。

glEndList();

return TRUE;

}

----下面就看如何显示它了。编辑RenderScene 函数:

void COPDoc::RenderScene(void)

{

double m_angle1=60.0;double m_angle2=30.0;

glClear

(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glPushMatrix();

glTranslated(3.0, 0.0, -8.0); glRotated( m_angle1, 0, 0, 1);

glRotated( m_angle2, 0, 1, 0);

glCallList(armPart1);

glPopMatrix();

glPushMatrix();

glTranslated(0.0, 0.0, -8.0);

glCallList(armPart2);

glPopMatrix();

glFlush();

您可能还会对下面的文章感兴趣: