C#+OpenGL程式設計之環境搭建(windows)
現在各種引擎紅紅火火,為什麼還要開影象基礎呢?現在的遊戲開發中遊戲引擎有什麼樣的地位,是不是不可缺少的。我覺得遊戲引擎或多或少的會對遊戲開發的靈活性有一些限制。不同公司使用的引擎應該是不一樣的,有沒有必要現在就確定去學習某一種遊戲引擎?
一般來說必須用的,涉及到遊戲製作的速度質量問題。
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();
}
}
}
也就是我們的Class 就好了。
但上述方法我們是無法啟動程式的,會報缺少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