OpenTK介绍
OpenTK是一个开源、跨平台的游戏开发库,由MonoGame团队创建。它为C#开发者提供了一个简单易用的接口,以便使用OpenGL、OpenAL和OpenCL进行3D渲染、音频处理和并行计算。OpenTK的目标是提供一个一致且高效的框架,让开发者能够专注于构建他们的游戏和图形应用程序,而无需担心底层硬件和操作系统之间的差异。
此外,OpenTK是一个对OpenGL、OpenAL、OpenCL的跨平台封装,使用C#编写,可以运行在Windows、Linux以及MacOSX平台上,任何.Net语言都可以使用它进行开发。OpenTK具有快速开发的特点,它使用.Net的强类型和内嵌的注释文档,有助于提高代码流程,并且有助于快速发现错误。同时,OpenTK也可以单独使用,或者无缝集成到Windows Forms、WPF或GTK#等其它应用程序中。
总的来说,OpenTK是一个功能强大的跨平台游戏开发库,为C#开发者提供了便捷的开发接口和工具,使得开发者能够更加专注于游戏和图形应用程序的构建,提高了开发效率和便捷性。
OpenTK 和 OpenGL 区别。
OpenGL 是一种跨平台的图形渲染 API,用于创建 2D 和 3D 图形。它由 Khronos Group 组织维护,并支持多种编程语言和平台。OpenGL 提供了一组用于绘制图形的函数和数据类型,它们可以用于创建各种各样的图形效果,如模拟光照、纹理映射、变换等等。
OpenTK 是一个开源的跨平台的 .NET 绑定库,它提供了一组 C# 接口,用于访问 OpenGL 等底层图形 API。OpenTK 可以让 .NET 开发人员使用 C# 语言编写图形应用程序,而无需依赖于底层的 OpenGL API。
因此,可以说 OpenTK 是 OpenGL 的一个封装库,它封装了 OpenGL 的底层实现,提供了更加易用的 C# 接口。如果你使用 OpenTK,你可以使用 C# 编写 OpenGL 应用程序,而无需了解 OpenGL 的底层实现细节。
以下演示使用OpenTK框架绘制一个着色矩形,
矩形为OpenTK.Graphics.OpenGL.PrimitiveType.Quads
新建Winform应用程序OpenTKDemo,将默认的Form1重命名为FormOpenTK_GLControl
注意在WindowsForm应用程序中,需要使用框架OpenTK.GLControl
因使用.net framework4..6.1版本,没有使用.net core,这里选择OpenTK较低版本3.3.3
管理Nuget包,输入关键字OpenTK
点击安装
安装完后
窗体FormOpenTK_GLControl设计器代码如下:
文件FormOpenTK_GLControl.Designer.cs
using OpenTK;
namespace OpenTKDemo
{
partial class FormOpenTK_GLControl
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FormOpenTK_GLControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Name = "FormOpenTK_GLControl";
this.Text = "WindowsForm应用程序需要使用OpenTK.GLControl框架";
this.Load += new System.EventHandler(this.FormOpenTK_GLControl_Load);
this.ResumeLayout(false);
}
#endregion
}
}
窗体 FormOpenTK_GLControl绘制矩形相关程序如下:
文件FormOpenTK_GLControl.cs
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace OpenTKDemo
{
public partial class FormOpenTK_GLControl : Form
{
private static GameWindow gameWindow;
private static int _vao;
private static int _vbo;
private static int _shaderProgram;
public FormOpenTK_GLControl()
{
InitializeComponent();
}
private void FormOpenTK_GLControl_Load(object sender, EventArgs e)
{
using (gameWindow = new GameWindow(960, 720, GraphicsMode.Default, title: "OpenTK 斯内科"))
{
gameWindow.Load += GameWindow_Load;
gameWindow.RenderFrame += GameWindow_RenderFrame;
gameWindow.Run();
}
//Vector2
}
private void GameWindow_RenderFrame(object sender, FrameEventArgs e)
{
//图形渲染
// 清屏【红绿蓝都为1为白色,都为0为黑色】
GL.ClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
// 使用着色器并绘制矩形
GL.UseProgram(_shaderProgram);
GL.BindVertexArray(_vao);
GL.DrawArrays(PrimitiveType.Quads, 0, 4);
// 交换缓冲区
gameWindow?.SwapBuffers();
}
private void GameWindow_Load(object sender, EventArgs e)
{
// 顶点数据:矩形的顶点位置和颜色
// 【数学中的X0Y坐标系【屏幕中心为原点,X轴向右,Y轴向上】,这个与Winform的坐标系【左上角为原点,X轴向右,Y轴向下】不同】
float[] vertices = {
// Positions // Colors
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, // 顶点2:红色(位置x,y,颜色r,g,b,a)
0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, // 顶点1:红色
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 顶点3:绿色
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f // 顶点4:蓝色
};
//顶点数组对象(VAO)和顶点缓冲对象(VBO)
// 创建并绑定 VAO:Vertex Array Object
_vao = GL.GenVertexArray();
GL.BindVertexArray(_vao);
// 创建并绑定 VBO:Vertex Buffer Object
_vbo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw);
// 创建和编译着色器
_shaderProgram = CreateShaderProgram();
// 设置顶点属性指针
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 0);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 3 * sizeof(float));
GL.EnableVertexAttribArray(1);
}
private static int CreateShaderProgram()
{
// 顶点着色器代码
string vertexShaderSource = @"
#version 330 core
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aColor;
out vec3 vColor;
void main()
{
vColor = aColor;
gl_Position = vec4(aPosition, 1.0);
}
";
// 片段着色器代码
string fragmentShaderSource = @"
#version 330 core
in vec3 vColor;
out vec4 FragColor;
void main()
{
FragColor = vec4(vColor, 1.0);
}
";
// 创建和编译着色器
int vertexShader = CompileShader(ShaderType.VertexShader, vertexShaderSource);
int fragmentShader = CompileShader(ShaderType.FragmentShader, fragmentShaderSource);
// 链接着色器程序
int program = GL.CreateProgram();
GL.AttachShader(program, vertexShader);
GL.AttachShader(program, fragmentShader);
GL.LinkProgram(program);
// 检查链接错误
GL.GetProgram(program, GetProgramParameterName.LinkStatus, out int success);
if (success == 0)
{
GL.GetProgramInfoLog(program, out string info);
throw new Exception($"Shader linking failed: {info}");
}
// 删除着色器
GL.DeleteShader(vertexShader);
GL.DeleteShader(fragmentShader);
return program;
}
private static int CompileShader(ShaderType type, string source)
{
int shader = GL.CreateShader(type);
GL.ShaderSource(shader, source);
GL.CompileShader(shader);
// 检查编译错误
GL.GetShader(shader, ShaderParameter.CompileStatus, out int success);
if (success == 0)
{
GL.GetShaderInfoLog(shader, out string info);
throw new Exception($"{type} compilation failed: {info}");
}
return shader;
}
}
}