WhyGL:一套学习OpenGL的框架,及翻写Nehe的OpenGL教程
最近在重学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键可以隐藏文字.
软件下载地址:
https://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