九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
用MFC實(shí)現(xiàn)OpenGL編程

用MFC實(shí)現(xiàn)OpenGL編程

                           
一、OpenGL簡(jiǎn)介
  眾所周知,OpenGL原先是Silicon Graphics Incorporated(SGI公司)在他們的圖形工作站上開(kāi)發(fā)高質(zhì)量圖像的接口。但最近幾年它成為一個(gè)非常優(yōu)秀的開(kāi)放式三維圖形接口。實(shí)際上它是圖形軟件和硬件的接口,它包括有120多個(gè)圖形函數(shù),"GL"是"GRAPHIC LIBRARY"的縮寫(xiě),意思是“圖形庫(kù)”。OpenGL的出現(xiàn)使大多數(shù)的程序員能夠在PC機(jī)上用C語(yǔ)言開(kāi)發(fā)復(fù)雜的三維圖形。微軟在Visual C++ 7中已提供了三個(gè)OpenGL的函數(shù)庫(kù)(glu32.lib, glau.lib,OpenGL32.lib),可以使我們方便地編程,簡(jiǎn)單、快速地生成美觀、漂亮的圖形。例如,Windows NT中的屏幕保護(hù)程序中的花籃和迷宮等都給人們留下了深刻的印象。
  
二、生成OpenGL程序的基本步驟和條件    
     本文將給出一個(gè)例子,這個(gè)例子是一個(gè)用OpenGL顯示圖像的Windows程序,通過(guò)這個(gè)程序我們也可以知道用OpenGL編程的基本要求。我們知道,GDI是通過(guò)設(shè)備句柄(Device Context以下簡(jiǎn)稱"DC")來(lái)繪圖,而OpenGL則需要繪制環(huán)境(Rendering Context,以下簡(jiǎn)稱"RC")。每一個(gè)GDI命令需要傳給它一個(gè)DC,與GDI不同,OpenGL使用當(dāng)前繪制環(huán)境(RC)。一旦在一個(gè)線程中指定了一個(gè)當(dāng)前RC,所有在此線程中的OpenGL命令都使用相同的當(dāng)前RC。雖然在單一窗口中可以使用多個(gè)RC,但在單一線程中只有一個(gè)當(dāng)前RC。本例將首先產(chǎn)生一個(gè)OpenGL RC并使之成為當(dāng)前RC,分為三個(gè)步驟:設(shè)置窗口像素格式;產(chǎn)生RC;設(shè)置為當(dāng)前RC。
1、首先創(chuàng)建工程
  用AppWizard產(chǎn)生一個(gè)EXE文件,選擇工程目錄,并在工程名字中輸入"OpenGL",保持其他的不變;第一步、選單文檔(SDI);第二步、不支持?jǐn)?shù)據(jù)庫(kù);第三步、不支持OLE;第四步、不選中浮動(dòng)工具條、開(kāi)始狀態(tài)條、打印和預(yù)覽支持、幫助支持的復(fù)選框,選中三維控制(3D Controls);第五步、選中產(chǎn)生源文件注釋并使用MFC為共享動(dòng)態(tài)庫(kù);第六步、保持缺省選擇。按Finish結(jié)束,工程創(chuàng)建完畢,如圖1所示。
 
2、將此工程所需的OpenGL文件 和庫(kù)加入到工程中
  在工程菜單中,選擇"Build"下的"Settings"項(xiàng)。單擊"Link"標(biāo)簽,選擇"General"目錄,在Object/Library Modules的編輯框中輸入"OpenGL32.lib glu32.lib glaux.lib"(注意,輸入雙引號(hào)中的內(nèi)容,各個(gè)庫(kù)用空格分開(kāi);否則會(huì)出現(xiàn)鏈接錯(cuò)誤),選擇"OK"結(jié)束。然后打開(kāi)文件"stdafx.h",將下列語(yǔ)句插入到文件中(劃下劃線的語(yǔ)句為所加語(yǔ)句):
  #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
  #include <afxwin.h> // MFC core and standard components
  #include <afxext.h> // MFC extensions
    #include <gl/gl.h>  // OpenGL32庫(kù)的頭文件
    #include <gl/glu.h>  // GLu32庫(kù)的頭文件
    #include <gl/glaux.h> // GLaux庫(kù)的頭文件
  #ifndef _AFX_NO_AFXCMN_SUPPORT
  #include <afxcmn.h> // MFC support for Windows 95 Common Controls
  #endif // _AFX_NO_AFXCMN_SUPPORT 
    //同樣也可以使用下列方式連接lib        
    #pragma comment( lib, "opengl32.lib") // OpenGL32連接庫(kù)
    #pragma comment( lib, "glu32.lib")  // GLu32連接庫(kù)
    #pragma comment( lib, "glaux.lib")  // GLaux連接庫(kù)
3、改寫(xiě)OnPreCreate函數(shù)并給視 類添加成員函數(shù)和成員變量
  OpenGL需要窗口加上WS_CLIPCHILDREN(創(chuàng)建父窗口使用的Windows風(fēng)格,用于重繪時(shí)裁剪子窗口所覆蓋的區(qū)域)和 WS_CLIPSIBLINGS(創(chuàng)建子窗口使用的Windows風(fēng)格,用于重繪時(shí)剪裁其他子窗口所覆蓋的區(qū)域)風(fēng)格。把OnPreCreate改寫(xiě)成如下所示:
  
   BOOL COpenGLView::PreCreateWindow(CREATESTRUCT& cs)
  {
   cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
   return CView::PreCreateWindow(cs);
  }
    產(chǎn)生一個(gè)RC的第一步是定義窗口的像素格式。像素格式?jīng)Q定窗口著所顯示的圖形在內(nèi)存中是如何表示的。由像素格式控制的參數(shù)包括:顏色深度、緩沖模式和所支持的繪畫(huà)接口。在下面將有對(duì)這些參數(shù)的設(shè)置。我們先在COpenGLView的類中添加一個(gè)保護(hù)型的成員函數(shù)BOOL SetWindowPixelFormat(HDC hDC),并編輯其中的代碼。
    BOOL COpenGLView::SetWindowPixelFormat(HDC hDC)
{
 PIXELFORMATDESCRIPTOR pixelDesc; 
 pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
 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; 
 
//接著用鼠標(biāo)右鍵在COpenGLView中添加保護(hù)型的成員變量: int m_GLPixelIndex;

 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; 
}    
    
4、用ClassWizard添加WM_CREATE的消息處理函數(shù)OnCreate
  添加OnCreate函數(shù)后如下所示。
int COpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
 if (CView::OnCreate(lpCreateStruct) == -1)
  return -1;
 
 // TODO: Add your specialized creation code here
 HWND hWnd = GetSafeHwnd(); 
 HDC hDC = ::GetDC(hWnd); 
 if (SetWindowPixelFormat (hDC)==FALSE) 
  return 0; 
 if (CreateViewGLContext (hDC)==FALSE) 
  return 0; 
 return 0;
}
至此,OpenGL工程的基本框架就建好了。但如果你現(xiàn)在運(yùn)行此工程,則它與一般的MFC程序看起來(lái)沒(méi)有什么兩樣。
 
5、代碼解釋
  現(xiàn)在我們可以看一看Describe-PixelFormat提供有哪幾種像素格式,并對(duì)代碼進(jìn)行一些解釋:
  PIXELFORMATDESCRIPTOR包括了定義像素格式的全部信息。
   DWFlags定義了與像素格式兼容的設(shè)備和接口。
  通常的OpenGL發(fā)行版本并不包括所有的標(biāo)志(flag)。wFlags能接收以下標(biāo)志:
  PFD_DRAW_TO_WINDOW 使之能在窗口或者其他設(shè)備窗口畫(huà)圖;
  PFD_DRAW_TO_BITMAP 使之能在內(nèi)存中的位圖畫(huà)圖;
  PFD_SUPPORT_GDI 使之能調(diào)用GDI函數(shù)(注:如果指定了PFD_DOUBLEBUFFER,這個(gè)選項(xiàng)將無(wú)效);
  PFD_SUPPORT_OpenGL 使之能調(diào)用OpenGL函數(shù);
  PFD_GENERIC_FORMAT 假如這種象素格式由Windows GDI函數(shù)庫(kù)或由第三方硬件設(shè)備驅(qū)動(dòng)程序支持,則需指定這一項(xiàng);
  PFD_NEED_PALETTE 告訴緩沖區(qū)是否需要調(diào)色板,本程序假設(shè)顏色是使用24或 32位色,并且不會(huì)覆蓋調(diào)色板;
  PFD_NEED_SYSTEM_PALETTE 這個(gè)標(biāo)志指明緩沖區(qū)是否把系統(tǒng)調(diào)色板當(dāng)作它自身調(diào)色板的一部分;
  PFD_DOUBLEBUFFER 指明使用了雙緩沖區(qū)(注:GDI不能在使用了雙緩沖區(qū)的窗口中畫(huà)圖);
  PFD_STEREO 指明左、右緩沖區(qū)是否按立體圖像來(lái)組織。
  PixelType定義顯示顏色的方法。PFD_TYPE_RGBA意味著每一位(bit)組代表著紅、綠、藍(lán)各分量的值。PFD_TYPE_COLORINDEX 意味著每一位組代表著在彩色查找表中的索引值。本例都是采用了PFD_TYPE_RGBA方式。
  ● cColorBits定義了指定一個(gè)顏色的位數(shù)。對(duì)RGBA來(lái)說(shuō),位數(shù)是在顏色中紅、綠、藍(lán)各分量所占的位數(shù)。對(duì)顏色的索引值來(lái)說(shuō),指的是表中的顏色數(shù)。
  ● cRedBits、cGreenBits、cBlue-Bits、cAlphaBits用來(lái)表明各相應(yīng)分量所使用的位數(shù)。
  ● cRedShift、cGreenShift、cBlue-Shift、cAlphaShift用來(lái)表明各分量從顏色開(kāi)始的偏移量所占的位數(shù)。
  一旦初始化完我們的結(jié)構(gòu),我們就想知道與要求最相近的系統(tǒng)象素格式。我們可以這樣做:
  
  m_hGLPixelIndex = ChoosePixelFormat(hDC, &pixelDesc);
  
  ChoosePixelFormat接受兩個(gè)參數(shù):一個(gè)是hDc,另一個(gè)是一個(gè)指向PIXELFORMATDESCRIPTOR結(jié)構(gòu)的指針&pixelDesc;該函數(shù)返回此像素格式的索引值。如果返回0則表示失敗。假如函數(shù)失敗,我們只是把索引值設(shè)為1并用DescribePixelFormat得到像素格式描述。假如你申請(qǐng)一個(gè)沒(méi)得到支持的像素格式,則Choose-PixelFormat將會(huì)返回與你要求的像素格式最接近的一個(gè)值。一旦我們得到一個(gè)像素格式的索引值和相應(yīng)的描述,我們就可以調(diào)用SetPixelFormat設(shè)置像素格式,并且只需設(shè)置一次。
  現(xiàn)在像素格式已經(jīng)設(shè)定,我們下一步工作是產(chǎn)生繪制環(huán)境(RC)并使之成為當(dāng)前繪制環(huán)境。在COpenGLView中加入一個(gè)保護(hù)型的成員函數(shù)BOOL CreateViewGLContext(HDC hDC),使之如下所示:
  BOOL COpenGLView::CreateViewGLContext(HDC hDC)
  { m_hGLContext = wglCreate Context(hDC);//用當(dāng)前DC產(chǎn)生繪制環(huán)境(RC)
   if (m_hGLContext == NULL)
   { return FALSE;
   }
   if (wglMakeCurrent(hDC, m_hGLContext)==FALSE)
   { return FALSE;
   }
   return TRUE;
  }
  并加入一個(gè)保護(hù)型的成員變量HGLRC m_hGLContext;HGLRC是一個(gè)指向rendering context的句柄。
  在OnCreate函數(shù)中調(diào)用此函數(shù):
  
  int COpenGLView::OnCreate (LPCREATESTRUCT lpCreateStruct)
  {
  if (CView::OnCreate(lpCreateS truct) == -1)
   return -1;
   HWND hWnd = GetSafeHwnd();
   HDC hDC = ::GetDC(hWnd);
   if (SetWindowPixelFormat (hDC)==FALSE)
       return 0;
   if (CreateViewGLContext (hDC)==FALSE)
       return 0;
   return 0;
  }
  
  添加WM_DESTROY的消息處理函數(shù)Ondestroy( ),使之如下所示:
  
  void COpenGLView::OnDestroy()
  {
   if(wglGetCurrentContext()!=NULL)
   { // make the rendering context not current
   wglMakeCurrent(NULL, NULL) ;
   }
   if (m_hGLContext!=NULL)
   { wglDeleteContext(m_hGLContext);
   m_hGLContext = NULL;
   }
   // Now the associated DC can be released.
   CView::OnDestroy();
  }
  
  最后,編輯COpenGLView的構(gòu)造函數(shù),使之如下所示:
  
  CGLTutor1View::CGLTutor1View()
  {
         m_hGLContext = NULL;
      m_GLPixelIndex = 0;
  }
  
  至此,我們已經(jīng)構(gòu)造好了框架,使程序可以利用OpenGL進(jìn)行畫(huà)圖了。你可能已經(jīng)注意到了,我們?cè)诔绦蜷_(kāi)頭產(chǎn)生了一個(gè)RC,自始自終都使用它。這與大多數(shù)的GDI程序不同。在GDI程序中,DC在需要時(shí)才產(chǎn)生,并且是畫(huà)完立刻釋放掉。實(shí)際上,RC也可以這樣做;但要記住,產(chǎn)生一個(gè)RC需要很多處理器時(shí)間。因此,要想獲得高性能流暢的圖像和圖形,最好只產(chǎn)生RC一次,并始終用它,直到程序結(jié)束。
  CreateViewGLContex產(chǎn)生RC并使之成為當(dāng)前RC。WglCreateContext返回一個(gè)RC的句柄。在你調(diào)用CreateViewGLContex之前,你必須用SetWindowPixelFormat(hDC)將與設(shè)備相關(guān)的像素格式設(shè)置好。wglMakeCurrent將RC設(shè)置成當(dāng)前RC。傳入此函數(shù)的DC不一定就是你產(chǎn)生RC的那個(gè)DC,但二者的設(shè)備句柄(Device Context)和像素格式必須一致。假如你在調(diào)用wglMakeforCurrent之前已經(jīng)有另外一個(gè)RC存在,wglMakeforCurrent就會(huì)把舊的RC沖掉,并將新RC設(shè)置為當(dāng)前RC。另外你可以用wglMakeCurrent(NULL, NULL)來(lái)消除當(dāng)前RC。
  我們要在OnDestroy中把繪制環(huán)境刪除掉。但在刪除RC之前,必須確定它不是當(dāng)前句柄。我們是通過(guò)wglGetCurrentContext來(lái)了解是否存在一個(gè)當(dāng)前繪制環(huán)境的。假如存在,那么用wglMakeCurrent(NULL, NULL)來(lái)把它去掉。然后就可以通過(guò)wglDelete-Context來(lái)刪除RC了。這時(shí)允許視類刪除DC才是安全的。注:一般來(lái)說(shuō),使用的都是單線程的程序,產(chǎn)生的RC就是線程當(dāng)前的RC,不需要關(guān)注上述這一點(diǎn)。但如果使用的是多線程的程序,那我們就特別需要注意這一點(diǎn)了,否則會(huì)出現(xiàn)意想不到的后果。
 
三、實(shí)例
下面給出一個(gè)簡(jiǎn)單的二維圖形的例子(這個(gè)例子都是以上述設(shè)置為基礎(chǔ)的)。
用Classwizard為COpenGLview添加WMSIZE的消息處理函數(shù)OnSize,使之如下所示。
  void COpenGLView::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();
   gluOrtho2D(0.0, 500.0*aspect, 0.0, 500.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
  }
  
用Classwizard為COpenGLview添加WM_PAINT的消息處理函數(shù)OnPaint,使之如下所示。
  void COpenGLView::OnPaint()
  { CPaintDC DC(this); // device context for painting (added by ClassWizard)
   glLoadIdentity();
   glClear(GL_COLOR_BUFFER_BIT);
   glBegin(GL_POLYGON);
   glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
   glVertex2f(100.0f, 50.0f);
   glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
   glVertex2f(450.0f, 400.0f);
   glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
   glVertex2f(450.0f, 50.0f);
   glEnd();
   glFlush();
  }
   
  這個(gè)程序的運(yùn)行結(jié)果是黑色背景下的一個(gè)絢麗多彩的三角形(如圖2所示)。這里你可以看到用OpenGL繪制圖形非常容易,只需要幾條簡(jiǎn)單的語(yǔ)句就能實(shí)現(xiàn)強(qiáng)大的功能。如果你縮放窗口,三角形也會(huì)跟著縮放。這是因?yàn)镺nSize通過(guò)glViewport(0, 0, width, height)定義了視口和視口坐標(biāo)。glViewport的第一、二個(gè)參數(shù)是視口左下角的像素坐標(biāo),第三、四個(gè)參數(shù)是視口的寬度和高度。
  OnSize中的glMatrixMode是用來(lái)設(shè)置矩陣模式的,它有三個(gè)選項(xiàng):GL_MODELVIEW、GL_PROJECTION、GL_TEXTURE。GL_MODELVIEW表示從實(shí)體坐標(biāo)系轉(zhuǎn)到人眼坐標(biāo)系。GL_PROJECTION表示從人眼坐標(biāo)系轉(zhuǎn)到剪裁坐標(biāo)系。GL_TEXTURE表示從定義紋理的坐標(biāo)系到粘貼紋理的坐標(biāo)系的變換。
  glLoadIdentity初始化工程矩陣(project matrix);gluOrtho2D把工程矩陣設(shè)置成顯示一個(gè)二維直角顯示區(qū)域。
  這里我們有必要說(shuō)一下OpenGL命令的命名原則。大多數(shù)OpenGL命令都是以"gl"開(kāi)頭的。也有一些是以"glu"開(kāi)頭的,它們來(lái)自O(shè)penGL Utility。大多數(shù)"gl"命令在名字中定義了變量的類型并執(zhí)行相應(yīng)的操作。例如:glVertex2f就是定義了一個(gè)頂點(diǎn),參數(shù)變量為兩個(gè)浮點(diǎn)數(shù),分別代表這個(gè)頂點(diǎn)的x、y坐標(biāo)。類似的還有g(shù)lVertex2d、glVertex2f、glVertex3I、glVertex3s、glVertex2sv、glVertex3dv……等函數(shù)。
  那么,怎樣畫(huà)三角形呢?我們首先調(diào)用glColor4f(1.0f, 0.0f, 0.0f, 1.0f),把紅、綠、藍(lán)分量分別指定為1、0、0。然后我們用glVertex2f(100.0f, 50.0f)在(100,50)處定義一個(gè)點(diǎn)。依次,我們?cè)?450,400)處定義綠點(diǎn),在(450,50)處定義藍(lán)點(diǎn)。然后我們用glEnd結(jié)束畫(huà)三角形。但此時(shí)三角形還沒(méi)畫(huà)出來(lái),這些命令還只是在緩沖區(qū)里,直到你調(diào)用glFlush函數(shù),由glFlush觸發(fā)這些命令的執(zhí)行。OpenGL自動(dòng)改變?nèi)切雾旤c(diǎn)間的顏色值,使之絢麗多彩。
  還可通過(guò)glBegin再產(chǎn)生新的圖形。glBegin(GLenum mode)參數(shù)有:
  
  GL_POINTS,GL_LINES, GL_LINE_STRIP,GL_LINE_LOOP, GL_TRIANGLES,GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN,GL_QUADS, GL_QUAD_STRIP, GL_POLYGON
  
  在glBegin和glEnd之間的有效函數(shù)有:
  glVertex,glColor,glIndex, glNormal,glTexCoord, glEvalCoord,glEvalPoint, glMaterial, glEdgeFlag
  
四、OpenGL編程小結(jié)
  
  1、如果要響應(yīng)WM_SIZE消息,則一定要設(shè)置視口和矩陣模式。
  2、盡量把你全部的畫(huà)圖工作在響應(yīng)WM_PAINT消息時(shí)完成。
  3、產(chǎn)生一個(gè)繪制環(huán)境要耗費(fèi)大量的CPU時(shí)間,所以最好在程序中只產(chǎn)生一次,直到程序結(jié)束。
  4、盡量把你的畫(huà)圖命令封裝在文檔類中,這樣你就可以在不同的視類中使用相同的文檔,節(jié)省你編程的工作量。
  5、glBegin和glEnd一定要成對(duì)出現(xiàn),這之間是對(duì)圖元的繪制語(yǔ)句。
  glPushMatrix()和glPopMatrix()也一定要成對(duì)出現(xiàn)。glPushMatrix()把當(dāng)前的矩陣拷貝到棧中。當(dāng)我們調(diào)用glPopMatrix時(shí),最后壓入棧的矩陣恢復(fù)為當(dāng)前矩陣。使用glPushMatrix()可以精確地把當(dāng)前矩陣保存下來(lái),并用glPopMatrix把它恢復(fù)出來(lái)。這樣我們就可以使用這個(gè)技術(shù)相對(duì)某個(gè)物體放置其他物體。例如下列語(yǔ)句只使用一個(gè)矩陣,就能產(chǎn)生兩個(gè)矩形,并將它們成一定角度擺放。
  
  glPushMatrix();
   glTranslated( m_transX, m_transY, 0);
   glRotated( m_angle1, 0, 0, 1);
   glPushMatrix();
   glTranslated( 90, 0, 0);
   glRotated( m_angle2, 0, 0, 1);
   glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
   glCallList(ArmPart);//ArmPart 且桓鼉卣竺??
   glPopMatrix();
   glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
   glCallList(ArmPart);
  glPopMatrix();
  
  6、 解決屏幕的閃爍問(wèn)題。我們知道,在窗口中拖動(dòng)一個(gè)圖形的時(shí)候,由于邊畫(huà)邊顯示,會(huì)出現(xiàn)閃爍的現(xiàn)象。在GDI中解決這個(gè)問(wèn)題較為復(fù)雜,通過(guò)在內(nèi)存中生成一個(gè)內(nèi)存DC,繪畫(huà)時(shí)讓畫(huà)筆在內(nèi)存DC中畫(huà),畫(huà)完后一次用Bitblt將內(nèi)存DC“貼”到顯示器上,就可解決閃爍的問(wèn)題。在OpenGL中,我們是通過(guò)雙緩存來(lái)解決這個(gè)問(wèn)題的。一般來(lái)說(shuō),雙緩存在圖形工作軟件中是很普遍的。雙緩存是兩個(gè)緩存,一個(gè)前臺(tái)緩存、一個(gè)后臺(tái)緩存。繪圖先在后臺(tái)緩存中畫(huà),畫(huà)完后,交換到前臺(tái)緩存,這樣就不會(huì)有閃爍現(xiàn)象了。通過(guò)以下步驟可以很容易地解決這個(gè)問(wèn)題:
  1) 要注意,GDI命令是沒(méi)有設(shè)計(jì)雙緩存的。我們首先把使用InvalidateRect(null)的地方改成InvalidateRect(NULL,FALSE)。這樣做是使GDI的重畫(huà)命令失效,由OpenGL的命令進(jìn)行重畫(huà);
  2) 將像素格式定義成支持雙緩存的(注:PFD_DOUBLEBUFFER和PFD_SUPPORT_GDI只能取一個(gè),兩者相互沖突)。
  
   pixelDesc.dwFlags =
   PFD_DRAW_TO_WINDOW |
   PFD_SUPPORT_OPENGL |
   PFD_DOUBLEBUFFER |
   PFD_STEREO_DONTCARE;
  
  3) 我們得告訴OpenGL在后臺(tái)緩存中畫(huà)圖,在視類的OnSize()的最后一行加入:glDrawBuffer (GL_BACK);
  4) 最后我們得把后臺(tái)緩存的內(nèi)容換到前臺(tái)緩存中,在視類的OnPaint()的最后一行加入:SwapBuffers(dc.m_ ps.hdc)。
  7、生成簡(jiǎn)單的三維圖形。我們知道,三維和二維的坐標(biāo)系統(tǒng)不同,三維的圖形比二維的圖形多一個(gè)z坐標(biāo)。我們?cè)谏珊?jiǎn)單的二維圖形時(shí),用的是gluOrtho2D;我們?cè)谏扇S圖形時(shí),需要兩個(gè)遠(yuǎn)近裁剪平面,以生成透視效果。實(shí)際上,二維圖形只是視線的近裁剪平面z= -1,遠(yuǎn)裁剪平面z=1;這樣z坐標(biāo)始終當(dāng)作0,兩者沒(méi)有本質(zhì)的差別。
  在上述基礎(chǔ)之上,我們只做簡(jiǎn)單的變化,就可以生成三維物體。
  1) 首先,在OnSize()中,把gluOrtho2D(0.0, 500.0*aspect,0.0, 500.0)換成gluPerspective(60, aspect, 1, 10.0);這樣就實(shí)現(xiàn)了三維透視坐標(biāo)系的設(shè)置。該語(yǔ)句說(shuō)明了視點(diǎn)在原點(diǎn),透視角是60度,近裁剪面在z=1處,遠(yuǎn)裁剪面在z=10.0處。
  2) 在RenderScene()中生成三維圖形;實(shí)際上,它是由多邊形組成的。下面就是一個(gè)三維多邊形的例子:
  
  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();
  
  3) 我們使用glMaterialfv(GL_ FRONT_AND_BACK, GL_AMBIENT, RedSurface)這個(gè)函數(shù)來(lái)定義多邊形的表面屬性,為每一個(gè)平面的前后面設(shè)置環(huán)境顏色。當(dāng)然,我們得定義光照模型,這只需在OnSize()的最后加上glEnable(GL_LIGHTING);RedSufFace是一個(gè)顏色分量數(shù)組,例如:RedSufFace[] ={1.0f,0.0f,0.0f};要定義某個(gè)平面的環(huán)境顏色,只需把glMaterialfv加在平面的定義前面即可,如上例所示。
  4) Z緩沖區(qū)的問(wèn)題:要使三維物體顯得更流暢,前后各面的空間關(guān)系正確,一定得使用Z緩沖技術(shù);否則,前后各面的位置就會(huì)相互重疊,不能正確顯示。Z緩沖區(qū)存儲(chǔ)物體每一個(gè)點(diǎn)的值,這個(gè)值表明此點(diǎn)離人眼的距離。Z緩沖需要占用大量的內(nèi)存和CPU時(shí)間。啟用Z緩沖只需在OnSize()的最后加上glEnable(GL_DEPTH_TEST);要記?。涸诿看沃乩L之前,應(yīng)使用glClear(GL_DEPTH_BUFFER_BIT)語(yǔ)句清空Z(yǔ)緩沖區(qū)。
  5) 現(xiàn)在已經(jīng)可以正確地生成三維物體了,但還需要美化,可以使物體顯得更明亮一些。我們用glLightfv函數(shù)定義光源的屬性值。下例就定義了一個(gè)光源:
  
  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);
  
  GL_LIGHT0是光源的標(biāo)識(shí)號(hào),標(biāo)識(shí)號(hào)由GL_LIGHTi組成(i從0到GL_MAX_LIGHTS)。 GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR、GL_POSITION分別定義光源的周圍顏色強(qiáng)度、光源的散射強(qiáng)度、光源的鏡面反射強(qiáng)度和光源的位置。
  本文例子較簡(jiǎn)單,VC中還有很多例子。參照本文的設(shè)置,你一定能體會(huì)到OpenGL強(qiáng)大的圖形、圖像繪制功能。
posted @ 2011-09-28 22:37 zhixing 閱讀(122) 評(píng)論(0) 編輯

opengl 旋轉(zhuǎn)三角形

// openglTestDlg.cpp : 實(shí)現(xiàn)文件

//

#include "stdafx.h"

#include "openglTest.h"

#include "openglTestDlg.h"

#include "math.h"

#pragma comment( lib, "glaux.lib")

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// 用于應(yīng)用程序“關(guān)于”菜單項(xiàng)的 CAboutDlg 對(duì)話框

class CAboutDlg : public CDialog

{

public:

CAboutDlg();

// 對(duì)話框數(shù)據(jù)

enum { IDD = IDD_ABOUTBOX };

protected:

virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 實(shí)現(xiàn)

protected:

DECLARE_MESSAGE_MAP()

};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

END_MESSAGE_MAP()

// CopenglTestDlg 對(duì)話框

CopenglTestDlg::CopenglTestDlg(CWnd* pParent /*=NULL*/)

: CDialog(CopenglTestDlg::IDD, pParent)

{

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}

void CopenglTestDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

}

BEGIN_MESSAGE_MAP(CopenglTestDlg, CDialog)

ON_WM_SYSCOMMAND()

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

//}}AFX_MSG_MAP

ON_WM_CREATE()

ON_WM_DESTROY()

ON_WM_SIZE()

ON_WM_ERASEBKGND()

ON_WM_TIMER()

ON_WM_TIMER()

END_MESSAGE_MAP()

// CopenglTestDlg 消息處理程序

BOOL CopenglTestDlg::OnInitDialog()

{

CDialog::OnInitDialog();

// 將“關(guān)于...”菜單項(xiàng)添加到系統(tǒng)菜單中。

// IDM_ABOUTBOX 必須在系統(tǒng)命令范圍內(nèi)。

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);

if (pSysMenu != NULL)

{

CString strAboutMenu;

strAboutMenu.LoadString(IDS_ABOUTBOX);

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

}

// 設(shè)置此對(duì)話框的圖標(biāo)。當(dāng)應(yīng)用程序主窗口不是對(duì)話框時(shí),框架將自動(dòng)

//  執(zhí)行此操作

SetIcon(m_hIcon, TRUE); // 設(shè)置大圖標(biāo)

SetIcon(m_hIcon, FALSE); // 設(shè)置小圖標(biāo)

///////////////////////OPENGL INIT///////////////////////// 

CWnd *wnd=GetDlgItem(IDC_RENDER); 

wnd->MoveWindow(10,10,600,500);

hrenderDC=::GetDC(wnd->m_hWnd); 

if(SetWindowPixelFormat(hrenderDC)==FALSE) 

return 0; 

if(CreateViewGLContext(hrenderDC)==FALSE) 

return 0; 

glPolygonMode(GL_FRONT,GL_FILL); 

glPolygonMode(GL_BACK,GL_FILL); 

/////////////////////////////////////////// 

glEnable(GL_TEXTURE_2D); 

glShadeModel(GL_SMOOTH); 

glViewport(0,0,600,500); 

glMatrixMode(GL_PROJECTION); 

glLoadIdentity(); 

gluPerspective(45,1,0.1,100.0); 

glMatrixMode(GL_MODELVIEW); 

glLoadIdentity(); 

glShadeModel(GL_SMOOTH);       // Enable Smooth Shading 

glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    // Black Background 

glClearDepth(1.0f);         // Depth Buffer Setup 

glEnable(GL_DEPTH_TEST);       // Enables Depth Testing 

glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do 

///////////////////////////////////////////////////////////////////////// 

glEnableClientState(GL_VERTEX_ARRAY); 

glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

SetTimer(1,50,NULL); 

//////////////////////////////////////////////////////////////// 

return TRUE;  // 除非將焦點(diǎn)設(shè)置到控件,否則返回 TRUE

}

void CopenglTestDlg::OnSysCommand(UINT nID, LPARAM lParam)

{

if ((nID & 0xFFF0) == IDM_ABOUTBOX)

{

CAboutDlg dlgAbout;

dlgAbout.DoModal();

}

else

{

CDialog::OnSysCommand(nID, lParam);

}

}

// 如果向?qū)υ捒蛱砑幼钚』粹o,則需要下面的代碼

//  來(lái)繪制該圖標(biāo)。對(duì)于使用文檔/視圖模型的 MFC 應(yīng)用程序,

//  這將由框架自動(dòng)完成。

void CopenglTestDlg::OnPaint()

{

if (IsIconic())

{

CPaintDC dc(this); // 用于繪制的設(shè)備上下文

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// 使圖標(biāo)在工作矩形中居中

int cxIcon = GetSystemMetrics(SM_CXICON);

int cyIcon = GetSystemMetrics(SM_CYICON);

CRect rect;

GetClientRect(&rect);

int x = (rect.Width() - cxIcon + 1) / 2;

int y = (rect.Height() - cyIcon + 1) / 2;

// 繪制圖標(biāo)

dc.DrawIcon(x, y, m_hIcon);

}

else

{

CDialog::OnPaint();

}

RenderScene();

}

//當(dāng)用戶拖動(dòng)最小化窗口時(shí)系統(tǒng)調(diào)用此函數(shù)取得光標(biāo)顯示。

//

HCURSOR CopenglTestDlg::OnQueryDragIcon()

{

return static_cast<HCURSOR>(m_hIcon);

}

BOOL CopenglTestDlg::SetWindowPixelFormat(HDC hDC) 

PIXELFORMATDESCRIPTOR pixelDesc; 

pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); 

pixelDesc.nVersion = 1; 

pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW |  

PFD_SUPPORT_OPENGL | 

PFD_DOUBLEBUFFER | 

PFD_TYPE_RGBA; 

pixelDesc.iPixelType = PFD_TYPE_RGBA; 

pixelDesc.cColorBits = 32; 

pixelDesc.cRedBits = 0; 

pixelDesc.cRedShift = 0; 

pixelDesc.cGreenBits = 0; 

pixelDesc.cGreenShift = 0; 

pixelDesc.cBlueBits = 0; 

pixelDesc.cBlueShift = 0; 

pixelDesc.cAlphaBits = 0; 

pixelDesc.cAlphaShift = 0; 

pixelDesc.cAccumBits = 0; 

pixelDesc.cAccumRedBits = 0; 

pixelDesc.cAccumGreenBits = 0; 

pixelDesc.cAccumBlueBits = 0; 

pixelDesc.cAccumAlphaBits = 0; 

pixelDesc.cDepthBits = 0; 

pixelDesc.cStencilBits = 1; 

pixelDesc.cAuxBuffers = 0; 

pixelDesc.iLayerType = PFD_MAIN_PLANE; 

pixelDesc.bReserved = 0; 

pixelDesc.dwLayerMask = 0; 

pixelDesc.dwVisibleMask = 0; 

pixelDesc.dwDamageMask = 0; 

PixelFormat = ChoosePixelFormat(hDC,&pixelDesc); 

if(PixelFormat==0) // Choose default 

PixelFormat = 1; 

if(DescribePixelFormat(hDC,PixelFormat, 

sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0) 

return FALSE; 

if(SetPixelFormat(hDC,PixelFormat,&pixelDesc)==FALSE) 

{  

return FALSE; 

return TRUE; 

BOOL CopenglTestDlg::CreateViewGLContext(HDC hDC) 

hrenderRC = wglCreateContext(hDC); 

if(hrenderRC==NULL) 

return FALSE; 

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

return FALSE; 

return TRUE; 

void CopenglTestDlg::RenderScene()    

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity(); 

glTranslatef(0.0f,0.0f,-5.0f);      // Move Left 1.5 Units And Into The Screen 6.0 

glRotated(m_yRotate, 0.0, 1.0, 0.0); 

glBegin(GL_TRIANGLES); // Drawing Using Triangles 

glColor3f(1.0,1.0,0.0); /* red color */

glVertex3f( 0.0f, 1.0f, -0.0f);     // Top 

glVertex3f(-0.0f,-1.0f, 1.0f);     // Bottom Left 

glVertex3f( 1.0f,-1.0f, 0.0f);     // Bottom Right 

glEnd();           // Finished Drawing The Triangle

SwapBuffers(hrenderDC); 

void CopenglTestDlg::OnTimer(UINT_PTR nIDEvent)

{

// TODO: 在此添加消息處理程序代碼和/或調(diào)用默認(rèn)值

RenderScene(); 

m_yRotate = m_yRotate + 10; 

CDialog::OnTimer(nIDEvent);

}

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
基于MFC的OpenGL繪圖
利用OpenGL添加AutoCAD中的平移與縮放功能
OpenGL(非常值得借鑒)
OpenGL VS2008 環(huán)境配置
OpenGL游戲?qū)W習(xí)一:MFC下OpenGL環(huán)境的搭建
《基于MFC的OpenGL編程》Part 11 Blending, Antialiasing and Fog
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服