首先,使用的库是GLUT以及GLAUX,先下载两者,添加查找路径以及链接
//openGL 所需要的头文件 #include <gl/gl.h> #include <gl/glu.h> #include <gl/glut.h> #include <gl/glaux.h>
WS_CLIPCHILDREN和
WS_CLIPSIBLINGS,从而避免OpenGL绘制到其他窗口中去。这些应该放在PreCreateWindow()中。
BOOL CopenGLMFCView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; return CView::PreCreateWindow(cs); }
HGLRC m_hRC; //RC 绘图上下文 CDC* m_pDC; //DC 设备上下文 BOOL InitializeOpenGL(); //初始化 OpenGL BOOL SetupPixelFormat(); //为 DC 建立像素格式
WM_SIZE触发,需要调整绘图
WM_ERASEBACKGROUND消息触发的事件
OnCreate OnDestroy OnSize OnEraseBkground
将通过建立像素格式和绘制上下文来初始化OpenGL. 在InitializeOpenGL()中会创建一个设备上下文(DC),为这个DC选择一个像素格式,创建和这个DC相关的绘制上下文(RC),然后选择这个RC.这个函数会调用SetupPixelFormat()来建立像素格式。
int CopenGLMFCView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here InitializeOpenGL(); return 0; } BOOL CopenGLMFCView::InitializeOpenGL() { //客户区获得DC m_pDC = new CClientDC(this); //Failure to Get DC if (m_pDC == NULL) { MessageBox(L"Error Obtaining DC"); return FALSE; } //为DC建立像素格式 if (!SetupPixelFormat()) { return FALSE; } //创建 RC m_hRC = ::wglCreateContext(m_pDC->GetSafeHdc()); //Failure to Create Rendering Context if (m_hRC == 0) { MessageBox(L"Error Creating RC"); return FALSE; } //设定OpenGL当前线程的渲染环境。 //以后这个线程所有的OpenGL调用都是在这个hdc标识的设备上绘制。 if (::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC) == FALSE) { MessageBox(L"Error making RC Current"); return FALSE; } //背景颜色 ::glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //深度缓存 1最大,让任何都能显示出来 ::glClearDepth(1.0f); //如果通过比较后深度值发生变化了,会进行更新深度缓冲区的操作 ::glEnable(GL_DEPTH_TEST); return TRUE; } //建立像素格式 ///////////////////////////////////////////////////////////////////////////// BOOL CopenGLMFCView::SetupPixelFormat() { static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 1, // version number PFD_DRAW_TO_WINDOW | // support window PFD_SUPPORT_OPENGL | // support OpenGL PFD_DOUBLEBUFFER, // double buffered PFD_TYPE_RGBA, // RGBA type 24, // 24-bit color depth 0, 0, 0, 0, 0, 0, // color bits ignored 0, // no alpha buffer 0, // shift bit ignored 0, // no accumulation buffer 0, 0, 0, 0, // accum bits ignored 16, // 16-bit z-buffer 0, // no stencil buffer 0, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored }; 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; }
void CopenGLMFCView::OnDraw(CDC* /*pDC*/) { CopenGLMFCDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: add draw code for native data here // 清除颜色、深度缓存 ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //可以添加渲染函数 // Flush掉渲染流水线 ::glFinish(); // 交换前后缓存区 ::SwapBuffers(m_pDC->GetSafeHdc()); }
9、背景绘制修改
试试改变窗口的大小,你会看到很严重的闪烁,并且关闭程序后会报告内存泄露,因此我们这就来解决这两个问题吧。
发生闪烁的原因是Windows先绘制背景,然后再是OpenGL绘制,因为我们已经让OpenGL负责清空背景色,因此我们不需要Windows去清空背景了
BOOL CopenGLMFCView::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default return TRUE;//CView::OnEraseBkgnd(pDC); }
内存泄露的原因是我们在InitializeOpenGL()中使用了new运算符来为CClientDC对象分配内存,因此需要显示delete掉。
void CopenGLMFCView::OnDestroy() { CView::OnDestroy(); // TODO: Add your message handler code here if (::wglMakeCurrent(0, 0) == FALSE) { MessageBox(L"Could not make RC non-current"); } //Delete the rendering context if (::wglDeleteContext(m_hRC) == FALSE) { MessageBox(L"Could not delete RC"); } //Delete the DC if (m_pDC) { delete m_pDC; } //Set it to NULL m_pDC = NULL; }
void CopenGLMFCView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // TODO: Add your message handler code here GLdouble aspect_ratio; // width/height ratio if (0 >= cx || 0 >= cy) { return; } // select the full client area ::glViewport(0, 0, cx, cy); // compute the aspect ratio // this will keep all dimension scales equal aspect_ratio = (GLdouble)cx / (GLdouble)cy; // select the projection matrix and clear it ::glMatrixMode(GL_PROJECTION); ::glLoadIdentity(); // select the viewing volume ::gluPerspective(45.0f, aspect_ratio, .01f, 200.0f); // switch back to the modelview matrix and clear it ::glMatrixMode(GL_MODELVIEW); ::glLoadIdentity(); }
通过上面得到运行结果:
二、基于对话框
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/119499.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...