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

 运行如图:

可以拖动旋转:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/892732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle查询-in条件超过1000

目录 1.不分页 2.分页 oracle数据库中&#xff0c;in的查询条件超过1000的话&#xff0c;就会报错&#xff0c;应该怎样处理这样的情况呢&#xff1f; 1.不分页 把查询条件分成几个list&#xff0c;每个list有1000个数据&#xff0c;有几个list查询几次数据库就行了 2.分…

Android Room 报错:too many SQL variables (code 1 SQLITE_ERROR) 原因及解决方法

报错信息&#xff1a; android.database.sqlite.SQLiteException: too many SQL variables (code 1 SQLITE_ERROR): while compiling: SELECT * FROM points WHERE id IN (?,?,?,...,?,?,?)SQLiteException: too many SQL variables 通常是由于一次查询或插入的 SQL 语句…

ctf竞赛

在CTF&#xff08;Capture The Flag&#xff09;竞赛中&#xff0c;前端开发和后端开发都非常重要&#xff0c;二者各有其关键作用&#xff0c;很难简单地说哪个更重要&#xff0c;以下是具体分析&#xff1a; 前端开发的重要性 用户体验与交互&#xff1a;CTF竞赛平台的前端是…

【Vue】点击侧边导航栏,右侧main对应显示

需求&#xff1a;点击侧边导航栏&#xff0c;右侧main对应显示 通过v-if或v-show等指令来控制不同内容的显示隐藏来实现 注意&#xff1a; 使用v-if时候进行导航栏切换&#xff0c;右侧显示区域可能会出现样式错乱&#xff1b;使用v-show则不会出现此错误 <template>&…

JAVA:利用 RabbitMQ 死信队列实现支付超时场景的技术指南

1、简述 在支付系统中&#xff0c;订单支付的超时自动撤销是一个非常常见的业务场景。通常用户未在规定时间内完成支付&#xff0c;系统会自动取消订单&#xff0c;释放相应的资源。本文将通过利用 RabbitMQ 的 死信队列&#xff08;Dead Letter Queue, DLQ&#xff09;来实现…

特制一个自己的UI库,只用CSS、图标、emoji图 第二版

图&#xff1a; 代码&#xff1a; index.html <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>M…

1.14 互斥与同步

1.思维导图 2.有一个隧道&#xff0c;长1000m&#xff0c;有一辆高铁&#xff0c;每秒100米&#xff1b;有一辆快车&#xff0c;每秒50米&#xff1b;要求模拟这两列火车通过隧道的场景。 1>程序代码&#xff1a; #include <stdio.h> #include <string.h> #i…

solidity基础 -- 枚举

在智能合约开发领域&#xff0c;Solidity语言因其简洁高效而被广泛使用。其中&#xff0c;枚举&#xff08;enum&#xff09;作为一种特殊的数据类型&#xff0c;为合约的状态管理提供了极大的便利。本文将通过一个具体的Solidity合约示例&#xff0c;深入探讨枚举的定义、使用…

14.STM32F407ZGT6-SPI

参考&#xff1a; 1.正点原子 前言&#xff1a; SPI一般用在中高速的外围器件上&#xff0c;如FLASH, GPS模块等。很常用的一种通信方式&#xff0c;学习总结很有必要。 1.SPI的概念及时序。 2.通过SPI操作Flash芯片。 37.1 SPI 及 NOR Flash 介绍 37.1.1 SPI 介绍 我们将从…

基于SpringBoot的中华诗词赏析文化交流平台

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

44.ComboBox的数据绑定 C#例子 WPF例子

固定最简步骤&#xff0c;包括 XAML&#xff1a; 题头里引入命名空间 标题下面引入类 combobox绑定资源属性和选择属性&#xff0c;block则绑定和combobox一样的选择属性 C#&#xff1a; 通知的类&#xff0c;及对应固定的任务 引入字段 引入属性 其中资源是只读的 选…

Flink类加载机制详解

1. 总览 在运行Flink应用时,它会加载各种类,另外我们用户代码也会引入依赖,由于他们依赖版本以及加载顺序等不同,就可能会导致冲突,所以很要必要了解Flink是如何加载类的。 根据加载的来源的不同,我们可以将类分为三种: Java Classpath:Java类路径下,这是Java通用的…

水下通信:特点、主要应用与典型系统

引言 海洋覆盖了地球表面的71%&#xff0c;是地球上最大的生态系统。随着人类对海洋资源的不断探索和开发&#xff0c;水下通信成为了连接水下设备与陆上控制中心、实现水下数据交换和远程监控的关键技术。水下通信不仅在水下科研、资源开发、环境监测、水下救援等领域发挥着重…

GPU算力平台|在GPU算力平台部署Qwen-2通义千问大模型的教程

文章目录 一、GPU平台介绍算力平台概述 二、人工智能应用开发需要GPU算力平台GPU算力原理账号注册流程Qwen-2通义千问大模型的部署登录/注册选择SettingsURL配置选择模型部署完成进行问答 一、GPU平台介绍 算力平台概述 GPU算力平台是一个专注于GPU加速计算的专业云服务平台&…

“深入浅出”系列之设计模式篇:(0)什么是设计模式

设计模式六大原则 1. 单一职责原则&#xff1a;一个类或者一个方法只负责一项职责&#xff0c;尽量做到类的只有一个行为原因引起变化。 核心思想&#xff1a;控制类的粒度大小&#xff0c;将对象解耦&#xff0c;提高其内聚性。 2. 开闭原则&#xff1a;对扩展开放&#xf…

微信小程序集成Vant Weapp移动端开发的框架

什么是Vant Weapp Vant 是一个轻量、可靠的移动端组件库&#xff0c;于 2017 年开源。 目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本&#xff0c;并由社区团队维护 React 版本和支付宝小程序版本。 官网地睛&#xff1a;介绍 - Vant Weapp (vant-ui.gith…

【C++】:浅析 std::optional

std::optional 是 C17 引入的一个标准库特性&#xff0c;提供了一种简单的方式来表示一个可能存在或不存在的值。它可以用于替代指针或其他机制&#xff0c;以更安全和更清晰的方式处理可选值。 1. 基本概念 std::optional<T> 是一个模板类&#xff0c;其中 T 是存储的…

图形和动画本地化

图形和动画本地化是多媒体改编的一个关键方面&#xff0c;需要对技术技能和文化细微差别有深入的理解。当由母语人士和设计师进行时&#xff0c;这一过程达到了自动化系统通常无法复制的真实性和相关性水平。 本土专业人士对文化偏好、象征主义和视觉美学有着固有的理解&#…

浅谈云计算06 | 云管理系统架构

云管理系统架构 一、云管理系统架构&#xff08;一&#xff09;远程管理系统&#xff08;二&#xff09;资源管理系统&#xff08;三&#xff09;SLA 管理系统&#xff08;四&#xff09;计费管理系统 二、安全与可靠性保障&#xff08;一&#xff09;数据安全防线&#xff08;…

SpringBoot 基础学习

对于SpringBoot的了解&#xff0c;在初学者的角度看来&#xff0c;它是一种工具&#xff0c;用于简化一个Spring项目的初始搭建和开发过程。 1 入门案例 1.1 项目的创建 有四种方法创建&#xff0c;可以通过idea快捷创建&#xff0c;Spring的官网创建&#xff0c;阿里云创建&am…