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

来源:互联网 发布:耽美小说完结推荐知乎 编辑:程序博客网 时间:2024/04/28 22:40

 本文基础:

  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。

1 0
原创粉丝点击