使用顶点缓冲区绘制三角多边形

更新页 :
页面创建日期 :

总结

通过使用顶点缓冲区,可以快速绘制多边形。

頂点バッファを使用した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);
        }
    }
}