Gráficos de dibujo OpenGL bajo la plataforma .Net (2) (VS2019, Winform, C#)

Esta sección habla principalmente sobre el principio del dibujo de gráficos, la introducción y la demostración de código.

  • Introducción al principio

  Hablemos primero de la representación gráfica de OpenGL. De hecho, todos los gráficos están conectados por muchos gráficos pequeños. Puede entenderlo como los píxeles de la imagen.Una imagen en color se compone de muchos píxeles de diferentes colores. Para lograr un diseño gráfico colorido, debe comprender el principio de que dos puntos forman una línea, tres puntos forman un plano y el principio de formación de múltiples superficies. Aquí, demostramos el proceso de punto a línea, línea a superficie y superficie a forma a través de un programa simple.

   Aquí, permítanme presentarles algunas funciones y principios de dibujo comúnmente utilizados.

  1. Transformación de origen de coordenadas: Traducir (x flotante, y flotante, z flotante), también puede entenderlo como una transformación del eje de coordenadas. El ángulo de visión y las coordenadas mundiales establecidas por defecto están en el mismo origen. Por ejemplo: miramos el teléfono, asumiendo que el teléfono es el origen, y nuestro ángulo de visión también es el origen por defecto, tenemos que perforar nuestras cabezas en el teléfono. Correcto, no miramos el teléfono de esa manera, básicamente retiramos el teléfono y lo operamos en un ángulo cómodo, que es la transformación del artículo. Por lo tanto, es mejor establecer la posición adecuada del eje de coordenadas antes de dibujar el gráfico y también debe considerar el valor de configuración de la transformación del punto de vista. Las coordenadas de nuestros gráficos de entrada aún se ingresan de acuerdo con el origen y no se verán afectadas por Traducir; solo afecta la transformación general del eje de coordenadas y no es necesario cambiar su valor. Por supuesto, también puede modificar directamente todos los valores de coordenadas de los gráficos, pero esto es demasiado molesto e innecesario; también es posible modificar directamente el valor de transformación del ángulo de visión inicializado.

  2. El método de dibujar puntos, líneas y planos: comience con Begin (modo BeginMode) para comenzar a dibujar gráficos tipo modo, Vertex (float x, float y, float z) como los vértices gráficos, conecte cada vértice a su vez para formar un gráfico y finalice con Fin ( ) para finalizar el dibujo. Teóricamente hablando, siempre que le des todos los vértices de la gráfica, te saldrán fantasmas y serpientes, y no hay ningún problema (salvo la posibilidad de quedarte atascado). Tome el dibujo de una línea como un ejemplo:

  gl.Begin(OpenGL.GL_LINES);
  gl.Vértice(-1.0f, 0.0f, 0.0f);
  gl.Vértice(1.0f, 0.0f, 0.0f);
  gl.End();

  3. Asignar color: Color (rojo flotante, verde flotante, azul flotante)

  Agregue el color establecido antes de cada vértice del gráfico, y las opciones de dibujo del gráfico serán más diversas; al mismo tiempo, usar diferentes colores entre diferentes vértices producirá una diferencia de color degradado, que es muy hermosa.

  • código de demostración

  Agreguemos primero un cambio de sistema de coordenadas, luego. Seleccione para dibujar una línea, seguida de un triángulo y finalmente una pirámide. Este es el proceso de punto a línea, de línea a superficie y de superficie a forma.Todos los gráficos se combinan y conectan de esta manera.

  1. Primero, dibuje una línea y establezca el color en blanco (el fondo es negro)

#region 点到线
            gl.Begin(OpenGL.GL_LINES);
        gl.Color(1.0f, 1.0f, 1.0f);
            gl.Vertex(-2.0f, 0.0f, 0.0f);//左顶点
            gl.Vertex(2.0f, 2.0f, 0.0f);//右顶点
            gl.End();
            #endregion

 2. A continuación, dibujemos una superficie y luego agreguemos un poco de cambio de color #línea de región en una superficie (triángulo)
             

  gl.Begin(OpenGL.GL_TRIANGLES);//第一个面
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.End();
                #endregion

 

3. A continuación, dibuje una pirámide y seleccione blanco como el color del cuarto punto para separarlo. La pirámide también está compuesta por cuatro caras, por lo que añadimos tres caras más (nota que las coordenadas y los colores correspondientes de cada punto deben ser los mismos)

#region 面组合成体
                gl.Begin(OpenGL.GL_TRIANGLES);//第二个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.End();
                gl.Begin(OpenGL.GL_TRIANGLES);//第三个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.End();
                gl.Begin(OpenGL.GL_TRIANGLES);//第四个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.End();
                #endregion

 

Veremos que la interfaz no ha cambiado. Bueno, chicos, miren dónde está nuestro cuarto vértice. Coordenadas (0, 0, -2), relativas a los otros cuatro puntos, su posición es interior. Porque nuestra perspectiva en este momento es positiva. Bueno, por cierto, tengo que hablar sobre el ángulo de visión, que se establece mediante la transformación del punto de vista establecida por la inicialización.

  // Establecer el modo de matriz actual, aplicar operaciones de matriz posteriores a la
  matriz de proyección gl.MatrixMode(OpenGL.GL_PROJECTION);

  // Crear una transformación de proyección de perspectiva
  gl.Perspective(30.0f, (doble)Ancho / (doble)Altura, 5, 100.0);

  // transformación del punto de vista
  gl.LookAt(0, 5, 0, 0, 0, 0, 0, 1, 0);

  // Aquí está el ángulo de visión en este momento, que se puede entender como el punto de coordenadas (0, 5, 0) mirando el origen del espacio

   Translate(0.0f, 0.0f, -5.0f) se agrega al frente del programa, lo que equivale a mover los gráficos dibujados a la pantalla. Esto nos ayudará a ver el gráfico. (En el caso del eje Z, la normal es vertical al exterior de la pantalla)

  Volviendo al tema, el cuarto vértice está dentro del triángulo ya dibujado, por lo que no podemos verlo, así que rotemos un poco para ver el efecto, como se muestra en la figura a continuación.

Adjunte todo el código, este código se agrega sobre la base de  " Gráficos de dibujo OpenGL en la plataforma .Net (1) (VS2019, Winform, C#) "

using SharpGL;
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;

namespace SharpGLFormsApp1
{
    public partial class Form1 : Form
    {

        private bool drawLine = false;
        private bool drawArea = false;
        private bool drawVolume = false;
        private bool flagRotateX = false;
        private bool flagRotateY = false;
        private bool flagRotateZ = false;
        private float rotation_X = 0.0f;
        private float rotation_Y = 0.0f;
        private float rotation_Z = 0.0f;





        /// <summary>
        /// 默认绘画模式为线条
        /// </summary>
        private uint _model = OpenGL.GL_LINE_LOOP;

        /// <summary>
        /// X轴坐标
        /// </summary>
        private float _x = 0;

        /// <summary>
        /// Y轴坐标
        /// </summary>
        private float _y = 0;

        /// <summary>
        /// Z轴坐标
        /// </summary>
        private float _z = 0;


        public Form1()
        {
            InitializeComponent();

        }

        /// <summary>
        /// 复位事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            _x = _y = _z = 0;
            tbX.Value = tbY.Value = tbZ.Value = Convert.ToInt32(_x);
            label1.Text = "X轴" ;
            label2.Text = "Y轴";
            label3.Text = "Z轴";
        }

        /// <summary>
        /// 线条选择事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rbline_CheckedChanged(object sender, EventArgs e)
        {
            _model = OpenGL.GL_LINE_LOOP;
        }

        /// <summary>
        /// 球面事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rbfull_CheckedChanged(object sender, EventArgs e)
        {
            _model = OpenGL.GL_QUADS;
        }

        /// <summary>
        /// 控件绘图事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void openGLControl1_GDIDraw(object sender, RenderEventArgs args)
        {
            // 创建一个GL对象
            OpenGL gl = this.openGLControl1.OpenGL;

            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);	// 清空屏幕
            gl.LoadIdentity();					// 重置
            gl.Translate(0.0f, 0.0f, -6.0f);	// 设置坐标,距离屏幕距离为6

            gl.Rotate(_x, 1.0f, 0.0f, 0.0f);	// 绕X轴旋转
            gl.Rotate(_y, 0.0f, 1.0f, 0.0f);	// 绕Y轴旋转
            gl.Rotate(_z, 0.0f, 0.0f, 1.0f);	// 绕Z轴旋转

            gl.Begin(_model);				    // 绘制立方体
            gl.Color(0.0f, 1.0f, 0.0f);			// 设置颜色
            //绘制其中一个面
            gl.Vertex(1.0f, 1.0f, -1.0f);
            gl.Vertex(-1.0f, 1.0f, -1.0f);
            gl.Vertex(-1.0f, 1.0f, 1.0f);
            gl.Vertex(1.0f, 1.0f, 1.0f);

            //如下类同
            gl.Color(1.0f, 0.5f, 0.0f);
            gl.Vertex(1.0f, -1.0f, 1.0f);
            gl.Vertex(-1.0f, -1.0f, 1.0f);
            gl.Vertex(-1.0f, -1.0f, -1.0f);
            gl.Vertex(1.0f, -1.0f, -1.0f);

            gl.Color(1.0f, 0.0f, 0.0f);
            gl.Vertex(1.0f, 1.0f, 1.0f);
            gl.Vertex(-1.0f, 1.0f, 1.0f);
            gl.Vertex(-1.0f, -1.0f, 1.0f);
            gl.Vertex(1.0f, -1.0f, 1.0f);

            gl.Color(1.0f, 1.0f, 0.0f);
            gl.Vertex(1.0f, -1.0f, -1.0f);
            gl.Vertex(-1.0f, -1.0f, -1.0f);
            gl.Vertex(-1.0f, 1.0f, -1.0f);
            gl.Vertex(1.0f, 1.0f, -1.0f);

            gl.Color(0.0f, 0.0f, 1.0f);
            gl.Vertex(-1.0f, 1.0f, 1.0f);
            gl.Vertex(-1.0f, 1.0f, -1.0f);
            gl.Vertex(-1.0f, -1.0f, -1.0f);
            gl.Vertex(-1.0f, -1.0f, 1.0f);

            gl.Color(1.0f, 0.0f, 1.0f);
            gl.Vertex(1.0f, 1.0f, -1.0f);
            gl.Vertex(1.0f, 1.0f, 1.0f);
            gl.Vertex(1.0f, -1.0f, 1.0f);
            gl.Vertex(1.0f, -1.0f, -1.0f);
            gl.End();						// 结束绘制
        }

        /// <summary>
        /// X轴拖动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tbX_Scroll(object sender, EventArgs e)
        {
            int x = tbX.Value;
            _x = x;
            label1.Text = "X:" + x;
        }

        /// <summary>
        /// Y轴拖动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tbY_Scroll(object sender, EventArgs e)
        {
            int y = tbY.Value;
            _y = y;
            label2.Text = "Y:" + y;
        }
        /// <summary>
        ///Z轴拖动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tbZ_Scroll(object sender, EventArgs e)
        {
            int z = tbZ.Value;
            _z = z;
            label3.Text = "Z:" + z;
        }

        private void openGLControl2_GDIDraw(object sender, RenderEventArgs args)
        {
            SharpGL.OpenGL gl = this.openGLControl2.OpenGL;
            //清除深度缓存 
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);

            //重置当前指定的矩阵为单位矩阵,将当前的用户坐标系的原点移到了屏幕中心
            gl.LoadIdentity();

            //坐标轴变换位置到(0.0f, 0.0f, -5.0f),这样我们的坐标轴就相当于往屏幕内走5个单位
            gl.Translate(0.0f, 0.0f, -5.0f);

            if (flagRotateX)
            {
                rotation_X += 1f;
                gl.Rotate(rotation_X, 1.0f, 0.0f, 0.0f);//rotationX:角度
            }
            if (flagRotateY)
            {
                rotation_Y += 1f;
                gl.Rotate(rotation_Y, 0.0f, 1.0f, 0.0f);//rotationY:角度
            }
            if (flagRotateZ)
            {
                rotation_Z += 1f;
                gl.Rotate(rotation_Z, 0.0f, 0.0f, 1.0f);//rotationZ:角度
            }

            if (drawLine)
            {
                #region 点到线
                gl.Begin(OpenGL.GL_LINES);
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(-2.0f, -1.0f, 0.0f);//左顶点
                gl.Vertex(2.0f, 2.0f, 0.0f);//右顶点
                gl.End();
                #endregion
            }
            if (drawArea)
            {
                #region 线成面(三角形)
                gl.Begin(OpenGL.GL_TRIANGLES);//第一个面
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.End();
                #endregion
            }
            if (drawVolume)
            {
                #region 面组合成体
                gl.Begin(OpenGL.GL_TRIANGLES);//第二个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.End();
                gl.Begin(OpenGL.GL_TRIANGLES);//第三个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.End();
                gl.Begin(OpenGL.GL_TRIANGLES);//第四个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.End();
                #endregion
            }

            gl.Flush();   //强制刷新
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            OpenGL g2 = openGLControl2.OpenGL;
            g2.ClearColor(0, 0, 0, 0);
        }

        private void openGLControl2_Resize(object sender, EventArgs e)
        {
            OpenGL gl = openGLControl2.OpenGL;

            // 设置当前矩阵模式,对投影矩阵应用随后的矩阵操作
            gl.MatrixMode(OpenGL.GL_PROJECTION);

            // 重置当前指定的矩阵为单位矩阵,将当前的用户坐标系的原点移到了屏幕中心
            gl.LoadIdentity();

            // 创建透视投影变换
            gl.Perspective(30.0f, (double)Width / (double)Height, 5, 100.0);

            // 视点变换
            gl.LookAt(0, 5, 0, 0, 0, 0, 0, 1, 0);

            // 设置当前矩阵为模型视图矩阵
            gl.MatrixMode(OpenGL.GL_MODELVIEW);
        }

        private void ckline_CheckedChanged(object sender, EventArgs e)
        {
            drawLine = this.ckline.Checked;
        }

        private void ckarea_CheckedChanged(object sender, EventArgs e)
        {
            drawArea = this.ckarea.Checked;
        }
 

        private void ckvol_CheckedChanged(object sender, EventArgs e)
        {
            drawVolume = this.ckvol.Checked;
        }

        private void ckx_CheckedChanged(object sender, EventArgs e)
        {
            flagRotateX = this.ckx.Checked;
        }

        private void cky_CheckedChanged(object sender, EventArgs e)
        {
            flagRotateY = this.cky.Checked;
        }

        private void ckz_CheckedChanged(object sender, EventArgs e)
        {
            flagRotateZ = this.ckz.Checked;
        }
    }
}

Efecto:

 

 

 

Supongo que te gusta

Origin blog.csdn.net/hqwest/article/details/130663242
Recomendado
Clasificación