熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

Visual C++中OpenGL編程入門

2013-11-13 09:42:39  來源: .NET編程 

  OpenGL作圖非常方便故日益流行但對許多人來說是在微機上進行的首先碰到的問題是如何適應微機環境這往往是最關鍵的一步雖然也是最初級的一般的我不建議使用glut 包那樣難以充分發揮 windows 的界面上的功能

  下面介紹如何在 VC++ 上進行 OpenGL 編程 OpenGL 繪圖的一般過程可以看作這樣的先用 OpenGL 語句在 OpenGL 的繪圖環境 RenderContext (RC)中畫好圖 然後再通過一個 Swap buffer 的過程把圖傳給操作系統的繪圖環境 DeviceContext (DC)中實實在在地畫出到屏幕上

  下面以畫一條 Bezier 曲線為例詳細介紹VC++ 上 OpenGL編程的方法文中給出了詳細注釋以便給初學者明確的指引一步一步地按所述去做你將順利地畫出第一個 OpenGL 平台上的圖形來

  一產生程序框架 Testdsw

New Project | MFC Application Wizard (EXE) | Test | OK
*注* : 加者指要手工敲入的字串

  二導入 Bezier 曲線類的文件

  用下面方法產生 BezierCurveh BezierCurvecpp 兩個文件

WorkSpace | ClassView | Test Classes| <右擊彈出> New Class | Generic Class(不用MFC類) | CBezierCurve | OK

  三編輯好 Bezier 曲線類的定義與實現

  寫好下面兩個文件

BezierCurveh BezierCurvecpp

  四設置編譯環境

   在 BezierCurveh 和 TestViewh 內各加上

#include <GL/glh>
#include <GL/gluh>

#include <GL/glauxh>

   在集成環境中

Project | Settings | Link | Object/library module | opengllib glulib glauxlib | OK


設置 OpenGL 工作環境(下面各個操作均針對 TestViewcpp )

   處理 PreCreateWindow(): 設置 OpenGL 繪圖窗口的風格

csstyle |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CS_OWNDC;

   處理 OnCreate():創建 OpenGL 的繪圖設備

  OpenGL 繪圖的機制是: 先用 OpenGL 的繪圖上下文 Rendering Context (簡稱為 RC )把圖畫好再把所繪結果通過 SwapBuffer() 函數傳給 Window 的 繪圖上下文 Device Context (簡記為 DC)要注意的是程序運行過程中可以有多個 DC但只能有一個 RC因此當一個 DC 畫完圖後要立即釋放 RC以便其它的 DC 也使用在後面的代碼中將有詳細注釋



int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CView::OnCreate(lpCreateStruct) == )
  return ;
 myInitOpenGL();
 return ;
}

void CTestView::myInitOpenGL()
{
 m_pDC = new CClientDC(this); //創建 DC
 ASSERT(m_pDC != NULL);
 if (!mySetupPixelFormat()) //設定繪圖的位圖格式函數下面列出
  return;

 m_hRC = wglCreateContext(m_pDC>m_hDC);//創建 RC
 wglMakeCurrent(m_pDC>m_hDC m_hRC); //RC 與當前 DC 相關聯

} //CClient * m_pDC; HGLRC m_hRC; 是 CTestView 的成員變量

BOOL CTestView::mySetupPixelFormat()
{//我們暫時不管格式的具體內容是什麼以後熟悉了再改變格式

 static PIXELFORMATDESCRIPTOR pfd =
 {
  sizeof(PIXELFORMATDESCRIPTOR) // size of this pfd
   // version number
  PFD_DRAW_TO_WINDOW | // support window
  PFD_SUPPORT_OPENGL | // support OpenGL
  PFD_DOUBLEBUFFER // double buffered
  PFD_TYPE_RGBA // RGBA type
   // bit color depth
   // color bits ignored
   // no alpha buffer
   // shift bit ignored
   // no accumulation buffer
   // accum bits ignored
   // bit zbuffer
   // no stencil buffer
   // no auxiliary buffer
  PFD_MAIN_PLANE // main layer
   // reserved
   // layer masks ignored
 };
 int pixelformat;

 if ( (pixelformat = ChoosePixelFormat(m_pDC>m_hDC &pfd)) == )
 {
  MessageBox(ChoosePixelFormat failed);
  return FALSE;
 }

 if (SetPixelFormat(m_pDC>m_hDC pixelformat &pfd) == FALSE)
 {
  MessageBox(SetPixelFormat failed);
  return FALSE;
 }

 return TRUE;




   處理 OnDestroy()


void CTestView::OnDestroy()
{
 wglMakeCurrent(m_pDC>m_hDCNULL); //釋放與m_hDC 對應的 RC
 wglDeleteContext(m_hRC); //刪除 RC
 if (m_pDC)
  delete m_pDC; //刪除當前 View 擁有的 DC
  CView::OnDestroy();



   處理 OnEraseBkgnd()


BOOL CTestView::OnEraseBkgnd(CDC* pDC)
{
 // TODO: Add your message handler code here and/or call default
 // return CView::OnEraseBkgnd(pDC);
 //把這句話注釋掉若不然Window
 //會用白色北景來刷新導致畫面閃爍
 return TRUE;//只要空返回即可



   處理 OnDraw()


void CTestView::OnDraw(CDC* pDC)
{
 wglMakeCurrent(m_pDC>m_hDCm_hRC);//使 RC 與當前 DC 相關聯
 myDrawScene( ); //具體的繪圖函數在 RC 中繪制
 SwapBuffers(m_pDC>m_hDC);//把 RC 中所繪傳到當前的 DC 上從而
 //在屏幕上顯示
 wglMakeCurrent(m_pDC>m_hDCNULL);//釋放 RC以便其它 DC 進行繪圖

}

void CTestView::myDrawScene( )
{
 glClearColor(ffff);//設置背景顏色為黑色
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 glPushMatrix();
 glTranslated(fff);//把物體沿()方向平移
 //以便投影時可見因為缺省的視點在()只有移開
 //物體才能可見
 //本例是為了演示平面 Bezier 曲線的只要作一個旋轉
 //變換可更清楚的看到其 D 效果

 //下面畫一條 Bezier 曲線
 bezier_curvemyPolygon();//畫Bezier曲線的控制多邊形
 bezier_curvemyDraw(); //CBezierCurve bezier_curve
 //是 CTestView 的成員變量
 //具體的函數見附錄
 glPopMatrix();
 glFlush(); //結束 RC 繪圖
 return;



   處理 OnSize()


void CTestView::OnSize(UINT nType int cx int cy)
{
 CView::OnSize(nType cx cy);
 VERIFY(wglMakeCurrent(m_pDC>m_hDCm_hRC));//確認RC與當前DC關聯
 w=cx;
 h=cy;
 VERIFY(wglMakeCurrent(NULLNULL));//確認DC釋放RC



   處理 OnLButtonDown()


void CTestView::OnLButtonDown(UINT nFlags CPoint point)
{
 CView::OnLButtonDown(nFlags point);
 if(bezier_curvem_N>MAX)
 {
  MessageBox(頂點個數超過了最大數MAX=);
  return;
 }

 //以下為坐標變換作准備
 GetClientRect(&m_ClientRect);//獲取視口區域大小
 w=m_ClientRectrightm_ClientRectleft;//視口寬度 w
 h=m_ClientRectbottomm_ClientRecttop;//視口高度 h
 //wh 是CTestView的成員變量
 centerx=(m_ClientRectleft+m_ClientRectright)/;//中心位置
 centery=(m_ClientRecttop+m_ClientRectbottom)/;//取之作原點
 //centerxcentery 是 CTestView 的成員變量

 GLdouble tmpxtmpy;
 tmpx=scrxglx(pointx);//屏幕上點坐標轉化為OpenGL畫圖的規范坐標
 tmpy=scrygly(pointy);

 bezier_curvem_Vertex[bezier_curvem_N]x=tmpx;//加一個頂點
 bezier_curvem_Vertex[bezier_curvem_N]y=tmpy;

 bezier_curvem_N++;//頂點數加一
 InvalidateRect(NULLTRUE);//發送刷新重繪消息

}

double CTestView::scrxglx(int scrx)
{
 return (double)(scrxcenterx)/double(h);
}

double CTestView::scrygly(int scry)
{
}



  附錄

  CBezierCurve 的聲明: (BezierCurveh)


class CBezierCurve
{
 public:
 myPOINTD m_Vertex[MAX];//控制頂點以數組存儲
 //myPOINTD 是一個存二維點的結構
 //成員為Gldouble xy
 int m_N; //控制頂點的個數
 public:
  CBezierCurve();
  virtual ~CBezierCurve();
  void bezier_generation(myPOINTD P[MAX]int level);
  //算法的具體實現
  void myDraw();//畫曲線函數
  void myPolygon(); //畫控制多邊形
};


   CBezierCurve 的實現: (BezierCurvecpp)

CBezierCurve::CBezierCurve()
{
 m_N=;
 m_Vertex[]x=f;
 m_Vertex[]y=f;
 m_Vertex[]x=f;
 m_Vertex[]y=f;
 m_Vertex[]x=f;
 m_Vertex[]y=f;
 m_Vertex[]x=f;
 m_Vertex[]y=f;
}

CBezierCurve::~CBezierCurve()
{
}

void CBezierCurve::myDraw()
{
 bezier_generation(m_VertexLEVEL);
}
void CBezierCurve::bezier_generation(myPOINTD P[MAX] int level)
{ //算法的具體描述請參考相關書本
 int ij;
 level;
 if(level<)return;
 if(level==)
 {
  glColorf(fff);
  glBegin(GL_LINES); //畫出線段
  glVertexd(P[]xP[]y);
  glVertexd(P[m_N]xP[m_N]y);
  glEnd();//結束畫線段
  return; //遞歸到了最底層跳出遞歸
 }

 myPOINTD Q[MAX]R[MAX];
 
 for(i=;i {
  Q[i]x=P[i]x;
  Q[i]y=P[i]y;
 }

 for(i=;i<m_N;i++)
 {
  R[m_Ni]x=Q[m_N]x;
  R[m_Ni]y=Q[m_N]y;
  for(j=m_N;j>=i;j)
  {
   Q[j]x=(Q[j]x+Q[j]x)/double();
   Q[j]y=(Q[j]y+Q[j]y)/double();
  }
 }
 R[]x=Q[m_N]x;
 R[]y=Q[m_N]y;

 bezier_generation(Qlevel);
 bezier_generation(Rlevel);

}

void CBezierCurve::myPolygon()
{
 glBegin(GL_LINE_STRIP); //畫出連線段
 glColorf(fff);
 for(int i=;i<m_N;i++)
 {
  glVertexd(m_Vertex[i]xm_Vertex[i]y);
 }
 glEnd();//結束畫連線段



From:http://tw.wingwit.com/Article/program/net/201311/11388.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.