Построение тригонального многоугольника с помощью буфера вершин

Страница обновлена :
Дата создания страницы :

сводка

Используя буферы вершин, можно быстро рисовать многоугольники.

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

Операционная среда

Необходимые условия

Поддерживаемые версии XNA
  • 4.0
Поддерживаемые платформы
  • Windows (XP SP2 или новее, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Windows Требуемая версия вершинного шейдера 2.0
Требуемая версия пиксельного шейдера Windows 2.0

Операционная среда

платформа
  • Windows 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 передается в типе структуры. Поскольку для данных вершин используются "положение вершины" и "цвет вершины", структура "VertexPositionColor", предоставляемая XNA Framework, указана как стандартная.

Третий аргумент указывает количество создаваемых вершин.

Четвертый аргумент указывает использование буфера вершин, но если ничего конкретного нет, можно указать "BufferUsage.None".

VertexBuffer конструктор

Создадим экземпляр класса "VertexBuffer" для создания данных вершин.

graphicsDevice ГрафикаУстройство Указывает объект GraphicsDevice, который будет связан с буфером вершин.
vertexType Тип Указывает тип используемых данных вершин.
vertexCount int Указывает количество создаваемых вершин.
употребление Использование буфера Указывает использование буфера вершин. Если ничего конкретного нет, укажите "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 Тип значения Указывает структуру используемых данных вершин.
данные 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 Вертексный буфер Указывает буфер вершин, используемый для рисования.

Чтобы нарисовать настоящие многоугольники, используйте метод "GraphicsDevice.DrawPrimitives". Если вы хотите использовать буфер вершин, вы нарисуете его с помощью этого метода. В отличие от метода DrawUserPrimitives, который указывает определяемые пользователем данные точки как они есть, этот метод используется для рисования с использованием буфера вершин.

Первый аргумент — это тип примитива для рисования, второй аргумент — индекс вершины для начала рисования, а третий аргумент — количество примитивов для рисования.

GraphicsDevice.DrawPrimitives метод

Рисует примитив с использованием указанного буфера вершин.

primitiveType Тип примитива Указывает тип отрисовываемого примитива
startVertex int Первый индекс вершины для загрузки
примитивныйCount int Количество примитивов для рисования

Все коды

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