1. 程式人生 > >C#+OpenGL程式設計之環境搭建(windows)

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