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

Windows 95/NT 下 OpenGL 程式設計原理深度解析

     編輯:關於C++

OpenGL 在 Windows 下的架構支援

科學計算視覺化、電腦動畫、虛擬實體是電腦圖形學三大熱點,核心皆為三維真實感繪圖。OpenGL (Open Graphics Library) 憑藉跨平台、簡便、高效、功能完善,已成為三維圖形事實上的工業標準。自 Windows NT 3.51 支援 OpenGL 起,Windows 95 OSR2、NT 4.0 連續提供開發環境。Visual C++ 4.2+ 完整支援 OpenGL API,使三維開發普及化。

核心概念:DC 與 RC

  • GDI 繪圖透過裝置內容 (Device Context, DC) 調用函數。
  • OpenGL 繪圖透過繪圖內容 (Rendering Context, RC) 完成三維繪圖。
  • Windows 視窗與 DC 支援像素格式 (PIXELFORMAT) 屬性,RC 與 DC 在像素結構上保持一致。
  • 建立 RC 時需與一個已設定像素格式的 DC 關聯,OpenGL 函數即可透過 RC 對應的 DC 繪製到顯示裝置。

五大關鍵限制與特性

  1. 一執行緒一 RC:一個執行緒只能擁有一個 RC。若需在同一執行緒對不同裝置繪圖,只能切換 RC 對應的 DC,RC 本身不變(刪除舊 RC 重建除外)。RC 也只能屬於一個執行緒,不可跨執行緒共享。
  2. DC 像素格式一經設定不可變更:設定 DC 像素格式等於設定視窗像素格式,一旦確定無法改變,期待未來 Windows 版本改進。
  3. RC 可切換 DC 但同一時刻僅一個當前 DC:一個視窗可讓多個 DC 繪圖,進而允許多執行緒用多個 RC 在同一視窗執行 OpenGL 操作。
  4. OpenGL 與 GDI 同 DC 繪圖有限制:使用雙緩衝做動畫時,不能在該 DC 上使用 GDI 函數繪圖。
  5. 不建議用 ANSI C 撰寫 Windows OpenGL 程式:雖具跨平台可移植性,但無法利用 Windows 特性,實用價值低。

使用 VC++ 開發 OpenGL 程式標準流程

  1. 設定 DC 像素格式:填寫 PIXELFORMATDESCRIPTOR 結構決定物理裝置屬性(如 PFD_DOUBLEBUFFER 決定是否支援雙緩衝動畫)。先用 ChoosePixelFormat 選擇 DC 支援的最接近格式,再用 SetPixelFormat 設定。
  2. 建立 RC 並關聯 DC:wglCreateContext 建立 RC,wglMakeCurrent 使 RC 與 DC 關聯成為當前。
  3. 呼叫 OpenGL 函數繪圖:因執行緒與 RC 一一對應,OpenGL 函數參數不指定 RC 控制代碼。
  4. 清理資源:先 wglMakeCurrent(NULL, NULL) 斷開關聯,判斷 RC 控制代碼有效性後 wglDeleteContext 刪除 RC,再 ReleaseDC 或 DeleteDC 處理 DC。

MFC 實作 OpenGL 關鍵注意事項

附贈程式以 MFC 完成簡單 OpenGL 繪圖(輔助庫繪製帶光源實心球),以下為 MFC 開發 OpenGL 必須注意的要點:

1. 視窗樣式必須包含 WS_CLIPCHILDREN | WS_CLIPSIBLINGS

一旦設定 DC 像素格式,其關聯視窗格式隨之固定。若視窗含子視窗或同級視窗,其像素格式未設定為與 RC 一致,OpenGL 繪圖易出錯。主框架視窗構造函數中指定:

LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, NULL, NULL);

2. 回呼函數對應 Windows 訊息處理

  • ANSI C 中 auxReshapeFunc 定義視口大小回呼 → MFC 用 WM_SIZE 處理函數。
  • ANSI C 中 auxMainLoop 定義繪圖回呼 → MFC 用 WM_PAINT 處理函數。
  • 鍵盤/滑鼠處理同理對應 WM_KEYDOWN、WM_MOUSEMOVE 等 Windows 訊息。

3. 禁止 Windows 擦除背景避免閃爍

OpenGL 有 glClear 清除背景,應禁止 Windows 自動擦除背景。否則背景色非白色時,重繪會產生一幀白色閃爍(動畫時明顯)。WM_ERASEBKGND 處理函數中直接 return TRUE 即可。

4. 調色板模式處理

OpenGL 跨平台需使用系統調色板。GL_INDEX_MODE 繪圖時必須自行定義調色板,但 GL_RGBA_MODE 較方便,鮮少用索引模式。

5. 繪圖期間 RC 對應 DC 不可刪除/釋放

6. 視窗類別建議設定 CS_OWNDC

OpenGL 佔用 DC 時間長,設定 CS_OWNDC 避免頻繁 Get/Release DC。MFC 預設未設此屬性,需在 PreCreateWindow 自行註冊視窗類別:

cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_SAVEBITS | CS_NOCLOSE | CS_OWNDC, ...);
  • CS_HREDRAW/CS_VREDRAW:視窗縮放產生 WM_PAINT,修正視口與繪圖尺寸。
  • CS_SAVEBITS:視窗被遮蓋後顯現時用記憶體圖像填充,不產生 WM_PAINT,以空間換時間。

7. OpenGL 錯誤處理

OpenGL 出錯回傳錯誤碼、不拋出異常,錯誤後續函數通常仍回傳錯誤碼,易被忽略。對每個函數檢查錯誤較繁瑣,編寫時需格外小心。

參考書籍

  • 《OpenGL Programmer's Guide》 SGI Inc.
  • 《OpenGL 三維圖形程式設計》 廖朵朵、張華軍著,星球地圖出版社
  • 《Visual C++ 5.0 線上說明》

附件:完整 MFC OpenGL 範例程式碼

程式運行需 OpenGL32.dll、glu.dll、glaux.dll 置於 Windows System 目錄。VC 專案需加入 OpenGL.h、glu.h、glaux.h 及 OpenGL.lib、glu.lib、glaux.lib (VC 自帶)。

主視窗類別定義 (OpenGLWnd.h)、實作 (OpenGLWnd.cpp)、應用程式類別 (SimpleGLApp.h/.cpp) 完整原始碼請參考原文附件,核心包含:

  • PreCreateWindow 註冊 CS_OWNDC 視窗類別
  • OnCreate 建立 DC、設定像素格式、建立 RC、初始化 OpenGL 狀態
  • OnSize 更新 glViewport 與投影矩陣
  • OnDestroy 正確清理 RC/DC
  • OnEraseBkgnd 回傳 TRUE 禁止背景擦除
  • OnPaint 執行 OpenGL 繪圖 (含光源、深度測試、auxSolidSphere)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved