以文本方式查看主题 - 中文XML论坛 - 专业的XML技术讨论区 (http://bbs.xml.org.cn/index.asp) -- 『 C/C++编程思想 』 (http://bbs.xml.org.cn/list.asp?boardid=61) ---- OpenGL学习 (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=87760) |
-- 作者:葛靖青001 -- 发布时间:11/16/2010 11:57:00 AM -- OpenGL学习 【转自互联网】 ----要学习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 < gl\gl.h > #include < gl\glu.h > #include < gl\glaux.h > ----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(); } |
W 3 C h i n a ( since 2003 ) 旗 下 站 点 苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》 |
46.875ms |