C#+OpenGL编程之再见小桃子(The Tao Framework)

 本文基础:

  C#+OpenGL编程之OpenGL 纹理载入

  C#+OpenGL编程之OpenGL 多重纹理

  

小桃子The Tao FrameworkTao提供的所有库都是完全开源的。其中的多数库都可以免费用在商业项目中,该框架较其它框架实现更简单、容易,代码也简洁易读。

  很遗憾的是这个框架已经不再开发了,作为程序猿不得不想点其他的框架了。


  下面的课程,我们将使用另外一个框架,OpenGL DotNet 官方网站:http://www.taylaninan.com/opengl-dotnet

  作为我们的开发框架,比起 小桃子的后继者OpenTK更接近C代码风格,要知道,做什么事都要跟随大流。现在市面上的游戏引擎都是C或者C++,而很多OpenGL教程也是基于C或者C++,标新立异等于在装酷。


  首先我们实现最早的基础实例吧:

  

using System;
using System.Collections.Generic;
using System.Text;
using OpenGLDotNet;

namespace OpenGLTK
{
    ///OpenGLDotNet需要修改
    ///glut32.dll ->freeglut.dll
    ///GLUT最初是《OpenGL红皮书(第二版)》[注2]中的示例程序。自那以后,GLUT简单、跨平台的特点,使其在各种实际应用中广泛应用。
    ///目前最后版本GLUT v3.7的历史可追溯至1998年8月,且该项目似乎已经被废弃。它的许可证禁止任何人发布修改后的库代码。
    ///毋庸置疑GLUT已经很老了,真的需要改善。此外,GLUT的许可证与一些软件发行不兼容(如XFree86的)。
    ///一个轻量级的,开源的,跨平台的library。支持OpenGL及OpenGL ES,用来管理窗口,读取输入,处理事件等。因为OpenGL没有窗口管理的功能,所以很多热心的人写了工具来支持这些功能,比如早期的glut,现在的freeglut等。
    ///修改代码位置 GLU.Functions.cs


    ///找不到glu32.dll解决方法:
    ///glu32.dll 改为->GLU32.dll,具体文件名大小写可以去 系统目录搜索这个文件我的是server2012 
    ///修改代码位置 GLUT.Functions.cs

    ///tao->OpenGLDotNet 需要修改的地方
    ///函数去掉glu和gl部分,例如
    ///GL.glPopMatrix();->GL.PopMatrix();
    ///Gl.gl->GL.
    ///Gl.GL_->GL.GL_
    /// Glu.glu->GLU.
    ///当然你可以修改源代码private ->public
    ///修改代码位置 GL.CoreDelegates.cs

    /// <summary>
    /// 第二章 Opengl程序框架 C# by 大师♂罗莊
    /// 
    /// </summary>
    class Examplefirst : IDisposable
    {
         String title = "第二章 Opengl程序框架";
        ///窗口大小
        internal int windowWidth, windowHeight;
  
        //当前帧
        internal float currentTime, startTime;

        //鼠标位置
        internal int mouseX, mouseY, button,  state;
        //键盘按下

        internal byte key;
        public Examplefirst()
        {
            GLConfig.Init(0, 0, title, 25, 25, 1024, 768);
            GL.Init(true);
            GLUT.KeyboardFunc(Keyboard);
            GLUT.MouseFunc(Mouse);
            GLUT.IdleFunc(Idle);
            GLUT.ReshapeFunc(Reshape);
            GLUT.MotionFunc(Motion);
            GLUT.DisplayFunc(Display);
         }

        /// <summary>
        /// glut键盘回调函数  
        /// </summary>
        /// <param name="key"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public virtual void Keyboard(byte key, int x, int y)
        {
            this.key = key;
        }

        /// <summary>
        ///  glut鼠标按下与释放回调函数  
        /// </summary>
        /// <param name="button"></param>
        /// <param name="state"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public virtual void Mouse(int button, int state, int x, int y)
        {

            this.button = button;
            this.state = state;
            this.mouseX = x;
            this.mouseY = y;
            return;
        }

        /// <summary>
        /// glut空闲处理回调函数
        /// </summary>
        public void Idle()
        {
            currentTime = System.Environment.TickCount;
            Update(currentTime - startTime);
            startTime = currentTime;
            return;
        }

        /// <summary>
        ///  glut窗口重置回调函数  
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public void Reshape(int width, int height)
        {
            windowWidth = width;
            windowHeight = height;
            //防止除零问题
            windowHeight = windowWidth > 0 ? windowHeight : 1;
           InitGL(windowWidth, windowHeight);

        }

        /// <summary>
        /// glut鼠标移动回调函数  
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void Motion(int x, int y)
        {
            return;
        }

        /// <summary>
        /// glut描绘回调函数  
        /// </summary>
        public void Display()
        {
            //我感觉用这个得重新设置下lookUP才行
            iniView(windowWidth, windowHeight);
            DrawGLScene();
            
        }

        /// <summary>
        /// 入口点
        /// </summary>
        public void Run()
        {
            GLUT.MainLoop();
        }


        /// <summary>
        /// 更新用
        /// </summary>
        public virtual void Update(float milliseconds)
        {
            if (key == 27)                              // Escape 按下,退出
            {
                this.Dispose();
            }
            return;
        }

        /// <summary>
        /// 原书的初始化方法,C# by 大师♂罗莊
        /// </summary>
        /// <param name="windowWidth">窗口宽</param>
        /// <param name="windowHeight">窗口高</param>
        /// <returns></returns>
        Boolean InitGL(int windowWidth, int windowHeight)
        {
            // 设置视口 viewport
            GL.Viewport(0, 0, windowWidth, windowHeight);

            //启用阴影平滑
            GL.ShadeModel(GL.GL_SMOOTH);

            //启用反走样
            GL.Hint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
         
            // 设置投影模式 projection matrix
            GL.MatrixMode(GL.GL_PROJECTION);
            GL.LoadIdentity();
            GL.Disable(GL.GL_DITHER);
            return true;
        }
        /// <summary>
        /// 初始化视口投影,本例子没有采用原书例子,自定义的视口
        /// </summary>
        public virtual void iniView(int windowWidth, int windowHeight)
        {
            GLU.Perspective(65, windowWidth / (double)windowHeight, 1, 100);
            // 选择模型观察矩阵 modelview matrix
            GL.MatrixMode(GL.GL_MODELVIEW);
            //重置模型观察矩阵
            GL.LoadIdentity();
            GLU.LookAt(0, 1, 0,  // 眼睛位置
                0, 20, 0,           // 观察点
                0, 0, 1);           // 怎么看
        }

        /// <summary>
        /// 原书的绘制方法 C# by 大师♂罗莊
        /// <param name="currentTime">当前帧</param>
        /// </summary>
        public virtual void DrawGLScene()
        {
            // 重置黑色背景
            GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            GL.Clear(GL.GL_COLOR_BUFFER_BIT);
             // 画三角形
            GL.Translatef(0, 14, 0);
            GL.Begin(GL.GL_TRIANGLES);
            GL.Color3f(1, 0, 0);
            GL.Vertex3f(-5, 0, -4);
            GL.Color3f(0, 1, 0);
            GL.Vertex3f(5, 0, -4);
            GL.Color3f(0, 0, 1);
            GL.Vertex3f(0, 0, 6);
            GL.End();
            GLUT.SwapBuffers();
        }


        public void Dispose()
        {
            GLUT.KeyboardFunc(null);
            GLUT.MouseFunc(null);
            GLUT.IdleFunc(null);
            GLUT.ReshapeFunc(null);
            GLUT.MotionFunc(null);
            GLUT.DestroyWindow(GLUT.GetWindow());
        }
    }
}

   OpenGL DotNet也非十全十美,需要我们修改源代码:

  1、首先一个问题就是使用glut32.dll,这个库已经是上个世纪的库了,我们需要修改GLU.Functions.cs 里面把glut32.dll改为freeglut.dll

  2、找不到glu32.dll,这个要大家自己去windows目录看文件名大小写,在我的2012上面文件名为GLU32.dll

  然后就可以把桃子框架代码移植过来了。


  上面的代码就和C很相似了,使用GLUT函数实现窗口管理,代码量从160行升至220行。


  下面我们移植下多重纹理吧。


using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using OpenGLDotNet;

namespace OpenGLTK
{
    /// <summary>
    /// 自制的纹理载入类 C# by 大师♂罗莊
    /// </summary>
    class TextureLoad : IDisposable
    {
        public uint[] ID = new uint[3];
        Bitmap image;
        public bool Load(String fileName)
        {
            ///原则上材质只应该在初始化时候载入一次,否则会影响性能
            if (image != null)
            {
                return true;
            }
            FileInfo file = new FileInfo(fileName);
            if (file.Exists == false)
            {
                MessageBox.Show("无法载入" + fileName);
                return false;
            }
            try
            {
                if (file.Extension.ToUpper() == ".TGA")
                {
                    ///http://blog.csdn.net/zgke/article/details/4667499
                    ///C# 载入TGA 类,自行参考,这里不再列出
                    ImageTGA tga = new ImageTGA(fileName);
                    image = tga.Image;
                }
                else
                {
                    image = new Bitmap(fileName);
                }

            }
            catch (System.ArgumentException)
            {
                MessageBox.Show("无法载入" + fileName);
                return false;
            }

            if (image != null)
            {
                image.RotateFlip(RotateFlipType.RotateNoneFlipY);
                System.Drawing.Imaging.BitmapData bitmapdata;
                Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);

                ///Nearest Linear MipMapped三个纹理实现,本文暂时不考虑
                //bitmapdata = image.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                //GL.GenTextures(3, this.texture);

                //// Create Nearest Filtered Texture
                //GL.BindTexture(GL.GL_TEXTURE_2D, this.texture[0]);
                //GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
                //GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
                //GL.TexImage2D(GL.GL_TEXTURE_2D, 0, (int)GL.GL_RGB, image.Width, image.Height, 0, GL.GL_BGR_EXT, GL.GL_UNSIGNED_BYTE, bitmapdata.Scan0);
                //// Create Linear Filtered Texture
                //GL.BindTexture(GL.GL_TEXTURE_2D, this.texture[1]);
                //GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
                //GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
                //GL.TexImage2D(GL.GL_TEXTURE_2D, 0, (int)GL.GL_RGB, image.Width, image.Height, 0, GL.GL_BGR_EXT, GL.GL_UNSIGNED_BYTE, bitmapdata.Scan0);
                //// Create MipMapped Texture
                //GL.BindTexture(GL.GL_TEXTURE_2D, this.texture[2]);
                //GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
                //GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_NEAREST);
                //GL.uBuild2DMipmaps(GL.GL_TEXTURE_2D, (int)GL.GL_RGB, image.Width, image.Height, GL.GL_BGR_EXT, GL.GL_UNSIGNED_BYTE, bitmapdata.Scan0);
                //image.UnlockBits(bitmapdata);

                /** 生成纹理对象名称 */
                GL.GenTextures(3, ID);

                /** 创建纹理对象 */
                GL.BindTexture(GL.GL_TEXTURE_2D, ID[0]);

                /** 控制滤波 */
                GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, (int)GL.GL_LINEAR);
                GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, (int)GL.GL_LINEAR);
                GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, (int)GL.GL_REPEAT);
                GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, (int)GL.GL_REPEAT);

                bitmapdata = image.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                /** 创建纹理 */
                GLU.Build2DMipmaps(GL.GL_TEXTURE_2D, (int)GL.GL_RGB, image.Width,
                                  image.Height, GL.GL_BGR_EXT, GL.GL_UNSIGNED_BYTE,
                                  bitmapdata.Scan0);
                image.UnlockBits(bitmapdata);
            }
            return true;
        }

        public void FreeImage()
        {
            /** 释放内存 */
            if (image != null)
            {
                image.Dispose();
            }
        }
        public void Dispose()
        {
            FreeImage();
        }
    }
}

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using OpenGLDotNet;

namespace OpenGLTK
{
    /// <summary>
    /// 第四章 OpenGl 多重纹理载入 C# by 大师♂罗莊
    /// </summary>
    class OpenGLMultiTexture : Examplefirst
    {
        TextureLoad[] m_texture = new TextureLoad[4];
        bool multitexturing=false;
        /** 检查是否支持扩展 */
        string title = "第四章 OpenGl 多重纹理载入";

        public OpenGLMultiTexture()
            : base()
        {
            for (int i = 0; i < 4; i++)
            {
                m_texture[i] = new TextureLoad();//对象数组必须初始化
            }
            LoadTexture();
            GLUT.SetWindowTitle(title);
            /** 初始化 */
            if (!initMultiTexture())//和原来不一样,GL.GetString这个函数不能放入动画事件
            {
                MessageBox.Show("您的硬件和驱动不支持多重纹理");
                return;
            }

        }

        /// <summary>
        /// 检查多重纹理支持
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        bool isExtensionSupported(string input)
        {
            string extension = GL.GetString(GL.GL_EXTENSIONS);

            return extension.IndexOf(input)>=0;
        }

        
        bool initMultiTexture()
        {
            /** 检查是否支持扩展 */
            if (isExtensionSupported("GL_ARB_multitexture"))
            {
                return true;
            }
            else
                return false;
        }

        /** 载入纹理数据  */
        bool LoadTexture()
        {
            /// 文件名 
            String[] fileName = new String[4] { "wall.bmp", "lightmap.bmp", "bitmap.bmp", "fog.bmp" };

            /// 载入四幅位图 
            for (int i = 0; i < 4; i++)
            {
                    if (m_texture[i].Load(Path.Combine(Application.StartupPath, @"Image\" + fileName[i]).ToString()) == false)                         /**< 载入位图文件 */
                    {
                        MessageBox.Show("无法载入" + fileName[i]);
                        return false;
                    }
               

            }
            return true;

        }

        /// <summary>
        /// 初始化视口投影,恢复原书的视口
        /// </summary>
        public override void iniView(int windowWidth, int windowHeight)
        {
            GLU.Perspective(45.0f, windowWidth / windowHeight, 1.0f, 100.0f);
            GL.MatrixMode(GL.GL_MODELVIEW);
            GL.LoadIdentity();
            GLU.LookAt(0, 1, 0,  // 眼睛位置
             0, 20, 0,           // 观察点
             0, 0, 1);           // 怎么看
          
           
                      
        }

        /** 用户自定义的卸载函数 */
        public new void Dispose()
        {
            base.Dispose();
            for (int i = 0; i < 4; i++)
            {
                m_texture[i].FreeImage();
                GL.DeleteTextures(1, m_texture[i].ID);
            }
        }
        float wrap = 0;      /**< 用于雾的流动 */

        public override void Keyboard(byte key, int x, int y)
        {
            if (key == 27)                              // Escape 按下,退出
            {
                this.Dispose();
            }

            /////** 当按下空格时,开启多重纹理 */
            if (key == 0x20)
            {
                multitexturing = true;//开启
            }
            else
            {
                multitexturing = false;//按下其他键关闭
            }
        }
        /// <summary>
        /// 重载
        /// </summary>
        /// <param name="currentTime"></param>
        public override void Update(float milliseconds)
        {
            wrap += milliseconds /1000;                 //动画 速度请自己调节
            Display();
            
        }
        /// <summary>
        /// 重载,使用Draw方法绘图
        /// </summary>
        /// <param name="mouseX"></param>
        /// <param name="currentTime"></param>
        public override void DrawGLScene()
        {
            Draw();
            GLUT.SwapBuffers();
        }
    
        /** 绘制函数 */
        void Draw()
        {
            /** 用户自定义的绘制过程 */
            GL.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
            GL.LoadIdentity();

            GL.Translatef(0.0f, 0.0f, -10.0f);

            /** 激活纹理0,并绑定纹理 */
            GL.ActiveTextureARB(GL.GL_TEXTURE0_ARB);
            GL.Enable(GL.GL_TEXTURE_2D);
            GL.BindTexture(GL.GL_TEXTURE_2D, m_texture[0].ID[0]);

            /** 激活纹理1,并绑定纹理 */
            GL.ActiveTextureARB(GL.GL_TEXTURE1_ARB);

            /** 如果多重纹理启用,则启用该纹理 */
            if (multitexturing)
                GL.Enable(GL.GL_TEXTURE_2D);
            else
                GL.Disable(GL.GL_TEXTURE_2D);

            GL.BindTexture(GL.GL_TEXTURE_2D, m_texture[1].ID[0]);

            /** 绘制一个四方形墙面 */
            GL.PushMatrix();
            GL.Translatef(-2.5f, 0f, 0f);
            GL.Scalef(2.0f, 2.0f, 2.0f);
            GL.Begin(GL.GL_QUADS);

            /** 左上点 */
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 0.0f, 1.0f);
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 0.0f, 1.0f);
            GL.Vertex3f(-1, 1, 0);

            /** 左下点 */
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 0.0f, 0.0f);
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 0.0f, 0.0f);
            GL.Vertex3f(-1, -1, 0);

            /** 右下点 */
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 1.0f, 0.0f);
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 1.0f, 0.0f);
            GL.Vertex3f(1, -1, 0);

            /** 右上点 */
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 1.0f, 1.0f);
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 1.0f, 1.0f);
            GL.Vertex3f(1, 1, 0);

            GL.End();    /**< 绘制结束 */
            GL.PopMatrix();


            /** 激活纹理0,并绑定纹理 */
            GL.ActiveTextureARB(GL.GL_TEXTURE0_ARB);
            GL.Enable(GL.GL_TEXTURE_2D);
            GL.BindTexture(GL.GL_TEXTURE_2D, m_texture[2].ID[0]);

            /** 激活纹理1,并绑定纹理 */
            GL.ActiveTextureARB(GL.GL_TEXTURE1_ARB);

            /** 如果多重纹理启用,则启用该纹理 */
            if (multitexturing)
                GL.Enable(GL.GL_TEXTURE_2D);
            else
                GL.Disable(GL.GL_TEXTURE_2D);
            GL.BindTexture(GL.GL_TEXTURE_2D, m_texture[3].ID[0]);

           

            GL.Translatef(2.5f, 0, 0);
            GL.Scalef(2.0f, 2.0f, 2.0f);
            GL.Begin(GL.GL_QUADS);

            /** 左上点 */
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 0.0f, 1.0f);
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 0.0f - wrap, 1.0f);
            GL.Vertex3f(-1, 1, 0);

            /** 左下点 */
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 0.0f, 0.0f);
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 0.0f - wrap, 0.0f);
            GL.Vertex3f(-1, -1, 0);

            /** 右下点 */
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 1.0f, 0.0f);
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 1.0f - wrap, 0.0f);
            GL.Vertex3f(1, -1, 0);

            /** 右上点 */
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE0_ARB, 1.0f, 1.0f);
            GL.MultiTexCoord2fARB(GL.GL_TEXTURE1_ARB, 1.0f - wrap, 1.0f);
            GL.Vertex3f(1, 1, 0);
            GL.End();
        }
    }
}

  移植只要改改几个地方就很方便了。


  这里我再次提醒大家,因为我们用到非托管库,freeglut.dll。需要把这个DLL拷贝到应用程序目录,由于系统分32位和64位,而默认VS生成项目模板是Any CPU,也就是32、64位自适应的EXE,而OpenGLDotNet和tao 自带freeglut.dll都是32位。

  需要自己设置为X86 32位EXE,或者自行下载freeglut 编译一个64位DLL,然后做两个版本EXE。

你可能感兴趣的:(C#,framework,OpenGL,替代,the,Tao)