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

C#使用OpenTK绘制3D可拖动旋转图形三棱锥

接上篇,绘制着色矩形

C#使用OpenTK绘制一个着色矩形-CSDN博客

上一篇安装OpenTK.GLControl后,这里可以直接拖动控件GLControl

我们会发现GLControl继承于UserControl

    //// 摘要://     OpenGL-aware WinForms control. The WinForms designer will always call the default//     constructor. Inherit from this class and call one of its specialized constructors//     to enable antialiasing or custom OpenTK.GLControl.GraphicsModes.public class GLControl : System.Windows.Forms.UserControl

以下我们绘制一个三棱锥,三棱锥需要四个顶点Vertex

新建窗体FormGLControl,拖入一个控件GLControl,绑定Load,Paint等事件

窗体FormGLControl设计器代码为:

文件FormGLControl.Designer.cs

using OpenTK;
namespace OpenTKDemo
{partial class FormGLControl{/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){this.glControl1 = new OpenTK.GLControl();this.SuspendLayout();// // glControl1// this.glControl1.BackColor = System.Drawing.Color.Black;this.glControl1.Location = new System.Drawing.Point(12, 12);this.glControl1.Name = "glControl1";this.glControl1.Size = new System.Drawing.Size(800, 600);this.glControl1.TabIndex = 0;this.glControl1.VSync = false;this.glControl1.Load += new System.EventHandler(this.glControl1_Load);this.glControl1.Paint += new System.Windows.Forms.PaintEventHandler(this.glControl1_Paint);this.glControl1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseDown);this.glControl1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseMove);this.glControl1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseUp);this.glControl1.Resize += new System.EventHandler(this.glControl1_Resize);// // FormGLControl// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(832, 619);this.Controls.Add(this.glControl1);this.Name = "FormGLControl";this.Text = "FormGLControl";this.ResumeLayout(false);}#endregionprivate GLControl glControl1;}
}

窗体FormGLControl相关代码如下:

文件FormGLControl.cs

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;
using OpenTK;
using OpenTK.Graphics.OpenGL;namespace OpenTKDemo
{public partial class FormGLControl : Form{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 FormGLControl(){InitializeComponent();}private void glControl1_Load(object sender, EventArgs e){// 设置清屏颜色GL.ClearColor(1.0f, 1.0f, 1.0f, 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(x,y,z,red,green,blue)-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, BufferUsageHint.StaticDraw);GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo);GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length * sizeof(int), indices, BufferUsageHint.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), glControl1.Width / (float)glControl1.Height, 0.1f, 100.0f);GL.BindVertexArray(0);}private void glControl1_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.UniformMatrix4(GL.GetUniformLocation(shaderProgram, "model"), false, ref model);GL.UniformMatrix4(GL.GetUniformLocation(shaderProgram, "view"), false, ref view);GL.UniformMatrix4(GL.GetUniformLocation(shaderProgram, "projection"), false, ref projection);GL.BindVertexArray(vao);GL.DrawElements(PrimitiveType.Triangles, 12, DrawElementsType.UnsignedInt, 0);glControl1.SwapBuffers();}private void glControl1_Resize(object sender, EventArgs e){GL.Viewport(0, 0, glControl1.Width, glControl1.Height);projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45.0f), glControl1.Width / (float)glControl1.Height, 0.1f, 100.0f);}private void glControl1_MouseDown(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left){isDragging = true;lastMousePosition = e.Location;}}private void glControl1_MouseUp(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left){isDragging = false;}}private void glControl1_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;glControl1.Invalidate();}}private 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 status);if (status == 0){GL.GetShaderInfoLog(shader, out string infoLog);throw new Exception($"Error compiling shader ({type}): {infoLog}");}return shader;}}
}

 运行如图:

可以拖动旋转:

相关文章:

C#使用OpenTK绘制3D可拖动旋转图形三棱锥

接上篇,绘制着色矩形 C#使用OpenTK绘制一个着色矩形-CSDN博客 上一篇安装OpenTK.GLControl后,这里可以直接拖动控件GLControl 我们会发现GLControl继承于UserControl //// 摘要:// OpenGL-aware WinForms control. The WinForms designer will always call the default//…...

排序的本质、数据类型及算法选择

排序的本质、数据类型及算法选择 一、排序的本质二、排序的数据类型三、排序算法的选择依据 前两天老金写了篇 “十大排序简介”&#xff0c;有点意犹未尽&#xff0c;这一回老金想把排序连根拔起&#xff0c;从排序的本质说道说道。 一、排序的本质 从字面上理解&#xff0c…...

Python的列表基础知识点(超详细流程)

目录 一、环境搭建 二、列表 2.1 详情 2.2 列表定义 2.3 列表长度 2.4 列表索引 2.5 切片索引 2.6 添加 2.7 插入 2.8 剔除 2.8.1 pop方法 2.8.2 del方法 2.9 任何数据类型 2.10 拼接 2.10.1 “” 2.10.2 “*” 2.11 逆序 ​编辑 2.12 计算出现次数 2.13 排序…...

HarmonyOS鸿蒙开发 弹窗及加载中指示器HUD功能实现

HarmonyOS鸿蒙开发 弹窗及加载中指示器HUD功能实现 最近在学习鸿蒙开发过程中&#xff0c;阅读了官方文档&#xff0c;在之前做flutter时候&#xff0c;经常使用overlay&#xff0c;使用OverlayEntry加入到overlayState来做添加悬浮按钮、提示弹窗、加载中指示器、加载失败的t…...

【Ubuntu与Linux操作系统:一、Ubuntu安装与基本使用】

第1章 Ubuntu安装与基本使用 1.1 Linux与Ubuntu Linux是一种开源、类Unix操作系统内核&#xff0c;拥有高稳定性和强大的网络功能。由于其开源性和灵活性&#xff0c;Linux被广泛应用于服务器、嵌入式设备以及桌面环境中。 Ubuntu是基于Debian的一个流行Linux发行版&#xf…...

React 元素渲染

React 元素渲染 React 是一个用于构建用户界面的 JavaScript 库&#xff0c;它允许开发人员创建大型应用程序&#xff0c;这些应用程序可以随着时间的推移而高效地更新和渲染。React 的核心概念之一是元素渲染&#xff0c;它描述了如何将 JavaScript 对象转换为 DOM&#xff0…...

【2024年华为OD机试】 (C卷,100分)- 括号匹配(Java JS PythonC/C++)

一、问题描述 题目描述 给定一个字符串&#xff0c;里边可能包含“()”、“[]”、“{}”三种括号&#xff0c;请编写程序检查该字符串中的括号是否成对出现&#xff0c;且嵌套关系正确。 若括号成对出现且嵌套关系正确&#xff0c;或该字符串中无括号字符&#xff0c;输出&am…...

解锁企业数字化转型新力量:OpenCoze(开源扣子)

在当今数字化浪潮席卷之下&#xff0c;企业对于高效管理和协同运作的需求愈发迫切&#xff0c;而开源技术正逐渐成为众多企业破局的关键利器。今天&#xff0c;想给大家介绍一款极具潜力的开源项目 ——OpenCoze&#xff0c;中文名称 “开源扣子”。 一、OpenCoze 是什么&…...

【网络云SRE运维开发】2025第2周-每日【2025/01/12】小测-【第12章 rip路由协议】理论和实操考试题解析

文章目录 选择题答案及解析理论题答案及解析实操题答案及解析下一步进阶 选择题答案及解析 RIP路由协议是基于哪种算法的动态路由协议&#xff1f; 答案&#xff1a;B. 距离矢量算法解析&#xff1a;链路状态算法用于OSPF等协议&#xff1b;最小生成树算法主要用于生成树协议&…...

【微服务】8、分布式事务 ( XA 和 AT )

文章目录 利用Seata解决分布式事务问题&#xff08;XA模式&#xff09;AT模式1. AT模式原理引入2. AT模式执行流程与XA模式对比3. AT模式性能优势及潜在问题4. AT模式数据一致性解决方案5. AT模式一阶段操作总结6. AT模式二阶段操作分析7. AT模式整体特点8. AT模式与XA模式对比…...

CVE-2025-22777 (CVSS 9.8):WordPress | GiveWP 插件的严重漏洞

漏洞描述 GiveWP 插件中发现了一个严重漏洞&#xff0c;该插件是 WordPress 最广泛使用的在线捐赠和筹款工具之一。该漏洞的编号为 CVE-2025-22777&#xff0c;CVSS 评分为 9.8&#xff0c;表明其严重性。 GiveWP 插件拥有超过 100,000 个活跃安装&#xff0c;为全球无数捐赠平…...

TypeScript Jest 单元测试 搭建

NPM TypeScript 项目搭建 创建目录 mkdir mockprojectcd mockproject初始化NPM项目 npm init -y安装TypeScript npm i -D typescript使用VSCode 打开项目 创建TS配置文件tsconfig.json {"compilerOptions": {"target": "es5","module&…...

基于 SSH 的任务调度系统

文末附有完整项目代码 在当今科技飞速发展的时代&#xff0c;任务调度系统的重要性日益凸显。本文将详细介绍一个基于 SSH&#xff08;SpringStruts2Hibernate&#xff09;的任务调度系统的设计与实现。 一、系统概述 本系统旨在改变传统人工任务调度方式&#xff0c;通过计算…...

filestream安装使用全套+filebeat的模块用法

1 filestream介绍 官方宣布&#xff1a;输入类型为log在filebeat7.16版本已经弃用了 Filestream 是 Filebeat 中的一种 输入类型&#xff08;Input&#xff09;&#xff0c;用于处理日志文件的读取。它是为了取代 Filebeat 中传统的 log 输入&#xff08;Input&#xff09;设…...

java项目之房屋租赁系统源码(springboot+mysql+vue)

项目简介 房屋租赁系统实现了以下功能&#xff1a; 房屋租赁系统的主要使用者分为&#xff1a; 系统管理&#xff1a;个人中心、房屋信息管理、预约看房管理、合同信息管理、房屋报修管理、维修处理管理、房屋评价管理等模块的查看及相应操作&#xff1b; 房屋信息管理&#…...

sap mm学习笔记

1. 业务流程 2. 组织架构 3. 物料主数据 4.采购主数据 5. 采购管理 6. 库存管理 7.物料主数据 8. 采购申请 ME51N...

代码随想录_链表

代码随想录02 链表 203.移除链表元素 力扣题目链接(opens new window) 题意&#xff1a;删除链表中等于给定值 val 的所有节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#xff1a; 输入&#xff1a;he…...

EF Code 并发控制

【悲观控制】 不推荐用&#xff0c;EF Core 没有封装悲观并发控制的使用&#xff0c;需要使用原生Sql来使用悲观并发控制 一般使用行锁、表锁等排他锁对资源进行锁定&#xff0c;同时只有一个使用者操作被锁定的资源 拿sql server举例&#xff0c;可以使用表所、或者行所解决…...

ceph fs status 输出详解

ceph fs status 命令用于显示 Ceph 文件系统的状态信息&#xff0c;其中各列的含义如下&#xff1a; RANK&#xff1a;元数据服务器&#xff08;MDS&#xff09;的等级或标识符。 STATE&#xff1a;MDS 的当前状态&#xff0c;例如 active&#xff08;活跃&#xff09;、stan…...

FFmpeg Muxer HLS

使用FFmpeg命令来研究它对HLS协议的支持程度是最好的方法&#xff1a; ffmpeg -h muxerhls Muxer HLS Muxer hls [Apple HTTP Live Streaming]:Common extensions: m3u8.Default video codec: h264.Default audio codec: aac.Default subtitle codec: webvtt. 这里面告诉我…...

AMLP框架实战:基于MACE构建高精度机器学习势函数

1. 项目概述&#xff1a;当机器学习势函数遇上自动化管道在计算化学和材料科学领域&#xff0c;我们长久以来面临着一个核心矛盾&#xff1a;精度与效率的权衡。密度泛函理论&#xff08;DFT&#xff09;能提供接近实验的精度&#xff0c;但计算成本高昂&#xff0c;通常只能处…...

Obsidian PDF++:如何在Obsidian中实现PDF与笔记的无缝双向链接?

Obsidian PDF&#xff1a;如何在Obsidian中实现PDF与笔记的无缝双向链接&#xff1f; 【免费下载链接】obsidian-pdf-plus PDF: the most Obsidian-native PDF annotation & viewing tool ever. Comes with optional Vim keybindings. 项目地址: https://gitcode.com/gh_…...

Redis分布式锁进阶第二十篇

一、本篇前置衔接 第二十篇我们完成了全系列终局复盘&#xff0c;整理了故障排查SOP与企业级落地铁律。常规单资源锁、热点分片锁、隔离锁全部讲透&#xff0c;但真实复杂业务永远不是单一资源&#xff1a;下单要扣库存、扣优惠券、扣积分、冻结余额&#xff0c;多资源并行争抢…...

Python UiAutomation实战:从网页数据抓取到桌面应用,一个库打通数据采集全链路

Python UiAutomation实战&#xff1a;打通数据采集全链路的智能解决方案 在数据驱动的商业环境中&#xff0c;企业常常面临跨平台数据采集的挑战——财务系统里的交易记录需要与网站后台的报表进行交叉分析&#xff0c;销售数据要从桌面软件导出后上传到云端处理系统。传统的人…...

阿波罗登月,不可能:读心术与影子叙事 ——不是向全世界展示登月,而是向全世界注射登月

阿波罗登月&#xff0c;不可能&#xff1a;读心术与影子叙事 ——不是向全世界展示登月&#xff0c;而是向全世界注射登月 Jianbing Zhu 1^{1}1 1^{1}1 ECT-OS-JiuHuaShan 文明实验室 ORCID: 0009-0006-8591-1891 DOI: 10.5281/zenodo.20373157 Email: ect-os-jiuhuashanzoho…...

账务台账数据

银行里说的 “账务台账数据”&#xff0c;本质就是按会计规则把每笔业务逐笔、分户、分科目记下来的完整明细流水 余额 辅助信息&#xff0c;核心是 “可逐笔追溯、可对账、可审计” 的一套明细数据。下面用通俗、具体的方式拆开说&#xff1a;一、银行 “账务台账” 到底是什…...

DeepSeek重复代码识别失效了?5个被90%团队忽略的AST解析盲区及修复清单

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;DeepSeek代码重复检测失效的真相与影响 DeepSeek-R1 模型在代码理解任务中表现出色&#xff0c;但其内置的代码重复检测机制在特定场景下存在系统性失效。根本原因在于模型对语义等价但语法结构差异显著的代…...

树莓派工业GPIO接口板:电气隔离与电平转换实战指南

1. 项目概述&#xff1a;为什么需要一块工业级GPIO接口板&#xff1f;如果你用树莓派做过一些硬件项目&#xff0c;尤其是涉及到控制继电器、电机或者连接工业设备&#xff08;比如PLC、变频器&#xff09;时&#xff0c;大概率踩过这样的坑&#xff1a;直接用树莓派的GPIO引脚…...

终极AMD Ryzen调试指南:为什么你需要SMUDebugTool这个免费神器?

终极AMD Ryzen调试指南&#xff1a;为什么你需要SMUDebugTool这个免费神器&#xff1f; 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. …...

泰拉瑞亚地图编辑器:从像素画布到创意世界的蜕变之旅

泰拉瑞亚地图编辑器&#xff1a;从像素画布到创意世界的蜕变之旅 【免费下载链接】Terraria-Map-Editor TEdit - Terraria Map Editor - TEdit is a stand alone, open source map editor for Terraria. It lets you edit maps just like (almost) paint! It also lets you cha…...