學習OpenTk,筆記七

學習OpenGL、OpenTK

1、關鍵記錄,在使用着色器的時候,記得先清理綁定,然後執行順序上,先加載着色器程序,再綁定數據,最後繪製。

GL.UseProgram(0);//清理綁定

2、開始要擴展一下Texture,想着方便2D貼圖,就在原基礎上改了一下,把VAO、VBO、EBO全部封裝在一起,代碼如下:

// 加載紋理貼圖的幫助類
    public class TexturePlus
    {
        public readonly int Handle;

        public readonly int Width;
        public readonly int Height;

        public int X;
        public int Y;

        private int _elementBufferObject;

        private int _vertexBufferObject;

        private int _vertexArrayObject;

        public static TexturePlus LoadFromFile(string path)
        {
            int handle = GL.GenTexture();
            GL.ActiveTexture(TextureUnit.Texture0);
            GL.BindTexture(TextureTarget.Texture2D, handle);
            StbImage.stbi_set_flip_vertically_on_load(1);
            int width = 0,height=0;
            using (Stream stream = File.OpenRead(path))
            {
                ImageResult image = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
                width = image.Width;
                height = image.Height;
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, image.Data);
            }

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
            GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
            return new TexturePlus(handle, width ,height);
        }

        public TexturePlus(int glHandle,int width, int height, int x = 0, int y = 0)
        {
            Handle = glHandle;
            Width = width;
            Height = height;
            Init(x, y);
        }

        private readonly uint[] _indices =
        {
            0, 1, 3,
            1, 2, 3
        };
        public uint[] Indices { get { return _indices; } }

        private float[] getVertices(int x, int y) {
            X = x;
            Y = y;
            float[] vertices = {
                Width+x, Height+y,  1.0f, 1.0f, // top right
                Width+x, 0.0f+y, 1.0f, 0.0f, // bottom right
                x, y, 0.0f, 0.0f, // bottom left
                0.0f+x,  Height+y, 0.0f, 1.0f  // top left
            };
            return vertices;
        }

        /// <summary>
        /// 所在位置
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        private void Init(int x = 0, int y = 0) {
            float[] vertices = getVertices(x,y);
            _vertexArrayObject = GL.GenVertexArray();
            GL.BindVertexArray(_vertexArrayObject);

            _vertexBufferObject = GL.GenBuffer();
            GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject);
            //GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw);
            //改成動態
            GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.DynamicDraw);

            _elementBufferObject = GL.GenBuffer();
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _elementBufferObject);
            GL.BufferData(BufferTarget.ElementArrayBuffer, _indices.Length * sizeof(uint), _indices, BufferUsageHint.StaticDraw);

            GL.EnableVertexAttribArray(0);
            GL.VertexAttribPointer(0, 4, VertexAttribPointerType.Float, false, 4 * sizeof(float), 0);

            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
            GL.BindVertexArray(0);
        }

        public void Use(TextureUnit unit = TextureUnit.Texture0)
        {
            GL.BindVertexArray(_vertexArrayObject);
            GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _elementBufferObject);

            GL.ActiveTexture(unit);
            GL.BindTexture(TextureTarget.Texture2D, Handle);
            GL.DrawElements(PrimitiveType.Triangles, this.Indices.Length, DrawElementsType.UnsignedInt, 0);
        }

        public void MovePosition(int x = 0, int y = 0) {
            var vertices = getVertices(x, y);
            GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject);
            GL.BufferSubData(BufferTarget.ArrayBuffer, System.IntPtr.Zero, sizeof(float) * vertices.Length, vertices);
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
        }

        /// <summary>
        /// 刪除紋理
        /// </summary>
        public void Remove()
        {
            GL.DeleteTexture(Handle);
        }
    }
View Code

3、要是StbImage(stb_image.h)庫有人出中文文檔就好了 (項目地址:https://github.com/nothings/stb 、https://github.com/StbSharp/StbImageSharp),也是很好學習機會

4、GLSL的版本指定(參考:https://www.cnblogs.com/OctoptusLian/p/9909170.html),版本不同,功能不同

5、OpenTK的矩陣類型是根據OpenGL的預期進行轉換的——行和列是顛倒的,在OpenGL中,矩陣是列優先的。首先應用model矩陣,再應用view矩陣,最後projection矩陣

找到的不錯學習案例

https://github.com/Samson-Mano/2DTriangle_Mesh_Generator 大量三角形生成

https://github.com/glckfndr/OpenGL_Training 大量的練習案例

https://github.com/DarthXerox/SimpleGameEngine 一個3D遊戲的案例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章