標籤: 暫無標籤

OpenGL的英文全稱是「Open Graphics Library」,顧名思義,OpenGL便是「開放的圖形程序介面」。

OpenGL

OpenGL是個專業的3D程序介面,是一個功能強大,調用方便的底層3D圖形庫。OpenGL的前身是SGI公司為其圖形工作站開發的IRIS GL。IRIS GL是一個工業標準的3D圖形軟體介面,功能雖然強大但是移植性不好,於是SGI公司便在IRIS GL的基礎上開發了OpenGL。OpenGL的英文全稱是「Open Graphics Library」,顧名思義,OpenGL便是「開放的圖形程序介面」。雖然DirectX在家用市場全面領先,但在專業高端繪圖領域,OpenGL是不能被取代的主角。

1 OpenGL -概述

OpenGL是個與.硬體無關的軟體介面,可以在不同的平台如Windows 95、Windows NT、Unix、Linux、MacOS、OS/2之間進行移植。因此,支持OpenGL的軟體具有很好的移植性,可以獲得非常廣泛的應用。由於OpenGL是3D圖形的底層圖形庫,沒有提供幾何實體圖元,不能直接用以描述場景。但是,通過一些轉換程序,可以很方便地將AutoCAD、3DS等3D圖形設計軟體製作的DFX和3DS模型文件轉換成OpenGL的頂點數組。

在OpenGL的基礎上還有Open Inventor、Cosmo3D、Optimizer等多種高級圖形庫,適應不同應用。其中,Open Inventor應用最為廣泛。該軟體是基於OpenGL面向對象的工具包,提供創建互動式3D圖形應用程序的對象和方法,提供了預定義的對象和用於交互的事件處理模塊,創建和編輯3D場景的高級應用程序單元,有列印對象和用其它圖形格式交換數據的能力。

OpenGL
OpenGL的發展一直處於一種較為遲緩的態勢,每次版本的提高新增的技術很少,大多只是對其中部分做出修改和完善。1992年7月,SGI公司發布了OpenGL的1.0版本,隨後又與微軟公司共同開發了Windows NT版本的OpenGL,從而使一些原來必須在高檔圖形工作站上運行的大型3D圖形處理軟體也可以在微機上運用。1995年OpenGL的1.1版本面市,該版本比1.0的性能有許多提高,並加入了一些新的功能。其中包括改進印表機支持,在增強元文件中包含OpenGL的調用,頂點數組的新特性,提高頂點位置、法線、顏色、色彩指數、紋理坐標、多邊形邊緣標識的傳輸速度,引入了新的紋理特性等等。OpenGL 1.5又新增了「OpenGL Shading Language」,該語言是「OpenGL 2.0」的底核,用於著色對象、頂點著色以及片斷著色技術的擴展功能。

OpenGL 2.0標準的主要制訂者並非原來的SGI,而是逐漸在ARB中佔據主動地位的3Dlabs。2.0版本首先要做的是與舊版本之間的完整兼容性,同時在頂點與像素及內存管理上與DirectX共同合作以維持均勢。OpenGL 2.0將由OpenGL 1.3的現有功能加上與之完全兼容的新功能所組成(如圖一)。藉此可以對在ARB停滯不前時代各家推出的各種糾纏不清的擴展指令集做一次徹底的精簡。此外,硬體可編程能力的實現也提供了一個更好的方法以整合現有的擴展指令。

目前,隨著DirectX的不斷發展和完善,OpenGL的優勢逐漸喪失,至今雖然已有3Dlabs提倡開發的2.0版本面世,在其中加入了很多類似於DirectX中可編程單元的設計,但廠商的用戶的認知程度並不高,未來的OpenGL發展前景迷茫。

OpenGL

2 OpenGL -用Delphi進行OpenGL編程

---- 在開發圖形程序時,尤其是三維的圖形程序,因為感覺OpenGL沒有DirectX那麼龐雜,所以選擇了DelphiOpenGL,憑感覺而言,Delphi也沒有C++那麼繁雜而且更加人性化,於是選擇Delphi+OpenGL進行工作。在這過程中,碰到(肯定會)一些問題,在此提出希望和朋友們能夠進行交流。---- 首先是初始化。初始化時,有幾項工作需要進行:①創建設備描述表(Device Context)。(註:關於DC,各種資料譯文不盡相同如設備環境、設備描述表、設備上下文等,但好象都不太貼切。要是能有李善蘭這樣的翻譯就好了。下文中的RC情形相同)②設置相應的象素格式(PIXELFORMAT DESCRIPTOR)。③創建著色描述表(Rendering Context)。 Delphi中有好幾種獲得或創建設備描述表的方法。最簡單的就是直接獲得畫布對象(TCanvas)的句柄屬性(Handle),如:DC:HDC;
DC:=Canvas.Handle;
也可以用API函數GetDC獲得設備描述表。如:
DC:=GetDC(Handle,DC);---- 也可以用函數CreateCompatibleDC或者BeginPaint..EndPaint(需要注意它們之間的區別)等來獲得設備描述表。但是設備描述表用完之後要記得釋放或刪除它,以解放資源的佔用。擁有設備描述表的使用權后,就可以設置相應的象素格式。象素格式是個記錄類型,其中有些欄位或域是沒什麼用處的(至少現在是)。象素格式描述完成後,調用ChoosePixelFormat和SetPixelFormat函數將之與設備描述表進行匹配和設置。如下面代碼:
function SetupPixelFormat(var dc:HDC):Boolean;
var
ppfd:PPIXELFORMATDESCRIPTOR;
npixelformat:Integer;
begin
New(ppfd);
ppfd^.nSize:=sizeof(PIXELFORMATDESCRIPTOR);
ppfd^.nVersion:=1;
ppfd^.dwFlags:=PFD_DRAW_TO_WINDOW
or PFD_SUPPORT_OPENGL or
PFD_DOUBLEBUFFER;
ppfd^.dwLayerMask:=PFD_MAIN_PLANE;
ppfd^.iPixelType:=PFD_TYPE_COLORINDEX;
ppfd^.cColorBits:=8;

ppfd^.cDepthBits:=16;

    ppfd^.cAccumBits:=0;

    ppfd^.cstencilBits:=0;

    npixelformat:=ChoosePixelFormat(dc, ppfd);

    if (nPixelformat=0) then

      begin

        MessageBox(NULL, 'choosePixelFormat failed',

        'Error', MB_OK);

        Result:=False;

        Exit;

      end;

    if (SetPixelFormat(dc, npixelformat, ppfd)= FALSE) then

      begin

        MessageBox(NULL, 'SetPixelFormat failed',

     'Error', MB_OK);

        Result:=False;

        Exit;

      end;

    Result:=True;

    Dispose(ppfd);

end;

也可以向下面這樣進行設置如:

var pfd: PixelFormatDescriptor;

    nPixelFormat  : Integer;

begin

  fillchar(pfd,SizeOf(pfd),0);

  with pfd do

  begin

    nSize:=sizeof(pfd);

    nVersion:=1;

dwFlags:=PFD_SUPPORT_OPENGL

 or PFD_DRAW_TO_BITMAP

                     or PFD_DOUBLEBUFFER;

    iPixelType:=PFD_TYPE_RGBA;

    cColorBits:=32;

    cDepthBits:=32;

    iLayerType:=Byte(PFD_MAIN_PLANE);

  end;

  nPixelFormat:=ChoosePixelFormat(DC,@pfd);

  SetPixelFormat(DC,nPixelFormat,@pfd);

 { // 使用DescribePixelFormat檢查象素格式是否設置正確

  DescribePixelFormat(DC,nPixelFormat,SizeOf(pfd),@pfd);

 if (pfd.dwFlags and PFD_NEED_PALETTE)

  0 then SetupPalette(DC,pfd);

//SetupPalette是自定義函數

}end; 

---- 上述工作完成以後,最好先運行一遍,並檢查nPixelFormat的值。正常的話,該值應該是大於0的,否則就有問題。同樣的代碼,我在NT機器上能夠得到正確的大於0的值而在PWIN97或98的機器上得不到正確值,但是編譯時不會有問題,而且NT上編譯后在PWIN97機器上也能夠正確運行。現在可以創建著色描述表(RC)了。調用函數wglCreateContext、wglMakeCurrent,如下例示:

RC:HGLRC;

RC:=wglCreateContext(DC);

wglMakeCurrent(DC,RC);

在程序結束之前,要記得釋放所佔用的資源。

 wglMakeCurrent(0,0);

  if RCnull then

    wglDeleteContext(RC);

  if ghDCnull then

    ReleaseDC(Handle,DC); 

---- 以下的代碼是從C++Builder 4中OpenGL的例子改寫過來的。編譯后的程序大小為300K左右,而在C++Builder 4下編譯后程序的大小為384K。
---- 程序代碼 Zip 3KB
---- 程序中的OpenGL函數及象素格式在Delphi中的MSHelp中有比較詳細的解釋,本文不敢多做解釋。

3 OpenGL -一、OPENGL的功能

OPENGL原來是工作站上的一個圖形軟體庫,由於它在商業、軍事、醫學、航天航空等領域的廣泛應用,目前在低檔電腦也可以開發出符合用戶要求的圖形。OPENGL不僅可以繪製基本圖像,而且提供了大量處理圖形圖像的函數與過程
1、圖形變換
 是圖形顯示與製作的基礎,動畫設計和動畫顯示都離不開圖形的變換,圖形變換在數學上是由矩形的乘法來實現的,變換一般包括平移、旋轉和縮放。按圖形的顯示性質來分:視點變換、模型變換、投影變換、剪裁變換和視口變換等。
2、光照效果
 不發光的物體的顏色是由物體反射外界光所形成的,這是光照。在三維圖形中,如果光照使用不當,三維圖形就會失去真實的立體感,OPENGL把光照分為:輻射光、環境光、散射光、反射光等。
3、紋理映射
 通過紋理映射可以在三維表面添加顯示現實世界中的紋理。如:一個矩形它不能表示真實世界中的物體,如果填上"本質"紋理,就逼真了。
4、圖形特效
 混合函數、反走樣函數和霧函數,可以處理三維圖形聽之任之物體的透明和半透明、使用線段理加光滑以及提供霧化的效果。
5、圖像特效
 處理點陣圖的基本函數:圖像繪製、圖像拷貝和存儲、映射和轉移、圖像的縮放等。點陣圖操作函數可以人繪圖原的低層說明中文字元的形成過程。

4 OpenGL -二、創建OPENGL應用程序

1、一般原則
 A 有uses中添加OPENGL支持單元:OpenGL;
 B 在窗體的OnCreate事件過程中初始化OPENGL;
 C 在窗口的OnPaing 事件過程中初始化OPENGL;
 D 在窗口的OnResize事件過程中初始化OPENGL;
 E 在窗口的OnDestroy 事件過程中初始化 OPENGL;
2、簡單實例
 A 創建一個工程FILE->New Application
B 在OnCreate事件中添加代碼:
procedure TfrmMain.FormCreate(Sender: TObject);
var
  pfd:TPixelFormatDescriptor;   //設置描述表
  PixelFormat:Integer;
begin
  ControlStyle:=ControlStyle+[csOpaque];
  FillChar(pfd,sizeof(pfd),0);
  with pfd do
  begin
    nSize:=sizeof(TPixelFormatDescriptor);
    nVersion:=1;
    dwFlags:=PFD_DRAW_TO_WINDOW or
        PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
    iPixelType:=PFD_TYPE_RGBA;
    cColorBits:=24;
    cDepthBits:=32;
    iLayerType:=PFD_MAIN_PLANE;
  end;
  PixelFormat:=ChoosePixelFormat(Canvas.Handle,@pfd);
  SetPixelFormat(Canvas.Handle,PixelFormat,@pfd);
  hrc:=wglCreateContext(Canvas.Handle);
  w:=ClientWidth;
  h:=ClientHeight;
end;
C 在OnDestroy事件中的代碼
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  wglDeleteContext(hrc);
end;
D 在OnPaint事件中的代碼
procedure TfrmMain.FormPaint(Sender: TObject);
begin
  wglMakeCurrent(Canvas.Handle,hrc);
  glClearColor(1,1,1,1);
  glColor3f(1,0,0);
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  MyDraw;
  glFlush;
  SwapBuffers(Canvas.Handle);
end;
E 在OnResize事件中的代碼
procedure TfrmMain.FormResize(Sender: TObject);
begin
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  glFrustum(-1.0,1.0,-1.0,1.0,3.0,7.0);
  glViewport(0,0,ClientWidth,ClientHeight);
  MyDraw;
end;
F 在MyDraw函數中的代碼(用戶在窗口類中聲明)
procedure TfrmMain.MyDraw;
begin
  glPushMatrix;
  Sphere:=gluNewQuadric;
  gluQuadricDrawStyle(Sphere,GLU_LINE);
  gluSphere(Sphere,0.5,25,25);
  glPopMatrix;
  SwapBuffers(Canvas.handle);
  gluDeleteQuadric(Sphere);
end;

附本程序原碼:
unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OpenGL;

type
  TfrmMain = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private declarations }
    hrc:HGLRC;
    w,h:glFloat;
    Sphere:GLUquadricObj;
  public
    { Public declarations }
    procedure MyDraw;
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);
var
  pfd:TPixelFormatDescriptor;
  PixelFormat:Integer;
begin
  ControlStyle:=ControlStyle+[csOpaque];
  FillChar(pfd,sizeof(pfd),0);
  with pfd do
  begin
    nSize:=sizeof(TPixelFormatDescriptor);
    nVersion:=1;
    dwFlags:=PFD_DRAW_TO_WINDOW or
        PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
    iPixelType:=PFD_TYPE_RGBA;
    cColorBits:=24;
    cDepthBits:=32;
    iLayerType:=PFD_MAIN_PLANE;
  end;
  PixelFormat:=ChoosePixelFormat(Canvas.Handle,@pfd);
  SetPixelFormat(Canvas.Handle,PixelFormat,@pfd);
  hrc:=wglCreateContext(Canvas.Handle);
  w:=ClientWidth;
  h:=ClientHeight;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  wglDeleteContext(hrc);
end;

procedure TfrmMain.FormPaint(Sender: TObject);
begin
  wglMakeCurrent(Canvas.Handle,hrc);
  glClearColor(1,1,1,1);
  glColor3f(1,0,0);
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  MyDraw;
  glFlush;
  SwapBuffers(Canvas.Handle);
end;

procedure TfrmMain.MyDraw;
begin
  glPushMatrix;
  Sphere:=gluNewQuadric;
  gluQuadricDrawStyle(Sphere,GLU_LINE);
  gluSphere(Sphere,0.5,25,25);
  glPopMatrix;
  SwapBuffers(Canvas.handle);
  gluDeleteQuadric(Sphere);
end;

procedure TfrmMain.FormResize(Sender: TObject);
begin
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  glFrustum(-1.0,1.0,-1.0,1.0,3.0,7.0);
  glViewPort(0,0,ClientWidth,ClientHeight);
  MyDraw;
end;

end.

5 OpenGL -三、OPENGL變數和函數的約定

1、OPENGL的庫約定
 它共三個庫:基本庫、實用庫、輔助庫。在DELPHI中,基本庫由OpenGL單元實現,在Windows環境中,一般不使用輔助庫。
2、OPENGL常數約定
 OPENGL常數均使用大寫字母,以"GL"開頭,辭彙之間使用下劃線分隔,如:GL_LINES,表示使用基本庫繪製直線。
3、OPENGL函數的命名約定
 A 第一部分以gl或wgl開頭,如glColor3f中的gl。
 B 第二部分是用英文表示的函數功能,單詞的首字母大寫出。
 C 第三部分是數字,表示函數的參數。
 D 第四部分是小寫字母,表示函數的類型。
b 9位整數
s 16位整數
i 32位整數
f 32位浮點數
d 64位浮點數
ub 9位無符號整數
例:glVertex2f(37,40);  {兩個32位的浮點數作參數}
glVertex3d(37,40,5); {三個64位的浮點數作參數}
   p[1..3]:array of glFloat;
glVertes3fv(p);     {3f表示三個浮點數,v表示調用一個數組作為頂點坐標輸入}

6 OpenGL -四、OPENGL的初始化

1、PIXELFORMATDESCRIPTOR結構
 主要描述像素點的性質,如像素的顏色模式和紅、綠、藍顏色構成方式等。
  tagPIXELFORMATDESCRIPTOR = packed record
    nSize: Word;
    nVersion: Word;
    dwFlags: DWORD;
    iPixelType: Byte;
    cColorBits: Byte;
    cRedBits: Byte;
    cRedShift: Byte;
    cGreenBits: Byte;
    cGreenShift: Byte;
    cBlueBits: Byte;
    cBlueShift: Byte;
    cAlphaBits: Byte;
    cAlphaShift: Byte;
    cAccumBits: Byte;
    cAccumRedBits: Byte;
    cAccumGreenBits: Byte;
    cAccumBlueBits: Byte;
    cAccumAlphaBits: Byte;
    cDepthBits: Byte;
    cStencilBits: Byte;
    cAuxBuffers: Byte;
    iLayerType: Byte;
    bReserved: Byte;
    dwLayerMask: DWORD;
    dwVisibleMask: DWORD;
    dwDamageMask: DWORD;
  end;
  TPixelFormatDescriptor = tagPIXELFORMATDESCRIPTOR;
   dwFlags代表點格式的屬性:
PFD_DRAW_TO_WINDOW 圖形繪在屏幕或設備表面
PFD_DRAW_TO_BITMAP 在內存中繪製點陣圖
PFD_SUPPORT_GDI 支持GDI繪圖
PFD_SUPPORT_OPENGL 支持OPENGL函數
PFD_DOUBLEBUFFER 使用雙緩存
PFD_STEREO 立體緩存
PFD_NEED_PALLETTE 使用RGBA調色板
PFD_GENERIC_FORMAT 選擇GDI支持的格式繪圖
PFD_NEED_SYSTEM_PALETTE 使用OPENGL支持的硬體調色板
   iPixelType設置像素顏色模式:PFD_TYPE_RGBA或PFD_TYPE_INDEX.。
   cColorBits設置顏色的位,如是9表示有256種顏色表示點的顏色。
   cRedBits、cGreenBits、cBlueBits 使用RGBA時,三原色所使用的位數。
   cRedShitfs、cGreenShifts、cBlueShifts 使用RGBA時,三原色可以調節的位數。
   cAlphaBits、cAlphaShifts 使用RGBA時,Alpha使用的位數與可調節的位數。
 cAccumBits設置累積緩存區的位面總數。
 cAccumRedBits、cAccumGreenBits、cAccumBlueBits設置累積緩存區的三原色位面總數。
 cAccumAlphaBits設置累積緩存區的Alpha位面總數。
 cDepthBits設置濃度緩存的深度。
 cStencilBits設置Stencil緩存的深度。
 cAuxBuffers指輔助緩存的大小。
 iLayerType指定層的類型。
 bReserved不使用,必須是零。
 dwLayerMask指定覆蓋層的屏蔽。
 dwDamageMask設置在相同的框架緩存下是否共用同一種像素模式。
2、OPENGL的初始化步驟
 A 使用Canvas.Handle獲得窗口句柄。
 B 創建一個TPixelFormatDescriptor變數定義像素格式。
 C 使用ChoosePixelFormat函數選擇像素格式。
 D 使用SetPixelFormat函數使用像素格式生效。
 E 使用wglCreateContext函數建立翻譯描述表。
 F 使用wglMakeCurrent函數把建立的翻譯描述表作為當前翻譯描述表。
3、資源釋放
 A 使用wglDeleteContext過程刪除像素描述表。
 B 使用ReleaseDC過程釋放窗口內存。
 在窗口的OnDestroy事件中:
 begin
  if hrcnull then
   wglDeleteCurrent(hrc);
  if hdcnull then
   ReleaseDC(Handle,hdc);
 end;

7 OpenGL -五、OPENGL基本圖形的繪製

1、圖形的顏色
 注意底色的設置,顏色設置通常與像素描述變數有關,即與TPixelFormatDescriptor定義中的iPixelType成員有關。
 iPixelType:=PFD_TYPE_COLORINDEX;
 則只能使用glIndexd,glIndexf,glIndexi,glIndexs,glIndexv,glIndexfv,glIndexiv,glIndexsv過程設置圖形顏色。
 iPixelType:=PFD_TYPE_RGBA;
 則只能使用 glColor3b,glColor3f,glColor4b,glColor4f,glColor4fv設置圖形顏色。
A 圖形底色:屏幕與窗口的顏色,即顏色緩衝區的顏色。改變圖形底色首先應使用glClearColor過程設定底色,然後使用glClear過程以這種底色刷新窗口和屏幕。
 procedure glClearColor(red:GLClampf,green:GLClampf,blue:GLClampf,alpha:GLClampf);
 procedure glClear(mask:GLBitField);
 red,green,blue,alpha是準備設置的底色,它們的取值是0到1。mask是刷新底色的方式。
例:將繪聲繪色圖窗口設置為綠色
glClearColor(0,1,0,1);
glClear(GL_COLOR_BUFFER_BIT);
mask的取值和意義:
GL_COLOR_BUFFER_BIT 設置當前的顏色緩衝
GL_DEPTH_BUFFER_BIT 設置當前的深度緩衝
GL_ACCUM_BUFFER_BIT 設置當前的積累緩衝
GL_STENCIL_BUFFER_BIT 設置當前的STENCIL(模板)緩衝
繪圖窗口設置為灰色
glClearColor(0.3,0.3,0.3,1);
glClear(GL_COLOR_BUFFER_BIT);
B 圖形顏色
 使用glClear3f與glClear4f可以設置圖形的繪製顏色。若用三個參數,則分別指設置紅、藍、綠三色光。若用四個參數,則第四個表示RGBA值。
 例設置當前的繪圖顏色為藍色:
 glColor3f(0,0,1);
 設置繪圖顏色為白色:
 glColor3f(1,1,1);
2、簡單圖形的繪製
 在glBegin與glEnd過程之間繪製簡單圖形,如點、線、多邊形等。
 glBegin(mode:GLenum);{繪製過程}glEnd;
 mode的取值:
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 繪製多邊形
 例繪製三個點:
 begin
  glPushMatrix;
  glBegin(GL_POINT);
   glVertex2f(0.1,0.1);
   glVertex2f(0.5,0.5);
   glVertex2f(0.1,0.3);
  glEnd;
  SwapBuffers(Canvas.Handle);
 end;
如果將GL_POINT改為GL_LINES,則將畫一條線.第三個點無效.在glVertex2f之前執行glColor3f(0,0,1)則將線條的顏色改為綠色. 如果將GL_LINES改為GL_LINE_STRIP則可以繪製兩條直線.
 使用glPointSize過程可以設置點的大小;使用glLineWidth過程可以設置線的寬度.
 使用glLineStipple過程設置點劃線的樣板,使用glEnable(GL_LINE_STIPPLE)過程和對應參數使繪圖能夠繪製點劃線.glDisable(GL_LINE_STIPPLE)過程和對應參數關閉點劃線.
 procedure glLineStipple(factor:GLint,pattern:GLushort);
 參數factor表示點劃線樣板Pattern的重複次數,factor取值1255,Pattern是二進位序列.
 glLineStipple(1,0,0x11C);{0x11C表示為10001110,0表示不畫點,1表示畫點}
例:   begin
  glColor3f(1,0,0);
  glLineWidth(2);
  glLineStipple(1,$11C);
  glEnable(GL_LINE_STIPPLE);
  glBegin(GL_LINES);
   glVertex2f(-0.9,0.3);
   glVertex2f(0.9,0.3);
  glEnd;
  glDisable(GL_LINE_STIPPLE);
  glColor3f(1,0,1);
  glLineStipple(2,$11C);
  glEnable(GL_LINE_STIPPLE);
  glBegin(GL_LINES);
   glVertex2f(-0.9,0.1);
   glVertex2f(0.9,0.1);
  glEnd;
  glDisable(GL_LINE_STIPPLE);
  SwapBuffers(Canvas.Handle);
 end;
 多邊形繪製與點線相似,要改變參數為GL_POLYGON,GL_QUADS,GL_TRANGLES.在繪製時的注意事項:
 A 多邊形的邊與邊只在頂點相交
 B 多邊形必須是凸多邊形,如果是凹多邊形,用戶只有折成凸多邊形,加快繪製速度.
例: glBegin(GL_POLYGON);
  glVertex2f(-0.9,0.3);
  glVertex2f(0.9,0.3);
  glVertex2f(0.9,-0.6);
  glVertex2f(0.5,-0.6);
  glVertex2f(-0.9,-0.2);
 glEnd;
多邊形有正面與反面,與之相關的過程:
glPolygonMode 控制多邊形正,反面繪圖模式
glFrontface 指定多邊形的正面
glCullFace 顯示多邊形是設置消除面
glPolygonStripple 形成多邊形填充的樣式
3、簡單二次曲面
 圓柱,圓環和球都屬於二次曲面.
A 圓柱
gluCylinder(qobj:GLUquadricObj,baseRadius:GLdouble,topRadius:GLdouble,height:GLdouble,
slices:GLint,stacks:GLint);
qobj指定一個二次曲面,baseRadius為圓柱的底半徑;topRadius為所繪製圓柱的上頂面半徑;height為圓柱的高;slices為繞Z軸的分割線數;stacks為沿Z軸的分割線數.
如果baseRadius和topRadius不相等,則可以繪製錐台與圓錐.
procedure TfrmMain.MyDraw;
var
  qObj:GLUQuadricObj;
begin
  glPushMatrix;
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glColor3f(1,0,0);
  qObj:=gluNewQuadric;
  gluQuadricDrawStyle(qObj,GLU_LINE);
  gluCylinder(qObj,0.5,0.1,0.2,10,10);
end;
B 圓環
gluDisk(qobj:GLUquadricObj,innerRadius:GLdouble,outerRadius:GLdouble,slices:GLint,
loops:GLint);
procedure TfrmMain.MyDraw;
var
  qObj:GLUQuadricObj;
begin
  glPushMatrix;
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glColor3f(1,0,0);
  qObj:=gluNewQuadric;
  gluQuadricDrawStyle(qObj,GLU_LINE);
  gluDisk(qObj,0.2,0.5,10,5);
  SwapBuffers(Canvas.Handle);
end;
C 半圓環
gluPartialDisk(qobj:GLUquadricObj,innerRadius:GLdouble,outerRadius:GLdouble,slices:GLint,
loops:GLint,startAngle:GLdouble,sweepAngle:GLdouble);
startAngle,sweepAngle是半圓環的起始角與終止角.
procedure TfrmMain.MyDraw;
var
  qObj:GLUQuadricObj;
begin
  glPushMatrix;
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glColor3f(1,0,0);
  qObj:=gluNewQuadric;
  gluQuadricDrawStyle(qObj,GLU_LINE);
  gluPartialDisk(qObj,0.2,0.5,10,5,90,190);
  SwapBuffers(Canvas.Handle);
end;
D 球體
function gluSphere(qObj:GLUquadricObj,radius:GLdouble,slices:GLint,stacks:GLint);
procedure TfrmMain.MyDraw;
var
  qObj:GLUQuadricObj;
begin
  glPushMatrix;
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glColor3f(1,0,0);
  qObj:=gluNewQuadric;
  gluQuadricDrawStyle(qObj,GLU_LINE);
{ silhouette[ silu(:)5et ]n.側面影象, 輪廓}
  gluSphere(qObj,0.5,20,20);
  SwapBuffers(Canvas.Handle);
end;
E 關於二次曲面的過程
gluNewQuadric 創建一個新的二次曲面對象
gluDeleteQuadric 刪除一個二次曲面對象
gluQuadricDrawStyle 指定要繪製的二次曲面類型
gluQuadricNormal 設置二次曲面的法矢量
gluQuadricOrientation 設置二次曲面是內旋還是外旋轉
gluQuadricTexture 設置二次曲面是否使用紋理
F 繪製二次曲面的一般步驟
 首先定義一個GLUquadricObj對象;
 其次創建一個曲面對象gluNewQuadric;
 再次設置二次曲面的特性(gluQuadricDrawStyle, gluQuadricTexture)
 繪製二次曲面(gluCylinder,gluSphere,gluDisk, gluPartialDisk)

8 OpenGL -六、OPENGL中的變換

變換是動畫設計的基礎,包括圖形的平移,旋轉,縮放等操作,在數學上是通過矩陣來實現的。
1 glLoadIdentity過程
 能夠把當前矩陣變為單位矩陣。
2 glLoadMatrix過程
 能夠把指定的矩陣設為當前矩陣。
 procedure glLoadmatrixd(m:GLdouble);
 procedure glLoadmatrixf(m:GLfloat);
 m表示4X4矩陣,下面的代碼定義並使之成為當前矩陣
 M:array[1..4,1..4] of GLfloat;
 glLoadMatrix(@M);
3 glMultMatrix過程
 能夠將當前矩與指定矩陣相乘,並把結果作為當前矩.
 procedure glMultMatrixd(M:GLdouble);
 procedure glMultMatrixf(M:GLfloat);
4 glPushMatrix和glPopmatrix
 glPushMatrix能夠把當前矩壓入矩陣堆棧, glPopMatrix能夠把當前矩彈出矩陣堆棧.
 glPushMatrix能夠記憶矩陣當前位置,glPopmatrix能夠返回以前所在的位置.
 注:glPushMatrix與glPopMatrix必須放在glBegin與glEnd之外.
5 投影變換
A glOrtho能夠創建一個正投影矩陣,把當前矩乘以該正投影矩陣,其結果作為當前矩陣.
function glOrtho(left:GLdouble,right:GLdouble,bottom:GLdouble,top:GLdouble,
near:GLdouble,far:GLdouble);
 procedure TfrmMain.FormResize(Sender: TObject);
var
  nRange:GLfloat;
begin
  nRange:=50.0;
  w:=clientWidth;
  h:=clientHeight;
  if h=0 then
    h:=1;
  glViewPort(0,0,w,h);
  if wnull then
    wglDeleteContext(hrc);
end;

end.

七、OPENGL的光照與紋理
 都是增強三維立體效果和色彩效果的手段,光照能夠增加圖形的亮度和三維效果,紋理能夠使用圖形更加趨近現實。通過使用光照,可以將物體的外觀很強列的表現出來,紋理則可以使物體顯示多種多樣的外觀。
1 光照和光源過程及應用
A glIndex過程能夠使顏色索引表中的某一種顏色成為當前顏色。
 procedure glIndexd(c:GLdouble);
 procedure glIndexf(c:GLdouble);
 procedure glIndexi(c:GLdouble);
 procedure glIndexs(c:GLdouble);
 參數C為索引值,如果使用glIndex過程,則TPiexlFormatDescriptor結構中的iPixelType成員設置為PFD_TYPE_COLORINDEX。
B glShadeModel過程
 glShadeModel過程設置填充模式,取值:GL_SMOOTH.
 procedure  glShadeModel(mode:GLenum);
 註:以上兩個過程只能在glBegin.....glEnd之外使用。
C glLight過程定義光源
 procedure glLightf(light:GLenum,pname:GLenum,param:GLfloat);
 procedure glLighti(light:GLenum,pname:GLenum,param:GLfloat);
 參數light定義光源,其值可取:GL_LIGHT0.....GL_LIGHTN,N值小於GL_MAX_LIGHT.
 參數pname指定光源參數:
GL_AMBIENT 環境光的分量強度
GL_DIFFUSE 散射光的分量強度
GL_SPECULAR 反射光的分量強度
GL_POSITION 光源位置
GL_SPOT_DIRECTION 光源的聚光方向
GL_SPOT_EXPONENT 光源的聚光指數
GL_SPOT_CUTOFF 光源的聚光方向
GL_CONSTANT_ATTENUATION 光常數衰退因子
GL_LINEAR_ATTENUATION 光二次衰減因子
 啟用和關閉光源使用glEnable()與glDisable()過程
 glEnable(GL_LIGHTING);  //啟用光源
 glDisable(GL_LIGHTING); //關閉光源
 glEnable(GL_LIGHT0);       //啟用第0個光源
 glDisable(GL_LIGHT0);      //關閉第0個光源
 設置光源的實例:
 var
  sdirection:Array[1..4] of GLfloat:={0.0,1.0,0.0,0.0};
  glLightfv(GL_LIGHT0,GL_SPOT_CUTOFF,60);
  glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,sdirection);
2 材質和光照模型
A glMaterial過程設置材質參數
 procedure  glMaterialf(face:GLenum,pname :GLenum,param:GLfloat);
 procedure  glMateriali(face:GLenum,pname :GLenum,param:GLfloat);
 procedure  glMaterialfv(face:GLenum,pname :GLenum,param:GLfloat);
 procedure  glMaterialiv(face:GLenum,pname :GLenum,param:GLfloat);
 參數face指定物體表面,它的取值:GL_FRONT,GL_BACK,GL_FRONT_BACK.
 pname,param本資料沒作介紹.
B glLightModel過程
 procedure glLightModelf(pname:GLenum,param:GLfloat);
 參數pname為光源模型參數,可以取值GL_LIGHT_MODEL_AMBIENT,
 GL_LIGHT_MODEL_LOCAL_VIEWER,GL_LIGHT_MODEL_TWO_SIDE.
實例代碼:
procedure TfrmMain.SetLighting;
var
  MaterialAmbient:array[1..4] of GLfloat;
  MaterialDiffuse:Array[1..4] of GLfloat;
  MaterialSpecular:Array[1..4] of GLfloat;
  AmbientLightPosition:Array[1..4] of GLfloat;
  LightAmbient:Array[1..4] of GLfloat;
  MaterialShininess:GLfloat;
begin
  MaterialAmbient[1]:=0.5;
  MaterialAmbient[2]:=0.8;
  MaterialAmbient[1]:=0.2;
  MaterialAmbient[1]:=1.0;

  MaterialDiffuse[1]:=0.4;
  MaterialDiffuse[2]:=0.8;
  MaterialDiffuse[3]:=0.1;
  MaterialDiffuse[4]:=1.0;

  MaterialSpecular[1]:=1.0;
  MaterialSpecular[2]:=0.5;
  MaterialSpecular[3]:=0.1;
  MaterialSpecular[4]:=1.0;

  materialShininess:=50.0;

  AmbientLightPosition[1]:=0.5;
  AmbientLightPosition[2]:=1.0;
  AmbientLightPosition[3]:=1.0;
  AmbientLightPosition[4]:=0.0;

  LightAmbient[1]:=0.5;
  LightAmbient[2]:=0.2;
  LightAmbient[3]:=0.8;
  LightAmbient[4]:=1.0;

  glMaterialfv(GL_FRONT,GL_AMBIENT,@MaterialAmbient);
  glMaterialfv(GL_FRONT,GL_DIFFUSE,@MaterialDiffuse);
  glMaterialfv(GL_FRONT,GL_SPECULAR,@MaterialSpecular);
  glMaterialfv(GL_FRONT,GL_SHININESS,@MaterialShininess);

  glLightfv(GL_LIGHT0,GL_POSITION,@AmbientLightPosition);
  glLightModelfv(GL_LIGHT_MODEL_AMBIENT,@LightAmbient);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  GLShadeModel(GL_SMOOTH);
end;
3 紋理的應用
A glTexImage1D定義一維紋理映射.
 procedure glTexImage1D(target:GLenum,level:GLint,components:GLint,width:GLsizei,
  border:GLint,format:GLenum,type:GLenum,pixels:GLvoid);
 參數targer值為GL_TEXTURE_1D,定義為紋理映射,level為多級解析度的紋理圖像的等級,width為紋理寬,值為2n,n取值為32,64,129等.border為紋理的邊界,其值為0或1,Pixel為紋理在內存中的位置.Component指定RGBA的混合和調整:
1 選擇B成分
2 選擇B,A成分
3 選擇R,G,B成分
4 選擇R,G,B,A成分
B glTexImage2D定義二維紋理映射
 procedure glTexImage2D(target:GLenum,level:GLint,components:GLint,width:GLsizei,
  border:GLint,format:GLenum,type:GLenum,pixels:GLvoid);
若參數target為GL_TEXTURE_2D,意義為二維紋理映射,height為紋理的高,函數中的其它參數與glTexImage1D相同.component參數取值同上.
實例代碼:
procedure TfrmMain.SetTextures;
var
  bits:Array[1..64,1..64,1..64] of GLubyte;
  bmp:TBitmap;
  i,j:Integer;
begin
  bmp:=TBitmap.Create;
  bmp.LoadFromFile('d:dsoft11191logon.bmp');
  for i:=1 to 64 do
    for j:=1 to 64 do
    begin
      bits[i,j,1]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));
      bits[i,j,2]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));
      bits[i,j,3]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));
      bits[i,j,4]:=255;
    end;
  {0代表為單色著色水平,GL_RGBA表示混合值
   64X64代表紋理的高和寬,0表示無邊界,
   GL_RGBA代表紋理類型,GL_UNSIGNED_TYPE代表數據類型,@代對象地址}
  glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,64,64,0,GL_RGBA,
    GL_UNSIGNED_BYTE,@bits);
  glEnable(GL_TEXTURE_2D);
end;
C glTexParameter過程設置紋理參數
 procedure glTexParameterf(target:GLenum,pname:GLenum,param:GLfloat);
 procedure glTexParameteri(target:GLenum,pname:GLenum,param:GLfloat);
 參數target代表GL_TEXTURE_1D或GL_TEXTURE_2D,param為紋理值.
D glTexEnv函數設置紋理的環境參數
 function glTexEnvf(target:GLenum,pname:GLenum,param:GLfloat);
 function glTexEnvi(target:GLenum,pname:GLenum,param:GLfloat);
 參數target為GL_TEXTURE_ENV,
參數pname為紋理參數值,取值為GL_TEXTURE_ENV_MODE
參數param為環境值,取值為GL_MODULATE,GL_DECAL和GL_BLEND.
本程序示例代碼:
unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OpenGL, ExtCtrls;

type
  TfrmMain = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormResize(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    hrc:HGLRC;
    w,h:Integer;
    latitude,longitude:GLfloat;
    radius:GLdouble;
  public
    { Public declarations }
    procedure SetLighting;
    procedure SetTextures;
    procedure MyDraw;
    procedure InitializeGL(var width:GLsizei;height:GLsizei);
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);
var
  pfd:TPixelFormatDescriptor;
  PixelFormat:Integer;
begin
  ControlStyle:=ControlStyle+[csOpaque];
  FillChar(pfd,sizeof(pfd),0);
  with pfd do
  begin
    nSize:=sizeof(TPixelFormatDescriptor);
    nVersion:=1;
    dwFlags:=PFD_DRAW_TO_WINDOW or
        PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
    iPixelType:=PFD_TYPE_RGBA;
    cColorBits:=24;
    cDepthBits:=32;
    iLayerType:=PFD_MAIN_PLANE;
  end;
  PixelFormat:=ChoosePixelFormat(Canvas.Handle,@pfd);
  SetPixelFormat(Canvas.Handle,PixelFormat,@pfd);
  hrc:=wglCreateContext(Canvas.Handle);
  w:=ClientRect.Right;
  h:=ClientRect.Bottom;
  InitializeGL(w,h);
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  wglDeleteContext(hrc);
end;

procedure TfrmMain.FormPaint(Sender: TObject);
begin
  wglMakeCurrent(Canvas.Handle,hrc);
  glClearColor(1,1,1,1);
  glColor3f(1,0,0);
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  SetTextures;
  MyDraw;
  SetLighting;
  glFlush;
end;

procedure TfrmMain.MyDraw;
var
  qObj:GLUQuadricObj;
begin
  glPushMatrix;
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glColor3f(1,0,0);
  glRotated(0.5,0.0,1.0,0.0);
  glRotated(-latitude,1.0,0.0,0.0);
  glrotated(longitude,0.0,0.0,1.0);
  qObj:=gluNewQuadric;
  gluQuadricDrawStyle(qObj,GLU_LINE);
  gluSphere(qObj,0.5,20,20);
  SwapBuffers(Canvas.Handle);
  SetLighting;
  SetTextures;
end;

{procedure TfrmMain.FormResize(Sender: TObject);
var
  nRange:GLfloat;
begin
  nRange:=50.0;
  w:=clientWidth;
  h:=clientHeight;
  if h=0 then
    h:=1;
  glViewPort(0,0,w,h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  if wnull then
    wglDeleteContext(hrc);
end;

procedure TfrmMain.SetLighting;
var
  MaterialAmbient:array[1..4] of GLfloat;
  MaterialDiffuse:Array[1..4] of GLfloat;
  MaterialSpecular:Array[1..4] of GLfloat;
  AmbientLightPosition:Array[1..4] of GLfloat;
  LightAmbient:Array[1..4] of GLfloat;
  MaterialShininess:GLfloat;
begin
  MaterialAmbient[1]:=0.5;
  MaterialAmbient[2]:=0.8;
  MaterialAmbient[1]:=0.2;
  MaterialAmbient[1]:=1.0;

  MaterialDiffuse[1]:=0.4;
  MaterialDiffuse[2]:=0.8;
  MaterialDiffuse[3]:=0.1;
  MaterialDiffuse[4]:=1.0;

  MaterialSpecular[1]:=1.0;
  MaterialSpecular[2]:=0.5;
  MaterialSpecular[3]:=0.1;
  MaterialSpecular[4]:=1.0;

  materialShininess:=50.0;

  AmbientLightPosition[1]:=0.5;
  AmbientLightPosition[2]:=1.0;
  AmbientLightPosition[3]:=1.0;
  AmbientLightPosition[4]:=0.0;

  LightAmbient[1]:=0.5;
  LightAmbient[2]:=0.2;
  LightAmbient[3]:=0.8;
  LightAmbient[4]:=1.0;

  glMaterialfv(GL_FRONT,GL_AMBIENT,@MaterialAmbient);
  glMaterialfv(GL_FRONT,GL_DIFFUSE,@MaterialDiffuse);
  glMaterialfv(GL_FRONT,GL_SPECULAR,@MaterialSpecular);
  glMaterialfv(GL_FRONT,GL_SHININESS,@MaterialShininess);

  glLightfv(GL_LIGHT0,GL_POSITION,@AmbientLightPosition);
  glLightModelfv(GL_LIGHT_MODEL_AMBIENT,@LightAmbient);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  GLShadeModel(GL_SMOOTH);
end;

procedure TfrmMain.SetTextures;
var
  bits:Array[1..64,1..64,1..64] of GLubyte;
  bmp:TBitmap;
  i,j:Integer;
begin
  bmp:=TBitmap.Create;
  bmp.LoadFromFile('d:dsoft11192logon.bmp');
  for i:=1 to 64 do
    for j:=1 to 64 do
    begin
      bits[i,j,1]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));
      bits[i,j,2]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));
      bits[i,j,3]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));
      bits[i,j,4]:=255;
    end;
  glPixelStorei(GL_UNPACK_ALIGNMENT,4);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  {0代表為單色著色水平,GL_RGBA表示混合值
   64X64代表紋理的高和寬,0表示無邊界,
   GL_RGBA代表紋理類型,GL_UNSIGNED_TYPE代表數據類型,@代對象地址}
  glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,64,64,0,GL_RGBA,
    GL_UNSIGNED_BYTE,@bits);
  glEnable(GL_TEXTURE_2D);
  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
end;

end.

9 OpenGL -參考資料




 

上一篇[斐濟元]    下一篇 [象素]

相關評論

同義詞:暫無同義詞