使用頂點緩衝區繪製三角多邊形

更新頁 :
頁面創建日期 :

總結

通過使用頂點緩衝區,可以快速繪製多邊形。

頂点バッファを使用した3角形ポリゴンの描画

經營環境

先決條件

支援的 XNA 版本
  • 4.0
支援的平臺
  • Windows(XP SP2 或更高版本、Vista、7)
  • Xbox 360 的
  • Windows Phone 7 系列
Windows 所需的頂點著色器版本 2.0
Windows 所需的像素著色器版本 2.0

經營環境

平臺
  • 視窗 7
  • Xbox 360 的
  • Windows Phone 7 模擬器

物質

繪製多邊形時,可以使用稱為「頂點緩衝區」的內容來繪製它。 頂點緩衝區可以填充頂點數據,以便在繪製多邊形等基元時使用。 頂點緩衝區允許將頂點數據放置在視頻記憶體中,並且繪圖管道可以比從普通主記憶體交換數據的速度快得多,因此可以預期會提高繪圖速度。

在像這樣的單個多邊形的情況下,你感覺不到你在高速繪製,但我認為在繪製數千或數萬個多邊形時,效果是可見的。

/// <summary>
/// 頂点バッファ
/// </summary>
private VertexBuffer vertexBuffer = null;

要使用頂點緩衝區,請使用 「VertexBuffer」 類。 如果每次繪製使用者定義的頂點數據時都將其發送到管道,則必須始終保留頂點數據,但如果創建了頂點緩衝區,則頂點緩衝區將管理頂點數據,因此無需保留頂點數據。

創建頂點緩衝區

// 頂点の数
int vertexCount = 3;

// 頂点バッファ作成
this.vertexBuffer = new VertexBuffer(this.GraphicsDevice,
    typeof(VertexPositionColor), vertexCount, BufferUsage.None);

在LoadGraphicsContent方法中,我們將創建一個 VertexBuffer。

第一個參數是 GraphicsDevice。

第二個參數指定包含頂點數據的結構類型,或要使用的頂點數據的頂點聲明。 此處,typeof 傳入結構的類型。 由於「頂點位置」和「頂點顏色」用於頂點數據,因此 XNA 框架提供的「VertexPositionColor」結構被指定為標準。

第三個參數指定要創建的頂點數。

第四個參數指定頂點緩衝區使用方式,但如果沒有特別的內容,則可以指定 “BufferUsage.None”。

VertexBuffer 構造 函數

創建用於創建頂點數據的類 「VertexBuffer」 的實例。

graphics設備 圖形設備 指定要與頂點緩衝區關聯的 GraphicsDevice。
vertexType 類型 指定要使用的頂點數據類型。
頂點計數 int 指定要創建的頂點數。
用法 BufferUsage (緩衝區使用) 指定頂點緩衝區的用法。 如果沒有特別的內容,請指定 「BufferUsage.None」。。
// 頂点データを作成する
VertexPositionColor[] pointList = new VertexPositionColor[vertexCount];

pointList[0] = new VertexPositionColor(new Vector3(0.0f3.0f0.0f), Color.Red);
pointList[1] = new VertexPositionColor(new Vector3(3.0f-2.0f0.0f), Color.Blue);
pointList[2] = new VertexPositionColor(new Vector3(-3.0f-2.0f0.0f), Color.Green);

// 頂点データを頂点バッファに書き込む
this.vertexBuffer.SetData(pointList);

創建頂點緩衝區后,使用頂點數據設置頂點緩衝區。 要設置頂點數據,請使用 「VertexBuffer.SetData」 方法。

在頂點緩衝區中設置頂點數據后,它由頂點緩衝區管理,因此,如果您不再使用它,則可以按原樣丟棄它。

VertexBuffer.SetData 方法

在頂點緩衝區中設置頂點數據。

T ValueType 指定要使用的頂點數據的結構。
數據 T[] 指定要在頂點緩衝區中設置的頂點數據陣列。 在頂點緩衝區中指定的大小必須與要設置的頂點數據的大小匹配。

繪圖

// 描画に使用する頂点バッファをセットします
this.GraphicsDevice.SetVertexBuffer(this.vertexBuffer);

// パスの数だけ繰り返し描画
foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
{
    // パスの開始
    pass.Apply();

    // 三角形を描画する
    this.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
}

若要繪製多邊形,請設置用於繪製的頂點緩衝區。 GraphicsDevice 有一個“SetVertexBuffer”方法,用於為其設置頂點緩衝區。

GraphicsDevice.SetVertexBuffer 方法

指定要用於繪製的頂點緩衝區。

vertexBuffer (頂點緩衝區) VertexBuffer (頂點緩衝區) 指定要用於繪製的頂點緩衝區。

要繪製實際的多邊形,請使用 “GraphicsDevice.DrawPrimitives” 方法。 如果要使用頂點緩衝區,您將使用此方法繪製它。 與按原樣指定使用者定義的點數據的 DrawUserPrimitives 方法不同,此方法用於使用頂點緩衝區進行繪製。

第一個參數是要繪製的基元類型,第二個參數是開始繪製的頂點索引,第三個參數是要繪製的基元數。

GraphicsDevice.DrawPrimitives 方法

使用指定的頂點緩衝區繪製基元。

primitiveType (原始類型) PrimitiveType (基元類型) 指定要繪製的基本體的類型
startVertex int 要載入的頂點的第一個索引
primitiveCount int Number of primitives to draws (要繪製的基元數)

所有代碼

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif

namespace VertexBufferTriangle
{
    /// <summary>
    /// ゲームメインクラス
    /// </summary>
    public class GameMain : Microsoft.Xna.Framework.Game
    {
        /// <summary>
        /// グラフィックデバイス管理クラス
        /// </summary>
        private GraphicsDeviceManager graphics = null;

        /// <summary>
        /// スプライトのバッチ化クラス
        /// </summary>
        private SpriteBatch spriteBatch = null;

        /// <summary>
        /// 頂点バッファ
        /// </summary>
        private VertexBuffer vertexBuffer = null;

        /// <summary>
        /// 基本エフェクト
        /// </summary>
        private BasicEffect basicEffect = null;


        /// <summary>
        /// GameMain コンストラクタ
        /// </summary>
        public GameMain()
        {
            // グラフィックデバイス管理クラスの作成
            this.graphics = new GraphicsDeviceManager(this);

            // ゲームコンテンツのルートディレクトリを設定
            this.Content.RootDirectory = "Content";

#if WINDOWS_PHONE
            // Windows Phone のデフォルトのフレームレートは 30 FPS
            this.TargetElapsedTime = TimeSpan.FromTicks(333333);

            // バックバッファサイズの設定
            this.graphics.PreferredBackBufferWidth = 480;
            this.graphics.PreferredBackBufferHeight = 800;

            // フルスクリーン表示
            this.graphics.IsFullScreen = true;
#endif
        }

        /// <summary>
        /// ゲームが始まる前の初期化処理を行うメソッド
        /// グラフィック以外のデータの読み込み、コンポーネントの初期化を行う
        /// </summary>
        protected override void Initialize()
        {
            // TODO: ここに初期化ロジックを書いてください

            // コンポーネントの初期化などを行います
            base.Initialize();
        }

        /// <summary>
        /// ゲームが始まるときに一回だけ呼ばれ
        /// すべてのゲームコンテンツを読み込みます
        /// </summary>
        protected override void LoadContent()
        {
            // テクスチャーを描画するためのスプライトバッチクラスを作成します
            this.spriteBatch = new SpriteBatch(this.GraphicsDevice);

            // エフェクトを作成
            this.basicEffect = new BasicEffect(this.GraphicsDevice);

            // エフェクトで頂点カラーを有効にする
            this.basicEffect.VertexColorEnabled = true;

            // ビューマトリックスをあらかじめ設定 ((0, 0, 15) から原点を見る)
            this.basicEffect.View = Matrix.CreateLookAt(
                    new Vector3(0.0f, 0.0f, 15.0f),
                    Vector3.Zero,
                    Vector3.Up
                );

            // プロジェクションマトリックスをあらかじめ設定
            this.basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.ToRadians(45.0f),
                    (float)this.GraphicsDevice.Viewport.Width /
                        (float)this.GraphicsDevice.Viewport.Height,
                    1.0f,
                    100.0f
                );

            // 頂点の数
            int vertexCount = 3;

            // 頂点バッファ作成
            this.vertexBuffer = new VertexBuffer(this.GraphicsDevice,
                typeof(VertexPositionColor), vertexCount, BufferUsage.None);

            // 頂点データを作成する
            VertexPositionColor[] pointList = new VertexPositionColor[vertexCount];

            pointList[0] = new VertexPositionColor(new Vector3(0.0f, 3.0f, 0.0f), Color.Red);
            pointList[1] = new VertexPositionColor(new Vector3(3.0f, -2.0f, 0.0f), Color.Blue);
            pointList[2] = new VertexPositionColor(new Vector3(-3.0f, -2.0f, 0.0f), Color.Green);

            // 頂点データを頂点バッファに書き込む
            this.vertexBuffer.SetData(pointList);
        }

        /// <summary>
        /// ゲームが終了するときに一回だけ呼ばれ
        /// すべてのゲームコンテンツをアンロードします
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: ContentManager で管理されていないコンテンツを
            //       ここでアンロードしてください
        }

        /// <summary>
        /// 描画以外のデータ更新等の処理を行うメソッド
        /// 主に入力処理、衝突判定などの物理計算、オーディオの再生など
        /// </summary>
        /// <param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
        protected override void Update(GameTime gameTime)
        {
            // Xbox 360 コントローラ、Windows Phone の BACK ボタンを押したときに
            // ゲームを終了させます
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                this.Exit();
            }

            // TODO: ここに更新処理を記述してください

            // 登録された GameComponent を更新する
            base.Update(gameTime);
        }

        /// <summary>
        /// 描画処理を行うメソッド
        /// </summary>
        /// <param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
        protected override void Draw(GameTime gameTime)
        {
            // 画面を指定した色でクリアします
            this.GraphicsDevice.Clear(Color.CornflowerBlue);

            // 描画に使用する頂点バッファをセットします
            this.GraphicsDevice.SetVertexBuffer(this.vertexBuffer);

            // パスの数だけ繰り返し描画
            foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
            {
                // パスの開始
                pass.Apply();

                // 三角形を描画する
                this.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
            }

            // 登録された DrawableGameComponent を描画する
            base.Draw(gameTime);
        }
    }
}