首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 開發 OpenGL 入門心得:裝置內容、像素格式與繪圖內容建立全流程

     編輯:Delphi

在 Delphi 中使用 OpenGL 進行 3D 繪圖,第一步就是正確建立裝置內容 (DC)、設定像素格式 (PFD) 與繪圖內容 (RC)。本文整理作者從 C++ 轉 Delphi 開發 OpenGL 的實戰筆記,涵蓋多種 DC 取得方式、PFD 參數設定細節、RC 建立與釋放、跨平台 (NT/9x) 差異排查等關鍵知識點。

OpenGL 初始化三部曲

  1. 取得裝置內容 (HDC)
  2. 設定像素格式 (PIXELFORMATDESCRIPTOR)
  3. 建立繪圖內容 (HGLRC) 並設為當前

取得 HDC 的多種方式

// 方式 1:直接使用 Canvas.Handle (最簡單,適用於 TForm/TPaintBox)
DC := Canvas.Handle;

// 方式 2:API GetDC (需配對 ReleaseDC)
DC := GetDC(Handle);

// 方式 3:CreateCompatibleDC (離屏繪圖/列印)
// 方式 4:BeginPaint/EndPaint (WM_PAINT 中)

注意:非 Canvas.Handle 方式取得的 DC,用畢必須 ReleaseDC 或 DeleteDC 釋放,否則洩漏 GDI 物件。

像素格式設定 (PFD) 兩種寫法

寫法 A:指標配置 (需 Dispose)

function SetupPixelFormat(var DC: HDC): Boolean;
var
  ppfd: PIXELFORMATDESCRIPTOR;
  nPixelFormat: Integer;
begin
  FillChar(ppfd, SizeOf(ppfd), 0);
  ppfd.nSize := SizeOf(PIXELFORMATDESCRIPTOR);
  ppfd.nVersion := 1;
  ppfd.dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
  ppfd.iPixelType := PFD_TYPE_COLORINDEX; // 或 PFD_TYPE_RGBA
  ppfd.cColorBits := 8;
  ppfd.cDepthBits := 16;
  ppfd.cAccumBits := 0;
  ppfd.cStencilBits := 0;
  ppfd.iLayerType := PFD_MAIN_PLANE;

  nPixelFormat := ChoosePixelFormat(DC, @ppfd);
  if nPixelFormat = 0 then begin Result := False; Exit; end;

  if not SetPixelFormat(DC, nPixelFormat, @ppfd) then begin Result := False; Exit; end;

  Result := True;
end;

寫法 B:記錄體變數 (較簡潔,推薦)

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 := PFD_MAIN_PLANE;
  end;
  nPixelFormat := ChoosePixelFormat(DC, @pfd);
  SetPixelFormat(DC, nPixelFormat, @pfd);
  // 可選:DescribePixelFormat 檢查是否需調色盤
end;

關鍵 PFD 旗標說明

旗標用途
PFD_DRAW_TO_WINDOW繪製到視窗 (螢幕)
PFD_DRAW_TO_BITMAP繪製到記憶體位圖 (離屏/列印)
PFD_SUPPORT_OPENGL支援 OpenGL 呼叫
PFD_DOUBLEBUFFER雙緩衝 (動畫必備)
PFD_STEREO立體視覺 (專業顯示卡)

建立與啟用繪圖內容 (RC)


RC := wglCreateContext(DC);
wglMakeCurrent(DC, RC);

程式結束時的資源釋放順序


wglMakeCurrent(0, 0); // 解除當前 RC
if RC <> 0 then wglDeleteContext(RC);
if DC <> 0 then ReleaseDC(Handle, DC); // 若用 GetDC 取得
// 若用 Canvas.Handle 則無需釋放 DC,由 VCL 管理

跨系統 (NT vs 9x) 的像素格式陷阱

作者發現相同程式在 Windows NT 上 ChoosePixelFormat 回傳 >0,但在 Win9x 回傳 0。然而 NT 編譯的 EXE 在 9x 上卻能正常執行。推測為驅動程式對 PFD 旗標組合支援度不同。建議:

  • 開發機與目標機測試 PFD 參數組合。
  • 優先使用 PFD_TYPE_RGBA + 32 位元色彩 + 32 位元深度,相容性最佳。
  • 若 ChoosePixelFormat 失敗,嘗試移除 PFD_DOUBLEBUFFER 或降低色彩位數。

OpenGL 函數在 Delphi 中的宣告

Delphi 內建 OpenGL.pas (或 dglOpenGL.pas 第三方更新版) 已宣告所有 gl*、glu*、wgl* 函數,直接 uses OpenGL 即可呼叫,參數型別對應:GLfloat=Single, GLint=Integer, GLenum=Cardinal 等。

小結

Delphi 開發 OpenGL 的核心難點不在 OpenGL 本身,而在於正確建立與管理 Windows 圖形子系統資源 (DC/PFD/RC)。掌握 Canvas.Handle 簡化 DC 管理、PFD 旗標組合對相容性的影響、RC 生命週期綁定視窗生命週期,即可避開 90% 的初始化坑,專心投入 3D 場景開發。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved