QQ交流群:110826636

学习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游戏的案例

posted @ 2023-04-17 11:22  FourOne  阅读(148)  评论(1编辑  收藏  举报