Menampilkan Kotak Menggunakan Buffer Indeks
ringkasan
Saya menggunakan banyak poligon untuk membuat kotak. Dengan demikian, buffer indeks digunakan untuk mengurangi jumlah data dalam data simpul.
Lingkungan operasi
Prasyarat
Versi XNA yang Didukung |
|
Platform yang Didukung |
|
Versi Vertex Shader yang Diperlukan Windows | 2.0 |
Versi Pixel Shader yang Diperlukan Windows | 2.0 |
Lingkungan operasi
balei-balei |
|
zat
Tentang kotak
Kotak itu terdiri dari enam wajah, salah satunya terdiri dari dua poligon segitiga. Ini berarti bahwa jumlah total poligon segitiga adalah "2×6 = 12". Selanjutnya, karena poligon segitiga memiliki tiga simpul, total simpulnya adalah "12×3 = 36". Oleh karena itu, ketika membuat hanya dengan "VertexBuffer", dimungkinkan untuk menampilkannya sebagai kotak jika Anda memutuskan informasi posisi sehingga 36 potong data berbentuk kotak dan menulisnya. (24 diperlukan untuk TriangleStrip)
Tapi bayangkan sebuah kotak. Sudut kotak adalah 8 buah. Delapan seharusnya cukup untuk informasi lokasi. Ketika jumlah data simpul meningkat, itu memberi tekanan pada memori. Untuk mengurangi ini entah bagaimana, kami menggunakan "IndexBuffer".
Anda hanya membutuhkan 8 informasi posisi, tetapi Anda selalu membutuhkan 36 simpul untuk poligon. Oleh karena itu, tujuan penggunaan "IndexBuffer" adalah untuk berbagi 8 data simpul.
kebun
<summary>
インデックスバッファ
</summary>
private IndexBuffer indexBuffer = null;
<summary>
インデックスバッファの各頂点番号配列
</summary>
private static readonly Int16[] vertexIndices = new Int16[] {
2, 0, 1, // 1枚目のポリゴン
1, 3, 2, // 2枚目のポリゴン
4, 0, 2, // 3枚目のポリゴン
2, 6, 4, // 4枚目のポリゴン
5, 1, 0, // 5枚目のポリゴン
0, 4, 5, // 6枚目のポリゴン
7, 3, 1, // 7枚目のポリゴン
1, 5, 7, // 8枚目のポリゴン
6, 2, 3, // 9枚目のポリゴン
3, 7, 6, // 10枚目のポリゴン
4, 6, 7, // 11枚目のポリゴン
7, 5, 4 // 12枚目のポリゴン
};
Bidang ini dinyatakan sebagai "IndexBuffer", tetapi "array nomor simpul" dibuat sebelumnya di bawahnya. Array ini mencadangkan array untuk 36 simpul, tetapi arti dari setiap angka adalah berapa banyak data simpul dari delapan data simpul yang digunakan setiap poligon segitiga. Jika Anda melihat lebih dekat, Anda dapat melihat bahwa data di dalamnya ditulis dengan indeks antara "0 ~ 7". Sangat mudah untuk melihat di komentar.
Ngomong-ngomong, jenis arraynya adalah "Int16[]", tetapi bisa juga "short[]" (2 byte). Dalam beberapa kasus, array dibuat dengan "int" (4 byte), tetapi ini digunakan ketika jumlah simpul melebihi "65535". Jika jumlah simpul tidak pernah melebihi angka ini, buat array data 2 byte untuk mengurangi konsumsi memori.
Penciptaan
// 頂点の数
int vertexCount = 8;
// 頂点バッファ作成
this.vertexBuffer = new VertexBuffer(this.GraphicsDevice,
typeof(VertexPositionColor), vertexCount, BufferUsage.None);
// 頂点データを作成する
VertexPositionColor[] vertives = new VertexPositionColor[vertexCount];
vertives[0] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, -2.0f), Color.Yellow);
vertives[1] = new VertexPositionColor(new Vector3(2.0f, 2.0f, -2.0f), Color.Gray);
vertives[2] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, 2.0f), Color.Purple);
vertives[3] = new VertexPositionColor(new Vector3(2.0f, 2.0f, 2.0f), Color.Red);
vertives[4] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, -2.0f), Color.SkyBlue);
vertives[5] = new VertexPositionColor(new Vector3(2.0f, -2.0f, -2.0f), Color.Orange);
vertives[6] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, 2.0f), Color.Green);
vertives[7] = new VertexPositionColor(new Vector3(2.0f, -2.0f, 2.0f), Color.Blue);
// 頂点データを頂点バッファに書き込む
this.vertexBuffer.SetData(vertives);
Membuat buffer simpul. Awalnya, perlu membuat 36 simpul, tetapi dengan menggunakan buffer indeks, Anda hanya perlu membuat 8 simpul.
// インデックスバッファを作成
this.indexBuffer = new IndexBuffer(this.GraphicsDevice,
IndexElementSize.SixteenBits, 3 * 12, BufferUsage.None);
// 頂点インデックスを書き込む
this.indexBuffer.SetData(vertexIndices);
Membuat buffer indeks. Argumen kedua menentukan jumlah bit indeks simpul yang akan ditulis. Karena satu indeks adalah 2 byte, tentukan "IndexElementSize.SixteenBits".
Argumen ketiga adalah jumlah indeks. Dalam hal ini, kita akan menggambar 12 poligon, jadi tentukan 36, yang merupakan jumlah simpul × poligon dari poligon segitiga. Tentu saja, tidak ada masalah jika Anda menentukan jumlah elemen dalam array indeks apa adanya, tetapi kali ini angkanya sengaja dipisahkan untuk kejelasan.
Karena kita telah membuat array indeks simpul dengan bidang, kita akan menulisnya dengan metode "IndexBuffer.SetData".
IndexBuffer
pembangun
Membuat instans kelas IndexBuffer yang mengelola indeks yang mereferensikan data simpul.
graphicsPerangkat | Perangkat grafis | Menentukan GraphicsDevice untuk dikaitkan dengan buffer indeks. |
indexElementSize | Ukuran Elemen Indeks | Ukuran indeks simpul tunggal. Tentukan "SixteenBits" untuk 2 byte, "ThirtyTwoBits" untuk 4 byte, dan tentukan BufferUsage.None. |
indexCount | Int | Menentukan jumlah indeks. |
Penggunaan | Penggunaan Penyangga | Penggunaan buffer indeks. Tentukan BufferUsage.None kecuali sebaliknya. |
IndexBuffer.SetData
Metode
Salin array indeks simpul ke buffer indeks.
T | Tipe Nilai | Jenis array indeks simpul |
data | T | Array indeks simpul untuk disalin |
gambar
// インデックスバッファをセット
this.GraphicsDevice.Indices = this.indexBuffer;
Jika Anda ingin menggunakan buffer indeks, atur buffer indeks pada perangkat sebelum menggambar poligon.
// インデックスを使用してポリゴンを描画する
this.GraphicsDevice.DrawIndexedPrimitives(
PrimitiveType.TriangleList,
0,
0,
8,
0,
12
);
Jika Anda menggunakan buffer indeks dan simpul, gunakan metode "GraphicsDevice.DrawIndexedPrimitives" untuk menggambar poligon.
Argumen keempat adalah jumlah simpul yang dibuat. Dalam sampel, "8" ditentukan karena 8 data simpul dibagikan.
Argumen keenam menentukan jumlah primitif. Ini adalah "12" karena menggambar 12 poligon segitiga.
Untuk parameter numerik lainnya, 0 baik-baik saja.
GraphicsDevice.DrawIndexedPrimitives
Metode
Menggambar primitif berdasarkan indeks simpul dan buffer simpul yang ditentukan.
tipe primitif | Tipe Primitif | Menentukan primitif yang akan digambar. |
Puncak dasar | Int | Offset untuk ditambahkan ke setiap indeks simpul di buffer indeks. Misalnya, ketika indeks simpul pertama menunjuk ke data simpul 2, jika "1" ditentukan dalam argumen ini, indeks simpul pertama akan menunjuk ke data simpul 3. |
Indeks minVertex | Int | Indeks simpul minimum dari simpul yang digunakan dalam panggilan. Misalnya, minVertexIndex 1 meningkatkan indeks data simpul sebesar 1 (tidak meningkatkan jumlah buffer, sehingga elemen terakhir dari data simpul tidak dapat ditentukan). Jika indeks simpul menunjuk ke data simpul kedua, indeks simpul akan menunjuk ke data simpul pertama. |
numVertices | Int | Jumlah data simpul yang digunakan. |
Indeks awal | Int | Offset awal indeks simpul. Misalnya, jika Anda menentukan TriangleList sebagai primitiveType, tentukan "3, 6, 9,..." untuk melewati poligon yang mulai menggambar. Jika Anda menentukan nilai selain angka yang dibagi 3, model akan runtuh. (Karena semua indeks mati) |
primitifCount | Int | Jumlah primitif yang akan digambar. Nilai maksimum yang dapat ditentukan adalah "Jumlah indeks simpul÷ Jumlah simpul primitif - startIndex" |
Semua Kode
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 IndexBufferBox
{
<summary>
ゲームメインクラス
</summary>
public class GameMain : Microsoft.Xna.Framework.Game
{
<summary>
グラフィックデバイス管理クラス
</summary>
private GraphicsDeviceManager graphics = null;
<summary>
スプライトのバッチ化クラス
</summary>
private SpriteBatch spriteBatch = null;
<summary>
基本エフェクト
</summary>
private BasicEffect basicEffect = null;
<summary>
頂点バッファ
</summary>
private VertexBuffer vertexBuffer = null;
<summary>
インデックスバッファ
</summary>
private IndexBuffer indexBuffer = null;
<summary>
インデックスバッファの各頂点番号配列
</summary>
private static readonly Int16[] vertexIndices = new Int16[] {
2, 0, 1, // 1枚目のポリゴン
1, 3, 2, // 2枚目のポリゴン
4, 0, 2, // 3枚目のポリゴン
2, 6, 4, // 4枚目のポリゴン
5, 1, 0, // 5枚目のポリゴン
0, 4, 5, // 6枚目のポリゴン
7, 3, 1, // 7枚目のポリゴン
1, 5, 7, // 8枚目のポリゴン
6, 2, 3, // 9枚目のポリゴン
3, 7, 6, // 10枚目のポリゴン
4, 6, 7, // 11枚目のポリゴン
7, 5, 4 // 12枚目のポリゴン
};
<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;
// ビューマトリックスをあらかじめ設定 ((10, 10, 10) から原点を見る)
this.basicEffect.View = Matrix.CreateLookAt(
new Vector3(10.0f, 10.0f, 10.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 = 8;
// 頂点バッファ作成
this.vertexBuffer = new VertexBuffer(this.GraphicsDevice,
typeof(VertexPositionColor), vertexCount, BufferUsage.None);
// 頂点データを作成する
VertexPositionColor[] vertives = new VertexPositionColor[vertexCount];
vertives[0] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, -2.0f), Color.Yellow);
vertives[1] = new VertexPositionColor(new Vector3(2.0f, 2.0f, -2.0f), Color.Gray);
vertives[2] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, 2.0f), Color.Purple);
vertives[3] = new VertexPositionColor(new Vector3(2.0f, 2.0f, 2.0f), Color.Red);
vertives[4] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, -2.0f), Color.SkyBlue);
vertives[5] = new VertexPositionColor(new Vector3(2.0f, -2.0f, -2.0f), Color.Orange);
vertives[6] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, 2.0f), Color.Green);
vertives[7] = new VertexPositionColor(new Vector3(2.0f, -2.0f, 2.0f), Color.Blue);
// 頂点データを頂点バッファに書き込む
this.vertexBuffer.SetData(vertives);
// インデックスバッファを作成
this.indexBuffer = new IndexBuffer(this.GraphicsDevice,
IndexElementSize.SixteenBits, 3 * 12, BufferUsage.None);
// 頂点インデックスを書き込む
this.indexBuffer.SetData(vertexIndices);
}
<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);
// インデックスバッファをセット
this.GraphicsDevice.Indices = this.indexBuffer;
// パスの数だけ繰り替えし描画 (といっても BasicEffect は通常1回)
foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
{
// パスの開始
pass.Apply();
// インデックスを使用してポリゴンを描画する
this.GraphicsDevice.DrawIndexedPrimitives(
PrimitiveType.TriangleList,
0,
0,
8,
0,
12
);
}
// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);
}
}
}