最近在重學OpenGL,之所以說重學是因為上次接觸OpenGL還是在學校里,工作之后就一直在搞D3D,一轉眼已經畢業6年了.OpenGL這門手藝早就完全荒廢了,現在只能是重學.學習程序最有效的辦法是動手寫,光看書是不行了,因為看書的時候很容易陷入對人類兩大難題的思考中,以至於進展緩慢.這兩大難題是:這特媽是啥?那特媽又是啥?在重學的過程中,我翻寫了Nehe所有的OpenGL教程DEMO.本來打算把"翻寫"寫成"重構"的,但想想"重構"這個詞這么高端大氣上檔次,通常只有牛B的人和裝B的人愛提,我要是用"重構",感覺后者的嫌疑更大.
先貼出我的OpenGL作品:
軟件說明:
"WhyGL演示程序平台.exe"和"WhyGL.exe"都可以運行程序,不同之處在於,一個是基本的Windows窗體程序,一個是MFC的單文檔界面程序.
主UI界面上,鼠標點擊可以選擇要運行的DEMO
鍵盤的上下鍵也可以選擇DEMO,PageUp和PageDown用於翻頁,回車鍵用於啟動選中的DEMO
F11鍵用於全屏切換,
ESC用於退出當前DEMO及退出全屏
每個DEMO都會將提示文字信息顯示在界面上,H鍵可以隱藏文字.
軟件下載地址:
http://files.cnblogs.com/WhyEngine/WhyGL.7z
所有的DEMO都寫在同一個程序中,采用面向對象的方法,每一個DEMO都對應一個對象.Nehe的DEMO中基本上是采用全局變量,全局函數來實現,而我翻寫的程序盡量將其封裝為對象的成員變量和成員函數.之所以稱這套系統為一個框架,是因為我提供了一套學習OpenGL的平台,可以幫助3D程序的初學者更容易入門,用戶可以方便的在上面添加自己的程序.
3D程序一開始接觸會覺得很難,不過究其根本可以分為以下幾個過程:
(1)初始化渲染設備;
(2)創建渲染數據,設置渲染狀態;
(3)執行數據的處理操作;
(4)響應消息事件;
(5)渲染處理;
(6)刪除渲染數據,恢復渲染狀態;
(7)銷毀渲染設備.
在WhyGL框架中,我盡量將一些系列通用的復雜的流程封裝好,以便於用戶寫代碼時,只關心具體的渲染邏輯.這有些類似GLUT,在GLUT中將windows窗體的創建,事件處理都封裝好,用戶只填寫回調函數即可實現.在WhyGL,為用戶提供一個DEMO基類,用戶需要繼承該類,並添加自己的成員變量,重載其方法就可以繪制自己的圖形.這就如同考試時將問答題改成填空題,降低了難度.
先提供個具體的DEMO類如何寫:
FlyingHelper.h

1 #ifndef _FlyingHelper_H_ 2 #define _FlyingHelper_H_
3
4 // INCLUDES -----------------------------------------------------------------------------
5
6 #include "..\DemoGL.h"
7
8 // --------------------------------------------------------------------------------------
9
10 class CFlyingHelper : public CDemoGL 11 { 12 public: 13 CFlyingHelper(); 14
15 ~CFlyingHelper(); 16
17 // 對該對象類型的判斷
18 WHY_DEFINE_IS_KIND_OF(CFlyingHelper, CDemoGL); 19
20 // 初始化處理
21 bool Initialize(); 22
23 // 銷毀處理(刪除創建的對象,恢復GL設備狀態)
24 void Destroy(); 25
26 // 執行,用於對邏輯的處理
27 void Execute(Yuint deltaTime); 28
29 // 渲染
30 void Render(); 31
32 // UI界面的渲染
33 void RenderUI(); 34
35 // Windows系統消息響應
36 bool ProcessSystemMessage(Yuint, Yuint, Yuint); 37
38 // 返回功能說明
39 const char* GetTip() const
40 { 41 return "Flying Helper: Tell you how to create a demo."; 42 } 43
44 // 對GL設備狀態的設置
45 void InitGLStates(); 46
47 // 鍵盤事件響應
48 void OnKeyDown(Yuint key); 49
50 // 鼠標左鍵按下響應
51 void OnMouseDown(short x, short y); 52
53 // 鼠標左鍵彈起響應
54 void OnMouseUp(short x, short y); 55
56 // 鼠標移動事件響應
57 void OnMouseMove(short x, short y); 58
59 // 窗口大小變化響應
60 void OnResize(Yuint width, Yuint height); 61
62 private: 63 short m_mouseX; 64 short m_mouseY; 65 bool m_bMouseDown; 66 }; 67
68 // --------------------------------------------------------------------------------------
69
70 #endif
FlyingHelper.cpp

1 // --------------------------------------------------------------------------------------
2
3 #include "..\..\..\WhyEngine\YInterface\WhyModuleAPI.h"
4 #include "..\..\..\Interface\YicGLDevice.h"
5 #include "..\..\..\Interface\YicGLFont.h"
6 #include "..\..\..\Interface\YicGLPrimitive2DRender.h"
7 #include <gl\gl.h> // Header File For The OpenGL32 Library
8 #include <gl\glu.h> // Header File For The GLu32 Library
9 #include "FlyingHelper.h"
10
11 // --------------------------------------------------------------------------------------
12
13 #ifndef WM_MOUSEWHEEL 14 #define WM_MOUSEWHEEL 0x020A
15 #endif
16
17 // -------------------------------------------------------------------------------------- 18
19 // 將實體對象注冊到引擎(非常重要)
20 WHY_REGISTER_ENTITY(CFlyingHelper) 21
22 // --------------------------------------------------------------------------------------
23
24 CFlyingHelper::CFlyingHelper() 25 { 26 m_mouseX = 0; 27 m_mouseY = 0; 28 m_bMouseDown = false; 29 } 30
31 CFlyingHelper::~CFlyingHelper() 32 { 33 } 34
35 // 初始化處理
36 bool CFlyingHelper::Initialize() 37 { 38 if (!CDemoGL::Initialize()) 39 { 40 return false; 41 } 42
43 // ....... 44
45 // 注冊引擎的系統消息層
46 _WHY_CORE->RegisterEntityLayer(this, YE_ELAYER_WINDOWS_MESSAGE, 0x80000000); 47
48 return true; 49 } 50
51 // 銷毀處理(刪除創建的對象,恢復GL設備狀態)
52 void CFlyingHelper::Destroy() 53 { 54 // .......
55
56 CDemoGL::Destroy(); 57 } 58
59 // 執行,用於對邏輯的處理(每幀都會被執行一次)
60 void CFlyingHelper::Execute(Yuint deltaTime) 61 { 62 // .......
63 } 64
65 // 渲染(每幀都會被執行一次)
66 void CFlyingHelper::Render() 67 { 68 // .......
69 } 70
71 // UI界面的渲染(每幀都會被執行一次)
72 void CFlyingHelper::RenderUI() 73 { 74 CDemoGL::RenderUI(); 75
76 char szPos[64]; 77 sprintf(szPos, "(%d, %d)", m_mouseX, m_mouseY); 78 unsigned int color = (m_bMouseDown) ? 0xffff0000 : 0xff00ff00; 79 m_pGLFont->DrawText2D(m_mouseX, m_mouseY, color, szPos); 80 } 81
82 // Windows系統消息響應
83 bool CFlyingHelper::ProcessSystemMessage(Yuint iMsg, Yuint wParam, Yuint lParam) 84 { 85 switch (iMsg) 86 { 87 case WM_SIZE: 88 break; 89 case WM_KEYDOWN: 90 break; 91 case WM_LBUTTONDOWN: 92 break; 93 case WM_LBUTTONUP: 94 break; 95 case WM_RBUTTONDOWN: 96 break; 97 case WM_RBUTTONUP: 98 break; 99 case WM_MOUSEMOVE: 100 break; 101 case WM_MOUSEWHEEL: 102 break; 103 } 104
105 return false; 106 } 107
108 // 對GL設備狀態的設置
109 void CFlyingHelper::InitGLStates() 110 { 111 // .......
112 } 113
114 // 鍵盤事件響應
115 void CFlyingHelper::OnKeyDown(Yuint key) 116 { 117 char c[4]; 118 c[0] = (char)key; 119 c[1] = '\r'; 120 c[2] = '\n'; 121 c[3] = 0; 122 ::OutputDebugStringA(c); 123 } 124
125 // 鼠標左鍵按下響應
126 void CFlyingHelper::OnMouseDown(short x, short y) 127 { 128 m_bMouseDown = true; 129 } 130
131 // 鼠標左鍵彈起響應
132 void CFlyingHelper::OnMouseUp(short x, short y) 133 { 134 m_bMouseDown = false; 135 } 136
137 // 鼠標移動事件響應
138 void CFlyingHelper::OnMouseMove(short x, short y) 139 { 140 m_mouseX = x; 141 m_mouseY = y; 142 } 143
144 // 窗口大小變化響應
145 void CFlyingHelper::OnResize(Yuint width, Yuint height) 146 { 147 CDemoGL::OnResize(width, height); 148
149 // .......
150 }
代碼中"// ......."的部分是由用戶改寫的.
源碼下載地址:
http://pan.baidu.com/s/1bniWD0z
源碼中有4個模塊,
"SampleWin"和"WhyDemoViewer"為Windows應用程序.
"WhyGLDevice"為OpenGL的設備創建模塊,里面還實現了字體的顯示功能和簡單二維圖形顯示的功能.
"WhyTestGL"為具體的DEMO邏輯,用戶可以在這里添加自己的代碼.
程序中還需要一個模塊WhyCore這是我引擎的核心,用於對其他模塊的加載管理,不過我尚沒有將其開源的打算.
接下來要說下程序需要的兩個配置文件
WhyCore.ini是引擎的啟動文件
ModulesPath = .\dll\ DumpProcess = true CreateDumpFile = true WriteDumpLog = true MaxNumStackFrame = 10 Game = CWhyTestGL [WhyTestGL] ;DemoGL = CFlying01
[WhyTestGL] DemoGL = CFlying01 這個表示初始時將啟動哪一個DEMO,CFlying01為一個DEMO對象的類名.用該方法在調試程序時比較方便.
前面加分號;表示該行無效.
WhyTestGL.ini是DEMO的配置文件
[WhyTestGL] Nehe = OpenGL-Nehe OpenGL tutorials most of the source data sets to help you from entry to proficient in OpenGL Flying = WhyEngine Demo [Nehe] CNeheLesson01 = Press any key to change background color CNeheLesson02 = My First Polygon, Draw Triangle and Quad ......... CNeheLesson47 = CG Vertex Shader CNeheLesson48 = ArcBall Rotation [Flying] CFlyingHelper = Flying Helper: Tell you how to create a demo CFlying01 = Test YicGLPrimitive2DRender and draw some 2D graph
這里的]表示DEMO分為幾組.
然后每個字段下是DEMO對象的類名以及對應的相關信息.
用戶如果寫了自己的DEMO,請務必在WhyTestGL.INI配置文件中添加上相關信息.
-------------------------------------------------------------------------------------
最后要說的是,這個東西寫得很倉促,如果有什么BUG,請與我聯系.
[Nehe]
CNeheLesson01 OpenGL窗口 Press any key to change background color
CNeheLesson02 多邊形 My First Polygon, Draw Triangle and Quad
CNeheLesson03 添加顏色 Adding Color
CNeheLesson04 旋轉 Rotation
CNeheLesson05 3D空間 3D Shapes: Pyramid and Box
CNeheLesson06 紋理映射 Texture Mapping
CNeheLesson07 光照和鍵盤 Texture Filters, Lighting & Keyboard Control
CNeheLesson08 混合 Blending
CNeheLesson09 移動圖像 Moving Bitmaps In 3D Space
CNeheLesson10 3D世界 Loading And Moving Through A 3D World
CNeheLesson11 飄動的旗幟 Flag Effect (Waving Texture)
CNeheLesson12 顯示列表 Display List
CNeheLesson13 2D字體 Draw Text
CNeheLesson14 3D字體 Draw 3D Text
CNeheLesson15 紋理圖形字 Texture Mapped Outline Fonts
CNeheLesson16 霧 Cool Looking Fog
CNeheLesson17 2D圖像文字 2D Texture Font
CNeheLesson18 二次幾何體 Quadric Geometry
CNeheLesson19 粒子系統 Particle Engine Using Triangle Strips
CNeheLesson20 蒙板 Masking
CNeheLesson21 線的游戲 Game Crazy Grid. Lines, Antialiasing, Timing, Ortho View And Simple Sounds
CNeheLesson22 凹凸映射 Bump-Mapping, Multi-Texturing & Extensions
CNeheLesson23 球面映射 Sphere Mapping Quadrics In OpenGL
CNeheLesson24 擴展TGA紋理 Tokens, Extensions, Scissor Testing And TGA Loading
CNeheLesson25 變形 Morphing & Loading Objects From A File
CNeheLesson26 反射 Clipping & Reflections Using The Stencil Buffer
CNeheLesson27 影子 Shadows
CNeheLesson28 貝塞爾曲面 Bezier Patches / Fullscreen Fix
CNeheLesson29 Blt函數 Blitter Function, RAW Texture Loading
CNeheLesson30 碰撞檢測 Collision Detection
CNeheLesson31 模型加載 Model Loading
CNeheLesson32 拾取游戲 Shoot Game. Picking, Alpha Blending, Alpha Testing, Sorting
CNeheLesson33 TGA文件 Loading Compressed And Uncompressed TGA's
CNeheLesson34 地形 Beautiful Landscapes By Means Of Height Mapping
CNeheLesson35 播放AVI Playing AVI Files In OpenGL
CNeheLesson36 渲染到紋理 Radial Blur & Rendering To A Texture
CNeheLesson37 卡通映射 Cel-Shading
CNeheLesson38 資源文件 Butterfly Texturing Triangles
CNeheLesson39 物理模擬 Introduction to Physical Simulations
CNeheLesson40 繩子的模擬 Rope Physics
CNeheLesson41 體積霧氣 Volumetric Fog & IPicture Image Loading
CNeheLesson42 多重視口 Multiple Viewports
CNeheLesson43 FreeType庫 FreeType Fonts in OpenGL
CNeheLesson44 3D 光暈 3D Lens Flare With Occlusion Testing
CNeheLesson45 頂點緩存 Vertex Buffer Objects
CNeheLesson46 全屏反走樣 Fullscreen AntiAliasing
CNeheLesson47 CG頂點腳本 CG Vertex Shader
CNeheLesson48 軌跡球 ArcBall Rotation
[Flying]
CFlyingHelper = Flying Helper: Tell you how to create a demo
CFlying01 = Test YicGLPrimitive2DRender and draw some 2D graph