三、SharpGL的功能應用--圖形繪制


三、SharpGL的功能應用--圖形繪制 

  本節主要講訴圖形繪制的原理,使用介紹和代碼演示。

  • 原理介紹

  我們先來講講OpenGL的圖形繪制。其實,所有的圖形都是由許多個小圖形連接而成的。你可以理解為是圖片的像素,一張彩圖是由很多個色彩不一的像素點組合而成。要實現色彩絢麗的圖形設計,你需要理解兩點成線,三點成面,多面成形的原理。在這里,我們通過簡單的程序演示一下點到線,線到面,面到形的過程。

   在此,先介紹一下幾個常用的函數和繪制原理。

  1. 坐標原點變換:Translate(float x, float y, float z) ,你也可以理解為是坐標軸變換。默認設定的視角和世界坐標都是在同個原點,打個比方:我們看手機,假設手機是原點,我們視角默認也是原點的話,我們腦殼都得鑽手機里面。對吧,我們不這么看手機,基本都是把手機拉遠,以一種舒服的角度進行操作,這就是在物品的變換了。所以我們,在繪制圖形前最好設定合適的坐標軸位置,同時也需要考慮視點變換的設置值。我們輸入圖形的坐標仍是按照原點來輸入的,不會受到Translate的影響;他影響的只是整體的坐標軸變換,他的值是不需要做改變的。當然了,你也可以直接全部修改圖形的坐標值,不過這樣就太麻煩了,沒必要;直接修改初始化的視角變換值也是可以的。

  2. 繪制點,線,面的方式:以Begin(BeginMode mode)為首開始繪制mode類型的圖形,Vertex(float x, float y, float z)為圖形頂點,依次連接各個頂點形成圖形,以End()結束繪制。理論上來說,只要你給出圖形的所有頂點,牛鬼蛇神都給你搞出來,一點問題也沒有(除了可能會卡之外)。以畫線為例:

  gl.Begin(OpenGL.GL_LINES);
  gl.Vertex(-1.0f, 0.0f, 0.0f);
  gl.Vertex(1.0f, 0.0f, 0.0f);
  gl.End();

  3. 賦予顏色:Color(float red, float green, float blue)

  在每個圖形頂點前加上設定顏色,圖形的繪制選擇就更加多樣;同時,不同頂點間采用不同的顏色會產生漸變色差,非常好看。

  • 演示代碼

  我們先添加一個坐標系變化,然后。選擇繪制一條線,接着繪制一個三角形,最后繪制一個角錐。這就是由點到線,線到面,面到形的過程,所有的圖形都是這樣組合銜接而來的。

  1.首先,畫一條線,顏色設定為白色(背景是黑色)

            #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.接着,來畫個面,再稍微加點顏色變化

                #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

  

 

  3.接着,來畫個角錐,第四個點顏色選擇白色區分開。角錐也就是由四個面組合而成的,所以我們再加上三個面(注意每個點坐標和對應顏色要相同)

                #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

  

   我們會發現,界面沒什么變化。嗯,大伙看看我們的第四個頂點在哪里。坐標(0,0,-2),相對於其他四個點,他的位置是靠里面的。因為我們此時的視角是在正值的。額,對了,還得說說視角的事,視角受到初始化設置的視點變換設置。

  // 設置當前矩陣模式,對投影矩陣應用隨后的矩陣操作
  gl.MatrixMode(OpenGL.GL_PROJECTION);

  // 創建透視投影變換
  gl.Perspective(30.0f, (double)Width / (double)Height, 5, 100.0);

  // 視點變換
  gl.LookAt(0, 5, 0, 0, 0, 0, 0, 1, 0);

  //此時的視角在這里,可以理解為是坐標點(0,5,0)往空間原點處看

   程序的前端添加了Translate(0.0f, 0.0f, -5.0f) ,相當於把繪制的圖形往屏幕內移動。這樣會有利於我們查看圖形。(Z軸的話法線是垂直屏幕往外的)

  說回正題,第四個頂點是在已經畫好的三角形的里面,所以我們看不到,那我們就稍微的旋轉一下看看效果,如下圖所示。

  

 

   附上代碼:

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

namespace test
{
    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;
        public Form1()
        {
            InitializeComponent();
        }

        private void openGLControl1_OpenGLDraw(object sender, RenderEventArgs args)
        {
            SharpGL.OpenGL gl = this.openGLControl1.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, 0.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 openGLControl1_OpenGLInitialized(object sender, EventArgs e)
        {
            OpenGL gl = openGLControl1.OpenGL;
            gl.ClearColor(0, 0, 0, 0);
        }

        private void openGLControl1_Resize(object sender, EventArgs e)
        {
            OpenGL gl = openGLControl1.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 checkBoxDrawLine_CheckedChanged(object sender, EventArgs e)
        {
            drawLine = this.checkBoxDrawLine.Checked;
        }
        private void checkBoxDrawArea_CheckedChanged(object sender, EventArgs e)
        {
            drawArea = this.checkBoxDrawArea.Checked;
        }
        private void checkBoxDrawVolume_CheckedChanged(object sender, EventArgs e)
        {
            drawVolume = this.checkBoxDrawVolume.Checked;
        }
        private void checkBoxRotateX_CheckedChanged(object sender, EventArgs e)
        {
            flagRotateX = this.checkBoxRotateX.Checked;
        }

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

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM