C#使用OpenTK绘制一个着色矩形

发布于:2025-02-10 ⋅ 阅读:(73) ⋅ 点赞:(0)

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;
        }
    }
}

程序运行如图:


网站公告

今日签到

点亮在社区的每一天
去签到