当前位置: 首页 > news >正文

图形开发基础之在WinForms中使用OpenTK.GLControl进行图形绘制

在这里插入图片描述

前言

GLControl 是 OpenTK 库中一个重要的控件,专门用于在 Windows Forms 应用程序中集成 OpenGL 图形渲染。通过 GLControl,可以轻松地将 OpenGL 的高性能图形绘制功能嵌入到传统的桌面应用程序中。

1. GLControl 的核心功能

  • OpenGL 渲染上下文: 提供一个 OpenGL 上下文,用于调用 OpenGL 的绘图函数。
  • 与 WinForms 集成: 能嵌入到 WinForms 界面中,与其他控件如按钮、文本框一起使用。
  • 双缓冲支持: 默认启用双缓冲以减少画面撕裂。
  • 硬件加速支持: 自动利用 GPU 的并行计算能力以实现高效渲染。

2. GLControl 的典型使用场景

  1. 实时图形渲染: 游戏开发、3D 数据可视化。
  2. 科学计算可视化: 例如绘制复杂函数曲面、模拟物理系统等。
  3. CAD/建模工具: 提供交互式的 3D 建模功能。
  4. 教学演示: 展示 OpenGL 图形渲染的基本原理和实现方法。

3. GLControl 的主要属性和方法

主要属性

属性描述
Context获取 OpenGL 渲染上下文。
GraphicsMode指定 OpenGL 渲染模式(颜色深度、模板缓冲、抗锯齿等)。
IsIdle指示当前控件是否处于空闲状态,可以用于控制渲染循环。
MakeCurrent()将当前 OpenGL 上下文切换到此控件。
SwapBuffers()交换前缓冲区和后缓冲区,用于实现双缓冲渲染。

主要事件

事件描述
Load在控件加载时触发,用于初始化 OpenGL 配置。
Resize在控件大小调整时触发,用于重新设置视口尺寸。
Paint在控件需要重新绘制时触发,调用 OpenGL 的绘图逻辑。

在这里插入图片描述

4. 使用 GLControl 的完整示例代码

以下代码展示了如何在 Windows Forms 中使用 GLControl 实现鼠标控制旋转的三角锥(四面体)。

环境准备和引用库

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>WinExe</OutputType><TargetFramework>net8.0-windows</TargetFramework><Nullable>enable</Nullable><UseWindowsForms>true</UseWindowsForms><ImplicitUsings>enable</ImplicitUsings></PropertyGroup><ItemGroup><PackageReference Include="OpenTK" Version="5.0.0-pre.13" /><PackageReference Include="OpenTK.Core" Version="5.0.0-pre.13" /><PackageReference Include="OpenTK.Mathematics" Version="5.0.0-pre.13" /><PackageReference Include="OpenTK.GLControl" Version="4.0.1" /><PackageReference Include="OpenTK.Windowing.Common" Version="5.0.0-pre.13" /><PackageReference Include="OpenTK.Windowing.Desktop" Version="5.0.0-pre.13" /></ItemGroup>
</Project>

主窗体代码

using OpenTK.GLControl;
using OpenTK.Graphics.OpenGL;
using OpenTK.Mathematics;namespace GLControlExample
{public partial class Form1 : Form{private GLControl glControl;private int vao, vbo, shaderProgram;private Matrix4 model, view, projection;private float rotationX = 0.0f, rotationY = 0.0f; // 旋转角度private bool isDragging = false;private Point lastMousePosition;public Form1(){InitializeComponent();// 创建 GLControlglControl = new GLControl{Dock = DockStyle.Fill};Controls.Add(glControl);// 绑定事件glControl.Load += GlControl_Load;glControl.Paint += GlControl_Paint;glControl.Resize += GlControl_Resize;glControl.MouseDown += GlControl_MouseDown;glControl.MouseUp += GlControl_MouseUp;glControl.MouseMove += GlControl_MouseMove;}private void GlControl_Load(object sender, EventArgs e){// 设置清屏颜色GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);// 初始化 VAO 和 VBOvao = GL.GenVertexArray();vbo = GL.GenBuffer();GL.BindVertexArray(vao);float[] vertices = {// 顶点位置       // 颜色0.0f,  0.5f,  0.0f,  1.0f, 0.0f, 0.0f, // 顶点1-0.5f, -0.5f,  0.5f,  0.0f, 1.0f, 0.0f, // 顶点20.5f, -0.5f,  0.5f,  0.0f, 0.0f, 1.0f, // 顶点30.0f, -0.5f, -0.5f,  1.0f, 1.0f, 0.0f  // 顶点4};int[] indices = {0, 1, 2, // 正面0, 2, 3, // 右面0, 3, 1, // 左面1, 3, 2  // 底面};int ebo = GL.GenBuffer();GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsage.StaticDraw);GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo);GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length * sizeof(int), indices, BufferUsage.StaticDraw);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);// 创建并编译着色器string vertexShaderSource = @"#version 330 corelayout (location = 0) in vec3 aPosition;layout (location = 1) in vec3 aColor;out vec3 vertexColor;uniform mat4 model;uniform mat4 view;uniform mat4 projection;void main(){gl_Position = projection * view * model * vec4(aPosition, 1.0);vertexColor = aColor;}";string fragmentShaderSource = @"#version 330 corein vec3 vertexColor;out vec4 FragColor;void main(){FragColor = vec4(vertexColor, 1.0);}";int vertexShader = CompileShader(ShaderType.VertexShader, vertexShaderSource);int fragmentShader = CompileShader(ShaderType.FragmentShader, fragmentShaderSource);shaderProgram = GL.CreateProgram();GL.AttachShader(shaderProgram, vertexShader);GL.AttachShader(shaderProgram, fragmentShader);GL.LinkProgram(shaderProgram);// 删除着色器GL.DeleteShader(vertexShader);GL.DeleteShader(fragmentShader);// 初始化矩阵view = Matrix4.LookAt(new Vector3(0.0f, 0.0f, 2.0f), Vector3.Zero, Vector3.UnitY);projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45.0f), glControl.Width / (float)glControl.Height, 0.1f, 100.0f);GL.BindVertexArray(0);}private void GlControl_Resize(object sender, EventArgs e){GL.Viewport(0, 0, glControl.Width, glControl.Height);projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45.0f), glControl.Width / (float)glControl.Height, 0.1f, 100.0f);}private void GlControl_Paint(object sender, PaintEventArgs e){// 清屏GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);// 绘制三角锥GL.UseProgram(shaderProgram);model = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(rotationX)) *Matrix4.CreateRotationY(MathHelper.DegreesToRadians(rotationY));GL.UniformMatrix4f(GL.GetUniformLocation(shaderProgram, "model"),1, false, ref model);GL.UniformMatrix4f(GL.GetUniformLocation(shaderProgram, "view"), 1, false, ref view);GL.UniformMatrix4f(GL.GetUniformLocation(shaderProgram, "projection"), 1, false, ref projection);GL.BindVertexArray(vao);GL.DrawElements(PrimitiveType.Triangles, 12, DrawElementsType.UnsignedInt, 0);glControl.SwapBuffers();}private void GlControl_MouseDown(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left){isDragging = true;lastMousePosition = e.Location;}}private void GlControl_MouseUp(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left){isDragging = false;}}private void GlControl_MouseMove(object sender, MouseEventArgs e){if (isDragging){int deltaX = e.X - lastMousePosition.X;int deltaY = e.Y - lastMousePosition.Y;rotationX += deltaY * 0.5f;rotationY += deltaX * 0.5f;lastMousePosition = e.Location;glControl.Invalidate();}}private int CompileShader(ShaderType type, string source){int shader = GL.CreateShader(type);GL.ShaderSource(shader, source);GL.CompileShader(shader);GL.GetShaderi(shader, ShaderParameterName.CompileStatus, out int status);if (status == 0){GL.GetShaderInfoLog(shader, out string infoLog);throw new Exception($"Error compiling shader ({type}): {infoLog}");}return shader;}}
}

启动程序

using System;
using System.Windows.Forms;namespace GLControlExample
{static class Program{[STAThread]static void Main(){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);Application.Run(new Form1());}}
}

在这里插入图片描述

5. 性能优势

  • 硬件加速: GLControl 能直接利用 GPU 的并行计算能力,大幅提升复杂场景的渲染效率。
  • 现代 OpenGL 特性: 支持着色器编程、帧缓冲、深度测试等现代图形技术。
  • 与 UI 的无缝集成: 在嵌入 WinForms 界面的同时,保持强大的图形渲染能力。

结语

通过本文,可以了解如何使用 OpenTK.GLControl 进行图形绘制,并掌握GLControl 基本用法,通过硬件加速是实现高效图形渲染。

相关文章:

图形开发基础之在WinForms中使用OpenTK.GLControl进行图形绘制

前言 GLControl 是 OpenTK 库中一个重要的控件&#xff0c;专门用于在 Windows Forms 应用程序中集成 OpenGL 图形渲染。通过 GLControl&#xff0c;可以轻松地将 OpenGL 的高性能图形绘制功能嵌入到传统的桌面应用程序中。 1. GLControl 的核心功能 OpenGL 渲染上下文&…...

离散数学重点复习

第一章.集合论 概念 1.集合是不能精确定义的基本数学概念.通常是由指定范围内的满足给定条件的所有对象聚集在一起构成的 2.制定范围内的每一个对象称为这个集合的元素 3.固定符号如下: N:自然数集合 Z:整数集合 Q:有理数集合 R:实数集合 C:复数集合 4.集合中的元素是…...

Javaweb梳理21——Servlet

Javaweb梳理21——Servlet 21 Servlet21.1 简介21.3 执行流程21.4 生命周期4.5 方法介绍21.6 体系结构21.7 urlPattern配置21.8 XML配置 21 Servlet 21.1 简介 Servlet是JavaWeb最为核心的内容&#xff0c;它是Java提供的一门动态web资源开发技术。使用Servlet就可以实现&…...

推荐学习笔记:矩阵补充和矩阵分解

参考&#xff1a; 召回 fun-rec/docs/ch02/ch2.1/ch2.1.1/mf.md at master datawhalechina/fun-rec GitHub 业务 隐语义模型与矩阵分解 协同过滤算法的特点&#xff1a; 协同过滤算法的特点就是完全没有利用到物品本身或者是用户自身的属性&#xff0c; 仅仅利用了用户与…...

etcd分布式存储系统快速入门指南

在分布式系统的复杂世界中&#xff0c;确保有效的数据管理至关重要。分布式可靠的键值存储在维护跨分布式环境的数据一致性和可伸缩性方面起着关键作用。 在这个全面的教程中&#xff0c;我们将深入研究etcd&#xff0c;这是一个开源的分布式键值存储。我们将探索其基本概念、特…...

解决VUE3 Vite打包后动态图片资源不显示问题

解决VUE3 Vite打包后动态图片资源不显示问题 <script setup> let url ref()const setimg (item)>{let src ../assets/image/${e}.pngurl.value src }</script><template><div v-for"item in 6"><h1 click"setimg(item)"…...

大数据新视界 -- 大数据大厂之 Hive 临时表与视图:灵活数据处理的技巧(上)(29 / 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

Android学习14--charger

1 概述 最近正好在做关机充电这个&#xff0c;就详细看看吧。还是本着保密的原则&#xff0c;项目里的代码也不能直接用&#xff0c;这里就用的Github的。https://github.com/aosp-mirror 具体位置是&#xff1a;https://github.com/aosp-mirror/platform_system_core/tree/mai…...

页面开发样式和布局入门:Vite + Vue 3 + Less

页面开发样式和布局入门&#xff1a;Vite Vue 3 Less 引言 在现代前端开发中&#xff0c;样式和布局是页面开发的核心部分。随着技术的不断发展&#xff0c;Vite、Vue 3和Less等工具和框架的出现&#xff0c;使得前端开发变得更加高效和灵活。然而&#xff0c;尽管这些工具…...

瑞芯微RK3566/RK3568开发板安卓11固件ROOT教程,Purple Pi OH演示

本文介绍RK3566/RK3568开发板Android11系统&#xff0c;编译ROOT权限固件的方法。触觉智能Purple Pi OH鸿蒙开发板演示&#xff0c;搭载了瑞芯微RK3566四核处理器&#xff0c;Laval鸿蒙社区推荐开发板&#xff0c;已适配全新OpenHarmony5.0 Release系统&#xff0c;SDK源码全开…...

Netty 入门应用:结合 Redis 实现服务器通信

在上篇博客中&#xff0c;我们了解了 Netty 的基本概念和架构。本篇文章将带你深入实践&#xff0c;构建一个简单的 Netty 服务端&#xff0c;并结合 Redis 实现一个数据存取的示例。在这个场景中&#xff0c;Redis 作为缓存存储&#xff0c;Netty 作为服务端处理客户端请求。通…...

试题转excel;pdf转excel;试卷转Excel,word试题转excel

一、问题描述 一名教师朋友&#xff0c;偶尔会需要整理一些高质量的题目到excel中 以往都是手动复制搬运&#xff0c;几百道题几乎需要一个下午的时间 关键这些事&#xff0c;枯燥无聊费眼睛&#xff0c;实在是看起来就很蠢的工作 就想着做一个工具&#xff0c;可以自动处理…...

查看网卡设备Bus号

在Linux系统中&#xff0c;通过ip命令能够看到网卡设备的名称&#xff0c;那么怎么看这个网卡设备对应的硬件设备以及Bus号&#xff1f; 例如在下面的虚拟机中能够看到有一个网口名为enp1s0 如何查看这个设备对应的Bus编号&#xff0c;可以在/sys中找到对应的设备 ll /sys/cl…...

鸿蒙Next星河版高级用例之网络请求和自适应布局以及响应式布局

目录&#xff1a; 1、发起网络请求的两种方式第一种使用httpRequest发送http的请求&#xff1a;1.1、在进行网络请求前&#xff0c;您需要在module.json5文件中申明网络访问权限1.2、GET 请求1.3、POST请求1.4、处理响应的结果第二种使用axios发送http的请求&#xff1a;1.1、在…...

鸿蒙技术分享:敲鸿蒙木鱼,积____功德——鸿蒙元服务开发:从入门到放弃(3)...

本文是系列文章&#xff0c;其他文章见&#xff1a;敲鸿蒙木鱼&#xff0c;积____功德&#x1f436;&#x1f436;&#x1f436;——鸿蒙元服务开发&#xff1a;从入门到放弃(1)敲鸿蒙木鱼&#xff0c;积____功德&#x1f436;&#x1f436;&#x1f436;——鸿蒙元服务开发&am…...

Hadoop生态圈框架部署 伪集群版(六)- MySQL安装配置

文章目录 前言一、MySQL安装与配置1. 安装MySQL2. 安装MySQL服务器3. 启动MySQL服务并设置开机自启动4. 修改MySQL初始密码登录5. 设置允许MySQL远程登录6. 登录MySQL 卸载1. 停止MySQL服务2. 卸载MySQL软件包3. 删除MySQL配置文件及数据目录 前言 在本文中&#xff0c;我们将…...

【Docker】创建Docker并部署Web站点

要在服务器上创建Docker容器&#xff0c;并在其中部署站点&#xff0c;你可以按照以下步骤操作。我们将以Flask应用为例来说明如何完成这一过程。 1. 准备工作 确保你的服务器已经安装了Docker。如果没有&#xff0c;请根据官方文档安装&#xff1a; Docker 安装指南 2. 创…...

实验七 用 MATLAB 设计 FIR 数字滤波器

实验目的 加深对窗函数法设计 FIR 数字滤波器的基本原理的理解。 学习用 Matlab 语言的窗函数法编写设计 FIR 数字滤波器的程序。 了解 Matlab 语言有关窗函数法设计 FIR 数字滤波器的常用函数用法。 掌握 FIR 滤波器的快速卷积实现原理。 不同滤波器的设计方法具有不同的优…...

学习ESP32开发板安装鸿蒙操作系统(新板子esp32c3不支持)

鸿蒙LiteOS网址&#xff1a;LiteOS: Huawei LiteOS开源代码官方主仓库.LiteOS Studio 开发工具请访问https://gitee.com/LiteOS/LiteOS_Studio 失败的实践记录见&#xff1a;完全按照手册win10里装Ubuntu 虚拟机然后编译ESP32&#xff08;主要是想针对ESP32C3和S3&#xff09;…...

asp.net core过滤器应用

筛选器类型 授权筛选器 授权过滤器是过滤器管道的第一个被执行的过滤器&#xff0c;用于系统授权。一般不会编写自定义的授权过滤器&#xff0c;而是配置授权策略或编写自定义授权策略。简单举个例子。 using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCo…...

暗黑破坏神2存档修改实用教程:从入门到精通的d2s编辑器全攻略

暗黑破坏神2存档修改实用教程&#xff1a;从入门到精通的d2s编辑器全攻略 【免费下载链接】d2s-editor 项目地址: https://gitcode.com/gh_mirrors/d2/d2s-editor d2s-editor是一款专为《暗黑破坏神2》玩家打造的开源存档编辑工具&#xff0c;支持角色属性调整、物品管…...

【T型三电平仿真】SPWM调制中的单双极性载波特性对比

1. T型三电平逆变器基础认知 第一次接触T型三电平拓扑时&#xff0c;我被它精巧的结构设计惊艳到了。与传统的两电平逆变器相比&#xff0c;这种拓扑在每相桥臂上增加了两个钳位开关管&#xff0c;形成了独特的"T"字形结构。实际搭建电路时&#xff0c;你会发现它的输…...

Ollama实测:Yi-Coder-1.5B代码生成速度有多快?3秒搞定日常函数

Ollama实测&#xff1a;Yi-Coder-1.5B代码生成速度有多快&#xff1f;3秒搞定日常函数 1. 测试背景与目标 作为一名开发者&#xff0c;每天都要面对各种编码任务。从简单的工具函数到复杂的算法实现&#xff0c;代码生成速度直接影响着开发效率。Yi-Coder-1.5B作为一款开源的…...

Python数据库操作终极指南:5分钟快速上手dataset轻松管理数据

Python数据库操作终极指南&#xff1a;5分钟快速上手dataset轻松管理数据 【免费下载链接】dataset Easy-to-use data handling for SQL data stores with support for implicit table creation, bulk loading, and transactions. 项目地址: https://gitcode.com/gh_mirrors/…...

从LVGL V7.11到V9.1:我维护中文文档这三年踩过的坑与实战经验

从LVGL V7.11到V9.1&#xff1a;一个中文文档维护者的技术叙事 三年前&#xff0c;当我第一次在嵌入式项目中尝试使用LVGL时&#xff0c;完全没想到这个轻量级图形库会成为我技术生涯中的重要篇章。作为国内最早系统维护LVGL中文文档的开发者之一&#xff0c;这段跨越三个大版本…...

UDOP-large高性能部署:Tesseract OCR预处理与UDOP-large联合加速方案

UDOP-large高性能部署&#xff1a;Tesseract OCR预处理与UDOP-large联合加速方案 1. 引言&#xff1a;当文档理解遇上效率瓶颈 想象一下&#xff0c;你手头有几百份英文PDF报告需要处理。你需要从中提取标题、摘要&#xff0c;甚至表格里的关键数据。传统的方法是&#xff1a…...

霜儿-汉服-造相Z-Turbo作品集:看看AI能生成多美的汉服少女图

霜儿-汉服-造相Z-Turbo作品集&#xff1a;看看AI能生成多美的汉服少女图 1. 惊艳开篇&#xff1a;AI汉服艺术的魅力 当传统汉服遇上现代AI技术&#xff0c;会碰撞出怎样的火花&#xff1f;霜儿-汉服-造相Z-Turbo给出了令人惊叹的答案。这个基于Xinference部署的文生图模型服务…...

MXene基单原子催化剂在电催化CO2还原中的电子结构调控与性能优化

1. MXene基单原子催化剂为何能成为CO2还原的"黑马"&#xff1f; 在碳中和背景下&#xff0c;电催化CO2还原技术就像一位"化学魔术师"&#xff0c;能把温室气体变废为宝。而MXene材料凭借其独特的层状结构和导电性&#xff0c;正成为这场魔术表演的明星道具…...

颠覆级植物大战僵尸修改工具:一站式资源管理与战局掌控解决方案

颠覆级植物大战僵尸修改工具&#xff1a;一站式资源管理与战局掌控解决方案 【免费下载链接】pvztoolkit 植物大战僵尸 PC 版综合修改器 项目地址: https://gitcode.com/gh_mirrors/pv/pvztoolkit 还在为植物大战僵尸中阳光不足而焦虑吗&#xff1f;面对海量僵尸浪潮却束…...

EnergyStarX深度解析:开源开发者如何让Windows 11续航提升40%+

EnergyStarX深度解析&#xff1a;开源开发者如何让Windows 11续航提升40% 【免费下载链接】EnergyStarX &#x1f50b; Improve your Windows 11 devices battery life. A WinUI 3 GUI for https://github.com/imbushuo/EnergyStar. 项目地址: https://gitcode.com/gh_mirror…...