學習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); } }
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遊戲的案例