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

接上篇,绘制着色矩形

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

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

我们会发现GLControl继承于UserControl

cs 复制代码
    //
    // 摘要:
    //     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

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

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

运行如图:

可以拖动旋转:

相关推荐
源之缘-OFD先行者19 分钟前
FreeType 介绍及 C# 示例
开发语言·c#
小兵小卒1 小时前
ElectronSharp,.Net跨平台的多一种选择
android·macos·c#·.net·wpf
向宇it2 小时前
【零基础入门unity游戏开发——unity3D篇】URP 3D光源组件(Light)介绍、烘培灯光、实现太阳耀斑镜头光晕效果(基于unity6开发介绍)
开发语言·游戏·3d·unity·c#·游戏引擎
飞人博尔特的摄影师4 小时前
C#界面框架Avalonia中使用依赖注入
系统架构·前端框架·c#·.net·wpf·.netcore·依赖倒置原则
刘欣的博客5 小时前
C# 25Dpoint
c#·c# 25dpoint
向宇it6 小时前
【零基础入门unity游戏开发——unity3D篇】地形Terrain的使用介绍
开发语言·unity·c#·编辑器·游戏引擎
上位机付工7 小时前
开源免费的上位机数据转换库
开发语言·c#
YYHYJX9 小时前
C#补充----反射,特性,迭代器,特殊语法,值类型运用类型。
c#
步、步、为营10 小时前
ASP.NET Core 全局异常处理
后端·c#·asp.net