用C# OpenGL渲染魔兽世界地图系列(一) 魔兽世界地图介绍与OpenGL环境

本文由lanbinfeng原创,转载请注明出处https://blog.csdn.net/lanbinfeng/article/details/82814952

        魔兽世界作为MMO游戏的标杆,它的渲染效果也是一直让人叹为观止的。学习它的渲染细节,尝试它的渲染方式,大概是那些要成为渲染工程师、技术美术的一条捷径吧。魔兽世界的地图是由地形、水体、建筑物、摆设物品、天空、灯光、粒子动画和模型动画组成的。本系列的文章将用C#和OpenGL去解析和渲染魔兽世界的地图。至于为什么舍近求远使用C#而非C++,大概是为了方便将其改成Unity3D导入插件吧。

        OpenGL是一组渲染接口。它只提供了在一个表面上渲染需要的相关的接口,至于怎么把表面嵌入窗口、怎么管理键鼠的输入、怎么解析和组织要渲染的资源这些它都不包含。windows只包含了OpenGL 1.0的模拟驱动,高版本的驱动则是包含在显卡驱动包里的。如果在调用OpenGL api时遇到各种异常访问,那大概就是因为你的OpenGL版本太低的缘故,我们使用的是1.4版本。

         GLU则是另一个非常流行的OpenGL的辅助库,它实现了一组实用的窗口管理、键盘鼠标输入输出、一组非常实用的功能函数。使用它能大大简化我们在周边支撑环境的开发。

         Windows中OpenGL是一组标准的WIndows API ,需要从opengl32.dll导入。VC++里有可以直接使用的头文件和LIB库,在C#中则要自己导入或者使用开源库了。我们使用的是CSGL这个库,下载地址https://excellmedia.dl.sourceforge.net/project/csgl/CsGL/1.4.1/csgl.1.4.1.dll.zip

         下载了这个库,直接在工程中引用。然后创建一个类继承自CsGL.OpenGL.OpenGLControl。再把这个组件放到Form上就可以了。代码如下:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.Controls.Add(_glView);
            _glView.Dock = DockStyle.Fill;

            GL.glMatrixMode(GL.GL_PROJECTION);
            GL.glLoadIdentity();
            GL.gluPerspective(45.0f, (double)_glView.Size.Width / (double)_glView.Size.Height, 1.0f, 1024.0f);

            GL.glMatrixMode(GL.GL_MODELVIEW);
            GL.glLoadIdentity();
            GLU.gluLookAt(5, 5, 5, 0, 0, 0, 0, 1, 0);
            GL.glEnable(GL.GL_DEPTH_TEST);

            Timer timer = new Timer();
            timer.Interval = 10;
            timer.Tick += delegate{
                _glView.glDraw();
            };
            timer.Start();
        }

        private GlView _glView = new GlView();
    }

    struct Vector3
    {
        public Vector3(float x, float y, float z)
        {
            _x = x;
            _y = y;
            _z = z;
        }
        public float _x, _y, _z;
    };

    class GlView : OpenGLControl
    {
        public override void glDraw()
        {
            GL.glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
            GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

            // 立方体的8个顶点坐标
            Vector3[] vertex_list = {
                new Vector3( -0.5f, -0.5f, -0.5f ),
                new Vector3( 0.5f, -0.5f, -0.5f ),
                new Vector3( -0.5f, 0.5f, -0.5f ),
                new Vector3( 0.5f, 0.5f, -0.5f ),
                new Vector3( -0.5f, -0.5f, 0.5f ),
                new Vector3( 0.5f, -0.5f, 0.5f ),
                new Vector3( -0.5f, 0.5f, 0.5f ),
                new Vector3( 0.5f, 0.5f, 0.5f )
             };

            int[] index_list = {
                0, 2, 3, 1,
                0, 4, 6, 2,
                0, 1, 5, 4,
                4, 5, 7, 6,
                1, 3, 7, 5,
                2, 6, 7, 3,
            };

            GL.glDisable(GL.GL_CULL_FACE);
            
            GL.glBegin(GL.GL_QUADS);
            GL.glColor3f(0.5f, 0.5f, 0.5f);
            for (int i = 0; i < 6; ++i)
            {
                for (int j = 0; j < 4; ++j)
                {
                    Vector3 pos = vertex_list[index_list[i * 4 + j]];
                    GL.glColor3f(0.1f * i, 0.1f * i, 0.1f * i);
                    GL.glVertex3f(pos._x, pos._y, pos._z);
                }
            }
            GL.glEnd();
            this.SwapBuffer();
        }
    }

运行效果:

本文由lanbinfeng原创,转载请注明出处https://blog.csdn.net/lanbinfeng/article/details/8281495

猜你喜欢

转载自blog.csdn.net/lanbinfeng/article/details/82814952