现在各种引擎红红火火,为什么还要开图像基础呢?现在的游戏开发中游戏引擎有什么样的地位,是不是不可缺少的。我觉得游戏引擎或多或少的会对游戏开发的灵活性有一些限制。不同公司使用的引擎应该是不一样的,有没有必要现在就确定去学习某一种游戏引擎?
一般来说必须用的,涉及到游戏制作的速度质量问题。
EA游戏为例,如果你看过FIFA、极品飞车、模拟人生等等游戏的代码,很容易看出,EA做引擎的强项就是编辑器,市面上的引擎自带的编辑器只有40%的功能,可以看出大游戏中引擎的实力。
星际2卖的是地图编辑器,这句话足以说明上面的例子。
本文并不是一个Opengl起步教程,本系列教程参考《Opengl 游戏编程》一书
对于OPENGL,C#有多个库可供选择,http://www.opengl.org/resources/bindings/,自己可以去查询,本系列教程使用The Tao Framework+.net 2.0,作为开发平台
使用版本:taoframework-2.1.0
搭建环境有两个方式,一个类似控制台程序 等同于C int main(int argc, char** argv) 。
原书使用win32方式,我们使用winform项目搭建。
启动VS,新建一个C# WindowsFormsApplication,然后新建一个class
引用taoframework 的Tao.OpenGl、Tao.Glfw 、Tao.Platform.Windows
using System; using System.Collections.Generic; using System.Text; using Tao.Glfw; using Tao.OpenGl; namespace OpenGL { /// <summary> /// 第二章 Opengl程序框架 C# by 大师♂罗莊 /// </summary> class Examplefirst : IDisposable { internal String title = "第二章 Opengl程序框架"; ///窗口大小 internal int windowWidth, windowHeight; //鼠标位置 internal int mouseX, mouseY; //是否运行 internal bool isRunning; //当前帧 internal double currentTime, startTime; public Examplefirst() { // 初始化 GLFW Glfw.glfwInit(); // 创建 OpenGL window if (Glfw.glfwOpenWindow(640, 480, 0, 0, 0, 0, 0, 0, Glfw.GLFW_WINDOW) == Gl.GL_FALSE) { //不成功,退出 Glfw.glfwTerminate(); return; } Glfw.glfwSetWindowTitle(title); // 接受按键输入 Glfw.glfwEnable(Glfw.GLFW_STICKY_KEYS); //禁用垂直同步 vertical sync Glfw.glfwSwapInterval(0); // 主循环 isRunning = true; } /// <summary> /// 入口点 /// </summary> public void Run() { //使用循环,和原书一致 while (isRunning) { // 获得鼠标位置 Glfw.glfwGetMousePos(out mouseX, out mouseY); //获得时间,将来用来做动画 currentTime = Glfw.glfwGetTime(); // 获得当前窗口大小,因为是窗口模式,用户可以改变大小 Glfw.glfwGetWindowSize(out windowWidth, out windowHeight); //防止除零问题 windowHeight = windowHeight > 0 ? windowHeight : 1; InitGL(windowWidth, windowHeight); DrawGLScene(mouseX, currentTime); // 显存交换 Glfw.glfwSwapBuffers(); Update((float)(currentTime - startTime)); startTime = currentTime; } // 结束 Glfw.glfwCloseWindow(); Glfw.glfwTerminate(); } /// <summary> /// 更新用 /// </summary> public virtual void Update(float milliseconds) { //按下ESC结束 isRunning = ((Glfw.glfwGetKey(Glfw.GLFW_KEY_ESC) == Glfw.GLFW_RELEASE) && Glfw.glfwGetWindowParam(Glfw.GLFW_OPENED) == Gl.GL_TRUE); } /// <summary> /// 原书的初始化方法,C# by 大师♂罗莊 /// </summary> /// <param name="windowWidth">窗口宽</param> /// <param name="windowHeight">窗口高</param> /// <returns></returns> Boolean InitGL(int windowWidth, int windowHeight) { // 设置视口 viewport Gl.glViewport(0, 0, windowWidth, windowHeight); //启用阴影平滑 Gl.glShadeModel(Gl.GL_SMOOTH); //启用反走样 Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST); // 重置黑色背景 Gl.glClearColor(0, 0, 0, 0); Gl.glClear(Gl.GL_COLOR_BUFFER_BIT); // 设置投影模式 projection matrix Gl.glMatrixMode(Gl.GL_PROJECTION); Gl.glLoadIdentity(); iniView(windowWidth, windowHeight); return true; } /// <summary> /// 初始化视口投影,本例子没有采用原书例子,自定义的视口 /// </summary> public virtual void iniView(int windowWidth, int windowHeight) { Glu.gluPerspective(65, windowWidth / (double)windowHeight, 1, 100); // 选择模型观察矩阵 modelview matrix Gl.glMatrixMode(Gl.GL_MODELVIEW); //重置模型观察矩阵 Gl.glLoadIdentity(); Glu.gluLookAt(0, 1, 0, // 眼睛位置 0, 20, 0, // 观察点 0, 0, 1); // 怎么看 } /// <summary> /// 原书的绘制方法 C# by 大师♂罗莊 /// <param name="mouseX">鼠标位置</param> /// <param name="currentTime">当前帧</param> /// </summary> public virtual void DrawGLScene(int mouseX, double currentTime) { // 画三角形 Gl.glTranslatef(0, 14, 0); Gl.glBegin(Gl.GL_TRIANGLES); Gl.glColor3f(1, 0, 0); Gl.glVertex3f(-5, 0, -4); Gl.glColor3f(0, 1, 0); Gl.glVertex3f(5, 0, -4); Gl.glColor3f(0, 0, 1); Gl.glVertex3f(0, 0, 6); Gl.glEnd(); } public void Dispose() { Glfw.glfwCloseWindow(); Glfw.glfwTerminate(); } } }
如果没有opengl基础,要看懂上面例子比较困难。这里要求大家学习Opengl基础了。原书用了22-70页讲述框架搭建,你看我们才160行代码。。。
首先我们要理解,我们用win32方式非命令行方式,需要大家学习win32 编程,知道我们使用消息循环,初始化 GLFW就采用这种方式。
接下来我们需要初始化OpenGL变换:
物体坐标-》模型视点矩阵-》投影矩阵-》视口变换-》屏幕
为了以后教程方便,或者说我想节省代码(XXXX)。。
我把上述过程拆分为
InitGL 初始化OpenGL,基本不会变动的
iniView 初始化 投影矩阵和模型视点矩阵
DrawGLScene 绘制场景
Update 数据更新
这几个方法,都是用virtual 函数,将来我们可以通过重载修改里面的方法实现新场景。
然后把winform 启动类Program.cs修改为
using System.Collections.Generic; using System.Text; using System; namespace OpenGL { class Program { [STAThread] static void Main(string[] args) { Examplefirst main = new Examplefirst(); main.Run(); } } }
但上述方法我们是无法启动程序的,会报缺少glfw.dll,这是因为taoframework封装C代码或者说非托管代码,我们还需要把本地代码glfw.dll拷贝到程序目录才可以运行。
大家要注意的是,本机代码分X86和X64,也就是32位和64位,taoframework自带的是32位版本,这里有两个办法:
1、将VS 项目 build- platform target的Any Cpu 修改为x86,然后使用taoframework自带的glfw.dll
或者
去glfw官方下载编译好的X86和X64版本,然后制作两个平台的EXE。
OpenGl参考资料
1. 《 OpenGL Reference Manual 》, OpenGL 参考手册
2. 《 opengl 游戏编程》作者:徐明亮,卢红星,王琬编著,机械工业出版社, 本系列教程代码均参照此书,代码下载http://down.51cto.com/data/201697
3. 《win32 OpenGL编程 》 一个大牛的博客 http://blog.csdn.net/vagrxie/article/category/628716/3
4. 《OpenGL函数思考 》 里面有很多OpenGL函数的通俗解释 http://blog.csdn.net/shuaihj