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

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

        }

        #endregion

        private 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 和 VBO
            vao = 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, // 顶点2
                 0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 1.0f, // 顶点3
                 0.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 core
                layout (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 core
                in 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;
        }
    }
}

 运行如图:

可以拖动旋转:

原文地址:https://blog.csdn.net/ylq1045/article/details/145078587
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/504420.html

相关文章:

  • 【EXCEL_VBA_实战】多工作薄合并深入理解
  • 初步搭建并使用Scrapy框架
  • 除了基本的事件绑定,鸿蒙的ArkUI
  • 图形化数据报文转换映射工具
  • 简洁实用的wordpress外贸模板
  • DeepSeek-R1:性能对标 OpenAI,开源助力 AI 生态发展
  • 2025年01月13日Github流行趋势
  • 网络层协议-----IP协议
  • k8s之pod生命周期
  • Open FPV VTX开源之betaflight配置
  • 深度剖析RabbitMQ:从基础组件到管理页面详解
  • TiDB常见操作指南:从入门到进阶
  • Unreal Engine 5 C++ Advanced Action RPG 八章笔记
  • 【Uniapp-Vue3】uni-api交互反馈showToast的使用方法
  • RV1126+FFMPEG推流项目(4)VENC模块视频编码流程
  • adb端口转发
  • 网络安全的学习路径 (包括资源)快速学习
  • Mac上安装Label Studio
  • 钉钉实现第三方登录示例(重复回调问题解析)
  • SQL中的行转列,列转行
  • 一些常见的Java面试题及其答案
  • 网络攻击行为可视化分析系统【数据分析 + 可视化】
  • CSS | 实现三列布局(两边边定宽 中间自适应,自适应成比)
  • HTML文章翻页功能
  • 【已解决】【记录】2AI大模型web UI使用tips 本地
  • 阿里云直播Web